Discussion:
std::hex
(too old to reply)
gelbeiche
2006-03-10 10:31:11 UTC
Permalink
Hi,

I want to create a hex output of int values and used the following
function:

inline std::string stringify(int x)
{
std::ostringstream o;
o << std::hex << std::setw(2) << std::setfill('0') << x;
return o.str();
}

For negative ints I get strings like

ffffffca or ffffffef

for positive ints

3c,64 ...

How can I accomplish *always* to get 2 byte strings(in the example above
"ca" instead of "ffffffca").

(
Of course I could do something like
if ( s.length() == 8 )
s.erase(s.begin(), s.begin() + 6);
but it is not nice
)

Thomas



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Graham Menhennitt
2006-03-10 13:34:48 UTC
Permalink
Post by gelbeiche
How can I accomplish *always* to get 2 byte strings(in the example above
"ca" instead of "ffffffca").
If you only want two characters then you are using bytes, not ints.

Try casting your "int" to "unsigned char".

Graham

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Zara
2006-03-10 13:47:18 UTC
Permalink
On 10 Mar 2006 05:31:11 -0500, gelbeiche <***@randspringer.de> wrote:

<snip>
Post by gelbeiche
I want to create a hex output of int values and used the following
inline std::string stringify(int x)
{
std::ostringstream o;
o << std::hex << std::setw(2) << std::setfill('0') << x;
return o.str();
}
<snip>
Post by gelbeiche
How can I accomplish *always* to get 2 byte strings(in the example above
"ca" instead of "ffffffca").
<snip>

One possibility:

o << std::hex << std::setw(2) << std::setfill('0') <<
static_cast<unsigned char>(x);

Of course, it works only when your char is 8 bits long.

zara

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Rupert Swarbrick
2006-03-10 13:48:00 UTC
Permalink
Post by gelbeiche
Hi,
I want to create a hex output of int values and used the following
inline std::string stringify(int x)
{
std::ostringstream o;
o << std::hex << std::setw(2) << std::setfill('0') << x;
return o.str();
}
For negative ints I get strings like
ffffffca or ffffffef
for positive ints
3c,64 ...
How can I accomplish *always* to get 2 byte strings(in the example above
"ca" instead of "ffffffca").
(
Of course I could do something like
if ( s.length() == 8 )
s.erase(s.begin(), s.begin() + 6);
but it is not nice
)
Thomas
It's difficult to tell what you want. What's happening is that the
bitwise value of a negative integer is something like 0xffffffac or
whatever, as that's how they're stored.

The ostream code is thus working correctly. If you want -72 to output
the same as 72, you could just add some sort of:

if(x<0) x=-x;

line to your code. If you want to split up the longer negative numbers
instead, you have a more difficult problem. Incidentally, a larger
positive number (260) wouldn't just give you two characters either. Have
you considered making your class take the argument of type unsigned int?

Rupert

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
gelbeiche
2006-03-11 13:13:14 UTC
Permalink
Am 10 Mar 2006 08:48:00 -0500
Post by Rupert Swarbrick
Post by gelbeiche
Hi,
I want to create a hex output of int values and used the following
inline std::string stringify(int x)
{
std::ostringstream o;
o << std::hex << std::setw(2) << std::setfill('0') << x;
return o.str();
}
For negative ints I get strings like
ffffffca or ffffffef
for positive ints
3c,64 ...
How can I accomplish *always* to get 2 byte strings(in the example
above "ca" instead of "ffffffca").
(
Of course I could do something like
if ( s.length() == 8 )
s.erase(s.begin(), s.begin() + 6);
but it is not nice
)
Thomas
It's difficult to tell what you want. What's happening is that the
bitwise value of a negative integer is something like 0xffffffac or
whatever, as that's how they're stored.
The ostream code is thus working correctly. If you want -72 to output
if(x<0) x=-x;
line to your code. If you want to split up the longer negative numbers
instead, you have a more difficult problem. Incidentally, a larger
positive number (260) wouldn't just give you two characters either.
Have you considered making your class take the argument of type
unsigned int?
Rupert
I found now a solution by thinking what I really want.
The motivation was to replace a perl script which created a header file
from a binary file with a tiny C++ program. (Now the build process
does not longer depend on perl.)
Perl accomplished the task by the following expression:

s/(.)/"\\x".sprintf("%02x",unpack("C",$1))/ges;

Substitute every sign of a string with \x<value of unpack function>
[$1 is the search hit from (.)]

I read in my perl book about unpack and the "C" as first parameter:

one sign (8 Bit Integer) without sign

and now changed the code to

inline std::string stringify(unsigned char x)
{
std::string s;
std::ostringstream o;
o << std::hex << std::setw(2) << std::setfill('0') <<
static_cast<unsigned short>(x);
s = o.str();
return s;
}

std::string readBinaryFile(const std::string& filename)
{
std::ifstream input(filename.c_str(), std::ios::in |
std::ios::binary);
char c;
std::string tmp, rc;

while (input.get(c)) {
tmp = "\\x";
tmp += stringify(static_cast<unsigned char>(c));
rc.append(tmp);
}
return rc;
}

and it worked.

Still any comments ?

Thomas




[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Pete Becker
2006-03-10 13:51:00 UTC
Permalink
Post by gelbeiche
How can I accomplish *always* to get 2 byte strings(in the example above
"ca" instead of "ffffffca").
Instead of writing out the value of x, write out the value of (x & 0xff).
--
Pete Becker
Roundhouse Consulting, Ltd.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Bob Hairgrove
2006-03-10 14:05:09 UTC
Permalink
Post by gelbeiche
Hi,
I want to create a hex output of int values and used the following
inline std::string stringify(int x)
{
std::ostringstream o;
o << std::hex << std::setw(2) << std::setfill('0') << x;
return o.str();
}
For negative ints I get strings like
ffffffca or ffffffef
for positive ints
3c,64 ...
How can I accomplish *always* to get 2 byte strings(in the example above
"ca" instead of "ffffffca").
(
Of course I could do something like
if ( s.length() == 8 )
s.erase(s.begin(), s.begin() + 6);
but it is not nice
)
I've never seen signed hexadecimal literal values used, only unsigned.

You could always roll your own formatting using std::abs() and a ?::
to prefix the output with "-" or enclose it in parentheses, etc. I
don't think there is any other way, i.e. using the standard formatting
options available in <iomanip>.

--
Bob Hairgrove
***@Home.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
kanze
2006-03-13 13:56:17 UTC
Permalink
Post by Zara
On 10 Mar 2006 05:31:11 -0500, gelbeiche
Post by gelbeiche
I want to create a hex output of int values and used the
inline std::string stringify(int x)
{
std::ostringstream o;
o << std::hex << std::setw(2) << std::setfill('0') << x;
return o.str();
}
For negative ints I get strings like
ffffffca or ffffffef
for positive ints
3c,64 ...
How can I accomplish *always* to get 2 byte strings(in the
example above "ca" instead of "ffffffca").
(
Of course I could do something like
if ( s.length() == 8 )
s.erase(s.begin(), s.begin() + 6);
but it is not nice
)
I've never seen signed hexadecimal literal values used, only
unsigned.
He's not dealing with literal values here, but the problem is
really exactly that: conversion to hex is only defined for
unsigned values, and the implementation converts his int to an
unsigned before converting.

Of course, I really think that that is what he wants: something
like -3c is more than two characters as well.

In the end, Pete Becker had the right solution: if you only want
two hex digits, you only want 8 bits, and the way to get only 8
bits is to force the others to 0, using "& 0xFF".

With regards to all of those suggesting conversion to unsigned
char: the semantics of outputting an unsigned char don't include
conversion. (There's also the theoretical fact that a char
might be more than 8 bits -- 0xFF always gives exactly 8 bits.)
Post by Zara
You could always roll your own formatting using std::abs() and
a ?:: to prefix the output with "-" or enclose it in
parentheses, etc. I don't think there is any other way, i.e.
using the standard formatting options available in <iomanip>.
Which one could interpret as a defect. Inherited from C, but a
defect, none the less.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Carl Barron
2006-03-10 15:00:18 UTC
Permalink
Post by gelbeiche
I want to create a hex output of int values and used the following
inline std::string stringify(int x)
{
std::ostringstream o;
o << std::hex << std::setw(2) << std::setfill('0') << x;
std:string s(o,str());
std::string::size_type len=s.length();
char t1 = s[len-2];
char t2 = s[len-1];
s.clear();
s += t1;
s += t2;
return s;
}

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Dietmar Kuehl
2006-03-11 20:59:02 UTC
Permalink
Post by gelbeiche
For negative ints I get strings like
ffffffca or ffffffef
As is expected: in hex format the output contains a representation
of all bits in the value and negative values have the most significant
bit always set. If you only want to display the least significant byte,
you need to strip of the other bits, e.g. by converting the 'int' to
an 'unsigned char' and from there back to an integer type again (the
last conversion is necessary to enable integral formatting for the
value instead of formatting it as a single character):

std::cout << std::hex << int(static_cast<unsigned char>(i));
--
<mailto:***@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.eai-systems.com> - Efficient Artificial Intelligence

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Continue reading on narkive:
Loading...