使用 isdigit 比较 unicode 时调试断言失败错误

Debug Assertion Failed error while comparing unicode using isdigit

i = 7:

时,我在 if statement 中遇到调试断言错误
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);
}

我尝试删除字符串中所有非数字和','的字符。

对于 std::isdigit,请参阅 Notes section 以了解您得到断言的原因。

解决方法是转换为 unsigned char:

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

其次,您的函数 returns 本地临时地址,因此表现出未定义的行为。 Return 改为 std::string

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

第三,您可以使用 std::remove_ifstd::string::erase 重写您的函数,而不是编写一次删除一个字符的循环。

#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;
}

函数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();
}

有点跑题了,关于你的算法。

最好不要删除每个非数字字符,而是将字符向左移动,跳过所有非数字(',' 除外)并调整字符串大小。

关于 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();
}