2017-02-07 17 views
0

Я пытаюсь открыть файл, сканировать его, и программа распечатает количество положительных, отрицательных и нулевых значений. У меня есть программа, которая успешно открывает файлы, но найти «Частоту» - это то, что вызывает у меня проблемы. Я был болен в день занятий и не могу найти помощь, связанную с моей конкретной подсказкой. Вот что у меня есть до сих пор:Как найти конкретную величину/частоту положительных, отрицательных и нулевых целых чисел в файле? (Perl)

#!/usr/bin/perl 
use strict; 
use warnings; 
my ($ctrZ) = (0); 
while(my $num = <DATA>) { 
     chomp($num); 
     ## print "num=[$num]\n"; 
     if ($num =~ /^-\d+$/) { 
       $ctrZ++; 
     } 

printf("freq(0):%9s\n", $ctrZ); 

exit; 
__DATA__ 
19 
-22 
498 
512 
15 
-932 
0 
22 
808 
17 
-32 

Примечание: Наш профессор дал нам файл для использования. Это файл .txt с одним номером на каждой строке.

+1

Http: //perldoc.perl. org/perlop.html # Реляционные операторы – toolic

+0

Вам действительно нужны комментарии, такие как 'chomp ($ infile); # Chomps $ infile Variable.'? – Borodin

+0

Да, наш профессор предпочитает иметь их. Кроме того, я добавил неправильный код для начала. Это то, что у меня есть. Мне просто нужно найти, сколько целых чисел находится в файле. –

ответ

1

Там же несколько проблем с кодом, но основным из них является следующее:

if ($infile) { 
     $Pos_Int++; 
     $Neg_Int++; 
     $Zer_Int++; 
} 

Вот только оценивая содержание $infile которое является именем файла. Это всегда будет правдой, и поэтому вы всегда будете увеличивать все ваши счетчики на единицу.

Итак, все, что вы здесь делаете, в основном подсчитывает линии.

Я хотел бы также предположить, однако, что вам не нужно:

open(FHIN, '<', $infile); #Opens the file prompted by user. 
my @lines = <FHIN>; #Variable storing the number of lines in the file. 
chomp(@lines); 
close(FHIN); 

Открыть файл, прочитать его в массив, а затем перебирать массив?

Почему бы не вместо этого идти по строкам с циклом while (он также использует меньше памяти).

Также - хороший стиль - использовать лексические файлы, а не имя верхнего регистра, что является глобальной областью.

Итак:

open (my $input, '<', $infile) or die $!; #check return code for errors. 
while (my $line = <$input>) { #iterate the input line by line, setting $_ for each. 
    $Pos_Int++ if $line > 0; 
    $Neg_Int++ if $line < 0; 
    $Zer_Int++ if $line == 0; 
} 

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

также:

if (-e $infile) { #If the file can't be found, it will exit. 

    } else { 
     print ("No such file exists. Program closing.\n"); 
      exit; 
} 

Это является излишним, так как вы можете - и должны - ловушка код возврата open. Если вы это сделаете, вы поймаете другие условия, такие как файл, который нельзя читать, или быть сломанной символической ссылкой или множеством других проблем.

E.g.

open (my $input, '<', $infile) or die "Problem opening file: $!"; 

$! даст вам код ошибки, который немного больше смысла тоже - это вам скажу разницу между «нет такого файла или каталога» и «доступ запрещен», например.

+1

Также стоит отметить, что тест на существование лишний, так как статус 'open' должен быть проверен в любом случае. – Borodin

+0

Хорошая точка. Я поправляю. – Sobrique

+1

Просто примечание: * избыточное * на американском английском может означать что-то более похожее * чрезмерное *, * щедрое * или * за нормальное *. Например, двухфакторная аутентификация является «избыточной» безопасностью. Вот почему я придерживаюсь * лишних * на этих страницах. – Borodin

-1

Вы можете использовать оператор <=>, чтобы получить именно то, что хотите. В соответствии с perldoc perlop:

двоичный «<=>» возвращает -1, 0 или 1 в зависимости от того, является ли левый аргумент численно меньше, равен или больше, чем правый аргумента.

Итак:

$ perl -MData::Dumper -wne '$count{$_ <=> 0}++; END { print Dumper(\%count); }' numbers.txt 

Предполагая numbers.txt содержит следующее:

111 
0 
-892 
-664 
21 
0 
63 
868 
-351 
-263 
467 
-58 
625 
724 
0 
0 
990 
107 
-739 
-501 
-386 
909 
-96 
0 
-735 

выход будет:

$VAR1 = { 
      '0' => 5, 
      '1' => 10, 
      '-1' => 10 
     };