HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Calculating bytes of code

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
codecalculatingbytes

Problem

I am new to Perl and I wrote this Perl script to calculate bytes of code and lines of code in a directory. I want to know if there are any improvements that can be made to it.

```
#!/usr/bin/perl
# codestats.pl
# A perl script to calculate the number of lines of code in a project
# and what type of lines those code are, such as comments, code, or
# newlines. This script is specific to C/C++, but it should work with any
# language that has the same commenting scheme, so it should probably work
# with java too.
#
# Henry J Schmale
# April 30, 2015

use strict;
use warnings;

my @srcext = (".cpp", ".c", ".h", ".hpp", ".ino", ".cxx", "*.cc");

my $commLines = 0; # Lines that start with a comment symbol
my $bothLines = 0; # Lines that have a comment and code
my $newLines = 0; # Lines that are just whitespace
my $codeLines = 0; # Lines of code - lines that don't fit in another space
my $totLines = 0; # Total lines of code
my $srcBytes = 0; # Total Number of bytes in src code
my $fCount = 0; # Number of files read

my $files;
for($a = 0; $a ;
for($b = 0; $b newLine
$newLines++;
next;
}
if(($lines[$b] =~ /^\s*\/\//) || # comments only lines
($lines[$b] =~ /^\s\/\/) ||
($lines[$b] =~ /^\s\/)){
$commLines++;
next;
}
# code + comments
if(($lines[$b] =~ /\/\//) ||
($lines[$b] =~ /\/\.\*\//)){
$bothLines++;
next;
}
$codeLines++;
}
close FILE;
}

sub calcPercent{
return ($_[0] / $_[1]) * 100.0;
}

sub printResults{
# print out the results
printf("Read %d Files\n", $fCount);
printf("Average Lines Per File: %d\n", $totLines / $fCount);
printf("Code : %09d ln. %06.3f", $codeLines, calcPercent($codeLines, $totLines));
print "%\n";
printf("Comment : %09d ln. %06.3f", $commLines, calcPercent($commLines, $totLines));
print "%\n";
printf("Blank : %09d ln. %0

Solution

It's easy to write very ugly Perl code,
but this is pretty nicely written, so congrats.

Using barewords for file handles like this is discouraged:

open(FILE, ";
# ...
close FILE;


The recommended way:

open(my $fh, ";
# ...
close $fh;


Some simplifications are possible.
For example instead of this:

my @srcext = ("*.cpp", "*.c");


I find this way a lot easier to type:

my @srcext = qw/*.cpp *.c/;


Another, bigger simplification is in the loops.
Instead of this:

my @lines = ;
for($b = 0; $b  newLine
        $newLines++;
        next;
    }
    if(($lines[$b] =~ /^\s*\/\//) || # comments only lines
       ($lines[$b] =~ /^\s*\/\*/) ||
       ($lines[$b] =~ /^\s*\*/)){


You can iterate using for () { ... },
and instead of $lines[$b], benefit from the auto-variable $_,
which can be omitted from $lines[$b] =~ /.../ statements,
like this:

for () {
    $srcBytes += length($_);
    $totLines++;
    if(/^\s$/){ # is only whitespace ==> newLine
        $newLines++;
        next;
    }
    if(/^\s*\/\// || # comments only lines
       /^\s*\/\*/ ||
       /^\s*\*/){

Code Snippets

open(FILE, "<$srcfile") or die "Couldn't open file: $!\n";
my @lines = <FILE>;
# ...
close FILE;
open(my $fh, "<$srcfile") or die "Couldn't open file: $!\n";
my @lines = <$fh>;
# ...
close $fh;
my @srcext = ("*.cpp", "*.c");
my @srcext = qw/*.cpp *.c/;
my @lines = <FILE>;
for($b = 0; $b < scalar(@lines); $b++){
    $srcBytes += length($lines[$b]);
    $totLines++;
    if($lines[$b] =~ /^\s$/){ # is only whitespace ==> newLine
        $newLines++;
        next;
    }
    if(($lines[$b] =~ /^\s*\/\//) || # comments only lines
       ($lines[$b] =~ /^\s*\/\*/) ||
       ($lines[$b] =~ /^\s*\*/)){

Context

StackExchange Code Review Q#94581, answer score: 7

Revisions (0)

No revisions yet.