K&R Exercise 2-3 "Hex to int converter" Problem

Программа, которую я написал, работает в демографии, состоящей только из одного шестнадцатеричного значения. (Возможно, это не самое элегантное решение, но я новый программист). Мой вопрос: как мне поступить с обработкой нескольких шестнадцатеричных цифр, таких как 0xAF или 0xFF, и т. Д.? Я не совсем уверен, и я, похоже, сильно запутался в этой попытке. Я не прошу, чтобы кто-то держал меня за руку, но чтобы дать мне подсказку, где я ошибся в этом коде, и размышления о том, как это исправить.

Спасибо:)

/* Exercise 2-3.  Write the function htoi(s), which converts a string of
 * hexadecimal digits (including an optional 0x or 0X) into it's equivalent
 * integer value. The allowable digits are 0...9 - A...F and a...f.
 * 
 */

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

#define NL '\n'
#define MAX 24

int htoi(char *hexd);

int
main(void)
{
    char str[MAX] = {0};
    char hex[] = "0123456789ABCDEFabcdef\0";
    int c;
    int i;
    int x = 0;

    while((c = getchar()) != EOF) {
        for(i = 0; hex[i] != '\0'; i++) {
            if(c == hex[i])
                str[x++] = c;
        }
        if(c == NL) {
            printf("%d\n", htoi(str));
            x = 0, i = x;
        }
    }
    return 0;
}

int
htoi(char *hexd) 
{
    int i;
    int n = 0;

    for(i = 0; isdigit(hexd[i]); i++)
        n = (16 * i) + (hexd[i] - '0');
    for(i = 0; isupper(hexd[i]); i++) /* Let's just deal with lowercase characters */
        hexd[i] = hexd[i] + 'a' - 'A';
    for(i = 0; islower(hexd[i]); i++) {
        hexd[i] = hexd[i] - 'a';
        n = (16 + i) + hexd[i] + 10;
        n = hexd[i] + 10;
    }
    return n;
}

4 ответа

Кто-то уже спрашивал об этом (hex to int, k&r 2.3). Посмотрите, есть много хороших ответов, но вы должны заполнить пробелы.

Преобразование шестнадцатеричного в десятичное [упражнение K&R]

Редактировать:

в

char hex[] = "0123456789ABCDEFabcdef\0";

\0 не является необходимым. шестнадцатеричное окончено. Длина len (0...f) + 1 = 17 байт.

Я выберу один цикл и предоставлю вам переосмысление вашей реализации. Конкретно это:

for(i = 0; isdigit(hexd[i]); i++)
    n = (16 * i) + (hexd[i] - '0');

не делает то, что вы, вероятно, думаете, что делает...

  • Он обрабатывает только первый диапазон символов, где isdigit() правда.
  • Останавливается на первом символе, где isdigit() ЛОЖЬ.
  • Это не проходит мимо конца, потому что isdigit('\0') как известно, ЛОЖЬ. Я обеспокоен тем, что это может быть случайно правильно, хотя.
  • Он правильно конвертирует шестнадцатеричное число, которое может быть выражено исключительно цифрами 0-9.

Что нужно продумать для всей программы:

  • Как правило, предпочитайте не изменять входные строки, если изменение не является ценным побочным эффектом. В вашем примере кода вы заставляете строку вводиться в нижнем регистре. Изменение входной строки на месте означает, что пользователь пишет htoi("1234") вызывает неопределенное поведение. Вы действительно не хотите этого делать.
  • Только один из циклов над цифрами будет обрабатывать ненулевое число цифр.
  • Что произойдет, если я отправлю 0123456789ABCDEF0123456789ABCDEF в stdin?
  • Что вы ожидаете получить за 80000000? Что ты получил? Вы удивлены?
  • Лично я бы не использовал NL за '\n', Использование C в значительной степени ожидает увидеть \n во многих случаях, когда макрос не удобен, лучше просто привыкнуть к нему сейчас...

Я думаю, что максимальный размер строки должен быть 10 или 18 вместо 24 (если вы уже проверили int на вашем компьютере и следуя приведенным ниже рассуждениям, было бы полезно включить его в качестве комментария в ваш код.)

10: с htoi() возвращает int, int обычно составляет 4 байта (проверьте и вашу систему), поэтому шестнадцатеричное число может быть длиной не более 8 цифр (от 4 бит до 1 шестнадцатеричной цифры, 8 бит до байта), и мы хотим разрешить дополнительный 0x или же 0X,

18: было бы лучше, если htoi() вернул long и его 8 байтов (опять же, проверьте вашу систему), так что шестнадцатеричное число может быть длиной не более 16 цифр, и мы хотим, чтобы для дополнительного 0x или же 0X,

Обратите внимание, что эти размеры int а также long зависят от машины, и, пожалуйста, посмотрите упражнение 2.1 в книге K&R, чтобы найти их.

Вот моя версия классической функции htoi() для преобразования нескольких шестнадцатеричных значений в десятичные целые числа. Это полноценная рабочая программа, скомпилируйте ее и запустите.

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

int htoi(const char*);
int getRawInt(char);

int main(int argc, char **argv) {
    char hex[] = "       ";
    printf("Enter a hexadecimal number (i.e 33A)\n");
    scanf("%s", hex);

    printf("Hexedecimal %s in decimal is %d\n", hex, htoi(hex)); // result will be 826
    return 0;
}

int htoi(const char *hex) {
    const int LEN = strlen(hex) -1;
    int power = 1;
    int dec = 0;

    for(int i = LEN; i >= 0; --i) {
        dec += getRawInt(hex[i]) * power;
        power *= 16;
    }

    return dec;
}

int getRawInt(char c) {
    if(isalpha(c)) {
        return toupper(c) - 'A' + 10;
    } return c-'0';
}
Другие вопросы по тегам