为什么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。