"std::isdigit" 因几个扩展 ASCII 字符而崩溃

"std::isdigit" is crashing for few extended ASCII Chars

由于一些需要,我需要遍历一个字符串,看看字符串中是否存在任何数字。

当我尝试下面的代码时,在我的测试过程中,应用程序崩溃了。仔细观察后,我注意到输入的字符串有特殊字符(扩展的 ASCII 字符)。

#include <iostream>
#include <string>
#include <algorithm>

int main()
{
    std::string wordstr("tes¶¶"); //
    //int num  = unsigned char('¶'); // ASCII 182 (DEC)
    //int num1  = unsigned char('T'); // ASCII 84 (DEC)
    std::find_if(wordstr.begin(), wordstr.end(), ::isdigit) != wordstr.end();  
    return 0;
}

为什么 std::isdigit 会因扩展 ASCII 值而崩溃? (尝试了几个)。

是否有任何替代标准函数来查找字符是否为数字,如果我的输入字符串中有特殊字符,它不会崩溃?

注意:由于此代码库的维护问题,我不应该使用 C++11 及更高版本。

<ctype.h> 分类函数名义上接受 int,但输入值必须可表示为 unsigned char 或特殊值 EOF。所有其他输入都会导致未定义的行为。 C11 §7.4p1:

In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. If the argument has any other value, the behavior is undefined.

C++继承了这个限制。解决方案是在将任何普通 char 参数传递给 ::isdigit 之前将其转换为 unsigned char(而不是 unsigned!),或者在 [=] 中使用 C++ 语言环境感知重载21=].

在我们的服务器代码中接收电子邮件文本时,我遇到了 std::isspace() 的类似崩溃。在互联网上搜索时,我偶然发现了这个 post。似乎对于所有 <cctype> 方法,都必须强制转换为 unsigned char.

找到 reference 如下:

Like all other functions from , the behavior of std::isdigit (std::isxxx) is undefined if the argument's value is neither representable as unsigned char nor equal to EOF. To use these functions safely with plain chars (or signed chars), the argument should first be converted to unsigned char:
bool my_isdigit(char ch) {return std::isdigit(static_cast<unsigned char>(ch));}