Justin Hu
Justin Hu

Reputation: 107

Converting hexadecimal to decimal error in C

int htoi(char s[]) {
  int c;
  int sum = 0;
  int counter = 0;
  for (int i = sizeof(s)/sizeof(s[0]) - 2; (c = tolower(s[i])) >= 'a' && (c = tolower(s[i]) <= 'f'); i--) {
    int temp = (int) pow(16, counter) * (c - 87);
    sum += temp;
    counter++;
  }
  return sum;
}

I am calling the method with:

int main()
{
  char s[] = "FFF";
  printf("%d\n", htoi(s));
}

I'm just starting to learn C. I'm trying to create a method that converts hexadecimal to decimal, but the following code doesn't work. It's outputting -87 on my terminal, and I'm not sure why.

EDIT: Just realized my code doesn't take into account actual digits, but either way it doesn't work when I input "FFF" as the input array.

Upvotes: 2

Views: 102

Answers (1)

chux
chux

Reputation: 153358

Code has troubles:

It incorrectly uses sizeof(s) to find the size of "array" char s[], but s is a pointer. The calling code's s is an array, yet it converts to the address of the first element (a pointer) when used as a function argument. In particular char s[] is a pointer when used as a function parameter.

It assigns c to the result of the compare c = tolower(s[i]) <= 'f' rather than the lowercase value. @MikeCAT

It does not handle '0' - '9'.

Instead, simple walk the string pointed to by s, first (most significant digit) to last (least).

int htoi(const char *s) {
  int sum = 0;
  while (isxdigit((unsigned char) *s)) {
    int digit_value;
    int char_value = (unsigned char) *s++;  // Get unsigned value and advance s
    if (isdigit(char_value)) {
      digit_value = *s - '0'; 
    } else {
      digit_value = tolower(char_value) - 'a' + 10; 
    }
    sum = sum * 16 + digit_value;
  }
  return sum;
}

Rarely does code need a signed hexadecimal value. Consider returning an unsigned type.

unsigned htou(const char *s) { 
  unsigned  sum = 0;
  ...

Upvotes: 2

Related Questions