Printing an 8-bit number in hexadecimal with IO manipulators - c++

I have a uint8_t and want to convert it to a two-digit hex string in C++ in the same way that the format string %02x would.
To do this, I've enlisted the help of a stringstream and IO manipulators to configure how the stream should format numbers:
#include <iomanip>
#include <iostream>
#include <sstream>
int main()
{
uint8_t x = 3;
std::cout << std::hex << std::setw(2) << std::setfill('0')
<< x << std::endl;
return 0;
}
So this should print 03 right? No, it prints 0.

Your Standard Libraries implementation of <cstdint> (btw. ... you didn't include it and uint8_t is in the namespace std) uses a typedef for uint8_t:
namespace std {
// ...
typedef char unsigned `uint8_t`
// ...
};
so std::ostream interprets it as character, not as an integer type. To make sure it gets interpreted as an integer just cast it explicitly:
#include <cstdint>
#include <iomanip>
#include <iostream>
int main()
{
std::uint8_t x{ 3 };
std::cout << std::hex << std::setw(2) << std::setfill('0')
<< static_cast<int>(x) << '\n';
}

Actually, it prints 0\0x03. That's right, it interprets the variable x as a character, not as a number.
The correct way to do this is to use the unary plus operator:
std::cout << std::hex << std::setw(2) << std::setfill('0')
<< +x << std::endl;

Related

std::hex cannot process negative numbers?

I'm trying to use std::hex to read hexadecimal integers from a file.
0
a
80000000
...
These integers are both positive and negative.
It seems that std::hex cannot handle negative numbers. I don't understand why, and I don't see a range defined in the docs.
Here is a test bench:
#include <iostream>
#include <sstream>
#include <iomanip>
int main () {
int i;
std::stringstream ss;
// This is the smallest number
// That can be stored in 32 bits -1*2^(31)
ss << "80000000";
ss >> std::hex >> i;
std::cout << std::hex << i << std::endl;
}
Output:
7fffffff
Setting std::hex tells the stream to read integer tokens as though using std::scanf with the %X formatter. %X reads into an unsigned integer, and the resulting value would overflow an int even through the bit pattern fits. Because of the overflow, the read fails, and the contents of i cannot be trusted to hold the expected value. Side note: i will be set to 0 if compiling to C++11 or more recent or unchanged from its current unspecified value before c++11.
Note that if we check the stream state after the read, something you should ALWAYS do, we can see that the read failed:
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdint> // added for fixed width integers.
int main () {
int32_t i; //ensure 32 bit int
std::stringstream ss;
// This is the smallest number
// That can be stored in 32 bits -1*2^(31)
ss << "80000000";
if (ss >> std::hex >> i)
{
std::cout << std::hex << i << std::endl;
}
else
{
std::cout << "FAIL! " << std::endl; //will execute this
}
}
The solution is, as the asker surmised in the comments to read into an unsigned int (uint32_t to avoid further surprises if int is not 32 bits). The following is the zero-surprises version of the code using memcpy to transfer the exact bit pattern read into i.
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdint> // added for fixed width integers.
#include <cstring> //for memcpy
int main () {
int32_t i; //ensure 32 bit int
std::stringstream ss;
// This is the smallest number
// That can be stored in 32 bits -1*2^(31)
ss << "80000000";
uint32_t temp;
if (ss >> std::hex >> temp)
{
memcpy(&i, &temp, sizeof(i));// probably compiles down to cast
std::cout << std::hex << i << std::endl;
}
else
{
std::cout << "FAIL! " << std::endl;
}
}
That said, diving into old-school C-style coding for a moment
if (ss >> std::hex >> *reinterpret_cast<uint32_t*>(&i))
{
std::cout << std::hex << i << std::endl;
}
else
{
std::cout << "FAIL! " << std::endl;
}
violates the strict aliasing rule, but I'd be stunned to see it fail once 32 bit int is forced with int32_t i;. This might even be legal in more recent C++ Standards as being "Type Similar", but I'm still wrapping my head around that.

std::hex and std::setw not working with some characters

What I'm trying to do is converting a string's bytes into hexadecimal format.
Based on this answer (and many others consistent) I've tried the code:
#include <sstream>
#include <iomanip>
#include <iostream>
int main ()
{
std::string inputText = u8"A7°";
std::stringstream ss;
// print every char of the string as hex on 2 values
for (unsigned int i = 0; i < inputText.size (); ++i)
{
ss << std::hex << std::setfill ('0') << std::setw (2) << (int) inputText[i];
}
std::cout << ss.str() << std::endl;
}
but with some characters coded in UTF 8 it does't work.
For Instance, in strings containing the degrees symbol ( ° ) coded in UTF8, the result is: ffffffc2ffffffb0 instead of c2b0.
Now I would expect the algorithm to work on individual bytes regardless of their contents and furthermore the result seems to ignore the setw(2) parameter.
Why does I get such a result?
(run test program here)
As Pete Becker already hinted in a comment, converting a negative value to a larger integer fills the higher bits with '1'. The solution is to first cast the char to unsigned char before casting it to int:
#include <string>
#include <iostream>
#include <iomanip>
int main()
{
std::string inputText = "-12°C";
// print every char of the string as hex on 2 values
for (unsigned int i = 0; i < inputText.size(); ++i)
{
std::cout << std::hex << std::setfill('0')
<< std::setw(2) << (int)(unsigned char)inputText[i];
}
}
setw sets the minimal width, it does not truncate longer values.

C++ double to hex console output need help in resolving

my code:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
double A = 100.35;
cout.precision(0);
cout << std::hexfloat << std::fixed << std::left << A << endl;
return 0;
}
Current output:
100
my expected output:
x64
Explanation:
I want to print the hex value of decimal part of double. But I have been unsuccessful in getting this. need help. Any help in this direction will be appreciated.
What you're asking for is simply not possible. std::hex (the output you're looking for) only works for integral arguments, and std::hexfloat uses an undesirable format. You need to cast or round.
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int main() {
double A = 100.35;
cout.precision(0);
cout << std::hex << std::showbase << std::lround(A) << endl;
return 0;
}

Convert a number from stringstream to string with a set precision

I would like to obtain a number from stringstream and set it to 5 significant figures. How do I do this? So far, this is what I have managed to come up with:
double a = 34.34566535
std::stringstream precisionValue;
precisionValue.precision(6) << a << std::endl;
However, this is not compiling. Thanks.
It doesn't compile because ios_base::precision() returns streamsize (it's an integral type).
You can use stream manipulators:
precisionValue << std::setprecision(6) << a << std::endl;
You'll need to include <iomanip>.
std::stringstream::precision() returns a streamsize, not a reference to the stream itself, which is required if you want to sequence << operators. This should work:
double a = 34.34566535;
std::stringstream precisionValue;
precisionValue.precision(6);
precisionValue << a << std::endl;
The precision member function returns current precision, not a reference to the stringstream, so you cannot chain the calls as you've done in the snippet.
precisionValue.precision(6);
precisionValue << a;
std::cout << precisionValue.str() << std::endl;
Or use the setprecision IO manipulator to chain the calls:
precisionValue << setprecision(6) << a;
std::cout << precisionValue.str() << std::endl;
You can use std::setprecision from header <iomanip>
#include <string>
#include <sstream>
#include <iomanip>
#include <iostream>
int main()
{
double a = 34.34566535;
std::stringstream precisionValue;
precisionValue << std::setprecision(6);
precisionValue << a << std::endl;
std::cout << precisionValue.str();
}

String manipulation, when converted show 0 in the beginning of the string

I want to know how can I make the string I converted from DWORD to onstringstream and then to AnsiString.
But that doesn't really matter, the conversion could be from int to string, I just want to know how I can make every string converted to ALWAYS show 6 digits, like if my number is 57, in the string it will be 000057.
Thanks!
Use io manipulators setfill and setw:
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
int main()
{
std::ostringstream s;
s << std::setfill('0') << std::setw(6) << 154;
std::cout << s.str() << "\n";
return 0;
}
So, the question about formatted output?
you can use iostream::width and `iostream::fill':
// field width
#include <iostream>
using namespace std;
int main () {
cout << 100 << endl;
cout.width(6);
cout.fill('0');
cout << 100 << endl;
return 0;
}