为什么std :: ios_base :: ignore()设置EOF位?

时间:2016-10-28 15:11:54

标签: c++ c++11 std iostream

当我从流中读取所有数据但未尝试读取其结束时,未设置流的EOF。那就是C ++流如何工作,对吧?这就是原因:

#include <sstream>
#include <cassert>

char buf[255];

int main()
{
    std::stringstream ss("abcdef");
    ss.read(buf, 6);

    assert(!ss.eof());
    assert(ss.tellg() == 6);
}

但是,如果代替read()数据我ignore(),则设置EOF:

#include <sstream>
#include <cassert>

int main()
{
    std::stringstream ss("abcdef");
    ss.ignore(6);

    assert(!ss.eof());        // <-- FAILS
    assert(ss.tellg() == 6);  // <-- FAILS
}

这是在GCC 4.8和GCC主干(Coliru)上。

还有让tellg()返回-1的不幸副作用(因为那是tellg()所做的),这对我所做的事情很烦人。做。

这是标准规定的吗?如果是这样,哪一段和为什么?为什么ignore()会尝试阅读比我告诉它更多的内容?

我无法在cppreference's ignore() page找到此行为的任何理由。我可能.seekg(6, std::ios::cur)而不是,对吧?但我仍然想知道发生了什么。

1 个答案:

答案 0 :(得分:5)

我认为这是一个libstdc ++ bug(42875h/t NathanOliver)。 [istream.unformatted]中对ignore()的要求是:

  

提取字符直到任何字符   发生以下情况:
   - 目前已提取n != numeric_limits<streamsize>::max()(18.3.2)和n个字符    - 文件结束发生在输入序列上(在这种情况下函数调用setstate(eofbit),   这可能会抛出ios_base::failure(27.5.5.4));
   - traits::eq_int_type(traits::to_int_type(c), delim)表示下一个可用的输入字符   c(在这种情况下c被提取)   备注: traits::eq_int_type(delim, traits::eof())。将永远不会发生最后一个条件

所以我们有两个条件(最后一个被忽略) - 我们要么读n个字符,要么在某个时刻我们点击文件结尾,在这种情况下我们设置eofbit。但是,在这种情况下,我们能够从流中读取n个字符(实际上你的流中有6个字符),所以我们不会在输入序列上点击文件结尾。

在libc ++中,eof()未设置且tellg()确实返回6.