http://www.perlmonks.org?node_id=147260


in reply to uninitialized value in phonebook program

I noticed two problems in your code. First, the line where you're getting the warning:
$name =~ /(.+)&(.+)/; if ($2 =~ /^0$/) {
You haven't actually verified that the regex matched against $name. I suspect that the regex match is failing, leaving $1 and $2 uninitialized, because $name doesn't hold what you think it does. Make sure the match succeeds before relying on the special variables.

Second, to check the format, you have a while loop inside your foreach loop. If $_ is false, you push 0 onto @info, and then call next. However, this next jumps to the next iteration of the while loop (which would happen anyway), when you want to jump to the next iteration of the foreach loop. You should use a loop label to resolve this problem.

Replies are listed 'Best First'.
Re: Re: uninitialized value in phonebook program
by smgfc (Monk) on Feb 25, 2002 at 04:49 UTC
    when you change the code to print out the values of $name, $1, and $2:
    foreach $name (keys %book) { #write the data print "$name \n"; $name =~ /(.+)&(.+)/; print "$1, $2 \n"; if ($2 =~ /^0$/) { print BOOK "$1,::"; } else { print BOOK"$1,$2::"; } for ( 0 .. $#{ $book{$name} } ) { print BOOK $def[$_+2] . ":" . $book{$name}[$_] . "::" unless +$book{$name}[$_] =~ /^0$/; } print BOOK "\n"; }
    you get the correct output, and it shows $1 and $2 are initialized, but you still get the uninitialized error. Here is the output when you pass it School&0 and one number:
    
    school&0
    
    school, 0 
    # Use of uninitialized value, <> chunk 7.
    File 'untitled:Desktop Folder:Will's Stuff:Applications:MacPerl ƒ:phonebook'; Line 57
    
    so that isnt the problem. Loop lables are a good idea, though, thanks
      Oh, now I got it! The warning is not actually coming from the if ($2 =~ /^0$/) { line. Unfortunately, perl sometimes reports the line number where an if block starts when the warning actually occurs later in the block. That's what is happening here.

      First, you perform a regex match against $name, setting $1 and $2. Then, you perform a regex match against $2. So far, so good. Then you print out the values of $1 and $2. Oops! That second regex match you just did has wiped out the values of $1 and $2!

      jeffa's node shows two ways to solve this problem. Either assign the results of the first match to new variables: my($first, $last) = $name =~ /(.+)&(.+)/; Or replace the second match with a comparison: if ($2 eq '0') {