【问题标题】:Error in c++: "terminate called after throwing an instance of 'std::length_error' what(): basic_string::_M_replace_aux"c++ 中的错误:“在抛出 'std::length_error'what() 的实例后调用终止:basic_string::_M_replace_aux”
【发布时间】:2020-03-16 17:37:12
【问题描述】:

我有一个简单的函数,它接受一串数字并将它们转换为浮点数,函数在下面:

float convertStrToFloatNumber (std::string n) {
    // Converts the number n to a float in the form of 000.000
    if (6 - n.length() > 0) {
        // The representation is with trailing zeros
        n.append(6 - n.length(), '0');
    }
    // Insert . at the 3. spot
    n.insert(3, ".");
    return strtof((n).c_str(), 0);
}

当我使用输入 "030000" 运行时,我如何抛出以下异常:

“在抛出 'std::length_error' what() 的实例后调用终止:basic_string_M_repalce_aux” 我真正感兴趣的是了解错误的最后一部分是什么意思。

【问题讨论】:

  • 你能给我们足够的代码来复制错误吗?我构造了一个 main,我认为它会复制错误,但它运行得非常好。
  • 请稍等,显然源文件更大(G 代码解析器)
  • 长度不是字符数吗?
  • @MartinSigNørbjerg 长度是一个无符号整数,当你“通过”零时,结果会回绕到最大值。
  • @DavidSchwartz 代码上传到 github 仓库:github.com/Collatz124/GC-TSM

标签: c++ string floating-point


【解决方案1】:

"030000" 不会出现此问题,但任何长度超过 6 个字符的字符串都会出现此问题。

std::string::length() 返回无符号类型。由于整体提升规则,6 被提升为无符号类型,并且您对无符号类型执行减法。无符号类型的下溢导致回绕,因此0 - 1u 等于std::numeric_limits<unsigned>::max()(如果unsigned 是32 位,则等于2^32 - 1 = 4294967295


你可以简单地改变条件的逻辑:

if (n.length() < 6)

或将length 转换为签名类型:

if (6 - static_cast<int>(n.length()) > 0)

【讨论】:

    【解决方案2】:

    由于n.length() 是无符号的,6 被提升为相同的无符号类型,当长度大于 6 时,减法将回绕并产生一个巨大的正数。

    最稳健(也是最短)的解决方案是完全避免减法;

    if (n.length() < 6)
    {
        n.resize(6, '0');
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-04
      • 1970-01-01
      • 1970-01-01
      • 2022-11-14
      • 1970-01-01
      相关资源
      最近更新 更多