【问题标题】:Improving error processing for an istream helper class when using exceptions在使用异常时改进 istream 帮助程序类的错误处理
【发布时间】:2014-07-13 19:13:48
【问题描述】:

我写了一个类来控制 istream 上的强制输入,基于那里发布的原始想法:https://stackoverflow.com/a/14331519/3723423。它验证并跳过强制格式化字符,有点像 scanf(),但具有流语义:

int country; string phone;
cin >> mandatory_input(" ( + ") >> country >> mandatory_input(" ) ") >> phone;  

该类与标准 istream 操作一致,在输入不合规的情况下设置故障位,并且当且仅当设置了exceptions(istream::failbit); 时才抛出异常。

当类与异常一起使用时,我有一些关于改进错误处理的问题:

  • 备选方案 1:将错误信息放在静态成员中。这是我目前的解决方案。

  • 备选方案 2:抛出我自己的从 istream::failure 派生的异常类,其中包含有关错误条件的所有信息。那将是最优雅的解决方案。 有没有办法抛出我自己的异常并设置失败位?如果我设置了失败位,那么在我抛出自己的异常之前会抛出一个异常。但如果我不设置它,我不符合标准操作。 (编辑:如果我在设置 faibit 之前暂时停用异常,则一旦我反应异常就会抛出 std 异常,再次没有给我机会抛出自己的异常。)

    李>
  • 备选方案 3:是否可以设置设置失败位时由标准异常引发的错误代码? 不幸的是,在阅读了 std::io_errcstd::make_error_code() 之后,它是仍然不清楚如何使用我自己的错误代码使故障位异常。

这里是设置错误的代码:

...
else if ((c = is.get()) != *p) {   // input char not matching expected char
    is.putback(c);
    mandatory_input::read_error = c;  
    mandatory_input::expected = *p; 
    // <==== Here I would like to trigger my own exception or predefine error code thrown by standard exception
    is.setstate(std::ios::failbit); // stop extracting
}

【问题讨论】:

  • 可能是herehere 所写的内容有助于解决您的问题。顺便说一句,不要使用异常来提供程序逻辑。
  • @πάνταῥεῖ 感谢您的链接。但是它们似乎没有解决我的问题:我对跳过字符和控制它们是否符合预期没有任何问题。我的问题完全是关于定制标准错误处理。我将把是否使用异常的选择留给我班的客户。由于您似乎是流专家,您还有其他提示吗?
  • '看来你是流专家,...' 哇,不!走开! @Dietmar-Kühl 可能被认为是这样的专家。当然不是我 :-P ... 至于我的第二个链接,我特别指的是这个答案:stackoverflow.com/a/23070803/1413395 应该可以有一个验证提取器,它可以选择在提取失败时抛出。
  • 你说得对:我的班级遵循与此答案中提出的完全相同的原则。它只是专门用于跳过一系列指定字符而不是重新读取字段。但是,答案也没有解决错误处理。
  • 能否详细说明mandatory_input的错误处理需要“改进”的地方?

标签: c++ c++11 istream


【解决方案1】:

我非常专注于搜索 std 函数来解决这个问题,以至于我没有想到最明显的解决方案:劫持抛出的 std 异常。万一它可以帮助s.o.其他:

我首先定义了一个专用的嵌套故障类:

class mandatory_input { 
public:
...
    class failure : public std::istream::failure {
    public: 
        failure(std::error_code e);
    };
};

然后我在原来的错误处理代码中添加了以下块(见问题):

    // start of enhanced exception handling     
    if (is.exceptions() & std::istream::failbit) {  // if exception will be thrown
        try { 
            is.setstate(std::ios::failbit);
        } catch (std::istream::failure &e) {  // the failbit will trigger this
            throw mandatory_input::failure(e.code());  // and i throw my own
        } catch (std::exception &e) {   // just in case other low-level errors would be thrown 
            throw e;
        }
    } else  //======= end of enhanced exceptions handling 

现在有了这个解决方案,我的助手类中想要使用.exceptions() 的客户可以处理未区分的错误:

try { cin >> mandatory_input(" ( + ") >> country >> .... ;  
} catch (istream::failure e) {
cerr << "Input error: "<< e.code()<< " " << e.what(); 
}

或微调错误处理:

try {  ....   
} catch (mandatory_input::failure e) {
cerr << "Input format mismatch: " << mandatory_input::getexpected()
      << " was expected, but " << mandatory_input::getread_error() << " was read !\n";
} catch (istream::failure e) {
cerr << "Input error: "<< e.code()<< " " << e.what(); 
}

【讨论】:

    猜你喜欢
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2013-05-28
    • 2013-02-02
    • 2015-03-29
    • 1970-01-01
    • 2013-11-03
    相关资源
    最近更新 更多