布尔值
bool
类型
如果你回忆变量课程,其中列出的基本类型之一是 bool
。这个类型表示一个布尔值,它是一个单独的真/假值。
我们在条件课程早期学到的布尔表达式在求值时会创建一个布尔值。因此,我们可以创建这些布尔表达式的结果变量,然后在 if 语句的条件中进一步使用这些 bool
变量。
C++ 提供了两个内置的 bool
常量——true
和 false
。你可以在任何需要 bool
或布尔表达式的地方使用它们。例如
bool var1 = true;
bool var2 = false;
我们还可以用 bool
变量做更多有趣的事情。任何布尔表达式都可以在这里有效赋值。将这与 if 语句结合起来,在某些情况下可以使代码更短、更具可读性。
std::string name;
std::cout << "Enter your first name: ";
std::cin >> name;
// User is lucky if their name has more than 5 characters
bool is_lucky = name.size() > 5;
// Try changing these values yourself and see what happens!
bool is_tuesday = true;
bool is_cloudy = false;
std::string weather = "sunny";
if (not is_tuesday and is_cloudy) {
weather = "raining";
} else if (is_tuesday) {
if (is_cloudy) {
weather = "overcast";
} else if (not is_lucky) {
weather = "downpouring";
}
}
std::cout << "It is currently " << weather << " in your location!";
前面介绍的逻辑运算符也可以用来创建新的布尔变量。
bool is_precipitating = weather == "raining" or weather == "downpouring";
bool is_rainbow_made = is_precipitating and not is_cloudy;
bool is_boring_day = not is_rainbow_made;
bool
的输入/输出
如果你对这种新的 bool
类型进行了一些自主探索,你可能会注意到一个奇怪的现象……打印 bool
不会在终端显示 true
或 false
。相反,它会打印 1
或 0
。这只是 C++ 中的一个默认行为,与下一节相关。
你可以通过更改 std::cout
的一个设置来轻松更改此行为。只需“打印”出 std::boolalpha
内置常量,它将使 std::cout
上的所有未来布尔操作都打印 true
/false
而不是 1
/0
。
确保你 #include <iomanip>
来使用 std::boolalpha
。
std::cout << true << " " << false << "\n";
std::cout << std::boolalpha;
std::cout << true << " " << false << "\n";
1 0
true false
反之,std::cin
默认只接受 0
或 1
作为 bool
变量的输入。这个行为也可以通过“输入”到 std::boolalpha
标志来改变。在下面的例子中,用户将首先输入 0
,它代表 false
。然后,一旦应用了 std::boolalpha
设置,他们将输入 true
。
bool var;
std::cout << "Integral form: ";
std::cin >> var;
std::cin >> std::boolalpha;
std::cout << "Alphanumeric form: ";
std::cin >> var;
Integral form: 1
Alphanumeric form: true
作为练习,尝试修改上面的天气示例以接受用户输入,使用你刚刚学到的 std::boolalpha
修饰符。
“boolalpha”这个名字来源于布尔(boolean)和字母数字(alphanumeric)的合成词。
int
↔bool
转换
C++ 还有另一个相当恼人的行为,即布尔值和整数之间可以隐式转换。布尔值 false
等价于整数值 0
,而 true
等价于 1
。反之,整数值 0
等价于布尔值 false
,而任何非零整数都等价于 true
。
int x = true; // x is 1
int y = false; // y is 0
bool a = 1; // a is true
bool b = 25; // b is true
bool c = -194; // c is true
bool d = 0; // d is false
虽然这种行为看起来很整洁,但它可能会在许多不希望出现的地方意外出现。因此,如果你想有意触发 int
↔bool
转换,那么你应该强制转换该值。
int x = static_cast<int>(true); // Modern-style cast
int y = (int) false; // C-style cast
bool a = static_cast<bool>(1);
bool b = (bool) 0;
在 C++ 中,有两种主要的方法可以执行这种强制转换——“静态强制转换”和“C 风格强制转换”。你将在中级课程中学习它们之间的区别。目前只需知道,在 int
↔bool
转换的情况下,这两种选项是等效的。然而,static_cast
方法通常更受现代 C++ 的青睐。
意外转换
这些转换可能在你最意想不到的地方引起问题。一个例子是你在前面学过的复合布尔表达式。通常,如果你想将多个布尔表达式组合在一起,你会使用逻辑运算符,像这样
if (x > 10 && x < 25) { ... }
你可能会试图将条件重写为 10 < x < 25
。这将导致不正确的行为,因为此表达式将始终评估为 true
。这是因为暗中发生了隐式 bool
🡢int
转换。此表达式被解释为 (10 < x) < 25
。让我们看看这如何导致此条件始终评估为 true
,通过使用运算符优先级表
10 < x < 25 // Initial expression
10 < 15 < 25 // Substitute x
(10 < 15) < 25 // Operator precedence
(true) < 25 // Evaluate subexpression
1 < 25 // bool🡢int conversion
true // Evaluate subexpression
10 < x < 25 // Initial expression
10 < 7 < 25 // Substitute x
(10 < 7) < 25 // Operator precedence
(false) < 25 // Evaluate subexpression
0 < 25 // bool🡢int conversion
true // Evaluate subexpression
同样的问题也可能发生在其他类似场景中。例如,当检查一个变量是否是多种可能性之一时,正确的方法是 x == 5 || x == 10 || x == 15
。诱人的选项 x == 5 || 10 || 15
将不起作用,原因与上述类似。它将始终为真。让我们看看为什么
x == 5 || 10 || 15 // Initial expression
5 == 5 || 10 || 15 // Substitute x
((5 == 5) || 10) || 15 // Operator precedence
((true) || 10) || 15 // Evaluate subexpression
(true || true) || 15 // int🡢bool conversion
true || 15 // Evaluate subexpression
true || true // int🡢bool conversion
true // Evaluate subexpression
x == 5 || 10 || 15 // Initial expression
7 == 5 || 10 || 15 // Substitute x
((7 == 5) || 10) || 15 // Operator precedence
((false) || 10) || 15 // Evaluate subexpression
(false || true) || 15 // int🡢bool conversion
true || 15 // Evaluate subexpression
true || true // int🡢bool conversion
true // Evaluate subexpression
结论
总而言之,我们学到了
这是一段漫长的旅程,但你在这堂课中学到的技能对未来的道路至关重要。请多次阅读本课中提出的概念,因为逻辑和条件的基础是非常重要的技能。