2014-01-28 2 views
10

Скажите, что у меня есть dword. Я хочу вывести в шестнадцатеричном виде с std :: cout и левым pad с нулями, поэтому 0xabcd будет отображаться как 0x0000abcd. Похоже, что вы должны сделать это:Печать нулевого заполнения hex с std :: cout

uint32_t my_int = 0xabcd; 

std::cout << "0x" << std::hex << std::setw(8) << std::setfill('0') 
    << my_int << std::endl; 

Это кажется смешным то, что может быть достигнуто в С printf("0x%08X\n", my_int);. Есть ли способ сделать это короче при использовании std :: cout для вывода (помимо использования пространства имен std)?

+3

Написать функцию вывода в виде форматированного шестнадцатеричном и назвать его. – GManNickG

+1

Короче это относительная вещь, я полагаю. Если вы считаете, что код, стоящий за этим 'printf()', короткий, я могу заверить вас, что это ничего, кроме. Вам просто нужно бросить свой собственный (что будет выглядеть шокирующим, как у вас здесь). Вы всегда можете написать пару класса/оператора манипулятора, которая позволяет что-то вроде 'std :: cout << as_hex (n, 8,0);' – WhozCraig

ответ

12

Я полагаю, вы можете написать «поток манипулятором». Это полезно, если у вас есть несколько шестнадцатеричных чисел, которые вы хотите распечатать в этом формате. Это явно не идеальное решение, но с использованием типа обертки вы можете сделать свой собственный флаг формата для его переключения. См. Sticky custom stream manipulator для получения дополнительной информации.

#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; 
} 
+0

+1 полностью, как я бы это сделал, но манипулятор ширины сбрасывается (как я помню) при каждой выдаче потоку 'operator <<', поэтому вам может понадобиться сделать его частью манипулятора с параметризацией. Возможно, я ошибаюсь, но похоже, что так они работали (или это было наоборот, и у меня был дислексический момент). Редактирование: просто проверено, вы совершенно правы. Я был дислексичен. смущайся за путаницу. – WhozCraig

+0

@WhozCraig Я отредактировал свой ответ, но я не уверен, что это лучше. Я имею в виду, что может быть неприятно вспоминать использование 'WrapperType' для целей форматирования, где лучше всего использовать ваше решение только для использования функции. Но если OP ленив, возможно, это спасет печатание. –

3

Я бы не изменить (глобальные) флаги потока, только манипулятором:

#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'; 
} 
Смежные вопросы