【问题标题】:Clean istream when input is not correct输入不正确时清理 istream
【发布时间】:2014-04-12 10:46:53
【问题描述】:

我正在查看 istream 类,但没有看到完全清理缓冲区并将输入设置为下一个“清理”输入的方法。

我为我的类定义了提取运算符,并在我的主程序中要求用户输入,如下所示:

while (true) {
    try {
        cout << "Enter input: ";
        MyClass c;
        cin >> c;
        return c;
    } catch(const MyException& e) {
        cerr << "Error\n";
    }
}

如果我输入了意外的错误输入,我将陷入无限循环。

在我重写的提取方法中,我控制输入不正确并引发异常的时间,这一切都可以。我只想清理istream 对象,以防止无限循环。

【问题讨论】:

标签: c++ operators operator-overloading istream


【解决方案1】:

首先,您的类的插入器/提取器不应抛出异常。 IOStreams 被设计为默认不抛出异常并保持一致,我建议您不要从 I/O 操作符中抛出自定义异常。

正如 Dieter 所说,最好将 std::ios_base::failbit 标志设置为流状态而不是抛出。您可以使用setstate() 方法执行此操作。完成此操作后,您可以使用 if() 语句检查有效提取。要回答您的问题,一旦确定输入是否无效,您就清除流状态,并通过调用 ignore() 清除缓冲区以获取新输入,丢弃其余字符:

while (std::cout << "Enter input: ")
{  
    X x;
    if (!(std::cin >> x))
    {
        std::cout << "Invalid. Try again.\n";
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        continue; // or break if needed
    }
    // handle good input and break if needed
}

【讨论】:

  • 这些方法不会抛出异常,构造函数会,它在提取方法中被调用。 clear 和 ignore 方法对我有用,这就是我一直在寻找的答案,但是我在提取方法中调用它们,而不是在提取方法之外。清理缓冲区的责任应该是程序员,而不是用户。
  • @dabadaba 如果构造函数在提取器中抛出异常,那么就好像提取器本身在抛出异常。正如我所说,您仍然应该将构造函数包装在 try catch 块中并在流中设置 failbit。另外,我不是 100% 同意清理应该是程序员的工作。例如,标准流不会清除无效输入。此外,如果您要在存在无效输入时转到clear() 流状态,那么用户如何知道他是否首先输入了无效输入?
  • @dabadaba 我想您可以缓存流状态,进行清理,然后在流中重置流状态。不过那会很好。
  • 他会知道他输入了一个无效的输入,因为抛出了异常,即使你说这些方法不应该抛出任何异常
猜你喜欢
  • 1970-01-01
  • 2021-01-26
  • 1970-01-01
  • 2015-01-25
  • 2021-12-28
  • 2013-06-10
  • 2020-10-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多