或者从另一方面找到第一个非数字字符。
相同的函数是否适用于字符串和char *?
答案 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是用于表示无符号类型的位数)。 [注意:在二进制补码表示中,此转换是概念性的,并且位模式没有变化(如果没有截断)。 - 后注]
也就是说,从[可能]签名的char
到unsigned 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)
答案 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