Summary: Converting ascii hex to pure hex values

Chris Torek chris at mimsy.umd.edu
Sat Oct 27 08:30:19 AEST 1990


In article <302 at cti1.UUCP> mpledger at cti1.UUCP (Mark Pledger) writes:
>I sure caused alot of traffic for this little question.
>I guess I did'nt make myself clear enough on my question though.

Indeed.

>Without using scanf() (or even sprintf())  what is the best (fasted
>for me) way to convert a two-digit ascii code to a one digit hex code
>so I can put it back into the charater string s[], append a null, and
>write it back out to disk.

This question is *still* confused.

The Miriam-Webster dictionary defines `code' with four meanings.  The
one relevant to this discussion is number 3, `a system of signals', or
number 4, `a system of symbols or letters used (as in secret
communication or in a computing machine) with special meanings' (the
latter is more intended to refer to encryption codes and instruction
codes, I think).  In either case, there is no such thing as a `one
digit hex code'.  Hexadecimal is a base, not a value, and as such any
number of hexadecimal digits might be required to represent any
particular value.  Since hexadecimal is base sixteen, a single
hexadecimal digit can represent one of the values from the set
{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} (where these values are coded
in decimal).  Two hex digits can represent a value in the range
[0..255] (where the `[x..y]' notation implies `all integer values in
the range given with the lower bound x on the left and the upper bound
y on the right, inclusive of both bounds').

Now, as it happens, an eight bit byte, as is found on the most common
computers these days, can also represent a value in the range
[0..255].  The phrase `two-digit ASCII code', however, suggests a pair
of values from the set ['0'..'9'], which can represent at most 100
distinct values (usually the set [0..99]).  I.e., we have an ASCII
encoding of an integral value in [0..99].  There is no way this can be
represented with a single hexadecimal digit.  On the other hand, the
phrase `two-digit ASCII code' in close proximity to `hex code' suggests
that perhaps what is meant is a pair of values from the set
{['0'..'9'],['A'..'F']} (or the same but with lowercase).  Such a pair
can represent at most 256 distinct values, usually the set [0..255].
Coincidentally this corresponds exactly to the set of values that can
be represented by an (unsigned) eight bit byte.  But Mr. Pledger goes
on to say:

>I currently use atoi() and just write out the int to disk.

This suggests that the guess that `two ASCII digits' means `two ASCII
hexadecimal digits' (i.e., the set including the letters A through F,
rather than just the decimal digits zero through nine) is incorrect.
Now we are back to the concept of `two ASCII decimal digits', or a
printable ASCII representation of a value in the range [0..99].
We can now be fairly confident that what is desired is to take two
characters, each of which is guaranteed to be in the range ['0'..'9'],
and come up with an integer value in the range [0..99] according to
the obvious mapping ... until we reach his final sentence:

>I am interested in ... a routine that will take a character string as the 
>argument, and returning the hex result in the same character string.

But `hex', as noted above, is a particular ENCODING of a value.  It
is not a RESULT---the result of transforming two decimal ASCII digits
to a value is an integer in the range [0..99], and has nothing at all
to do with hexadecimal encodings.

Is it any wonder that such a question generates a multitude of answers?
There is no correct answer; the question is rather like asking how to
construct a circle with four sides.

Now, if all you want to do is convert an ASCII decimal representation of
a value to a binary value stored in a single `char', with the `char' being
the first of the set of `char's that held the original ASCII decimal
representation---and assuming that the original ASCII sequence is ended
with a NUL (character 0) or a non-digit, you can simply write:

	void foo(char *s) { *s = atoi(s); }

If you want the original ASCII sequence modified so that the result is
still a NUL-terminated string, you can add one more statement:

	void foo(char *s) { *s = atoi(s); s[1] = 0; }

If you want to take pairs of ASCII decimal digits and convert each pair
(with exactly two, no more and no fewer, required) into binary values and
store those in the original string, you can change this to:

	void foo(char *s) {
		char *out = s;

		while (isdigit(*s) && isdigit(s[1])) {
			*out++ = (*s - '0') * 10 + s[1] - '0';
			s += 2;
		}
		*out = 0;
	}

If you want something else, you will have to figure out what it is first.
There is no such thing as a `pure hexadecimal value', because hexadecimal
is a representation, not a value.  (Ask yourself just what an `impure
hexadecimal value' might be.)
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750)
Domain:	chris at cs.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.lang.c mailing list