微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

我有以下代码

#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

解决方法

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。