使用std :: cout打印零填充十六进制

jca*_*cai 13 c++ printf iostream cout

假设我有一个dword,我想用十六进制输出std :: cout和left-pad with zero,所以0xabcd将显示为0x0000abcd.看起来你必须这样做:

uint32_t my_int = 0xabcd;

std::cout << "0x" << std::hex << std::setw(8) << std::setfill('0')
    << my_int << std::endl;
Run Code Online (Sandbox Code Playgroud)

对于可以在C中完成的事情来说,这似乎很荒谬printf("0x%08X\n", my_int);.有没有办法让这个更短,同时仍然使用std :: cout输出(除了使用命名空间std)?

小智 14

我想你可以写一个"流操纵器".如果您要以此格式打印多个十六进制数,这将非常有用.这显然不是一个理想的解决方案,但使用包装器类型,您可以创建自己的"格式标志"来切换它.有关更多信息,请参阅Sticky自定义流操纵器.

#include <iostream>
#include <iomanip>

static int const index = std::ios_base::xalloc();

std::ostream& hexify(std::ostream& stream) {
    stream.iword(index) = 1;
    return stream;
}

std::ostream& nohexify(std::ostream& stream) {
    stream.iword(index) = 0;
    return stream;
}

struct WrapperType {
    uint32_t _m;
public:
    WrapperType(uint32_t m) : _m(m)
    {
    }

    uint32_t getm() const
    {
        return _m;
    }
};
std::ostream& operator<< (std::ostream& os, const WrapperType& t) {
    if (os.iword(index))
        return os << "0x" << std::hex << std::setw(8) << std::setfill('0') << t.getm();
    else
        return os << t.getm();
}

int main()
{
    WrapperType my_int{0xabcd};
    std::cout << hexify << my_int << my_int;
    std::cout << nohexify << my_int;
}
Run Code Online (Sandbox Code Playgroud)


小智 5

我不会改变流的(全局)标志,只是一个操纵器:

#include <iostream>
#include <iomanip>
#include <limits>

template <typename T>
struct Hex
{
    // C++11:
    // static constexpr int Width = (std::numeric_limits<T>::digits + 1) / 4;
    // Otherwise:
    enum { Width = (std::numeric_limits<T>::digits + 1) / 4 };
    const T& value;
    const int width;

    Hex(const T& value, int width = Width)
    : value(value), width(width)
    {}

    void write(std::ostream& stream) const {
        if(std::numeric_limits<T>::radix != 2) stream << value;
        else {
            std::ios_base::fmtflags flags = stream.setf(
                std::ios_base::hex, std::ios_base::basefield);
            char fill = stream.fill('0');
            stream << "0x" << std::setw(width) << value;
            stream.fill(fill);
            stream.setf(flags, std::ios_base::basefield);
        }
    }
};

template <typename T>
inline Hex<T> hex(const T& value, int width = Hex<T>::Width) {
    return Hex<T>(value, width);
}

template <typename T>
inline std::ostream& operator << (std::ostream& stream, const Hex<T>& value) {
    value.write(stream);
    return stream;
}

int main() {
    std::uint8_t u8 = 1;
    std::uint16_t u16 = 1;
    std::uint32_t u32 = 1;
    std::cout << hex(unsigned(u8), 2) << ", " << hex(u16) << ", " << hex(u32) << '\n';
}
Run Code Online (Sandbox Code Playgroud)