什么时候`ifstream :: readsome`设置`eofbit`?

Lig*_*ica 9 c++ iostream

这段代码永远循环:

#include <iostream>
#include <fstream>
#include <sstream>

int main(int argc, char *argv[])
{
    std::ifstream f(argv[1]);
    std::ostringstream ostr;

    while(f && !f.eof())
    {
        char b[5000];
        std::size_t read = f.readsome(b, sizeof b);
        std::cerr << "Read: " << read << " bytes" << std::endl;
        ostr.write(b, read);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是因为readsome永远不会设置eofbit.

cplusplus.com说:

通过修改内部状态标志来发出错误信号:

eofbit 调用函数时,get指针位于流缓冲区内部输入数组的末尾,这意味着内部缓冲区中没有要读取的位置(可能是输入序列的末尾).在提取第一个字符之前rdbuf()->in_avail()返回时会发生这种情况-1.

failbit 在调用函数之前,流位于字符源的末尾.

badbit 发生了上述以外的错误.

几乎相同,标准说:

[C++11: 27.7.2.3]: streamsize readsome(char_type* s, streamsize n);

32.效果:表现为无格式输入函数(如27.7.2.3第1段所述).构造一个sentry对象之后,如果!good()调用 setstate(failbit)可能会抛出异常,并返回.否则提取字符并将它们存储到第一个元素由其指定的数组的连续位置s.如果rdbuf()->in_avail() == -1,调用 setstate(eofbit)(可能抛出ios_base::failure(27.5.5.4)),并且不提取任何字符;

  • 如果rdbuf()->in_avail() == 0,则不提取任何字符
  • 如果rdbuf()->in_avail() > 0,提取min(rdbuf()->in_avail(),n)).

33.返回:提取的字符数.

in_avail() == 0条件是无操作意味着ifstream::readsome本身是一个空操作,如果流缓冲区是空的,但in_avail() == -1条件意味着它设置eofbit一些其它的操作导致in_avail() == -1.

这似乎是一种不一致,即使有"某种"性质readsome.

那么,什么语义readsomeeof?我是否正确地解释了它们?它们是流库中设计不佳的一个例子吗?


(从[IMO]无效的libstdc ++ bug 52169中窃取.)

Bo *_*son 5

我认为这是一个自定义点,默认流实现并未真正使用它。

in_avail()返回内部缓冲区中可以看到的字符数(如果有)。否则,它会调用showmanyc()尝试检测字符是否已知在其他地方可用,因此保证缓冲区填充请求成功。

反过来,showmanyc()将返回它知道的字符数(如果有),如果知道读取将失败,则返回 -1,如果没有线索,则返回 0。

默认实现 ( basic_streambuf) 始终返回 0,因此这就是您得到的结果,除非您有一个具有其他一些 Streambuf 覆盖的流showmanyc

您的循环本质上是按您所知的安全方式读取多个字符,当该值为零时(意味着“不确定”),它就会卡住。