C++ 从istream提取失败后字符串的内容

C++ 从istream提取失败后字符串的内容,c++,extraction,istream,C++,Extraction,Istream,如果我这样做: ifstream stream("somefilewhichopenssuccesfully.txt"); string token; if( stream >> token ) cout << token; else cout << token; ifstream流(“somefilewhichocpensuccessfully.txt”); 字符串标记; 如果(流>>令牌) 库特 第二种情况下的输出是否保证为空字符串 答案

如果我这样做:

ifstream stream("somefilewhichopenssuccesfully.txt");
string token;
if( stream >> token )
    cout << token;
else
    cout << token;
ifstream流(“somefilewhichocpensuccessfully.txt”);
字符串标记;
如果(流>>令牌)
库特
第二种情况下的输出是否保证为空字符串

答案是:不,因为这要视情况而定,如下所述

因为
else
块只有在尝试从流中读取失败时才会执行,并且在读取过程中随时都可能发生这种情况

  • 如果在第一次尝试时失败,则不会从流中提取字符,因此
    token
    将为空(原样)

  • 如果在几次读取后失败,则
    令牌
    将不会为空。它将包含从流中成功读取的字符

本标准第§21.3.7.9节规定:

首先构造一个哨兵对象 就好像k是由typename构造的一样 基本信息流:哨兵 k(is)。如果bool(k)为真,则调用 str.erase()然后提取 中的字符,并将其附加到 通过调用str.append(1,c)将str当作。 如果is.width()大于零, 最大字符数n 追加的是.width();否则n就是 str.max_size()字符为 提取并附加到以下任何一项: 出现以下情况

-n个字符 储存

-文件结束发生在 输入序列

-isspace(c,is.getloc())对于 下一个可用的输入字符c

最后一个字符(如果有)后面是 已提取,为。调用宽度(0)并 哨兵目标k被摧毁

如果函数不提取字符,则调用.setstate(ios::failbit),这可能引发ios_base::failure(27.4.4.3)



还请注意,标准§21.3.1/2部分保证默认构造字符串为空。标准上说它的大小是零,也就是说,是空的。

我删除了我原来的答案,因为我想测试这个。这就是我看到的,如果在读取时出现错误(EOF在此上下文中不计算),则修改原始字符串,分支会看到修改后的版本。为了进行测试,我创建了一个2Gb文件(
touch
然后
truncate
),上面的代码可以读取。当代码运行时,删除了文件(我认为这应该设置
故障位)。立即停止读取,但字符串被修改-它的大小更大


对我来说,这表示即使流操作失败,字符串也会被修改。

否,即使操作失败,字符串将包含到目前为止提取的字符

本标准规定(§21.4.8.9):

效果:表现为格式化输入函数(27.7.2.2.1)。在构造
sentry
对象后,如果sentry转换为true,则调用
str.erase()
,然后从
is
提取字符,并将它们附加到
str
,就像调用
str.append(1,c)
一样。如果
is.width()
大于零,则追加的最大字符数n为
is.width()
;否则n是
str.max\u size()
。提取并追加字符,直到出现以下任一情况:
-存储n个字符
-文件结束发生在输入序列上
-
isspace(c,is.getloc())
对于下一个可用的输入字符c为true


@纳瓦兹:我的意思是保证
istream
如果不成功,就不会改变字符串。@纳瓦兹:构造函数不相关,操作符还是会清除字符串。关键是,如果在字符串中读取了几个字符,然后通过读取操作设置了failbit,那么会发生什么?部分提取的字符串会发生什么。这似乎在标准中没有明确说明,它只是在上下文中提到了eof。@纳瓦兹:这还没有说明如果它提取了3个字符,然后得到一个非eof的失败会发生什么。@Erik:但不管它说什么,它清楚地表明,
token
在读取和追加时,即使一次读取成功,也不会为空。@Nawaz:看起来是这样的,所以OP的答案是“否”。@Nawaz,很抱歉您的评论断章取义,我删除了我的原始答案以进行正确的测试。感谢您的努力,但这并不能保证这种行为无处不在。