开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜