How to determine if a string is a number with C++?

C++Visual C++

C++ Problem Overview


I've had quite a bit of trouble trying to write a function that checks if a string is a number. For a game I am writing I just need to check if a line from the file I am reading is a number or not (I will know if it is a parameter this way). I wrote the below function which I believe was working smoothly (or I accidentally edited to stop it or I'm schizophrenic or Windows is schizophrenic):

bool isParam (string line)
{
	if (isdigit(atoi(line.c_str())))
        return true;

	return false;
}

C++ Solutions


Solution 1 - C++

The most efficient way would be just to iterate over the string until you find a non-digit character. If there are any non-digit characters, you can consider the string not a number.

bool is_number(const std::string& s)
{
	std::string::const_iterator it = s.begin();
	while (it != s.end() && std::isdigit(*it)) ++it;
	return !s.empty() && it == s.end();
}

Or if you want to do it the C++11 way:

bool is_number(const std::string& s)
{
	return !s.empty() && std::find_if(s.begin(), 
        s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
}

As pointed out in the comments below, this only works for positive integers. If you need to detect negative integers or fractions, you should go with a more robust library-based solution. Although, adding support for negative integers is pretty trivial.

Solution 2 - C++

Why reinvent the wheel? The C standard library (available in C++ as well) has a function that does exactly this:

char* p;
long converted = strtol(s, &p, 10);
if (*p) {
    // conversion failed because the input wasn't a number
}
else {
    // use converted
}

If you want to handle fractions or scientific notation, go with strtod instead (you'll get a double result).

If you want to allow hexadecimal and octal constants in C/C++ style ("0xABC"), then make the last parameter 0 instead.

Your function then can be written as

bool isParam(string line)
{
    char* p;
    strtol(line.c_str(), &p, 10);
    return *p == 0;
}

Solution 3 - C++

With C++11 compiler, for non-negative integers I would use something like this (note the :: instead of std::):

bool is_number(const std::string &s) {
  return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit);
}

http://ideone.com/OjVJWh

Solution 4 - C++

You can do it the C++ way with boost::lexical_cast. If you really insist on not using boost you can just examine what it does and do that. It's pretty simple.

try 
{
  double x = boost::lexical_cast<double>(str); // double could be anything with >> operator.
}
catch(...) { oops, not a number }

Solution 5 - C++

I'd suggest a regex approach. A full regex-match (for example, using boost::regex) with

-?[0-9]+([\.][0-9]+)?

would show whether the string is a number or not. This includes positive and negative numbers, integer as well as decimal.

Other variations:

[0-9]+([\.][0-9]+)?

(only positive)

-?[0-9]+

(only integer)

[0-9]+

(only positive integer)

Solution 6 - C++

I just wanted to throw in this idea that uses iteration but some other code does that iteration:

#include <string.h>

bool is_number(const std::string& s)
{
    return( strspn( s.c_str(), "-.0123456789" ) == s.size() );
}

It's not robust like it should be when checking for a decimal point or minus sign since it allows there to be more than one of each and in any location. The good thing is that it's a single line of code and doesn't require a third-party library.

Take out the '.' and '-' if positive integers are all that are allowed.

Solution 7 - C++

Here's another way of doing it using the <regex> library:

bool is_integer(const std::string & s){
    return std::regex_match(s, std::regex("[(-|+)|][0-9]+"));
}

Solution 8 - C++

With this solution you can check everything from negative to positive numbers and even float numbers. When you change the type of num to integer you will get an error if the string contains a point.

#include<iostream>
#include<sstream>
using namespace std;
 
 
int main()
{
      string s;
      
      cin >> s;
 
      stringstream ss;
      ss << s;
 
      float num = 0;
 
      ss >> num;
 
      if(ss.good()) {
          cerr << "No Valid Number" << endl;
      }
      else if(num == 0 && s[0] != '0') {
          cerr << "No Valid Number" << endl;
      }
      else {
          cout << num<< endl;
      }             
}

Prove: C++ Program

Solution 9 - C++

I've found the following code to be the most robust (c++11). It catches both integers and floats.

#include <regex>
bool isNumber( std::string token )
{
	return std::regex_match( token, std::regex( ( "((\\+|-)?[[:digit:]]+)(\\.(([[:digit:]]+)?))?" ) ) );
}

Solution 10 - C++

Try this:

isNumber(const std::string &str) {    
  return !str.empty() && str.find_first_not_of("0123456789") == string::npos;
}

Solution 11 - C++

Here is a solution for checking positive integers:

bool isPositiveInteger(const std::string& s)
{
    return !s.empty() && 
           (std::count_if(s.begin(), s.end(), std::isdigit) == s.size());
}

Solution 12 - C++

Brendan this

bool isNumber(string line) 
{
    return (atoi(line.c_str())); 
}

is almost ok.

assuming any string starting with 0 is a number, Just add a check for this case

bool isNumber(const string &line) 
{
 if (line[0] == '0') return true;
 return (atoi(line.c_str()));
}

ofc "123hello" will return true like Tony D noted.

Solution 13 - C++

As it was revealed to me in an answer to my related question, I feel you should use boost::conversion::try_lexical_convert

Solution 14 - C++

A solution based on a comment by kbjorklu is:

bool isNumber(const std::string& s)
{
   return !s.empty() && s.find_first_not_of("-.0123456789") == std::string::npos;
}

As with David Rector's answer it is not robust to strings with multiple dots or minus signs, but you can remove those characters to just check for integers.


However, I am partial to a solution, based on Ben Voigt's solution, using strtod in cstdlib to look decimal values, scientific/engineering notation, hexidecimal notation (C++11), or even INF/INFINITY/NAN (C++11) is:

bool isNumberC(const std::string& s)
{
    char* p;
    strtod(s.c_str(), &p);
    return *p == 0;
}

Solution 15 - C++

The simplest I can think of in c++

bool isNumber(string s) {
    if(s.size()==0) return false;
    for(int i=0;i<s.size();i++) {
    	if((s[i]>='0' && s[i]<='9')==false) {
            return false;
        }
    }
    return true;
}

Working code sample: https://ideone.com/nRX51Y

Solution 16 - C++

My solution using C++11 regex (#include <regex>), it can be used for more precise check, like unsigned int, double etc:

static const std::regex INT_TYPE("[+-]?[0-9]+");
static const std::regex UNSIGNED_INT_TYPE("[+]?[0-9]+");
static const std::regex DOUBLE_TYPE("[+-]?[0-9]+[.]?[0-9]+");
static const std::regex UNSIGNED_DOUBLE_TYPE("[+]?[0-9]+[.]?[0-9]+");

bool isIntegerType(const std::string& str_)
{
  return std::regex_match(str_, INT_TYPE);
}

bool isUnsignedIntegerType(const std::string& str_)
{
  return std::regex_match(str_, UNSIGNED_INT_TYPE);
}

bool isDoubleType(const std::string& str_)
{
  return std::regex_match(str_, DOUBLE_TYPE);
}

bool isUnsignedDoubleType(const std::string& str_)
{
  return std::regex_match(str_, UNSIGNED_DOUBLE_TYPE);
}

You can find this code at http://ideone.com/lyDtfi, this can be easily modified to meet the requirements.

Solution 17 - C++

We may use a stringstream class.

    bool isNumeric(string str)
    {
       stringstream stream;                   
       double number;

       stream<<str;
       stream>>number;
       
       return stream.eof();
    }

   

Solution 18 - C++

Using <regex>. This code was tested!

bool isNumber(const std::string &token)
{
    return std::regex_match(token, std::regex("(\\+|-)?[0-9]*(\\.?([0-9]+))$"));
}

Solution 19 - C++

to check if a string is a number integer or floating point or so you could use :

 #include <sstream>
  
    bool isNumber(string str) {
    double d;
    istringstream is(str);
    is >> d;
    return !is.fail() && is.eof();
}

Solution 20 - C++

Try this:

bool checkDigit(string str)
{  
   int n=str.length();

   for(int i=0;    i   < n ;   i++)
   {
     if(str[i]<'0' || str[i]>'9')
       return false;
   }

   return true;
}

Solution 21 - C++

C/C++ style for unsigned integers, using range based for C++11:

int isdigits(const std::string & s)
{
    for (char c : s) if (!isdigit(c)) return (0);
    return (1);
}

Solution 22 - C++

After consulting the documentation a bit more, I came up with an answer that supports my needs, but probably won't be as helpful for others. Here it is (without the annoying return true and return false statements :-) )

bool isNumber(string line) 
{
    return (atoi(line.c_str())); 
}

Solution 23 - C++

I think this regular expression should handle almost all cases

"^(\\-|\\+)?[0-9]*(\\.[0-9]+)?"

so you can try the following function that can work with both (Unicode and ANSI)

bool IsNumber(CString Cs){
Cs.Trim();

#ifdef _UNICODE
std::wstring sr = (LPCWSTR)Cs.GetBuffer(Cs.GetLength());
return std::regex_match(sr, std::wregex(_T("^(\\-|\\+)?[0-9]*(\\.[0-9]+)?")));

#else
	std::string s = (LPCSTR)Cs.GetBuffer();
return std::regex_match(s, std::regex("^(\\-|\\+)?[0-9]*(\\.[0-9]+)?"));
#endif
}

Solution 24 - C++

include <string>

For Validating Doubles:

bool validateDouble(const std::string & input) {
int decimals = std::count(input.begin(), input.end(), '.'); // The number of decimals in the string
int negativeSigns = std::count(input.begin(), input.end(), '-'); // The number of negative signs in the string

if (input.size() == decimals + negativeSigns) // Consists of only decimals and negatives or is empty
	return false;
else if (1 < decimals || 1 < negativeSigns) // More than 1 decimal or negative sign
	return false;
else if (1 == negativeSigns && input[0] != '-') // The negative sign (if there is one) is not the first character
	return false;
else if (strspn(input.c_str(), "-.0123456789") != input.size()) // The string contains a character that isn't in "-.0123456789"
	return false;
return true;

}

For Validating Ints (With Negatives)

bool validateInt(const std::string & input) {
int negativeSigns = std::count(input.begin(), input.end(), '-'); // The number of negative signs in the string

if (input.size() == negativeSigns) // Consists of only negatives or is empty
	return false;
else if (1 < negativeSigns) // More than 1 negative sign
	return false;
else if (1 == negativeSigns && input[0] != '-') // The negative sign (if there is one) is not the first character
	return false;
else if (strspn(input.c_str(), "-0123456789") != input.size()) // The string contains a character that isn't in "-0123456789"
	return false;
return true;

}

For Validating Unsigned Ints

bool validateUnsignedInt(const std::string & input) {
return (input.size() != 0 && strspn(input.c_str(), "0123456789") == input.size()); // The string is not empty and contains characters only in "0123456789"

}

Solution 25 - C++

bool isNumeric(string s){
	if ( !s.empty() && s[0] != '-' )
		s = "0" + s; //prepend 0
	
	string garbage;

	stringstream ss(s);	
	ss >> *(auto_ptr<double>(new double)) >> garbage;
/*
//the line above extracts the number into an anonymous variable. it could also be done like this:
double x;
ss >> x >> garbage;
*/
	//if there is no garbage return true or else return false
	return garbage.empty(); 
}

how it works: the stringstream >> overload can convert strings to various arithmetic types it does this by reading characters sequentially from the stringstream (ss in this case) until it runs out of characters OR the next character does not meet the criteria to be stored into the destination variable type.

example1:

stringstream ss("11");
double my_number;
ss >> my_number; //my number = 11

example2:

stringstream ss("011");
double my_number;
ss >> my_number; //my number = 11

example3:

stringstream ss("11ABCD");
double my_number;
ss >> my_number; //my number = 11 (even though there are letters after the 11)

the "garbage" variable explanation":

why not just check if extraction into my double has a valid value and then return true if it does?

notice example3 above will still successfully read the number 11 into the my_number variable even if the input string is "11ABCD" (which is not a number).

to handle this case we can do another extraction into a string variable(which I named garbage) which can read anything that may have been left over in the string buffer after the initial extraction into the variable of type double. If anything is left over it will be read into "garbage" which means the full string passed in was not a number (it just begins with one). in this which case we'd want to return false;

the prepended "0" explanation":

attempting to extract a single character into a double will fail(returning 0 into our double) but will still move the string buffer position to after the character. In this case our garbage read will be empty which would cause the function to incorrectly return true. to get around this I prepended a 0 to the string so that if for example the string passed in was "a" it gets changed to "0a" so that the 0 will be extracted into the double and "a" gets extracted into garbage.

prepending a 0 will not affect the value of the number so the number will still be correctly extracted into our double variable.

Solution 26 - C++

Yet another answer, that uses stold (though you could also use stof/stod if you don't require the precision).

bool isNumeric(const std::string& string)
{
    std::size_t pos;
    long double value = 0.0;

    try
    {
        value = std::stold(string, &pos);
    }
    catch(std::invalid_argument&)
    {
        return false;
    }
    catch(std::out_of_range&)
    {
        return false;
    }

    return pos == string.size() && !std::isnan(value);
}

Solution 27 - C++

bool is_number(const string& s, bool is_signed)
{
	if (s.empty()) 
        return false;

    auto it_begin = s.begin();
	if (is_signed && (s.front() == '+' || s.front() == '-'))
        ++it_begin;

	auto non_digit = std::find_if(it_begin, s.end(), [](const char& c) { return !std::isdigit(c); });
	return non_digit == s.end();
}

Solution 28 - C++

The following regex-based function supports both signed integer literals and decimal literals in standard and scientific notation (e.g. 42, 3.14, -1, +58., 4e2, 1.e-2, -12.34e-56, .1E4). Integers prefixed with zeros are also matched (e.g. 0001):

#include <string_view>
#include <regex>
 
bool is_number(std::string_view s) {
  static std::regex const re{
      R"([-+]?((\.\d+)|(\d+\.)|(\d+))\d*([eE][-+]?\d+)?)"};
  return std::regex_match(s.data(), re);
}

Hexadecimal literals, binary literals, single-quote separators and suffixes (f, F, l, L, u, U, ll, LL, Z) are not matched.

Below are some unit tests using gtest. The complete code is available at https://godbolt.org/z/Y56qqz1ET

TEST(IsNumber, True) {
  char const *tests[]{"42",     "3.14",    "-0",   "+4",    ".3",
                      "+.5",    "-.23",    "7.",   "1e2",   "1.e2",
                      "1.0e-2", "8.e+09",  "2E34", "61e2",  "-0e1",
                      "+0E+10", "-.01E-5", "07",   "+01E1", "12.34"};
  for (auto const &x : tests) {
    EXPECT_TRUE(is_number(x));
  }
}

TEST(IsNumber, False) {
  char const *tests[]{"4e",      "xyz",    ".3.14",   "--0",   "2-4",
                      "..3",     ".+5",    "7 2",     "1f",    "1.0f",
                      "1e-2.0",  "8e+0e1", "2E.4",    "a",     "e15",
                      "-0e10.3", ".e2",    "+1.2E0e", "1.2+3", "e1"};
  for (auto const &x : tests) {
    EXPECT_FALSE(is_number(x));
  }
}

Solution 29 - C++

Few months ago, I implemented a way to determine if any string is integer, hexadecimal or double.

enum{
		STRING_IS_INVALID_NUMBER=0,
		STRING_IS_HEXA,
		STRING_IS_INT,
		STRING_IS_DOUBLE
};

bool isDigit(char c){
	return (('0' <= c) && (c<='9'));
}

bool isHexaDigit(char c){
	return ((('0' <= c) && (c<='9')) || ((tolower(c)<='a')&&(tolower(c)<='f')));
}


char *ADVANCE_DIGITS(char *aux_p){

	while(CString::isDigit(*aux_p))	aux_p++;
	return aux_p;
}

char *ADVANCE_HEXADIGITS(char *aux_p){

	while(CString::isHexaDigit(*aux_p))	aux_p++;
	return aux_p;
}


int isNumber(const string & test_str_number){
	bool isHexa=false;
	char *str = (char *)test_str_number.c_str();

	switch(*str){
	case '-': str++; // is negative number ...
	           break;
	case '0': 
			  if(tolower(*str+1)=='x')  {
				  isHexa = true;
				  str+=2;
			  }
			  break;
	default:
			break;
	};

	char *start_str = str; // saves start position...
	if(isHexa) { // candidate to hexa ...
		str = ADVANCE_HEXADIGITS(str);
		if(str == start_str)
			return STRING_IS_INVALID_NUMBER;

		if(*str == ' ' || *str == 0) 
            return STRING_IS_HEXA;

	}else{ // test if integer or float
		str = ADVANCE_DIGITS(str);
		if(*str=='.') { // is candidate to double
			str++;
			str = ADVANCE_DIGITS(str);
			if(*str == ' ' || *str == 0)
				return STRING_IS_DOUBLE;

			return STRING_IS_INVALID_NUMBER;
		}

		if(*str == ' ' || *str == 0)
			return STRING_IS_INT;

	}

	return STRING_IS_INVALID_NUMBER;


}

Then in your program you can easily convert the number in function its type if you do the following,

string val; // the string to check if number...

switch(isNumber(val)){
   case STRING_IS_HEXA: 
   // use strtol(val.c_str(), NULL, 16); to convert it into conventional hexadecimal
   break;
   case STRING_IS_INT: 
   // use (int)strtol(val.c_str(), NULL, 10); to convert it into conventional integer
   break;
   case STRING_IS_DOUBLE:
   // use atof(val.c_str()); to convert it into conventional float/double
   break;
}

You can realise that the function will return a 0 if the number wasn't detected. The 0 it can be treated as false (like boolean).

Solution 30 - C++

I propose a simple convention:

If conversion to ASCII is > 0 or it starts with 0 then it is a number. It is not perfect but fast.

Something like this:

string token0;

if (atoi(token0.c_str())>0 || isdigit(token0.c_str()[0]) ) { //this is a value
    // do what you need to do...
}

Solution 31 - C++

This function takes care of all the possible cases:

bool AppUtilities::checkStringIsNumber(std::string s){
    //Eliminate obvious irritants that could spoil the party
    //Handle special cases here, e.g. return true for "+", "-", "" if they are acceptable as numbers to you
    if (s == "" || s == "." || s == "+" || s == "-" || s == "+." || s == "-.") return false;

    //Remove leading / trailing spaces **IF** they are acceptable to you
    while (s.size() > 0 && s[0] == ' ') s = s.substr(1, s.size() - 1);
    while (s.size() > 0 && s[s.size() - 1] == ' ') s = s.substr(0, s.size() - 1);


    //Remove any leading + or - sign
    if (s[0] == '+' || s[0] == '-')
        s = s.substr(1, s.size() - 1);

    //Remove decimal points
    long prevLength = s.size();

    size_t start_pos = 0;
    while((start_pos = s.find(".", start_pos)) != std::string::npos) 
        s.replace(start_pos, 1, "");

    //If the string had more than 2 decimal points, return false.
    if (prevLength > s.size() + 1) return false;

    //Check that you are left with numbers only!!
    //Courtesy selected answer by Charles Salvia above
    std::string::const_iterator it = s.begin();
    while (it != s.end() && std::isdigit(*it)) ++it;
    return !s.empty() && it == s.end();

    //Tada....
}

Solution 32 - C++

Could you simply use sscanf's return code to determine if it's an int?

bool is_number(const std::string& s)
{
    int value;
    int result = sscanf(valueStr.c_str(), "%d", &value);
    return (result != EOF && readResult != 0);
}

Solution 33 - C++

The simple and most basic way to determine if a string is a digit is by checking the first char of the string only. Then check it normally with isdigit().

string token = "99"
if(isdigit(token[0])) // CHECK FIRST CHAR OF THE STRING FOR NUMBER
        cout << token <<"\n";

Solution 34 - C++

To validate a string for a Number.

#include<bits/stdc++.h>
using namespace std;
int main()
{
    char input[100];
    gets(input);
    int l = strlen(input);
    int flag = 0;
    for(int i = 0; i<l; i++)
    {
        if(input[i] < '0' || input[i] > '9')
        {
            flag = 1;
            break;
        }
    }
    if(flag == 0)
    cout << "Input is a Number! " ;
    else
    cout << "Input is Not a Number! " ;
    return 0;
}

Solution 35 - C++

You may test if a string is convertible to integer by using boost::lexical_cast. If it throws bad_lexical_cast exception then string could not be converted, otherwise it can.

See example of such a test program below:

#include <boost/lexical_cast.hpp>
#include <iostream>

int main(int, char** argv)
{
        try
        {
                int x = boost::lexical_cast<int>(argv[1]);
                std::cout << x << " YES\n";
        }
        catch (boost::bad_lexical_cast const &)
        {
                std:: cout << "NO\n";
        }
        return 0;
}

Sample execution:

# ./a.out 12
12 YES
# ./a.out 12/3
NO

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBrendan WeinsteinView Question on Stackoverflow
Solution 1 - C++Charles SalviaView Answer on Stackoverflow
Solution 2 - C++Ben VoigtView Answer on Stackoverflow
Solution 3 - C++szxView Answer on Stackoverflow
Solution 4 - C++Edward StrangeView Answer on Stackoverflow
Solution 5 - C++MephaneView Answer on Stackoverflow
Solution 6 - C++David RectorView Answer on Stackoverflow
Solution 7 - C++mpataki14View Answer on Stackoverflow
Solution 8 - C++tzwicklView Answer on Stackoverflow
Solution 9 - C++dk123View Answer on Stackoverflow
Solution 10 - C++TomaszView Answer on Stackoverflow
Solution 11 - C++Jaime SotoView Answer on Stackoverflow
Solution 12 - C++Noam GeffenView Answer on Stackoverflow
Solution 13 - C++NoSenseEtAlView Answer on Stackoverflow
Solution 14 - C++chappjcView Answer on Stackoverflow
Solution 15 - C++Abhijit AnnaldasView Answer on Stackoverflow
Solution 16 - C++aniliitb10View Answer on Stackoverflow
Solution 17 - C++rashedcsView Answer on Stackoverflow
Solution 18 - C++Nery JrView Answer on Stackoverflow
Solution 19 - C++MuhammadKhalifaView Answer on Stackoverflow
Solution 20 - C++rrlinusView Answer on Stackoverflow
Solution 21 - C++KubatorView Answer on Stackoverflow
Solution 22 - C++Brendan WeinsteinView Answer on Stackoverflow
Solution 23 - C++MotazView Answer on Stackoverflow
Solution 24 - C++Erik NordinView Answer on Stackoverflow
Solution 25 - C++KorreyDView Answer on Stackoverflow
Solution 26 - C++Tim AngusView Answer on Stackoverflow
Solution 27 - C++shiwenwangView Answer on Stackoverflow
Solution 28 - C++hcbView Answer on Stackoverflow
Solution 29 - C++Jordi EspadaView Answer on Stackoverflow
Solution 30 - C++Gokhan UnelView Answer on Stackoverflow
Solution 31 - C++Vaibhav GuptaView Answer on Stackoverflow
Solution 32 - C++David DView Answer on Stackoverflow
Solution 33 - C++rodeone2View Answer on Stackoverflow
Solution 34 - C++AL MaMunView Answer on Stackoverflow
Solution 35 - C++Łukasz ŚlusarczykView Answer on Stackoverflow