Ошибка в c ++: «завершить вызов после выброса экземпляра 'std :: length_error' what (): basic_string :: _ M_replace_aux" - PullRequest
0 голосов
/ 16 марта 2020

У меня есть простая функция, которая берет строку цифр и превращает их в число с плавающей запятой, функция под ним:

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", что меня действительно интересует, так это понимание того, что означает последняя часть ошибки.

Ответы [ 2 ]

3 голосов
/ 16 марта 2020

Проблема не возникает для "030000", но для любой строки длиной более 6 символов.

std::string::length() возвращает тип без знака. Благодаря встроенным правилам повышения, 6 повышается до типа без знака, и вы выполняете вычитание для типов без знака. Недостаток на типах без знака приводит к переносу, поэтому 0 - 1u равно std::numeric_limits<unsigned>::max() (если unsigned 32-битное значение, то оно равно 2^32 - 1 = 4294967295)


You можно просто изменить лог c условия:

if (n.length() < 6)

или привести length к типу со знаком:

if (6 - static_cast<int>(n.length()) > 0)
0 голосов
/ 16 марта 2020

Поскольку n.length() является беззнаковым, 6 переводится в тот же тип без знака, и когда длина больше шести, вычитание будет округлено и даст огромное положительное число.

Самый надежный (и самое короткое) решение состоит в том, чтобы полностью избежать вычитания;

if (n.length() < 6)
{
    n.resize(6, '0');
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...