【问题标题】:seekg() does not set eofbit when reaching EOF of a stream. Is it by design?seekg() 在到达流的 EOF 时不设置 eofbit。是设计使然吗?
【发布时间】:2016-06-08 06:51:17
【问题描述】:

编辑:我的原始测试程序代码中有一个细微的错误: " char=" << aStream.peek() 行(可能还有" input pos=" << aStream.tellg())修改了流状态标志,因此没有报告真实状态。所以这些调用必须从代码中完全删除,否则我们无法看到seekg() 对状态标志的真正影响。 但是结果还是一样:eofbit 没有设置。

原帖:

我尝试通过调用将输入指针推进 1 步来检测 std::istream 的 EOF

seekg( 1, std::ios_base::cur )

但是,seekg() 在设置流的failbit 时,会在 EOF 之外移动 1 个位置。 eofbit 永远不会被设置。查看此测试程序的输出:

#include <iostream>
#include <sstream>

using namespace std;

void info( int aRelativePos, istream& aStream )
{
    cout << "POS=" << aRelativePos <<
            " input pos=" << aStream.tellg() <<
            " char=" << aStream.peek() <<
            "\tGood: " << aStream.good() <<
            " Eof: " << aStream.eof() <<
            " Bad: " << aStream.bad() <<
            " Fail: " << aStream.fail() << "\n";
}

int main()
{
    istringstream   input ("12");

    int i=0;
    while ( input.good() )
    {
        info( i, input );
        input.seekg( 1, std::ios_base::cur ); //advance 1 step forward
        ++i;
    }
    info ( i, input );

    return 0;
}

输出:

POS=0 input pos=0 char=49   Good: 1 Eof: 0 Bad: 0 Fail: 0
POS=1 input pos=1 char=50   Good: 1 Eof: 0 Bad: 0 Fail: 0
POS=2 input pos=-1 char=-1  Good: 1 Eof: 0 Bad: 0 Fail: 0
POS=3 input pos=-1 char=-1  Good: 0 Eof: 0 Bad: 0 Fail: 1

(由 gcc 5.2 使用 -std=c++11 编译。您可以在此处运行此代码:http://coliru.stacked-crooked.com/a/69f4d70e93359423

此外,seekg (https://msdn.microsoft.com/en-us/library/y2d6fx99(v=vs.120).aspx) 上的 MS 文档说 C++ 标准不支持文本文件中的相对定位。

但我在标准中找不到此类信息。可以给我参考一下吗?

【问题讨论】:

    标签: c++ c++11 stream


    【解决方案1】:

    只要你对标准说这是我们从 [istream.unformatted] 得到的行为没问题

    basic_istream&lt;charT,traits&gt;&amp; seekg(pos_type pos);

    效果: 表现为无格式输入函数(如 27.7.2.3,第 1 段所述),除了该函数首先清除 eofbit,它不计算提取的字符数,并且它不会影响后续调用gcount() 返回的值。构造一个哨兵对象后,如果fail() != true,则执行rdbuf()-&gt;pubseekpos(pos, ios_base::in)。如果失败,函数会调用setstate(failbit)(可能会抛出ios_base::failure)。

    因此,根据标准,我们将始终清除eofbit,并且在失败时仅设置失败位。试图阅读失败的结尾是失败的,所以这就是它被设置的原因。到达文件末尾并不是失败,因为末尾是一个有效位置。

    您可以在此示例中看到(从您的代码修改),一旦我们到达文件末尾,我们仍然很好,然后尝试从那里读取不仅会设置eofbit,还会设置failbit,因为我们位于文件末尾且提取失败

    input.seekg(0, std::ios::end);
    info (input);
    char ch;
    input >> ch;
    info (input);
    

    输出:

    Good: 1 Eof: 0 Bad: 0 Fail: 0
    Good: 0 Eof: 1 Bad: 0 Fail: 1
    

    Live Example

    【讨论】:

    • @NathanOlivier :你只解释了为什么eofbitseekg() 的开头被清除。对我来说,不清楚标准中的“如果发生故障,函数调用 setstate(failbit)”是什么意思。达到EOF是失败的吗?当 POS=2 时,输入指针被传递到流的最后一个字符(参见上面的输出),但 failbit 为 0。此位置没有有效输入,因此按照标准我可以推断 failbit 已设置然后。但事实并非如此。
    • @LeslieN 超过文件末尾是失败的。到达文件末尾并不是失败。
    • 请注意,当我使用seekg() 的绝对定位版本时,我得到相同的结果,即input.seekg( i )。所以在i == 2 的情况下,failbit 没有设置。
    • @LeslieN 流的“结束”是最后一个元素之后的一个元素,就像标准容器的 end 迭代器一样。所以有了i == 2,我们就到了最后,没关系。我们只是不能走得更远或用它做任何事情。
    • @NathanOlivier :您能否引用关于seekg() 的定义?顺便说一句,标准说 seekg() 调用具有相对定位实际上是一个 rdbuf()-&gt;pubseekoff(off, dir, std::ios_base::in) 调用,这反过来又是一个 seekoff(off, dir, std::ios_base::in) 调用。但是我在标准中找不到任何定义这些函数如何更改状态标志,当它们达到或通过 EOF...
    猜你喜欢
    • 2012-02-29
    • 1970-01-01
    • 2019-02-23
    • 2014-05-01
    • 2020-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-27
    相关资源
    最近更新 更多