跳到主要内容

布尔值

bool 类型

如果你回忆变量课程,其中列出的基本类型之一是 bool。这个类型表示一个布尔值,它是一个单独的真/假值。

我们在条件课程早期学到的布尔表达式在求值时会创建一个布尔值。因此,我们可以创建这些布尔表达式的结果变量,然后在 if 语句的条件中进一步使用这些 bool 变量。

C++ 提供了两个内置的 bool 常量——truefalse。你可以在任何需要 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 不会在终端显示 truefalse。相反,它会打印 10。这只是 C++ 中的一个默认行为,与下一节相关。

你可以通过更改 std::cout 的一个设置来轻松更改此行为。只需“打印”出 std::boolalpha 内置常量,它将使 std::cout 上的所有未来布尔操作都打印 true/false 而不是 1/0

头文件包含

确保你 #include <iomanip> 来使用 std::boolalpha

打印 true/false
std::cout << true << " " << false << "\n";
std::cout << std::boolalpha;
std::cout << true << " " << false << "\n";
输出
1 0
true false

反之,std::cin 默认只接受 01 作为 bool 变量的输入。这个行为也可以通过“输入”到 std::boolalpha 标志来改变。在下面的例子中,用户将首先输入 0,它代表 false。然后,一旦应用了 std::boolalpha 设置,他们将输入 true

输入 true/false
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)的合成词。

intbool 转换

C++ 还有另一个相当恼人的行为,即布尔值和整数之间可以隐式转换。布尔值 false 等价于整数值 0,而 true 等价于 1。反之,整数值 0 等价于布尔值 false,而任何非零整数都等价于 true

int↔bool 转换示例
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

虽然这种行为看起来很整洁,但它可能会在许多不希望出现的地方意外出现。因此,如果你想有意触发 intbool 转换,那么你应该强制转换该值。

执行强制转换
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 风格强制转换”。你将在中级课程中学习它们之间的区别。目前只需知道,在 intbool 转换的情况下,这两种选项是等效的。然而,static_cast 方法通常更受现代 C++ 的青睐。

意外转换

这些转换可能在你最意想不到的地方引起问题。一个例子是你在前面学过的复合布尔表达式。通常,如果你想将多个布尔表达式组合在一起,你会使用逻辑运算符,像这样

if (x > 10 && x < 25) { ... }

你可能会试图将条件重写为 10 < x < 25这将导致不正确的行为,因为此表达式将始终评估为 true。这是因为暗中发生了隐式 bool🡢int 转换。此表达式被解释为 (10 < x) < 25。让我们看看这如何导致此条件始终评估为 true,通过使用运算符优先级表

x = 15 时运算符链不正确
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
x = 7 时运算符链不正确
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 时运算符链不正确
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 = 7 时运算符链不正确
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

结论

总而言之,我们学到了

这是一段漫长的旅程,但你在这堂课中学到的技能对未来的道路至关重要。请多次阅读本课中提出的概念,因为逻辑和条件的基础是非常重要的技能。

布尔值

bool 类型

如果你回忆变量课程,其中列出的基本类型之一是 bool。这个类型表示一个布尔值,它是一个单独的真/假值。

我们在条件课程早期学到的布尔表达式在求值时会创建一个布尔值。因此,我们可以创建这些布尔表达式的结果变量,然后在 if 语句的条件中进一步使用这些 bool 变量。

C++ 提供了两个内置的 bool 常量——truefalse。你可以在任何需要 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 不会在终端显示 truefalse。相反,它会打印 10。这只是 C++ 中的一个默认行为,与下一节相关。

你可以通过更改 std::cout 的一个设置来轻松更改此行为。只需“打印”出 std::boolalpha 内置常量,它将使 std::cout 上的所有未来布尔操作都打印 true/false 而不是 1/0

头文件包含

确保你 #include <iomanip> 来使用 std::boolalpha

打印 true/false
std::cout << true << " " << false << "\n";
std::cout << std::boolalpha;
std::cout << true << " " << false << "\n";
输出
1 0
true false

反之,std::cin 默认只接受 01 作为 bool 变量的输入。这个行为也可以通过“输入”到 std::boolalpha 标志来改变。在下面的例子中,用户将首先输入 0,它代表 false。然后,一旦应用了 std::boolalpha 设置,他们将输入 true

输入 true/false
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)的合成词。

intbool 转换

C++ 还有另一个相当恼人的行为,即布尔值和整数之间可以隐式转换。布尔值 false 等价于整数值 0,而 true 等价于 1。反之,整数值 0 等价于布尔值 false,而任何非零整数都等价于 true

int↔bool 转换示例
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

虽然这种行为看起来很整洁,但它可能会在许多不希望出现的地方意外出现。因此,如果你想有意触发 intbool 转换,那么你应该强制转换该值。

执行强制转换
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 风格强制转换”。你将在中级课程中学习它们之间的区别。目前只需知道,在 intbool 转换的情况下,这两种选项是等效的。然而,static_cast 方法通常更受现代 C++ 的青睐。

意外转换

这些转换可能在你最意想不到的地方引起问题。一个例子是你在前面学过的复合布尔表达式。通常,如果你想将多个布尔表达式组合在一起,你会使用逻辑运算符,像这样

if (x > 10 && x < 25) { ... }

你可能会试图将条件重写为 10 < x < 25这将导致不正确的行为,因为此表达式将始终评估为 true。这是因为暗中发生了隐式 bool🡢int 转换。此表达式被解释为 (10 < x) < 25。让我们看看这如何导致此条件始终评估为 true,通过使用运算符优先级表

x = 15 时运算符链不正确
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
x = 7 时运算符链不正确
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 时运算符链不正确
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 = 7 时运算符链不正确
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

结论

总而言之,我们学到了

这是一段漫长的旅程,但你在这堂课中学到的技能对未来的道路至关重要。请多次阅读本课中提出的概念,因为逻辑和条件的基础是非常重要的技能。