How can I print 0x0a instead of 0xa using cout?
Asked Answered
M

10

89

How can I print 0x0a, instead of 0xa using cout?

#include  <iostream>

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

int main()  
{  
    cout << hex << showbase << 10 << endl;  
}
Moyra answered 22/4, 2011 at 21:29 Comment(6)
What exactly are your requirements. The title says 0x0a, the body of your question says 0x0A. Either way an explicit std::cout << "0x0a" or std::cout << "0x0A" would seem to meet your requirements but I assume that you really want to format a number. How do you want (e.g.) 16, 255, 256, 65536, -1 to be formatted?Pushy
@Charles The question was about how to print the 0 after the x and before the A, or the a, for that matter. As you can verify the first answer is wrong since it still prints 0xa (0xA if uppercase is used). But anyway the question is already marked as answered.Moyra
But why the extra 0? Do you always want 0x0 or do you need a minimum length for the string?Pushy
If the hex number is 0xA I want it 0x0A. If the number is 0x123 I want it 0x0123, and so forth, i.e., an even number of hex digits.Moyra
I don't think that you've understood what I'm driving at. You've specified exactly how you want 10 to appear, but what about 1 to 9 and 11 to 15? What about 256? Do you want 0x0a because you want a minimum width or because you always want a leading zero? Unless your exact with your specification you may not get the answers that you want.Pushy
possible duplicate of How can I pad an int with leading zeros when using cout << operator?Lanugo
D
143

This works for me in GCC:

#include  <iostream>
#include  <iomanip>

using namespace std;

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

If you are getting sick and tired of iostream's formatting quirkiness, give Boost.Format a try. It allows good-old-fashioned, printf-style format specifiers, yet it is type-safe.

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

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

UPDATE (2019)

Check out the {fmt} library that's been accepted into C++20. Benchmarks show it to be faster than Boost.Format.

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

std::cout << format("{:#04x}\n", 10);
Discommon answered 22/4, 2011 at 21:53 Comment(3)
This answer is wrong. If someone did cout << left << whatever before, you'll get bad output because of persistent left/right iomanip. It should be setfill('0') << setw(2) << right << hex to always guarantee right alignment.Disapprobation
@Disapprobation Wrong? That's rather harsh. I'd say that it's incomplete. Thanks for the suggestion, though.Discommon
@EmileCornier Sorry, did not mean to be harsh. Indeed, incomplete, but unfortunately may lead to nasty bugs. Had two bugs in my code lately because of persistent iomanip (full disclosure: I used to code a lot in C++, but not anymore), and this made me think that C++ iostream is terribly wrong. For a modern language, iostream makes printing the simplest things a complete nightmare. You think you print an integer, but in fact you print it in hex. Or, you get "0x90" in the output, but in fact the value is 0x09.Disapprobation
M
26

Use setw and setfill from 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;
}

Personally, the stateful nature of iostreams always annoys me. I think boost format is a better option, so I'd recommended the other answer.

Muncey answered 22/4, 2011 at 21:30 Comment(12)
I get 0xA too. Why is it so damn HARD to get iostream to format things the way you want??Discommon
This worked for me: cout << "0x" << setfill('0') << setw(2) << hex << 10 << endlDiscommon
@Doug T.: I took the liberty of editing your answer so that the OP may accept it as the answer that worked.Discommon
@Potatoswatter: setw(2) doesn't seem to play nice with showbase, at least in gcc 4.4.3. Maybe it's a bug in GCC?Discommon
When I use cout << showbase << setfill('0') << setw(2) << hex << 10 << endl; I still get 0xa in GCC.Discommon
@EmileCormier: 0xa is already wider than 2 characters so setw(2) isn't going to do anything. @Potatoswatter: In this case I think an explicit 0x is reasonable. setw(4) << hex << setfill('0') << showbase << 10 isn't going to have the desired effect (00xa!).Pushy
@Charles: Sorry, I forget setiosflags(ios::internal). This works: cout << showbase << setiosflags(ios::internal) << setfill('0') << setw(4) << hex << 10 << endl; Demo: ideone.com/WlusBProvided
@Potatoswatter: Nice, I didn't know that would work! internal: "adds fill characters at a designated internal point in certain generated output, or identical to right if no such point is designated" That's either underspecified or very cryptically specified.Pushy
@Charles @Emile thanks for your help, I didn't have time to test my answer. I think we've illustrated that iostreams can be frustrating to verify they're working just by looking.Muncey
@Charles: See table 61, §22.2.2.2.2/19 (isn't quoting iostreams fun? There is indeed a §22.2.2.2.2/22). @Doug: Without a doubt, iostreams is one of the worst interfaces to become portable enough that anyone was inclined to learn it.Provided
i prefer this rather than boost, you just have to remember to reset the iomanipulatorsImogeneimojean
note that you may need to call setw before each << n, at least that was the case for meTjaden
T
9

If you want to make an easier way to output a hex number, you could write a function like this:

Updated version is presented below; there are two ways the 0x base indicator can be inserted, with footnotes detailing the differences between them. The original version is preserved at the bottom of the answer, so as not to inconvenience anyone that was using it.

Note that both the updated and original versions may need some tailoring for systems where the byte size is a multiple of 9 bits.

#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();
}

It can be used as follows:

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;

See both options (as detailed in footnotes, below) live: here.

Footnotes:

  1. This line is responsible for showing the base, and can be either of the following:

    << "0x"
    << std::showbase
    
    • The first option will display improperly for custom types that try to output negative hex numbers as -0x## instead of as <complement of 0x##>, with the sign displaying after the base (as 0x-##) instead of before it. This is very rarely an issue, so I personally prefer this option.

      If this is an issue, then when using these types, you can check for negativity before outputting the base, then using abs() (or a custom abs() that returns an unsigned value, if you need to be able to handle the most-negative values on a 2's complement system) on val.

    • The second option will omit the base when val == 0, displaying (e.g., for int, where int is 32 bits) 0000000000 instead of the expected 0x00000000. This is due to the showbase flag being treated like printf()'s # modifier internally.

      If this is an issue, you can check whether val == 0, and apply special handling when it does.

  2. Depending on which option was chosen for showing the base, two lines will need to be changed.

    • If using << "0x", then HEX_BASE_CHARS is unnecessary, and can be omitted.
    • If using << std::showbase, then the value supplied to setw() needs to account for this:

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

The original version is as follows:

// 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();
}

Which can then be used like this:

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;

Working example: here.

Trumpetweed answered 12/3, 2016 at 21:8 Comment(5)
std::internal! You won the big prize! That's what I was missing! Thank you @Justin Time.Cowbird
@fljx You're welcome. I've improved on it since I posted this answer, so I'll edit the answer to reflect this.Trumpetweed
The required includes should be listed somewhere for this, from what I glance: climits, iomanip, iostream, types, string, stringstream with climits for CHAR_BIT being the one making me write this comment.Pharynx
Good idea, @mxmlnkn. Updated. (Also, it technically requires ios instead of iostream, but that's moot because iostream is required to include ios anyways. Noted this in the answer, as well.)Trumpetweed
Note that this might need to be modified to support C++20 char8_t, and that it might also be useful to have it treat all character types ([[un]signed] char, charN_t, wchar_t) identically for convenience. In this case, it will likely be best to cast to char_traits<T>::int_type when is_char<T> is true, since we already use <string>. [I'm currently waiting to see how things play out before doing so, though.]Trumpetweed
R
6

In C++20 you'll be able to use std::format to do this:

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

Output:

0a

In the meantime you can use the {fmt} library, std::format is based on. {fmt} also provides the print function that makes this even easier and more efficient (godbolt):

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

Disclaimer: I'm the author of {fmt} and C++20 std::format.

Registered answered 3/3, 2021 at 1:56 Comment(0)
T
3

The important thing that the answer is missing is that you must use right with all of the above mentioned flags:

cout<<"0x"<<hex<<setfill('0')<<setw(2)<<right<<10;
Titian answered 16/10, 2015 at 11:34 Comment(1)
Or, if you're using std::showbase instead of just outputing 0x directly, you use std::internal instead of std::right.Trumpetweed
C
1

try this.. you simply prepend zeroes based on magnitude.

cout << hex << "0x" << ((c<16)?"0":"") << (static_cast<unsigned int>(c) & 0xFF) << "h" << endl;

You can easily modify this to work with larger numbers.

cout << hex << "0x";
cout << ((c<16)?"0":"") << ((c<256)?"0":"");
cout << (static_cast<unsigned int>(c) & 0xFFF) << "h" << endl;

Factor is 16 (for one hex-digit):
16, 256, 4096, 65536, 1048576, ..
respective
0x10, 0x100, 0x1000, 0x10000, 0x100000, ..

Therefore you could also write like this..

cout << hex << "0x" << ((c<0x10)?"0":"") << ((c<0x100)?"0":"") << ((c<0x1000)?"0":"") << (static_cast<unsigned int>(c) & 0xFFFF) << "h" << endl;

And so on.. :P

Conglobate answered 19/8, 2014 at 13:24 Comment(0)
P
1

To shorten things up for outputting hex, I made a simple macro

#define PADHEX(width, val) setfill('0') << setw(width) << std::hex << (unsigned)val

then

cout << "0x" << PADHEX(2, num) << endl;
Planter answered 24/2, 2017 at 23:46 Comment(1)
I smiled. Writing C++ can at times be so cumbersome you have to resort to taboo areas such as macros ("he said macro, he said macro", "kill him, kill him" ... Life of Brian reimagined for C++) to keep it readable.Distract
H
0

Print any number to hex with auto-padding '0' or set. Template allows any data type (e.g. uint8_t)

template<typename T, typename baseT=uint32_t> struct tohex_t {
    T num_;
    uint32_t width_;
    bool showbase_;

    tohex_t(T num, bool showbase = false, uint32_t width = 0) { num_ = num; showbase_ = showbase; width_ = width; }
    friend std::ostream& operator<< (std::ostream& stream, const tohex_t& num) {
        uint32_t w;
        baseT val;

        if (num.showbase_)
            stream << "0x";

        if (num.width_ == 0) {
            w = 0;
            val = static_cast<baseT>(num.num_);
            do { w += 2; val = val >> 8; } while (val > 0);
        }
        else {
            w = num.width_;
        }
        stream << std::hex << std::setfill('0') << std::setw(w) << static_cast<baseT>(num.num_);

        return stream;
    }
};
template<typename T> tohex_t<T> TO_HEX(T const &num, bool showbase = false, uint32_t width = 0) { return tohex_t<T>(num, showbase, width); }

Example:

std::stringstream sstr;
uint8_t ch = 91;
sstr << TO_HEX(5) << ',' << TO_HEX(ch) << ',' << TO_HEX('0') << std::endl;
sstr << TO_HEX(1, true, 4) << ',' << TO_HEX(15) << ',' << TO_HEX(-1) << ',';
sstr << TO_HEX(513) << ',' << TO_HEX((1 << 16) + 3, true);
std::cout << sstr.str();

Output:

05,5b,30
0x0001,0f,ffffffff,0201,0x010003
Hyder answered 21/2, 2018 at 3:3 Comment(0)
P
0
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
    /*This should print out 0x0a. The internal adjustment pads the width with the fill character*/
    cout << hex << showbase << internal << setfill('0') << setw(4) << 10 << endl;
}
Prent answered 8/11, 2020 at 11:9 Comment(0)
E
0

Perhaps not exactly what he's looking for, but I usually use something like:

class HexDump
{
    unsigned char const*m_ptr;
    int                 m_len;
public:
    template< typename T >
    HexDump( T const& value )
        :   m_ptr( reinterpret_cast<unsigned char const*>( &value ) )
        ,   m_len( sizeof( T ) )
    {
    }

    friend std::ostream& operator<<( std::ostream& dest, HexDump const& hex )
    {
        auto                outOne = [&dest]( unsigned char one )
            {
                static char const   hexChars[] = "0123456789QBCDEF";
                dest.put( hexChars[one >> 4] );
                dest.put( hexChars[one & 0xF] );
            };
        outOne( *hex.m_ptr );
        for ( unsigned char const* p = hex.m_ptr + 1; p != hex.m_ptr + hex.m_len; ++ p ) {
            dest.put( ' ' );
            outOne( *p );
        }
        return dest;
    }

};

This will output two digits per byte in whatever object it is called on, and doesn't use (or consider) any formatting flags -- I usually use this for debugging, and so insert it into streams with no knowledge of the current format flags, and a very strong desire to not change them.

It can easily be modified to not insert spaces, for example; it would also be possible to modify it to take into consideration things like std::ios_base::showbase or std::ios_base::uppercase.

If you're using it for something other than debugging, you might want to call it something like AsHex, rather than HexDump.

Evenings answered 6/12, 2023 at 10:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.