#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