• 文章
  • 条件语句 - 真假故事
作者:
2008 年 8 月 11 日 (最后更新:2008 年 8 月 14 日)

条件语句 - 真假故事

评分:3.2/5 (24 票)
*****
我又一次看到了一段类似于下面这个非常常见的错误的代码

1
2
3
4
5
6
if (chr == 'Y' || 'y') // this will always return true
  do_something; // and this will always be called
else if (chr == 'N' || 'n') // this makes same mistake as above
  do_something_else; // but, this will never be called because of above
else
  do_some_other_thing; // This will never be called 


在深入探讨第一个 if 语句为何总是返回 true 之前,让我们先来看看条件语句的一些工作细节。

什么是条件语句? 条件语句是评估为 true(真)或 false(假)的语句。您所有的控制结构都依赖于条件语句。这包括...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if ( conditional )
else if ( conditional )

while ( conditional )

do { ... }
  while ( conditional )

// even
for ( initialization; conditional; incremental)
// for loops can have an empty conditional which evaluates to true. But this only works for For loops.

// and there is the conditional operator
int a = conditional ? ... : ...;


由于条件语句评估为 truefalse,因此上面的内容也可以这样编写...

1
2
3
4
5
6
7
8
9
10
11
if (true)
else if (true)

while (true)

do { ... }
  while (true)

for ( ...; true; ...)

int a = true ? ... : ...;


当然,if (true) 会失去 if 语句的意义,但 while (true) 却非常常用。

那么我们如何定义真或假呢? 很多人会告诉你 false,而 true 是任何大于 的数。这并不完全准确。更精确地说,false,而 true 是任何 非零 值。这包括负数。(我已经通过 DevC++ 测试确认了这一点

False 也可以是 null,这与 zero 有明显区别。有许多函数返回 null,因此这也可以用作条件语句。

那么什么可以算作条件语句? 任何评估为 truefalse 的东西。您所有的比较,例如 大于 '>',小于等于 '<=',以及 等于 '==',都会评估为 truefalse

1
2
3
4
5
6
7
8
9
10
11
12
int i = 5; // integer i is equal to five.

if (i == 5) // this evaluates to
if (true)

else if (i < 5) // this evaluates to
else if (false)

while (i >= 5) // this evaluates to
while (true)

// and so forth 


您所有的赋值也都会评估为 truefalse。这是因为赋值也返回一个值。a = 5; 将数字 5 存储到变量 a 中。但它也返回 5 这个值。这就是为什么 b = a = 5; 可以工作的原因。它首先将 5 存储到 a 中,然后返回 5,这个 5 又被存储到 b 中。

b = 5; 也返回 5,但由于我们没有将其存储到任何其他地方,所以它消失在时间和空间中,再也看不见了。这没关系,因为总有一天有人会发明一个以这些四处漂浮的丢失值来获取能量的超空间引擎。

1
2
3
4
5
6
7
8
// notice one '=' sign makes it an assignment, not a comparison
if (a = 5) // this evaluates into
if (5) // which since 5 is a non-zero, it evaluates into
if (true)

if (a = 0) // this evaluates to
if (0) // which as we know from above evaluates to
if (false)


最后,您还可以调用许多返回值的函数。任何不返回 void(或者根据 void 的定义,不返回任何东西)的函数都可以用作或包含在条件语句中。

逻辑运算符 有两个逻辑运算符可用于连接条件语句。它们是 And '&&' 和 Or '||' 运算符。它们都接受两个条件语句,一个在左边,一个在右边,并分别评估每个条件语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if ( condition_1 || condition_2 ) // or
if ( condition_1 && condition_2 ) // and

int i = 5, j = 1;

if ( i == 3 || j == 1 ) // evaluates to
if ( false || true ) // evaluates to
if ( true )

if ( i == 5 && j == 3 ) // evaluates to
if ( true && false ) // evaluates to
if ( false )

// You can even use multiple concatenations.
int h = 3;

if ( i == 2 || ( j == 1 && h == 3 ) ) // evaluates to
if ( false || ( true && true ) ) // evaluates to
if ( false || true ) // evaluates to
if ( true )


这就回到了开头的那段代码,以及它为何总是返回 true。那段代码是这样的...

1
2
3
4
if (chr == 'Y' || 'y') // which if chr = anything other than 'Y' would evaluate to
if ( false || 'y' ) // and since 'y' is a non-zero this would evaluate to
if ( false || true ) // which will evaluate to
if ( true )


特别说明 您也可以将赋值和函数调用与逻辑运算符一起使用。但是,在这里应该格外小心,因为这样做可能会产生意想不到的结果。这是由于程序处理这些逻辑运算符的方式。

例如,Or 如果任一条件语句为 true,则返回 true。它会检查第一个条件语句,如果返回 false,它会检查第二个条件语句。但是,如果第一个条件语句返回 true,它就不需要检查第二个条件语句了。它已经有足够的信息来返回 true。让我们来看下面的代码示例...

1
2
3
4
5
6
7
8
9
10
11
12
   int i = 0, j = 0;
   while (true)
   {
      if (++i >= 5 || ++j >= 5) // OR
         cout << i << " " << j << " true" << endl;

      else
         cout << i << " " << j << " false" << endl;

      if (i >= 10)
         break;
   }


看到这段代码,人们可能会认为 i 和 j 都会达到 10。然而,一旦 i 达到 5,它就返回 true,因此第二个条件语句不再需要进行测试。结果如下所示。

1 1 false
2 2 false
3 3 false
4 4 false
5 4 true
6 4 true
7 4 true
8 4 true
9 4 true
10 4 true

然而,And 需要两个条件语句都为 true。所以它会检查第一个条件语句,如果它返回 true,它会检查第二个条件语句。但是,如果第一个条件语句返回 false,就没有理由检查第二个条件语句了。它已经有足够的信息来返回 false。因此,下面的代码...

1
2
3
4
5
6
7
8
9
10
11
12
   int i = 0, j = 0;
   while (true)
   {
      if (++i >= 5 && ++j >= 5) // AND
         cout << i << " " << j << " true" << endl;

      else
         cout << i << " " << j << " false" << endl;

      if (i >= 10)
         break;
   }


...会产生以下输出...

1 0 false
2 0 false
3 0 false
4 0 false
5 1 false
6 2 false
7 3 false
8 4 false
9 5 true
10 6 true

Not 运算符 当然,还有一个逻辑运算符需要考虑。就是 Not '!' 运算符,当放在条件语句前面时,它会简单地反转它。它将 true 变成 false,将 false 变成 true

1
2
3
4
5
6
7
if (!true) // evaluates to
if (false)

// and

if (!false) // evaluates to
if (true)


题外话:XOR 我最初将 Xor 列为逻辑运算符,但它不是。它是一个按位运算符。但是,在逻辑意义上模拟 Xor 功能是可能的。Xor 简单来说就是‘Or And Not And’。但是,使用部分或全部赋值来实现这一点,其结果将更难预测。

1
2
3
4
5
6
7
8
9
10
11
12
   int i = 0, j = 0;
   while (true)
   {
      if ((++i >= 5 || ++j >= 5) && !(++i >= 5 && ++j >= 5))
         cout << i << " " << j << " true" << endl;

      else
         cout << i << " " << j << " false" << endl;

      if (i >= 10)
         break;
   }


...会产生如下输出...

1 1 false
2 2 false
3 3 false
4 4 false
6 5 false
8 6 false
10 7 false