vihar has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I am trying to do a simple thing here. I have 7 files that I am reading from directory. I need to be able to get number of lines for each file and then another number that has a total of lines counts for all 7 files.

Here is my code
#Getting all individual files and number of total files @ISFiles = glob 'dir1/file.split.*'; $ISNumFiles = scalar(@ISFiles); #getISCount() function that gets count for each file sub getISCount { my @files = @_; foreach $file (@files) { open(FILE, $file) or die "Can't open `$file': $!"; while (sysread FILE, $buffer, 4096) { $count += ($buffer =~ tr/\n//); } close FILE; } return $count; } $i = 0; $j = 1; while($i < scalar(@ISFiles)) { $ISCountForFile[$j] = &getISCount(@ISFiles[$i]); $i = $i + 1; $j = $j + 1; } $combinedCount = &getISCount(@ISFiles); print "combined count - $combinedCount\n";
The problem is when these individual counts are returned, the count for the second file is always count for the first file + count for second file and so on... I am not sure why it is incrementing.

Also, the final $combinedCount should just be a sum of all individual files. Instead, it returns the sum of (lines file1 + (lines file1 + lines file2) + ... )

For example,
If following are my line counts:
File1 = 10
File2 = 10
File3 = 10

The result I should be getting is
FileCount1 = 10
FileCount2 = 10
FieCount3 = 10
$combinedCount = 30

Instead, I am getting this:
FileCount1 = 10
FileCount2 = 20
FileCount3 = 30
$combinedCount = 60

Any idea why it is double counting?
Thanks

Replies are listed 'Best First'.
Re: While loop double counting
by LanX (Saint) on Nov 23, 2013 at 04:42 UTC
    You are not initializing $count with my in the sub.

    This way it becomes global and is never resetted.

    Plz use strict to avoid such problems.

    Cheers Rolf

    ( addicted to the Perl Programming Language)

      Never mind. I got it. Sorry for multiple replies. Thanks for your help and I will be sure to use strict from now on.
      Thanks for your reply. I am not sure if I am understanding it right. Do you mean add my in front of $ISCountForFile[$i] to make it
      my $ISCountForFile[$i] = &getISCount(@ISFiles[$i]);
      Thanks!
      I tried adding my for $count in sub but after that I don't get any numbers back. Thanks
Re: While loop double counting
by Laurent_R (Canon) on Nov 23, 2013 at 11:17 UTC

    You would need to declare $count with the my operator within the getISCount subroutine but before entering the loops.

    Also reading again all your files to get the total count can be very inefficient if your files are large, whereas you only need to accumulate the individual line counts. Perhaps something like this, which stores the file names and file line counts in a hash for further use:

    use strict; use warnings; use Data::Dumper; my $total_count; my %files = map {$_, 0} glob "./s*.pl"; for my $key (keys %files) { my $count = getcount($key); $files{$key} = $count; $total_count += $count; } sub getcount { local @ARGV = @_; while (<>) {}; return $.; } print Dumper \%files; print "Total size = $total_count lines.\n";
    which prints: If you only need to print the counts and don't need to store the values for further use, this can be simplified as follows: which prints this: