问题
I have an if
statement followed by several else if
statements. All of the if/else if statements have an argument structured something like this:
if (100 <= x <= 149) //do this
else if (150 <= x <= 199) //do that
else if ...etc...
However, for some reason only the first if statement ever gets executed. X can be 200 and only the first if statement will be recognized.
I'm not sure why it isn't moving on to the next else if statement when X doesn't fit the argument of the preceding statement. Does this not work in Obj-C? Any help is appreciated. Thanks
回答1:
You need to rephrase the statements like:
if (x >= 100 && x <= 149) {
} else if (x >= 150 && x <= 199) {
} ...
Your first if
is evaluated like:
if ((100 <= x) <= 149)
Let's have a look how that evaluates:
- If
x = 200
, then(100 <= 200)
is true and thus evaluates to the value1
(which means true). And then1 <= 149
is also true. - If
x
has a value smaller than 100, for example10
, then(100 <= 10)
is false and thus evaluates to the value0
(which means false). Again,0 <= 149
is true.
So regardless of the value of x
, the whole expression will always be true.
回答2:
C is not math, so
if (100 <= x <= 149)
is NOT the same as
if (100 <= x && x <= 149)
Which is what you meant. The former will be true always, because 100 <= x <= 149
becomes
((100 <= x) <= 149)
leaving two possibilities: (1 <= 149)
or (0 <= 149)
. Both are always true.
回答3:
Chained comparisons like these don't work in C-based languages. Or rather, they do, but not how you'd expect.
100 <= x <= 149
gets evaluated as (100 <= x) <= 149
. If x
is over 100, then (100 <= x)
will evaluate to true, or 1
. If x
is under 100, it's false, or 0
. In either case, 0 <= 149
or 1 <= 149
is true, so the overall expression is true.
To fix this, change your conditions to look like this:
if (100 <= x && x <= 149)
That will make it work as you expect.
回答4:
The compiler sees an expression formulated from binary operators. The <= symbol is a binary operator, as are =, >=, ||, &&, and so forth.
Just as with arithmetic, there is an order of precedence that the compiler must follow, evaluating the expression formed around each binary operator.
In arithmetic, you are probably familiar with this, as with these two examples:
2+5*7 This evaluates to 2+(5*7) or 37, because multiplication has precedence over addition.
2+3+21 is evaluated in the order the terms are read from left to right, since there is no other precedence rule. It becomes (2+3)+21.
So 100<=x<=150 is an expression of a similar type, where the binary operators are all the same, and thus have the same precedence. Once again, this is resolved by evaluating it from left to right, so it becomes (100<=x)<=150. If x>=100 the term in parentheses evaluates to TRUE, which has a numeric value of 1. Since 1 is less than 150, the rest evaluates to 1<=150, or TRUE, if x is greater than or equal to 100. On the other hand, it also evaluates to TRUE if x is less than 100, because the second comparison becomes 0<=150, which is TRUE.
The other recommendations to break this down with parentheses are correct if you aren't sure of the order of precedence for binary operators: (100<=x) && (x<=150). You can also write it as 100<=x && x<=150 since the order of precedence for value comparisons is higher than for logical operators.
回答5:
Because if (100 <= x <= 149)
is the same as if(1<=149)
if you give 200 or another number to x. And that is correct always.
For example.
x=1
100<=1
is false so you get if(0<=149)
which is true
x=200
100<=200
is true so you get if(1<=149)
which is true
So you always get true for it.
So you must do it in another way, like this
if(x>=100 && x<=149) ...
回答6:
Adding some additional parenthesis may help.
if ((100 <= x) && (x <= 149)) //do this
回答7:
I don't think you can write math functions like this in objective-c... Try separating them and combining with an && statement:
if ( (100 <= x) && (x <= 149) ) { // "&&" = and, "||" = or, other math comparison operators are: <=, >=, <, >, ==, != (!= is does not equal))
//do this
} else if ( (150 <= x) && (x <= 199) ) {
//do that
} else if ...etc...
回答8:
You've already got a lot of answers, but I'll add one more to cover one other possible point of confusion.
In C & Obj-C the boolean (and character) types are treated as integer types, which is not the case in call languages. So expressions like 'z' * true
make perfect sense!
(Modern) C uses the type _Bool
for boolean, which is defined to be large enough to hold 0
& 1
. Cocoa uses the type BOOL
for boolean, which is defined as signed char
. CoreFoundation uses the type Boolean
which is defined as unsigned char
. All three define YES
/true
as 1
and NO
/false
as 0
, while C itself treats any non-zero value as true
.
The relation operators such as <
, <=
etc. are defined to return the int
(yes, none of the booleans, not even _Bool
) value 0
if the relation is false, and the int
value 1
if the relation is true.
Given this and the left-to-right associativity of relational operators your:
if (100 <= x <= 149)
is parsed as:
if ((100 <= x) <= 149)
then 100 <= x
evaluates to the int
value 1
if x
is greater than or equal to 100, otherwise it evaluates to the int
value 0
, so we get:
if (1 <= 149)
or
if (0 <= 149)
both of these evaluate to 1
so we get:
if (1)
and the if
statement branches to the "then" branch if it's expression is non-zero.
It may be surprising, but the whole statement is evaluated without any use of booleans at all - it is all done with integers.
To achieve what you intended you need:
if((100 <= x) && (x <= 149))
etc. - which also doesn't use any booleans (&&
is defined in terms of integers).
来源:https://stackoverflow.com/questions/9014701/100-x-150-as-argument-in-if-acting-funny