如何检查给定的c ++字符串或char *是否只包含数字?

时间:2012-01-17 01:47:32

标签: c++ string pattern-matching

或者从另一方面找到第一个非数字字符。

相同的函数是否适用于字符串和char *?

8 个答案:

答案 0 :(得分:92)

当然,有许多方法可以仅为数字字符测试字符串。两种可能的方法是:

bool is_digits(const std::string &str)
{
    return str.find_first_not_of("0123456789") == std::string::npos;
}

bool is_digits(const std::string &str)
{
    return std::all_of(str.begin(), str.end(), ::isdigit); // C++11
}

答案 1 :(得分:12)

有几个人已经提到使用isdigit()。但请注意,这并非完全无关紧要,因为char可以签名,这会导致负值传递给isdigit()。但是,此功能只能采用正值。也就是说,你想要类似于此的东西:

if (s.end() == std::find_if(s.begin(), s.end(),
    [](unsigned char c)->bool { return !isdigit(c); })) {
    std::cout << "string '" << s << "' contains only digits\n";
}

似乎转换为unsigned char的原因并不明显。因此,以下是各自标准的相关引用:

根据ISO / IEC 9899:2011(或ISO / IEC 9899:1999)7.4第1段,以下内容适用于<ctype.h>的函数论据:

  

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

不幸的是,C ++标准没有指定char是无符号类型。相反,它在ISO / IEC 14882:2011 3.9.1 [basic.fundamental]第1段中指定:

  

...实现定义了unsigned char对象是否可以保存负值。 ...

显然,负值不能表示为char。也就是说,如果<ctype.h>在实现上使用了签名类型(实际上有几个使用gcc或clang在MacOS上签名),则存在调用{{1}中的任何一个的危险函数会导致未定义的行为。

现在,为什么转换为unsigned char会做正确的事情?

根据4.7 [conv.integral]第2段:

  

如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模2 n ,其中n是用于表示无符号类型的位数)。 [注意:在二进制补码表示中,此转换是概念性的,并且位模式没有变化(如果没有截断)。 - 后注]

也就是说,从[可能]签名的charunsigned char的转换定义明确,并导致结果在<ctype.h>函数的允许范围内。

答案 2 :(得分:5)

isdigit(int)告诉您字符是否为数字。如果您要假设ASCII和基数为10,您还可以使用:

int first_non_digit_offset= strspn(string, "0123456789")

答案 3 :(得分:4)

与Misha的回答一样,但更正确:sscanf(buf, "%*u%*c")==1

如果scanf数字提取失败,则

%d返回0;如果%c捕获的数字后面有任何内容,则返回2。由于*会阻止存储该值,因此您甚至无法获得溢出。

答案 4 :(得分:3)

cctype头文件具有大量字符分类函数,您可以在字符串中的每个字符上使用这些函数。对于数字检查,这将是isdigit

以下程序显示了如何检查C或C ++字符串的每个字符(在检查实际字符方面,该过程几乎相同,唯一真正的区别在于如何获取长度):

#include <iostream>
#include <cstring>
#include <cctype>
int main (void) {
    const char *xyzzy = "42x";
    std::cout << xyzzy << '\n';
    for (int i = 0; i < std::strlen (xyzzy); i++) {
        if (! std::isdigit (xyzzy[i])) {
            std::cout << xyzzy[i] << " is not numeric.\n";
        }
    }

    std::string plugh ("3141y59");
    std::cout << plugh << '\n';
    for (int i = 0; i < plugh.length(); i++) {
        if (! std::isdigit (plugh[i])) {
            std::cout << plugh[i] << " is not numeric.\n";
        }
    }

    return 0;
}

答案 5 :(得分:1)

cplusplus.com您可以使用isdigit函数,如下所示:

sample(DATA[,1:15],1)

注意:有两种类型的isdigit,另一种版本是本地独立的和基于ASCII的。

答案 6 :(得分:0)

如果严格要求您可以找到第一个非字符数字的确切位置,那么您必须检查每个字符。如果没有,我会使用这样的东西:

unsigned safe_atoi(const std::string& a)
{
    std::stringstream s(a);
    unsigned b;
    s >> b;
    return b;
}

答案 7 :(得分:0)

#include <regex>

std::string string( "I only have 3 dollars!" );
std::cout << std::regex_search( string, std::regex( "\\d+" ) ); // true

std::string string( "I only have three dollars!" );
std::cout << std::regex_search( string, std::regex( "\\d+" ) ); // false