سؤال

هل تعرف برنامج نصي بسيط لحساب NLOCs (نيتو خطوط من التعليمات البرمجية).البرنامج النصي يجب عد الأسطر من التعليمات البرمجية C.فإنه لا ينبغي الاعتماد فارغة خطوط أو خطوط فقط مع الأقواس.ولكن لا تحتاج إلى أن تكون مفرطة في الدقيقة أيضا.

هل كانت مفيدة؟

المحلول

أود أن تفعل ذلك باستخدام awk & cpp (المعالج) & wc .awk يزيل جميع الأقواس و الفراغات ، preprocessor يزيل جميع التعليقات و wc بحساب خطوط:

find . -name \*.cpp -o -name \*.h | xargs -n1 cpp -fpreprocessed -P | 
    awk '!/^[{[:space:]}]*$/' | wc -l

إذا كنت تريد أن يكون تضمنت التعليقات:

find . -name \*.cpp -o -name \*.h | xargs awk '!/^[{[:space:]}]*$/' | wc -l

نصائح أخرى

وتبحث NLOC على شبكة الإنترنت، وجدت معظمها "غير علق خطوط للقانون".
لم تقم بتحديد إذا كان يجب تخطي التعليقات ...
حتى لو كنت التمسك رسالة الحالية، ما يلي الخطوط الملاحية المنتظمة واحدة في بيرل يجب القيام بهذه المهمة:

perl -pe "s/^\s*[{}]?\s*\n//" Dialog.java | wc -l

ويمكنني توسيع نطاقه ليشمل التعامل مع تعليقات السطر:

perl -pe "s#^\s*[{}]?\s*\n|^\s*//.*\n##" Dialog.java | wc -l

وأو ربما

perl -pe "s#^\s*(?:[{}]?\s*|//.*)\n##" Dialog.java | wc -l

الصيانة تعليقات كتلة وأكثر قليلا صعبة (أنا لست خبير بيرل!).

[تحرير] حصلت عليه ... الجزء الأول يمكن ربما تحسن (أقصر). كانت ممتعة للتجربة.

perl -e "$x = join('', <>); $x =~ s#/\*.*?\*/##gs; print $x" Dialog.java | perl -pe "s#^\s*(?:[{}]?\s*|//.*)\n##" | wc -l

وPS: I استخدام علامات الاقتباس المزدوجة لأنني اختبرت على ويندوز ...

تحقق من DPack المساعد لبرنامج Visual Studio. أنه يحتوي على تقرير احصائيات لأي حل / مشروع.

وليس السيناريو، ولكن يمكنك أن تجرب هذا سطر الأوامر أداة مفتوحة المصدر: NLOC

رصد المصدر هي مجانية برامج التحليل المصدر. ومن نوافذ التطبيق ولكنه أيضا يمكن أن تعمل مع المعلمات من سطر الأوامر.

ويمكن تحليل C ++، C، C #، VB.NET، جافا، دلفي، فيجوال بيسك (VB6) أو HTML.

Ohloh يقدم مجانا <لأ href = "http://www.ohloh.net/projects/ ohcount "يختلط =" نوفولو noreferrer "> Ohcount التي تعتبر خطوط رمز والتعليقات.

إذا التعليقات يمكن أن يكون لا يزال في، وأداة يونكس القياسية تكفي:

grep  -x -v "[[:space:]}{]*" files.c  | wc

SLOCCOunt ليس سيناريو بسيط ويفعل أكثر من ذلك بكثير من ما تحتاجه. ومع ذلك، فإنه هو بديل قوي للOhcount التي سبق ذكرها وNLOC. :)

وأنا عادة مجرد قيام بذلك:

grep -vc '^$' (my files)

ويعمل فقط إذا خطوط الفارغة فارغة حقا (بدون مسافات). يكفي بالنسبة لي.

Locmetrics يعمل بشكل جيد.

وهنا مخطوطة برل بسيط eLOC.pl :

#!/usr/bin/perl -w
# eLOC - Effective Lines of Code Counter
# JFS (2005)
#
# $ perl eLOC.pl --help
#
use strict;
use warnings;
use sigtrap;
use diagnostics;

use warnings::register;
no warnings __PACKAGE__;
sub DEBUG { 0 }

use English qw( -no_match_vars ) ;  # Avoids regex performance penalty
use Getopt::Long qw(:config gnu_getopt);
use File::DosGlob 'glob';
use Pod::Usage;


our $VERSION = '0.01';

# globals
use constant NOTFILENAME => undef;
my %counter = ( 
    'PHYS'          => 0, 
    'ELOC'          => 0, 
    'PURE_COMMENT'  => 0,
    'BLANK'         => 0,
    'LLOC'          => 0,
    'INLINE_COMMENT'=> 0,
    'LOC'           => 0,
);
my %header = (
    "eloc"      =>  "eloc",
    "lloc"      =>  "lloc",
    "loc"       =>  "loc",
    "comment"   =>  "comment",
    "blank"     =>  "blank",
    "newline"   =>  "newline",
    "logicline" =>  "lgcline",
);
my %total = %counter; # copy
my $c = \%counter; # see format below
my $h = \%header;  # see top format below
my $inside_multiline_comment = 0;
my $filename = NOTFILENAME;
my $filecount = 0;
my $filename_header = "file name";

# process input args
my $version = '';
my $help = '';
my $man = '';
my $is_deterministic = '';
my $has_header = '';

print STDERR "Input args:'" if DEBUG;
print STDERR (join("|",@ARGV),"'\n") if DEBUG;

my %option = ('version' => \$version,
    'help' => \$help,   
    'man'  => \$man,
    'deterministic' => \$is_deterministic,
    'header' => \$has_header
);
GetOptions( \%option, 'version',    'help', 'man',
    'eloc|e', # print the eLOC counts
    'lloc|s', # print the lLOC counts (code statements)
    'loc|l' , # print the LOC counts (eLOC + lines of a single brace or parenthesis)
    'comment|c'    , # print the comments counts (count lines which contains a comment)
    'blank|b'      , # print the blank counts
    'newline|n'    , # print the newline count
    'logicline|g'  , # print the logical line count (= LOC + Comment Lines + Blank Lines)   
    'deterministic', # print the LOC determination for every line in the source file
    'header',        # print header line
) or invalid_options("$0: invalid options\nTry `$0 --help' for more information.");

version()                                   if $version;
pod2usage(-exitstatus => 0, -verbose => 1)  if $help ;
pod2usage(-exitstatus => 0, -verbose => 2)  if $man;

#
$has_header = 1 if $is_deterministic && $has_header eq '';

#format for print_loc_metric()
my ($format, $format_top) = make_format(); 
print STDERR "format:\n" if DEBUG > 10;
print STDERR $format if DEBUG > 10;
eval $format;
die $@ if $@; # $EVAL_ERROR

if(DEBUG>10) {
    print STDERR ("format_top:\n", $format_top);
}
if( $has_header) {
    eval $format_top;
    die $@ if $@; # $EVAL_ERROR 
}

# process files
print STDERR ("Input args after Getopts():\n",
    join("|",@ARGV),"\n") if DEBUG > 10;

expand_wildcards();
@ARGV = '-' unless @ARGV;
foreach my $fn (@ARGV) {
    $filename = $fn;
    unless (open(IN, "<$filename")) {
        warn "$0: Unable to read from '$filename': $!\n";
        next;
    }
    print STDERR "Scanning $filename...\n" if DEBUG;

    clear_counters();
    generate_loc_metric();  

    $filecount++;

    print_loc_metric();                     

    close(IN)
        or warn "$0: Could not close $filename: $!\n";      
}

# print total
if($filecount > 1) {
    $filename = "total";
    $c = \%total;
    print_loc_metric();
}
exit 0;

#-------------------------------------------------
sub wsglob {
    my @list = glob;
    @list ? @list : @_; #HACK: defence from emtpy list from glob()
}
sub expand_wildcards {
    print STDERR ("Input args before expand_wildcards():\n",
        join("|",@ARGV),"\n") if DEBUG;

    {       
        @ARGV = map( /['*?']/o ? wsglob($_) : $_ , @ARGV);
    }   
    print STDERR ("Input args after expand_wildcards():\n",
        join("|",@ARGV),"\n") if DEBUG; 
}
sub clear_counters {
    for my $name ( keys %counter) {
        $counter{$name} = 0;
    }   
}
sub make_format {
    my $f = 'format STDOUT =' . "\n";
    $f .= '# LOC, eLOC, lLOC, comment, blank, newline, logicline and filename' . "\n";
    my $f_top = 'format STDOUT_TOP =' . "\n";   
    my $console_screen_width = (get_terminal_size())[0];
    print STDERR '$console_screen_width=' . $console_screen_width ."\n" if DEBUG>10;
    $console_screen_width = 100 if $console_screen_width < 0;
    my $is_print_specifiers_set = 
         ($option{"eloc"} or
         $option{"lloc"} or
         $option{"loc"} or
         $option{"comment"} or
         $option{"blank"} or
         $option{"newline"} or
         $option{"logicline"});

    my %o = %option;
    my $fc = 0;
    if( $is_print_specifiers_set ) {

        $fc++ if $o{"eloc"};
        $fc++ if $o{"lloc"};
        $fc++ if $o{"loc"};
        $fc++ if $o{"comment"};
        $fc++ if $o{"blank"};
        $fc++ if $o{"newline"};
        $fc++ if $o{"logicline"};
        if( $fc == 0 ) { die "$0: assertion failed: field count is zero" }
    }
    else {
        # default
        $fc = 7;
        $o{"loc"}       = 1;       
        $o{"eloc"}      = 1;         
        $o{"lloc"}      = 1;      
        $o{"comment"}   = 1;   
        $o{"blank"}     = 1;     
        $o{"newline"}   = 1;   
        $o{"logicline"} = 1;        
    }
    if (DEBUG > 10) {
        while( (my ($name, $value) = each %{o}) ) {
            print STDERR "name=$name, value=$value\n";
        }       
    }


    # picture line  
    my $field_format = '@>>>>>> ';
    my $field_width = length $field_format;
    my $picture_line = $field_format x $fc;     
    #   place for filename
    $picture_line .= '^';       
    $picture_line .= '<' x ($console_screen_width - $field_width * $fc - 2);
    $picture_line .= "\n";  
    $f .= $picture_line;
    $f_top .= $picture_line;
    # argument line
    $f .=   '$$c{"LOC"}, '      ,$f_top .= '$$h{"loc"}, '       if $o{"loc"};
    $f .=   '$$c{"ELOC"}, '     ,$f_top .= '$$h{"eloc"}, '      if $o{"eloc"};      
    $f .=   '$$c{"LLOC"}, '     ,$f_top .= '$$h{"lloc"}, '      if $o{"lloc"};
    $f .=   '$$c{"comment"}, '  ,$f_top .= '$$h{"comment"}, '   if $o{"comment"};
    $f .=   '$$c{"BLANK"}, '    ,$f_top .= '$$h{"blank"}, '     if $o{"blank"};
    $f .=   '$$c{"PHYS"}, '     ,$f_top .= '$$h{"newline"}, '   if $o{"newline"};
    $f .=   '$$c{"logicline"}, ',$f_top .= '$$h{"logicline"}, ' if $o{"logicline"};
    $f .=  '$filename' . "\n";
    $f_top .= '$filename_header' . "\n";        

    # 2nd argument line for long file names
    $f .=   '^';    
    $f .= '<' x ($console_screen_width-2);
    $f .= '~~'  . "\n"
            .' $filename'  . "\n";
    $f .='.' . "\n";
    $f_top .='.' . "\n";
    return ($f, $f_top);
}
sub generate_loc_metric {
    my $is_concatinated = 0;
    LINE: while(<IN>)
    {
        chomp;      
        print if $is_deterministic && !$is_concatinated;        

        # handle multiline code statements
        if ($is_concatinated = s/\\$//) {
            warnings::warnif("$0: '\\'-ending line concantinated");
            increment('PHYS');
            print "\n" if $is_deterministic;
            my $line = <IN>;
            $_ .= $line;
            chomp($line);
            print $line if $is_deterministic;
            redo unless eof(IN);            
        }               

        # blank lines, including inside comments, don't move to next line here
        increment('BLANK')                  if( /^\s*$/ );  

        # check whether multiline comments finished
        if( $inside_multiline_comment && m~\*/\s*(\S*)\s*$~ ) {
            $inside_multiline_comment = 0;
            # check the rest of the line if it contains non-whitespace characters
            #debug $_ = $REDO_LINE . $1, redo LINE if($1);
            warnings::warnif("$0: expression '$1' after '*/' discarded") if($1);
            # else mark as pure comment
            increment('PURE_COMMENT');
            next LINE;
        }
        # inside multiline comments
        increment('PURE_COMMENT'), next LINE if( $inside_multiline_comment );

        # C++ style comment at the begining of line (except whitespaces)
        increment('PURE_COMMENT'), next LINE if( m~^\s*//~ ); 

        # C style comment at the begining of line (except whitespaces)
        if ( m~^\s*/\*~ ) {
            $inside_multiline_comment = 1 unless( m~\*/~ );
            increment('PURE_COMMENT'),  next LINE;
        }
        # inline comment, don't move to next line here
        increment('INLINE_COMMENT')        if ( is_inline_comment($_) );

        # lLOC implicitly incremented inside is_inline_comment($)

        #
        increment('LOC')                    unless( /^\s*$/ );

        # standalone braces or parenthesis  
                                  next LINE if( /^\s*(?:\{|\}|\(|\))+\s*$/ );           

        # eLOC is not comments, blanks or standalone braces or parenthesis
        #   therefore just increment eLOC counter here
        increment('ELOC'),        next LINE unless( /^\s*$/ );
    }
    continue {
        increment('PHYS');
        print " [$.]\n" if $is_deterministic; # $INPUT_LINE_NUMBER
    }
}

sub print_loc_metric {
    $$c{'comment'} = $$c{'PURE_COMMENT'} + $$c{'INLINE_COMMENT'}; 
    # LOC + Comment Lines + Blank Lines 
    $$c{'logicline'} = $$c{'LOC'} + $$c{'comment'} + $$c{'BLANK'};
    unless (defined $filename) { 
        die "print_loc_metric(): filename is not defined";
    }       

    my $fn = $filename;
    $filename = "", $filename_header = "" 
        unless($#ARGV);
    print STDERR ("ARGV in print_loc_metric:" , join('|',@ARGV), "\n") 
        if DEBUG;
    write STDOUT; # replace with printf
    $filename = $fn;
}
sub increment {
    my $loc_type = shift;
    defined $loc_type
        or die 'increment(\$): input argument is undefined';    

    $counter{$loc_type}++;
    $total{$loc_type}++;
    print "\t#". $loc_type ."#" if $is_deterministic;   
}

sub is_inline_comment {
    my $line = shift;
    defined $line 
        or die 'is_inline_comment($): $line is not defined';

    print "\n$line" if DEBUG > 10;  

# here: line is not empty, not begining both C and C++ comments signs,
#       not standalone '{}()', not inside multiline comment,
#       ending '\' removed (joined line created if needed)

# Possible cases: 
#   - no C\C++ comment signs                        => is_inline_comment = 0
#   - C++ comment (no C comment sign)
#       * no quote characters                       => is_inline_comment = 1
#       * at least one comment sign is not quoted   => is_inline_comment = 1
#       * all comment signs are quoted              => is_inline_comment = 0
#   - C comment (no C++ comment sign)
#       * no quote characters                       => is_inline_comment = 1,
#           ~ odd number of '/*' and '*/'           => $inside_multiple_comment = 1                             
#           ~ even number                           => $inside_multiple_comment = 0
#       * etc...
#   - ...
# algorithm: move along the line from left to right
# rule: quoted comments are not counted
# rule: quoted by distinct style quotes are not counted
# rule: commented quotes are not counted
# rule: commented distinct style comments are not counted
# rule: increment('LLOC') if not-quoted, not-commented
#           semi-colon presents in the line except that two 
#           semi-colon in for() counted as one.

# 
$_ = $line; #hack: $_ = $line inside sub
#   state
my %s = (
    'c'     => 0, # c slash star - inside c style comments
    'cpp'   => 0, # c++ slash slash - inside C++ style comment
    'qm'    => 0, # quoted mark - inside quoted string
    'qqm'   => 0, # double quoted - inside double quoted string
);
my $has_comment = 0;
# find state
LOOP:
    {
      /\G\"/gc  &&  do { # match double quote
                            unless( $s{'qm'} || $s{'c'} || $s{'cpp'} ) {
                                    # toggle 
                                $s{'qqm'} = $s{'qqm'} ? 0 : 1; 
                            }
                            redo LOOP;
                    };
      /\G\'/gc  &&  do { # match single quote
                            unless( $s{'qqm'} || $s{'c'} || $s{'cpp'} ) {
                                    # toggle 
                                $s{'qm'} = $s{'qm'} ? 0 : 1; 
                            }
                            redo LOOP;
                    };
      m~\G//~gc &&  do { # match C++ comment sign
                            unless( $s{'qm'} || $s{'qqm'} || $s{'c'} ) {
                                    # on
                                $has_comment = 1;
                                $s{'cpp'} = 1; 
                            } 
                            redo LOOP;
                    };
      m~\G/\*~gc    &&  do { # match begining C comment sign
                            unless( $s{'qm'} || $s{'qqm'} || $s{'cpp'} ) {
                                    # on
                                $has_comment = 1;
                                $s{'c'} = $s{'c'} ? 1 : 1; 
                            } 
                            redo LOOP;
                    };
      m~\G\*/~gc    &&  do { # match ending C comment sign
                            unless( $s{'qm'} || $s{'qqm'} || $s{'cpp'} ) {
                                    # off                                   
                                if( $s{'c'} ) {                                     
                                    $s{'c'} = 0;
                                }
                                else {
                                    die 'is_inline_comment($): unexpected c style ending comment sign'.
                                        "\n'$line'";
                                }
                            } 
                            redo LOOP;
                    };
      /\Gfor\s*\(.*\;.*\;.*\)/gc    &&  do { # match for loop
                            unless( $s{'qm'} || $s{'qqm'} || $s{'cpp'} || $s{'c'} ) {
                                # not-commented, not-quoted semi-colon                                  
                                increment('LLOC');
                            }
                            redo LOOP;
                    };                                          
      /\G\;/gc  &&  do { # match semi-colon
                            unless( $s{'qm'} || $s{'qqm'} || $s{'cpp'} || $s{'c'} ) {
                                # not-commented, not-quoted semi-colon
                                # not inside for() loop
                                increment('LLOC');
                            }
                            redo LOOP;
                    };                      
      /\G./gc   &&  do { # match any other character
                            # skip 1 character
                            redo LOOP;
                    };
      /\G$/gc   &&  do { # match end of the line
                            last LOOP;
                    };                      
      #default
        die 'is_inline_comment($): unexpected character in the line:' .
            "\n'$line'";
    }
# apply state
    $inside_multiline_comment = $s{'c'};
    return $has_comment;
}

sub version {
#   TODO: version implementation
    print <<"VERSION";
NAME v$VERSION
Written by AUTHOR

COPYRIGHT AND LICENSE
VERSION

exit 0;
}

sub invalid_options {
    print STDERR (@_ ,"\n");
    exit 2;
}

sub get_terminal_size {
    my ($wchar, $hchar) = ( -1, -1); 
    my $win32console = <<'WIN32_CONSOLE';   
        use Win32::Console; 
        my $CONSOLE = new Win32::Console(); 
        ($wchar, $hchar) = $CONSOLE->MaxWindow();
WIN32_CONSOLE

    eval($win32console); 
    return ($wchar, $hchar) unless( $@ );
    warnings::warnif($@); # $EVAL_ERROR

    my $term_readkey = <<'TERM_READKEY';
        use Term::ReadKey; 
        ($wchar,$hchar, $wpixels, $hpixels) = GetTerminalSize(); 
TERM_READKEY

    eval($term_readkey); 
    return ($wchar, $hchar) unless( $@ );

    warnings::warnif($@); # $EVAL_ERROR 
    my $ioctl = <<'IOCTL'; 
        require 'sys/ioctl.ph'; 
        die "no TIOCGWINSZ " unless defined &TIOCGWINSZ; 
        open(TTY, "+</dev/tty")                     
            or die "No tty: $!"; 
        unless (ioctl(TTY, &TIOCGWINSZ, $winsize='')) { 
            die sprintf "$0: ioctl TIOCGWINSZ (%08x: $!)\n", 
                    &TIOCGWINSZ; 
        } 
        ($hchar, $wchar, $xpixel, $ypixel) = 
            unpack('S4', $winsize); # probably $hchar & $wchar should be swapped here 
IOCTL

    eval($ioctl); 
    warnings::warnif($@) if $@ ; # $EVAL_ERROR  

    return ($wchar, $hchar); 
}

1;
__END__ 

=head1 NAME

eLOC - Effective Lines of Code Counter

=head1 SYNOPSIS

B<eloc> B<[>OPTIONB<]...> B<[>FILEB<]...>

Print LOC, eLOC, lLOC, comment, blank, newline and logicline counts 
for each FILE, and a total line if more than one FILE is specified.
See L</"LOC Specification"> for more info, use `eloc --man'.

  -e, --eloc             print the {E}LOC counts
  -s, --lloc             print the lLOC counts (code {S}tatements)
  -l, --loc              print the {L}OC counts (eLOC + lines of a single brace or parenthesis)
  -c, --comment          print the {C}omments counts (count lines which contains a comment)
  -b, --blank            print the {B}lank counts
  -n, --newline          print the {N}ewline count
  -g, --logicline        print the lo{G}ical line count (= LOC + Comment Lines + Blank Lines)
      --deterministic    print the LOC determination for every line in the source file
      --header           print header line
      --help display this help and exit
      --man  display full help and exit
      --version  output version information and exit

With no FILE, or when FILE is -, read standard input.      

Metrics counted by the program are based on narration from 
http://msquaredtechnologies.com/m2rsm/docs/rsm_metrics_narration.htm

=for TODO: Comment Percent = Comment Line Count / Logical Line Count ) x 100      

=for TODO: White Space Percentage = (Number of spaces / Number of spaces and characters) * 100       

=head1 DESCRIPTION

eLOC is a simple LOC counter. See L</"LOC Specification">. 

=head2 LOC Specification

=over 1

=item LOC

Lines Of Code = eLOC + lines of a single brace or parenthesis

=item eLOC

An effective line of code or eLOC is the measurement of all lines that are 
not comments, blanks or standalone braces or parenthesis. 
This metric more closely represents the quantity of work performed. 
RSM introduces eLOC as a metrics standard.
See http://msquaredtechnologies.com/m2rsm/docs/rsm_metrics_narration.htm

=item lLOC

Logical lines of code represent a metrics for those line of code which form 
code statements.  These statements are terminated with a semi-colon.  

The control line for the "for" loop contain two semi-colons but accounts 
for only one semi colon.
See http://msquaredtechnologies.com/m2rsm/docs/rsm_metrics_narration.htm

=item comment

comment = pure comment + inline comment



=over

=item pure comment

Comment lines represent a metrics for pure comment line without any code in it.
See L</"inline comment">.

=item inline comment

Inline comment line is a line which contains both LOC line and pure comment.

Inline comment line and pure comment line (see L</"pure comment">)
are mutually exclusive, that is a given physical line cannot be an inline comment
line and a pure comment line simultaneously.

=over

=item Example:

    static const int defaultWidth = 400;        // value provided in declaration

=back

=back

=item blank

Blank line is a line which contains at most whitespaces.
Blank lines are counted inside comments too.

=item logicline

The logical line count = LOC + Comment Lines + Blank Lines

=back

=head1 KNOWN BUGS AND LIMITATIONS

=over

=item

It supports only C/C++ source files.

=item

Comments inside for(;;) statements are not counted

=over

=item Example:

    for(int i = 0; i < N /*comment*/; i++ );        #LLOC#  #LLOC#  #LOC#   #ELOC#  #PHYS# [1]

=back

=item

'\'-ending lines are concatinated ( though newline count is valid)

=item

Input from stdin is not supported in the case 
the script is envoked solely by name without explicit perl executable.

=item

Wildcards in path with spaces are not supported (like GNU utilities).

=back

=over

=begin fixed
=item Limitation: single source file

    Only one source file at time supported

=item Limitation: LLOC is unsupported

    The logical lines of code metric is unsupported. 

=item missed inline comment for C style comment

    #include <math.h> /* comment */ #ELOC#  #PHYS# [2]

But must be
    #include <math.h> /* comment */ #INLINE_COMMENT#    #ELOC#  #PHYS# [2]

=item wrong LOC type for the code after '*/'

    /* another  #PURE_COMMENT#  #PHYS# [36]
    trick   #PURE_COMMENT#  #PHYS# [37]
    */  i++;    #PURE_COMMENT#  #PHYS# [38]

In the last line must be 

    #INLINE_COMMENT# #PHYS# [38]

=end fixed

=back

=head1 SEE ALSO

Metrics counted by the program are based on narration from L<http://msquaredtechnologies.com/m2rsm/docs/rsm_metrics_narration.htm>

=cut

والبرنامج النصي التالي سوف تحصل على عدد من كل ملف مطابقة نمط في دليل معين.

و# START OF SCRIPT

والملفات فار شارع
فار شارع دير

و$ يقع الملفات = "* .CPP" # <===================== تعيين الخاص بك ملف نقش اسم هنا.
مجموعة $ دير = "C: / myproject" # <===================== تعيين دليل المشروع الخاص بك هنا

.

و# الحصول على قائمة الملفات في FILELIST متغير.
فار شارع FILELIST
العثور على ملفات-rn ($ الملفات) دير (دير $)> $ FILELIST

و# بتعريف المتغيرات حيث سنقوم انقاذ تهم الملفات الفردية.
فار الباحث ج # جميع خطوط
خطوط فار كثافة ملحوظة # غير فارغة

و# بتعريف المتغيرات حيث سنقوم انقاذ العدد الكلى لكافة الملفات.
فار الباحث totalc # مبلغ-مجموعه جميع خطوط
فار الباحث totalnb # مبلغ-مجموعه جميع خطوط غير فارغة

و# بتعريف متغير حيث سنقوم بتخزين عدد الملفات.
فار الباحث fileCount

و# سنقوم بتخزين اسم الملف ونحن نعمل على حاليا، في ما يلي.
فار ملف شارع

و# الذهاب من خلال لFILELIST $ احدا تلو ملف واحد.
بينما ($ FILELIST <> "")

في   # استخراج الملف التالي.
  ليكس "1" $ FILELIST> ملف $

و# معرفة ما اذا كان هذا هو ملف ثابت. نحن لا نرغب في الدلائل.
  بالعربية ملف $> اغيا # نحن لا نريد أن نرى الإخراج.
        # نحن نريد فقط لتعيين متغير $ ftype.
  إذا ($ ftype == "و")
  
في     # نعم، هذا هو ملف ثابت.

 # Increment file count.<br>
set $fileCount = $fileCount+1<br>

# Collect the content of $file in $content<br>
var str content # Content of one file at a time<br>
repro $file >$content<br>

# Get count and non-blank count.<br>
set $c={len -e $content}<br>
set $nb={len $content}<br>

echo -e "File: " $file ", Total Count: " $c ", Non-blank Count: " $nb<br>

# Update total counts.<br>
set $totalc = $totalc + $c<br>
set $totalnb = $totalnb + $nb<br>

والقيام
  ENDIF

والقيام

إظهار مبلغ-المجاميع

وصدى "********************************************* ************************************************** *********************************** "
صدى "عدد الإجمالي لكافة خطوط: \ ر" $ totalc "، \ tTotal عدد من خطوط غير فارغة: \ ر" $ totalnb "، مجموع الملفات:" $ fileCount
صدى صوت "************************************************ ************************************************** ******************************** "

و# END OF SCRIPT

إذا كنت تريد التهم خط في الملفات التي تم تعديلها في العام 2008 فقط، إضافة ($ fmtime> = "2008")، وما إلى ذلك.

إذا لم يكن لديك biterscripting، والحصول عليها من كوم.

كان

وليس سيناريو بسيط، ولكن CCCC (C و C ++ كود عداد) حولها لبعض الوقت ويعمل كبيرة بالنسبة لي.

لدي برنامج يسمى scc أن شرائط ج التعليقات (و C++ التعليقات ، ولكن مع C99 انهم نفس).تطبيق هذا بالإضافة إلى فلتر إزالة الأسطر الفارغة ، إذا رغبت في ذلك, خطوط تحتوي فقط على فتح و إغلاق الأقواس لإنشاء خط التهم.لقد استعملت هذا على المشاريع الداخلية - لا حاجة إلى خصم فتح/إغلاق الأقواس.تلك النصوص كانت أكثر تعقيدا مقارنة مصدر رمز اثنين من إصدارات مختلفة من كبير المشروع المخزنة في ClearCase.كما أنها لم إحصاءات عن الملفات إضافة و إزالة و على خطوط إضافة و إزالة من الملفات المشتركة ، إلخ.

لا عد الأقواس يجعل فرقا:

Black JL: co -q -p scc.c | scc | sed '/^[       ]*$/d' | wc -l
     208
Black JL: co -q -p scc.c | scc | sed '/^[       {}]*$/d' | wc -l
     144
Black JL: co -p -q scc.c | wc -l
     271
Black JL:

لذا 144 خطوط تحت القواعد ؛ 208 عد فتح وإغلاق هدفين خطوط ؛ 271 عد كل شيء.

يمي أعرف إذا كنت تريد رمز scc (إرسال بريد إلكتروني إلى أول نقطة في جوجل دوت كوم).انها 13 KB المضغوطة من الملف tar بما في ذلك الصفحة التعذيب اختبار بعض ملفات المكتبة.


@litb وعلق 'cpp -fpreprocessed -P file مقابض تجريد تعليقات.فإنه في الغالب لا.ومع ذلك ، عند تشغيلها على اختبار الإجهاد بالنسبة SCC, فهو يشكو عندما (في رأيي) أنه لا ينبغي أن:

SCC has been trained to handle 'q' single quotes in most of
the aberrant forms that can be used. '\0', '\', '\'', '\\
n' (a valid variant on '\n'), because the backslash followed
by newline is elided by the token scanning code in CPP before
any other processing occurs.

عندما CPP من دول مجلس التعاون الخليجي 4.3.2 العمليات هذا ، فإنه يشكو (يحذر):

SCC has been trained to handle 'q' single quotes in most of
<stdin>:2:56: warning: missing terminating ' character
the aberrant forms that can be used. '\0', '\', '\'', '\\
<stdin>:3:27: warning: missing terminating ' character
n' (a valid variant on '\n'), because the backslash followed
by newline is elided by the token scanning code in CPP before
any other processing occurs.

القسم 5.1.1.2 الترجمة مراحل C99 القياسية يقول:

الأسبقية بين قواعد النحو الترجمة المحدد من خلال المراحل التالية.(الحاشية رقم 5)

  1. المادية الملف المصدر متعدد البايت الأحرف تعيين في تنفيذ محددة بطريقة المصدر الأحرف تعيين (جديدة-خط حرفا نهاية خط المؤشرات) إذا لزم الأمر.Trigraph تسلسل محلها المقابلة حرف واحد تمثيلات داخلية.

  2. كل مثيل مائل حرف () تليها مباشرة جديد-خط حرف حذف الربط المادي المصدر خطوط على شكل منطقي المصدر خطوط.فقط آخر مائل على أي البدنية المصدر خط ويجوز كونها جزءا من هذه الوصلة.مصدر الملف فارغة لا تنتهي في خط حرف ، والتي لن تكون على الفور يسبقه حرف مائل قبل أي من هذه الربط يأخذ مكان.

الحاشية رقم 5 هو:

(5) تطبيقات يجب التصرف كما لو أن هذه مراحل منفصلة تحدث حتى على الرغم من العديد من عادة مطوية معا في الممارسة العملية.

وبالتالي, في رأيي, CPP هو سوء المرحلة الثانية في المثال النص.أو على الأقل هذا هو ما أريد - بناء صالحة C و ليس من البديهي أن التحذير له ما يبرره.

إنها قضية حافة إضافية تحذيرات المسموح بها.ولكنها قد تزعج الأحياء النهار من لي.إذا لم يكن لديك بلدي ، ربما أفضل وسيلة للحصول على الوظيفة ، ثم باستخدام 'cpp -fpreprocessed -P'أن أفعل ذلك هو أقصى حافة حال أنا تشكو (و قد تكون مشروعة القول أنه من المرجح أكثر أن هناك مشكلة من لا -- على الرغم من أفضل ارشادي أن نلاحظ أن الخط كان تقسم و النتيجة كانت مشروعة حرف واحد ثابت وبالتالي فإن الشكوى ينبغي قمعها;إذا كانت النتيجة غير المشروعة حرف واحد ثابت ، ثم الشكوى يجب أن تنتج.(في حالة اختبار المسلم اختبار التعذيب - CPP ينتج 13 مشاكل تتعلق في معظمها إلى واحد أنا تشكو حيث SCC بشكل صحيح ينتج 2.)

(ألاحظ أن '-P'تمكن من قمع '#line'التوجيه في الإخراج الذي يظهر عند خيار حذف.)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top