Reputation: 29387
Or from the other way around find first non digit character.
Do the same functions apply for string and for char* ?
Upvotes: 67
Views: 134729
Reputation: 529
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.
Upvotes: 1
Reputation: 23804
#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
Upvotes: 2
Reputation: 153840
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 char
or 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
char
object 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.
Upvotes: 17
Reputation: 179867
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.
Upvotes: 6
Reputation: 18652
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
}
Upvotes: 142
Reputation: 26040
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;
}
Upvotes: 0
Reputation: 881543
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;
}
Upvotes: 5
Reputation: 54604
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")
Upvotes: 6