Как вручную преобразовать десятичное значение в шестнадцатеричную строку в C? - PullRequest
7 голосов
/ 08 марта 2011

nb Я знаю, что этот вопрос задавался ранее в StackOverflow различными способами и обстоятельствами, но поиск ответа, который я ищу, не совсем помогает моему конкретному случаю.Поэтому, хотя изначально это выглядит как копия вопроса, такого как Как я могу преобразовать целое число в шестнадцатеричную строку в C? данные ответы точны, но бесполезны для меня.

Мой вопрос заключается в том, как преобразовать десятичное целое число в шестнадцатеричную строку вручную.Я знаю, что есть некоторые хитрости с stdlib.h и printf, но это задача колледжа, и мне нужно сделать это вручную (приказ профессора).Однако нам разрешено обращаться за помощью.

Использование старого доброго "деления на 16 и преобразования остатка в шестнадцатеричное и обратного значения" метод получения шестнадцатеричной строки, но здесь необходимобыть большой ошибкой в ​​моем коде, так как он не возвращает меня, например, "BC" для десятичного значения "188".

Предполагается, что алгоритму НИКОГДА не потребуется находить шестнадцатеричные значения для десятичных чисел большего размера.чем 256 (или FF).Хотя передача параметров может быть неоптимальной или нежелательной, это то, что нам сказали использовать (хотя мне разрешено изменять функцию getHexValue, поскольку я сам ее написал).

Это то, что ядо сих пор:

/* Function to get the hex character for a decimal (value) between
 * 0 and 16.  Invalid values are returned as -1.
 */
char getHexValue(int value) 
{
   if (value < 0) return -1;
   if (value > 16) return -1;
   if (value <= 9) return (char)value;
   value -= 10;
   return (char)('A' + value);
}


/* Function asciiToHexadecimal() converts a given character (inputChar) to
 * its hexadecimal (base 16) equivalent, stored as a string of
 * hexadecimal digits in hexString. This function will be used in menu
 * option 1.
 */
void asciiToHexadecimal(char inputChar, char *hexString)
{
   int i = 0;
   int remainders[2];
   int result = (int)inputChar;
   while (result) {
      remainders[i++] = result % 16;
      result /= (int)16;
   }
   int j = 0;
   for (i = 2; i >= 0; --i) {
      char c = getHexValue(remainders[i]);
      *(hexString + (j++)) = c;
   }
}

char *hexString - это указатель на строку символов, которую мне нужно вывести на экран (в конце концов).Параметр char inputChar, который мне нужно преобразовать в шестнадцатеричный формат (поэтому мне никогда не нужно преобразовывать значения свыше 256).

Если есть лучший способ сделать это, в котором все еще используется функция void asciiToHexadecimal(char inputChar, char *hexString)Я все уши, кроме этого, моя отладка, кажется, указывает, что значения в порядке, но вывод получается как \377 вместо ожидаемого шестнадцатеричного буквенно-цифрового представления.

Извините, если есть какая-либо терминология илидругие проблемы с самим вопросом (или с кодом), я все еще очень плохо знаком с миром C.

Обновление: Мне только что пришло в голову, что это может иметь отношение к записиспособ, которым я показываю значение в случае, если это печать, а не преобразование, которое является ошибочным.Вот оно:

char* binaryString = (char*) malloc(8);
char* hexString = (char*) malloc(2);
asciiToBinary(*(asciiString + i), binaryString);
asciiToHexadecimal(*(asciiString + i), hexString);
printf("%6c%13s%9s\n", *(asciiString + i), binaryString, hexString);

(все в этом коде работает, кроме hexString)

Ответы [ 6 ]

2 голосов
/ 08 марта 2011
char getHexValue(int value)
{
   if (value < 0) return -1;
   if (value > 16) return -1;
   if (value <= 9) return (char)value;
   value -= 10;
   return (char)('A' + value);
}

Возможно, вы захотите распечатать символы, полученные при вызове этой подпрограммы, для каждого интересующего вас значения. :) (printf(3) format %c.)

Когда вы звоните getHexValue() с номером от 0 до 9, вы возвращаете номер от 0 до 9 в диапазоне управляющих символов ASCII .Когда вы звоните getHexValue() с номером от 10 до 15, вы возвращаете номер от 65 до 75 в диапазоне букв ASCII.

Проповедь? Модульное тестирование может сэкономить вам часов времени, если вы будете писать тесты примерно в то же время, когда пишете код.

Некоторые люди сначала любят писать тесты.Хотя у меня никогда не было дисциплины, чтобы долго придерживаться этого подхода, знание того, что у вас есть для написания тестов, заставит вас писать код, который на проще для тестирования.А код, который легче тестировать, это менее связанный (или «более разъединенный»), что обычно приводит к меньшему количеству ошибок!

Пишите тесты рано и часто.:)

Обновление : После того, как вы включили свой выходной код, мне тоже пришлось это прокомментировать:)

char* binaryString = (char*) malloc(8);
char* hexString = (char*) malloc(2);
asciiToBinary(*(asciiString + i), binaryString);
asciiToHexadecimal(*(asciiString + i), hexString);
printf("%6c%13s%9s\n", *(asciiString + i), binaryString, hexString);

hexStringвыделен один байт слишком мал, чтобы быть C-строкой - вы забыли оставить место для символа ASCII NUL '\0'.Если вы печатаете hexString с помощью спецификатора формата %c или строите строку большего размера с помощью memcpy(3), это может быть хорошо, но ваш вызов printf() обрабатывает hexString как строку.

В общем, когда вы видите

char *foo = malloc(N);

, бойтесь - идиома C

char *foo = malloc(N+1);

То, что +1 - это ваш сигнал другим (и вам самим,через два месяца) что вы оставили место для NUL.Если вы скрываете это +1 в другом вычислении, вы упускаете возможность запомнить шаблон, который может поймать эти ошибки каждый раз, когда вы читаете код.(Честно говоря, я нашел один из них по этой точной схеме на SO всего два дня назад.:)

1 голос
/ 03 мая 2014

Я сделал библиотеку, чтобы сделать шестнадцатеричное / десятичное преобразование без использования stdio.h.Очень прост в использовании:

char* dechex (int dec);

. Он будет использовать calloc() для возврата указателя на шестнадцатеричную строку, таким образом, количество используемой памяти оптимизируется, поэтому не забудьте использовать free()

Вот ссылка на github: https://github.com/kevmuret/libhex/

1 голос
/ 08 марта 2011

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

0 голосов
/ 12 марта 2015

В дополнение к другим хорошим ответам ....

Если числа, представленные этими шестнадцатеричными или десятичными символьными строками, огромны (например, сотни цифр), они не поместятся в long long (или в любой самый большой целочисленный тип, предоставляемый вашей реализацией C). Тогда вам понадобится Бигнум . Я бы предложил не кодировать вашу собственную реализацию (сложно сделать эффективную), а использовать существующую, такую ​​как GMPlib

0 голосов
/ 12 марта 2015
#include<stdio.h>

char* inttohex(int);
main()
{
    int i;
    char *c;
    printf("Enter the no.\n");
    scanf("%d",&i);
    c=inttohex(i);
    printf("c=%s",c);
}

char* inttohex(int i)
{
    int l1,l2,j=0,n;
    static char a[100],t;

    while(i!=0)
    {
    l1=i%16;
    if(l1>10)
    {
        a[j]=l1-10+'A';
    }

    else
        sprintf(a+j,"%d",l1);

    i=i/16;
    j++;
    }
    n=strlen(a);
    for(i=0;i<n/2;i++)
    {
        t=a[i];
        a[i]=a[n-i-1];
        a[n-i-1]=t;
    }

    //printf("string:%s",a);
    return a;
    //
}
0 голосов
/ 08 марта 2011

Вы очень близки - внесите следующие два небольших изменения, и он будет работать достаточно хорошо, чтобы вы могли его завершить:

(1) изменение:

if (value <= 9) return (char)value;

на:

if (value <= 9) return '0' + value;

(вам нужно преобразовать значение 0,9 в символ, а не просто наложить его).

(2) изменить:

void asciiToHexadecimal(char inputChar, char *hexString)

до:

void asciiToHexadecimal(unsigned char inputChar, char *hexString)

(inputChar обрабатывался как подписанный, что давало нежелательные результаты с %).

Пара советов:

  • возвращают getHexValue '?' вместо -1 для неверного ввода (облегчить отладку)

  • написать тестовый жгут для отладки, например

    int main(void)
    {
        char hexString[256];
    
        asciiToHexadecimal(166, hexString);
    
        printf("hexString = %s = %#x %#x %#x ...\n", hexString, hexString[0], hexString[1], hexString[2]);
    
        return 0;
    }
    
...