本节是《if 语句与语句块》的延续,我们将讨论使用 if 语句时常见的一些问题。
嵌套 if 语句与悬垂 else 问题
可以将 if 语句嵌套在另一个 if 语句内部:
#include <iostream>
int main()
{
std::cout << "Enter a number: ";
int x{};
std::cin >> x;
if (x >= 0) // 外层 if
if (x <= 20) // 内层 if
std::cout << x << " is between 0 and 20\n";
return 0;
}
然而,考虑以下程序:
#include <iostream>
int main()
{
std::cout << "Enter a number: ";
int x{};
std::cin >> x;
if (x >= 0) // 外层 if
if (x <= 20) // 内层 if
std::cout << x << " is between 0 and 20\n";
else // 这个 else 属于哪个 if?
std::cout << x << " is negative\n";
return 0;
}
上述代码引入了名为“悬垂 else”的潜在歧义:该 else 究竟与外层 if 还是内层 if 配对?
规则:else 与同一语句块中最后一个尚未匹配的 if 配对。因此,上例中的 else 与内层 if 匹配,等效于:
#include <iostream>
int main()
{
std::cout << "Enter a number: ";
int x{};
std::cin >> x;
if (x >= 0)
{
if (x <= 20)
std::cout << x << " is between 0 and 20\n";
else // 与内层 if 匹配
std::cout << x << " is negative\n";
}
return 0;
}
这将导致错误输出:
Enter a number: 21
21 is negative
为避免在嵌套 if 语句时出现歧义,应将内层 if 显式置于语句块中,从而可将 else 明确关联到外层或内层 if:
#include <iostream>
int main()
{
std::cout << "Enter a number: ";
int x{};
std::cin >> x;
if (x >= 0)
{
if (x <= 20)
std::cout << x << " is between 0 and 20\n";
else
std::cout << x << " is greater than 20\n";
}
else
std::cout << x << " is negative\n";
return 0;
}
扁平化嵌套 if 语句
嵌套 if 语句常可通过重构逻辑或使用逻辑运算符(见 6.8 节《逻辑运算符》)来扁平化。减少嵌套可降低出错概率。
例如,上述示例可扁平化为:
#include <iostream>
int main()
{
std::cout << "Enter a number: ";
int x{};
std::cin >> x;
if (x < 0)
std::cout << x << " is negative\n";
else if (x <= 20) // 仅当 x >= 0 时求值
std::cout << x << " is between 0 and 20\n";
else // 仅当 x > 20 时求值
std::cout << x << " is greater than 20\n";
return 0;
}
再举一例,使用逻辑运算符在单个 if 语句中检查多重条件:
#include <iostream>
int main()
{
std::cout << "Enter an integer: ";
int x{};
std::cin >> x;
std::cout << "Enter another integer: ";
int y{};
std::cin >> y;
if (x > 0 && y > 0) // && 为逻辑与,检查两条件是否均为真
std::cout << "Both numbers are positive\n";
else if (x > 0 || y > 0) // || 为逻辑或,检查是否至少一个条件为真
std::cout << "One of the numbers is positive\n";
else
std::cout << "Neither number is positive\n";
return 0;
}
空语句
空语句是仅由一个分号构成的表达式语句:
if (x > 10)
; // 空语句
空语句不执行任何操作,常用于语法上要求存在语句而程序员无需任何动作之处。为了提高可读性,空语句通常单独成行。本章后续介绍循环时,将展示有意使用空语句的示例。
空语句很少与 if 语句配合使用,却可能因疏忽而引入错误。例如:
if (nuclearCodesActivated()); // 行尾意外加分号
blowUpTheWorld();
由于分号的存在,代码等价于:
if (nuclearCodesActivated())
; // 空语句
blowUpTheWorld(); // 始终执行
警告
切勿在 if 语句末尾误加分号,否则原本应条件执行的语句将无条件执行,即使它们位于块内亦如此。
提示
在 Python 中,pass
关键字充当空语句,常用于占位,便于后续实现。因其为单词而非符号,误用概率低且易于搜索定位。
for x in [0, 1, 2]:
pass # 将来补全
在 C++ 中,可通过预处理器模拟 pass
:
#define PASS
void foo(int x, int y)
{
if (x > y)
PASS;
else
PASS;
}
int main()
{
foo(4, 7);
return 0;
}
为与其他 C++ 语句保持一致,PASS
需以分号结尾。预处理器将 PASS
移除,分号被解释为空语句。
条件表达式中的 ==
与 =
误用
在条件中应使用 ==
进行相等测试,而非赋值运算符 =
。例如:
#include <iostream>
int main()
{
std::cout << "Enter 0 or 1: ";
int x{};
std::cin >> x;
if (x = 0) // 误用赋值而非相等比较
std::cout << "You entered 0\n";
else
std::cout << "You entered 1\n";
return 0;
}
该程序虽可编译运行,但部分情况下结果错误:
Enter 0 or 1: 0
You entered 1
事实上,程序始终输出 “You entered 1”。原因是 x = 0
先将 0 赋给 x
,然后表达式求值为 x
的值 0,对应布尔值 false,故条件恒为假,else 分支始终执行。