假设我们有一个流,其中只包含:
hello
请注意,\n
最后没有像文本文件中那样的额外内容。现在,以下简单代码显示eof
在提取单个std::string
.
int main(int argc, const char* argv[])
{
std::stringstream ss("hello");
std::string result;
ss >> result;
std::cout << ss.eof() << std::endl; // Outputs 1
return 0;
}
但是,我不明白为什么根据标准会发生这种情况(我正在阅读 C++11 - ISO/IEC 14882:2011(E))。operator>>(basic_stream<...>&, basic_string<...>&)
被定义为表现得像一个格式化的输入函数。这意味着它构造了一个sentry
对象,该对象继续吃掉空白字符。在这个例子中,没有,所以sentry
构造完成没有问题。当转换为 abool
时,sentry
对象给出true
,因此提取器继续进行字符串的实际提取。
然后将提取定义为:
提取并附加字符,直到发生以下任何情况:
n
存储字符;- 文件结束出现在输入序列上;
isspace(c,is.getloc())
对于下一个可用的输入字符c为真。提取最后一个字符(如果有)后,调用 is.width(0) 并销毁哨兵对象 k。如果函数没有提取字符,它会调用
is.setstate(ios::failbit)
,这可能会抛出ios_base::failure
(27.5.5.4)。
这里实际上没有任何东西会导致该eof
位被设置。是的,如果到达文件末尾,提取将停止,但它不会设置该位。实际上,eof
只有在执行 another 时才应设置该位ss >> result;
,因为当sentry
尝试吞噬空白时,会发生以下情况:
如果
is.rdbuf()->sbumpc()
或is.rdbuf()->sgetc()
返回traits::eof()
,函数调用setstate(failbit | eofbit)
但是,这肯定还没有发生,因为尚未failbit
设置。
设置该位的结果是,在读取文件时邪恶习语不起作用eof
的唯一原因是因为最后的额外内容,而不是因为该位尚未设置。当提取在文件末尾停止时,我的编译器很乐意设置该位。while (!stream.eof())
\n
eof
eof
那么这应该发生吗?还是标准的意思是说setstate(eofbit)
应该发生?
为了使它更容易,标准的相关部分是:
- 21.4.8.9 插入器和提取器 [string.io]
- 27.7.2.2 格式化输入函数 [istream.formatted]
- 27.7.2.1.3 类
basic_istream::sentry
[istream::sentry]