验证输入参数

时间:2017-02-09 09:26:14

标签: c++ exception testing design-by-contract

我试图决定是否应该在我的一些代码中使用异常,断言或边界检查。

该程序包含许多依赖于用户输入的计算。该程序在嵌入式系统上运行。

以下代码是一个典型示例。参数weight_percent_salt显然不应为负数,且不应超过100。

float Conductivity(const float weight_percent_salt)
{

    float sigma_20C = 0.0;

    if(weight_percent_salt > 16.2)
    {
        sigma_20C = 19.4;
    }
    else
    {   
        sigma_20C = 2.0487 * weight_percent_salt - 0.2352 * pow(weight_percent_salt,2) + 0.0187 * pow(weight_percent_salt,3);
    }

    return sigma_20C;   

}

在这种特殊情况下,我可以将用户输入限制在0 - 100%之间并保持代码不变,但其他功能不直接依赖于用户输入,而是其他计算的结果。

在这些类型的函数中处理错误输入参数的最佳方法是什么?

2 个答案:

答案 0 :(得分:0)

请勿对您的班级用户强制例外,而是允许他们这样做。

  • 提供validWeightValue(x)函数,如果truex的有效值,则返回weight_percent_salt

  • Conductivity假设weight_percent_salt作为合同的一部分有效。

bool isValidWeightPercentSalt(const float x) noexcept
{
    return x >= 0.f && x <= 100.f;
}

float Conductivity(const float weight_percent_salt)
{
    assert(isValidWeightPercentSalt(weight_percent_salt));
    // ...
}

用户现在可以使用isValidWeightPercentSalt来验证输入并抛出异常。用户知道Conductivity假定其参数满足isValidWeightPercentSalt谓词。

float calculateConductivityViaUserInput()
{
    float percent;
    std::cin >> percent;

    if(!isValidWeightPercentSalt(percent))
    {
        throw InvalidPercentUserInput{percent};
    }

    return Conductivity(percent);
}

请注意,我不喜欢异常 - 如果您的设计允许,请返回 monadic错误处理类,如std::optionalstd::variant或{{1}而不是抛出异常。或者,如果您没有与错误条件相关联的任何额外状态,请考虑使用boost::expected 返回代码

答案 1 :(得分:0)

断言:   这些通常仅针对调试版本启用,并将导致崩溃。由于它们通常对发布版本禁用,因此您可能需要跟进另一种引发错误的机制;因为他们的主要任务是向开发人员表明程序的状态是开发人员认为不可能的状态。 显然,对于用户输入,一切皆有可能,这不是一个合适的选择。

(差不多)还有别的:   是为调试和发布版本完成的;因此,对于用户输入的地方,更为可取。什么是&#39;其他什么&#39;是,取决于你打算如何处理失败,这在很大程度上是一个意见问题。

那就是说,例外应该是特殊的&#39;因为它们不仅不经常发生;这可能不适用于用户输入解析。