Dalam C, apa adalah cara yang paling efisien untuk mengkonversi string hex digit biner menjadi unsigned int
atau unsigned long
?
Misalnya, jika saya memiliki hingga 0xfffffffe
, aku ingin int
dengan base10 nilai 4294967294
.
Anda ingin strtol
atau strtoul
. Lihat juga Unix halaman
Edit: Sekarang kompatibel dengan MSVC, C++ dan non-GNU compiler (lihat akhir).
Pertanyaan itu "cara yang paling efisien." OP doesn't menentukan platform, ia bisa menyusun sebuah RISC berbasis ATMEL chip dengan 256 byte penyimpanan flash untuk kode nya.
Sebagai catatan, dan untuk orang-orang (seperti saya), yang menghargai perbedaan antara "cara termudah" dan "cara yang paling efisien", dan yang menikmati belajar...
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;
}
Hal ini tidak memerlukan eksternal perpustakaan, dan itu harus menyilaukan cepat. Menangani huruf besar, huruf kecil, karakter yang tidak valid, aneh berukuran masukan hex (misalnya: 0xfff), dan ukuran maksimum hanya dibatasi oleh compiler.
Untuk non-GCC atau C++ compiler atau kompiler yang tidak akan menerima mewah hextable deklarasi.
Mengganti pernyataan dengan ini (lagi, tapi yang lebih sesuai) versi:
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
};
Jika anda don't memiliki stdlib maka anda harus melakukannya secara manual.
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;
}
Catatan: kode Ini mengasumsikan huruf besar A-F. Ini tidak bekerja jika len luar terpanjang integer 32 atau 64bits, dan tidak ada kesalahan perangkap untuk kegiatan ilegal karakter hex.
Untuk Mikrokontroler AVR yang saya tulis fungsi berikut, termasuk komentar yang relevan untuk membuatnya mudah untuk memahami:
/**
* 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;
}
Contoh:
char *z ="82ABC1EF";
uint32_t x = hex2int(z);
printf("Number is [%X]\n", x);
Karena jika sering terjadi, pertanyaan anda menderita serius terminologi kesalahan/ambiguitas. Dalam pidato umum itu biasanya doesn't peduli, tapi dalam konteks ini masalah tertentu itu sangat penting.
Anda lihat, ada's ada hal seperti itu sebagai "nilai hex" dan "nilai desimal" (atau "nomor hex" dan "angka desimal"). "Hex" dan "desimal" adalah sifat-sifat pernyataan dari nilai-nilai. Sementara itu, nilai-nilai (atau angka) dengan sendirinya tidak memiliki representasi, sehingga mereka dapat't "hex" atau "desimal". Misalnya, 0xF
dan 15
dalam sintaks C adalah dua hal yang berbeda pernyataan dari jumlah yang sama.
Saya akan menebak bahwa pertanyaan anda, cara itu menyatakan, menunjukkan bahwa anda perlu mengkonversi ASCII hex representasi dari sebuah nilai (yaitu string) ke ASCII desimal representasi dari sebuah nilai (string lain). Salah satu cara untuk melakukannya adalah dengan menggunakan integer representasi sebagai perantara satu: pertama, mengkonversi ASCII hex representasi integer ukuran yang cukup (menggunakan fungsi dari strto...
kelompok, seperti strtol
), kemudian mengkonversi bilangan bulat ke dalam representasi desimal ASCII (menggunakan sprintf
).
Jika itu's tidak apa yang perlu anda lakukan, maka anda harus menjelaskan pertanyaan anda, karena itu adalah mungkin untuk mencari tahu dari cara anda pertanyaan yang dirumuskan.
@Eric
Mengapa kode solusi yang bekerja mendapatkan ditolak? Yakin, itu's jelek dan tidak mungkin cara tercepat untuk melakukan itu, tapi itu's lebih instruktif yang mengatakan "strtol" atau "sscanf". Jika anda mencobanya sendiri, anda akan belajar sesuatu tentang bagaimana hal-hal terjadi di bawah tenda.
Saya don't benar-benar berpikir solusi anda harus telah ditolak, namun saya duga mengapa itu's terjadi adalah karena itu's kurang praktis. Ide dengan voting adalah bahwa "terbaik" jawabannya akan mengapung ke atas, dan sementara jawaban anda mungkin akan lebih instruktif tentang apa yang terjadi di bawah kap mesin (atau cara itu mungkin terjadi), it's pasti bukan cara terbaik untuk mengurai hex angka-angka dalam suatu sistem produksi.
Sekali lagi, saya don't pikir ada's sesuatu yang salah dengan jawaban anda dari sudut pandang pendidikan, dan saya pasti tidak't (dan tidak't) memilih ke bawah. Don't berkecil hati dan berhenti mem-posting hanya karena beberapa orang tidak't seperti salah satu dari jawaban anda. Hal ini terjadi.
Saya meragukan jawaban saya membuat anda merasa baik tentang anda yang ditolak, tapi aku tahu itu's sangat tidak menyenangkan ketika anda bertanya mengapa sesuatu's yang ditolak dan tidak ada answers.
#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);
}
Mengapa kode solusi yang bekerja mendapatkan ditolak? Yakin, itu's jelek ...
Mungkin karena serta menjadi jelek ini isn't pendidikan dan doesn't bekerja. Juga, saya menduga bahwa seperti saya, kebanyakan orang-orang yang don't memiliki kekuatan untuk mengedit saat ini (dan dilihat dari peringkat yang dibutuhkan - tidak akan pernah).
Penggunaan array dapat baik untuk efisiensi, tapi yang's tidak disebutkan dalam kode ini. Hal ini juga tidak memperhitungkan dari atas dan bawah sehingga tidak bekerja untuk contoh yang diberikan dalam pertanyaan. FFFFFFFE
Mencoba untuk Mengkonversi dari Desimal ke Hex
#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
saya benar-benar berharap untuk melihat C wizard posting sesuatu yang benar-benar keren, seperti apa yang saya lakukan tapi kurang verbose, sementara masih melakukan itu, "manual".
Yah, aku'm tidak ada C guru, tapi di sini's apa yang saya datang dengan:
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;
}
Pada mulanya saya lebih bitmasking terjadi bukan perbandingan, tapi aku benar-benar ragu bitmasking ini lebih cepat dibandingkan pada hardware modern.
Di C, anda dapat mengkonversi nomor heksadesimal ke desimal dalam banyak cara. Salah satu cara adalah untuk cor nomor heksadesimal untuk bilangan bulat. Saya pribadi menemukan ini untuk menjadi sederhana dan kecil.
Berikut adalah contoh kode untuk mengubah angka Heksadesimal ke bilangan Desimal dengan bantuan casting.
#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;
}
Seperti yang tertulis sebelumnya, efisiensi pada dasarnya tergantung pada apa yang mengoptimalkan.
Ketika optiming untuk baris kode, atau hanya bekerja di lingkungan tanpa sepenuhnya-dilengkapi standar perpustakaan yang cepat dan kotor bisa menjadi pilihan:
// 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;
}
... lebih lanjut di thread serupa di sini: https://stackoverflow.com/a/58253380/5951263
Ini saat ini hanya bekerja dengan kasus yang lebih rendah tapi super mudah untuk membuatnya bekerja dengan baik.
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";