如果我这样做:
ifstream stream("somefilewhichopenssuccesfully.txt");
string token;
if( stream >> token )
cout << token;
else
cout << token;
第二种情况下的输出是否保证为空字符串?我似乎无法在 cplusplus.com 上找到答案。
谢谢!
如果我这样做:
ifstream stream("somefilewhichopenssuccesfully.txt");
string token;
if( stream >> token )
cout << token;
else
cout << token;
第二种情况下的输出是否保证为空字符串?我似乎无法在 cplusplus.com 上找到答案。
谢谢!
第二种情况下的输出是否保证为空字符串?
答案是:不,因为它取决于,如下所述。
因为else
只有在尝试从流中读取失败时才会执行块,并且在读取过程中随时可能发生这种情况。
如果它在第一次尝试时失败,则不会从流中提取字符,因此token
将是空的(原样)。
如果在几次读取后失败,则token
不会为空。它将包含到目前为止从流中成功读取的字符。
标准中的第 21.3.7.9 节说,
从构造一个哨兵对象 k 开始,就好像 k 是由 typename basic_istream::sentry k(is) 构造的。如果 bool(k) 为真,它调用 str.erase() 然后从 is 中提取字符并将它们附加到 str ,就像调用 str.append(1,c) 一样。如果 is.width() 大于零,则追加的最大字符数为 is.width();否则 n 是 str.max_size()。字符被提取并附加,直到发生以下任何情况:
— 存储 n 个字符;
— 文件结束出现在输入序列上;
— isspace(c,is.getloc()) 对于下一个可用的输入字符 c 为真。
提取最后一个字符(如果有)后,调用 is.width(0) 并销毁哨兵对象 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):
效果:表现为格式化输入函数 (27.7.2.2.1)。构造
sentry
对象后,如果哨兵转换为 true,则调用str.erase()
然后从中提取字符is
并将它们附加到,str
就好像通过调用str.append(1,c)
. 如果is.width()
大于零,则追加的最大字符数为is.width()
; 否则 n 是str.max_size()
。字符被提取和附加,直到发生以下任何情况:
— n 个字符被存储;
— 文件结束出现在输入序列上;
—isspace(c,is.getloc())
对下一个可用的输入字符 c 为真。