读取与忽略的不同EOF行为

时间:2011-07-09 20:59:11

标签: c++ iostream

我最近因为std::istream::readstd::istream::ignore的行为之间的微妙区别而被绊倒。基本上,read从输入流中提取N个字节,并将它们存储在缓冲区中。 ignore函数从输入流中提取N个字节,但只是丢弃它们而不是将它们存储在缓冲区中。所以,我的理解是readignore在各个方面基本相同,除了read保存提取的字节而ignore只丢弃它们。< / p>

但是readignore之间还有另一个微妙的区别,它设法让我失望。如果您读到流的末尾,则不会触发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是通过调用忽略来“提前”触发的?

3 个答案:

答案 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中的合法错误。由于我没有看到提交错误报告的迹象,我现在正在这样做。该报告可在以下网址查看:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51651