0

Here's my issue:

I have written a function to detect if a string is hex based off of the "0x####" format:

int lc3_hashex(char *str)
{
    int val = 0;      
    char *to;
    to = strndup(str+2, 10);
    val = sscanf(to, "%x", &val); 
    if (val)
    {
        return val;
    }

    return 0;
}

Assuming the parameter is of the form "0x####", it returns the decimal version of the post "0x" numbers. But is there any built in way (or a way I am just overseeing) to get the integer value of the hexidecimal number "0x4000" as opposed to the integer value of "4000"?

Thanks.

Mat
  • 202,337
  • 40
  • 393
  • 406
Phil
  • 297
  • 2
  • 5
  • 10
  • The string returned by `strndup` must be `free`d once you're done using it. – Praetorian Jul 29 '11 at 05:49
  • ... I think @jonsca answeres the question -- but on a side note, make sure you free the memory you allocate (C is not like Java) -- i.e. strdup mallocs memory, you need to free it rather than leak it. – Soren Jul 29 '11 at 05:49
  • There is a similar discussion if C++ is a possibility http://stackoverflow.com/questions/194465/how-to-parse-a-string-to-an-int-in-c For 'C' Mat's answer is good. – Rajesh Gautam PhD Jul 29 '11 at 06:15

3 Answers3

6

You can reduce that function to:

int cnt = sscanf(str, "%x", &val);
if (cnt == 1) {
  // read a valid `0xNNNN` string
}

scanf with the %x format already does the hex conversion, and deals with the 0x prefix just fine. Also, it's return value is the number of items matched, so you can use that to determine if it did find a hex value in str or not.

With this you have both pieces of information you need: whether or not the string was formatted as you expected it, and what value it was (properly converted). It also avoids a string allocation (which you're not freeing), and the bug your code has if strlen(str) is less than two.

If you change your function signature to:

int check_and_get_hex(const char *str, int *val);

(or something like that), update the sscanf call accordingly (passing val rather than &val), and return (cnt == 1), you can get both the "it's a valid hex string" and the value to the caller in a single shot.

Mat
  • 202,337
  • 40
  • 393
  • 406
2

Use strtol from stdlib.h and specify the base as 16.

The only downside is that this function returns 0 upon failure, so you'll want to check to make sure the input to it is not 0.

jonsca
  • 10,218
  • 26
  • 54
  • 62
1

I fail to understand why the string is being cut short before doing sscanf. If you want the string in hex value to be converted to the decimal integer, you can give it directly.

#include<stdio.h>
int main()
{
  char sHex[7] = "0x2002";
  int nVal = 0;
  sscanf( sHex, "%x", &nVal );
  printf( "%d", nVal );
  return 0;
}

This will print 8194, the decimal value for 0x2002. By giving "%x" to sscanf, you are specifying the input string as hexadecimal. so, the preceding "0x" is fine.

Ragesh Chakkadath
  • 1,521
  • 1
  • 14
  • 32