Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I'm working on an assignment which requires me to read from a .log file, split it, and count how many times a certain ID went to a certain building. For example: a19:01-01-2009:s1 a31:01-01-2009:s2 a28:01-01-2009:s1 a41:01-01-2009:s1 I would split on the colons. Element one is the ID (For an animal) Element 2 is the date it visited a building (I don't use this value in my code) and the third element is the building the ID visited. I keep getting an error when I run my code
#!/usr/bin/perl -w use strict; use warnings; use diagnostics; my %s1 = (); #initialize hashes my %s2 = (); open FILE, "stations.log" or die "cannot open file stations.log:\, it +does not exist. $!\n"; #open file for reading while (<FILE>){ my $station_visits = $_; #initialize variable and set to the file +which was opened chomp ($station_visits); #CHOMP! my ($animal_id, $date , $station) = split/:/, $station_visits; #sp +lit on colons $s1{animal_id} = 0; $s2{animal_id} = 0; if ($s1{$animal_id} eq undef){ #if there is no value for $s1{anima +l_id}, set it to 0 $s1{$animal_id} = 0; } if ($s2{$animal_id} eq undef){ #if there is no value for $s2{animal +_id}, set it to 0 $s2{$animal_id} = 0; } #number of times animal visits station 1 if ($station eq 's1'){ #If the animal vists station 1, create, to + 0, and add 1. # if (not exists($s1{$animal_id})){ # $s1{$animal_id} = 0; #} $s1{$animal_id} = $s1{$animal_id} + 1; } else{# ($station eq 's2'){ #if (not exists($s2{$animal_id})){ #If the animal vists stati +on 2, create, to 0, and add 1. # $s2{$animal_id} = 0; # } $s2{$animal_id} = $s2{$animal_id} + 1; } } print "Animal Id\tStation 1\t Station 2\n"; foreach my $animal_id (sort keys (%s1)){ #for each hash, print values + into a table print "$animal_id \t\t $s1{$animal_id} \t\t $s2{$animal_id}\n";
The error I recieve is "Use of uninitialized value in string eq at analyze-frequencies.pl line 21, <FILE> line 283 (#1) Use of uninitialized value in string eq at analyze-frequencies.pl line 18, <FILE> line 284 (#1) Use of uninitialized value in string eq at analyze-frequencies.pl line 21, <FILE> line 284 (#1) Followed by the desired output : Animal Id Station 1 Station 2 a23 6 0 a37 12 4 a45 0 10 ... I am really unsure as to why I am getting this error. I thought I initialized my hashes and the $s1{animal_id} = 0; part too. I am at my wits end regarding this, I've spend quite a few hours and this is all I have. Thanks for taking the time to read my plea for help ; ;

Replies are listed 'Best First'.
Re: Uninitialized errors when using 2 hashes.
by ssandv (Hermit) on Oct 22, 2010 at 22:39 UTC

    To expand on the answer above, the correct way to test for definedness, or the lack thereof, is with defined, something like

    if (!defined $var) {...
    , not with
    if ($var eq undef) {...
    See also exists

Re: Uninitialized errors when using 2 hashes.
by AnomalousMonk (Archbishop) on Oct 23, 2010 at 04:10 UTC
    ... I initialized my hashes and the  $s1{animal_id} = 0; part too.

    In addition to the other replies, and in case you have not already realized it, the statements
        $s1{animal_id} = 0;
        $s2{animal_id} = 0;
    do nothing in the context of the code you have shown. What they actually do is to set the value of the key  'animal_id' to 0 in both the  %s1 and  %s2 hashes on each pass through the  while loop. No further reference is made to this key in these hashes in the code shown. The keys contained in the scalar variable  $animal_id seem to have a format like  'a19' (as far as I can tell from the confusingly formatted OP), and are nothing like  'animal_id'.

    The other point to understand is that creating an empty hash (as all hashes and arrays are when created) and then initializing it as an empty hash is not really 'initializing' it in any programatic sense. The only purpose, IMO, of a statement like
        my %s1 = ();
    is to say 'yes, I really do mean this hash to be empty at this point', thus obviating the need to type out an explicit comment to this effect – which may be a very useful side effect!

Re: Uninitialized errors when using 2 hashes.
by shevek (Beadle) on Oct 23, 2010 at 10:44 UTC
    You need to make sure you understand defined, exists, and false values. You can enter a value of undef for a given key in a hash.
    my %hash = (); $hash{'bar'} = undef;
    At this point, defined $hash{'bar'} is false, but exists $hash{'bar'} evaluates to true. defined will signal if a key has a "defined" value. exists signals whether the key "exists".
    $hash{'bar'} = '';
    The above code will evaluate to true when tested with defined or exists. One thing to remember is that there are four false values: '',0,'0', and undef. If you assign undef to a hash key the following if statements are equivalent:
    $hash{'bar'} = undef; if(defined $hash{'bar'}){print "false"} if($hash{'bar'}){print "false"}
    If you assign any other false value to a hash key you get a different result:
    $hash{'bar'} = '0'; if(defined $hash{'bar'}){print "true") if($hash{'bar'}){print "false")
    The lesson, I guess, is when you are testing whether a value has been set to undef you should use defined;it will return false for the value undef, and true for all other values. When testing whether a key exists in a hash then you use exist. When testing whether a value is false or true you should just use the value itself.
Re: Uninitialized errors when using 2 hashes.
by Tails (Novice) on Oct 22, 2010 at 23:16 UTC
    Hey guys, I forgot to log on when posting this question. I'm just a mess right now. The !defined worked, and I am filled with joy! Thank you so much for the helpful information, I can now proceed to finish the rest of the assignment without worrying about this. Thanks very much!
Re: Uninitialized errors when using 2 hashes.
by choroba (Cardinal) on Oct 22, 2010 at 22:26 UTC
    The variable is not the uninitialized value, the undef is.
A reply falls below the community's threshold of quality. You may see it by logging in.