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

时间:2011-04-17 19:00:11

标签: c++ extraction istream

如果我这样做:

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

第二种情况下的输出是否保证为空字符串?我似乎无法在cplusplus.com上找到答案。

谢谢!

3 个答案:

答案 0 :(得分:2)

  

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

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

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

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

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

标准中的§21.3.7.9部分说明,

  

通过构建一个哨兵对象开始   k好像k是由typename构造的   basic_istream ::哨兵   K(是)。如果bool(k)为真,则调用   str.erase()然后提取   来自的字符并将它们附加到   str就像调用str.append(1,c)一样。   如果is.width()大于零,   最大字符数n   附加的是is.width();否则n是   str.max_size()。 字符是   提取并附加到任何一个   发生以下情况

     

- n个字符   存储;

     

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

     

- isspace(c,is.getloc())为true   下一个可用的输入字符c。

     

在最后一个字符(如果有)之后   提取,is.width(0)被调用   哨兵对象k被摧毁。

     

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


另请注意,标准中的第21.3.1 / 2节保证默认构造的字符串为空。标准说它的大小将为零,这意味着空。

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

标准说(§21.4.8.9):

  

效果:表现为格式化输入功能(27.7.2.2.1)。构建sentry对象后,如果哨兵转换为true,则调用str.erase(),然后从is中提取字符并将其附加到str,就好像通过调用str.append(1,c)一样}。如果is.width()大于零,则附加的字符的最大数量n为is.width();否则n是str.max_size()。提取并附加字符,直到出现以下任何一种情况:
    - 存储n个字符;
   - 输入序列上出现文件结尾;
   - isspace(c,is.getloc())对于下一个可用输入字符c为真。