【问题标题】:C++ - How to recover istream if self defined extractor failsC++ - 如果自定义提取器失败,如何恢复 istream
【发布时间】:2014-11-29 15:26:01
【问题描述】:

我需要一个自定义的提取器(运算符>>)来读取特定的字符串 变成我自己的数据类型。

问题是对字符串的要求很大。

因此最简单的方法可能是从 istream 中读取整个字符串 然后检查是否满足所有要求。

我的问题是字符串是否无效。 据我所知,在 C++ 中流是不变的是很常见的。

在这种情况下恢复 istream 的最佳做法是什么? 下面例子中的异常处理够吗?

std::istream& operator>>(std::istream& is, Foo& f)
{
    std::string str;

    if (is >> str)
    {
        // check if string is valid
        if ( is_valid( str ) )
        {
            // set new values in f
        }
        else
        {
            // recover stream
            std::for_each(str.rbegin(), str.rend(),
                          [&] (char c)
            {
                is.putback(c);
            });

            // ste failbit
            is.clear(std::ios_base::failbit);
        }
    }

    return is;
}

那么 std::getline() 而不是 is >> str 呢?还有其他陷阱吗?

谢谢

马可

【问题讨论】:

  • 不,如果流不支持(无限)多次放回或向后搜索,则无法将流恢复到其初始状态。

标签: c++ io stream recovery


【解决方案1】:

您无法将流返回到您开始阅读的初始位置,至少一般情况下不会。理论上,您可以放回字符或搜索到您以前去过的位置,但许多流缓冲区不支持放回字符或搜索。标准库提供了一些有限的指导,但它处理相当简单的类型,例如整数:只要格式匹配,就会读取字符并且它就停在那里。即使格式匹配,也可能存在一些本可以更早检测到的错误。

这是一个演示标准库行为的测试程序:

#include <iostream>
#include <sstream>

void test(std::string const& input)
{
    std::istringstream in(input);
    int i;
    std::string tail;

    bool result(in >> i);
    in.clear();
    std::getline(in, tail);
    std::cout << "input='" << input << "' "
              << "fail=" << std::boolalpha << result << " "
              << "tail='" << tail << "'\n";
}

int main()
{
    test("10 y");
    test("-x y");
    test("0123456789 x");
    test("123456789012345678901234567890 x");
}

只是解释四个测试用例:

  1. 只是为了确保测试按预期进行,第一个输入实际上是可以的,没有问题。
  2. 第二个输入以匹配格式的字符开头,后面跟着不匹配的字符,读取在'-' 字符之后立即停止。
  3. 第三个测试使用八进制数读取int。可以在字符 '8' 上检测到失败,但 '8''9' 都被消耗并且输入失败。
  4. 最后一个示例导致溢出,可以在读取所有数字之前检测到,但仍会读取所有数字。

基于此,我认为当对格式正确的输入进行语义检查失败时,不会期望将流重置为原始位置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-06
    • 1970-01-01
    • 2020-10-24
    • 1970-01-01
    相关资源
    最近更新 更多