Упражнение K & R 2-3: «Преобразователь шестнадцатеричного кода в int» - PullRequest
3 голосов
/ 30 апреля 2009

Программа, которую я написал, работает в демографии, состоящей только из одного шестнадцатеричного значения. (Возможно, это не самое элегантное решение, но я новый программист). Мой вопрос: как мне поступить с обработкой нескольких шестнадцатеричных цифр, таких как 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 ]

1 голос
/ 30 апреля 2009

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

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 во многих контекстах, где макрос не удобен, поэтому лучше просто привыкнуть к нему сейчас ...
1 голос
/ 30 апреля 2009

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

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

Edit:

в

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

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

0 голосов
/ 27 июля 2015

Вот моя версия классической функции 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';
}
0 голосов
/ 17 августа 2013

Я думаю, что МАКСИМАЛЬНЫЙ размер строки должен быть либо 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, чтобы найти их.

...