How do I check if a C++ string is an int?

北战南征 提交于 2019-11-26 03:35:48

问题


When I use getline, I would input a bunch of strings or numbers, but I only want the while loop to output the \"word\" if it is not a number. So is there any way to check if \"word\" is a number or not? I know I could use atoi() for C-strings but how about for strings of the string class?

int main () {
  stringstream ss (stringstream::in | stringstream::out);
  string word;
  string str;
  getline(cin,str);
  ss<<str;
  while(ss>>word)
    {
      //if(    )
        cout<<word<<endl;
    }
}

回答1:


Another version...

Use strtol, wrapping it inside a simple function to hide its complexity :

inline bool isInteger(const std::string & s)
{
   if(s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false;

   char * p;
   strtol(s.c_str(), &p, 10);

   return (*p == 0);
}

Why strtol ?

As far as I love C++, sometimes the C API is the best answer as far as I am concerned:

  • using exceptions is overkill for a test that is authorized to fail
  • the temporary stream object creation by the lexical cast is overkill and over-inefficient when the C standard library has a little known dedicated function that does the job.

How does it work ?

strtol seems quite raw at first glance, so an explanation will make the code simpler to read :

strtol will parse the string, stopping at the first character that cannot be considered part of an integer. If you provide p (as I did above), it sets p right at this first non-integer character.

My reasoning is that if p is not set to the end of the string (the 0 character), then there is a non-integer character in the string s, meaning s is not a correct integer.

The first tests are there to eliminate corner cases (leading spaces, empty string, etc.).

This function should be, of course, customized to your needs (are leading spaces an error? etc.).

Sources :

See the description of strtol at: http://en.cppreference.com/w/cpp/string/byte/strtol.

See, too, the description of strtol's sister functions (strtod, strtoul, etc.).




回答2:


The accepted answer will give a false positive if the input is a number plus text, because "stol" will convert the firsts digits and ignore the rest.

I like the following version the most, since it's a nice one-liner that doesn't need to define a function and you can just copy and paste wherever you need it.

#include <string>

...

std::string s;

bool has_only_digits = (s.find_first_not_of( "0123456789" ) == std::string::npos);

EDIT: if you like this implementation but you do want to use it as a function, then this should do:

bool has_only_digits(const string s){
  return s.find_first_not_of( "0123456789" ) == string::npos;
}



回答3:


You might try boost::lexical_cast. It throws an bad_lexical_cast exception if it fails.

In your case:

int number;
try
{
  number = boost::lexical_cast<int>(word);
}
catch(boost::bad_lexical_cast& e)
{
  std::cout << word << "isn't a number" << std::endl;
}



回答4:


If you're just checking if word is a number, that's not too hard:

#include <ctype.h>

...

string word;
bool isNumber = true;
for(string::const_iterator k = word.begin(); k != word.end(); ++k)
    isNumber &&= isdigit(*k);

Optimize as desired.




回答5:


Use the all-powerful C stdio/string functions:

int dummy_int;
int scan_value = std::sscanf( some_string.c_str(), "%d", &dummy_int);

if (scan_value == 0)
    // does not start with integer
else
    // starts with integer



回答6:


You can use boost::lexical_cast, as suggested, but if you have any prior knowledge about the strings (i.e. that if a string contains an integer literal it won't have any leading space, or that integers are never written with exponents), then rolling your own function should be both more efficient, and not particularly difficult.




回答7:


Ok, the way I see it you have 3 options.

1: If you simply wish to check whether the number is an integer, and don't care about converting it, but simply wish to keep it as a string and don't care about potential overflows, checking whether it matches a regex for an integer would be ideal here.

2: You can use boost::lexical_cast and then catch a potential boost::bad_lexical_cast exception to see if the conversion failed. This would work well if you can use boost and if failing the conversion is an exceptional condition.

3: Roll your own function similar to lexical_cast that checks the conversion and returns true/false depending on whether it's successful or not. This would work in case 1 & 2 doesn't fit your requirements.




回答8:


template <typename T>
const T to(const string& sval)
{
        T val;
        stringstream ss;
        ss << sval;
        ss >> val;
        if(ss.fail())
                throw runtime_error((string)typeid(T).name() + " type wanted: " + sval);
        return val;
}

And then you can use it like that:

double d = to<double>("4.3");

or

int i = to<int>("4123");



回答9:


I have modified paercebal's method to meet my needs:

typedef std::string String;    

bool isInt(const String& s, int base){
   if(s.empty() || std::isspace(s[0])) return false ;
   char * p ;
   strtol(s.c_str(), &p, base) ;
   return (*p == 0) ;
}


bool isPositiveInt(const String& s, int base){
   if(s.empty() || std::isspace(s[0]) || s[0]=='-') return false ;
   char * p ;
   strtol(s.c_str(), &p, base) ;
   return (*p == 0) ;
}


bool isNegativeInt(const String& s, int base){
   if(s.empty() || std::isspace(s[0]) || s[0]!='-') return false ;
   char * p ;
   strtol(s.c_str(), &p, base) ;
   return (*p == 0) ;
}

Note:

  1. You can check for various bases (binary, oct, hex and others)
  2. Make sure you don't pass 1, negative value or value >36 as base.
  3. If you pass 0 as the base, it will auto detect the base i.e for a string starting with 0x will be treated as hex and string starting with 0 will be treated as oct. The characters are case-insensitive.
  4. Any white space in string will make it return false.



回答10:


Here is another solution.

try
{
  (void) std::stoi(myString); //cast to void to ignore the return value   
  //Success! myString contained an integer
} 
catch (const std::logic_error &e)
{   
  //Failure! myString did not contain an integer
}


来源:https://stackoverflow.com/questions/2844817/how-do-i-check-if-a-c-string-is-an-int

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!