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';
Related
I'm trying to use std::from_chars to convert std::string to integer specifically like this:
//selection_msg is read from a file and is a std::string
int selection_data;
auto result = std::from_chars(selection_msg.data(),
selection_msg.data() + selection_msg.size(),
selection_data);
Now this works for a decimal selection_msg = "1234", selection_data = 1234 and the result ec=0.
But if selection_msg = "0xABC", selection_data = 0 the result ec=0 but importantly the ptr="xABC" indicating the x isn't part of a recognised pattern.
Note: IF I add the base:
auto result = std::from_chars(selection_msg.data(),
selection_msg.data() + selection_msg.size(),
selection_data,
16);
selection_msg = "ABC" parses just fine, but obviously I can't decode a parse a decimal.
The spec https://en.cppreference.com/w/cpp/utility/from_chars seems to suggest "0x" should be a valid pattern am reading it wrong?
I was hoping to use the auto base detection to make the file input a bit more flexible.
Can anyone see what I'm doing wrong?
P.S. all tested in VS2019.
There is no auto base detection for from_chars. It's a very low-level interface designed for performance, not flexibility.
If you want auto-detection, use stoi and friends.
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
...
}
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 am writing and reading string and int values using a file-backed QSettings object.
When I later try to read the values from a different process, the values are read as strings instead of int.
This is the code I am using to write values:
QSettings settings("TestQSettings.ini", QSettings::IniFormat);
settings.setValue("AAA",QString("111"));
settings.setValue("BBB",222);
This is the file created:
[General]
AAA=111
BBB=222
This is the code I am using to read values:
QVariant qvar = settings.value("AAA");
std::cout << "AAA type " << qvar.type() << std::endl;
qvar = settings.value("BBB");
std::cout << "BBB type " << qvar.type() << std::endl;
If I run this code from the same process:
AAA type 10
BBB type 2
If I run this code from a different process:
AAA type 10
BBB type 10
I know it's possible to convert the types after they have been read.
Unfortunately, this solution will require modifying Windows legacy cross-platform code which I prefer not to modify, for example multiple calls to RegQueryValueEx().
Is it possible to store and read the type information for strings and integers?
For example, Strings will have quotes "" and integers will not:
[General]
AAA="111"
BBB=222
This problem is present on both Qt 4 and Qt 5, on Linux.
Whoa whoa, are you using .ini files or the registry?
With .ini files it's obviously impossible to know what the type was, since it's all a string. You can attempt conversion of the variant to an integer (don't use canConvert!), and assume it's an integer if it converts into one.
With the registry, QSettings will work as you expect it to.
I really don't see what the problem is. Don't use .ini files if you wish to retain type information. You'd face exactly the same problems if you wrote the code by hand in a platform-dependent manner.
You can explicitly write quoted strings into the .ini files, and check for presence of quotes when reading them back. If the quotes are not present, you can try conversion to an integer.
I solved this problem for a component which needs to save and restore variants of arbitrary type, without knowing what its clients expect. The solution was to store the variant's typeName() alongside each value:
void store(QSettings& settings, const QString& key, const QVariant& value)
{
settings.setValue(key+"value", value);
settings.setValue(key+"type", value.typeName());
}
When reading back, we also read the type name, and convert() the variant if it's not already the correct type, before returning it.
QVariant retrieve(const QSettings& settings, const QString& key)
{
auto value = settings.value(key+"value");
const auto typeName = settings.value(key+"type").toString();
const bool wasNull = value.isNull(); // NOTE 1
const auto t = QMetaType::type(typeName.toUtf8()); // NOTE 2
if (value.userType() != t && !value.convert(t) && !wasNull) {
// restore value that was cleared by the failed convert()
value = settings.value(key+"value");
qWarning() << "Failed to convert value" << value << "to" << typeName;
}
return value;
}
Notes
The wasNull variable is in there because of this niggle of convert():
Warning: For historical reasons, converting a null QVariant results in a null value of the desired type (e.g., an empty string for QString) and a result of false.
In this case, we need to ignore the misleading return value, and keep the successfully-converted null variant of the correct type.
It's not clear that UTF-8 is the correct encoding for QMetaType names (perhaps local 8-bit is assumed?); my types are all ASCII, so I just use toLatin1() instead, which might be faster. If it were an issue, I'd use QString::fromLatin1 in the store() method (instead of implicit char* to QString conversion), to ensure a clean round-trip.
If the type name is not found, t will be QMetaType::UnknownType; that's okay, because convert() will then fail, and we'll return the unconverted variant (or a null). It's not great, but it's a corner case that won't happen in normal usage, and my system will recover reasonably quickly.
Turns out the solution was very simple.
When values are written to the INI file, the type is known.
I am appending to the value "\"STRING right before SetValue
When values are read back from the INI file.
I verify that string types have the above postfix.
If they do, I chop the postfix off.
If they don't I assume they are integers instead of strings.
Works like a charm!
Thanks to you all and especially #Kuba Ober for practically handing out the solution.
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?