"Key Takeaway"
- 不能用括号初始化和一个整型数来初始化布尔变量,其他情况是可以转换的
std::cin
不能接收true
或者false
,除非使用std::cout << std::boolalpha;
在现实中,有些问题的答案只有”是“或”不是“两种。”苹果是水果吗?“,是的。”你爱吃笋吗?“不。
现在,我们考虑一个类似的语句,它只能用true
或false
来回答:”苹果是水果“,true
。”我喜欢吃笋“,false
。
像这种只有两种可能答案的语句(yes/true 或 no/false)很常见,很多编程语言都有用于处理此类输出结果的特殊类型。它们称为布尔类型(注意:Boolean在英语中是大大写字母开头的,因为它的发明人是乔治布尔(George Boole))。
布尔变量
布尔变量只有两种可能的值:true 和 false。
声明布尔类型的变量需要使用关键字 bool。
bool b;
初始化布尔类型的变量或为其赋值,需要使用 true
或 false
。
bool b1 { true };
bool b2 { false };
b1 = false;
bool b3 {}; // 默认初始化为 false
和一元负号运算符(-
)可以被用来将一个正数变成负数一样,使用逻辑非运算符(!
)可以将布尔值true
变成false
或者把false
变成true
:
bool b1 { !true }; // b1 被初始化为 false
bool b2 { !false }; // b2 被初始化为 true
布尔值通常并不会以 “true” 或 “false”来存储。实际上它是以整型来存储的:true
会变成1,false
会变成0。类似地,当布尔类型求值时,求值的实际结果也并不是“true” 或 “false”。通常它们会求值成_0_ (false) 或 1 (true)。因为布尔类型实际上是以整型存储的,因此它属于一种整形的类型(integral type)。
打印布尔变量
当使用 std::cout
打印布尔变量时, std::cout
会将 false 打印成 0,而把 true 打印成1:
#include <iostream>
int main()
{
std::cout << true << '\n'; // true evaluates to 1
std::cout << !true << '\n'; // !true evaluates to 0
bool b{false};
std::cout << b << '\n'; // b is false, which evaluates to 0
std::cout << !b << '\n'; // !b is true, which evaluates to 1
return 0;
}
Outputs:
1
0
0
1
如果你希望 std::cout
打印 “true” 或 “false” 而不是 0 或 1,你可以使用 std::boolalpha
。例如:
#include <iostream>
int main()
{
std::cout << true << '\n';
std::cout << false << '\n';
std::cout << std::boolalpha; // print bools as true or false
std::cout << true << '\n';
std::cout << false << '\n';
return 0;
}
打印结果:
1
0
true
false
你可以使用 std::noboolalpha
来关闭此功能。
整型转换为布尔类型
你不能用括号初始化和一个整型数来初始化布尔变量:
#include <iostream>
int main()
{
bool b{ 4 }; // 错误:: 不允许缩窄转换
std::cout << b;
return 0;
}
(注意:有些版本的g++并不会有上述限制)
不过,在其他场景下整型是可以被转换为布尔值的。整型值0会被转换为false
,而其他整型会被转换为true
。
#include <iostream>
int main()
{
std::cout << std::boolalpha; // print bools as true or false
bool b1 = 4 ; // 拷贝初始化允许隐式转换
std::cout << b1 << '\n';
bool b2 = 0 ; // 拷贝初始化允许隐式转换
std::cout << b2 << '\n';
return 0;
}
打印结果为:
true
false
注意:bool b1 = 4;
可以能会产生警告。这种情况下你需要关闭编译的”将告警当做错误处理“功能,这样你猜呢编译上述代码。
输入布尔值
使用 std::cin
来输入布尔类型常常会让新手程序员抓狂。
考虑下面的程序:
#include <iostream>
int main()
{
bool b{}; // 默认初始化为 false
std::cout << "Enter a boolean value: ";
std::cin >> b;
std::cout << "You entered: " << b << '\n';
return 0;
}
Enter a Boolean value: true
You entered: 0
什么!怎么会这样?
实际上,std::cin
只能够接收两种布尔类型输入:0和1(而不是 true
或 false
)。任何其他的输入都会导致 std::cin
出错。在上面的例子中,因为我们输入了true,因此实际上 std::cin
出错了,输入出错后,接受输入的变量会被清零,因此b
就被赋值为false
。因此,当 std::cout
打印b
的时候,会打印0。
为了让 std::cin
能够接受 “false” 和 “true” 作为输入,std::boolalpha
必须被打开。
#include <iostream>
int main()
{
bool b{};
std::cout << "Enter a boolean value: ";
// 允许用户输入 'true' 或 'false' 作为布尔值
std::cin >> std::boolalpha;
std::cin >> b;
std::cout << "You entered: " << b << '\n';
return 0;
}
不过,当std::boolalpha
打卡后,“0” 和 “1” 就不会再被看出布尔类型了。
布尔类型的返回值
布尔值常备用作函数的返回值,用来检查某件事(物)是否为true。这种函数命名时通常以is
开头(例如 isEqual
)或 has
(例如 hasCommonDivisor
)。
考虑下面这个例子,和上面有些类似:
#include <iostream>
// 如果 x 和 y 相等则返回 true 否则返回 false
bool isEqual(int x, int y)
{
return (x == y); // 如果 x 和 y 相等,operator== 则返回 true 否则返回 false
}
int main()
{
std::cout << "Enter an integer: ";
int x{};
std::cin >> x;
std::cout << "Enter another integer: ";
int y{};
std::cin >> y;
std::cout << std::boolalpha; // print bools as true or false
std::cout << x << " and " << y << " are equal? ";
std::cout << isEqual(x, y); // will return true or false
return 0;
}
两次运行的输出结果如下:
Enter an integer: 5
Enter another integer: 5
5 and 5 are equal? true
Enter an integer: 6
Enter another integer: 4
6 and 4 are equal? false
原理是什么呢?首先我们从输入获取 x 和 y 的值。接下来,表达式 isEqual(x, y)
会进行求值。在第一次运行时,执行的函数相当于 isEqual(5, 5)
。在函数中,5 == 5
被求值,得到的结果是 true。随后 true 被返回给主调函数并通过 std::cout
被打印出来。在第二次运行时,调用的函数相当于 isEqual(6, 4)
,返回的结果为 false。
使用布尔值需要熟悉一下,不过当你习惯之后,会非常喜欢它表现出来的简洁!布尔值也是编程中非常大的一部分——你使用布尔值的情况比其他基本类型加起来都多。
我们会在下一节课中继续讨论布尔值。