Wie drucke ich ein Zeichen ohne Vorzeichen als Hex in C++ mit ostream?

Lesezeit: 2 Minuten

Wie drucke ich ein Zeichen ohne Vorzeichen als Hex in
Nathan Fellmann

Ich möchte mit vorzeichenlosen 8-Bit-Variablen in C++ arbeiten. Entweder unsigned char oder uint8_t machen den Trick, was die Arithmetik betrifft (was erwartet wird, da AFAIK uint8_t ist nur ein Alias ​​für unsigned charoder so präsentiert es der Debugger.

Das Problem ist, dass, wenn ich die Variablen mit ostream in C++ ausdrucke, sie als char behandelt werden. Wenn ich habe:

unsigned char a = 0;
unsigned char b = 0xff;
cout << "a is " << hex << a <<"; b is " << hex << b << endl;

dann ist die Ausgabe:

a is ^@; b is 377

anstatt

a is 0; b is ff

Ich habe versucht, mit uint8_taber wie ich bereits erwähnt habe, ist das typdefiniert unsigned char, also tut es dasselbe. Wie kann ich meine Variablen korrekt drucken?

Bearbeiten: Ich mache das an vielen Stellen in meinem Code. Gibt es eine Möglichkeit, wie ich dies tun kann ohne Gießen zu int Jedes Mal, wenn ich drucken möchte?

  • Ich denke, die Antwort von MartinStettner ist ziemlich verwirrend, ich denke nicht, dass es sich lohnt, eine zusätzliche Struktur und einen zusätzlichen Stream-Operator zu implementieren. Die Lösung von anon ist einfach und funktioniert gut genug für mich.

    – tdihp

    28. September 2012 um 8:38 Uhr

Verwenden:

cout << "a is " << hex << (int) a <<"; b is " << hex << (int) b << endl;

Und wenn Sie mit führenden Nullen auffüllen möchten, dann:

#include <iomanip>
...
cout << "a is " << setw(2) << setfill('0') << hex << (int) a ; 

Da wir Casts im C-Stil verwenden, warum nicht mit Terminal-C++-Bösartigkeit aufs Ganze gehen und ein Makro verwenden!

#define HEX( x )
   setw(2) << setfill('0') << hex << (int)( x )

kannst du dann sagen

cout << "a is " << HEX( a );

Bearbeiten: Allerdings ist die Lösung von MartinStettner viel schöner!

  • Kann ich Sie überzeugen, die bösen C-Style-Casts ein für alle Mal zu meiden? stackoverflow.com/questions/527999/…

    – Konrad Rudolf

    23. März 2009 um 12:54 Uhr

  • Nicht in diesem Fall – es ist ungefähr der einzige Ort, an dem sie meiner Meinung nach gerechtfertigt sind.

    anon

    23. März 2009 um 12:57 Uhr

  • Ich würde es genauso machen, außer um den Cast zu vermeiden, würde ich cout << hex << int(a) verwenden; Es bedeutet dasselbe wie eine Besetzung, ohne die Besetzung. :)

    – Brian Neal

    23. März 2009 um 14:35 Uhr

Wie drucke ich ein Zeichen ohne Vorzeichen als Hex in
Martin Stettner

Ich würde vorschlagen, die folgende Technik zu verwenden:

struct HexCharStruct
{
  unsigned char c;
  HexCharStruct(unsigned char _c) : c(_c) { }
};

inline std::ostream& operator<<(std::ostream& o, const HexCharStruct& hs)
{
  return (o << std::hex << (int)hs.c);
}

inline HexCharStruct hex(unsigned char _c)
{
  return HexCharStruct(_c);
}

int main()
{
  char a = 131;
  std::cout << hex(a) << std::endl;
}

Es ist kurz zu schreiben, hat die gleiche Effizienz wie die ursprüngliche Lösung und lässt Sie wählen, ob Sie die “ursprüngliche” Zeichenausgabe verwenden möchten. Und es ist typsicher (es werden keine “bösen” Makros verwendet :-))

  • Solange wir Makros meiden: Um vollständiger C++ zu sein, sollten Sie nicht schreiben (int)hs.c als static_cast<int>(hs.c)? 😛

    – Seth Johnson

    8. Juli 2009 um 11:10 Uhr

  • Es gibt einen kleinen Fehler in Ihrem Code. Wenn Sie im Code ein negatives Zeichen eingeben, wird der Hex-Wert 4 Bytes statt 2. Umschalten auf unsigned char behebt das Problem.

    –Ted

    22. Februar 2010 um 22:47 Uhr

  • Ein weiterer Fehler (?) ist der oben genannte operator<< ändert den Modus des angegebenen Streams in hexadezimal: cout << hex(a) << 100 wird Sie überraschen. Sie sollten den Status des Streams speichern, bevor Sie ihn ändern, und ihn später wiederherstellen.

    – musiphil

    19. Juni 2012 um 20:23 Uhr

  • Ich bin wirklich erstaunt, wie schlecht C++ beim Konvertieren ist char zu Hex.

    – Craig Ringer

    6. Februar 2018 um 6:17 Uhr

Mehr dazu können Sie unter nachlesen http://cpp.indi.frih.net/blog/2014/09/tippet-printing-numeric-values-for-chars-and-uint8_t/ und http://cpp.indi.frih.net/blog/2014/08/code-critique-stack-overflow-posters-cant-print-the-numeric-value-of-a-char/. Ich poste dies nur, weil klar geworden ist, dass der Autor der obigen Artikel dies nicht beabsichtigt.

Die einfachste und korrekteste Technik, um ein Zeichen als Hex zu drucken, ist

unsigned char a = 0;
unsigned char b = 0xff;
auto flags = cout.flags(); //I only include resetting the ioflags because so
                           //many answers on this page call functions where
                           //flags are changed and leave no way to  
                           //return them to the state they were in before 
                           //the function call
cout << "a is " << hex << +a <<"; b is " << +b << endl;
cout.flags(flags);

Die Readers Digest-Version davon, wie dies funktioniert, ist, dass der unäre +-Operator eine Typkonvertierung von no op in ein int mit der korrekten Vorzeichenbelegung erzwingt. Ein unsigned char wird also in unsigned int konvertiert, ein signed char wird in int konvertiert und ein char wird entweder in unsigned int oder int konvertiert, je nachdem, ob char auf Ihrer Plattform signiert oder nicht signiert ist (es ist für viele ein Schock, dass char etwas Besonderes ist und weder signiert noch unsigniert angegeben).

Der einzige Nachteil dieser Technik ist, dass es möglicherweise nicht offensichtlich ist, was jemandem passiert, der damit nicht vertraut ist. Ich denke jedoch, dass es besser ist, die richtige Technik zu verwenden und andere darüber zu unterrichten, als etwas zu tun, das falsch, aber sofort klar ist.

  • Warum ist dies nicht die Top-Antwort? Es ist kurz und effektiv.

    – James Pack

    23. März 2015 um 2:22 Uhr

  • Bei dieser Technik werden Typen kleiner als vorzeichenerweitert unsigned int / intwas bedeutet, dass Sie für negative Zeichen mit Vorzeichen (oder z. B. int16_t) 8 Ausgabe-Nibbles erhalten, von denen die ersten 6 sind F.

    – Brian McFarland

    13. März 2016 um 3:29 Uhr

  • @BrianMcFarland Ich habe dieses Problem sogar für unsigned char bemerkt (wenn es größer als 127 ist), also habe ich es mit einer Bitmaske gelöst: (+c & 0xFF).

    – Nach SE

    22. November 2016 um 1:24 Uhr

  • @To마SE, das Unäre + ist unnötig, die binäre & wandelt sich bereits in eine um int.

    – Adrian

    21. Juni 2019 um 1:02 Uhr

Nun, das funktioniert bei mir:

std::cout << std::hex << (0xFF & a) << std::endl;

Wenn Sie nur werfen (int) Wie vorgeschlagen, könnte es 1s links von hinzufügen a wenn sein höchstwertiges Bit 1 ist. Wenn Sie also diese binäre UND-Operation durchführen, wird garantiert, dass die linken Bits der Ausgabe mit 0 gefüllt werden, und sie wird auch in unsigned int konvertiert, wodurch cout gezwungen wird, sie als Hex auszugeben.

Ich hoffe das hilft.

1646352608 531 Wie drucke ich ein Zeichen ohne Vorzeichen als Hex in
vitaut

In C++20 können Sie verwenden std::format um dies zu tun:

std::cout << std::format("a is {:x}; b is {:x}\n", a, b);

Ausgabe:

a is 0; b is ff

In der Zwischenzeit können Sie verwenden die {fmt}-Bibliothek, std::format basiert auf. {fmt} bietet auch die print Funktion, die dies noch einfacher und effizienter macht (Gottriegel):

fmt::print("a is {:x}; b is {:x}\n", a, b);

Haftungsausschluss: Ich bin der Autor von {fmt} und C++20 std::format.

Hm, anscheinend habe ich gestern das Rad neu erfunden … Aber hey, zumindest ist es diesmal ein generisches Rad 🙂 chars werden mit zwei Hex-Ziffern gedruckt, shorts mit 4 Hex-Ziffern und so weiter.

template<typename T>
struct hex_t
{
    T x;
};

template<typename T>
hex_t<T> hex(T x)
{
    hex_t<T> h = {x};
    return h;
}

template<typename T>
std::ostream& operator<<(std::ostream& os, hex_t<T> h)
{
    char buffer[2 * sizeof(T)];
    for (auto i = sizeof buffer; i--; )
    {
        buffer[i] = "0123456789ABCDEF"[h.x & 15];
        h.x >>= 4;
    }
    os.write(buffer, sizeof buffer);
    return os;
}

1646352609 810 Wie drucke ich ein Zeichen ohne Vorzeichen als Hex in
tdihp

Ich denke, die Antwort von TrungTN und anon ist in Ordnung, aber MartinStettners Art, die hex()-Funktion zu implementieren, ist nicht wirklich einfach und zu dunkel, wenn man bedenkt, dass hex << (int)mychar bereits eine Problemumgehung ist.

Hier ist meine Lösung, um den Operator “<<" einfacher zu machen:

#include <sstream>
#include <iomanip>

string uchar2hex(unsigned char inchar)
{
  ostringstream oss (ostringstream::out);
  oss << setw(2) << setfill('0') << hex << (int)(inchar);
  return oss.str();
}

int main()
{
  unsigned char a = 131;
  std::cout << uchar2hex(a) << std::endl;
}

Es lohnt sich einfach nicht, einen Stream-Operator zu implementieren 🙂

928890cookie-checkWie drucke ich ein Zeichen ohne Vorzeichen als Hex in C++ mit ostream?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy