1

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.

1
  • 4
    ALWAYS use strict; use warnings; at the begining of your scripts. Commented Aug 30, 2014 at 11:44

3 Answers 3

2

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;
}
Sign up to request clarification or add additional context in comments.

Comments

1

It isn't an array, you are using a hash (%CHenergy). To print its keys:

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

The module Data::Dumper may helps you to show the variable contents:

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

Note: use the modern perl approach to handle files:

open (HND,"$outputFile");

should be (replace HND by $HND in the rest of your code):

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

2 Comments

It is giving me output like this $VAR1 = '6'; $VAR2 = 78956; $VAR3 = '4'; $VAR4 = 40271; $VAR5 = '1'; $VAR6 = 26731; $VAR7 = '3'; $VAR8 = 39792; $VAR9 = '2'; $VAR10 = 30111; $VAR11 = '5'; $VAR12 = 62232; How can I format it to. 1 some number 2 some number ..
@MuhammadZaighum: use this: print Dumper\%CHenergy;, notice the backslash.
0

You should use strict and use warnings. Beside it's primary function, it will help you to understand some of the Perl's principles and features.

As pointed out, the CHenergy variable is not an array, but a hash. If you want to use an array (which is perhaps a little more suitable for this problem), you must prefix the variable with the at-sign (my @array) and access the members of the array using square brackets instead of braces ($array[0]).

This is how I would have done it:

#!/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);

As a following edit to the program, I suggest to alter the regular expression (particularly the double space after the third pair of parentheses). If you are not using the fields $1 and $3, then don't include them in the regex. You can also perform a validation on the fields to ensure there is a number on the line:

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

Also note that the chomp statement is not necessarry - the newline is matched by the dollar sign in the regular expression.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.