17

Here is what I currently have so far:

void WriteHexToFile( std::ofstream &stream, void *ptr, int buflen, char *prefix )
{
    unsigned char *buf = (unsigned char*)ptr;

    for( int i = 0; i < buflen; ++i ) {
        if( i % 16 == 0 ) {
            stream << prefix;
        }

        stream << buf[i] << ' ';
    }
}

I've tried doing stream.hex, stream.setf( std::ios::hex ), as well as searching Google for a bit. I've also tried:

stream << stream.hex << (int)buf[i] << ' ';

But that doesn't seem to work either.

Here is an example of some output that it currently produces:

Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í 
Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í 
Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í 
Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í 
Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í 
Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í Í 

I would like the output to look like the following:

FF EE DD CC BB AA 99 88 77 66 55 44 33 22 11 00
FF EE DD CC BB AA 99 88 77 66 55 44 33 22 11 00
FF EE DD CC BB AA 99 88 77 66 55 44 33 22 11 00
FF EE DD CC BB AA 99 88 77 66 55 44 33 22 11 00
FF EE DD CC BB AA 99 88 77 66 55 44 33 22 11 00
FF EE DD CC BB AA 99 88 77 66 55 44 33 22 11 00
xian
  • 4,657
  • 5
  • 34
  • 38
  • 1
    BTW: You should use const void *ptr and const char *prefix to make clear that you won't modify these buffers. – mmmmmmmm Mar 08 '09 at 16:23
  • 1
    this is why I like stack overflow so much. these fun little problems come up from time to time and someone drops in a snippet of code and its solved... – MikeJ Mar 08 '09 at 16:51

7 Answers7

32
#include <iostream>
int main() {
    char c = 123;
    std::cout << std::hex << int(c) << std::endl;
}

Edit: with zero padding:

#include <iostream>
#include <iomanip>
int main() {
    char c = 13;
    std::cout << std::hex << std::setw(2) << std::setfill('0') << int(c) << std::endl;
}
glitchyme
  • 235
  • 3
  • 12
  • Won't that just output it to the console? – xian Mar 08 '09 at 16:26
  • Could you explain why that should work any differently from using stream.hex, like the asker already tried? – Rob Kennedy Mar 08 '09 at 16:27
  • I find the 'hex' stream modifier a bit of a pain. If you are outputting other types you have to keep switching the stream back (using 'dec' for example) and as far as I know, it doesn't do leading zeros. – Arnold Spence Mar 08 '09 at 16:27
  • 1
    @kitchen - replace cout with your own stream. –  Mar 08 '09 at 16:31
  • @Neil: It worked, but what's the difference between using ofstream.hex and std::hex? – xian Mar 08 '09 at 16:35
  • OK, I'll explain it myself. Using stream.hex prints the value of the member-function pointer ostream::hex. (For me the value is 8.) Then it prints the integer value of the character in decimal. – Rob Kennedy Mar 08 '09 at 16:38
  • 1
    @rob the hex manipul;ator is not a member of the stream class. The hex you are printing is acually an enumeration value –  Mar 08 '09 at 16:54
  • 2
    You might want to use unsigned(c) instead of int(c) if c<0. – Mr.Ree Mar 08 '09 at 17:53
  • mrree better (int)(unsigned char)c :) – Johannes Schaub - litb Mar 08 '09 at 19:04
  • 4
    And this is why I *love* C++ streams: cout << hex << setw(2) << setfill('0') << int(c) << endl is just *so* much clearer than printf("%02x", c) ;-) I know its typesafe(er) but couldn't they have dreamed up something less grotesque? – RBerteig Mar 08 '09 at 22:54
  • 4
    Clarity is a question of point of view... I don't think printf("%02x", c) can be considered as "clear" – Edouard A. Mar 09 '09 at 09:50
  • @RBerteig: nitpick: those aren't quite equivalent, the C++ shouldn't have the `endl` there. – Mooing Duck Jan 18 '12 at 20:05
  • With c value being 197, it prints ffffffc5. Can anybody explain why it's not printing C5 and how to avoid extra 'f' padding? – Naresh T Nov 28 '17 at 08:25
7
char upperToHex(int byteVal)
{
    int i = (byteVal & 0xF0) >> 4;
    return nibbleToHex(i);
}

char lowerToHex(int byteVal)
{
    int i = (byteVal & 0x0F);
    return nibbleToHex(i);
}

char nibbleToHex(int nibble)
{
    const int ascii_zero = 48;
    const int ascii_a = 65;

    if((nibble >= 0) && (nibble <= 9))
    {
        return (char) (nibble + ascii_zero);
    }
    if((nibble >= 10) && (nibble <= 15))
    {
        return (char) (nibble - 10 + ascii_a);
    }
    return '?';
}

More code here.

McDowell
  • 107,573
  • 31
  • 204
  • 267
2

Try:

#include <iomanip>
....
stream << std::hex << static_cast<int>(buf[i]);
Martin York
  • 257,169
  • 86
  • 333
  • 562
1

You can also do it using something a bit more old-fashioned:

char buffer[4];//room for 2 hex digits, one extra ' ' and \0
sprintf(buffer,"%02X ",onebyte);
Mnebuerquo
  • 5,759
  • 5
  • 45
  • 52
0

CHAR to wchar_t (unicode) HEX string

wchar_t* CharToWstring(CHAR Character)
{
wchar_t TargetString[10];
swprintf_s(TargetString, L"%02X", Character);

// then cut off the extra characters
size_t Length = wcslen(TargetString);

wchar_t *r = new wchar_t[3];
r[0] = TargetString[Length-2];
r[1] = TargetString[Length-1];
r[2] = '\0';
return r;
}
Alatey
  • 371
  • 2
  • 6
0

I usually make a function which returns the digits and just use it:

void CharToHex(char c, char *Hex)
{
   Hex[0]=HexDigit(c>>4);
   Hex[1]=HexDigit(c&0xF);
}

char HexDigit(char c)
{
   if(c<10)
     return c;
   else
     return c-10+'A';
}
Jason Plank
  • 2,336
  • 5
  • 31
  • 40
SurDin
  • 3,281
  • 4
  • 26
  • 28
-1

You simply need to configure your stream once:

stream << std::hex << std::setfill('0') << std::setw(2)
Edouard A.
  • 6,100
  • 26
  • 31