1

Possible Duplicate:
Convert string to int C++
What’s the fastest way to check if a string is a number?

I need to convert string to int and I need to know if converting was successful. But number can be zero, so I can't use atoi and others. String to convert I read from file.

Community
  • 1
  • 1
Alecs
  • 2,256
  • 8
  • 32
  • 45
  • @chris not duplicate, in that thread only one answer shows how to check if conversion was successful, and did it for using boost library, that is to much for me to use boost for one check. – Alecs Dec 11 '12 at 07:12
  • For one, `std::stoi` (also in the answers) throws an exception if something goes wrong, but still accepts things like `123abc`, only giving back 123 as an answer. `lexical_cast` disallows `123abc`, but accepts strings with spaces, only converting the first word. If you want it more fine-grained than that, you can make a custom stringstream version. Of course there's always good old `strtol` as well. – chris Dec 11 '12 at 07:15

3 Answers3

5

you can use this template function, but this is not just for converting a string to an int - it is to convert a string to every type:

template <typename T>
T ConvertString( const std::string &data )
{
  if( !data.empty( ))
  {
    T ret;
    std::istringstream iss( data );
    if( data.find( "0x" ) != std::string::npos )
    {
      iss >> std::hex >> ret;
    }
    else
    {
      iss >> std::dec >> ret;
    }

    if( iss.fail( ))
    {
      std::cout << "Convert error: cannot convert string '" << data << "' to value" << std::endl;
      return T( );
    }
    return ret;
  }
  return T( );
}

If you want to now if the convert was successfull, then return a specific value in the if iss.fail() or pass a second reference argument to the function and set the value to false if it failed.

You can use it like this:

uint16_t my_int = ConvertString<uint16_t>("15");

If you like the solution with the reference argument, here an example:

#include <iostream>
#include <sstream>
#include <string>

#include <inttypes.h>

template <typename T>
T ConvertString(const std::string &data, bool &success)
{
  success = true;
  if(!data.empty())
  {
    T ret;
    std::istringstream iss(data);
    if(data.find("0x") != std::string::npos)
    {
      iss >> std::hex >> ret;
    }
    else
    {
      iss >> std::dec >> ret;
    }

    if(iss.fail())
    {
      success = false;
      return T();
    }
    return ret;
  }
  return T();
}

int main(int argc, char **argv)
{
  bool convert_success;
  uint16_t bla = ConvertString<uint16_t>("15", convert_success);
  if(convert_success)
    std::cout << bla << std::endl;
  else
    std::cerr << "Could not convert" << std::endl;
  return 0;
}
tuxtimo
  • 2,730
  • 20
  • 29
  • Thanks! Too complicated for my case, 'cos I need to perform only one check, but I used stringstream, because it is easy to check with it was conversion successful – Alecs Dec 11 '12 at 07:25
  • Okay, maybe you can use this method in future for other cases. But yes, in stringstream you can use the fail-method as well, to check if every thing was read correctly. Thanks for accepting answer – tuxtimo Dec 11 '12 at 07:28
4

The good old strtol is also available. In C++ code it's best used from #include <cstdio> as std::strtol:

#include <cstdlib>

//...

std::string str;
char *endp;

// change base 10 below to 0 for handing of radix prefixes like 0x
long value = std::strtol(str.c_str(), &endp, 10); 

if (endp == str.c_str()) { 
    /* conversion failed completely, value is 0, */ 
    /* endp points to start of given string */ 
}
else if (*endp != 0) {
    /* got value, but entire string was not valid number, */ 
    /* endp points to first invalid character */ 
}
else {
    /* got value, entire string was numeric, */
    /* endp points to string terminating 0 */ 
}
hyde
  • 60,639
  • 21
  • 115
  • 176
2

use streams (c++):

std::string intString("123");

int result;
std::stringstream stream(intString);

if (stream >> result) {
    std::cout << result;
} else {
    std::cout << "there was an error parsing the string";
}
Julien May
  • 2,011
  • 15
  • 18
  • The first was explicitly disallowed (for good reason), and the second offers no advice on how to check for errors. – chris Dec 11 '12 at 07:21
  • The stream extraction operator returns a bool on success. Should be `if (stream >> result) ... else ...` – acraig5075 Dec 11 '12 at 07:36