2009-09-08 12 views
1

Мне дана строка hex_txt, содержащая четырехзначный шестнадцатеричный номер, описанный в коде, разделенный двумя записями. Мне нужно преобразовать его в десятичный. Следующее - это то, как я это делаю.Преобразование шестнадцатеричной строки, хранящейся в виде символов в десятичный код в C

unsigned char hex_txt[] = "\xAB\xCD"; 
unsigned char hex_num[5]; 
unsigned int dec_num; 

sprintf(hex_num, "%.2x%.2x", (int)hex_txt[0], (int)hex_txt[1]); 
printf("%s\n", hex_num); 
sscanf(hex_num, "%x", &dec_num); 
printf("%d\n", dec_num); 

Есть ли более быстрый или более эффективный способ сделать это? Это мое текущее решение ad hoc, но я хотел бы знать, есть ли подходящий способ сделать это.

ответ

5
int result = (unsigned char)hex_txt[0] * 256 + (unsigned char)hex_txt[1]; 

Строка hex_txt содержит два байта; Я предполагаю, что порядок имеет большой энтиан (обратный индекс, если он малозначен). Символьный код для hex_txt[0] - 0xAB, для hex_txt[1] - 0xCD. Использование unsigned char cast гарантирует, что вы не будете перепутаны подписанными символами.

Или, чтобы сделать все это сразу:

printf("%d\n", (unsigned char)hex_txt[0] * 256 + (unsigned char)hex_txt[1]); 
+0

Точно, что я искал, спасибо. – v64

+0

Как вы можете быть уверены (без знака) hex_txt [0] * 256 не равен нулю? –

+0

@Mike: hex_txt [0] - 0xAB или 171; 171 * 256 = 43776. Если «int» было 16-разрядной величиной, это было бы отрицательным отличным от нуля результатом (или, возможно, сигналом переполнения, но я не слышал о машине, которая генерирует сигнал переполнения для подписанного арифметического переполнения); если это 16-разрядное количество без знака, это все равно будет отличным от нуля. Я не вижу, чтобы умножение давало нуль. И, кроме того, мой ответ не зависел от умножения, дающего ненулевой результат - оставив меня озадаченным тем, откуда возник ваш вопрос. –

0

Вот что я делаю:

n = 0; 
while (*p){ 
    if (ISDIGIT(*p)) n = n*16 + (*p++ - '0'); 
    else if (ISALPHA(*p)) n = n*16 + (LOWERCASE(*p++) - 'a' + 10); 
    else break; 
} 

И (вы будете ненавидеть это, но это работает для ASCII) я обманываю:

#define LOWERCASE(c) ((c) | ' ') 

ДОБАВЛЕНО: К сожалению, я только что перечитал ваш вопрос , Почему бы не сделать:

(unsigned int)(unsigned char)p[0] * 256 + (unsigned int)(unsigned char)p[1] 
+0

Использование 'IsAlpha' (почему не "ISALPHA?) Оставляет вас уязвимыми для преобразования 'г'. Проверка не является достаточно строгой. Если бы я был вами, я бы удалил первую часть вашего ответа и оставил только вторую. Кроме того, «unsigned int» не нужны, хотя они не навредят. –

+0

@Jonathan: Если вы умножаете символ unsigned на 256, разве вы ничего не получаете? И если вы передали подписанный символ в unsigned int, я хотел быть уверенным, что он случайно не будет распространять бит знака. –

+0

Mike: Промежуточные результаты в C всегда являются по крайней мере 'int' - если вы вычисляете все операнды' unsigned char', они продвигаются либо в 'int', либо' unsigned int', в зависимости от относительного размера 'int' и 'char'. Если вы вернете результат в 'unsigned char', *, то есть *, когда результат уменьшается по модулю' UCHAR_MAX', но в этом случае результат сохраняется в 'int', так что все хорошо. – caf

0

я мог бы лепетать, но если вы используете:

char hex_txt[] = "\xAB\xCD"; 

то в действительности вы просто определить 2 байта:

char hex_txt[] = {0xab, 0xcd}; 

поэтому, чтобы преобразовать это в int, вы можете сделать это:

int number = (int) ((short *) *hex_text); 
+0

Отбросьте * от перед 'hex_text' и второй e внутри него. Тогда вы просто остаетесь с неопределенным результатом; вы получаете один ответ на машине большого конца и еще один ответ на маленькой машине. Вы также уязвимы для ошибки SIGBUS, если компилятор достаточно жесток, чтобы поместить hex_txt на границу нечетного байта, а объекты вашего процессора - на чтение коротких целых чисел из нечетных адресов. О, и первая декларация определяет массив длины 3, а не 2. –

+0

Вы можете столкнуться с 1) проблемами с endian и 2) вопросами выравнивания, нет? –

+0

К сожалению, при просмотре таких деталей, как эти ведущие компиляторы, объекты во время компиляции, а также программы для сбоя или получения ошибочных результатов во время выполнения. Ни один из них не является хорошим результатом. –

0

Возможно, вам это не понадобится, хотя есть код C++, который я опубликовал here.

1

Просто используйте strtoul() функция от stdlib.h.
Смотрите следующий пример:

const char sHex[] = "AE"; 

unsigned char ucByte = 0; 

ucByte = (unsigned char) strtoul(sHex, NULL, 16); //BASE 16 FOR HEX VALUES 

 Смежные вопросы

  • Нет связанных вопросов^_^