为什么字符串流>>失败时更改目标的值?
Why does stringstream >> change value of target on failure?
摘自Stroustrup的TC++PL,第三版,第21.3.3节:
如果我们试图读取变量v,但操作失败,v的值应该保持不变(如果v是istream或ostream成员函数处理的类型之一,则它保持不变)。
下面的示例似乎与上面的引用相矛盾。根据上面的引用,我原本希望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: eofbitn";
if( ss.rdstate() & std::stringstream::failbit ) std::cout << "state: failbitn";
if( ss.rdstate() & std::stringstream::badbit ) std::cout << "state: badbitn";
return 1;
}
我使用x86_64-w64-mingw32-g++.exe(ruenvb-4.7.2-release)4.7.2得到的输出是:
Before: 123
After: 0
state: failbit
谢谢。
来自此引用:
如果提取失败(例如,如果在需要数字的地方输入了一个字母),则值保持不变,并设置故障位(直到C++11)
如果提取失败,则将0写入值,并设置故障位。如果提取导致值太大或太小而无法放入值,则写入std::numeric_limits:max()或std::numeric_limits::min(),并设置故障位标志。(自C++11起)
编译器似乎是在C++11模式下编译的,这会改变行为。
输入运算符使用区域设置方面std::num_get
,其get
函数调用do_get
。对于C++11,指定使用std::strtoll
等类型的函数。在C++11之前,它显然使用了std::scanf
风格的解析(根据引用,我无法访问C++03规范)来提取数字。行为的变化是由于解析输入时的这种变化。
运算符>>是一个格式化的输入运算符
因此,如何从流中读取输入取决于区域设置:
[isream.formatted.athmethyl]
与插入器一样,这些提取器取决于区域设置的num_get<>(22.4.2.1)对象来执行对输入流数据的解析。这些提取器表现为格式化的输入函数(如27.7.2.2.1所述)。在构造哨兵对象后,转换发生,就像由以下代码片段执行一样:
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);
正如我们在上面看到的,该值实际上是由流中嵌入的区域设置的numget
方面设置的。
num_get虚拟函数[facet.num.get.virtuals]
第3阶段:
要存储的数值可以是以下值之一:
- 零,如果转换函数无法转换整个字段。ios_base::failbit已分配给err
- 如果字段表示的值太大而不能用val.iosbase::failbit表示,则表示最正的值
- 对于无符号整数类型,如果字段表示的值太大而不能用值表示,则表示最负的值或零。ios_base::failbit被分配给err
第3阶段的定义在n2723->n2798 之间发生了巨大变化
在哪里可以找到当前的C或C++标准文档?
num_get虚拟函数[facet.num.get.virtuals]
第3阶段:第2阶段处理的结果可以是以下之一:
- 在第2阶段中积累了一个字符序列,该序列被转换(根据scanf规则)为val类型的值。该值存储在val中,ios_base::goodbit存储在err中
- 第2阶段中累积的字符序列会导致scanf报告输入失败。ios_base::failbit已分配给err
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- C++A*算法并不总是在路径中具有目标节点
- 基于树莓pi的tensorflow lite量化ssd目标检测
- 为测试目标创建具有不同源文件夹的文件
- EASTL矢量<向量<int>>连续的
- 使用源向量作为目标
- 是否可以用C++/WinRT将windows 10.0.14393作为目标
- 在 CMake 中为每个目标设置编译器/链接器标志
- qmake:检测目标位宽(32 位或 64 位)
- 如何在 CMake 中对目标依赖项进行分组?
- 我的目标是编写一个程序来计算和存储字符串在字符数组中出现的位置
- 如何为包含头文件的目标编写生成文件?
- 线性优化目标函数中的绝对值
- 制作文件:没有规则来制定目标:如何设置正确的规则?
- 字符串函数在目标C++上运行时C++返回空
- 如何定义自定义生成配置类型,其中通常是.exe的目标改为 DLL
- 请求最简单的 OpenMP 目标 GPU 示例
- LLVM 编译:目标的配方 '../lib/IR/Release+Asserts/Intrinsics.gen.tmp' failed
- 当目标指针不是基类的类型时,为什么允许dynamic_cast为多态类生成 null 指针?
- 我应该如何在没有变量的情况下将相同的参数传递给 CMAKE 中的多个目标?