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

2019-01-03 09:21发布

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;
    }
}

10条回答
Fickle 薄情
2楼-- · 2019-01-03 09:52

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
}
查看更多
不美不萌又怎样
3楼-- · 2019-01-03 09:55

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.).

查看更多
SAY GOODBYE
4楼-- · 2019-01-03 09:55

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.

查看更多
Fickle 薄情
5楼-- · 2019-01-03 09:58

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;
}
查看更多
爷、活的狠高调
6楼-- · 2019-01-03 10:02

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;
}
查看更多
手持菜刀,她持情操
7楼-- · 2019-01-03 10:02

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
查看更多
登录 后发表回答