I often do something like:
uint8_t c=some_value;
std::cout << std::setfill('0') << std::setw(2);
std::cout << std::hex << int(c);
std::cout << std::setfill(' ');
(in particular while dumping debugging information). Wouldn't it be nice to have something manipulatorish that I could put in a stream like this:
std::cout << "c value: 0x" << hexb(c) << '\\n';
that would do all of that? Does anyone know how to do that?
I've gotten this to work but would love to have a simpler way:
#include <iostream>
#include <iomanip>
class hexcdumper{
public:
hexcdumper(uint8_t c):c(c){};
std::ostream&
operator( )(std::ostream& os) const
{
// set fill and width and save the previous versions to be restored later
char fill=os.fill('0');
std::streamsize ss=os.width(2);
// save the format flags so we can restore them after setting std::hex
std::ios::fmtflags ff=os.flags();
// output the character with hex formatting
os << std::hex << int(c);
// now restore the fill, width and flags
os.fill(fill);
os.width(ss);
os.flags(ff);
return os;
}
private:
uint8_t c;
};
hexcdumper
hexb(uint8_t c)
{
// dump a hex byte with width 2 and a fill character of '0'
return(hexcdumper(c));
}
std::ostream& operator<<(std::ostream& os, const hexcdumper& hcd)
{
return(hcd(os));
}
When I do this:
std::cout << "0x" << hexb(14) << '\n';
On the output, I see:
0x0e
Is there a simpler way to do this?
Patrick
You can do this directly on the stream pipe:
std::cout << "Hex = 0x" << hex << 14 << ", decimal = #" << dec << 14 << endl;
Output:
Hex = 0xe, decimal = #14
Just as a follow up, this does the same this for arbitrary width, and does the same for binary output, for example, assuming the below in in a file called hexbinfmt.h, the following:
#include <hexbinfmt.h>
int
main()
{
unsigned long long ll=0x7589347dfdf7834;
std::cout << "hexb(ll): 0x" << hexb(ll) << ", bin(ll): " << bin(ll) << '\n';
uint8_t u8t=0xce;
std::cout << "hexb(u8t): 0x" << hexb(u8t) << ", bin(u8t): " << bin(u8t) << '\n';
}
outputs:
hexb(ll): 0x07589347dfdf7834, bin(ll): 0000011101011000100100110100011111011111110111110111100000110100
hexb(u8t): 0xce, bin(u8t): 11001110
Can you help me find a simpler way of doing the same thing?
#ifndef HEXBINFMT_H
#define HEXBINFMT_H
#include <iostream>
#include <iomanip>
template<typename T>
class hexcdumper{
public:
hexcdumper(T c):c(c){};
std::ostream&
operator()(std::ostream& os) const
{
// set fill and width and save the previous ones to be restored later
char fill=os.fill('0');
std::streamsize ss=os.width(sizeof(T)*2);
// get a copy of the format flags to be restored after setting std::hex
std::ios::fmtflags ff=os.flags();
// put the character out as hex
if(sizeof(T)==1){
os << std::hex << int(c);
}else{
os << std::hex << c;
}
// restore everything
os.fill(fill);
os.width(ss);
os.flags(ff);
return os;
}
private:
T c;
};
template<typename T>
hexcdumper<T>
hexb(T c)
{
return(hexcdumper<T>(c));
}
template<typename T>
std::ostream& operator<<(std::ostream& os, const hexcdumper<T>& hcd)
{
return(hcd(os));
}
template<typename T>
class bincdumper{
public:
bincdumper(T c):c(c){};
std::ostream&
operator()(std::ostream& os) const
{
T mask=1;
mask <<= (sizeof(T)*8)-1;
for(size_t i=0;i<sizeof(T)*8;i++){
if(c&mask){
os<<'1';
}else{
os<<'0';
}
mask>>=1;
}
return os;
}
private:
T c;
};
template<typename T>
bincdumper<T>
bin(T c)
{
return(bincdumper<T>(c));
}
template<typename T>
std::ostream& operator<<(std::ostream& os, const bincdumper<T>& bcd)
{
return(bcd(os));
}
#endif
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.