Какой способ преобразования строки шестнадцатеричных цифр в двоичные unsigned int
или unsigned long
является наиболее эффективным в языке C?
Например, если у меня есть 0xFFFFFFFE
, я хочу получить int
со значением base10 4294967294
.
Отредактируйте: Теперь совместимый с MSVC, C ++ и компиляторы негну (см. конец).
Вопросом был " самый эффективный путь " OP doesn' t определяют платформу, он мог собирать для базирующегося чипа ATMEL RISC с 256 байтами флеш-памяти для его кодекса.
Для отчета, и для тех (как я), кто ценит различие между " самый легкий way" и " самый эффективный way" и кто любит учиться...
static const long hextable[] = {
[0 ... 255] = -1, // bit aligned access into this table is considerably
['0'] = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // faster for most modern processors,
['A'] = 10, 11, 12, 13, 14, 15, // for the space conscious, reduce to
['a'] = 10, 11, 12, 13, 14, 15 // signed char.
};
/**
* @brief convert a hexidecimal string to a signed long
* will not produce or process negative numbers except
* to signal error.
*
* @param hex without decoration, case insensitive.
*
* @return -1 on error, or result (max (sizeof(long)*8)-1 bits)
*/
long hexdec(unsigned const char *hex) {
long ret = 0;
while (*hex && ret >= 0) {
ret = (ret << 4) | hextable[*hex++];
}
return ret;
}
Это не требует никаких внешних библиотек, и это должно быть ослепляюще быстро. Это обращается с прописными буквами, строчными буквами, недействительными знаками, шестнадцатеричный вход странного размера (например: 0xfff), и максимальный размер ограничен только компилятором.
Для non-GCC или C ++ компиляторы или компиляторы, которые не примут необычную hextable декларацию.
Замените первое заявление этим (дольше, но больше приспосабливания) версия:
static const long hextable[] = {
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1, 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
};
Попробуйте это:
#include <stdio.h>
int main()
{
char s[] = "fffffffe";
int x;
sscanf(s, "%x", &x);
printf("%u\n", x);
}
Если Вы don' у t есть stdlib тогда, Вы должны сделать это вручную.
unsigned long hex2int(char *a, unsigned int len)
{
int i;
unsigned long val = 0;
for(i=0;i<len;i++)
if(a[i] <= 57)
val += (a[i]-48)*(1<<(4*(len-1-i)));
else
val += (a[i]-55)*(1<<(4*(len-1-i)));
return val;
}
Примечание: Этот кодекс принимает заглавный A-F. Это не работает, если len - вне Вашего самого длинного целого числа 32 или 64 бита, и нет никакой ошибки при заманивании в ловушку для незаконных шестнадцатеричных знаков.
Для Микродиспетчеров AVR я написал следующую функцию, включая соответствующие комментарии, чтобы облегчить понимать:
/**
* hex2int
* take a hex string and convert it to a 32bit number (max 8 hex digits)
*/
uint32_t hex2int(char *hex) {
uint32_t val = 0;
while (*hex) {
// get current character then increment
char byte = *hex++;
// transform hex character to the 4bit equivalent number, using the ascii table indexes
if (byte >= '0' && byte <= '9') byte = byte - '0';
else if (byte >= 'a' && byte <='f') byte = byte - 'a' + 10;
else if (byte >= 'A' && byte <='F') byte = byte - 'A' + 10;
// shift 4 to make space for new digit, and add the 4 bits of the new digit
val = (val << 4) | (byte & 0xF);
}
return val;
}
Пример:
char *z ="82ABC1EF";
uint32_t x = hex2int(z);
printf("Number is [%X]\n", x);
Произведет: ! [введите описание изображения здесь] [1]
Как будто часто происходит, Ваш вопрос страдает от серьезной терминологической ошибки/двусмысленности. В общей речи это обычно doesn' t вопрос, но в контексте этой определенной проблемы это критически важно.
Вы видите, there' s никакая такая вещь как " шестнадцатеричный value" и " десятичное число value" (или " шестнадцатеричный number" и " десятичное число number"). " Hex" и " decimal" свойства представления ценностей. Между тем у ценностей (или числа) собой нет представления, таким образом, они can' t быть " hex" или " decimal". например, '0xF' и '15' в синтаксисе C два отличающиеся представления тот же number.
Я предположил бы, что Ваш вопрос, способ, которым он указан, предлагает, чтобы Вы преобразовали представление ведьмы ASCII стоимости (т.е. последовательность) в представление десятичного числа ASCII стоимости (другая последовательность). Один способ сделать, который должен использовать представление целого числа в качестве промежуточного: во-первых, представление ведьмы ASCII новообращенного целому числу достаточного размера (использующий функции от 'strto...' группа, как 'strtol'), затем преобразовывает целое число в представление десятичного числа ASCII (использующий 'sprintf').
Если that' s не, что Вы должны сделать, тогда Вы должны разъяснить свой вопрос, так как невозможно изобразить его из способа, которым сформулирован Ваш вопрос.
Шестнадцатеричный к десятичному числу. Don' t управляют им на компиляторах онлайн, потому что это won' t работа.
#include<stdio.h>
void main()
{
unsigned int i;
scanf("%x",&i);
printf("%d",i);
}
Поскольку более крупная Ведьма натягивает как в примере, я должен был использовать [strtoul] (http://www.cplusplus.com/reference/clibrary/cstdlib/strtoul.html).
@Eric
Почему за решение, которое работает, голосуют? Конечно, это некрасиво и, возможно, не самый быстрый способ сделать это, но это более поучительно, чем сказать "strtol" или "sscanf". Если вы попробуете сделать это сами, вы узнаете кое-что о том, как все происходит под капотом.
Я не думаю, что ваше решение должно было быть проголосовано, но я предполагаю, почему это происходит, потому что оно менее практично. Идея голосования заключается в том, что "лучший" ответ поднимается наверх, и хотя ваш ответ может быть более поучительным в отношении того, что происходит под капотом (или способа, которым это может произойти), он определенно не является лучшим способом разбора шестнадцатеричных чисел в производственной системе.
Опять же, я не думаю, что в вашем ответе есть что-то плохое с образовательной точки зрения, и я, конечно, не стал бы (и не стал) голосовать за него. Не падайте духом и не прекращайте писать только потому, что некоторым людям не понравился один из ваших ответов. Это случается.
Я сомневаюсь, что мой ответ заставит вас почувствовать себя лучше из-за того, что ваш ответ был отклонен, но я знаю, что это особенно невесело, когда вы спрашиваете, почему что-то отклоняется, а никто не отвечает.
#include "math.h"
#include "stdio.h"
///////////////////////////////////////////////////////////////
// The bits arg represents the bit say:8,16,32...
/////////////////////////////////////////////////////////////
volatile long Hex_To_Int(long Hex,char bits)
{
long Hex_2_Int;
char byte;
Hex_2_Int=0;
for(byte=0;byte<bits;byte++)
{
if(Hex&(0x0001<<byte))
Hex_2_Int+=1*(pow(2,byte));
else
Hex_2_Int+=0*(pow(2,byte));
}
return Hex_2_Int;
}
///////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////
void main (void)
{
int Dec;
char Hex=0xFA;
Dec= Hex_To_Int(Hex,8); //convert an 8-bis hexadecimal value to a number in base 10
printf("the number is %d",Dec);
}
Почему кодовое решение, которое работает проваленный? Несомненно, it' s ужасный ...
Возможно, потому что, а также быть ужасным это isn' t образовательный и doesn' t работа. Кроме того, я подозреваю это как я, большинство людей don' t имеют власть редактировать в настоящее время (и оценка по необходимому разряду - никогда не будет).
Использование множества может быть хорошо для эффективности, но that' s не упомянутый в этом кодексе. Это также не уделяет внимания верхнему и нижнему регистру, таким образом, это не работает на пример, поставляемый в вопросе. FFFFFFFE
Попробуйте это, чтобы Преобразовать из Десятичного числа, чтобы Околдовать
#include<stdio.h>
#include<conio.h>
int main(void)
{
int count=0,digit,n,i=0;
int hex[5];
clrscr();
printf("enter a number ");
scanf("%d",&n);
if(n<10)
{
printf("%d",n);
}
switch(n)
{
case 10:
printf("A");
break;
case 11:
printf("B");
break;
case 12:
printf("B");
break;
case 13:
printf("C");
break;
case 14:
printf("D");
break;
case 15:
printf("E");
break;
case 16:
printf("F");
break;
default:;
}
while(n>16)
{
digit=n%16;
hex[i]=digit;
i++;
count++;
n=n/16;
}
hex[i]=n;
for(i=count;i>=0;i--)
{
switch(hex[i])
{
case 10:
printf("A");
break;
case 11:
printf("B");
break;
case 12:
printf("C");
break;
case 13:
printf("D");
break;
case 14:
printf("E");
break;
case 15:
printf("F");
break;
default:
printf("%d",hex[i]);
}
}
getch();
return 0;
}
@Eric
я на самом деле надеялся видеть, что волшебник C отправить что-то действительно охлаждает, вид подобных, что я сделал, но менее многословный, все еще делая его " manually".
Ну, I' m никакой гуру C, но here' s, что я придумал:
unsigned int parseHex(const char * str)
{
unsigned int val = 0;
char c;
while(c = *str++)
{
val <<= 4;
if (c >= '0' && c <= '9')
{
val += c & 0x0F;
continue;
}
c &= 0xDF;
if (c >= 'A' && c <= 'F')
{
val += (c & 0x07) + 9;
continue;
}
errno = EINVAL;
return 0;
}
return val;
}
У меня первоначально было больше bitmasking, продолжающийся вместо сравнений, но я серьезно сомневаюсь, что bitmasking немного быстрее, чем сравнение на современных аппаратных средствах.
В C Вы можете преобразовать шестнадцатеричное число в десятичное число во многих отношениях. Один путь состоит в том, чтобы бросить шестнадцатеричное число к целому числу. Я лично нашел, что это было простым и маленьким.
Вот типовой кодекс для преобразования Шестнадцатеричного числа к Десятичному числу с помощью кастинга.
#include <stdio.h>
int main(){
unsigned char Hexadecimal = 0x6D; //example hex number
int Decimal = 0; //decimal number initialized to 0
Decimal = (int) Hexadecimal; //conversion
printf("The decimal number is %d\n", Decimal); //output
return 0;
}
Как написано прежде, эффективность в основном зависит от того, для чего каждый оптимизирует.
Когда optiming для линий кодекса, или просто работающий в окружающей среде без полностью оборудованной стандартной библиотеки один быстрый и грязный выбор мог быть:
// makes a number from two ascii hexa characters
int ahex2int(char a, char b){
a = (a <= '9') ? a - '0' : (a & 0x7) + 9;
b = (b <= '9') ? b - '0' : (b & 0x7) + 9;
return (a << 4) + b;
}
... больше в подобной нити здесь: https://stackoverflow.com/a/58253380/5951263
Это в настоящее время только работает с нижним регистром, но его супер легким, чтобы заставить его работать с обоими.
cout << "\nEnter a hexadecimal number: ";
cin >> hexNumber;
orighex = hexNumber;
strlength = hexNumber.length();
for (i=0;i<strlength;i++)
{
hexa = hexNumber.substr(i,1);
if ((hexa>="0") && (hexa<="9"))
{
//cout << "This is a numerical value.\n";
}
else
{
//cout << "This is a alpabetical value.\n";
if (hexa=="a"){hexa="10";}
else if (hexa=="b"){hexa="11";}
else if (hexa=="c"){hexa="12";}
else if (hexa=="d"){hexa="13";}
else if (hexa=="e"){hexa="14";}
else if (hexa=="f"){hexa="15";}
else{cout << "INVALID ENTRY! ANSWER WONT BE CORRECT\n";}
}
//convert from string to integer
hx = atoi(hexa.c_str());
finalhex = finalhex + (hx*pow(16.0,strlength-i-1));
}
cout << "The hexadecimal number: " << orighex << " is " << finalhex << " in decimal.\n";