Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to handle $x = undef and $x = 0 1

Status
Not open for further replies.

whn

Programmer
Oct 14, 2007
265
0
0
US
I wrote a small piece of codes that does not run as I expected:

Code:
my $x1 = undef;
my $x2 = 0;
my $x3 = -1;
my $x4 = 1;

my @arr = ($x1, $x2, $x3, $x4);
for(my $i = 0; $i <= $#arr; $i++) {
  if($arr[$i]) {
    print "\$i = $i, \$arr[$i] = $arr[$i]\n";
  }
  else {
    if($arr[$i] == 0) { [b]# This is line 16[/b]
      print "\$i = $i, \$arr[$i] is zero\n";
    }
    elsif($arr[$i] < 0) {
      print "\$i = $i, \$arr[$i] is negative\n";
    }
    else {
      print "\$i = $i, \$arr[$i] = undef\n";
    }
  }
}

And the output of an actual test run:
Code:
% test.pl -w
Use of uninitialized value within @arr in numeric eq (==) at ./test.pl [b]line 16[/b].
$i = 0, $arr[0] is zero
$i = 1, $arr[1] is zero
$i = 2, $arr[2] = -1 // I don't understand why $arr[2] falls into the 'if' block, instead of the 'else' block
$i = 3, $arr[3] = 1

My first question is --
How can I get rid the warning?

Secondly, once I get rid of the warning, here is what I expect:
Code:
% test.pl -w
Use of uninitialized value within @arr in numeric eq (==) at ./test.pl [b]line 16[/b].
$i = 0, $arr[0] = undef
$i = 1, $arr[1] is zero
$i = 2, $arr[2] is negative // question: wouldn't 'if($arr[2])' returns false when $arr[2] == -1? At least it's case in C/C++, right?
$i = 3, $arr[3] = 1

BTW, I know 'if(!$arr[$i])' would get rid of the warning, bug I don't know how distinguish '0' and 'undef'.

Thanks for the explanation and I hope I have made myself clear.
 
I also tried this:
Code:
my $x1 = undef;
my $x2 = 0;
my $x3 = -1;
my $x4 = 1;

my @arr = ($x1, $x2, $x3, $x4);
for(my $i = 0; $i <= $#arr; $i++) {
  if($arr[$i]) {
    print "\$i = $i, \$arr[$i] = $arr[$i]\n";
  }
  else {
    if(!$arr[$i] && $arr[$i] != 0) { [b]# line 16[/b]
      print "\$i = $i, \$arr[$i] = undef\n";
    }
    elsif(!$arr[$i] && $arr[$i] == 0) { [b]# line 19[/b]
      print "\$i = $i, \$arr[$i] is zero\n";
    }
    elsif($arr[$i] < 0) {
      print "\$i = $i, \$arr[$i] is negative\n";
    }
  }
}

And the output:

Code:
% ./test.pl -w
Use of uninitialized value within @arr in numeric ne (!=) at ./test.pl line 16.
Use of uninitialized value within @arr in numeric eq (==) at ./test.pl line 19.
$i = 0, $arr[0] is zero
$i = 1, $arr[1] is zero
$i = 2, $arr[2] = -1
$i = 3, $arr[3] = 1

Thanks again for your time and help!!
 
Hi

I think that is a pure logical issue : you should check definedness first, not last :
Code:
[b]for[/b][teal]([/teal][b]my[/b] [navy]$i[/navy] [teal]=[/teal] [purple]0[/purple][teal];[/teal] [navy]$i[/navy] [teal]<=[/teal] [navy]$#arr[/navy][teal];[/teal] [navy]$i[/navy][teal]++)[/teal] [teal]{[/teal]
  [b]if[/b][teal]([/teal][navy]$arr[/navy][teal][[/teal][navy]$i[/navy][teal]])[/teal] [teal]{[/teal]
    [b]print[/b] [green][i]"\$i = $i, \$arr[$i] = $arr[$i]\n"[/i][/green][teal];[/teal]
  [teal]}[/teal]
  [b]else[/b] [teal]{[/teal]
    [b]unless[/b] [teal]([/teal][b]defined[/b][teal]([/teal][navy]$arr[/navy][teal][[/teal][navy]$i[/navy][teal]]))[/teal] [teal]{[/teal]
      [b]print[/b] [green][i]"\$i = $i, \$arr[$i] = undef\n"[/i][/green][teal];[/teal]
    [teal]}[/teal] [b]elsif[/b] [teal]([/teal][navy]$arr[/navy][teal][[/teal][navy]$i[/navy][teal]][/teal] [teal]==[/teal] [purple]0[/purple][teal])[/teal] [teal]{[/teal]
      [b]print[/b] [green][i]"\$i = $i, \$arr[$i] is zero\n"[/i][/green][teal];[/teal]
    [teal]}[/teal]
    [b]elsif[/b] [teal]([/teal][navy]$arr[/navy][teal][[/teal][navy]$i[/navy][teal]][/teal] [teal]<[/teal] [purple]0[/purple][teal])[/teal] [teal]{[/teal]
      [b]print[/b] [green][i]"\$i = $i, \$arr[$i] is negative\n"[/i][/green][teal];[/teal]
    [teal]}[/teal]
  [teal]}[/teal]
[teal]}[/teal]
( Personally I would remove the outer [tt]if[/tt] and put its block as [tt]else[/tt] for that [tt]if[/tt]/[tt]elsif[/tt]/.../[tt]else[/tt] instruction. )

To just get rid of the warning without reorganizing the conditional instruction, just prepend the test expression with the definedness test : [tt]if [teal]([/teal][highlight]defined [navy]$arr[/navy][teal][[/teal][navy]$i[/navy][teal]][/teal] [teal]&&[/teal][/highlight] [navy]$arr[/navy][teal][[/teal][navy]$i[/navy][teal]][/teal] [teal]==[/teal] [purple]0[/purple][teal])[/teal][/tt].

Regarding the -1, there is nothing special with it. 0 is false, anything else is true. In C/C++, JavaScript, Awk, etc. too.
Code:
[blue]master #[/blue] cat bool.c 
#include <stdio.h>

void main(void)
{
  int i;

  for (i = -2; i <= 2; i++)
    printf("%2d is %s\n", i, i ? "true" : "false");
}

[blue]master #[/blue] cc -o bool bool.c

[blue]master #[/blue] ./bool 
-2 is true
-1 is true
 0 is false
 1 is true
 2 is true


Feherke.
feherke.github.io
 
Thank you, Feherke! You are the man!!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top