如果第一次读取失败,则 std::istream::unget() 设置失败和坏位,但如果第二次或进一步读取失败则不会

时间:2021-01-29 11:09:46

标签: c++ istream

我有以下代码:

#include <algorithm>
#include <ios>
#include <iostream>
#include <string>
#include <vector>

std::vector<int> read_ints(std::istream& is)
{
    std::vector<int> res;

    std::cout << "Please input a list of integers ('quit' to finish):" << std::endl;
    for (int i; is >> i; )
    {
        res.push_back(i);
    }
    if (is.eof())  // fine: end of file
    {
        std::cout << "EOF reached" << std::endl;
        return res;
    }
    std::cout << (is.bad() ? "1) BAD\n" : "");
    std::cout << (is.fail() ? "1) FAIL\n" : "");
    if (is.fail())  // we failed to read an int: was it the 'quit' string?
    {
        is.clear();  // reset the state to good
        std::cout << (is.bad() ? "2) BAD\n" : "");
        std::cout << (is.fail() ? "2) FAIL\n" : "");
        is.unget();  // put the non-digit back into the stream
        std::cout << (is.bad() ? "3) BAD\n" : "");
        std::cout << (is.fail() ? "3) FAIL\n" : "");
        std::string s;
        if (is >> s && s == "quit")
        {
            std::cout << "Exiting correctly" << std::endl;
            return res;
        }
        std::cout << "Exiting with an error. User typed: " << s << std::endl;
        is.setstate(std::ios_base::failbit);  // add fail() to stream's state
    }
    return res;
}

int main()
{
    // Read ints
    auto v = read_ints(std::cin);
    bool first = true;
    std::for_each(v.begin(), v.end(),
        [&first](int n) { std::cout << (first ? "" : " ") << n; first = false; });
    std::cout << std::endl;
}

如果我输入一个或多个数字后跟一个单词(例如 1hola1 2 3 quit),is.unget() 既不会设置失败位也不会设置坏位,并且我获取预期的输出消息(例如 Exiting with an error. User typed: holaExiting correctly)。

但是如果我只是输入一个单词(例如 holaquit),is.unget() 会设置失败位和错误位,我无法恢复最后一个输入,得到消息 {{ 1}}。

对于后一种情况,为什么我们不能将从流中读取的任何内容放回其中?

https://godbolt.org/z/dMoodE

1 个答案:

答案 0 :(得分:1)

您的错误似乎是认为在读取整数和非数字时发现字符被消耗了。不是。只需删除对 std::unget 的调用。

相关问题