halexh halexh - 2 months ago 4x
C Question

Unsuccessfully using sscanf to read in hexadecimal value

Here is a much more short version of my code:

char token[256];
unsigned int maskval = 0;

//Token gets read in here.

printf("token: %s\n", token);

if (sscanf(token + 2, "%x", &maskval) == 1) {
//do stuff
} else {
printf("error: %d, %x\n", maskval, maskval);

As you can see I am passing hexadecimal strings to the function, reading them into token and using sscanf() to convert the string version of the hexadecimal value into a unsigned int. The string token always begins with "0x", "0X", "Ox", or "OX". The reason for this is because the user will be unable to tell the difference between a 0 or a O when inputting the value (vi displays them the same, graphical). The result I get if I pass it "0x00EE" is:

token: 0x00EE
error: 0

The problem I believe is whether I pass it something along the lines of "0x00EE" or "OxOOEE" (zero's vs capital o's). Both look identical in vi, and I am not sure if they are handled differently in this scenario. Hopefully I am just doing something really simple and stupid that I overlooked though (that's usually the case). Also, I have tried using

maskval = strtol(token, NULL, 16);

instead of sscanf() but I get the exact same results.

Any ideas?


Here's one mistake:

char *token[256];

This is a an array of 256 pointers to character (char *), not an array of characters.

You meant:

char token[256];

There should be plenty of compiler warnings from this.

Trying to parse a hexadecimal value from a string beginning something that is not a valid hexadecimal digit will of course fail, for both sscanf() and strtoul(). You almost sound as if you think the standard functions should consider 'O' to be hex just because it looks like the digit 0 for you. That is ... not how they've been designed, which I think is fortunate. :) You might want to look into changing your fonts.

You could manually strip the non-conforming prefix. Assuming you always have the 2-character prefix, and then might have one, you could do:

const char *number = token + 2;

/* Now number will point at the first hexadecimal
   digit in token, or '\0' if none were found.
if(sscanf(number, "%x", &maskval) == 1)
  printf("success, got %x\n", maskval);
  printf("failed to parse '%s' as hexadecimal number\n", number);