读和忽略的不同EOF行为
Different EOF behavior with read versus ignore
我最近被std::istream::read
和std::istream::ignore
行为之间的微妙区别绊倒了。基本上,read
从输入流中提取N个字节,并将它们存储在缓冲区中。ignore
函数从输入流中提取N个字节,但简单地丢弃它们,而不是将它们存储在缓冲区中。所以,我的理解是,read
和ignore
在各方面基本上是相同的,除了read
保存提取的字节,而ignore
只是丢弃它们。
但是read
和ignore
之间还有一个微妙的区别,这让我很困惑。如果读取到流的末尾,则不会触发EOF条件。为了触发EOF条件,必须读取流的之后的。但是使用ignore就不同了:你只需要读到流的结尾。
考虑:
#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被"提前"触发,并被要求忽略?
eof()
应该只在您已经尝试阅读过了结尾时返回true。这两种情况都不应该是真的。
我将在这里冒险并回答我自己的问题:这看起来真的像是GCC中的一个错误。
标准读27.6.1.3第23段:
[istream::ignore]表现为一个未格式化的输入函数(如如27.6.1.3第1段所述。在建造了一个哨兵物体之后,提取字符并丢弃它们。字符被提取,直到任意一个出现以下情况:
如果n != numeric_limits::max()(18.2.1),提取n个字符
- 文件结束符出现在输入序列上(在这种情况下,函数调用setstate(eofbit),它可以扔ios_base:失败(27.4.4.3)),
- c == delim表示下一个可用的输入字符c(在这种情况下,c为提取)。注:最后一个条件将永远不会发生如果delim ==特征::eof ()
我的(有些试探性的)解释是GCC在这里是错误的,因为上面的粗体部分。Ignore应该表现为未格式化的输入函数(如read()
),这意味着只有在(流中最后一个字节已被提取)之后试图提取额外的字节时,文件结束才应该出现在输入序列上。
如果我发现有足够多的人同意这个答案,我将提交一个错误报告。
大家一致认为这是gcc中一个合理的错误。由于我没有看到任何提交bug报告的迹象,所以我现在正在这样做。该报告可在以下网址查看:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51651- 理解boost::asio-async_read在无需读取内容时的行为
- 如何确定我已使用非编码文件到达 EOF?
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- arr[-1]在c++中的奇怪行为
- 继承期间显示未知行为的子类
- 如何在c++中使用引用实现类似python的行为
- G锁定铸造到基础上会释放模拟行为
- 在C++中对T*类型执行std::move的意外行为
- std::当在256字节边界上写入整数时,流的奇怪行为
- 不知道某个东西是否被忽略会引入未定义的行为吗
- 奇怪的构造函数行为
- 重载运算符new[]的行为取决于析构函数
- 不同语言中相同代码的不同行为
- 处理除以零会导致<csignal>意外行为
- Fstream 在点击 EOF 时读取行为
- C++/VIM相对于其他IDE的怪异EOF行为
- C++ eof 上的 istream tellg()/fail() :行为改变;解决方法
- istream::偷看奇怪的行为.EOF
- 为什么当我提取到"char"和"int"时,IOStream的EOF标志行为会有所不同?
- 读和忽略的不同EOF行为