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

时间:2021-10-14 01:42:12

Or from the other way around find first non digit character.

或者从另一种角度来看第一个非数字字符。

Do the same functions apply for string and for char* ?

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

8 个解决方案

#1


83  

Of course, there are many ways to test a string for only numeric characters. Two possible methods are:

当然,测试字符串的方法有很多,只对数字字符进行测试。两种可能的方法是:

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

or

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

#2


10  

Several people already mentioned to use isdigit(). However, note that this isn't entirely trivial because char can be signed which would cause a negative value to be passed to isdigit(). However, this function can only take positive values. That is, you want something akin to this:

有几个人已经提到使用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";
}

It seems the reasoning for the conversion to unsigned char isn't obvious. So, here are the relevant quotes from their respective standards:

看起来,转换到无符号字符的原因并不明显。因此,以下是他们各自标准的相关报价:

According to ISO/IEC 9899:2011 (or ISO/IEC 9899:1999) 7.4 paragraph 1 the following applies to the arguments of the functions from <ctype.h>:

根据ISO/ iec9899:2011(或ISO/IEC 989:1999) 7.4第1款,以下适用于 :

... 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.

…在所有情况下,参数都是int型的,其值应被表示为无符号字符,或等于宏EOF的值。如果参数具有其他值,则该行为是未定义的。

Unfortunately, the C++ standard doesn't specify that char is an unsigned type. Instead it specifies in ISO/IEC 14882:2011 3.9.1 [basic.fundamental] paragraph 1:

不幸的是,c++标准没有指定char是无符号类型。相反,它在ISO/ iec14882:2011 3.9.1 [basic。基本]段1:

... It is implementation-defined whether a char object can hold negative values. ...

…它是实现—定义一个char对象是否可以持有负值。

Clearly, a negative value cannot be represented as an unsigned char. That is, if char is using a signed type on an implementation (there are actually several which do, e.g., it is signed on MacOS using gcc or clang) there is the danger that calling any of the <ctype.h> function would cause undefined behavior.

显然,负值不能表示为无符号字符。也就是说,如果char在实现上使用已签名的类型(实际上有几个这样的类型,例如,它在使用gcc或clang的MacOS上签名),那么就有调用任何 函数会导致未定义的行为。 的危险。h>

Now, why does the conversion to unsigned char does the right things?

现在,为什么转换为无符号字符会做正确的事情呢?

According to 4.7 [conv.integral] paragraph 2:

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

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note ]

如果目标类型是未签名的,则产生的值是源整数的最小无符号整数(模2n,其中n是用于表示未签名类型的比特数)。[注意:在两个补充表示中,这个转换是概念上的,并且位模式没有变化(如果没有截断)。端注)

That is, the conversion from a [potentially] signed char to unsigned char is well-defined and causes the result to be in the permitted range for the <ctype.h> functions.

也就是说,从一个[可能]签名的字符到未签名的char的转换被定义良好,并使结果处于 功能。 的允许范围内。h>

#3


5  

isdigit(int) tells you if a character is a digit. If you are going to assume ASCII and base 10, you can also use:

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

int first_non_digit_offset= strspn(string, "0123456789")

#4


4  

In the same spirit as Misha's answer, but more correct: sscanf(buf, "%*u%*c")==1.

与Misha的答案一样,但更正确的是:sscanf(buf,“%*u%*c”)==1。

scanf returns 0 if the %d digit extraction fails, and 2 if there is anything after the digits captured by %c. And since * prevents the value from being stored, you can't even get an overflow.

如果%d的数字提取失败,那么scanf返回0,如果在%c捕获的数字后面有任何数字,则返回2。由于*阻止了存储的值,所以您甚至不能得到溢出。

#5


3  

The cctype header file has a good number of character classifications functions which you can use on each character in the string. For numeric checks, that would be isdigit.

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

The following program shows how to check each character of a C or C++ string ( the process is pretty much identical in terms of checking the actual characters, the only real difference being how to get the length):

下面的程序演示了如何检查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;
}

#6


0  

If it's a strict requirement that you can find exactly where the first non-character digit is, then you'll have to check each character. If not, I'd use either something like this:

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

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

#7


0  

#include <regex>

# include <正则表达式>

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

and

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

#8


0  

From the cplusplus.com you can use isdigit function as follow:

从cplusplus.com你可以使用isdigit函数如下:

// isdigit example (C++)
#include <iostream>       // std::cout
#include <string>         // std::string
#include <locale>         // std::locale, std::isdigit
#include <sstream>        // std::stringstream

int main ()
{
  std::locale loc;
  std::string str="1776ad";
  if (isdigit(str[0],loc))
  {
    int year;
    std::stringstream(str) >> year;
    std::cout << "The year that followed " << year << " was " << (year+1) << ".\n";
  }
  return 0;
}

Note: there is 2 types of isdigit the other version is local independent and ASCII based.

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

#1


83  

Of course, there are many ways to test a string for only numeric characters. Two possible methods are:

当然,测试字符串的方法有很多,只对数字字符进行测试。两种可能的方法是:

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

or

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

#2


10  

Several people already mentioned to use isdigit(). However, note that this isn't entirely trivial because char can be signed which would cause a negative value to be passed to isdigit(). However, this function can only take positive values. That is, you want something akin to this:

有几个人已经提到使用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";
}

It seems the reasoning for the conversion to unsigned char isn't obvious. So, here are the relevant quotes from their respective standards:

看起来,转换到无符号字符的原因并不明显。因此,以下是他们各自标准的相关报价:

According to ISO/IEC 9899:2011 (or ISO/IEC 9899:1999) 7.4 paragraph 1 the following applies to the arguments of the functions from <ctype.h>:

根据ISO/ iec9899:2011(或ISO/IEC 989:1999) 7.4第1款,以下适用于 :

... 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.

…在所有情况下,参数都是int型的,其值应被表示为无符号字符,或等于宏EOF的值。如果参数具有其他值,则该行为是未定义的。

Unfortunately, the C++ standard doesn't specify that char is an unsigned type. Instead it specifies in ISO/IEC 14882:2011 3.9.1 [basic.fundamental] paragraph 1:

不幸的是,c++标准没有指定char是无符号类型。相反,它在ISO/ iec14882:2011 3.9.1 [basic。基本]段1:

... It is implementation-defined whether a char object can hold negative values. ...

…它是实现—定义一个char对象是否可以持有负值。

Clearly, a negative value cannot be represented as an unsigned char. That is, if char is using a signed type on an implementation (there are actually several which do, e.g., it is signed on MacOS using gcc or clang) there is the danger that calling any of the <ctype.h> function would cause undefined behavior.

显然,负值不能表示为无符号字符。也就是说,如果char在实现上使用已签名的类型(实际上有几个这样的类型,例如,它在使用gcc或clang的MacOS上签名),那么就有调用任何 函数会导致未定义的行为。 的危险。h>

Now, why does the conversion to unsigned char does the right things?

现在,为什么转换为无符号字符会做正确的事情呢?

According to 4.7 [conv.integral] paragraph 2:

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

If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note ]

如果目标类型是未签名的,则产生的值是源整数的最小无符号整数(模2n,其中n是用于表示未签名类型的比特数)。[注意:在两个补充表示中,这个转换是概念上的,并且位模式没有变化(如果没有截断)。端注)

That is, the conversion from a [potentially] signed char to unsigned char is well-defined and causes the result to be in the permitted range for the <ctype.h> functions.

也就是说,从一个[可能]签名的字符到未签名的char的转换被定义良好,并使结果处于 功能。 的允许范围内。h>

#3


5  

isdigit(int) tells you if a character is a digit. If you are going to assume ASCII and base 10, you can also use:

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

int first_non_digit_offset= strspn(string, "0123456789")

#4


4  

In the same spirit as Misha's answer, but more correct: sscanf(buf, "%*u%*c")==1.

与Misha的答案一样,但更正确的是:sscanf(buf,“%*u%*c”)==1。

scanf returns 0 if the %d digit extraction fails, and 2 if there is anything after the digits captured by %c. And since * prevents the value from being stored, you can't even get an overflow.

如果%d的数字提取失败,那么scanf返回0,如果在%c捕获的数字后面有任何数字,则返回2。由于*阻止了存储的值,所以您甚至不能得到溢出。

#5


3  

The cctype header file has a good number of character classifications functions which you can use on each character in the string. For numeric checks, that would be isdigit.

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

The following program shows how to check each character of a C or C++ string ( the process is pretty much identical in terms of checking the actual characters, the only real difference being how to get the length):

下面的程序演示了如何检查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;
}

#6


0  

If it's a strict requirement that you can find exactly where the first non-character digit is, then you'll have to check each character. If not, I'd use either something like this:

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

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

#7


0  

#include <regex>

# include <正则表达式>

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

and

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

#8


0  

From the cplusplus.com you can use isdigit function as follow:

从cplusplus.com你可以使用isdigit函数如下:

// isdigit example (C++)
#include <iostream>       // std::cout
#include <string>         // std::string
#include <locale>         // std::locale, std::isdigit
#include <sstream>        // std::stringstream

int main ()
{
  std::locale loc;
  std::string str="1776ad";
  if (isdigit(str[0],loc))
  {
    int year;
    std::stringstream(str) >> year;
    std::cout << "The year that followed " << year << " was " << (year+1) << ".\n";
  }
  return 0;
}

Note: there is 2 types of isdigit the other version is local independent and ASCII based.

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