Search code examples
ckernighan-and-ritchie

Conversion of hexadecimal string constant to decimal value using C


The following program gives the result as 0 instead of the expected decimal equivalent of the hexadecimal string constant.

#include <stdio.h>

int my_htoi(char[]);

int main(void) {
    printf("%d", my_htoi("0xABC"));
    return 0;
}

int my_htoi(char str[]) {
    int i, num = 0;
    for (i = 0; i != '\0'; ++i) {
        if (str[i+1] == 'x' || str[i+1] == 'X') {
            i = i + 1;
            continue;
        }
        if (str[i] >= '0' && str[i] <= '9') {
            num = num * 16 + (str[i] - '0');
        } else if (str[i] >= 'a' && str[i] <= 'f') {
            num = num * 16 + (str[i] - 'a' + 10);
        } else if (str[i] >= 'A' && str[i] <= 'F') {
            num = num * 16 + (str[i] - 'A' + 10);
        }
    }
    return num;
}

While the following program runs fine and outputs the correct decimal equivalent of the hexadecimal string constant.

#include <stdio.h>
#include <string.h>

int my_htoi(char[]);

int main(void) {
    printf("%d", my_htoi("0xABC"));
    return 0;
}

int my_htoi(char str[]) {
    int i, num = 0;
    for (i = 0; i < strlen(str); ++i) {
        if (str[i+1] == 'x' || str[i+1] == 'X') {
            i = i + 1;
            continue;
        }
        if (str[i] >= '0' && str[i] <= '9') {
            num = num * 16 + (str[i] - '0');
        } else if (str[i] >= 'a' && str[i] <= 'f') {
            num = num * 16 + (str[i] - 'a' + 10);
        } else if (str[i] >= 'A' && str[i] <= 'F') {
            num = num * 16 + (str[i] - 'A' + 10);
        }
    }
    return num;
}

The only difference is in the way we find the qualifying condition for the loop. Why does it not work with the null byte checking?


Solution

  • There are some problems in your code:

    • the loop index i is compared to '\0' instead of str[i], causing immediate termination of the loop with a return value of 0.

    • the test for x is incorrect: it would cause "1x2" to convert to 2 instead of 1.

    • you accept letters beyond f and convert them to digits. The function should instead stop parsing at the first character that is not a hex digit.

    Here is a corrected version:

    #include <stdio.h>
    
    int my_htoi(const char[]);
    
    int main(void) {
        printf("%d", my_htoi("0xABC"));
        return 0;
    }
    
    int my_htoi(const char str[]) {
        int i = 0, num = 0;
        if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
            i += 2;
        for (; str[i] != '\0'; ++i) {
            if (str[i] >= '0' && str[i] <= '9') {
                num = num * 16 + (str[i] - '0');
            } else if (str[i] >= 'a' && str[i] <= 'f') {
                num = num * 16 + (str[i] - 'a' + 10);
            } else if (str[i] >= 'A' && str[i] <= 'F') {
                num = num * 16 + (str[i] - 'A' + 10);
            } else {
                break;
            }
        }
        return num;
    }