I'm trying to convert hex strings to double values, where some of the values are negative. This answer works fine for positive double hex strings, but when the double is negative I get a std::out_of_range exception. Why is that? Is there a way to get around it?
I have also tried to do the same thing with stringstream, and that works just fine for both positive and negative hex strings. So there is always that solution, but to me the union approach looks a bit more elegant. A matter of taste I guess.
Sample code:
#include <string>
#include <iostream>
#include <iomanip>
#include <sstream>
int main()
{
std::string str1("3fb999999999999a"); // 0.1
std::string str2("bfb999999999999a"); // -0.1
// ******************************
// UNION
// ******************************
union uint64double
{
unsigned long long i;
double d;
};
uint64double val1;
val1.i = std::stoll(str1, nullptr, 16);
uint64double val2;
val2.i = std::stoll(str2, nullptr, 16); // This throws std::out_of_range exception
const int w = 18;
std::cout << "USING UNION" << std::endl;
std::cout << std::setw(w) << "HEX" << std::setw(w) << "DOUBLE" << std::endl;
std::cout << std::setw(w) << str1 << std::setw(w) << val1.d << std::endl;
std::cout << std::setw(w) << str2 << std::setw(w) << val2.d << std::endl;
std::cout << std::endl;
// ******************************
// STRINGSTREAM
// ******************************
unsigned long long i1;
std::stringstream ss;
ss << std::hex << str1;
ss >> i1;
double d1(reinterpret_cast<double&>(i1));
unsigned long long i2;
ss.clear();
ss << std::hex << str2;
ss >> i2;
double d2(reinterpret_cast<double&>(i2));
std::cout << "USING STRINGSTREAM" << std::endl;
std::cout << std::setw(w) << "HEX" << std::setw(w) << "DOUBLE" << std::endl;
std::cout << std::setw(w) << str1 << std::setw(w) << d1 << std::endl;
std::cout << std::setw(w) << str2 << std::setw(w) << d2 << std::endl;
std::cout << std::endl;
return 0;
}
Output:
USING UNION
HEX DOUBLE
3fb999999999999a 0.1
bfb999999999999a 1.#QNAN
USING STRINGSTREAM
HEX DOUBLE
3fb999999999999a 0.1
bfb999999999999a -0.1
I'm using VS2012
Of course stoll throws std::out_of_range exception on input "bfb999999999999a", because 0xbfb999999999999a > LLONG_MAX. If you use stoull instead, everything works nicely, because 0xbfb999999999999a <= ULLONG_MAX.
You can pass the hex string into the stringstream constructor to clean it up a bit. Your std::hex is in the wrong place. std::hex tells the stream to treat the input as a hex value, rather than just a bunch of characters.
I would put this functionality in its own function too, to make it cleaner:
#include <string>
#include <iostream>
#include <iomanip>
#include <sstream>
double hexToDouble(const std::string& hex)
{
double d = 0;
std::stringstream ss(hex);
ss >> std::hex >> reinterpret_cast<uint64_t&>(d); // I feel dirty
return d;
}
int main()
{
std::string str1("3fb999999999999a"); // 0.1
std::string str2("bfb999999999999a"); // -0.1
std::cout << str1 << ' ' << hexToDouble(str1) << std::endl;
std::cout << str2 << ' ' << hexToDouble(str2) << std::endl;
return 0;
}
Related
I need to convert string to hex format and append "0x" prefix to hex value.
For Example:
Input: std::string s = "0x06A4";
Output: int num = 0x06A4
I have tried this code:
{
std::stringstream ss;
std::string s = "0x06A4";
int num = std::stoi(s, 0, 16);
std::cout << "value in decimal = " << num << '\n';
std::cout << "value in hexadecimal = " << std::hex << num << '\n';
ss << "0x" << std::hex << num << '\n'; //
std::string res = ss.str();
std::cout << "result " << res << '\n';
}
#yogita, std::hex is just one of the configuration you need. You are probably missing the setfill and the setw configuration, as following:
#include <iostream>
#include <sstream>
#include <iomanip>
int main()
{
std::stringstream ss;
std::string s = "0x06A4";
int num = std::stoi(s, nullptr, 16);
std::cout << "value in decimal = " << num << '\n';
std::cout << "value in hexadecimal = " << std::hex << num << '\n';
ss << "0x" << std::hex << std::setfill('0') << std::setw(4) <<num << '\n';
std::string res = ss.str();
std::cout << "result " << res << '\n';
return 0;
}
I want to convert a hexadecimal string to a decimal number (integer) in C++ and tried with following ways:
std::wstringstream SS;
SS << std::dec << stol(L"0xBAD") << endl;
But it returned 0 instead 2989.
std::wstringstream SS;
SS << std::dec << reinterpret_cast<LONG>(L"0xBAD") << endl;
But it returned -425771592 instead 2989.
But, when I use it like below, it works fine and gives 2989 as expect.
std::wstringstream SS;
SS << std::dec << 0xBAD << endl;
But I want to input a string and get 2989 as output, instead integer input like 0xBAD. For example, I want to input "0xBAD" and cast it to integer and then convert to a decimal number.
Thanks in advance.
// stol example
#include <iostream> // std::cout
#include <string> // std::string, std::stol
int main ()
{
std::string str_dec = "1987520";
std::string str_hex = "2f04e009";
std::string str_bin = "-11101001100100111010";
std::string str_auto = "0x7fffff";
std::string::size_type sz; // alias of size_t
long li_dec = std::stol (str_dec,&sz);
long li_hex = std::stol (str_hex,nullptr,16);
long li_bin = std::stol (str_bin,nullptr,2);
long li_auto = std::stol (str_auto,nullptr,0);
std::cout << str_dec << ": " << li_dec << '\n';
std::cout << str_hex << ": " << li_hex << '\n';
std::cout << str_bin << ": " << li_bin << '\n';
std::cout << str_auto << ": " << li_auto << '\n';
return 0;
}
I want to save the output from
std::cout << endl << std::setprecision(20) << std::fixed;
cout << ((.0000023)*(.00000023))<< endl;
Which is: 0.00000000000052900000
-into a string variable.
You could split this into steps using std::ostringstream:
std::ostringstream output;
output << << endl << std::setprecision(20) << std::fixed;
output << ((.0000023)*(.00000023))<< endl;
std::string result_string = output.str();
I suggest to try std::ostringstream:
std::ostringstream oss;
oss << ...;
std::string result(oss.str());
Note that it's slow on some platfroms/compilers.
See std::stringstream to stream into a string.
#include <string>
#include <sstream>
int main()
{
std::ostringstream stream;
stream << 10 + 10;
std::string result = stream.str(); // result contains "20"
return 0;
}
Edit: String manipulators work with std::ostringstream just like std::cout.
stream << std::fixed << (1.0 / 100.0); // result will contain "0.010000"
I need to print the exact hex value of a char variable using C++.
Here is my code:
#include <iostream>
#include <string>
#include <memory>
#include <sstream>
#include <iomanip>
int main()
{
char val = 0xfe;
std::stringstream ss1;
std::stringstream ss2;
ss1 << "#645" << std::setfill('0') << std::setw(2) << std::hex << val;
ss2 << "#645" << std::setfill('0') << std::setw(2) << std::hex << (int) val;
std::cout << ss1.str() << std::endl;
std::cout << ss2.str() << std::endl;
}
And my output:
#6450�
#645fffffffe
And what I expected:
#645FE
quick fix:
unsigned char val = 0xfe;
...
ss2 << "#645" << std::setfill('0') << std::setw(2) << std::hex << std::uppercase <<
(int) val;
or (as proposed by #Kerrek SB):
ss2 << "#645" << std::setfill('0') << std::setw(2) << std::hex << std::uppercase <<
static_cast<unsigned int>(static_cast<unsigned char>(val));
Note that if (on your platform) char defaults to signed char, then
0xfe is a negative number (-2).
In other words, if char is a signed char and sizeof(int) is 4, then
(int)val is 0xfffffffe. That is what you get.
-2 as signed char: 0xfe
-2 as int: 0xfffffffe
I wouldn't bother with streams manipulators when it's easier to do it yourself (exploiting the implicit conversion to unsigned char).
std::string hexb(unsigned char b) {
const char *s="0123456789ABCDEF";
return std::string(s[b>>4]) + s[b&0xf];
}
Usage:
std::cout<<hexb(val);
I'm getting string like 2015-04-29 15:36:16.5761891 +03:00. I can easily exctract the date using std::get_time.
std::tm time;
std::string stringTime = "2015-04-29 15:36:16.5761891 +03:00";
std::istringstream stringStream(stringTime);
stringStream >> std::get_time(&time, "%Y-%m-%d %H:%M:%S");
cout << time.tm_year << endl;
cout << time.tm_mon << endl;
cout << time.tm_mday << endl;
cout << time.tm_hour << endl;
cout << time.tm_min << endl;
cout << time.tm_sec << endl;
It's working fine for me. Now how can I extract UTC offset from this string?
You can just keep on reading like this:
#include <ctime>
#include <string>
#include <sstream>
#include <iomanip>
#include <iostream>
int main()
{
std::tm time;
std::string stringTime = "2015-04-29 15:36:16.5761891 +03:00";
std::istringstream stringStream(stringTime);
std::string decimals;
std::string offset;
stringStream >> std::get_time(&time, "%Y-%m-%d %H:%M:%S") >> decimals >> offset;
std::cout << time.tm_year << '\n';
std::cout << time.tm_mon << '\n';
std::cout << time.tm_mday << '\n';
std::cout << time.tm_hour << '\n';
std::cout << time.tm_min << '\n';
std::cout << time.tm_sec << '\n';
std::cout << decimals << '\n';
std::cout << offset << '\n';
}
Output:
115
3
29
15
36
16
.5761891
+03:00