Почему моя программа, использующая функцию Perl getc, не работает должным образом? - PullRequest
0 голосов
/ 16 октября 2011

Я хочу рассчитать частоту появления символов в сообщении, используя Perl. Например, если символ «а» появляется в сообщении 10 раз, то частота равна 10. Для этого я читаю сообщение из ФАЙЛА по одному символу за раз, используя функцию getc, Вот фрагмент, который я написал. Это очень просто, я знаю. Но когда я компилирую, я получаю сообщение об ошибке:

Детали:

#!/usr/bin/perl

use strict;
use warnings;

my $input=$ARGV[0];

open(INPUT,"<$input");

while(<INPUT>
{
 my $c=getc(INPUT);
 print $c."\n";
}

close(INPUT);

Я получаю сообщение об ошибке ниже при попытке его скомпилировать:

Use of uninitialized value in print at AccessChar.pl line 13, <INPUT> line 1.

Я не могу понять, что не так с этим сценарием. Может ли кто-нибудь помочь мне с этим?

Я даже пытался использовать getc INPUT вместо getc(INPUT). Я не думаю, что мне нужно включать какие-либо другие пакеты при запуске этого скрипта.

Ответы [ 3 ]

5 голосов
/ 16 октября 2011
while (<INPUT>)

будет читать всю строку из INPUT на каждой итерации цикла.Если вы хотите обрабатывать этот дескриптор файла по одному символу за раз, это неправильная конструкция для использования.

Попробуйте что-то вроде:

my $c;
while (defined($c = getc(INPUT))) {
  print $c, "\n";
}
2 голосов
/ 16 октября 2011

Смешивать оператор чтения файлов (< ... >) с getc - плохая идея.Он не делает то, что вы думаете.

Попробуйте вставить отладочный вывод в программу, чтобы увидеть, что происходит.Я протестировал программу, запустив ее на себя (./getc getc).

В начале цикла while <INPUT> читает строку из вашего файла и сохраняет ее в $_.Затем вы используете getc, чтобы прочитать следующий символ из файла.Это будет первый символ из второй строки вашего файла (вероятно, символ новой строки - который, вероятно, будет единственным символом в этой строке).

В следующий раз при цикле, <INPUT> читаетследующая строка ввода.Это строка use strict.getc читает следующий символ, который является 'u' из use warnings.

И поэтому он продолжается до конца файла.<INPUT> читает строку, а затем getc читает первый символ из следующей строки.

Это совсем не то, что вам нужно.Если вы хотите прочитать символ за раз, тогда вам просто нужно getc.

#!/usr/bin/perl

use strict;
use warnings;

my $input = shift;

open(my $file, '<', $input);

while (defined(my $c = getc $file)) {
  print "$c\n";
}

Другой вариант - просто использовать < ... > и разбивать каждую строку, когда вы ее читаете.

#!/usr/bin/perl

use strict;
use warnings;

my $input = shift;

open(my $file, '<', $input);

while (<$file>) {
  foreach my $c (split //) {
    print "$c\n";
  }
}

Но смешивание двух подходов никогда не сработает.

1 голос
/ 17 октября 2011

Просто для небольшого TIMTOWTDI:

#!/usr/bin/env perl

use strict;
use warnings;

use Data::Dumper;

local $/;
my %chars;

$chars{$_}++ for split //, <>;

print Dumper \%chars;

, который работает до тех пор, пока файл не слишком большой, чтобы его обойти;если это чтение и разбить каждую строку.Использование:

$ count_chars.pl file_to_read
...