89 Stimmen

Wie kann ich 0x0a anstelle von 0xa mit cout drucken?

Wie kann ich 0x0a anstelle von 0xa mit cout drucken?

#include  <iostream>

using std::cout;  
using std::endl;  
using std::hex;

int main()  
{  
    cout << hex << showbase << 10 << endl;  
}

0 Stimmen

Was genau sind Ihre Anforderungen? Der Titel sagt 0x0a heißt es im Text Ihrer Frage 0x0A . In jedem Fall ist eine explizite std::cout << "0x0a" o std::cout << "0x0A" scheint Ihren Anforderungen zu entsprechen, aber ich nehme an, dass Sie wirklich eine Zahl formatieren wollen. Wie wollen Sie (z. B.) 16, 255, 256, 65536, -1 formatiert haben?

0 Stimmen

@Charles Die Frage bezog sich darauf, wie man die 0 nach dem x und vor dem A bzw. dem a druckt. Wie Sie sehen können, ist die erste Antwort falsch, da sie immer noch 0xa druckt (0xA, wenn Großbuchstaben verwendet werden). Aber wie auch immer, die Frage ist bereits als beantwortet markiert.

0 Stimmen

Aber warum die zusätzliche 0 ? Wollen Sie immer 0x0 oder benötigen Sie eine Mindestlänge für die Zeichenfolge?

143voto

Emile Cormier Punkte 27125

Das funktioniert bei mir im GCC:

#include  <iostream>
#include  <iomanip>

using namespace std;

int main()
{
    cout << "0x" << setfill('0') << setw(2) << right << hex << 10 << endl;
}

Wenn Sie die Formatierungswut von iostream satt haben, geben Sie Boost.Format einen Versuch. Es erlaubt gute altmodische, printf-ähnliche Formatspezifikationen und ist dennoch typsicher.

#include <iostream>
#include <boost/format.hpp>

int main()
{
    std::cout << boost::format("0x%02x\n") % 10;
}

UPDATE (2019)

Überprüfen Sie die Bibliothek {fmt} das akzeptiert wurde in C++20 . Benchmarks zeigen, dass es schneller als Boost.Format ist.

#if __has_include(<format>)
    #include <format>
    using std::format;
#else
    #include <fmt/format.h>
    using fmt::format;
#endif

std::cout << format("{:#04x}\n", 10);

0 Stimmen

Diese Antwort ist falsch. Wenn jemand cout << left << whatever erhalten Sie aufgrund der anhaltenden Links/Rechts-Verschiebung eine schlechte Ausgabe. Es sollte sein setfill('0') << setw(2) << right << hex um stets die richtige Ausrichtung zu gewährleisten.

2 Stimmen

@fuujuhi Falsch ? Das ist ziemlich hart. Ich würde sagen, dass es unvollständig ist. Aber danke für die Anregung.

3 Stimmen

@EmileCornier Entschuldigung, ich wollte nicht zu hart sein. In der Tat, unvollständig, aber leider kann zu bösen Bugs führen. Ich hatte in letzter Zeit zwei Bugs in meinem Code aufgrund von hartnäckigem iomanip (um ganz ehrlich zu sein: ich habe früher viel in C++ programmiert, aber jetzt nicht mehr), und das hat mich zu der Überzeugung gebracht, dass C++ iostream furchtbar falsch ist. Für eine moderne Sprache macht iostream das Drucken der einfachsten Dinge zu einem kompletten Albtraum. Man denkt, man druckt einen Integer, aber in Wirklichkeit druckt man ihn in Hex. Oder man bekommt "0x90" in der Ausgabe, aber in Wirklichkeit ist der Wert 0x09.

26voto

Doug T. Punkte 61739

Utilice setw y setfill von iomanip

#include  <iostream>
#include  <iomanip>

using std::cout;  
using std::endl;  
using std::hex;

int main()
{
    cout << "0x" << std::setfill('0') << std::setw(2) << hex << 10 << endl;
}

Mich persönlich stört der zustandsbehaftete Charakter von iostreams immer. Ich denke, das Boost-Format ist eine bessere Option, daher würde ich die andere Antwort empfehlen.

7 Stimmen

Ich bekomme auch 0xA. Warum ist es so verdammt schwer, iostream dazu zu bringen, Dinge so zu formatieren, wie man es möchte?

2 Stimmen

Das hat bei mir funktioniert: cout << "0x" << setfill('0') << setw(2) << hex << 10 << endl

1 Stimmen

@Doug T.: Ich habe mir die Freiheit genommen, Ihre Antwort zu bearbeiten, damit der Auftraggeber sie als die richtige Antwort akzeptieren kann.

9voto

Wenn Sie eine einfachere Möglichkeit zur Ausgabe einer Hexadezimalzahl suchen, könnten Sie eine Funktion wie die folgende schreiben:

Die aktualisierte Version wird unten dargestellt; es gibt zwei Möglichkeiten, die 0x Basisindikator eingefügt werden, mit Fußnoten, die die Unterschiede zwischen ihnen erläutern. Die ursprüngliche Version wird am Ende der Antwort beibehalten, um niemanden zu belästigen, der sie verwendet hat.

Beachten Sie, dass sowohl die aktualisierte als auch die ursprüngliche Version für Systeme, bei denen die Bytegröße ein Vielfaches von 9 Bit ist, möglicherweise etwas angepasst werden muss.

#include <type_traits> // For integral_constant, is_same.
#include <string>      // For string.
#include <sstream>     // For stringstream.
#include <ios>         // For hex, internal, [optional] showbase.
                       // Note: <ios> is unnecessary if <iostream> is also included.
#include <iomanip>     // For setfill, setw.
#include <climits>     // For CHAR_BIT.

namespace detail {
    constexpr int HEX_DIGIT_BITS = 4;
    //constexpr int HEX_BASE_CHARS = 2; // Optional.  See footnote #2.

    // Replaced CharCheck with a much simpler trait.
    template<typename T> struct is_char
      : std::integral_constant<bool,
                               std::is_same<T, char>::value ||
                               std::is_same<T, signed char>::value ||
                               std::is_same<T, unsigned char>::value> {};
}

template<typename T>
std::string hex_out_s(T val) {
    using namespace detail;

    std::stringstream sformatter;
    sformatter << std::hex
               << std::internal
               << "0x"                                             // See footnote #1.
               << std::setfill('0')
               << std::setw(sizeof(T) * CHAR_BIT / HEX_DIGIT_BITS) // See footnote #2.
               << (is_char<T>::value ? static_cast<int>(val) : val);

    return sformatter.str();
}

Sie kann wie folgt verwendet werden:

uint32_t       hexU32 = 0x0f;
int            hexI   = 0x3c;
unsigned short hexUS  = 0x12;

std::cout << "uint32_t:       " << hex_out_s(hexU32) << '\n'
          << "int:            " << hex_out_s(hexI)   << '\n'
          << "unsigned short: " << hex_out_s(hexUS)  << std::endl;

Sehen Sie sich beide Optionen (wie in den Fußnoten unten beschrieben) live an: aquí .

Fußnoten:

  1. Diese Zeile ist für die Darstellung der Basis verantwortlich und kann eine der folgenden sein:

    << "0x"
    << std::showbase
    • Die erste Option wird bei benutzerdefinierten Typen, die versuchen, negative Hex-Zahlen auszugeben, nicht korrekt angezeigt -0x## statt als <complement of 0x##> wobei das Vorzeichen nach der Basis angezeigt wird (wie 0x-## ) und nicht vor ihm. Dies ist sehr selten ein Problem, so dass ich persönlich diese Option bevorzuge.

      Wenn dies ein Problem ist, können Sie bei Verwendung dieser Typen vor der Ausgabe der Basis auf Negativität prüfen und dann mit abs() (o ein Brauch abs() die einen Wert ohne Vorzeichen zurückgibt wenn Sie in der Lage sein müssen, die höchstnegativen Werte in einem 2er-Komplement-System zu verarbeiten) auf val .

    • Bei der zweiten Option wird die Basis weggelassen, wenn val == 0 und zeigt (z. B. für int , donde int ist 32 Bit) 0000000000 statt der erwarteten 0x00000000 . Dies ist zurückzuführen auf die showbase Flagge, die behandelt wird wie printf() 's # Modifikator intern.

      Wenn dies ein Problem ist, können Sie prüfen, ob val == 0 und wenden Sie in diesem Fall eine Sonderbehandlung an.

  2. Je nachdem, welche Option für die Darstellung der Basis gewählt wurde, müssen zwei Zeilen geändert werden.

    • Bei Verwendung von << "0x" entonces HEX_BASE_CHARS ist unnötig und kann weggelassen werden.
    • Bei Verwendung von << std::showbase dann wird der Wert, der an setw() muss diesem Umstand Rechnung tragen:

      << std::setw((sizeof(T) * CHAR_BIT / HEX_DIGIT_BITS) + HEX_BASE_CHARS)

Die ursprüngliche Fassung lautet wie folgt:

// Helper structs and constants for hex_out_s().
namespace hex_out_helper {
    constexpr int HEX_DIGIT_BITS = 4; // One hex digit = 4 bits.
    constexpr int HEX_BASE_CHARS = 2; // For the "0x".

    template<typename T> struct CharCheck {
        using type = T;
    };

    template<> struct CharCheck<signed char> {
        using type = char;
    };

    template<> struct CharCheck<unsigned char> {
        using type = char;
    };

    template<typename T> using CharChecker = typename CharCheck<T>::type;
} // namespace hex_out_helper

template<typename T> std::string hex_out_s(T val) {
    using namespace hex_out_helper;

    std::stringstream sformatter;
    sformatter << std::hex
               << std::internal
               << std::showbase
               << std::setfill('0')
               << std::setw((sizeof(T) * CHAR_BIT / HEX_DIGIT_BITS) + HEX_BASE_CHARS)
               << (std::is_same<CharChecker<T>, char>{} ? static_cast<int>(val) : val);
    return sformatter.str();
}

Diese kann dann wie folgt verwendet werden:

uint32_t       hexU32 = 0x0f;
int            hexI   = 0x3c;
unsigned short hexUS  = 0x12;

std::cout << hex_out_s(hexU32) << std::endl;
std::cout << hex_out_s(hexI) << std::endl;
std::cout << "And let's not forget " << hex_out_s(hexUS) << std::endl;

Arbeitsbeispiel: aquí .

4 Stimmen

std::internal ! Du hast den großen Preis gewonnen! Das hat mir noch gefehlt! Vielen Dank @Justin Time.

0 Stimmen

@fljx Gern geschehen. Ich habe es verbessert, seit ich diese Antwort gepostet habe, also werde ich die Antwort bearbeiten, um dies zu berücksichtigen.

0 Stimmen

Soweit ich weiß, sollten die erforderlichen Includes irgendwo aufgeführt sein: climits , iomanip , iostream , types , string , stringstream mit Klimazonen für CHAR_BIT die mich dazu gebracht hat, diesen Kommentar zu schreiben.

6voto

vitaut Punkte 42467

In C++20 werden Sie in der Lage sein, Folgendes zu verwenden std::format um dies zu tun:

std::cout << std::format("{:02x}\n", 10);  

出力します。

0a

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

fmt::print("{:02x}\n", 10); 

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

3voto

lentz Punkte 31

Das Wichtigste, was in der Antwort fehlt, ist, dass Sie die right mit allen oben genannten Flaggen:

cout<<"0x"<<hex<<setfill('0')<<setw(2)<<right<<10;

1 Stimmen

Oder, wenn Sie Folgendes verwenden std::showbase statt nur auszugeben 0x direkt, Sie verwenden std::internal anstelle von std::right .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X