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?
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. 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.
std::istringstream ss(thestring);
ss >> thevalue;
To be fully correct you'll want to check the error flags.
use the atoi function to convert the string to an integer:
string a = "25";
int b = atoi(a.c_str());
http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
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 the following quick-bench link: https://quick-bench.com/q/GBzK53Gc-YSWpEA9XskSZLU963Y
(std::from_chars is the fastest and std::istringstream is the slowest)
1. std::stoi
std::string str = "10";
int number = std::stoi(str);
2. string streams
std::string str = "10";
int number;
std::istringstream(str) >> number
3. 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;
}
4. std::atoi
std::string str = "10";
int number = std::atoi(str.c_str());
5. sscanf()
std::string str = "10";
int number;
if (sscanf(str .c_str(), "%d", &number) == 1)
{
std::cout << number << '\n';
}
else
{
std::cout << "Bad Input";
}
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);
}
}
...
}
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
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;
}
It's probably a bit of overkill, but
boost::lexical_cast<int>( theString ) should to the job
quite well.
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 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.
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);
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;
}
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/
From http://www.cplusplus.com/reference/string/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
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;
}
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"));
}
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++
int stringToInt(std::string value) {
if(value.length() == 0 ) return 0; //tu zmiana..
if (value.find( std::string("NULL") ) != std::string::npos) {
return 0;
}
if (value.find( std::string("null") ) != std::string::npos) {
return 0;
}
int i;
std::stringstream stream1;
stream1.clear();
stream1.str(value);
stream1 >> i;
return i;
};
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
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
I think that converting from int to std::string or vice versa needs some special functions like std::stoi()
but if you need to convert a double into a string use to_string() (NOT C#. C# is .ToString() not to_string())
If you wot hard code :)
bool strCanBeInt(std::string string){
for (char n : string) {
if (n != '0' && n != '1' && n != '2' && n != '3' && n != '4' && n != '5'
&& n != '6' && n != '7' && n != '8' && n != '9') {
return false;
}
}
return true;
}
int strToInt(std::string string) {
int integer = 0;
int numInt;
for (char n : string) {
if(n == '0') numInt = 0;
if(n == '1') numInt = 1;
if(n == '2') numInt = 2;
if(n == '3') numInt = 3;
if(n == '4') numInt = 4;
if(n == '5') numInt = 5;
if(n == '6') numInt = 6;
if(n == '7') numInt = 7;
if(n == '8') numInt = 8;
if(n == '9') numInt = 9;
if (integer){
integer *= 10;
}
integer += numInt;
}
return integer;
}
Trying to convert my following go code question
How to create a 0x appended hex string from a hex string for each byte of hex characters in golang?
to C++ - but completely lost.
#include <iostream>
#include <string>
using namespace std;
// Function to append 0x
void appendX(string str)
{
// Appends 1 occurrences of "X" to str
str.append(1, 'X');
cout << "Modified append() : ";
cout << str;
}
int main()
{
string str("01234567891011121314151617181920");
cout << "String : " << str << endl;
appendX(str);
return 0;
}
Your function appendX() is going to append only one 'X' at the end of your input string, as your comment also says.
But if you are trying to append "0x" after every hex byte within your string, (as asked in the GO language question you mentioned), you should be appending "0x" after every 2 characters in your input string. Try below:
void appendX(String str)
{
String outstr;
for(int i=0;i<str.size();i=i+2)
{
outstr.append("0x");
outstr.append(str,i,2);
}
cout << "Modified append() : ";
cout << outstr;
}
Simplest/Understandable way is to iterate over a string and add the desirable amount of characters to a result string.
std::string insertStringInto(const std::string& s, const int interval, const std::string& sep_str)
{
std::string result_str;
auto chars_count_until_sep = interval;
for (auto ch: s)
{
if (chars_count_until_sep == 0)
{
result_str += sep_str;
chars_count_until_sep = interval;
}
result_str += ch;
--chars_count_until_sep;
}
return result_str;
}
int main()
{
std::string str("01234567891011121314151617181920");
std::cout << "String : " << insertStringInto(str,2,", 0x") << std::endl;
return 0;
}
Using the Ranges V3 library (in the future all these functions should be available in the C++ standard library):
std::string insertStringInto(const std::string& in_string, const int interval, const std::string& sep_str)
{
using namespace ranges::views;
auto concat_to_str = [](auto grp) { // auxilllary function to concat single characters into a string
return ranges::accumulate(grp, std::string {});
};
auto r = in_string // Use the characters from the input string parameter
| chunk(interval) // Split string up into interval count of characters
| transform(concat_to_str) // combine characters from chunks into strings
| intersperse(sep_str); // intersperse between the chunks the separator text
return concat_to_str(r); // concat all the strings into 1 string
}
int main()
{
std::string str("01234567891011121314151617181920");
std::cout << "String : " << insertStringInto(str, 2, ", 0x") << std::endl;
return 0;
}
Last week I got an homework to write a function: the function gets a string and a char value and should divide the string in two parts, before and after the first occurrence of the existing char.
The code worked but my teacher told me to do it again, because it is not well written code. But I don't understand how to make it better. I understand so far that defining two strings with white spaces is not good, but i get out of bounds exceptions otherwise. Since the string input changes, the string size changes everytime.
#include <iostream>
#include <string>
using namespace std;
void divide(char search, string text, string& first_part, string& sec_part)
{
bool firstc = true;
int counter = 0;
for (int i = 0; i < text.size(); i++) {
if (text.at(i) != search && firstc) {
first_part.at(i) = text.at(i);
}
else if (text.at(i) == search&& firstc == true) {
firstc = false;
sec_part.at(counter) = text.at(i);
}
else {
sec_part.at(counter) = text.at(i);
counter++;
}
}
}
int main() {
string text;
string part1=" ";
string part2=" ";
char search_char;
cout << "Please enter text? ";
getline(cin, text);
cout << "Please enter a char: ? ";
cin >> search_char;
divide(search_char,text,aprt1,part2);
cout << "First string: " << part1 <<endl;
cout << "Second string: " << part2 << endl;
system("PAUSE");
return 0;
}
I would suggest you, learn to use c++ standard functions. there are plenty utility function that can help you in programming.
void divide(const std::string& text, char search, std::string& first_part, std::string& sec_part)
{
std::string::const_iterator pos = std::find(text.begin(), text.end(), search);
first_part.append(text, 0, pos - text.begin());
sec_part.append(text, pos - text.begin());
}
int main()
{
std::string text = "thisisfirst";
char search = 'f';
std::string first;
std::string second;
divide(text, search, first, second);
}
Here I used std::find that you can read about it from here and also Iterators.
You have some other mistakes. you are passing your text by value that will do a copy every time you call your function. pass it by reference but qualify it with const that will indicate it is an input parameter not an output.
Why is your teacher right ?
The fact that you need to initialize your destination strings with empty space is terrible:
If the input string is longer, you'll get out of bound errors.
If it's shorter, you got wrong answer, because in IT and programming, "It works " is not the same as "It works".
In addition, your code does not fit the specifications. It should work all the time, independently of the current value which is stored in your output strings.
Alternative 1: your code but working
Just clear the destination strings at the beginning. Then iterate as you did, but use += or push_back() to add chars at the end of the string.
void divide(char search, string text, string& first_part, string& sec_part)
{
bool firstc = true;
first_part.clear(); // make destinations strings empty
sec_part.clear();
for (int i = 0; i < text.size(); i++) {
char c = text.at(i);
if (firstc && c != search) {
first_part += c;
}
else if (firstc && c == search) {
firstc = false;
sec_part += c;
}
else {
sec_part += c;
}
}
}
I used a temporary c instead of text.at(i) or text\[i\], in order to avoid multiple indexing But this is not really required: nowadays, optimizing compilers should produce equivalent code, whatever variant you use here.
Alternative 2: use string member functions
This alternative uses the find() function, and then constructs a string from the start until that position, and another from that position. There is a special case when the character was not found.
void divide(char search, string text, string& first_part, string& sec_part)
{
auto pos = text.find(search);
first_part = string(text, 0, pos);
if (pos== string::npos)
sec_part.clear();
else sec_part = string(text, pos, string::npos);
}
As you understand yourself these declarations
string part1=" ";
string part2=" ";
do not make sense because the entered string in the object text can essentially exceed the both initialized strings. In this case using the string method at can result in throwing an exception or the strings will have trailing spaces.
From the description of the assignment it is not clear whether the searched character should be included in one of the strings. You suppose that the character should be included in the second string.
Take into account that the parameter text should be declared as a constant reference.
Also instead of using loops it is better to use methods of the class std::string such as for example find.
The function can look the following way
#include <iostream>
#include <string>
void divide(const std::string &text, char search, std::string &first_part, std::string &sec_part)
{
std::string::size_type pos = text.find(search);
first_part = text.substr(0, pos);
if (pos == std::string::npos)
{
sec_part.clear();
}
else
{
sec_part = text.substr(pos);
}
}
int main()
{
std::string text("Hello World");
std::string first_part;
std::string sec_part;
divide(text, ' ', first_part, sec_part);
std::cout << "\"" << text << "\"\n";
std::cout << "\"" << first_part << "\"\n";
std::cout << "\"" << sec_part << "\"\n";
}
The program output is
"Hello World"
"Hello"
" World"
As you can see the separating character is included in the second string though I think that maybe it would be better to exclude it from the both strings.
An alternative and in my opinion more clear approach can look the following way
#include <iostream>
#include <string>
#include <utility>
std::pair<std::string, std::string> divide(const std::string &s, char c)
{
std::string::size_type pos = s.find(c);
return { s.substr(0, pos), pos == std::string::npos ? "" : s.substr(pos) };
}
int main()
{
std::string text("Hello World");
auto p = divide(text, ' ');
std::cout << "\"" << text << "\"\n";
std::cout << "\"" << p.first << "\"\n";
std::cout << "\"" << p.second << "\"\n";
}
Your code will only work as long the character is found within part1.length(). You need something similar to this:
void string_split_once(const char s, const string & text, string & first, string & second) {
first.clear();
second.clear();
std::size_t pos = str.find(s);
if (pos != string::npos) {
first = text.substr(0, pos);
second = text.substr(pos);
}
}
The biggest problem I see is that you are using at where you should be using push_back. See std::basic_string::push_back. at is designed to access an existing character to read or modify it. push_back appends a new character to the string.
divide could look like this :
void divide(char search, string text, string& first_part,
string& sec_part)
{
bool firstc = true;
for (int i = 0; i < text.size(); i++) {
if (text.at(i) != search && firstc) {
first_part.push_back(text.at(i));
}
else if (text.at(i) == search&& firstc == true) {
firstc = false;
sec_part.push_back(text.at(i));
}
else {
sec_part.push_back(text.at(i));
}
}
}
Since you aren't handling exceptions, consider using text[i] rather than text.at(i).
here is my problem. i have some two dimensional data with changing dimensionality, that i want to read into an 2d-array of doubles. Furthermore, there are at some points not number in the file but "NaN"s, that i want to be replaced by a zero. I made my code working so far, but i only managed to read integers. Maybe you could help me out to read it as doubles?
Here is what i got so far:
void READER(char filepath [], int target [129][128])
{
//---------------------------- header double & int
int rowA = 0;
int colA = 0;
std::string line;
std::string x;
std::cout << "reading file: " << filepath << "\n";
std::cout << std::endl;
std::ifstream fileIN;
fileIN.open(filepath);
if (!fileIN.good())
std::cerr << "READING ERROR IN FILE: " << filepath << std::endl;
while (fileIN.good())
{
while (getline(fileIN, line))
{
std::istringstream streamA(line);
colA = 0;
while (streamA >> x)
{
boost::algorithm::replace_all(x, "NaN", "0");
boost::algorithm::replace_all(x, ",", ""); //. rein
// std::cout << string_to_int(x) << std::endl;
target [rowA][colA] = string_to_int(x);
colA++;
}
rowA++;
if(rowA%5 ==0)
{
std::cout << "*";
}
}
}
std::cout << " done." <<std::endl;
}
this writes the files into 'target'. The function string to int looks the following:
int string_to_int (const std::string& s)
{
std::istringstream i(s);
int x;
if(!(i >> x))
return 0;
return x;
}
here you find some example data:
"exactly, thats what i thought about doing with the line boost::algorithm::replace_all(x, ",", ""); by replacing , by ."
Use following function to convert to any type, say double :-
template <typename T>
T StringToNumber ( const std::string &Text )
{
std::istringstream ss(Text);
T result;
return ss >> result ? result : 0;
}
Call using :
boost::algorithm::replace_all(x, ",", "."); // Change , to .
std::cout << StringToNumber<double>(x) << std::endl;
Or
you can simply use boost::lexical_cast
std::cout<<boost::lexical_cast<double>( x )<<std::endl;
Make sure you have a double 2D array