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

.

+3


source share


2 answers


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

.

+4


source


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.

0


source







All Articles