我最近因为std::istream::read
与std::istream::ignore
的行为之间的微妙区别而被绊倒。基本上,read
从输入流中提取N个字节,并将它们存储在缓冲区中。 ignore
函数从输入流中提取N个字节,但只是丢弃它们而不是将它们存储在缓冲区中。所以,我的理解是read
和ignore
在各个方面基本相同,除了read
保存提取的字节而ignore
只丢弃它们。< / p>
但是read
和ignore
之间还有另一个微妙的区别,它设法让我失望。如果您读到流的末尾,则不会触发EOF条件。您必须读取过去流的结尾才能触发EOF条件。但忽略它是不同的:你只需要读取流的 end 。
考虑:
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
{
std::stringstream ss;
ss << "abcd";
char buf[1024];
ss.read(buf, 4);
std::cout << "EOF: " << std::boolalpha << ss.eof() << std::endl;
}
{
std::stringstream ss;
ss << "abcd";
ss.ignore(4);
std::cout << "EOF: " << std::boolalpha << ss.eof() << std::endl;
}
}
在GCC 4.4.5上,打印出来:
EOF: false
EOF: true
那么,为什么这里的行为不同?这种微妙的差异让我感到困惑,不知道为什么会有区别。是否有一些令人信服的理由认为EOF是通过调用忽略来“提前”触发的?
答案 0 :(得分:2)
eof()
只有在您已经尝试阅读结束时才会返回true。在任何情况下都不应该是真的。这可能是您实施中的错误。
答案 1 :(得分:2)
我将在这里站出来回答我自己的问题:看起来这真的是GCC中的一个错误。
该标准见27.6.1.3第23段:
[istream :: ignore]表现为 无格式输入功能(如 在27.6.1.3,第1段中描述。 构建哨兵对象后, 提取字符并丢弃它们。 提取字符直到任何一个 发生以下情况:
- if n!= numeric_limits :: max() (18.2.1),提取n个字符
- 文件结束发生在输入序列上(在这种情况下是函数 调用setstate(eofbit),可以 throw ios_base :: failure(27.4.4.3));
- c == delim下一个可用的输入字符c(在这种情况下c为 萃取)。注意:最后一个条件 如果delim ==将永远不会发生 性状:: EOF()
我的(有点试探性的)解释是GCC在这里是错误的,因为上面的大胆部分。 Ignore应该表现为无格式输入函数,(如read()
),这意味着如果尝试提取其他字节,则文件结尾应仅出现在输入序列上< em>在之后,已经提取了流中的最后一个字节。
如果我发现有足够的人同意这个答案,我会提交错误报告。
答案 2 :(得分:0)
共识似乎是这是gcc中的合法错误。由于我没有看到提交错误报告的迹象,我现在正在这样做。该报告可在以下网址查看: