我这样做:
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。