I am looking for a method to convert a string represent of an integer (say, "123") to an integer in C++03.
I am aware about the usual method of using stringstreams:
string token="1234";
stringstream sss(token);
int tokenInt;
sss>>tokenInt;
cout<<"Int token is: "<<tokenInt<<"\n";
However, the problem with this is that it doesn't appear to work on values like 1e1. It just prints out 1. Working demo here. stoi is unfortunately ruled out since I am using C++0x. Any other way?
Thanks!
Edit: I am basically working on IPv4 and IPv6 addresses. The function ipValidator() returns valid if it is a valid IPv4 or IPv6 address. I split the input, say, 1e1.4.5.6 into tokens 1e1, 4, 5 and 6. Since, 1e1 is incorrect, I need to return false. Unfortunately, the above method returns true since it process 1e1 as just a 1.
You're almost there. After you do the conversion you need to check if there is any data left in the stream. If there is then you know you had invalid input. So if
the_stream.eof()
is true then you consumed on the input and you have a valid result. If not then you have invalid input.
You can use C function strtol as well:
std::string token = "1234";
char *endp = 0;
int value = strtol( token.c_str(), &endp, 10 );
if( **endp ) { // invalid symbol detected
...
}
Related
I was practicing converting numbers in Qt and ran into a problem. I have a variable of type int - result, its value is, for example, 11111 (I get it in a certain way). I want this number to be considered binary in my program. To do this, I'm trying to translate it into a string in variable res and add "0b" in front of my value, like
QString res = "0b" + QString:number(result);
My variable res is "0b11111" and that's right, but I want to get a variable of type int, so I'm trying to cast a string to it:
result = res.toInt();
and in the end I get 0. I understand that this is most likely due to the second character "b", but is there really no way to convert the number to the binary system as it is?
Or did I made a mistake somewhere?
Thank you for all answers, that could helps me to understand what’s wrong!
With Qt, you can specify the base, if you look carefully at the QString documentation, you could simply write:
res = QString::number(11111);
result = res.toInt(nullptr, 2); // Base 2
Or even better:
bool success; // Can be used to check if the conversion succeeded
res = QString::number(11111);
result = res.toInt(&success, 2);
In order for the QString.toInt() function to use the "C Convention" and determine which base to use according to known prefixes (the "0b" in your case), you need to explicitly specify a base of zero in the call:
QString res = "0b" + QString:number(result);
result = res.toInt(nullptr, 0); // If "base" is zero, parse/use the "0b"
Otherwise, if no "base" argument is given, it will default to 10 (i.e. decimal) and, in that case, only the leading zero in your string will be parsed, because the 'b' character is not a valid decimal digit.
Alternatively, you can skip the leading "0b" characters and explicitly tell the function to use base 2:
QString res = QString:number(result); // No added "0b" prefix
result = res.toInt(nullptr, 2); // Force use of binary
So you have an integer variables with the value eleven thousand one hundred and eleven, but you want it to be considered binary and therefore a value of thirty one? Can't help thinking that you are solving the wrong problem.
But anyway, convert to a std::string using std::to_string and then use the std::stoi function to convert back to an integer. std::stoi allows you to specify binary a binary conversion.
int result = 11111;
int res = std::stoi(std::to_string(result), nullptr, 2);
std::cout << res << '\n';
This is the code I wrote to convert integer to string.
#include <iostream>
using namespace std;
int main()
{
string s;
int b=5;
s.push_back((char)b);
cout<<s<<endl;
}
I expected the output to be 5 but it is giving me blank space.
I know there is another way of doing it using stringstream but I want to know what is wrong in this method?
Character code for numbers are not equal to the integer the character represents in typical system.
It is granteed that character codes for decimal digits are consecutive (N3337 2.3 Character sets, Paragraph 3), so you can add '0' to convert one-digit number to character.
#include <iostream>
using namespace std;
int main()
{
string s;
int b=5;
s.push_back((char)(b + '0'));
cout<<s<<endl;
}
You are interpreting the integer 5 as a character. In ASCII encoding, 5 is the Enquiry control character as you lookup here.
The character 5 on the other hand is represented by the decimal number 53.
As others said, you can't convert an integer to a string the way you are doing it.
IMHO, the best way to do it is using the C++11 method std::to_string.
Your example would translate to:
using namespace std;
int main()
{
string s;
int b=5;
s = to_string(b);
cout<<s<<endl;
}
The problem in your code is that you are converting the integer 5 to ASCII (=> ENQ ASCII code, which is not "printable").
To convert it to ASCII properly, you have to add the ASCII code of '0' (48), so:
char ascii = b + '0';
However, to convert an integer to std::string use:
std::stringstream ss; //from <sstream>
ss << 5;
std::string s = ss.str ();
I always use this helper function in my projects:
template <typename T>
std::string toString (T arg)
{
std::stringstream ss;
ss << arg;
return ss.str ();
}
Also, you can use stringstream,
std::to_string doesn't work for me on GCC
If we were writing C++ from scratch in 2016, maybe we would make this work. However as it choose to be (mostly) backward compatible with a fairly low level language like C, 'char' is in fact just a number, that string/printing algorithms interpret as a character -but most of the language doesn't treat special. Including the cast. So by doing (char) you're only converting a 32 bit signed number (int) to a 8 bit signed number (char).
Then you interpret it as a character when you print it, since printing functions do treat it special. But the value it gets printed to is not '5'. The correspondence is conventional and completely arbitrary; the first numbers were reserved to special codes which are probably obsolete by now. As Hoffman pointed out, the bit value 5 is the code for Enquiry (whatever it means), while to print '5' the character has to contain the value 53. To print a proper space you'd need to enter 32. It has no meaning other than someone decided this was as good as anything, sometime decades ago, and the convention stuck.
If you need to know for other characters and values, what you need is an "ASCII table". Just google it, you'll find plenty.
You'll notice that numbers and letters of the same case are next to each other in the order you expect, so there is some logic to it at least. Beware, however, it's often not intuitive anyway: uppercase letters are before lowercase ones for instance, so 'A' < 'a'.
I guess you're starting to see why it's better to rely on dedicated system functions for strings!
I recently migrated from C to C++, and there's a little confusion about strings. Strings just aren't what they used to be any more, as in, not just char arrays with a terminating '\0'.
I haven't found a real answer to this question, so how far can you treat the std::string class like C-Strings?
For example: If I know there's a number somewhere in a string, let the string be ireallylike314, in C I could use strtol(string + 10, NULL, 10) to just get that number.
And, if this doesn't work, is there a way to use std::string like C-strings?
Use c_str().
strtol(string.c_str() + 10, NULL, 10);
If you want to get C-style string from std::string, then as mentioned use c_str() method. But another solution to this specific problem would be just using stol instead of strtol.
While stol doesn't (in itself) support what you want, I think I'd use it in conjunction with substr to get the required result:
std::string in = "ireallylike314";
// extract number and print it out multiplied by 2 to show we got a number
std::cout << 2 * stol(in.substr(11));
Result:
628
This has both good and bad points though. On the bad side, it creates a whole new string object to hold the digits out of the input string. On the good side, it gives a little more control over the number of digits to convert, so if (for example) you only wanted to convert the first two digits from the string (even if, as in this case, they're followed by more digits) you can do that pretty easily too:
std::cout << 2 * stol(in.substr(11, 2));
Result:
62
In quite a few cases, the degree to which this is likely to be practical for you will depend heavily upon whether your implementation includes the short string optimization. If it does, creating a (small) string is often cheap enough to make this perfectly reasonable. If it doesn't, the heap allocation to create the temporary string object as the return value from substr may be a higher price than you want to pay.
The C-like way:
long n = std::strtol( string.c_str() + offset, nullptr, 10 );
// sets ERRNO on error and returns value by saturating arithmetic.
The Java-ish way:
long n = std::stol( string.substr( offset, std::string::npos ) );
// exception (no return value) and perhaps ERRNO is set on error.
The streams way:
long n = 0;
std::istringstream( string ).ignore( offset ) >> n;
// n is unmodified on error
The locales way:
long n = 0;
std::ios_base fmt; // Use default formatting: base-10 only.
std::ios::iostate err = {};
std::num_get< char, std::string::iterator >()
.get( string.begin() + offset, string.end(), fmt, err, n );
// err is set to std::ios::failbit on error
This is maybe beyond the scope of the question but since you are migrating to C++ and you seem confused about std::string, you'll likely find the following useful.
The point of having std::string is not to use it like C-Strings (ofc you can do it, like the previous answers showed). You can take a lot more advantages of std::string capabilities. For example it is a C++ container, there are functions to get substrings, to compare strings, etc ...
String manipultions are generally a lot easier with std::string rather than C-Strings.
See for example http://www.cplusplus.com/reference/string/string/ for its capabilities.
Strings just aren't what they used to be any more, as in, not just
char arrays with a terminating '\0'.
You are wrong. In C++ strings are defined the same way. In both languages strings are defined like
A string is a contiguous sequence of characters terminated by and
including the first null character.
You mix strings with class std::string (or std::basic_string) that are not the same.
For example: If I know there's a number somewhere in a string, let the
string be ireallylike314, in C I could use strtol(string[10], NULL,
10) to just get that number
You are mistaken. The valid function call will look like
strtol( &string[11], NULL, 10)
or
strtol( string + 11, NULL, 10)
The same function you can call for an object of class std::string using member function c_str() or (starting from C++ 2011) data()
For example
std::string s( "ireallylike314" );
auto x = std::strtol( s.c_str() + 11, NULL, 10 );
or
auto x = std::strtol( s.data() + 11, NULL, 10 );
I have a function that parses some input from std::cin and returns an integer value on success. I need to detect, based on the return value, if something went wrong when parsing input. Zero is a valid return. What can I use to differentiate between valid zero and "bad input"?
If I need to post code as an example, just let me know. Thanks!
[EDIT]
int parseInput(){
int calculatedValue = 0;
bool parseOk = true;
/* Parse cin for valid input.*/
if (parseOk) {
/* Perform calculation. Can be zero */
}
return calculatedValue; // Any integer is valid
}
This would be the perfect job for std::optional. Your best alternative, with regards to notify at return value, is to implement a similar class.
Alternatively, you should really use an exception. Exceptions are made exactly to notify the user of your function that something went wrong.
You can use an boolean flag for checking if something went wrong, it is common practice (for instance, Qt library uses it) to do something like:
int getIntegerStuffFromInput(bool & ok);
or
bool getIntegerStuffFromInput(int & value);
When you read numbers from std::cin, the most important thing is not to read directly into an int. Instead, you use std::getline to read a whole line of input into an std::string. This way you can detect wrong input much more easily.
Once the line has been entered, you convert the resulting std::string to an int.
std::string input_line;
std::getline(std::cin, input_line);
// input_line now contains a whole line of input
In C++11, you just use std::stoi for the conversion:
int const input = std::stoi(input_line);
This function will throw an exception if the string cannot be converted to an integer number.
In pre-C++11, you use std::istringstream:
std::istringstream is(input_line);
int input = 0;
is >> input;
The following code then checks if the line could be correctly converted to an integer number or not:
if (!is)
{
// error
}
"What can I use to differentiate between valid zero and "bad input"?"
You have basically three choices
If you need to handle all integers as a valid return value:
Throw an exception, that can be handled outside from your function call
Have a dedicated output parameter passed by reference, and return bool from your function, false indicates bad input.
If negative integers aren't a valid return value:
Just return a negative value and test for result < 0.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to convert a single char into an int
Well, I'm doing a basic program, wich handles some input like:
2+2
So, I need to add 2 + 2.
I did something like:
string mys "2+2";
fir = mys[0];
sec = mys[2];
But now I want to add "fir" to "sec", so I need to convert them to Int.
I tried "int(fir)" but didn't worked.
There are mulitple ways of converting a string to an int.
Solution 1: Using Legacy C functionality
int main()
{
//char hello[5];
//hello = "12345"; --->This wont compile
char hello[] = "12345";
Printf("My number is: %d", atoi(hello));
return 0;
}
Solution 2: Using lexical_cast(Most Appropriate & simplest)
int x = boost::lexical_cast<int>("12345");
Solution 3: Using C++ Streams
std::string hello("123");
std::stringstream str(hello);
int x;
str >> x;
if (!str)
{
// The conversion failed.
}
Alright so first a little backround on why what you attempted didn't work. In your example, fir is declared as a string. When you attempted to do int(fir), which is the same as (int)fir, you attempted a c-style cast from a string to an integer. Essentially you will get garbage because a c-style cast in c++ will run through all of the available casts and take the first one that works. At best your going to get the memory value that represents the character 2, which is dependent upon the character encoding your using (UTF-8, ascii etc...). For instance, if fir contained "2", then you might possibly get 0x32 as your integer value (assuming ascii). You should really never use c-style casts, and the only place where it's really safe to use them are conversions between numeric types.
If your given a string like the one in your example, first you should separate the string into the relevant sequences of characters (tokens) using a function like strtok. In this simple example that would be "2", "+" and "2". Once you've done that you can simple call a function such as atoi on the strings you want converted to integers.
Example:
string str = "2";
int i = atoi(str.c_str()); //value of 2
However, this will get slightly more complicated if you want to be able to handle non-integer numbers as well. In that case, your best bet is to separate on the operand (+ - / * etc), and then do a find on the numeric strings for a decimal point. If you find one you can treat it as a double and use the function atof instead of atoi, and if you don't, just stick with atoi.
Have you tried atoi or boost lexical cast?