如何检查给定的c + +string或字符*只包含数字?
或者从相反的方向find第一个非数字字符。
相同的函数是否适用于string和char *?
当然,有很多方法只用数字字符来testing一个string。 两种可能的方法是:
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 }
有几个人已经提到要使用isdigit()
。 但是请注意,这并不是微不足道的,因为可以对char
进行签名,从而将负值传递给isdigit()
。 但是,这个function只能取正值。 也就是说,你想要类似这样的东西:
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
或者等于macrosEOF
的值。 如果参数具有任何其他值,则行为是未定义的。
不幸的是,C ++标准没有指定char
是一个无符号types。 相反,它在ISO / IEC 14882:2011中规定3.9.1 [basic.fundamental]第1段:
…实现定义
char
对象是否可以保存负值。 …
显然,负值不能表示为unsigned char
。 也就是说,如果char
在一个实现上使用签名types(实际上有几个这样做,例如,它使用gcc或clang在MacOS上签名),那么调用任何<ctype.h>
函数都会导致未定义的行为。
现在,为什么转换为unsigned char
做正确的事情?
根据4.7 [conv.integral]第2段:
如果目标types是无符号的,则结果值是与源整数相等的最小无符号整数(模2 n ,其中n是用于表示无符号types的位数)。 [注意:在二进制补码表示中,这种转换是概念性的,位模式没有变化(如果没有截断)。 – 注意]
也就是说,从[可能]有符号char
到unsigned char
是很好定义的,并且使得结果在<ctype.h>
函数的允许范围内。
isdigit(int)
告诉你一个字符是否是一个数字。 如果你要假设ASCII和10,你也可以使用:
int first_non_digit_offset= strspn(string, "0123456789")
正如Misha的回答一样,但更正确的是: sscanf(buf, "%*u%*c")==1
。
如果%d
数字提取失败,则scanf
返回0,如果%c
捕获的数字之后有scanf
返回2。 由于*
阻止了存储的值,所以甚至无法获得溢出。
cctype
头文件有很多字符分类函数,可以在string中的每个字符上使用。 对于数字检查,这将是isdigit
。
以下程序显示了如何检查C或C ++string的每个字符(在检查实际字符方面,这个过程几乎完全相同,唯一的区别是如何获得长度):
#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; }
如果这是一个严格的要求,你可以find第一个非字符数字的确切位置,那么你将不得不检查每个字符。 如果没有,我会使用这样的东西:
unsigned safe_atoi(const std::string& a) { std::stringstream s(a); unsigned b; s >> b; return b; }
#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
从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; }
注意:isdigit有两种types,其他版本是本地独立的和基于ASCII的。