提问人:sampathsris 提问时间:10/13/2014 最后编辑:Karl Knechtelsampathsris 更新时间:8/30/2023 访问量:3250
为什么对一个变量进行多个值的不相等检查总是返回 true?
Why does non-equality check of one variable against many values always return true?
问:
我的程序中有一个变量,它可以从值集中获取任何值v
"a", "b", "c", ..., "z"
我的目标是仅在 不是 、 或 时执行某些语句。v
"x"
"y"
"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' 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
答:
使用 //,而不是 //:&&
AND
and
||
OR
or
v != "x" && v != "y" && v != "z"
问题
如果始终执行块,则 if 块的条件的计算结果始终为 true
。逻辑表达式一定是错误的。if
让我们考虑 的每个值。v != "x" || v != "y" || v != "z"
v
什么时候
v = "x"
v != "x"
成为 ,这是错误的。
成为 ,这是真的。
成为 ,这是真的。"x" != "x"
v != "y"
"x" != "y"
v != "z"
"x" != "z"
表达式的计算结果为 ,即为 true。
false || true || true
当 时,表达式变为
v = "y"
"y" != "x" || "y" != "y" || "y" != "z"
或 ,这是真的。
true || false || true
当 时,表达式变为
v = "z"
"z" != "x" || "z" != "y" || "z" != "z"
或 ,这是真的。
true || true || false
对于 的任何其他值,表达式的计算结果为 ,即 true。
v
true || true || true
或者,考虑真值表:
│ A B C │
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
溶液
你要做的是,找到一个计算结果为 when 的逻辑表达式true
(v is not "x")
和
。
(v is not "y")
(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;
德摩根定律
根据德摩根定律,表达式也可以改写为(使用类似 C 的语法)
!(v == "x" || v == "y" || v == "z")
意义
不是
或或
。((v is "x")
(v is "y")
(v is "z"))
这使得逻辑更加明显。
特定语言
某些语言具有用于测试集合中成员身份的特定构造,或者您可以使用数组/列表操作。
SQL格式:
v NOT IN ('x', 'y', 'z')
JavaScript的:
!["x", "y", "z"].includes(v)
蟒蛇:
v not in {"x", "y", "z"}
对于 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
还有更多的方法,我只是太懒了。
发挥你的想象力,写出你更喜欢的那个!
我想我会为 Bourne shell 脚本提供一个答案,因为语法有些特殊。
在传统/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'
)
这里显而易见的解决方法是 use 而不是 ,但你也应该注意,通常支持正则表达式,所以你可以说这样&&
||
[[
if [[ ! $v =~ ^(x|y|z)$ ]]; then
: yeah
fi
不要忘记这个值得信赖的旧声明,这是很自然的,并且可以移植到 1970 年代后期:case
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 允许您在匹配表达式之前放置一个左括号,这样您就不会有不成对的右括号,但这种用法相当罕见。
(对于不是来自 Bourne 家族的 Unix shell 来说,这显然不是一个合适的答案。C系列的shell--包括仍然有点流行的--使用一种据说是“类似C-like”的语法,但这就像无法区分Alice Cooper和去仙境的女孩一样;鱼壳有它自己的特点,我什至没有资格评论。tcsh
评论
if(var != “x” || var != “y” ...)
的规范、与语言无关的问题所描述的问题类型创建一个规范的问答对。.equals
方法,如 (或如果可能是)。有关详细信息,请参阅如何在 Java 中比较字符串?String
==
!=
v != "x"
!v.equals("x")
!"x".equals(v)
v
null