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



我这样做:

ifstream stream("somefilewhichopenssuccesfully.txt");
string token;
if( stream >> token )
    cout << token;
else
    cout << token;

第二种情况下的输出保证是空字符串吗?我似乎在cplusplus.com上找不到这个问题的答案。

谢谢!

第二种情况下的输出保证是空字符串吗?

答案是:不,因为这取决于情况,如下所述。

由于else块只有在读取流失败时才会被执行,而这种情况在读取过程中随时都可能发生。

  • 如果它在第一次尝试失败,那么没有从流中提取字符,因此token将为空(就像它一样)。

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

标准第21.3.7.9节说,

首先构造一个哨兵对象就好像K是由typename构造的basic_istream:哨兵k(是)。如果bool(k)为真,则调用str.erase(),然后提取字符从is中取出,并将它们追加到调用str.append(1,c)。如果is.width()大于零,最大字符数nis.width();否则n等于str.max_size()。字符提取并追加,直到任意一个:

- n个字符存储;

- end- file发生在输入序列;

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

最后一个字符(如果有的话)后面是提取后,is.width(0)被称为and哨兵对象k被销毁。

如果函数没有提取字符,它调用is.setstate(ios::failbit),这可能会抛出ios_base::failure(27.4.4.3)。


还要注意,标准中的§21.3.1/2节保证默认构造的字符串为空。

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

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

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

标准规定(§21.4.8.9):

Effects:表现为格式化的输入函数(27.7.2.2.1)。在构造sentry对象之后,如果哨兵转换为true,则调用str.erase(),然后从is中提取字符并将它们附加到str,就像调用str.append(1,c)一样。如果is.width()大于0,则追加的最大字符数n为is.width();否则n为str.max_size()。字符被提取并追加,直到出现以下任意一种情况:
-存储n个字符;
- end- file出现在输入序列上;
- isspace(c,is.getloc())对于下一个可用的输入字符c为true。

最新更新