为什么一个变量对多个值的质量检查总是返回true?

2024-06-08 22:42:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我的程序中有一个变量v,它可以从值集中获取任何

"a", "b", "c", ..., "z"

我的目标是只在v不是"x""y""z"时执行一些语句

我试过了

  • 对于类C语言(其中等式运算符比较实际字符串值;例如

    if (v != "x" || v != "y" || v != "z")
    {
        // the statements I want to be executed
        // if v is neither "x", nor "y", nor "z"
    }
    
  • 对于类Pascal语言(例如

    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条件中的语句始终执行。我做错什么了吗


Tags: ortheto程序目标ifis语句
3条回答

我想我应该为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等现代shell也有[[,这有点不那么麻烦

#### 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'),以及引用的明显的可选性。不引用值通常不是语法错误,但如果不引用需要引用的值,则会导致严重的语义错误。(More on this elsewhere.

这里明显的修复方法是使用&&而不是||,但是您还应该注意[[通常支持正则表达式,因此您可以说

if [[ ! $v =~ ^(x|y|z)$ ]]; then
    : yeah
fi

别忘了值得信赖的古老的case语句,这是很自然的,并且可以追溯到20世纪70年代末:

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,包括仍然流行的tcsh,使用了一种被认为是“类似C”的语法但这就像无法区分爱丽丝·库珀和去仙境的女孩一样;而鱼壳有它自己的特点,我甚至无法对此发表评论。)

对于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

还有更多的方法,我只是太懒了

发挥你的想象力,只写一个你更喜欢的

使用&&/AND/and,而不是||/OR/or

v != "x" && v != "y" && v != "z"

问题

如果始终执行if块,则If块的条件始终计算为true。逻辑表达式一定是错的

让我们考虑{{CD10}}的每个值^ {CD9>}。

  • v = "x"

    v != "x"变成"x" != "x",这是
    v != "y"变成"x" != "y",这是真的
    v != "z"变成"x" != "z",这是真的

    表达式的计算结果为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,这是真的

  • 对于v的任何其他值,表达式的计算结果为true || 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

解决方案

您要做的是,找到一个逻辑表达式,当

(v is not "x")and(v is not "y")and(v is not "z")

正确的结构是,

  • 对于类C语言(例如-(可能需要严格的相等运算符!==),

      if (v != "x" && v != "y" && v != "z")
      {
          // the statements I want to be executed
          // if v is neither "x", nor "y", nor "z"
      }
    
  • 对于类Pascal语言

      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;
    

德摩根定律

通过De Morgan's law,表达式也可以重写为(使用类似C的语法)

!(v == "x" || v == "y" || v == "z")

意义

{}{}{}{}{}{}

这使得逻辑更加明显

特定语言

有些语言有特定的结构来测试集合中的成员资格,或者您可以使用数组/列表操作

相关问题 更多 >