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 strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Switch v nested IF inconsitencies 1

Status
Not open for further replies.

caffrinho

MIS
Mar 1, 2002
91
GB
Please help, this is driving me nuts!

Can anybody spot a difference/something wrong with either of these? In case you haven't already guessed, the switch statement doesn't resolve like i'd expect it to. The nested if does fine though.

The specific problem comes when $hcap-$this->si (should) equate to 0, i get a 2 returned rather than a 1.

I'm commenting out each code respectively, so the input data is the always the same, but the output varies depending on which i use. I must be missing something, i just don't know what!

Cheers
Code:
      switch($hcap - $this->si){
         case ($hcap - $this->si >= 18):
            return 2;
            break;
         case ($hcap - $this->si >= 0):
            return 1;
            break;
         case ($hcap - $this->si < 0):
            return 0;
            break;
      }
Code:
     if($hcap - $this->si >= 18){
         return 2;
     }else if($hcap - $this->si >= 0){
         return 1;
     }else if($hcap - $this->si < 0){
         return 0;
     }
 
Code:
$diff = $hcap - $this->si ;
 switch(TRUE){
         case ($diff >= 18):
            return 2;
            break;
         case ($diff >= 0):
            return 1;
            break;
         case ($diff < 0):
            return 0;
            break;
      }

--------------------------------------------------------------------------
I never set a goal because u never know whats going to happen tommorow.
 
thanks spookie, that does indeed work.

But would you mind enlightening me as to why my version didn't?

I'm not sure i understand your use of TRUE, either :-s , not particularly intuitive (the switch function i mean!). Found no reference or mention of it being used like that on the PHP website.

Incidentally, when trying to figure this out, i wanted to echo the value of variables being passed to the function so i did this:

Code:
   echo $i=$hcap-($this->si).":".$hcap."||";

          switch($i){
            case ($i > 17):
                 return 2;
                 break;
            case ($i >= 0):
                 return 1;
                 break;
            case ($i < 0):
                 return 0;
                 break;
          }

This gives me the same results as the nested if statement. If i just used $i = $hcap-($this->si) it would fail again!

I thought i understood the switch function, until about 2 hours ago!!?!?!?
 
Your version didn't work because the switch statement isn't supposed to work that way. It is intended for comparing a variable to discrete values, not testing ranges. This is actually a case where it would make more sense and be much clearer to just use an if statment.

A switch statement compares the variable in the switch to the value for each case and starts executing when it finds a value that is equal. Including the switch variable in the case as you did doesn't make sense. When you break it down, your original switch statement was actually the equivalent of this if statement:
Code:
if ( ($hcap - $this->si) == ($hcap - $this->si >= 18) ) {
   return 2;
} elseif ( ($hcap - $this->si) == ($hcap - $this->si >= 0) ) { 
   return 1;
} elseif ( ($hcap - $this->si) == ($hcap - $this->si < 0) ) {
   return 0;
}

You repeat the same mistake in your second version. The first case is not evaluating ($i > 17), it's evaluating ($i == ($i > 17)). Tacking on those extra characters just changes the way PHP casts the data types for comparison.

The version posted by spookie works because it compares the expression in each case to true. Since the expressions in the case statements are boolean comparisons, they would look like true == ($diff >= 18) which is equivalent to $diff >= 18. Still, it would be shorter and clearer to just use an if statement.
 
Well, actually, you can make a PHP switch act more like a switch in perl. The code:

Code:
<?php
for ($counter = 0; $counter < 10; $counter++)
{	
	$a = rand(1,6);
	
	print $a . ' ';
	
	switch (TRUE)
	{
		case (($a == 1) || ($a == 2)):
			print 'one or two';
			break;
			
		case (($a == 3) || ($a == 4)):
			print 'three or four';
			break;
		
		case (($a == 5) || ($a == 6)):
			print 'five or six';
			break;
	}
	
	print '<br>';
}
?>

Just output on my machine:

[tt]2 one or two
6 five or six
3 three or four
5 five or six
2 one or two
3 three or four
3 three or four
2 one or two
1 one or two
1 one or two[/tt]



Want the best answers? Ask the best questions! TANSTAAFL!
 
Your version didn't work because the switch statement isn't supposed to work that way.

This is correct. More specifically you can not test expressions using switch, only compare values of some variable.

switch( $var1 + $var2 ) <- using expressions will fail

$myVar = $var1+$var2;
switch( $myVar ) <- will work

This is true for most C based languages with switch available, including actionscript for flash.

However, in ASP/VBScript, you have 'Select Case' (vs switch) and can test expressions, whose resulting value can be compared in following Case statements.

dim a,b
a=1
b=2
Select Case(a+b)
Case 1
response.write('1')
Case 2
response.write('2')
Case 3
response.write('3')
End Select

-a6m1n0

Curiosity only kills cats.
 
a6m1n0 said:
switch( $var1 + $var2 ) <- using expressions will fail
Actually, you can put use an expression as the switch "variable." That's no problem at all in PHP. In fact, you can even do it in C. The expression just gets evaluated exactly as in teh VBScript example you posted.

The problem with caffrinho's code is that it is trying to include the switch variable in the case value. It is treating the case expression as though it is evaluated in isolation rather than being compared to the switch expression for equality.
 
Thanks for the detailed responses, have a star!

just one thing...

$myVar = $var1+$var2;
switch( $myVar ) <- will work

Does this mean i should be able to do something along the lines of...?
Code:
 $i=$hcap-($this->si;

          switch($i){
            case > 17:
                 return 2;
                 break;
            case >= 0:
                 return 1;
                 break;
            case < 0:
                 return 0;
                 break;
          }

You can probably guess that i've tried and failed to do this, it's what started the whole issue in the first place. Why can i not use case > 17?

The reason i used "case ($hcap-$this->si > 17)" was because I found it somewhere on the net as a solution to my initial problem of case > 17, hence my confusion!

 
Your version didn't work because the switch statement isn't supposed to work that way. It is intended for comparing a variable to discrete values, not testing ranges.

I guess this is the reason...

 
Let me try to clarify just a bit more. I think your mental model of how the switch statement works is a little off.

A switch statement compares the switch expression to each case expression until it finds a case where the values are equal. So it can only test for equality. It's just a short-hand way of doing a lot of $a == $b comparisons.

Take your original example. Your switch expression was $hcap-$this->si and the expression for your first case was ($hcap - $this->si >= 18). When PHP checks that case, it does the comparison:
$hcap-$this->si == ($hcap - $this->si >= 18)
When $hcap-$this->si is 0, this becomes:
0 == (0 >= 18)
Since 0 is less than 18, this simplifies to:
0 == false
And in PHP, zero is equivalent to false, so this evaluates to true! That's why the first case was getting executed - when you evaluate both the switch expression and the case expression, they actually are equal.

From this, it should be clear why you can't use > 17 as a case value. It's because > 17 is not an expression. When PHP tries to do the comparison $i == > 17 it can't do it because > 17 is only half an expression. By itself it is not a value, so it's meaningless to try to compare it to $i.
 
Thanks for the explanation Adahacker.

It's all well and good finding out the "right way" to do things, but i like to understand why. Otherwise I'd never learn it and fall into the same problem six months down the line.

It makes sense now, the reason for it not working i mean. I don't think the way switch works makes too much sense, though. I mean, why didn't they write it to work as such in the first place. I'm fairly certain that i've used such statements in vb in the past. Just seems a little short sighted to stick to equality only. (Of course, my little understanding of programming probably means i'm missing the reason why they didn't ;o) )



 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top