【问题标题】:C++ Boolean evaluationC++ 布尔求值
【发布时间】:2012-06-05 05:54:57
【问题描述】:

所以我很好奇为什么会发生这种情况。

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

预期行为: 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.

程序为什么会陷入死循环?

【问题讨论】:

  • +1 提出一个恰当的问题。布尔值是一条红鲱鱼;真正的问题与流输入的工作方式有关。用 int 尝试同样的事情,然后输入一个字母,看看会发生什么;-)
  • 也许我错了,但是当您输入表单命令行时...不会变成字符串,因此您实际上是在字符串和布尔值之间进行转换?这可能会把事情搞砸......
  • Cameron 提出了一个很好的观点:一个字符可以转换为一个整数。例如,'A' == 65,但同样的事情也会发生。
  • @Flo:不,这根本不是命令行输入的工作方式。
  • @Flo:从字符串到布尔值的转换正是operator&gt;&gt;(istream&amp;, bool&amp;)的目标。同样,operator&gt;&gt;(istream&amp;, int&amp;) 将字符串转换为整数。

标签: c++ boolean type-conversion iostream


【解决方案1】:

实际上,用于读取booloperator&gt;&gt; 重载仅允许将01 的值作为有效输入。运算符重载遵循num_get 类模板,该模板从输入流中读取下一个数字,然后行为如下(C++11 §22.4.2.1/6):

  • 如果要存储的值为0,则存储false

  • 如果值为1,则存储true

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

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

当您输入一个非零或一的值时,会在流上设置失败状态,这会导致进一步的提取失败。 answer 设置为 true 并永远保持 true,从而导致无限循环。

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

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

【讨论】:

  • +1:比接受的答案要好得多,因为它解释了标准要求这种行为。
  • 同意 :) 更改了答案以反映提供更好的理解。绝对是为什么输入验证总是很重要的一个例子:)
【解决方案2】:

因为operator&gt;&gt;如果输入不是0或1就失败了,失败时不消耗输入。所以循环包括读取数字,然后重复读取它。

尝试像这样更改代码以查看它:

if (cin >> answer) {
  cout << answer << endl;
} else {
  cerr << "oops" << endl;
  break;
}

【讨论】:

  • 虽然你一般想写if (!(cin &gt;&gt; answer))而不是cin &gt;&gt; answer; if (cin.fail())
  • 刚试过这个,如果你只是输入一些东西然后按回车,程序就会“挂起”。但是,如果您再次键入它,它会继续评估输入。为什么?
  • 反对传播if (cin.fail()) 反模式。测试操作的结果(正如@SteveJessop 建议的那样)而不是流状态。
  • @Jonathan:至少它是正确的,你只是在抱怨风格。更多时候,您会看到检查 bad()eof() 而不是 fail() 的错误代码。
猜你喜欢
  • 2011-12-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-12
  • 2015-08-03
  • 2011-03-28
  • 2018-12-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多