对于少数扩展的ASCII字符,“std :: isdigit”崩溃了

时间:2017-04-10 21:13:45

标签: c++ std

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

当我尝试下面的代码时,在我的测试中,应用程序崩溃了......仔细观察后,我注意到输入字符串有特殊字符(扩展的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及更高版本。

2 个答案:

答案 0 :(得分:5)

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

  

在所有情况下,参数都是int,其值应为。{1}}   可表示为unsigned char或等于的值   宏EOF。如果参数具有任何其他值,则行为为   未定义。

C ++继承了这个限制。解决方案是将任何普通char参数转换为unsigned char(不是unsigned!),然后再将其传递给::isdigit,或者使用<locale>中的C ++语言环境感知重载。 1}}。

答案 1 :(得分:1)

在我们的服务器代码中接收电子邮件文本时,std::isspace()面临类似的崩溃。在搜索互联网时,我偶然发现了这篇文章。似乎对于所有<cctype>方法,都必须将其类型转换为unsigned char

发现了一个reference,如下所示:

与参数中的所有其他函数一样,如果std::isdigitstd::isxxx)的行为 undefined ,则该参数的值也不能表示为无符号字符也不等于EOF。为了安全地将这些函数与纯字符(或带符号的字符)一起使用,应首先将参数转换为无符号字符:
bool my_isdigit(char ch) {return std::isdigit(static_cast<unsigned char>(ch));}