Преобразование шестнадцатеричной строковой константы в десятичное значение с использованием C

Следующая программа возвращает результат в виде 0 вместо ожидаемого десятичного эквивалента шестнадцатеричной строковой константы.

#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;
}

В то время как следующая программа работает нормально и выводит правильный десятичный эквивалент шестнадцатеричной строковой константы.

#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;
}

Единственная разница заключается в том, как мы находим квалификационное условие для цикла. Почему не работает проверка нулевого байта?


person Rai    schedule 07.03.2019    source источник
comment
Вы сравниваете индекс i с нулем, что не имеет смысла. Вместо этого вы должны сравнить str[i] с ним.   -  person Eugene Sh.    schedule 07.03.2019
comment
Еще одно замечание: i=i+1, если встречающийся char равен 'x' или 'X', является ошибкой. Когда выполняется continue, for выполняет приращение переменной i, тогда ваш код, когда встречается "x", пропускает первый символ после "x".   -  person Sir Jo Black    schedule 07.03.2019


Ответы (2)


В вашем коде есть некоторые проблемы:

  • индекс цикла i сравнивается с '\0' вместо str[i], что приводит к немедленному завершению цикла с возвращаемым значением 0.

  • тест для x неверен: это приведет к преобразованию "1x2" в 2 вместо 1.

  • вы принимаете буквы после f и конвертируете их в цифры. Вместо этого функция должна прекратить синтаксический анализ на первом символе, который не является шестнадцатеричной цифрой.

Вот исправленная версия:

#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;
}
person chqrlie    schedule 07.03.2019

Неверный код: i != '\0' проверяет, равен ли индекс 0.

for(i = 0; i != '\0'; ++i) {

Должно быть ниже, чтобы проверить, является ли элемент str[i] нулевым символом.

for(i = 0; str[i] != '\0'; ++i) {

Другие проблемы существуют ненужное приращение, int переполнение (здесь лучше использовать unsigned), неправильное обнаружение x - рассмотрим "0x0x0x1", ведущий - или +, char str[] --> const char str[], ...

person Community    schedule 07.03.2019