Using hashes and arrays in Perl

advertisements

Below I am trying to read data from a file and trying to store them in an array. The array size in this case should be 6 as highest value of round is 6 (1,2,3,4,5,6).

I am expecting an array of 6 elements having some number. Please help me where I am going wrong. I am new to 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);

At then end I am printing values of the array but it is printing nothing.


You must always add use strict and use warnings to the top of every Perl program, and declare all your variables using my. In this instance it would have told you that there was no hash %CHenergy.

Remember that Perl has three primary data types -- scalars, that start with $; arrays, that start with @; and hashes, that start with %. And they may share identifiers, for instance, $data, @data, and %data can all exist at the same time and are independent from one another. Hash values are indexed using square brackers [...] and array values are indexed using braces {...}, but because a single value is a scalar, they both start with $; for instance $data[0] and $data{key}.

You are using braces { .. } to index what you thought was an array, but $CHenergy{$round} is indexing the hash %CHenergy. @ARGV is an array, and you have indexed that successfully with brackets [ .. ]. You need to access array @CHenergy in the same way.

You should also use lower-case letters, digits and underscore to name local variables. Capital letters are reserved for global identifiers.

I have modified your program, to show a better way of writing it, and have used printf to format the data.

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;
}