Why is my program using Perl's getc function not working properly?
I want to calculate the frequency of occurrence of chars in a message using Perl. For instance, if the char "a" appears 10 times in a message, then the frequency would be 10. To do this, I am reading the message from a FILE one char at a time using the getc function. Here's the snippet I have written. It's very basic, I know. But when I compile, I get an error:
Details:
#!/usr/bin/perl开发者_C百科
use strict;
use warnings;
my $input=$ARGV[0];
open(INPUT,"<$input");
while(<INPUT>
{
my $c=getc(INPUT);
print $c."\n";
}
close(INPUT);
I get the below error when I try to compile it:
Use of uninitialized value in print at AccessChar.pl line 13, <INPUT> line 1.
I am not able to figure out, what's wrong with this script. Could someone help me out with this?
I have even tried using getc
INPUT instead of getc(INPUT)
. I don't think I need to include any other packages while running this script.
while (<INPUT>)
will read a whole line from INPUT
at each iteration of the loop. If you want to process that file handle one char at a time, it is not the right construct to use.
Try something like:
my $c;
while (defined($c = getc(INPUT))) {
print $c, "\n";
}
Mixing the file read operator (< ... >
) with getc
is a bad idea. It's not doing what you think it is.
Try putting some debug output into the program to see what's going on. I tested the program by running it on itself (./getc getc
).
At the start of the while
loop, the <INPUT>
reads a line from your file and stores it in $_
. You then use getc
to read the next character from the file. That will be the first character from the second line of your file (probably a newline character - which is likely to be the only character on that line).
The next time round the loop, the <INPUT>
reads the next line of input. That's the use strict
line. The getc
reads the next character which is the 'u' from use warnings
.
And so it continues to the end of the file. The <INPUT>
reads a line and then the getc
reads the first character from the next line.
That's not what you want at all. If you want to read a character at a time then you just need the getc
.
#!/usr/bin/perl
use strict;
use warnings;
my $input = shift;
open(my $file, '<', $input);
while (defined(my $c = getc $file)) {
print "$c\n";
}
Another alternative would be to just use < ... >
and split each line as you read it.
#!/usr/bin/perl
use strict;
use warnings;
my $input = shift;
open(my $file, '<', $input);
while (<$file>) {
foreach my $c (split //) {
print "$c\n";
}
}
But mixing the two approached is never going to work.
Just for a little TIMTOWTDI:
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;
local $/;
my %chars;
$chars{$_}++ for split //, <>;
print Dumper \%chars;
which works as long as the file isn't too large to slurp; if it is the read and split each line. Usage:
$ count_chars.pl file_to_read
精彩评论