100 <= x <= 150 в качестве аргумента в if (), действуя смешно - PullRequest
3 голосов
/ 26 января 2012

У меня есть оператор if, за которым следуют несколько операторов else if.Все операторы if / else if имеют аргумент, структурированный примерно так:

if (100 <= x <= 149) //do this
else if (150 <= x <= 199) //do that
else if ...etc...

Однако по какой-то причине выполняется только первый оператор if.X может быть 200, и только первый оператор if будет распознан.

Я не уверен, почему он не переходит к следующему оператору if, если X не соответствует аргументу предыдущего оператора,Разве это не работает в Obj-C?Любая помощь приветствуется.Спасибо

Ответы [ 8 ]

18 голосов
/ 26 января 2012

Вам нужно перефразировать операторы вроде:

if (x >= 100 && x <= 149) {
} else if (x >= 150 && x <= 199) {
} ...

Ваш первый if оценивается как:

if ((100 <= x) <= 149)

Давайте посмотрим, как это оценивает:

  • Если x = 200, то (100 <= 200) имеет значение true и, таким образом, оценивается в значение 1 (что означает true).И тогда 1 <= 149 также верно.
  • Если x имеет значение меньше 100, например 10, то (100 <= 10) равно false и, таким образом, оценивается в значение 0 (что означаетложный).Опять же, 0 <= 149 - это истина.

Таким образом, независимо от значения x, все выражение всегда будет истинным.

12 голосов
/ 26 января 2012

C не математика, поэтому

if (100 <= x <= 149)

НЕ совпадает с

if (100 <= x &&  x <= 149)

Что ты имел в виду. Первое будет всегда верно, потому что 100 <= x <= 149 становится

((100 <= x) <= 149)

оставляя две возможности: (1 <= 149) или (0 <= 149). Оба всегда верны.

4 голосов
/ 26 января 2012

Подобные цепные сравнения не работают в языках на основе Си.Вернее, они делают, но не так, как вы ожидаете.

100 <= x <= 149 оценивается как (100 <= x) <= 149.Если x больше 100, то (100 <= x) будет иметь значение true или 1.Если x меньше 100, это ложь или 0.В любом случае, 0 <= 149 или 1 <= 149 имеет значение true, поэтому общее выражение имеет значение true.

Чтобы исправить это, измените свои условия так:

if (100 <= x && x <= 149) 

Это будетсделайте так, как вы ожидаете.

3 голосов
/ 26 января 2012

Компилятор видит выражение, сформулированное из бинарных операторов. Символ <= является бинарным оператором, как и =,> =, ||, && и т. Д.

Как и в случае с арифметикой, существует порядок приоритетов, которому должен следовать компилятор, оценивая выражение, сформированное вокруг каждого бинарного оператора.

В арифметике вы, вероятно, знакомы с этим, как и с этими двумя примерами:

2 + 5 * 7 Это оценивается как 2+ (5 * 7) или 37, потому что умножение имеет приоритет перед сложением.

2 + 3 + 21 оценивается в том порядке, в котором термины читаются слева направо, поскольку другого правила приоритета не существует. Становится (2 + 3) + 21.

Таким образом, 100 <= x <= 150 является выражением аналогичного типа, в котором все двоичные операторы одинаковы и, следовательно, имеют одинаковый приоритет. Еще раз, это решено, оценивая это слева направо, таким образом это становится (100 <= x) <= 150. Если x> = 100, термин в скобках оценивается как TRUE, которое имеет числовое значение 1. Поскольку 1 меньше 150, остальные оцениваются как 1 <= 150, или TRUE, если x больше или равно 100. С другой стороны, он также оценивается как ИСТИНА, если х меньше 100, потому что второе сравнение становится 0 <= 150, что ИСТИНА. </p>

Другие рекомендации разбить это в скобках верны, если вы не уверены в порядке приоритета для двоичных операторов: (100 <= x) && (x <= 150). Вы также можете записать его как 100 <= x && x <= 150, так как порядок приоритета для сравнения значений выше, чем для логических операторов. </p>

2 голосов
/ 26 января 2012

У вас уже есть много ответов, но я добавлю еще один, чтобы охватить еще одну возможную путаницу.

В C & Obj-C обрабатываются булевы (и символьные) типыкак integer типов, что не имеет место в языках вызовов.Поэтому выражения типа 'z' * true имеют смысл!

(Modern) C использует тип _Bool для логического значения, которое определено как достаточно большое, чтобы содержать 0 & 1.Какао использует тип BOOL для логического значения, которое определяется как signed char.CoreFoundation использует тип Boolean, который определяется как unsigned char.Все три определяют YES / true как 1 и NO / false как 0, а сам C обрабатывает любое ненулевое значение как true.

Операторы отношениятакие как <, <= и т. д. определены как возвращающие значение int (да, ни одно из логических значений, даже не _Bool) 0, если отношение ложное, и значение int 1 если отношение истинно.

Учитывая это и ассоциативность слева направо реляционных операторов, ваш:

if (100 <= x <= 149)

анализируется как:

if ((100 <= x) <= 149)

затем 100 <= x оценивается в int значение 1, если x больше или равно 100, в противном случае оно оценивается в int значение 0, поэтому мы получаем:

if (1 <= 149)

или

if (0 <= 149)

оба эти значения оцениваются в 1, поэтому мы получаем:

if (1)

и оператор if переходит в ветвь "then", если это выражениене равен нулю.

Это может быть удивительно, но все утверждение оценивается без какого-либо использования логических значений - все это делается с целыми числами.

Для достиженияТо, что вы хотели, вам нужно:

if((100 <= x) && (x <= 149))

и т. д.- который также не использует логические значения (&& определяется в виде целых чисел).

2 голосов
/ 26 января 2012

Я не думаю, что вы можете написать математические функции, подобные этой, в target-c ... Попробуйте разделить их и объединить с помощью оператора &&:

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...
2 голосов
/ 26 января 2012

Может помочь добавление дополнительных скобок.

if ((100 <= x) && (x <= 149)) //do this
2 голосов
/ 26 января 2012

Потому что if (100 <= x <= 149) - это то же самое, что и if(1<=149), если вы даете 200 или другое число x И это всегда правильно.

Например.

x=1

100<=1 ложно, поэтому вы получите if(0<=149), что верно

x=200

100<=200 верно, поэтому вы получите if(1<=149), что верно

Так что вы всегда за это верны.

Так что вы должны сделать это по-другому, как это

if(x>=100 && x<=149) ...
...