Pad leads zeros in multiples of x using std :: cout << std :: hex
There are many questions as to how to use a fixed number of leading zeros when using C ++ streams with variables that we want to represent in hexadecimal:
std::cout << std::hex << setfill('0') << setw(8) << myByteSizedVar;
My question is about how to do this for not a fixed width, but a multiple of some fixed amount - probably 8 for the obvious reason that when comparing outputs, we might want to:
0x87b003a 0xab07
To make it easier to match widths for comparison (ok, the top is larger, but try a bitwise comparison in your head? Easy to get confused.)
0x87b003a 0x000ab07
Nice, two bytes lined up nicely and neatly. Except we only see 7 bits - it's not immediately obvious (especially if it was 15/16, 31/32, etc.), which may have caused us to mistake the upper for a negative number (assuming signed).
All is well and good, we can set the width to 8 as above.
However, when matching the following, for example a 32-bit word:
0x000000000000000000000000087b003a 0x238bfa700af26fa930b00b130b3b022b
This may be more unnecessary, depending on usage, or even misleading when dealing with hardware where the top number actually has no context in which the 32-bit word should be.
I would like to automatically set the width of the number to a multiple of 8, for example:
std::cout << std::hex << std::setfill('0') << setWidthMultiple(8) << myVar;
For results like:
0x00000000 0x388b7f62 0x0000000f388b7f62
How is this possible with standard libraries or minimal amount of code? Without something like Boost.Format
.
source share
How about this:
template <typename Int> struct Padme { static_assert(std::is_unsigned<Int>::value, "Unsigned ints only"); Int n_; explicit Padme(Int n) : n_(n) {} template <typename Char, typename CTraits> friend std::basic_ostream<Char, CTraits> & operator<<( std::basic_ostream<Char, CTraits> & os, Padme p) { return os << std::setw(ComputeWidth(p.n_)) << p.n_; } static std::size_t ComputeWidth(Int n) { if (n < 0x10000) { return 4; } if (n < 0x100000000) { return 8; } if (n < 0x1000000000000) { return 12; } return 16; } }; template <typename Int> Padme<Int> pad(Int n) { return Padme<Int>(n); }
Using:
std::cout << pad(129u) << "\n";
With additional work, you can provide versions with different digit group sizes, different numbers, etc. And for signed types, you can insert std::make_unsigned
functions into the template pad
.
source share
There is no immediate support because it involves more than one input value (if I understand what you are asking for correctly). The only solution that comes to mind is to use
std::max
to find the largest value and then print out the number of digits you want, say using a table:
struct DigitCount { unsigned long long maxValue; int digits; }; static const DigitCount digitCount[] = { { 255UL, 2 }, { 65535UL, 4 }, { 16777215UL, 6 }, { 4294967295UL, 8 }, };
and looking at the width in it.
source share