2014-01-28 17 views
10

Angenommen, ich habe ein dword, das ich in hex ausgeben soll mit std :: cout und links-pad mit Nullen, so 0xabcd wird als 0x0000abcd angezeigt. Es scheint, wie Sie hätte dies tun:Drucken zero-padded hex mit std :: cout

uint32_t my_int = 0xabcd; 

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

Das für etwas lächerlich scheint, die mit printf("0x%08X\n", my_int); in C erreicht werden kann. Gibt es eine Möglichkeit, dies kürzer zu machen, während immer noch std :: cout für die Ausgabe verwendet wird (neben der Verwendung von Namespace std)?

+3

eine Funktion zur Ausgabe als formatierte hex schreiben und es nennen. – GManNickG

+1

Kürzere ist eine relative Sache, nehme ich an. Wenn Sie denken, dass der Code hinter diesem 'printf()' kurz ist, kann ich Ihnen versichern, dass es alles andere als ist. Sie müssen nur Ihre eigenen rollen (was ähnlich wie Sie hier schockierend aussehen wird). Sie können immer ein Manipulator Klasse/Operator-Paar schreiben, die so etwas wie 'std :: cout << as_hex (n, 8,0) erlaubt;' – WhozCraig

Antwort

12

Ich nehme an, Sie können eine "Stream-Manipulator" schreiben. Dies ist nützlich, wenn Sie mehrere Hex-Zahlen haben, die Sie in diesem Format drucken möchten. Dies ist eindeutig keine ideale Lösung, aber mit einem Wrapper-Typ können Sie Ihr eigenes "Format Flag" erstellen, um es umzuschalten. Weitere Informationen finden Sie unter 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 völlig die Art, wie ich tun würde dies, aber die Breite Manipulator zurückgesetzt (wie ich mich erinnere) auf jeder Ausgabe an den Stream 'Operator <<', so dass Sie Teil machen müssen kann es aus einem paramaterized Manipulator. Ich mag mich darin irren, aber es scheint so zu sein, als hätten sie gearbeitet (oder es war das Gegenteil und ich habe einen legasthenischen Moment). Edit: nur getestet, du hast vollkommen recht. Ich war Legastheniker. sey für die Verwirrung. – WhozCraig

+0

@WhozCraig Ich habe meine Antwort bearbeitet, aber ich bin mir nicht sicher, ob es besser ist. Ich meine, es kann nervig sein, sich daran zu erinnern, für Formatierungszwecke 'WrapperType' zu ​​verwenden, wo Ihre Lösung, eine Funktion einfach zu verwenden, besser ist. Aber wenn OP faul ist, würde das vielleicht Tipparbeit sparen. –

3

Ich würde nicht die (globale) Fahnen eines Stroms ändern, nur einen Manipulator:

#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'; 
}