2014-08-30 2 views
1

Ниже я пытаюсь прочитать данные из файла и попытаться сохранить их в массиве. Размер массива в этом случае должен быть 6, так как максимальное значение раунда равно 6 (1,2,3,4,5,6).Использование хэшей и массивов в Perl

Я ожидаю массив из 6 элементов, имеющих некоторое количество. Пожалуйста, помогите мне, где я ошибаюсь. Я новичок в perl.

if (!defined($ARGV[0])) { print "ENTER OUTPUT Filename\n"; exit 1; } 
$outputFile = $ARGV[0]; 
open(HND, "$outputFile"); 
while (<HND>) 
{ 
    chomp; 
    my $line = $_; 
    if (/Node (.*) sending (.*) data to BS at time (.*) node 0 round (.*)$/) 
    { 
     my $round = $4; 
     my $data = $2; 
     if (exists($CHenergy{$round})) 
     { 
      $CHenergy{$round} += $data; 
     } 
     else 
     { 
      $CHenergy{$round} = $data; 
     } 
    } 
} 
close HND; 
print join(", ", $CHenergy); 

В конце концов я печатаю значения массива, но ничего не печатает.

+4

ВСЕГДА используйте строгое; использовать предупреждения, 'в начале ваших скриптов. – Toto

ответ

2

Вы должны всегда добавить use strict и use warnings в верхней части каждой программы Perl, и объявить все переменные с помощью my. В этом случае он сказал бы вам, что не было хеша %CHenergy.

Помните, что Perl имеет три основных типа данных - скаляры, начинающиеся с $; массивы, которые начинаются с @; и хешей, которые начинаются с %. И они могут делиться идентификаторами, например, $data, @data и %data могут существовать одновременно и не зависят друг от друга. Значения хэш индексируются с использованием квадратных скобок [...], а значения массивов индексируются с помощью фигурных скобок {...}, но поскольку одно значение представляет собой скаляр , они начинаются с $; например $data[0] и $data{key}.

Вы используете брекет{ .. } индексировать то, что вы думали, был массив, но $CHenergy{$round} является индексация хэша%CHenergy. @ARGV - массив, и вы успешно проиндексировали его с помощью скобок [ .. ]. Таким же образом вам необходимо получить доступ к массиву @CHenergy.

Вы также должны использовать строчные буквы, цифры и подчеркивание для обозначения локальных переменных. Заглавные буквы зарезервированы для глобальных идентификаторов.

Я изменил вашу программу, чтобы показать лучший способ ее записи, и использовал формат printf для форматирования данных.

use strict; 
use warnings; 

my ($input_file) = @ARGV; 

unless ($input_file) { 
    warn "Enter input filename\n"; 
    exit 1; 
} 

open my ($hnd), '<', $input_file or die $!; 

my @ch_energy; 
while (<$hnd>) { 
    next unless /Node (.*) sending (.*) data to BS at time (.*) node 0 round (.*)/; 
    my ($data, $round) = ($2, $4); 
    $ch_energy[$round] += $data; 
} 

for my $i (0 .. $#ch_energy) { 
    my $energy = $ch_energy[$i]; 
    printf "%2d => %d\n", $i, $energy if defined $energy; 
} 
1

Это не массив, вы используете хэш (%CHenergy). Для того, чтобы напечатать свои ключи:

my @the_keys = keys %CHenergy; 
print join(", ", @the_keys), "\n"; 

Модуль Data::Dumper может, поможет вам показать содержимое переменной:

use Data::Dumper; 
#... 
print Dumper(%CHenergy), "\n"; 

Примечание: используйте современный PERL подход для работы с файлами:

open (HND,"$outputFile"); 

должно быть (замените HND на $ HND в остальной части вашего кода):

open my $HND, ">", "$outputFile" or die $!; 
+0

Это дает мне вывод как это $ VAR1 = '6'; $ VAR2 = 78956; $ VAR3 = '4'; $ VAR4 = 40271; $ VAR5 = '1'; $ VAR6 = 26731; $ VAR7 = '3'; $ VAR8 = 39792; $ VAR9 = '2'; $ VAR10 = 30111; $ VAR11 = '5'; $ VAR12 = 62232; Как я могу отформатировать его. 1 некоторый номер 2 некоторая цифра .. –

+0

@MuhammadZaighum: используйте это: 'print Dumper \% CHenergy;', обратите внимание на обратную косую черту. – Toto

0

Вы должны use strict и use warnings. Помимо его основной функции, это поможет вам понять некоторые из принципов и функций Perl.

Как указывалось, переменная CHenergy не является массивом, а хешей. Если вы хотите использовать массив (который, возможно, немного более подходит для этой проблемы), вы должны префикс переменной с помощью знака at (my @array) и получить доступ к элементам массива, используя квадратные скобки вместо скобок ($array[0]).

Это, как я сделал бы это:

#!/usr/bin/env perl 

use strict; 
use warnings; 

my $filename = shift or die "You must supply an input file."; 
open my $fh, $filename or die $!; 

my @CHenergy = (0,0,0,0,0,0); 

while (<$fh>) { 

    if (/Node (.*) sending (.*) data to BS at time (.*) node 0 round (.*)$/) { 
     my $data = $2; 
     my $round = $4; # replace with "$4 - 1" when 
         # the round is from 1 to 6 
         # instead of 0 to 5 

     $CHenergy[$round] += $data; 
    } 
} 

close $fh; 
print join(", ", @CHenergy); 

В следующей правке программы, я предлагаю, чтобы изменить регулярное выражение (в частности, двойной пробел после третьей пары скобок). Если вы не используете поля $1 и $3, тогда не включайте их в регулярное выражение. Кроме того, можно выполнить проверку на полях для обеспечения существует ряд на линии:

/^Node .* sending ([0-9]+) data to BS at time .* node 0 round ([0-5])$/ 

отметить также, что chomp утверждение не necessarry - символ новой строки сопоставляется знаком доллара в регулярном выражении.

Смежные вопросы