C++布尔评估

23 c++ iostream boolean type-conversion

所以我很好奇为什么会这样.

int main()
{
   bool answer = true;
   while(answer)
   {
      cout << "\nInput?\n";
      cin >> answer;
   }
return 0;
}
Run Code Online (Sandbox Code Playgroud)

预期行为:0 - 退出程序,1 - 再次提示,除1以外的任何非零整数 - 再次提示

实际行为:0 - 正如预期的那样,1 - 正如预期的那样,除1之外的任何非零整数 - 无限循环

来自http://www.learncpp.com/cpp-tutorial/26-boolean-values/

One additional note: when converting integers to booleans, 
the integer zero resolves to boolean false, 
whereas non-zero integers all resolve to true.
Run Code Online (Sandbox Code Playgroud)

为什么程序会进入无限循环?

Jam*_*lis 24

实际上,operator>>用于读取a 的重载bool仅允许值01作为有效输入.运算符重载num_get遵循类模板,类模板从输入流中读取下一个数字,然后表现如下(C++11§22.4.2.1/ 6):

  • 如果要存储的值,0然后false保存.

  • 如果该值1然后true被存储.

  • 否则true存储并ios_base::failbit分配给err.

(err这是您正在阅读的流的错误状态; cin在这种情况下.请注意,还有其他语言指定boolalpha使用操纵器时的行为,允许使用其名称插入和提取布尔值; true并且false;我有为简洁起见,省略了这些其他细节.)

当您输入非零或一的值时,将在流上设置失败状态,这会导致进一步的提取失败. answer被设置为truetrue永远保持,导致无限循环.

您必须在每次提取后测试流的状态,以查看提取是否成功以及流是否仍处于良好状态.例如,您可以将循环重写为:

bool answer = true;
while (std::cin && answer)
{
    std::cout << "\nInput?\n";
    std::cin >> answer;
}
Run Code Online (Sandbox Code Playgroud)


Jam*_*man 15

因为operator>>如果输入不是0或1则失败,并且当它失败时,它不消耗输入.所以循环包括读取数字然后重复读取它.

尝试更改这样的代码来查看它:

if (cin >> answer) {
  cout << answer << endl;
} else {
  cerr << "oops" << endl;
  break;
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然你通常想写`if(!(cin >> answer))`而不是`cin >>回答; if(cin.fail())` (4认同)
  • Downvoted用于传播`if(cin.fail())`反模式.测试操作的结果(如@SteveJessop建议的那样)而不是流状态. (3认同)
  • @Jonathan:至少它是正确的,你只是抱怨风格.更常见的是,您会看到错误的代码检查`bad()`或`eof()`而不是`fail()`. (2认同)