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

#perl #getc

#perl #getc

Вопрос:

Я хочу рассчитать частоту появления символов в сообщении с использованием Perl. Например, если символ «a» появляется в сообщении 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 ВВОД вместо getc(INPUT) . Я не думаю, что мне нужно включать какие-либо другие пакеты при запуске этого скрипта.

Комментарии:

1. У вас синтаксическая ошибка в этом фрагменте (в while строке).

2. getc не работает… О, да, это так.

Ответ №1:

 while (<INPUT>)
  

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

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

 my $c;
while (defined($c = getc(INPUT))) {
  print $c, "n";
}
  

Комментарии:

1. Спасибо! Это работает 🙂 Мне нравится ваша идея. Поскольку getc возвращает значение undef при ошибке или EOF, мы можем использовать определенную функцию. Интересно!

Ответ №2:

Смешивать оператор чтения файла ( < ... > ) с 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 "$cn";
}
  

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

 #!/usr/bin/perl

use strict;
use warnings;

my $input = shift;

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

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

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

Ответ №3:

Просто для небольшого 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