How can I print 0x0a instead of 0xa using cout?
Solution 1
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);
Solution 2
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.
Solution 3
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:
-
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 (as0x-##
) 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 customabs()
that returns an unsigned value, if you need to be able to handle the most-negative values on a 2's complement system) onval
. -
The second option will omit the base when
val == 0
, displaying (e.g., forint
, whereint
is 32 bits)0000000000
instead of the expected0x00000000
. This is due to theshowbase
flag being treated likeprintf()
's#
modifier internally.If this is an issue, you can check whether
val == 0
, and apply special handling when it does.
-
-
Depending on which option was chosen for showing the base, two lines will need to be changed.
- If using
<< "0x"
, thenHEX_BASE_CHARS
is unnecessary, and can be omitted. -
If using
<< std::showbase
, then the value supplied tosetw()
needs to account for this:<< std::setw((sizeof(T) * CHAR_BIT / HEX_DIGIT_BITS) + HEX_BASE_CHARS)
- If using
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.
Solution 4
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
.
Solution 5
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;
Ayrosa
Updated on July 07, 2022Comments
-
Ayrosa almost 2 years
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; }
-
Emile Cormier about 13 yearsI get 0xA too. Why is it so damn HARD to get iostream to format things the way you want??
-
Emile Cormier about 13 yearsThis worked for me:
cout << "0x" << setfill('0') << setw(2) << hex << 10 << endl
-
Emile Cormier about 13 years@Doug T.: I took the liberty of editing your answer so that the OP may accept it as the answer that worked.
-
Emile Cormier about 13 years@Potatoswatter:
setw(2)
doesn't seem to play nice withshowbase
, at least in gcc 4.4.3. Maybe it's a bug in GCC? -
Emile Cormier about 13 yearsWhen I use
cout << showbase << setfill('0') << setw(2) << hex << 10 << endl;
I still get0xa
in GCC. -
CB Bailey about 13 years@EmileCormier:
0xa
is already wider than 2 characters sosetw(2)
isn't going to do anything. @Potatoswatter: In this case I think an explicit0x
is reasonable.setw(4) << hex << setfill('0') << showbase << 10
isn't going to have the desired effect (00xa
!). -
Potatoswatter about 13 years@Charles: Sorry, I forget
setiosflags(ios::internal)
. This works:cout << showbase << setiosflags(ios::internal) << setfill('0') << setw(4) << hex << 10 << endl;
Demo: ideone.com/WlusB -
CB Bailey about 13 years@Potatoswatter: Nice, I didn't know that would work!
internal
: "adds fill characters at a designated internal point in certain generated output, or identical toright
if no such point is designated" That's either underspecified or very cryptically specified. -
Doug T. about 13 years@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.
-
Potatoswatter about 13 years@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.
-
Justin Time - Reinstate Monica about 8 yearsOr, if you're using
std::showbase
instead of just outputing0x
directly, you usestd::internal
instead ofstd::right
. -
j4x almost 7 years
std::internal
! You won the big prize! That's what I was missing! Thank you @Justin Time. -
Justin Time - Reinstate Monica almost 7 years@fljx You're welcome. I've improved on it since I posted this answer, so I'll edit the answer to reflect this.
-
mxmlnkn over 6 yearsThe required includes should be listed somewhere for this, from what I glance:
climits
,iomanip
,iostream
,types
,string
,stringstream
with climits forCHAR_BIT
being the one making me write this comment. -
463035818_is_not_a_number about 5 yearsi prefer this rather than boost, you just have to remember to reset the iomanipulators
-
Justin Time - Reinstate Monica almost 5 yearsGood idea, @mxmlnkn. Updated. (Also, it technically requires
ios
instead ofiostream
, but that's moot becauseiostream
is required to includeios
anyways. Noted this in the answer, as well.) -
Justin Time - Reinstate Monica over 4 yearsNote 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 tochar_traits<T>::int_type
whenis_char<T>
is true, since we already use<string>
. [I'm currently waiting to see how things play out before doing so, though.] -
fuujuhi over 4 yearsThis answer is wrong. If someone did
cout << left << whatever
before, you'll get bad output because of persistent left/right iomanip. It should besetfill('0') << setw(2) << right << hex
to always guarantee right alignment. -
Emile Cormier over 4 years@fuujuhi Wrong? That's rather harsh. I'd say that it's incomplete. Thanks for the suggestion, though.
-
fuujuhi over 4 years@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.
-
0xC0000022L almost 4 yearsI 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.
-
kraxor over 3 yearsnote that you may need to call setw before each
<< n
, at least that was the case for me