istream读取时存储的值失败

时间:2015-10-05 10:05:13

标签: c++ c++11 language-lawyer iostream

示例代码:

#include <iostream>

int main()
{
    int x = 5;
    std::cin >> x;
    std::cout << x << '\n';
}

one particular implementation上,会发生以下行为:

  • 输入:6;输出6
  • 输入:a;输出:0
  • 输入:(文件结尾);输出5
  • 输入:(空格后跟文件结尾);输出5

因此,如果失败,cin >> x会将0分配给x,如果它无法将文本转换为int;但如果失败是由于文件结束,则不会分配0

这是正确的行为吗?如果没有,根据C ++标准,正确的行为是什么?

我从之前的SO讨论中回忆起所有案例都应该从C ++ 11开始编写0,但我找不到任何使用搜索功能的内容。而且C ++标准的iostreams部分非常重要。

2 个答案:

答案 0 :(得分:3)

是的,这是自C ++ 11以来的正确行为。

您所看到的差异在于写入零&#34;当提取失败&#34;时,如果已经在流上设置了EOF,则甚至不尝试提取...所以没有任何反应。< / p>

答案 1 :(得分:1)

根据27.7.2.2.1 [istream.formatted.reqmts]第1段,格式化输入函数的第一件事是构造一个std::istream::senty对象。进一步处理取决于此对象是转换为true还是false:如果sentry转换为false,则该值不会发生任何变化。

根据27.7.2.1.3 [istream :: sentry]第5和第7段,如果流的标志不是sentryfalse将转换为std::ios_base::goodbit。也就是说,如果发生失败或EOF,sentry将转换为false。因此,如果设置了value,则在跳过空格后达到EOF时5会保持std::ios_base::skipws。如果至少有一个空格,则取消设置std::ios_base::skipws会导致值变为0

实际完成解析后,应用逻辑在22.4.2.1.2 [facet.num.get.virtuals]第3段第3阶段中定义。受影响值的关键部分是

  

...

     

要存储的数值可以是以下之一:

     

- 零,如果转换函数无法转换整个字段。 ios_base::failbit被分配到err

     

- 最积极的可表示值,如果该字段表示的值太大而无法在val中表示。 ios_base::failbit被分配到err

     

- 无符号整数类型的最负值可表示值或零,如果该字段表示的值太大而无法在val中表示。 ios_base::failbit被分配到err

     

- 转换后的值,否则。

     

结果数值存储在val

因此,观察到的行为是正确的。

对于预C ++ 11,所有情况下的值都保持不变。认为分开错误并用值表示应该表示哪个值是合乎需要的。关于如何改变行为的讨论持续了相当长的时间,实际上很有争议。

如果在尝试转换之前达到EOF,则该值不会被更改,这可能会被视为错误。我不记得在讨论变更时要考虑的情况。