tags:

views:

15244

answers:

7

What's the C++ way of parsing a string (given as char *) into an int? Robust and clear error handling is a plus (instead of returning zero).

+4  A: 

The good 'old C way still works. I recommend strtol or strtoul. Between the return status and the 'endPtr', you can give good diagnostic output. It also handles multiple bases nicely.

Chris Arguin
Oh please don't use this old C stuff when programming C++. There are better/easier/cleaner/more modern/safer ways to do this in C++!
jk
It's funny when people are concerned about "more modern" ways to solve a problem.
Jeff Miller
@Jason, IMO stronger type safety and error handling is more modern idea compared to that of C.
eed3si9n
I've looked at the other answers, and so far nothing is obviously better/easier/cleaner or safer.The poster said he had a char *. That limits the amount of safety you are going to get :)
Chris Arguin
+4  A: 

You can use stringstream's

int str2int (const string &str) {
  stringstream ss(str);
  int num;
  ss >> num;
  return num;
}
CMS
But this does not handle any errors. You have to check the stream for failures.
jk
Right you have to check the stream if((ss >> num).fail()){ //ERROR}
CMS
The C++ stringstream method doesn't work for strings such as "12-SomeString" even with the 'stream state' check
captonssj
+9  A: 

You can use Boost's lexical_cast, which wraps this in a more generic interface. lexical_cast<Target>(Source) throws bad_lexical_cast on failure.

jk
Could you separate the stringstream to another post? People voted for Boost.
eed3si9n
Thanks. Now, I am torn between two good solutions. I personally like the Boost way, but stringstream way seems more portable.
eed3si9n
+27  A: 

This is a safer C way than atoi()

const char* str = "123";
int i;

if(sscanf(str, "%d", &i)  == EOF )
{
   /* error */
}

C++ with standard library stringstream: (thanks CMS )

int str2int (const string &str) {
  stringstream ss(str);
  int num;
  if((ss >> num).fail())
  { 
      //ERROR 
  }
  return num;
}

With boost library: (thanks jk)

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

try
{
    std::string str = "123";
    int number = boost::lexical_cast< int >( str );
}
catch( const boost::bad_lexical_cast & )
{
    // Error
}

Edit: Fixed the stringstream version so that it handles errors. (thanks to CMS's and jk's comment on original post)

Luka Marinko
please updated your stringstream version to include a check for stringstream::fail() (as requested by the questioner "Robust and clear error handling")
jk
Your stringstream version will accept stuff like "10haha" without complaining
Johannes Schaub - litb
Johannes Schaub - litb
The C++ with standard library stringstream method doesn't work for strings such as "12-SomeString" even with the .fail() check.
captonssj
+7  A: 

You can use the a stringstream from the C++ standard libraray:

stringstream ss(str);
int x;
ss >> x;

if(ss) { // <-- error handling
  // use x
} else {
  // not a number
}

The stream state will be set to fail if a non-digit is encountered when trying to read an integer.

See Stream pitfalls for pitfalls of errorhandling and streams in C++.

jk
The C++ stringstream method doesn't work for strings such as "12-SomeString" even with the 'stream state' check.
captonssj
A: 

As far as I remember, possible solution is described in one of early chapters of "C++ Programming Language" by Bjarne Stroustrup. Maybe it makes sense for you to use it as a reference.

Maxim Ananyev
+5  A: 
Beh Tou Cheh