Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Convert HEX string to bin

10 views
Skip to first unread message

GIR

unread,
Nov 30, 2003, 6:11:20 AM11/30/03
to
Hi,

I've been trying to tackle the following problem but haven't been
succesfull so far.

I have string

char buffer[64];

which is filled with hexadecimal values, like this.

buffer[0] = A;
buffer[1] = 1;

buffer[0..1] combined make one value, 0xA1, which should be converted
into 10100001.

I know I could use sscanf to get the values out but sscanf is not an
option because it's too big.

Does anybody know a efficient way of converting these values?

TIA,
GIR

GIR

unread,
Nov 30, 2003, 6:59:05 AM11/30/03
to


Ofcourse this:


buffer[0] = A;
buffer[1] = 1;

should be this:
buffer[0] = 'A';
buffer[1] = '1';

Just to avoid confusion.

pete

unread,
Nov 30, 2003, 7:03:25 AM11/30/03
to

hex2bin.c output:

The binary representation of 0xA1 is 10100001.

/* BEGIN hex2bin.c */

#include <stdio.h>
#include <limits.h>

char *bitstr(char *, void const *, size_t);

int main(void)
{
char buffer[64] = "A1";
unsigned char value;
char *pointer;
char ebits[CHAR_BIT * sizeof value + 1];

puts("hex2bin.c output:\n");
value = 0;
for (pointer = buffer; *pointer; ++pointer) {
value *= 16;
switch (*pointer) {
case 'a':
case 'A':
value += 0xa;
break;
case 'b':
case 'B':
value += 0xb;
break;
case 'c':
case 'C':
value += 0xc;
break;
case 'd':
case 'D':
value += 0xd;
break;
case 'e':
case 'E':
value += 0xe;
break;
case 'f':
case 'F':
value += 0xf;
break;
default:
value += *pointer - '0';
break;
}
}
bitstr(ebits, &value, sizeof value);
printf("The binary representation of 0x%s is %s.\n",
buffer, ebits);
return 0;
}

char *bitstr(char *str, const void *obj, size_t n)
{
unsigned char mask;
const unsigned char *byte = obj;
char *const ptr = str;

while (n--) {
mask = ((unsigned char)-1 >> 1) + 1;
do {
*str++ = (char)(mask & byte[n] ? '1' : '0');
mask >>= 1;
} while (mask);
}
*str = '\0';
return ptr;
}

/* END hex2bin.c */

Richard Heathfield

unread,
Nov 30, 2003, 7:30:39 AM11/30/03
to
GIR wrote:

Assuming it really is a string (i.e. null-terminated), this ought to work,
modulo bugs...

#include <ctype.h>
#include <string.h>

void printbinary(const char *hex)
{
char *p;
int i, j;
while(*hex)
{
p = strchr("0123456789abcdef", tolower(*hex));
if(p != NULL)
{
for(i = p - hex, j = 8; j > 0; j /= 2)
{
if(i >= j)
{
putchar('1');
i -= j;
}
else
{
putchar('0');
}
}
}
++hex;
}
}

--
Richard Heathfield : bin...@eton.powernet.co.uk
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton

Sidney Cadot

unread,
Nov 30, 2003, 8:45:39 AM11/30/03
to
GIR wrote:

> I have string
>
> char buffer[64];
>
> which is filled with hexadecimal values, like this.
>
> buffer[0] = A;
> buffer[1] = 1;

"buffer[0] = A;" doesn't mean anything; I'm assuming that you mean

buffer[0] = 'A';
buffer[1] = '1';

> buffer[0..1] combined make one value, 0xA1, which should be converted
> into 10100001.

> I know I could use sscanf to get the values out but sscanf is not an
> option because it's too big.

I'd write something like this (which doesn't depend on ASCII per se):

for(i=0;i<64;i++)
{
switch(tolower(buffer[i]))
{
case '0': emit("0000"); break;
case '1': emit("0001"); break;
case '2': emit("0010"); break;
case '3': emit("0011"); break;
case '4': emit("0100"); break;
case '5': emit("0101"); break;
case '6': emit("0110"); break;
case '7': emit("0111"); break;
case '8': emit("1000"); break;
case '9': emit("1001"); break;
case 'a': emit("1010"); break;
case 'b': emit("1011"); break;
case 'c': emit("1100"); break;
case 'd': emit("1101"); break;
case 'e': emit("1110"); break;
case 'f': emit("1111"); break;
default:
fprintf(stderr, "oops!\n");
exit(EXIT_FAILURE);
}
}

Nejat AYDIN

unread,
Nov 30, 2003, 9:06:31 AM11/30/03
to
Richard Heathfield wrote:
>
> GIR wrote:
>
> > Hi,
> >
> > I've been trying to tackle the following problem but haven't been
> > succesfull so far.
[...]

>
> Assuming it really is a string (i.e. null-terminated), this ought to work,
> modulo bugs...
^^^^^^^^^^^

Some bug fixes below.

> #include <ctype.h>
> #include <string.h>
>
> void printbinary(const char *hex)
> {
> char *p;
> int i, j;
> while(*hex)
> {

char *hexdigits = "0123456789abcdef";

> p = strchr("0123456789abcdef", tolower(*hex));

p = strchr(hexdigits, tolower(*hex));

> if(p != NULL)
> {
> for(i = p - hex, j = 8; j > 0; j /= 2)

^^^

for(i = p - hexdigits, j = 8; j > 0; j /= 2)

/* I would also do while(isxdigit(*hex)) in the while loop
* instead of while(*hex), so I would not have to test
* the p for NULL, and the function would return as soos as
* it encounters a non-hexadecimal digit.
*/

Richard Heathfield

unread,
Nov 30, 2003, 10:10:33 AM11/30/03
to
Nejat AYDIN wrote:

> Richard Heathfield wrote:
>>
>> GIR wrote:
>>
>> > Hi,
>> >
>> > I've been trying to tackle the following problem but haven't been
>> > succesfull so far.
> [...]
>>
>> Assuming it really is a string (i.e. null-terminated), this ought to
>> work, modulo bugs...
> ^^^^^^^^^^^
>
> Some bug fixes below.
>
>> #include <ctype.h>
>> #include <string.h>
>>
>> void printbinary(const char *hex)
>> {
>> char *p;
>> int i, j;
>> while(*hex)
>> {
>
> char *hexdigits = "0123456789abcdef";
>
>> p = strchr("0123456789abcdef", tolower(*hex));

Stupid stupid stupid of me.

Yes, your corrections are spot-on.

That's why I put these damn things into libraries.

>
> /* I would also do while(isxdigit(*hex)) in the while loop

Nice. A definite improvement.

GIR

unread,
Nov 30, 2003, 10:16:42 AM11/30/03
to
On Sun, 30 Nov 2003 14:45:39 +0100, Sidney Cadot <sid...@jigsaw.nl>
wrote:

>GIR wrote:
>
>> I have string
>>
>> char buffer[64];
>>
>> which is filled with hexadecimal values, like this.
>>
>> buffer[0] = A;
>> buffer[1] = 1;
>
>"buffer[0] = A;" doesn't mean anything; I'm assuming that you mean
>
>buffer[0] = 'A';
>buffer[1] = '1';
>

Yes, I made a little post below this one with the subject: "Re: Small
correction: Convert HEX string to bin". I ment 'A' and not A.

The thing is that I cannot use any of the standard functions, they're
too big and too slow. This is my solution:

bit sec_char; // holds wether processing first or second char
unsigned char memory[32768]; // holds the final bit patern
/* SBUF is the Serial Buffer which holds the current char to be
processed */

if(!sec_char) {

memory[i] = 0x00;

if (SBUF >= 'A' && SBUF <= 'F') {
memory[i] |= (SBUF - '0') - 7;
} else {
memory[i] |= (SBUF - '0');
}

memory[i] <<= 4;
sec_char = 1;

} else {

if (SBUF >= 'A' && SBUF <= 'F') {
memory[i] |= (SBUF - '0') - 7;
} else {
memory[i] |= (SBUF - '0');
}

sec_char = 0;
i++;
}

The thing is that I need something even faster.

Sidney Cadot

unread,
Nov 30, 2003, 3:56:44 PM11/30/03
to
GIR wrote:

> Yes, I made a little post below this one with the subject: "Re: Small
> correction: Convert HEX string to bin". I ment 'A' and not A.

Ok, missed that.

> The thing is that I cannot use any of the standard functions, they're
> too big and too slow. This is my solution:
>
> bit sec_char; // holds wether processing first or second char
> unsigned char memory[32768]; // holds the final bit patern
> /* SBUF is the Serial Buffer which holds the current char to be
> processed */
>
> if(!sec_char) {
>
> memory[i] = 0x00;
>
> if (SBUF >= 'A' && SBUF <= 'F') {
> memory[i] |= (SBUF - '0') - 7;
> } else {
> memory[i] |= (SBUF - '0');
> }
>
> memory[i] <<= 4;
> sec_char = 1;
>
> } else {
>
> if (SBUF >= 'A' && SBUF <= 'F') {
> memory[i] |= (SBUF - '0') - 7;
> } else {
> memory[i] |= (SBUF - '0');
> }
>
> sec_char = 0;
> i++;
> }
>
> The thing is that I need something even faster.

Ok, this does something different than I understood you needed; you are
not converting to a binary external representation but you basically
need to parse a hexadecimal ascii representation to an array of unsigned
bytes.

Judging from your implementation, I'd say that roughly a factor 2--3
gain is still possible (that's without a lookup table, which I think
will be prohibitively big). Before we go down that road, please explain
where you get SBUF from, is it directly coming from a serial controller?
Is its value reliable (i.e., what should happen if SBUF contains a
character other than '0'..'9', 'A'..'F')?

And: what happened to the 64-byte length of buffer? This could yield 32
bytes of information, but not 32768.

In short, in order to squeeze every last bit of performance out of the
compiler for your problem, more problem-specific context is needed.

Regards, Sidney

CBFalconer

unread,
Nov 30, 2003, 5:05:27 PM11/30/03
to
GIR wrote:
> On Sun, 30 Nov 2003 12:11:20 +0100, GIR <n...@spam.com> wrote:
> >
> > I've been trying to tackle the following problem but haven't
> > been succesfull so far.
> >
> > I have string
> >
> > char buffer[64];
> >
> > which is filled with hexadecimal values, like this.
> >
> > buffer[0] = A;
> > buffer[1] = 1;
> >
> > buffer[0..1] combined make one value, 0xA1, which should be
> > converted into 10100001.
> >
> > I know I could use sscanf to get the values out but sscanf
> > is not an option because it's too big.
> >
> > Does anybody know a efficient way of converting these values?
>
> Ofcourse this:
> buffer[0] = A;
> buffer[1] = 1;
>
> should be this:
> buffer[0] = 'A';
> buffer[1] = '1';

If you simply impose a condition "buffer[2] = non-hex-character",
which includes '\0', blank, etc. you have an extremely simple
solution:

#include <stdlib.h>

...
<some integral type> val; /* suitable to hold the values */
...
val = strtoul(buffer, NULL, 16);

--
Chuck F (cbfal...@yahoo.com) (cbfal...@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!

Andy

unread,
Dec 1, 2003, 1:34:36 AM12/1/03
to
On Sun, 30 Nov 2003 16:16:42 +0100, GIR <n...@spam.com> wrote:

>The thing is that I cannot use any of the standard functions, they're
>too big and too slow. This is my solution:
>
>bit sec_char; // holds wether processing first or second char
>unsigned char memory[32768]; // holds the final bit patern
>/* SBUF is the Serial Buffer which holds the current char to be
>processed */
>
>if(!sec_char) {
>
> memory[i] = 0x00;

Make memory[i] a register variable. After assembling a complete byte,
then store the register contents in memory[i].

>
> if (SBUF >= 'A' && SBUF <= 'F') {

If SBUF is guaranteed to be only hex characters,
if (SBUF > '9') { is sufficient.

Richard Heathfield

unread,
Dec 1, 2003, 2:49:52 AM12/1/03
to
Andy wrote:

> On Sun, 30 Nov 2003 16:16:42 +0100, GIR <n...@spam.com> wrote:
>
>> if (SBUF >= 'A' && SBUF <= 'F') {
>
> If SBUF is guaranteed to be only hex characters,
> if (SBUF > '9') { is sufficient.

No, because the C language does not guarantee that 'A' has a coding point
higher than '9'.

The Real OS/2 Guy

unread,
Dec 1, 2003, 7:34:33 AM12/1/03
to

works when
1. buffer has always an even size
2. buffer if always filled completely:


size_t i, j;
unsigned char c = 0;
for (i = j = 0; j < sizeof(buffer); ) {
if (buffer[j] >= '0' && buffer[j] <= '9')
c = buffer[j++] - '0';
else {
switch (buffer[j]) {
case 'a':
c = buffer[j++] - 'a';
break;
case 'A'
c = buffer[i++] - 'A';
break;
.....other hex digits go here.....
case 'F':
c = buffer[i++] - 'F';
break;
}
c <<= 8;
if (buffer[j] >= '0' && buffer[j] <= '9'
c |= buffer[j++] - '0';
else {
......like the else above, but insted of = use |=
}
buffer[i++] = c;
}

The standard guarantees thet '0' to '9' are continous, but there is no
guarantee that 'a' - 'f' or 'A' - 'F' have the same continuity, so use
a switch for them makes it portable.

--
Tschau/Bye
Herbert

To buy eComStation 1.1 in germany visit http://www.pc-rosenau.de

Peter Nilsson

unread,
Dec 1, 2003, 8:00:46 AM12/1/03
to
"Richard Heathfield" <dont...@address.co.uk.invalid> wrote
>
> #include <ctype.h>
...
> void printbinary(const char *hex)
> {
...
> while(*hex)
> {
> ...tolower(*hex)...

I believe your book has some explanation on why an (unsigned char) cast is
reasonably appropriate here. :-)

--
Peter


pete

unread,
Dec 1, 2003, 9:18:12 AM12/1/03
to
Richard Heathfield wrote:
>
> Andy wrote:
>
> > On Sun, 30 Nov 2003 16:16:42 +0100, GIR <n...@spam.com> wrote:
> >
> >> if (SBUF >= 'A' && SBUF <= 'F') {
> >
> > If SBUF is guaranteed to be only hex characters,
> > if (SBUF > '9') { is sufficient.
>
> No, because the C language does not guarantee
> that 'A' has a coding point higher than '9'.

The C language does not guarantee
that 'F' has a coding point higher than 'A'.
Which character constants, are bewteen 'A' and 'F',
is implementation defined also.

--
pete

CBFalconer

unread,
Dec 1, 2003, 1:16:54 PM12/1/03
to
The Real OS/2 Guy wrote:
>
... snip ...

>
> The standard guarantees thet '0' to '9' are continous, but there is
> no guarantee that 'a' - 'f' or 'A' - 'F' have the same continuity,
> so use a switch for them makes it portable.

Instead of all the complexity, and assuming that the OP will not
use the strto*() family for some reason, the digit conversions can
be done by:

#include <string.h>

/* Convert hex char to value, -1 for non-hex char */
int unhexify(char c)
{
static hexchars = "0123456789abcdefABCDEF";
char *p;
int val;

val = -1; /* default assume non-hex */
if ((p = strchr(hexchars, c))) {
val = p - hexchars;
if (val > 15) val = val - 6;
}
return val;
} /* unhexify, untested */

Which I believe to be fully portable, including char coding. Now
the OP can convert his (terminated) input string with:

char *p
unsigned int v;
int d;

.....
p = &instring[0];
v = 0;
while ((d = unhexify(*p)) >= 0) {
v = 16 * v + d;
++p;
}
/* desired result in v */

Richard Heathfield

unread,
Dec 1, 2003, 2:17:37 PM12/1/03
to
Peter Nilsson wrote:

Believe it or not, I put it in, and then took it out again. :-)

That whole reply was a heap of crud, which I wish I'd never posted.

Incidentally, it may be worth pointing out that, if I'd used
while(isxdigit((unsigned char)*hex) instead of while(*hex), the cast to
unsigned char in the call to tolower() would be unnecessary (since all the
characters '0' through '9' and ABCDEFabcdef are guaranteed to be
representable as unsigned char).

Richard Heathfield

unread,
Dec 1, 2003, 2:19:46 PM12/1/03
to
pete wrote:

> Richard Heathfield wrote:
>>
>> Andy wrote:
>>
>> > On Sun, 30 Nov 2003 16:16:42 +0100, GIR <n...@spam.com> wrote:
>> >
>> >> if (SBUF >= 'A' && SBUF <= 'F') {
>> >
>> > If SBUF is guaranteed to be only hex characters,
>> > if (SBUF > '9') { is sufficient.
>>
>> No, because the C language does not guarantee
>> that 'A' has a coding point higher than '9'.

(I meant "code point".)

> The C language does not guarantee
> that 'F' has a coding point higher than 'A'.

That's another reason, yes. :-)

> Which character constants, are bewteen 'A' and 'F',
> is implementation defined also.

And that!

GIR

unread,
Dec 1, 2003, 3:12:10 PM12/1/03
to
On Sun, 30 Nov 2003 21:56:44 +0100, Sidney Cadot <sid...@jigsaw.nl>
wrote:

>Ok, this does something different than I understood you needed; you are

>not converting to a binary external representation but you basically
>need to parse a hexadecimal ascii representation to an array of unsigned
>bytes.
>
>Judging from your implementation, I'd say that roughly a factor 2--3
>gain is still possible (that's without a lookup table, which I think
>will be prohibitively big). Before we go down that road, please explain
>where you get SBUF from, is it directly coming from a serial controller?
>Is its value reliable (i.e., what should happen if SBUF contains a
>character other than '0'..'9', 'A'..'F')?
>
>And: what happened to the 64-byte length of buffer? This could yield 32
>bytes of information, but not 32768.
>
>In short, in order to squeeze every last bit of performance out of the
>compiler for your problem, more problem-specific context is needed.
>
>Regards, Sidney

Okay here's a little explenation and background info.

This is for a little project which somebody dumped on mu desk. The
idea is to have a 8051 derative (Infineon 80c515A) process audio at
8bit mono 8khz.

There is a preprocessor which converts the binary wavefile to hex and
strips the header/footer. Don't ask me why, it wasn't my idea. In my
opinion it would be much simpeler if the preprocessor would just dump
everything to the serialport, now we go from bin=>hex - serial -
hex=>bin. The preprocessor is out of my range. In the docs it's
specified that the preprocessor will check the stream for errors and
such, so I don't have to worry about that.

What happens when the microcontroller receives the data over the
serialport? First of all a interupt is generated, the data on the
serial line is placed in SBUF (a special function register) and the
processor jumps to the interuptvector depending on it's priority.

Why the 32k length of the buffer? I don't know why... ;) The thing has
64k of memory so I just took half of that, remember this is just
version 0.000000001a. I was thinking of building a dynamic listm but
that seriously cuts in on the available memory. For instance:

struct mem_byte {
char mem;
char *next_byte;
};

So I need a byte for storing the info and I need a byte for storing
the adres of the next byte. That's double...

Anywayz, I'll just run over to the guyz who are did the preprocessor
and "ask" (read yell and order) them if it isn't better for them to
just dump binary data on the line.

Anywayz, tnx for your help. You guyz got a nice little group going
here :)

grtz,
GIR

Sidney Cadot

unread,
Dec 1, 2003, 3:55:13 PM12/1/03
to
Richard Heathfield wrote:

>>If SBUF is guaranteed to be only hex characters,
>> if (SBUF > '9') { is sufficient.
>
>
> No, because the C language does not guarantee that 'A' has a coding point
> higher than '9'.

The OP is of course presuming ascii... c-'0'-7 to get 'A' to 10 is the clue.

Best regards,

Sidney

The Real OS/2 Guy

unread,
Dec 1, 2003, 4:33:57 PM12/1/03
to
On Mon, 1 Dec 2003 18:16:54 UTC, CBFalconer <cbfal...@yahoo.com>
wrote:

> The Real OS/2 Guy wrote:
> >
> ... snip ...
> >
> > The standard guarantees thet '0' to '9' are continous, but there is
> > no guarantee that 'a' - 'f' or 'A' - 'F' have the same continuity,
> > so use a switch for them makes it portable.
>
> Instead of all the complexity, and assuming that the OP will not
> use the strto*() family for some reason, the digit conversions can
> be done by:
>
> #include <string.h>
>
> /* Convert hex char to value, -1 for non-hex char */
> int unhexify(char c)
> {
> static hexchars = "0123456789abcdefABCDEF";
> char *p;
> int val;
>
> val = -1; /* default assume non-hex */
> if ((p = strchr(hexchars, c))) {
> val = p - hexchars;
> if (val > 15) val = val - 6;
> }
> return val;
> } /* unhexify, untested */
>
> Which I believe to be fully portable, including char coding. Now
> the OP can convert his (terminated) input string with:

Yes, but the OP was asking for a method to save all possible runtime.
And a table lookup is relatively slow. So it is justified to have a
more complex code but save runtime.



> char *p
> unsigned int v;
> int d;
>
> .....
> p = &instring[0];
> v = 0;
> while ((d = unhexify(*p)) >= 0) {
> v = 16 * v + d;
> ++p;
> }
> /* desired result in v */
>

Calling a function for each char is another brake. I had not used
pointers because I'm not sure that the OP is ready to understund
pointer arithmetc yet and any good compiler should create even the
same code.

By that, the separate p++ can be another brake as many real CPU can do
*p++ in an single instruction instead of *p and some times later p +=
1.

Sidney Cadot

unread,
Dec 1, 2003, 4:55:16 PM12/1/03
to
GIR wrote:

But as I understand it, the preprocessor is sitting on the other side of
the serial line. So what should happen if an 'A' is converted to a '@' ?
It only takes one bit-fault.

> What happens when the microcontroller receives the data over the
> serialport? First of all a interupt is generated, the data on the
> serial line is placed in SBUF (a special function register) and the
> processor jumps to the interuptvector depending on it's priority.
>
> Why the 32k length of the buffer? I don't know why... ;) The thing has
> 64k of memory so I just took half of that, remember this is just
> version 0.000000001a. I was thinking of building a dynamic listm but
> that seriously cuts in on the available memory. For instance:
>
> struct mem_byte {
> char mem;
> char *next_byte;
> };
>
> So I need a byte for storing the info and I need a byte for storing
> the adres of the next byte. That's double...

Make that triple. Since you're working with 16-bit addressable memory,
the pointer will be at least 2 chars. An then there is the heap manager
overhead. It's a good idea you dumped this idea.

> Anywayz, I'll just run over to the guyz who are did the preprocessor
> and "ask" (read yell and order) them if it isn't better for them to
> just dump binary data on the line.

Most certainly. Yell and order them to include a CRC as well, every 256
bytes or so, for starters. Make sure you get a quantitive handle on the
number of bit-faults you get, and think of how to handle them.

> Anywayz, tnx for your help. You guyz got a nice little group going
> here :)

I'm quite sure you would be better of coding this little gadget in
assembly. It wouldn't be too hard.

Best regards,

Sidney

glen herrmannsfeldt

unread,
Dec 1, 2003, 7:16:02 PM12/1/03
to
The Real OS/2 Guy wrote:

(snip)

> The standard guarantees thet '0' to '9' are continous, but there is no
> guarantee that 'a' - 'f' or 'A' - 'F' have the same continuity, so use
> a switch for them makes it portable.

Yes, the standard doesn't guarantee that.

It is, however, true in both ASCII and EBCDIC.

Do you know anyone using a different character set?

-- glen

Richard Heathfield

unread,
Dec 2, 2003, 2:20:03 AM12/2/03
to
glen herrmannsfeldt wrote:

> Yes, the standard doesn't guarantee that.
>
> It is, however, true in both ASCII and EBCDIC.
>
> Do you know anyone using a different character set?

That isn't the right criterion to apply here. Rather, we should ask
ourselves whether there is anyone we /don't/ know who is using a different
character set, and whether we want our code to work on their machine as
well.

CBFalconer

unread,
Dec 2, 2003, 3:29:24 AM12/2/03
to

Possibly, but try it first. strchr may be very efficient.

>
> > char *p
> > unsigned int v;
> > int d;
> >
> > .....
> > p = &instring[0];
> > v = 0;
> > while ((d = unhexify(*p)) >= 0) {
> > v = 16 * v + d;
> > ++p;
> > }
> > /* desired result in v */
>
> Calling a function for each char is another brake. I had not used
> pointers because I'm not sure that the OP is ready to understund
> pointer arithmetc yet and any good compiler should create even the
> same code.
>
> By that, the separate p++ can be another brake as many real CPU
> can do *p++ in an single instruction instead of *p and some times
> later p += 1.

That combination is a trap. It would allow the pointer to be
advanced past the known area of instring, which may or may not be
legitimate.

I rather doubt that speed is any great consideration for the OP -
he wants to minimize code size. I suspect that these will be used
in i/o, and thus limited by the i/o rates anyhow.

CBFalconer

unread,
Dec 2, 2003, 3:29:26 AM12/2/03
to

Yes

The Real OS/2 Guy

unread,
Dec 2, 2003, 5:25:48 AM12/2/03
to
On Mon, 1 Dec 2003 20:12:10 UTC, GIR <n...@spam.com> wrote:

> Okay here's a little explenation and background info.
>
> This is for a little project which somebody dumped on mu desk. The
> idea is to have a 8051 derative (Infineon 80c515A) process audio at
> 8bit mono 8khz.

Ok so far. But gets you an unordered stream of data or is there some
more logic behind that?

Maybe you can get the stream ordered by telegrams. That means you get
at first the size (one or two bytes and then the data block from
outside? Yes, when they can send you the data in binary it saves both
ends some time (converting nibbles to hex char and back, the number of
bytes needed to transfer.
Is the line trusted? When not packing a CRC in the telegram (with the
possibility to correct single (or multibit errors) would make an
untrusted line (nearly) trusted.

May be you should simply receive note by note - so your transfer
buffer can shrink significantly. As any byte you saves gives you more
freedom of use the limited memory for other things.

> Why the 32k length of the buffer? I don't know why... ;) The thing has
> 64k of memory so I just took half of that, remember this is just
> version 0.000000001a. I was thinking of building a dynamic listm but
> that seriously cuts in on the available memory. For instance:

When it is possible to break the stream into little telegrams you may
use a circular buffer. Wheras you works on a single telegram while the
next ones gets received.

The Real OS/2 Guy

unread,
Dec 2, 2003, 5:49:33 AM12/2/03
to

I don't know any kind of computer having an C imlementation. There are
too many different kinds of processors on the world. So programming in
a manner that does not requires something the standard does not
guarantee is errornous whenever it is possible to do it ANSI
compilant.

Dan Pop

unread,
Dec 2, 2003, 8:10:21 AM12/2/03
to

The trivial, assumption free approach is to define the hex digits
yourself:

int hex2dec(char c)
{
char *hexdigs = "01234567890ABCDEF";
char *p = strchr(hexdigs, toupper((unsigned char)c));

if (p != NULL)
return p - hexdigs;
else
return -1;
}

Trivia quiz: find the bug in this code.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Dan...@ifh.de

Johan Aurer

unread,
Dec 2, 2003, 10:24:40 AM12/2/03
to
On Tue, 2 Dec 2003, Dan Pop wrote:

> The trivial, assumption free approach is to define the hex digits
> yourself:
>
> int hex2dec(char c)
> {
> char *hexdigs = "01234567890ABCDEF";
> char *p = strchr(hexdigs, toupper((unsigned char)c));
>
> if (p != NULL)
> return p - hexdigs;
> else
> return -1;
> }
>
> Trivia quiz: find the bug in this code.

Which one? The c == 0 bug?

--
au...@axis.com

Irrwahn Grausewitz

unread,
Dec 2, 2003, 11:17:26 AM12/2/03
to
Dan...@cern.ch (Dan Pop) wrote:
<snip>
> The trivial, assumption free approach is to define the hex digits
> yourself:
>
> int hex2dec(char c)
> {
> char *hexdigs = "01234567890ABCDEF";
> char *p = strchr(hexdigs, toupper((unsigned char)c));
>
> if (p != NULL)
> return p - hexdigs;
> else
> return -1;
> }
>
> Trivia quiz: find the bug in this code.

You mean: the bugs (plural!). :)

1. failure to #include <string.h>

2. failure to #include <ctype.h>

3. "01234567890ABCDEF" should be "0123456789ABCDEF"

4. With 1.-3. corrected, hex2dev will return 16 if c equals zero,
because strchr will return a pointer to the terminating null
character of the digit string (the terminating null character is
considered to be part of the string).

What did I win? ;)

Regards
--
Irrwahn
(irrw...@freenet.de)

Richard Bos

unread,
Dec 2, 2003, 11:28:27 AM12/2/03
to
Irrwahn Grausewitz <irrw...@freenet.de> wrote:

5. In some locales, passing an accented character, which is not a hex
digit, to toupper() may result in an upper-case unaccented character,
which is.

Richard

Dan Pop

unread,
Dec 2, 2003, 11:17:40 AM12/2/03
to
In <3FCB5B3B...@yahoo.com> CBFalconer <cbfal...@yahoo.com> writes:

>Instead of all the complexity, and assuming that the OP will not
>use the strto*() family for some reason, the digit conversions can
>be done by:
>
>#include <string.h>
>
>/* Convert hex char to value, -1 for non-hex char */
>int unhexify(char c)
>{
> static hexchars = "0123456789abcdefABCDEF";
> char *p;
> int val;
>
> val = -1; /* default assume non-hex */
> if ((p = strchr(hexchars, c))) {
> val = p - hexchars;
> if (val > 15) val = val - 6;
> }
> return val;
>} /* unhexify, untested */

It has the same bug that I deliberately left unfixed in my version, posted
to the original thread ;-)

Dan Pop

unread,
Dec 2, 2003, 11:12:31 AM12/2/03
to
In <bqhef2$ie0$1...@titan.btinternet.com> Richard Heathfield <dont...@address.co.uk.invalid> writes:

>glen herrmannsfeldt wrote:
>
>> Yes, the standard doesn't guarantee that.
>>
>> It is, however, true in both ASCII and EBCDIC.
>>
>> Do you know anyone using a different character set?
>
>That isn't the right criterion to apply here. Rather, we should ask
>ourselves whether there is anyone we /don't/ know who is using a different
>character set, and whether we want our code to work on their machine as
>well.

As usual, in real world programming, when there is a tradeoff between
portability and performance, the good programmer makes the right choice:
if the portable code is fast enough, it is used, otherwise the fast code
is used and the assumptions it relies upon are clearly documented.

Dan Pop

unread,
Dec 2, 2003, 11:56:59 AM12/2/03
to
In <foepsvos1kifjeqq0...@4ax.com> Irrwahn Grausewitz <irrw...@freenet.de> writes:

>Dan...@cern.ch (Dan Pop) wrote:
><snip>
>> The trivial, assumption free approach is to define the hex digits
>> yourself:
>>
>> int hex2dec(char c)
>> {
>> char *hexdigs = "01234567890ABCDEF";
>> char *p = strchr(hexdigs, toupper((unsigned char)c));
>>
>> if (p != NULL)
>> return p - hexdigs;
>> else
>> return -1;
>> }
>>
>> Trivia quiz: find the bug in this code.
>
>You mean: the bugs (plural!). :)
>
>1. failure to #include <string.h>
>
>2. failure to #include <ctype.h>

These are deliberate omissions. My code was not supposed to be a
complete translation unit.

>3. "01234567890ABCDEF" should be "0123456789ABCDEF"

That's called a typo. I had to reread my string several times before
seeing it.

>4. With 1.-3. corrected, hex2dev will return 16 if c equals zero,
> because strchr will return a pointer to the terminating null
> character of the digit string (the terminating null character is
> considered to be part of the string).
>
>What did I win? ;)

Did I promise anything? ;-)

The Real OS/2 Guy

unread,
Dec 2, 2003, 1:38:21 PM12/2/03
to
On Tue, 2 Dec 2003 08:29:24 UTC, CBFalconer <cbfal...@yahoo.com>
wrote:

> > Yes, but the OP was asking for a method to save all possible
> > runtime. And a table lookup is relatively slow. So it is
> > justified to have a more complex code but save runtime.
>
> Possibly, but try it first. strchr may be very efficient.

Not so efficient than 2 if. Even not so efficieant than 2 if and a
switch of at least only 6 cases.



> >
> > > char *p
> > > unsigned int v;
> > > int d;
> > >
> > > .....
> > > p = &instring[0];
> > > v = 0;
> > > while ((d = unhexify(*p)) >= 0) {
> > > v = 16 * v + d;
> > > ++p;
> > > }
> > > /* desired result in v */
> >
> > Calling a function for each char is another brake. I had not used
> > pointers because I'm not sure that the OP is ready to understund
> > pointer arithmetc yet and any good compiler should create even the
> > same code.
> >
> > By that, the separate p++ can be another brake as many real CPU
> > can do *p++ in an single instruction instead of *p and some times
> > later p += 1.
>
> That combination is a trap. It would allow the pointer to be
> advanced past the known area of instring, which may or may not be
> legitimate.

And that is really wrong. As the standard allows to build the address
of the first member directly behind the array.



> I rather doubt that speed is any great consideration for the OP -
> he wants to minimize code size. I suspect that these will be used
> in i/o, and thus limited by the i/o rates anyhow.
>

The OP required speed over size.

Irrwahn Grausewitz

unread,
Dec 2, 2003, 1:44:37 PM12/2/03
to
Dan...@cern.ch (Dan Pop) wrote:
> In <foepsvos1kifjeqq0...@4ax.com> Irrwahn Grausewitz <irrw...@freenet.de> writes:
>
> >Dan...@cern.ch (Dan Pop) wrote:
> ><snip>
> >> The trivial, assumption free approach is to define the hex digits
> >> yourself:
> >>
> >> int hex2dec(char c)
> >> {
> >> char *hexdigs = "01234567890ABCDEF";
> >> char *p = strchr(hexdigs, toupper((unsigned char)c));
> >>
> >> if (p != NULL)
> >> return p - hexdigs;
> >> else
> >> return -1;
> >> }
> >>
> >> Trivia quiz: find the bug in this code.
> >
> >You mean: the bugs (plural!). :)
> >
> >1. failure to #include <string.h>
> >
> >2. failure to #include <ctype.h>
>
> These are deliberate omissions. My code was not supposed to be a
> complete translation unit.

Fair enough.



> >3. "01234567890ABCDEF" should be "0123456789ABCDEF"
>
> That's called a typo. I had to reread my string several times before
> seeing it.

That's the most dangerous kind of typos: the ones that aren't caught
by the compiler and are hard to find, even when you *know* they are
there (and yes, I know that you already knew that ;).


> >4. With 1.-3. corrected, hex2dev will return 16 if c equals zero,
> > because strchr will return a pointer to the terminating null
> > character of the digit string (the terminating null character is
> > considered to be part of the string).
> >
> >What did I win? ;)
>
> Did I promise anything? ;-)

Nope, that's why I asked... ;D

Regards
--
Irrwahn Grausewitz (irrw...@freenet.de)
welcome to clc : http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html
clc faq-list : http://www.eskimo.com/~scs/C-faq/top.html
acllc-c++ faq : http://www.contrib.andrew.cmu.edu/~ajo/faqs/acllc-c++.html

glen herrmannsfeldt

unread,
Dec 2, 2003, 3:37:20 PM12/2/03
to
Richard Heathfield wrote:

> glen herrmannsfeldt wrote:

>>Yes, the standard doesn't guarantee that.

>>It is, however, true in both ASCII and EBCDIC.

>>Do you know anyone using a different character set?

> That isn't the right criterion to apply here. Rather, we should ask
> ourselves whether there is anyone we /don't/ know who is using a different
> character set, and whether we want our code to work on their machine as
> well.

I think I agree with Dan's answer here. Program in the real world, and
document what you do. As EBCDIC does have other characters between 'A'
and 'Z', (only '\\' and '}' on the chart I have) you can't depend on
just testing 'A' and 'Z' in a portable program if your program might run
on EBCDIC systems.

On the other hand, all these programs do assume that an alphabet with
characters like 'A' exists? People in some countries may disagree with
that assumption.

There is a program I know, written using EBCDIC characters, that has
comments indicating that if the source is translated to a different
character set it will process input in that character set. I don't
believe that has ever been done, but it is nice that they documented it.

I expect it is extremely unlikely that anyone will come up with a
character code based on the roman alphabet which doesn't have the
letters 'A' to 'F' in ascending order. It seems more likely that they
will want to use it with a non roman alphabet.

Oh, in EBCDIC '0' (zero, not oh) is greater than 'Z'. I believe one of
the posted programs assumed it was not.

-- glen

GIR

unread,
Dec 2, 2003, 4:15:47 PM12/2/03
to
On Tue, 2 Dec 2003 10:25:48 +0000 (UTC), "The Real OS/2 Guy"
<os2...@pc-rosenau.de> wrote:

>On Mon, 1 Dec 2003 20:12:10 UTC, GIR <n...@spam.com> wrote:
>
>> Okay here's a little explenation and background info.
>>
>> This is for a little project which somebody dumped on mu desk. The
>> idea is to have a 8051 derative (Infineon 80c515A) process audio at
>> 8bit mono 8khz.
>
>Ok so far. But gets you an unordered stream of data or is there some
>more logic behind that?
>
>Maybe you can get the stream ordered by telegrams. That means you get
>at first the size (one or two bytes and then the data block from
>outside? Yes, when they can send you the data in binary it saves both
>ends some time (converting nibbles to hex char and back, the number of
>bytes needed to transfer.
>Is the line trusted? When not packing a CRC in the telegram (with the
>possibility to correct single (or multibit errors) would make an
>untrusted line (nearly) trusted.
>
>May be you should simply receive note by note - so your transfer
>buffer can shrink significantly. As any byte you saves gives you more
>freedom of use the limited memory for other things.

Well the logic behind converting the binary file to HEX was that they
could convert it to Intel HEX and have a "easy" way of implementing a
checksum and such. Having 1 byte out of order isn't a big deal,
remember this is going at 8 khkz, that's 8000 times per sec. Having
just 1 borked block wouldn't make any difference, not to the untrained
ear anywayz. The quality is so low you wouldn't know the difference
anyway.

Error checking and such isn't a big priority rightnow, my job is too
look at what they already did (which is craphola to say the least) and
optimize it in such way that it's still useable and understandable to
them (So ASM is out). That means writing custom functions and methods
which can read/write to the serial interface without the use of the
standard functions.

I'm just going to stick to that job specification and let them handle
the rest. As you may have noticed, my job is not C :)

>> Why the 32k length of the buffer? I don't know why... ;) The thing has
>> 64k of memory so I just took half of that, remember this is just
>> version 0.000000001a. I was thinking of building a dynamic listm but
>> that seriously cuts in on the available memory. For instance:
>
>When it is possible to break the stream into little telegrams you may
>use a circular buffer. Wheras you works on a single telegram while the
>next ones gets received.

the buffer is already a circular buffer :)

I told them today that it would be easier for them to implement a
custom protocol. Like say 'C' followed by a string is a Command and
'D' followed by some binary data is Data.

I always wanted to say this and I quote: "Don't ask me I just work
here".

pete

unread,
Dec 2, 2003, 5:07:05 PM12/2/03
to
glen herrmannsfeldt wrote:

> On the other hand, all these programs do assume that an alphabet with
> characters like 'A' exists?
> People in some countries may disagree with that assumption.

'A' exists in both the basic source and basic execution character sets.

--
pete

Mark McIntyre

unread,
Dec 2, 2003, 6:34:11 PM12/2/03
to
On Tue, 02 Dec 2003 00:16:02 GMT, in comp.lang.c , glen herrmannsfeldt
<g...@ugcs.caltech.edu> wrote:

>The Real OS/2 Guy wrote:
>
>> The standard guarantees thet '0' to '9' are continous, but there is no
>> guarantee that 'a' - 'f' or 'A' - 'F' have the same continuity, so use
>> a switch for them makes it portable.
>

>It is, however, true in both ASCII and EBCDIC.
>
>Do you know anyone using a different character set?

Only a couple of billion of them.

"All the world's a Vax" as someone once said.

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html>


----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---

CBFalconer

unread,
Dec 2, 2003, 7:47:47 PM12/2/03
to
The Real OS/2 Guy wrote:
> CBFalconer <cbfal...@yahoo.com> wrote:
>
... snip ...

> > >
> > > > char *p
> > > > unsigned int v;
> > > > int d;
> > > >
> > > > .....
> > > > p = &instring[0];
> > > > v = 0;
> > > > while ((d = unhexify(*p)) >= 0) {
> > > > v = 16 * v + d;
> > > > ++p;
> > > > }
> > > > /* desired result in v */
> > >
> > > Calling a function for each char is another brake. I had not used
> > > pointers because I'm not sure that the OP is ready to understund
> > > pointer arithmetc yet and any good compiler should create even the
> > > same code.
> > >
> > > By that, the separate p++ can be another brake as many real CPU
> > > can do *p++ in an single instruction instead of *p and some times
> > > later p += 1.
> >
> > That combination is a trap. It would allow the pointer to be
> > advanced past the known area of instring, which may or may not be
> > legitimate.
>
> And that is really wrong. As the standard allows to build the address
> of the first member directly behind the array.

Not if one of the objectives is to examine the termination
character. It is an extremely minor point anyhow, and closer to a
style criterion than anything else.

CBFalconer

unread,
Dec 2, 2003, 7:47:49 PM12/2/03
to
Dan Pop wrote:
> CBFalconer <cbfal...@yahoo.com> writes:
>
> > Instead of all the complexity, and assuming that the OP will not
> > use the strto*() family for some reason, the digit conversions
> > can be done by:
> >
> >#include <string.h>
> >
> >/* Convert hex char to value, -1 for non-hex char */
> >int unhexify(char c)
> >{
> > static char *hexchars = "0123456789abcdefABCDEF";

> > char *p;
> > int val;
> >
> > val = -1; /* default assume non-hex */
> > if ((p = strchr(hexchars, c))) {
> > val = p - hexchars;
> > if (val > 15) val = val - 6;
> > }
> > return val;
> >} /* unhexify, untested */
>
> It has the same bug that I deliberately left unfixed in my
> version, posted to the original thread ;-)

What's that? I am offline here, and no such posting remains on my
machine.

AHA - I think I see it. It needs:

if (c && (p = strchr(hexchars, c))) {

The Real OS/2 Guy

unread,
Dec 3, 2003, 3:44:32 AM12/3/03
to
On Wed, 3 Dec 2003 00:47:47 UTC, CBFalconer <cbfal...@yahoo.com>
wrote:


> > > That combination is a trap. It would allow the pointer to be
> > > advanced past the known area of instring, which may or may not be
> > > legitimate.
> >
> > And that is really wrong. As the standard allows to build the address
> > of the first member directly behind the array.
>
> Not if one of the objectives is to examine the termination
> character. It is an extremely minor point anyhow, and closer to a
> style criterion than anything else.

Even then can you build legally the address of the member directly
behind the last one. You may not allowed to dereference it, so it may
useless for other than decrement it.

Dan Pop

unread,
Dec 3, 2003, 6:49:41 AM12/3/03
to
In <tanpsvca5hvreahbq...@4ax.com> Irrwahn Grausewitz <irrw...@freenet.de> writes:

>Dan...@cern.ch (Dan Pop) wrote:
>> In <foepsvos1kifjeqq0...@4ax.com> Irrwahn Grausewitz <irrw...@freenet.de> writes:
>>
>> >3. "01234567890ABCDEF" should be "0123456789ABCDEF"
>>
>> That's called a typo. I had to reread my string several times before
>> seeing it.
>
>That's the most dangerous kind of typos: the ones that aren't caught
>by the compiler and are hard to find, even when you *know* they are
>there (and yes, I know that you already knew that ;).

Not at all: if I actually needed that function for one of my programs,
I would have tested it. All the results produced for the "digits" A to F
being off by one, the origin of the bug is obvious: an extraneous
character between 9 and A in the string literal. No need to actually
reread it, because I know the exact the position of the character that
needs to be deleted.

goose

unread,
Dec 3, 2003, 8:49:58 AM12/3/03
to
Dan...@cern.ch (Dan Pop) wrote in message news:<bqi2vt$hud$2...@sunnews.cern.ch>...

> In <bqg9rg$r1t$1...@news.tudelft.nl> Sidney Cadot <sid...@jigsaw.nl> writes:
>
> >Richard Heathfield wrote:
> >
> >>>If SBUF is guaranteed to be only hex characters,
> >>> if (SBUF > '9') { is sufficient.
> >>
> >>
> >> No, because the C language does not guarantee that 'A' has a coding point
> >> higher than '9'.
> >
> >The OP is of course presuming ascii... c-'0'-7 to get 'A' to 10 is the clue.
>
> The trivial, assumption free approach is to define the hex digits
> yourself:
>
> int hex2dec(char c)
> {
> char *hexdigs = "01234567890ABCDEF";
^

> char *p = strchr(hexdigs, toupper((unsigned char)c));
>
> if (p != NULL)
> return p - hexdigs;
return (int) (p - hexdigs);

> else
> return -1;
> }
>
> Trivia quiz: find the bug in this code.
>

printf (A is %i\n", hex2dec ('A'));

should result in

A is 11

what do i get :-) ?

goose,

Dan Pop

unread,
Dec 3, 2003, 8:13:12 AM12/3/03
to

True, but how does it look like in the basic execution character set?

One of my most important objections to the C standard is that it doesn't
guarantee the semantics of the characters in the basic execution character
set. Therefore, you have no idea how the output of the canonical hello
world program would look on a conforming implementation. One performing
Rot13 to convert from source characters to execution characters would
be perfectly conforming, as far as the standard is concerned.

Dan Pop

unread,
Dec 3, 2003, 9:29:37 AM12/3/03
to

That was the typo in the code, not the bug ;-)

Anupam

unread,
Dec 4, 2003, 3:57:59 AM12/4/03
to
Johan Aurer <au...@axis.com> wrote in message news:<Pine.LNX.4.58.03...@aurer.se.axis.com>...
'0' surely??

Actually it will return the actual represenation + 1 for all the
digits from 'A' to 'F'.
Change to :
char *hexdigs = "0123456789ABCDEF";

Regards,
Anupam

Irrwahn Grausewitz

unread,
Dec 4, 2003, 3:45:40 PM12/4/03
to
anupam_m...@persistent.co.in (Anupam) wrote:
> Johan Aurer <au...@axis.com> wrote in message news:<Pine.LNX.4.58.03...@aurer.se.axis.com>...
> > On Tue, 2 Dec 2003, Dan Pop wrote:
> >
> > > The trivial, assumption free approach is to define the hex digits
> > > yourself:
> > >
> > > int hex2dec(char c)
> > > {
> > > char *hexdigs = "01234567890ABCDEF";
> > > char *p = strchr(hexdigs, toupper((unsigned char)c));
> > >
> > > if (p != NULL)
> > > return p - hexdigs;
> > > else
> > > return -1;
> > > }
> > >
> > > Trivia quiz: find the bug in this code.
> >
> > Which one? The c == 0 bug?
> '0' surely??

No. Hint: what does strchr return if c == 0?



> Actually it will return the actual represenation + 1 for all the
> digits from 'A' to 'F'.
> Change to :
> char *hexdigs = "0123456789ABCDEF";
>

That was the typo, not the bug. ;)

Anupam

unread,
Dec 5, 2003, 3:29:45 AM12/5/03
to
Irrwahn Grausewitz <irrw...@freenet.de> wrote in message news:<834vsv4jef3biv4v5...@4ax.com>...

> anupam_m...@persistent.co.in (Anupam) wrote:
> > Johan Aurer <au...@axis.com> wrote in message news:<Pine.LNX.4.58.03...@aurer.se.axis.com>...
> > > On Tue, 2 Dec 2003, Dan Pop wrote:
> > >
> > > > The trivial, assumption free approach is to define the hex digits
> > > > yourself:
> > > >
> > > > int hex2dec(char c)
> > > > {
> > > > char *hexdigs = "01234567890ABCDEF";
> > > > char *p = strchr(hexdigs, toupper((unsigned char)c));
> > > >
> > > > if (p != NULL)
> > > > return p - hexdigs;
> > > > else
> > > > return -1;
> > > > }
> > > >
> > > > Trivia quiz: find the bug in this code.
> > >
> > > Which one? The c == 0 bug?
> > '0' surely??
>
> No. Hint: what does strchr return if c == 0?
Oh that's quite Ok. I understand that strchr returns a pointer
to the terminating '\0' at the end of the string, so the return will
not be -1 to indicate that its not a hex digit. Rather it will be
16.
But I thought that the double '0' inside the string was a more evident
bug. Should have guessed at it not being quite so simple :).

Anupam

unread,
Dec 5, 2003, 3:31:54 AM12/5/03
to
Irrwahn Grausewitz <irrw...@freenet.de> wrote in message news:<834vsv4jef3biv4v5...@4ax.com>...
> anupam_m...@persistent.co.in (Anupam) wrote:
> > Johan Aurer <au...@axis.com> wrote in message news:<Pine.LNX.4.58.03...@aurer.se.axis.com>...
> > > On Tue, 2 Dec 2003, Dan Pop wrote:
> > >
> > > > The trivial, assumption free approach is to define the hex digits
> > > > yourself:
> > > >
> > > > int hex2dec(char c)
> > > > {
> > > > char *hexdigs = "01234567890ABCDEF";
> > > > char *p = strchr(hexdigs, toupper((unsigned char)c));
> > > >
> > > > if (p != NULL)
> > > > return p - hexdigs;
> > > > else
> > > > return -1;
> > > > }
> > > >
> > > > Trivia quiz: find the bug in this code.
> > >
> > > Which one? The c == 0 bug?
> > '0' surely??
>
> No. Hint: what does strchr return if c == 0?
>
> > Actually it will return the actual represenation + 1 for all the
> > digits from 'A' to 'F'.
> > Change to :
> > char *hexdigs = "0123456789ABCDEF";
> >
>
> That was the typo, not the bug. ;)
Beg your pardon. You had already posted the answer. I was too fast at
the typing trigger.
>
> Regards

Anupam

unread,
Dec 5, 2003, 3:33:44 AM12/5/03
to
ru...@webmail.co.za (goose) wrote in message news:<ff82ae1b.0312...@posting.google.com>...
^
printf ("A is %i\n", hex2dec ('A'));

Comprendo ;)

goose

unread,
Dec 10, 2003, 12:18:31 AM12/10/03
to
anupam_m...@persistent.co.in (Anupam) wrote in message news:<aa67fba3.0312...@posting.google.com>...

> ru...@webmail.co.za (goose) wrote in message news:<ff82ae1b.0312...@posting.google.com>...
> > Dan...@cern.ch (Dan Pop) wrote in message news:<bqi2vt$hud$2...@sunnews.cern.ch>...
> > > In <bqg9rg$r1t$1...@news.tudelft.nl> Sidney Cadot <sid...@jigsaw.nl> writes:
> > >
> > > >Richard Heathfield wrote:
> > > >
> > > >>>If SBUF is guaranteed to be only hex characters,
> > > >>> if (SBUF > '9') { is sufficient.
> > > >>
> > > >>
> > > >> No, because the C language does not guarantee that 'A' has a coding point
> > > >> higher than '9'.
> > > >
> > > >The OP is of course presuming ascii... c-'0'-7 to get 'A' to 10 is the clue.
> > >
> > > The trivial, assumption free approach is to define the hex digits
> > > yourself:
> > >
> > > int hex2dec(char c)
> > > {
> > > char *hexdigs = "01234567890ABCDEF";
> ^
> > > char *p = strchr(hexdigs, toupper((unsigned char)c));
> > >
> > > if (p != NULL)
> > > return p - hexdigs;
> return (int) (p - hexdigs);
> > > else
> > > return -1;
> > > }
> > >
> > > Trivia quiz: find the bug in this code.
> > >
> >
> > printf (A is %i\n", hex2dec ('A'));
> ^

ooohh ... the *irony* of me pointing out a typo :-)

> printf ("A is %i\n", hex2dec ('A'));
>
> Comprendo ;)

yup. good catch (most others missed it:-)

goose,
i cnt spll wrth a dam!!!

0 new messages