为什么stringstream >>更改目标失败的值?

从Stroustrup的TC ++ PL第3版第21.3.3节:

如果我们尝试读入variablesv并且操作失败,则v的值应该保持不变(如果v是istream或ostream成员函数处理的types之一,则不变)。

下面的例子似乎与上面的引用相矛盾。 根据上面的报价,我期待v的价值保持不变 – 但它被归零。 这种明显的矛盾行为的解释是什么?

#include <iostream> #include <sstream> int main( ) { std::stringstream ss; ss << "The quick brown fox."; int v = 123; std::cout << "Before: " << v << "\n"; if( ss >> v ) { std::cout << "Strange -- was successful at reading a word into an int!\n"; } std::cout << "After: " << v << "\n"; if( ss.rdstate() & std::stringstream::eofbit ) std::cout << "state: eofbit\n"; if( ss.rdstate() & std::stringstream::failbit ) std::cout << "state: failbit\n"; if( ss.rdstate() & std::stringstream::badbit ) std::cout << "state: badbit\n"; return 1; } 

我使用x86_64-w64-mingw32-g ++。exe(rubenvb-4.7.2-release)4.7.2得到的输出是:

 Before: 123 After: 0 state: failbit 

谢谢。

从这个参考 :

如果提取失败(例如,如果input的字母是数字所在的位置),值将保持不变,并设置失败位( 直到C ++ 11

如果提取失败,写入零值并设置失败位。 如果提取的结果值太大或太小而不适合值,则std :: numeric_limits :: max()或std :: numeric_limits :: min()被写入,并设置failbit标志。 ( 自C ++ 11以来

看来你的编译器正在用C ++ 11模式编译,这会改变行为。


input运算符使用其get函数调用do_get的语言环境构面std::num_get do_get 。 对于C ++ 11,它被指定使用std::strtoll et。 人。 types的function。 在C ++ 11之前,它显然使用std::scanf风格parsing(通过引用进行,我没有访问C ++ 03规范)来提取数字。 行为的改变是由于parsinginput的这种改变。

操作员>>是格式化的input操作员。
因此,这取决于如何从stream中读取input的语言环境:

[istream.formatted.arithmetic]

和插入程序一样,这些提取程序依赖于语言环境的num_get <>(22.4.2.1)对象来parsinginputstream数据。 这些提取器performance为格式化的input函数(如27.7.2.2.1所述)。 在创build一个哨兵对象之后,转换发生如同由以下代码片段执行:

  typedef num_get< charT,istreambuf_iterator<charT,traits> > numget; iostate err = iostate::goodbit; use_facet< numget >(loc).get(*this, 0, *this, err, val); setstate(err); 

正如我们上面看到的那样,这个值实际上是通过被embedded到stream中的区域设置的numget facet设置的。

num_get虚函数[facet.num.get.virtuals]

阶段3:

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

  • 零,如果转换函数无法转换整个字段。 ios_base :: failbit被分配给err。
  • 如果该字段表示一个值太大的正值,则表示为val。 ios_base :: failbit被分配给err。
  • 对于无符号整数types来说,如果该字段表示值太大而不能在val中表示,则为负数可表示的值或零。 ios_base :: failbit被分配给err。

第三阶段的定义在n2723 – > n2798之间急剧变化

我在哪里可以find当前的C或C ++标准文档?

num_get虚函数[facet.num.get.virtuals]

阶段3:阶段2处理的结果可以是以下之一:

  • 在阶段2中已经积累了一系列的字符(根据scanf的规则)转换为valtypes的值。 该值存储在val中,ios_base :: goodbit存储在err中。
  • 阶段2中积累的字符序列会导致scanf报告input失败。 ios_base :: failbit被分配给err。