-1

Possible Duplicate:
C++ convert string to hexadecimal and vice versa

Trying this sample code which I found in StackOverflow...

std::string text = "¯"; // AF in HEX ASCII. 
std::ostringstream result;  
result << std::setw(2) << std::setfill('0') << std::hex << std::uppercase;  
std::copy(text.begin(), text.end(), std::ostream_iterator<unsigned int>(result, " "));  

result.str() will be 'FFFFFFAF' instead of just 'AF'

What can I do?

My text can have more than one character, like that: text = '¯ABCÈ'; // AF414243C8 The result after 'convertion' is: FFFFFFAF414243FFFFFFC8.

.

Well, I solved it with a replace... it's not a good practice in this case, but solved.

                    if(value > 6)
                    {   //replace
                        std::string& str = stringlist2[count];
                        const std::string& from = "FFFFFF";
                        const std::string& to = "";
                        size_t j;
                        for ( ; (j = stringlist2[count].find( from )) != string::npos ; ) {
                            stringlist2[count].replace( j, from.length(), to );
                        }
                    }
Community
  • 1
  • 1
  • 1
    Looks like sign extension while converting from `char` to `int` (`0xaf` is more than `0x7f` and is thus negative). – Hristo Iliev Sep 13 '12 at 12:31
  • Yeah, I think Hristo is right. The wrong assumption here is that the character is ASCII-encoded (because ASCII ranges only from `0x0` to `0x7f`) – Niklas B. Sep 13 '12 at 12:35
  • It's extended ASCII. http://www.ascii-code.com/ – Guilherme Quelhos Sep 13 '12 at 12:50
  • @GuilhermeQuelhos: There's no such thing as "extended ASCII". You need to specify an encoding if you use more than the standardized 127 character codes (that website mentions that it's ISO-8859-1, but there exist others) – Niklas B. Sep 13 '12 at 14:45

1 Answers1

1

You're not passing unsigned int to the operator<< invoked by ostream_iterator; you're passing a char. Depending on your system, char may be signed or unsigned, and if it is signed and 8 bits (the most common case), it cannot contain 0xAF (which would be 175). If the bit pattern is 0xAF, what it actually contains is -0x51 (or -81). Which will be converted to an unsigned by adding it to UINT_MAX+1, which makes for a very large unsigned value.

What you probably need to do is to convert each character to unsigned char first. This will cause negative values to be converted by adding UCHAR_MAX+1; if you add 0x100 + (0-x51), you'll get 0xAF. As a positive value, so when it is converted to unsigned (or even to int), it will retain its value.

Typically, when one is doing this sort of thing, it is one character at a time, and:

result << static_cast<int>( static_cast< unsigned char >( ch ) );

is used. (Note the double conversion.) You could, however, do something like:

std::vector< unsigned char > tmp( text.begin(), text.end() );

and use your call to copy on tmp. Or use std::transform:

struct ToUnsignedChar
{
    unsigned char operator()( char ch ) const
    {
        return static_cast<unsigned char>( ch );
    }
};

std::transform( 
    text.begin(),
    text.end(),
    std::ostream_iterator<unsigned int>( result, " " ),
    ToUnsignedChar() );

(This would be a good candidate for a lambda if you have C++11.)

James Kanze
  • 150,581
  • 18
  • 184
  • 329