0
    #include <string>
    #include <iostream>

    int main() {
        std::string str;
        char magic[9];
        std::cin.read((char *)magic, sizeof(magic));
        std::cin.seekg(0, std::ios::beg);

        while (std::cin >> str) {
            std::cout << str << std::endl;
        }
    }

我的代码包含在 std::cin 上的 seekg(0) 函数的实现,当运行时它在某些文件上的行为不符合预期 ./a.out < filename

那些行为不符合预期的文件具有字符数(包括结束行字符和其他空格)小于 9 的属性(9 是我们在 seekg 之前从 cin 读取的字符数)

如果文件包含超过 9 个字符,则它的行为符合预期,例如:

123456789

将输出为

123456789

而包含少于 9 个字符的文件不会给出输出

例如:

1234

不会输出

4

1 回答 1

2

对于少于九个字符的文件,您已经尝试使用初始的read. 这意味着eof(文件结尾)和fail标志已为流设置,虽然seekg可能会重置eof,但它不会重置fail (a)

您可以通过插入来检查:

cout << "eof/fail=" << cin.eof() << '/' << cin.fail() << '\n';

之前和之后seekg。对于分别为 8、9 和 10 的文件大小,您将获得:

eof/fail=1/1
eof/fail=0/1

eof/fail=0/0
eof/fail=0/0
12345678

eof/fail=0/0
eof/fail=0/0
123456789

您可以看到第一个失败导致没有输出,因为该fail位仍然设置。第二个和第三个有输出,因为它从未设置过(输出是显示的字符加上一个换行符)。

要修复此问题,您只需在 之前插入以下内容即可清除该位:failseekg

std::cin.clear();

然后在八字符文件上运行该代码给出:

eof/fail=1/1
eof/fail=0/0
1234567

表明clear确实清除了该fail位。


您可能还需要记住,流不是可搜索的要求,特别是如果它只是通过标准输入进入时。如果您已通读大量流,您可能会发现对于某些大小的文件,您无法找到任意数量的文件。


(a)对于我们中间的语言律师来说,(Unformatted input functions和)基本上都有相同的文本来说明如何工作(我的重点):C++11 27.7.2.3/41C++14 27.7.2.3/41C++17 30.7.4.3/41seekg

构造一个哨兵对象后,如果fail() != true,执行...

于 2018-02-26T01:17:36.897 回答