Почему проверка равноценности одной переменной по многим значениям всегда возвращает true?
У меня есть переменная v
в моей программе, и она может принимать любое значение из набора значений
"a", "b", "c", ..., "z"
И моя цель – выполнить какое-то утверждение только тогда, когда v
не является "x"
, "y"
или "z"
.
Я пытался,
- Простой способ понять инкапсуляцию и абстракцию
- Какое лучшее регулярное выражение проверяет правильность строки?
- Как завершить работу программы при ее сбое? (который должен просто сбить единичный тест, а не застревать навсегда)
- Получение частей URL (регулярное выражение)
- Почему JVM по-прежнему не поддерживает оптимизацию хвостового вызова?
-
для C-подобных языков (где операторы равенства сравнивают фактические значения строк, например c # , javascript , php )
if (v != "x" || v != "y" || v != "z") { // the statements I want to be executed // if v is neither "x", nor "y", nor "z" }
-
для Pascal-подобных языков (например, plsql )
IF (v != 'x' OR v != 'y' OR v != 'z') THEN -- the statements I want to be executed -- if v is neither "x", nor "y", nor "z" END IF;
Операторы внутри условия if всегда выполняются . Я что-то делаю неправильно?
- Сумма-подмножество с фиксированным размером подмножества
- Двоичный поиск в массиве
- Случайная строка, которая соответствует регулярному выражению
- Моностат против Синглтона
- Являются ли глобальные статические classы и методы плохими?
- Преобразование RGB в оттенки серого / интенсивность
- Что делает хороший модульный тест?
- Что такое ошибка переполнения целого числа?
Используйте &&
/ AND
/ and
, а не ||
/ OR
/ or
:
v != "x" && v != "y" && v != "z"
Если блок if
всегда выполняется, условие для блока if всегда равно true
. Логическое выражение должно быть неправильным.
Рассмотрим v != "x" || v != "y" || v != "z"
v != "x" || v != "y" || v != "z"
v != "x" || v != "y" || v != "z"
для каждого значения v
.
-
Когда
v = "x"
,v != "x"
становится"x" != "x"
, что дает false .
v != "y"
становится"x" != "y"
, что дает true .
v != "z"
становится"x" != "y"
, что дает true .Выражение принимает значение
false || true || true
false || true || true
false || true || true
, что верно . -
Когда
v = "y"
, выражение становится"y" != "x" || "y" != "y" || "y" != "z"
или
true || false || true
true || false || true
true || false || true
, что верно . -
Когда
v = "z"
, выражение становится"z" != "x" || "z" != "y" || "z" != "z"
или
true || true || false
true || true || false
true || true || false
, что верно . -
Для любого другого значения для
v
выражение вычисляется какtrue || true || true
true || true || true
true || true || true
, что верно .
В качестве альтернативы рассмотрим таблицу истинности:
│ ABC │ v │ v != "x" v != "y" v != "z" │ A || B || C ───────┼──────────────────────────────────┼────────────── "x" │ false true true │ true "y" │ true false true │ true "z" │ true true false │ true other │ true true true │ true
Как вы можете видеть, ваше логическое выражение всегда имеет значение true
.
То, что вы хотите сделать, – найти логическое выражение, которое оценивается как true
когда
(v is not "x")
and
(v is not "y")
and
(v is not "z")
.
Правильная конструкция,
-
для C-подобных языков (например, c # , javascript – (может потребоваться строгий оператор равенства
!==
), php )if (v != "x" && v != "y" && v != "z") { // the statements I want to be executed // if v is neither "x", nor "y", nor "z" }
-
для Pascal-подобных языков plsql
IF (v != 'x' AND v != 'y' AND v != 'z') THEN -- the statements I want to be executed -- if v is neither "x", nor "y", nor "z" END IF;
По закону Моргана выражение также можно переписать как (используя синтаксис Си)
!(v == "x" || v == "y" || v == "z")
имея в виду
not
((v is "x")
or
(v is "y")
or
(v is "z"))
.
Это делает логику более очевидной.
Некоторые языки имеют конкретные конструкции для тестирования членства в наборах или вы можете использовать операции массива / списка.
-
sql :
v NOT IN ('x', 'y', 'z')
-
javascript :
["x", "y", "z"].indexOf(v) == -1
-
python :
v not in {"x", "y", "z"}
Я полагал, что внес бы ответ на сценарий оболочки Bourne, поскольку синтаксис несколько свойственен.
В традиционном / POSIX sh
тест равенства строк является признаком [
команды (да, это отдельное имя команды!), Которое имеет некоторые отвратительные требования при цитировании и т. Д.
#### WRONG if [ "$v" != 'x' ] || [ "$v" != 'y'] || [ "$v" != 'z' ]; then : some code which should happen when $v is not 'x' or 'y' or 'z' fi
Современные раковины, такие как Ksh, Bash, Zsh и т. Д., Также имеют [[
который несколько менее надоедливый.
#### STILL WRONG if [[ $v != 'x' || $v != 'y' || $v != 'z' ]]; then : some code which should happen when $v is not 'x' or 'y' or 'z' fi
Мы должны подчеркнуть требование наличия пробелов вокруг каждого токена, который пропускается многими новичками (т. Е. Вы не можете сказать, if[[$v
или $v!='y'
без пробелов вокруг команд и операторов), и кажущееся опциональность цитирования. Неспособность указать значение часто не является синтаксической ошибкой, но это приведет к серьезным нежелательным семантическим проблемам, если вы не укажете значение, которое должно быть указано. ( Больше об этом в другом месте. )
Очевидное решение здесь – использовать &&
вместо ||
но вы также должны заметить, что [[
обычно спортивная поддержка регулярных выражений, поэтому вы можете сказать что-то вроде
if [[ ! $v =~ ^(x|y|z)$ ]]; then : yeah fi
и не забудьте верное старое case
которое вполне естественно для этого, и переносится обратно в конце 1970-х годов:
case $v in x | y | z) ;; # don't actually do anything in this switch *) # anything else, we fall through to this switch yeah some more yeah in fact, lots of yeah;; esac
Конечные двойные точки с запятой сначала вызывают аневризмы, но вы быстро восстанавливаетесь и учитесь ценить, даже любите их. POSIX позволяет помещать открывающую скобку перед выражением соответствия, поэтому у вас нет непарных правых круглых скобок, но это использование довольно необычно.
(Это, очевидно, не подходит для оболочек Unix, которые не относятся к семейству Bourne. Семейство C-оболочек, включая еще несколько популярный tcsh
использует синтаксис, предположительно «C-like», но это похоже на невозможность рассказать обо всем Элис Купер от девушки, которая отправилась в Страну Чудес, а у рыбской раковины есть свои особенности, о которых я даже не могу комментировать.)
Вы можете использовать что-то вроде этого, для PHP:
if(strpos('xyz',$v[0])===false)//example 1 //strpos returns false when the letter isn't in the string //returns the position (0 based) of the substring //we must use a strict comparison to see if it isn't in the substring if(!in_array($v[0],array('x','y','z')))//example 2 //example 3 $out=array('x'=>1,'y'=>1,'z'=>1); //create an array if(!$out[$v[0]]) //check if it's not 1 if(!preg_match('/^[xyz]$/',$v))//example 4, using regex if(str_replace(array('x','y','z'),'',$v[0]))//example 5 if(trim($v[0],'xyz'))//example 6
Для Javascript:
if(~'xyz'.search(v[0]))//example 1(.indexOf() works too) if(!(v[0] in {x:0,y:0,z:0}))//example 2 if(~['x','y','z'].indexOf(v[0]))//example 3, incompatible with older browsers. if(!/^[xyz]$/.match(v))//example 4 if(v.replace(/^[xyz]$/))//example 5
Для MySQL:
Select not locate(@v,'xyz'); -- example 1 select @v not in ('x','y','z'); -- example 2 -- repetition of the same pattern for the others
Для C:
if(!strstr('xyz',v))//example 1, untested
Есть больше способов, я просто слишком ленив.
Используйте свое воображение и просто напишите то, что вам нравится больше!