Integer to hex string in C++
Solution 1
Use <iomanip>'s std::hex. If you print, just send it to std::cout, if not, then use std::stringstream
std::stringstream stream;
stream << std::hex << your_int;
std::string result( stream.str() );
You can prepend the first << with << "0x" or whatever you like if you wish.
Other manips of interest are std::oct (octal) and std::dec (back to decimal).
One problem you may encounter is the fact that this produces the exact amount of digits needed to represent it. You may use setfill and setw this to circumvent the problem:
stream << std::setfill ('0') << std::setw(sizeof(your_type)*2)
<< std::hex << your_int;
So finally, I'd suggest such a function:
template< typename T >
std::string int_to_hex( T i )
{
std::stringstream stream;
stream << "0x"
<< std::setfill ('0') << std::setw(sizeof(T)*2)
<< std::hex << i;
return stream.str();
}
Solution 2
To make it lighter and faster I suggest to use direct filling of a string.
template <typename I> std::string n2hexstr(I w, size_t hex_len = sizeof(I)<<1) {
static const char* digits = "0123456789ABCDEF";
std::string rc(hex_len,'0');
for (size_t i=0, j=(hex_len-1)*4 ; i<hex_len; ++i,j-=4)
rc[i] = digits[(w>>j) & 0x0f];
return rc;
}
Solution 3
Use std::stringstream to convert integers into strings and its special manipulators to set the base. For example like that:
std::stringstream sstream;
sstream << std::hex << my_integer;
std::string result = sstream.str();
Solution 4
You can do it with C++20 std::format:
std::string s = std::format("{:x}", 42); // s == 2a
Until std::format is widely available you can use the {fmt} library, std::format is based on (godbolt):
std::string s = fmt::format("{:x}", 42); // s == 2a
Disclaimer: I'm the author of {fmt} and C++20 std::format.
Solution 5
Just print it as an hexadecimal number:
int i = /* ... */;
std::cout << std::hex << i;
Related videos on Youtube
kryptobs2000
Updated on November 20, 2021Comments
-
kryptobs2000 about 1 yearHow do I convert an integer to a hex string in C++?
I can find some ways to do it, but they mostly seem targeted towards C. It doesn't seem there's a native way to do it in C++. It is a pretty simple problem though; I've got an
intwhich I'd like to convert to a hex string for later printing. -
MSalters almost 12 yearssizeof(your_type)*2is a bit ugly;numeric_limits<your_type>::digits/4is cleaner. -
Kornel Kisielewicz almost 12 years@MSalters - quite on the contrary. Test your suggestion on theinttype ;) -
Alan Turing almost 10 years@Kornel, great answer, but why template it? To supportlong int? -
Kornel Kisielewicz almost 10 years@LexFridman, to emit exactly the amount of hex digits as needed. Why emit 8 digits if the type is a uint8_t? -
Alexander Oh over 8 yearsa nice answer, but beware thatto_stringis part of the namespacestdin C++11 -
Alex over 8 years@Alex yes, it is 2014 after all... heaven forbid we'll have to start dealing with C++14 soon.
-
ov7a almost 7 yearsWARNIG: this will not work for single byte because char is always threated as char
-
ShadowRanger almost 7 yearsThis doesn't really add to the existing answers, and it's pointless to explicitlyclearthesstream(it will be destroyed when the function returns on the next line anyway). You could avoid the namedhexStrentirely and justreturn sstream.str();withoutclearing and get the same effect, reducing four lines of code to one. -
parasrish almost 7 yearswhen purpose of the forum is to understand the things and usage. being verbose is far better to provide clear picture, than saving lines. question was not on optimized code, and answer tries to give a modular-method way of dealing with such conversions. @ShadowRanger -
Wolf over 6 yearsWhat is the purpose ofsstream.clear();? Thesstreamobject is automatically destroyed at the end of the scope, soreturn sstream.str();would do it. -
parasrish over 6 yearssstream.clearwill just clear the content, before stream ends with scope end (to clear any fail and eof flags with clear). Indeed, when the scope dies, with the life-span of the stream-variable, and thereforesstream.strcan be used to return by value. [Reference : cplusplus.com/reference/ios/ios/clear/] -
ruipacheco about 6 yearsShouldn't you just return buf.str() ? -
S.R over 5 yearsWill this work for any type? I mean also double, float, uint8_t? -
Wolf almost 5 years@S.R It works for integral types, not fordoubleandfloat(and not for pointers) -
Wolf almost 5 years... a very pragmatic (but valid) mix of C and C++, I'm not sure about speed ... for my taste, it's a bit dense. -
Foxcat385 almost 5 yearsI tried this and I got error error C2784: 'std::basic_ostream<_Elem,_Traits> &std::operator <<(std::basic_ostream<_Elem,_Traits> &,const std::_Smanip<_Arg> &)': could not deduce template argument for 'std::basic_ostream<_Elem,_Traits> &' from 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>' -
Foxcat385 almost 5 yearsNevermind. Another line of code in my code caused the error. If only C++ compiler knew how to tell me at which line of code the problem is happening. -
David Gausmann almost 5 yearsYou also require #include <sstream> -
DeveloperChris over 4 yearsThank you, brilliant answer. Bringing in a stream library 'just' to do this seems such a waste. -
wcochran over 4 yearsIf I am formatting multiple ints, It seems thatstd::setwneeds to be output to the stream for every int, whereasstd::hex,std::setfill,std::uppercase, ... only need to be sent to the output stream once. This seems inconsistent? -
Lincoln about 4 yearsin my testing std::to_string(i) does not print std::uint8_t integers as hex. I think this may have to have separate conditions for both uint8_t and int8_t types, since they need to be cast to larger integers. -
Loss Mentality about 4 years@Lincoln You are right. I don't know what I was doing at the time (months ago now) that made me thing to_string handled 8-bit ints. I even went back to the compiler version I think I was using back then, just to double check, but to_string didn't work as I said it did. So who knows? Anyway, thanks for catching this - I've edited answer to something that should work correctly. -
Lightness Races in Orbit about 4 yearsCould show off the width deduction with e.g.TEST_ASSERT(int_to_hex(short(0x12)) == "0012"); -
Mark Lakata almost 4 yearsI would usestd::cout<<std::hex<<i<<std::dec;, otherwise all integers that are streamed out later will be in hex. You don't need to do that for the other answers that usestringstreambecause the stream is discarded after it is used, butcoutlives forever. -
Ruslan about 3 yearsThis will still work unexpectedly forchar(which is distinct from bothuint8_tandint8_tin most implementations (where they are respectivelyunsigned charandsigned char)). -
Loss Mentality over 2 years@ruslan Yes, also bool and wide char types all match std::is_integral and will not fail the assert. But since char is, per the std., a guaranteed unique type, as are the wide char types, you can handle all of them if desired (exceptions are un/signed char, which match the un/signed integral type of whatever width a byte is on the current machine - typically int8 - and so can't be filtered if you want to match ints of the same width as well). You can reject char, wide chars, bools by adding more terms to the the static_assert:... && !std::is_same_v<char, T> && !std::is_same_v<bool, T>etc... -
jaques-sam over 2 yearsThis prints0000FFFFfor0xFFFF. I prefer to have0xFFFFas output. -
Code Abominator over 2 yearsI expect this will annoy everyone else in your project since so few people ever think to<< std:decbefore pushing numbers into a stream. I thought was a widely known flaw in C++ streams? -
Jason Aller over 2 yearsThis does use some techniques not seen in the other answers. Can you please edit the answer to include some explanation of how and why it works? -
Wade Wang over 1 yearThe header file is#include <boost/format.hpp> -
Haseeb Mir over 1 yearBoost doesn't come pre-installed that's why
-
Plater about 1 year@DrumM pass a 4 into the hex_len parameter then?