Ошибка отладочного утверждения при сравнении юникода с использованием isdigit - PullRequest
1 голос
/ 21 февраля 2020

У меня ошибка подтверждения отладки в if statement, когда i = 7:

Expression: c>= -1 && c <= 255

Это мой код:

#include <iostream>
#include <string>

const char* clearString(std::string str)
{
    for (int i = str.length() - 1; i >= 0; i--)
    {
        if (  !isdigit(str[i])
            && str[i] != ',')
        {
            str.erase(i, 1);
        }
    }
    return str.c_str();
}

int main()
{
    std::string str = "688,13 €";

    std::cout << clearString(str);
}

Я пытаюсь удалить все символы в строка, которая не является числом и ','.

Ответы [ 3 ]

1 голос
/ 21 февраля 2020

Функция isdigit() работает только с символами, у которых их десятичное значение находится в диапазоне от -1 до 255.

Десятичное значение символа равно -128, которое функция не поддерживает.

Я бы предложил изменить сравнение вместо использования isdigit(), сравните десятичные значения символов.

Измените свою функцию следующим образом:

const char* clearString(std::string& str)
{
    for (int i = str.length() - 1; i >= 0; i--)
    {
        if ((str[i] < '0' || str[i] > '9') && str[i] != ',')
        {
            str.erase(i, 1);
        }
    }
    return str.c_str();
}
1 голос
/ 21 февраля 2020

Немного о топи c, о вашем алгоритме.

Было бы лучше, если бы вы не стирали каждый не-ди git символ, а смещали свои символы влево, пропуская все не -digits (кроме ',') и изменить размер строки.

О isdigit Я бы сделал так, как предложил 0xBlackMirror, сравнив с '0' и '9'.

Вот код:

const char* clearString(std::string str)
{
    int j = 0;
    for (uint i = 0; i < str.size(); i++)
    {
        if ((str[i] >= '0' && str[i] <= '9') || str[i] == ',')
        {
            str[j++] = str[i];
        }
    }
    str.resize(j);
    return str.c_str();
}
1 голос
/ 21 февраля 2020

Для std::isdigit см. Раздел Примечания о том, почему вы получаете утверждение.

Исправление - привести к unsigned char:

if (!isdigit(static_cast<unsigned char>(str[i]))

Во-вторых, ваша функция возвращает локальный временный адрес, поэтому демонстрирует неопределенное поведение. Вместо этого верните std::string.

std::string clearString(std::string str)
{
   //…
   return str;
}

В-третьих, вы можете переписать свою функцию, используя std::remove_if и std::string::erase, вместо того, чтобы писать al oop, который удаляет символ за раз.

#include <algorithm>
//...
std::string clearString(std::string str)
{
    auto iter = std::remove_if(str.begin(), str.end(),
          [&](char ch) 
         { return !isdigit(static_cast<unsigned char>(ch)) && ch != ',';});
    str.erase(iter, str.end());
    return str;
}
...