Reputation: 8355
I want to convert a string to an int and I don't mean ASCII codes.
For a quick run-down, we are passed in an equation as a string. We are to break it down, format it correctly and solve the linear equations. Now, in saying that, I'm not able to convert a string to an int.
I know that the string will be in either the format (-5) or (25) etc. so it's definitely an int. But how do we extract that from a string?
One way I was thinking is running a for/while loop through the string, check for a digit, extract all the digits after that and then look to see if there was a leading '-', if there is, multiply the int by -1.
It seems a bit over complicated for such a small problem though. Any ideas?
Upvotes: 817
Views: 2279254
Reputation: 83
From std::stoi()
:
// stoi example #include <iostream> // std::cout #include <string> // std::string, std::stoi int main () { std::string str_dec = "2001, A Space Odyssey"; std::string str_hex = "40c3"; std::string str_bin = "-10010110001"; std::string str_auto = "0x7f"; std::string::size_type sz; // Alias of size_t int i_dec = std::stoi (str_dec,&sz); int i_hex = std::stoi (str_hex,nullptr,16); int i_bin = std::stoi (str_bin,nullptr,2); int i_auto = std::stoi (str_auto,nullptr,0); std::cout << str_dec << ": " << i_dec << " and [" << str_dec.substr(sz) << "]\n"; std::cout << str_hex << ": " << i_hex << '\n'; std::cout << str_bin << ": " << i_bin << '\n'; std::cout << str_auto << ": " << i_auto << '\n'; return 0; }
Output:
2001, A Space Odyssey: 2001 and [, A Space Odyssey] 40c3: 16579 -10010110001: -1201 0x7f: 127
Upvotes: -1
Reputation: 39375
C++ has evolved over time, and with it the methods to parse int
s.
I will provide a summary in this answer.
Note: the answer applies equally to long
, float
, and other arithmetic types.
The following table compares all options (only C++ standard options, no third-party libraries) from most recent to least recent.
Method | Error Handling | Pros & Cons |
---|---|---|
std::from_chars c++17 |
std::from_chars_result (manual error handling) |
✔️ fast and zero overhead ✔️ supports ANY base as run-time argument ✔️ also works for floats, with a format of choice ❌ interface is not ergonomic ❌ no locale support |
std::sto* family c++11 |
std::invalid_argument std::out_of_range (exceptions) |
✔️ simple interface ✔️ supports ANY base as run-time argument ✔️ also works for floats ✔️ no overhead in happy path ✔️ supports locale ❌ inefficient if errors are common ❌ obscure name |
std::istringstream c++98 |
bool flag, orstream.exceptions() |
✔️ universal method (for types with >> operator)✔️ considers locale (e.g. can change base) ✔️ can detect different formats (e.g. 0x... )❌ slow, and high overhead of streams ❌ limited support for different bases |
std::strto* family c++98 |
std::errno (global flag, manual) |
✔️ small assembly output ✔️ small overhead in happy/sad path ✔️ supports ANY base as run-time argument ✔️ compatible with C ✔️ also works for floats ✔️ supports locale ✔️ can detect different formats if base is zero ❌ obscure name ❌ interface is not ergonomic |
std::ato* family c++98 |
zero indicates failure (manual error handling) |
✔️ small assembly output ✔️ simple interface ✔️ small overhead in happy/sad path ✔️ compatible with C ✔️ also works for floats ❌ obscure name ❌ for int , no support for bases, formats, etc. |
std::sscanf c++98 |
int amount ofarguments parsed (manual error handling) |
✔️ small assembly output ✔️ also works for floats ✔️can detect different formats (e.g. 0x... )✔️ compatible with C ❌ interface is not ergonomic ❌ no type safety, very bug-prone ❌ limited support for different bases |
std::from_chars
, or std::strto*
if not available.
The overhead of exceptions in std::sto*
or std::istringstream
would be unacceptable.std::strto*
.std::istringstream
.std::sto*
, or create a wrapper around std::from_chars
.Most of the special cases are unlikely, so most of the time, use std::stoi
or a std::from_chars
wrapper:
// could be generalized with a template
bool parse_int(std::string_view str, int& out, int base = 10) {
auto [ptr, err] = std::from_chars(str.data(), str.data() + str.size(), out, base);
return err == std::errc{};
}
std::string s = ...;
if (int x; parse_int(s, x)) {
// x has been parsed :)
}
The advantage of such a wrapper is that you can always fall back onto other functions prior C++17 while always having the same interface:
// alternative pre-C++17 version
bool parse_int(const std::string& str, int& out, int base = 10) {
errno = 0;
char* end = nullptr;
out = std::strtol(str.data(), str.data() + str.size(), &end, base);
return str.data() != end && errno == 0;
}
If you don't care about that, you can also make parse_int
return std::optional<int>
instead of assigning a reference.
Upvotes: 24
Reputation: 16297
Use the atoi
function to convert the string to an integer:
string a = "25";
int b = atoi(a.c_str());
Upvotes: 53
Reputation: 135
int stringToInt(std::string value) {
if (value.length() == 0 || value.find(std::string("NULL")) != std::string::npos || value.find(std::string("null")) != std::string::npos) {
return 0;
}
int i;
std::stringstream stream1;
stream1.clear();
stream1.str(value);
stream1 >> i;
return i;
}
Upvotes: -1
Reputation: 1
long long toll(string a) {
long long 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;
}
Usage:
long long a = toll(string("-1234"));
Upvotes: -1
Reputation: 395
std::stoi()
std::string str = "10";
int number = std::stoi(str);
std::string str = "10";
int number;
std::istringstream(str) >> number;
boost::lexical_cast
#include <boost/lexical_cast.hpp>
std::string str = "10";
int number;
try
{
number = boost::lexical_cast<int>(str);
std::cout << number << std::endl;
}
catch (boost::bad_lexical_cast const &e) // Bad input
{
std::cout << "error" << std::endl;
}
std::atoi()
std::string str = "10";
int number = std::atoi(str.c_str());
sscanf()
std::string str = "10";
int number;
if (sscanf(str .c_str(), "%d", &number) == 1)
{
std::cout << number << '\n';
}
else
{
std::cout << "Bad Input";
}
Upvotes: 16
Reputation: 1691
To be more exhaustive (and as it has been requested in comments), I add the solution given by C++17 using std::from_chars
.
std::string str = "10";
int number;
std::from_chars(str.data(), str.data()+str.size(), number);
If you want to check whether the conversion was successful:
std::string str = "10";
int number;
auto [ptr, ec] = std::from_chars(str.data(), str.data()+str.size(), number);
assert(ec == std::errc{});
// ptr points to chars after read number
Moreover, to compare the performance of all these solutions, see this quick-bench link. std::from_chars
is the fastest and std::istringstream
is the slowest.
Upvotes: 64
Reputation: 2067
error handling not done
int myatoti(string ip)
{
int ret = 0;
int sign = 1;
if (ip[0] == '-')
{
ip.erase(0, 1);
sign = -1;
}
int p = 0;
for (auto it = ip.rbegin(); it != ip.rend(); it++)
{
int val = *it - 48;
int hun = 1;
for (int k = 0; k < p; k++)
{
hun *= 10;
}
ret += val * hun;
p++;
}
return ret * sign;
}
Upvotes: -1
Reputation: 273
In C++11 we can use "stoi" function to convert string into a int
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s1 = "16";
string s2 = "9.49";
string s3 = "1226";
int num1 = stoi(s1);
int num2 = stoi(s2);
int num3 = stoi(s3);
cout << "stoi(\"" << s1 << "\") is " << num1 << '\n';
cout << "stoi(\"" << s2 << "\") is " << num2 << '\n';
cout << "stoi(\"" << s3 << "\") is " << num3 << '\n';
return 0;
}
Upvotes: 5
Reputation: 95
You can use std::stringstream
, here's an example:
#include <iostream>
#include <sstream>
using namespace std;
string r;
int main() {
cin >> r;
stringstream tmp(r);
int s;
tmp >> s;
cout << s;
return 0;
}
Upvotes: 1
Reputation: 10947
The possible options are described below:
1. 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. 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. 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. 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. 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. 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.
Upvotes: 117
Reputation: 99
I know this question is really old but I think there's a better way of doing this
#include <string>
#include <sstream>
bool string_to_int(std::string value, int * result) {
std::stringstream stream1, stream2;
std::string stringednumber;
int tempnumber;
stream1 << value;
stream1 >> tempnumber;
stream2 << tempnumber;
stream2 >> stringednumber;
if (!value.compare(stringednumber)) {
*result = tempnumber;
return true;
}
else return false;
}
If I wrote the code right, this will return a boolean value that tells you if the string was a valid number, if false, it wasn't a number, if true it was a number and that number is now result, you would call this this way:
std::string input;
std::cin >> input;
bool worked = string_to_int(input, &result);
Upvotes: 1
Reputation: 1
To convert from string representation to integer value, we can use std::stringstream.
if the value converted is out of range for integer data type, it returns INT_MIN or INT_MAX.
Also if the string value can’t be represented as an valid int data type, then 0 is returned.
#include
#include
#include
int main() {
std::string x = "50";
int y;
std::istringstream(x) >> y;
std::cout << y << '\n';
return 0;
}
Output: 50
As per the above output, we can see it converted from string numbers to integer number.
Source and more at string to int c++
Upvotes: 0
Reputation: 118
My Code:
#include <iostream>
using namespace std;
int main()
{
string s="32"; //String
int n=stoi(s); //Convert to int
cout << n + 1 << endl;
return 0;
}
Upvotes: -1
Reputation: 667
One line version: long n = strtol(s.c_str(), NULL, base);
.
(s
is the string, and base
is an int
such as 2, 8, 10, 16.)
You can refer to this link for more details of strtol
.
The core idea is to use strtol
function, which is included in cstdlib
.
Since strtol
only handles with char
array, we need to convert string
to char
array. You can refer to this link.
An example:
#include <iostream>
#include <string> // string type
#include <bitset> // bitset type used in the output
int main(){
s = "1111000001011010";
long t = strtol(s.c_str(), NULL, 2); // 2 is the base which parse the string
cout << s << endl;
cout << t << endl;
cout << hex << t << endl;
cout << bitset<16> (t) << endl;
return 0;
}
which will output:
1111000001011010
61530
f05a
1111000001011010
Upvotes: -2
Reputation: 1973
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.
Upvotes: 2
Reputation: 168586
What about Boost.Lexical_cast?
Here is their example:
The following example treats command line arguments as a sequence of numeric data:
int main(int argc, char * argv[])
{
using boost::lexical_cast;
using boost::bad_lexical_cast;
std::vector<short> args;
while(*++argv)
{
try
{
args.push_back(lexical_cast<short>(*argv));
}
catch(bad_lexical_cast &)
{
args.push_back(0);
}
}
...
}
Upvotes: 10
Reputation: 153889
It's probably a bit of overkill, but
boost::lexical_cast<int>( theString )
should to the job
quite well.
Upvotes: 4
Reputation: 41775
In Windows, you could use:
const std::wstring hex = L"0x13";
const std::wstring dec = L"19";
int ret;
if (StrToIntEx(hex.c_str(), STIF_SUPPORT_HEX, &ret)) {
std::cout << ret << "\n";
}
if (StrToIntEx(dec.c_str(), STIF_SUPPORT_HEX, &ret)) {
std::cout << ret << "\n";
}
strtol
,stringstream
need to specify the base if you need to interpret hexdecimal.
Upvotes: 1
Reputation: 13531
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
Upvotes: 1161
Reputation: 13
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
Upvotes: -2
Reputation: 361264
Admittedly, my solution wouldn't work for negative integers, but it will extract all positive integers from input text containing integers. It makes use of numeric_only
locale:
int main() {
int num;
std::cin.imbue(std::locale(std::locale(), new numeric_only()));
while ( std::cin >> num)
std::cout << num << std::endl;
return 0;
}
Input text:
the format (-5) or (25) etc... some text.. and then.. 7987...78hjh.hhjg9878
Output integers:
5
25
7987
78
9878
The class numeric_only
is defined as:
struct numeric_only: std::ctype<char>
{
numeric_only(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table()
{
static std::vector<std::ctype_base::mask>
rc(std::ctype<char>::table_size,std::ctype_base::space);
std::fill(&rc['0'], &rc[':'], std::ctype_base::digit);
return &rc[0];
}
};
Complete online demo : http://ideone.com/dRWSj
Upvotes: 8
Reputation: 45039
std::istringstream ss(thestring);
ss >> thevalue;
To be fully correct you'll want to check the error flags.
Upvotes: 68