简体   繁体   English

使用std :: cout << std :: hex填充x的倍数的前导零

[英]Pad leading zeroes in multiples of x, using std::cout << std::hex

There are many questions regarding how to pad a fixed number of leading zeroes when using C++ streams with variables we want represented in hexadecimal format: 当使用带有我们想要的十六进制格式的变量的C ++流时,有很多关于如何填充固定数量的前导零的问题

std::cout << std::hex << setfill('0') << setw(8) << myByteSizedVar;

My question regards how to do this for not a fixed width, but a multiple of some fixed amount - likely 8 for the obvious reason that when comparing outputs we might want: 我的问题是如何做到这一点不是一个固定的宽度,而是一些固定数量的倍数 - 可能是8,因为明显的原因是在比较输出时我们可能需要:

0x87b003a
0xab07

To match up for width to be compared more easily (okay the top is larger - but try a bitwise comparison in your head? Easily confused.) 要比较宽度以便更容易进行比较(好吧顶部更大 - 但是尝试在头脑中进行逐位比较?容易混淆。)

0x87b003a
0x000ab07

Nice, two bytes lined up nice and neatly. 不错,两个字节排列整齐,整齐。 Except we only see 7 bits - which is not immediately obvious (especially if it were 15/16, 31/32, etc.), possibly causing us to mistake the top for a negative number (assuming signed). 除了我们只看到7位 - 这不是立即明显的(特别是如果它是15 / 16,31 / 32等),可能导致我们将顶部误认为负数(假设已签名)。

All well and good, we can set the width to 8 as above. 一切顺利,我们可以将宽度设置为8,如上所述。

However, when making the comparison next to say a 32-bit word: 但是,在进行比较时,请说一个32位字:

0x000000000000000000000000087b003a
0x238bfa700af26fa930b00b130b3b022b

It may be more unneccessary, depending on the use, or even misleading if dealing with hardware where the top number actually has no context in which to be a 32-bit word. 根据使用情况,它可能更不必要,或者如果处理硬件,其中顶部数字实际上没有上下文中的32位字,则可能更加不必要。

What I would like, is to automagically set the width of the number to be a multiple of 8, like: 我想要的是,自动将数字的宽度设置为8的倍数,如:

std::cout << std::hex << std::setfill('0') << setWidthMultiple(8) << myVar;

For results like: 对于以下结果:

0x00000000
0x388b7f62
0x0000000f388b7f62

How is this possible with standard libraries, or a minimal amount of code? 如何使用标准库或少量代码实现这一点? Without something like Boost.Format . 没有像Boost.Format这样的东西。

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); }

Usage: 用法:

std::cout << pad(129u) << "\n";

With some more work you could provide versions with different digit group sizes, different number bases etc. And for signed types you could stick std::make_unsigned into the pad function template. 通过一些更多的工作,您可以提供具有不同数字组大小,不同数字基础等的版本。对于签名类型,您可以将std::make_unsignedpad函数模板中。

There's no immediate support for it, because it involves more than one input value (if I understand what you're asking for correctly). 没有立即支持它,因为它涉及多个输入值(如果我理解你正确要求的话)。 The only solution which comes to mind is to use std::max to find the largest value, and then derive the number of digits you need from that, say by using a table: 想到的唯一解决方案是使用std::max来查找最大值,然后从中获取所需的位数,例如使用表:

struct DigitCount
{
    unsigned long long maxValue;
    int digits;
};
static const DigitCount digitCount[] =
{
    {        255UL, 2 },
    {      65535UL, 4 },
    {   16777215UL, 6 },
    { 4294967295UL, 8 },
};

and looking up the width in it. 并查看其中的宽度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM