Печать ноль-padded hex с std:: cout
Скажем, у меня есть dword, который я хочу вывести в hex с std:: cout и left-pad с нулями, поэтому 0xabcd будет отображаться как 0x0000abcd. Похоже, вам придется это сделать:
uint32_t my_int = 0xabcd;
std::cout << "0x" << std::hex << std::setw(8) << std::setfill('0')
<< my_int << std::endl;
Это кажется смешным для чего-то, что может быть выполнено на C с printf("0x%08X\n", my_int);
. Есть ли способ сделать это короче при использовании std:: cout для вывода (помимо использования пространства имен std)?
Ответы
Ответ 1
Я полагаю, вы можете написать "манипулятор потока". Это полезно, если у вас есть несколько шестнадцатеричных чисел, которые вы хотите распечатать в этом формате. Это явно не идеальное решение, но с использованием типа обертки вы можете сделать свой собственный флаг формата для его переключения. Подробнее см. Привилегированный пользовательский манипулятор потока.
#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;
}
Ответ 2
Я бы не изменил (глобальные) флаги потока, просто манипулятор:
#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';
}
Ответ 3
Мой С++ ржавый, но как насчет использования форматирования форматирования: http://www.boost.org/doc/libs/1_37_0/libs/format/index.html