Or from the other way around find first non digit character.
Do the same functions apply for string and for char* ?
Or from the other way around find first non digit character.
Do the same functions apply for string and for char* ?
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
}
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:
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>:
... In all cases the argument is an
int, the value of which shall be representable as anunsigned charor shall equal the value of the macroEOF. If the argument has any other value, the behavior is undefined.
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:
... It is implementation-defined whether a
charobject can hold negative values. ...
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.
Now, why does the conversion to unsigned char does the right things?
According to 4.7 [conv.integral] paragraph 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 ]
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.
isdigit(int) tells you if a character is a digit. If you are going to assume ASCII and base 10, you can also use:
int first_non_digit_offset= strspn(string, "0123456789")
In the same spirit as Misha's answer, but more correct: 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.
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.
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):
#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;
}
#include <regex>
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
From the cplusplus.com you can use isdigit function as follow:
// 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.
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;
}