Problem printing Hexadecimal

T

Tobias Rischer

Hi,
I am trying to read an exe file and print it out character by
character in hexadecimal format. The file goes something like this in
hexadecimal
0x4d 0x5a 0x90 0x00 0x03 .... so on
When I read it into my array " two_bytes" which has 16 characters in
total, I get each of these values read correctly, but when I attempt
printing them out, it prints something like this:
0x4d 0x5a 0xffffff90 0x00 0x03 .... so on. I have no clue why.

Because the char is a small integer which can be positive or negative.
Before being used by printf, it is implicitly converted to a normal
integer. Every byte from 0x80 to 0xFF will be interpreted as a negative
number, and the print result is based on a four-byte-representation of
that number.
How can
I correct this

FILE *fp = NULL;
int count = 0;
char nibble = NULL;
char two_bytes[16];

Here: declare your bytes as unsigned char.

Good luck!

Tobias
 
A

abhishekkarnik

Hi,
I am trying to read an exe file and print it out character by
character in hexadecimal format. The file goes something like this in
hexadecimal
0x4d 0x5a 0x90 0x00 0x03 .... so on
When I read it into my array " two_bytes" which has 16 characters in
total, I get each of these values read correctly, but when I attempt
printing them out, it prints something like this:
0x4d 0x5a 0xffffff90 0x00 0x03 .... so on. I have no clue why. How can
I correct this

FILE *fp = NULL;
int count = 0;
char nibble = NULL;
char two_bytes[16];
int i;
fp = fopen("xyz.exe","r");
if(fp == NULL)
{
printf("Unable to Open file\n");
exit(0);
}
while(!feof(fp))
{
fscanf(fp,"%c",&two_bytes[count++]);
if(count % 16 == 0)
{
for(i=0; i<count ; i++)
printf("%#x ",two_bytes);
printf(" || ");
for(i=0; i<count ; i++)
printf("%4c ",two_bytes);
count = 0;
printf("\n");
}
}
fclose(fp);
return 0;
 
H

Hallvard B Furuseth

char two_bytes[16];
(...)
printf("%#x ",two_bytes);


'char' can be signed. A negative char is promoted to int, and
%#x prints it as unsigned int, thus char 0x90 becomes 0xffffff90.

Use unsigned char two_bytes[16];
or printf("%#x ", (unsigned char) two_bytes);
 
W

Walter Roberson

I am trying to read an exe file and print it out character by
character in hexadecimal format. The file goes something like this in
hexadecimal
0x4d 0x5a 0x90 0x00 0x03 .... so on
When I read it into my array " two_bytes" which has 16 characters in
total, I get each of these values read correctly, but when I attempt
printing them out, it prints something like this:
0x4d 0x5a 0xffffff90 0x00 0x03 .... so on. I have no clue why. How can
I correct this
FILE *fp = NULL;
int count = 0;
char nibble = NULL;
char two_bytes[16];

make two_bytes unsigned char
int i;
fp = fopen("xyz.exe","r");
if(fp == NULL)
{
printf("Unable to Open file\n");
exit(0);
}
while(!feof(fp))
{
fscanf(fp,"%c",&two_bytes[count++]);

You've made a classic error there. feof() is not set until
you try and fail to read a character -- it does NOT "peek ahead"
to see whether the next read would fail or not. So you are going
to have to try to read the character and then determine whether
the read failed.

There is no good reason to fscanf with a single %c format:
see fgetc().
if(count % 16 == 0)
{
for(i=0; i<count ; i++)
printf("%#x ",two_bytes);
printf(" || ");
for(i=0; i<count ; i++)
printf("%4c ",two_bytes);


Oh, you don't want to do that. What if it's a newline or a bell
or something like that?

You should first test that it's a printable character, and if
it is then you can putchar() it; if it isn't, then print
a placeholder instead ('.' is typical.)

Or instead of a placeholder, if it isn't important that the
text equivilent always be exactly the same length, you could
print a representation -- for example, the character pair
'\' 't' for tab, '\' 'b' for backspace. ^ followed by a letter
is a common representation for ASCII control characters.

That just leaves you with a choice of representations when
the character is above the ASCII printable range, such as if
it is 0xac ...
 
A

abhishekkarnik

Thank you !!! That fixed it. I realized I'd forgotten to make it a
"unsigned char"

char two_bytes[16];
(...)
printf("%#x ",two_bytes);


'char' can be signed. A negative char is promoted to int, and
%#x prints it as unsigned int, thus char 0x90 becomes 0xffffff90.

Use unsigned char two_bytes[16];
or printf("%#x ", (unsigned char) two_bytes);
 
O

Old Wolf

char two_bytes[16];

make two_bytes unsigned char
fscanf(fp,"%c",&two_bytes[count++]);

There is no good reason to fscanf with a single %c format:
see fgetc().

Well, fgetc() returns a value in the range for unsigned char.
If he were still reading into a char, then using fgetc() would
cause implementation-defined behaviour due to out-of-range
assignment. However, fscanf with "%c" does not suffer that same
problem.
 
P

pete

Old said:
char two_bytes[16];

make two_bytes unsigned char
fscanf(fp,"%c",&two_bytes[count++]);

There is no good reason to fscanf with a single %c format:
see fgetc().

Well, fgetc() returns a value in the range for unsigned char.
If he were still reading into a char, then using fgetc() would
cause implementation-defined behaviour due to out-of-range
assignment.
However, fscanf with "%c" does not suffer that same problem.

fgetc returns type int
and is capable of returning a negative value equal to EOF.
 
W

Walter Roberson

char two_bytes[16];
make two_bytes unsigned char
fscanf(fp,"%c",&two_bytes[count++]);
There is no good reason to fscanf with a single %c format:
see fgetc().
Well, fgetc() returns a value in the range for unsigned char.
If he were still reading into a char, then using fgetc() would
cause implementation-defined behaviour due to out-of-range
assignment.

You cannot "read into a char" when using fgetc(): you have
to assign its value to something. You would take the usual
precautions to assign to an int, check the value for EOF, and
only then assign from the int into the unsigned char.

However, fscanf with "%c" does not suffer that same problem.

You would have to check the return value of fscanf(), which
is going to return EOF when the input ends. If you are prone
to make the mistake of assigning the return value to an unsigned
value for fgetc(), you are equally likely to be prone to assigning
the return value from fscanf() to an unsigned int.
 
O

Old Wolf

You cannot "read into a char" when using fgetc(): you have
to assign its value to something. You would take the usual
precautions to assign to an int, check the value for EOF, and
only then assign from the int into the unsigned char.

My comment was relating to the situation where you want to read
a value into a plain char. In that case, assigning from the int
to the char, on systems where plain char is signed, could cause
an out-of-range assignment problem.
You would have to check the return value of fscanf(), which
is going to return EOF when the input ends. If you are prone
to make the mistake of assigning the return value to an unsigned
value for fgetc(), you are equally likely to be prone to assigning
the return value from fscanf() to an unsigned int.

My original post was not concerned with error-checking. But if you
are to check for EOF then I think it is still much simpler in the
fscanf situation! The code with error-checking would have to be
something like:

int ch;
/* ... */
ch = fgetc(fp);
if ( ch == EOF )
break; /* or whatever */
two_bytes[count++] = ch;

vs.

if ( fscanf(fp, "%c", &two_bytes[count++]) )
break;

Furthermore, the first snippet still has the problem of out-of-range
assignment, which I don't see an easy way around.

(Of course the better solution to the original problem is to switch
to using unsigned char, in which case fgetc() becomes superior to
fscanf, no argument there).
 
W

Walter Roberson

Old Wolf said:
My original post was not concerned with error-checking. But if you
are to check for EOF then I think it is still much simpler in the
fscanf situation! The code with error-checking would have to be
something like:
int ch;
/* ... */
ch = fgetc(fp);
if ( ch == EOF )
break; /* or whatever */
two_bytes[count++] = ch;

if ( fscanf(fp, "%c", &two_bytes[count++]) )
break;
Furthermore, the first snippet still has the problem of out-of-range
assignment, which I don't see an easy way around.

Where do you see the possibility of an out of range assignment in
the first snippet? Unless two_bytes is defined as {signed} char --
but my commentary specifically said to define it as unsigned.
fgetc() will output EOF or an "unsigned char converted to int", so
unless your unsigned char has the same range as 0 to INT_MAX
you are going to be able to fit the converted value. But since unsigned
char may not have padding bits and int must have the signed range
available to it, int would have to be have a type larger than
0 to UCHAR_MAX, and we'd be getting into pathological cases
where sizeof(int) > 1 but all the int bits (except the sign bit)
beyond those needed to hold UCHAR_MAX would have to be padding.
Maybe possible, but we're talking DS9K environments now.

if ( fscanf(fp, "%c", &two_bytes[count++]) )
break;

If fscanf() successfully reads a char in that snippet, then
it is going to return the number of input items successfully
matched, namely 1, so the if condition would be true.

If fscanf() encounters EOF then it is going to return EOF
which is guaranteed negative (and hence non-zero), and the
logical value of any negative number is true, so the if
condition would be true.

If the format item were nearly anything other than %c then
if characters were present but failed to match the format
spec then 0 items would be matched and the return value would
be 0 and the if condition there would be false. But %c cannot
fail to match a character if one is present, so that's not
going to happen.

Hence it would appear that you got the termination condition
on the fscanf() case wrong, which argues against your earlier
claim that it is easier to get the termination condition
right for fscanf() than for fgetc().
 
O

Old Wolf

Old Wolf said:
int ch;
/* ... */
ch = fgetc(fp);
if ( ch == EOF )
break; /* or whatever */
two_bytes[count++] = ch;
Furthermore, the first snippet still has the problem of out-of-range
assignment, which I don't see an easy way around.

Where do you see the possibility of an out of range assignment in
the first snippet? Unless two_bytes is defined as {signed} char

We are talking about the case where two_bytes is plain char,
and char is signed. As I pointed out in both of my previous
posts on this thread, there's no debate about the fact that
you should use fgetc when two_bytes is unsigned char.
if ( fscanf(fp, "%c", &two_bytes[count++]) )
break;

Hence it would appear that you got the termination condition
on the fscanf() case wrong, which argues against your earlier
claim that it is easier to get the termination condition
right for fscanf() than for fgetc().

Well, I could as easily have messed up the code for fgetc as I
did for fscanf! The correct version (ie. testing against 1) is
simpler than the correct version of fgetc.
 
C

CBFalconer

Old said:
.... snip ...

Well, I could as easily have messed up the code for fgetc as I
did for fscanf! The correct version (ie. testing against 1) is
simpler than the correct version of fgetc.

fgetc returns EOF for any trouble, otherwise the integer
representation of an unsigned char.
 
P

Peter Shaggy Haywood

Groovy hepcat (e-mail address removed) was jivin' on 19 Mar 2007
14:04:50 -0700 in comp.lang.c.
Problem printing Hexadecimal's a cool scene! Dig it!
I am trying to read an exe file and print it out character by
character in hexadecimal format. The file goes something like this in
hexadecimal

FILE *fp = NULL;
int count = 0;
char nibble = NULL;
char two_bytes[16];
int i;
fp = fopen("xyz.exe","r");

In addition to what others have told you, you need to open the file
in binary mode.

--

Dig the even newer still, yet more improved, sig!

http://alphalink.com.au/~phaywood/
"Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,740
Latest member
JudsonFrie

Latest Threads

Top