Just have a quick question. I\'ve looked around the internet quite a bit and I\'ve found a few solutions but none of them have worked yet. Looking at converting a string to
Well, lot of answers, lot of possibilities. What I am missing here is some universal method that converts a string to different C++ integral types (short, int, long, bool, ...). I came up with following solution:
#include<sstream>
#include<exception>
#include<string>
#include<type_traits>
using namespace std;
template<typename T>
T toIntegralType(const string &str) {
static_assert(is_integral<T>::value, "Integral type required.");
T ret;
stringstream ss(str);
ss >> ret;
if ( to_string(ret) != str)
throw invalid_argument("Can't convert " + str);
return ret;
}
Here are examples of usage:
string str = "123";
int x = toIntegralType<int>(str); // x = 123
str = "123a";
x = toIntegralType<int>(str); // throws exception, because "123a" is not int
str = "1";
bool y = toIntegralType<bool>(str); // y is true
str = "0";
y = toIntegralType<bool>(str); // y is false
str = "00";
y = toIntegralType<bool>(str); // throws exception
Why not just use stringstream output operator to convert a string into an integral type? Here is the answer: Let's say a string contains a value that exceeds the limit for intended integral type. For examle, on Wndows 64 max int is 2147483647. Let's assign to a string a value max int + 1: string str = "2147483648". Now, when converting the string to an int:
stringstream ss(str);
int x;
ss >> x;
x becomes 2147483647, what is definitely an error: string "2147483648" was not supposed to be converted to the int 2147483647. The provided function toIntegralType spots such errors and throws exception.
In C++11 there are some nice new convert functions from std::string
to a number type.
So instead of
atoi( str.c_str() )
you can use
std::stoi( str )
where str
is your number as std::string
.
There are version for all flavours of numbers:
long stol(string)
, float stof(string)
, double stod(string)
,...
see http://en.cppreference.com/w/cpp/string/basic_string/stol
The possible options are described below:
1. First option: sscanf()
#include <cstdio>
#include <string>
int i;
float f;
double d;
std::string str;
// string -> integer
if(sscanf(str.c_str(), "%d", &i) != 1)
// error management
// string -> float
if(sscanf(str.c_str(), "%f", &f) != 1)
// error management
// string -> double
if(sscanf(str.c_str(), "%lf", &d) != 1)
// error management
This is an error (also shown by cppcheck) because "scanf without field width limits can crash with huge input data on some versions of libc" (see here, and here).
2. Second option: std::sto*()
#include <iostream>
#include <string>
int i;
float f;
double d;
std::string str;
try {
// string -> integer
int i = std::stoi(str);
// string -> float
float f = std::stof(str);
// string -> double
double d = std::stod(str);
} catch (...) {
// error management
}
This solution is short and elegant, but it is available only on on C++11 compliant compilers.
3. Third option: sstreams
#include <string>
#include <sstream>
int i;
float f;
double d;
std::string str;
// string -> integer
std::istringstream ( str ) >> i;
// string -> float
std::istringstream ( str ) >> f;
// string -> double
std::istringstream ( str ) >> d;
// error management ??
However, with this solution is hard to distinguish between bad input (see here).
4. Fourth option: Boost's lexical_cast
#include <boost/lexical_cast.hpp>
#include <string>
std::string str;
try {
int i = boost::lexical_cast<int>( str.c_str());
float f = boost::lexical_cast<int>( str.c_str());
double d = boost::lexical_cast<int>( str.c_str());
} catch( boost::bad_lexical_cast const& ) {
// Error management
}
However, this is just a wrapper of sstream
, and the documentation suggests to use sstream
for better error management (see here).
5. Fifth option: strto*()
This solution is very long, due to error management, and it is described here. Since no function returns a plain int, a conversion is needed in case of integer (see here for how this conversion can be achieved).
6. Sixth option: Qt
#include <QString>
#include <string>
bool ok;
std::string;
int i = QString::fromStdString(str).toInt(&ok);
if (!ok)
// Error management
float f = QString::fromStdString(str).toFloat(&ok);
if (!ok)
// Error management
double d = QString::fromStdString(str).toDouble(&ok);
if (!ok)
// Error management
Conclusions
Summing up, the best solution is C++11 std::stoi()
or, as a second option, the use of Qt libraries. All other solutions are discouraged or buggy.
ll toll(string a){
ll ret=0;
bool minus=false;
for(auto i:a){
if(i=='-'){ minus=true; continue; }
ret*=10;
ret+=(i-'0');
} if(minus) ret*=-1;
return ret;
# ll is defined as, #define ll long long int
# usage: ll a = toll(string("-1234"));
}
there is another easy way : suppose you have a character like c='4'
therefore you can do one of these steps :
1st : int q
q=(int) c ; (q is now 52 in ascii table ) .
q=q-48; remember that adding 48 to digits is their ascii code .
the second way :
q=c-'0'; the same , character '0' means 48
atoi
is a built-in function that converts a string to an integer, assuming that the string begins with an integer representation.
http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/