Was ist in C der effizienteste Weg, um eine Zeichenfolge von Hex-Ziffern in eine Binärzahl umzuwandeln? unsigned int
oder unsigned long
?
Zum Beispiel, wenn ich habe 0xFFFFFFFE
ich möchte ein int
mit dem base10-Wert 4294967294
.
Was ist in C der effizienteste Weg, um eine Zeichenfolge von Hex-Ziffern in eine Binärzahl umzuwandeln? unsigned int
oder unsigned long
?
Zum Beispiel, wenn ich habe 0xFFFFFFFE
ich möchte ein int
mit dem base10-Wert 4294967294
.
Patrick
Sie wollen strtol
oder strtoul
. Siehe auch die Unix-Manpage
Orwellophil
Bearbeiten: Jetzt kompatibel mit MSVC, C++ und Nicht-GNU-Compilern (siehe Ende).
Die Frage war “effizienteste Weg.” Das OP gibt keine Plattform an, er könnte für seinen Code einen RISC-basierten ATMEL-Chip mit 256 Byte Flash-Speicher kompilieren.
Fürs Protokoll und für diejenigen (wie mich), die den Unterschied zwischen “dem einfachsten Weg” und dem “effizientesten Weg” zu schätzen wissen und Spaß am Lernen haben …
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;
}
Es erfordert keine externen Bibliotheken und sollte unglaublich schnell sein. Es verarbeitet Großbuchstaben, Kleinbuchstaben, ungültige Zeichen, Hex-Eingaben mit ungerader Größe (z. B.: 0xfff) und die maximale Größe wird nur vom Compiler begrenzt.
Für Nicht-GCC- oder C++-Compiler oder Compiler, die die ausgefallene Hextable-Deklaration nicht akzeptieren.
Ersetzen Sie die erste Anweisung durch diese (längere, aber konformere) Version:
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
};
Habe ich Recht, wenn ich denke, dass hextable
Der Initialisierungscode ist ein Pseudocode (wenn ja, sollte darauf hingewiesen werden), oder ist dies eine esoterische Array-Initialisierungssyntax, mit der ich nicht vertraut bin?
– John Carter
7. November 2012 um 1:02 Uhr
Es wird nicht mit Android ndk-build kompiliert.
– hB0
8. November 2013 um 22:53 Uhr
@hB0 Ich werde auf diese unglaublich vage und sinnlose Beobachtung antworten, indem ich in Form von Sachleistungen antworte: Es lässt sich gut auf Clang kompilieren. Es gibt 22 Warnungen, aber das ist zu erwarten.
– Orwellophil
17. November 2013 um 14:45 Uhr
Ich habe das ndk-build-Tool in Android ndk verwendet – developer.android.com/tools/sdk/ndk/index.html und es wird nicht kompiliert, gibt mir speziell bei der Array-Deklaration einen Fehler. Obwohl ich das Codefragment liebe, aber ich konnte es nicht verwenden, musste ich eine andere gute Methode verwenden (aber ineffizient). Ich kann Ihnen jetzt keinen genauen Kompilierungsfehler geben. (hat Ihnen bereits beim letzten Mal +1 gegeben)
– hB0
19. November 2013 um 10:12 Uhr
@hB0 kommentieren Sie einfach die zweite Codezeile mit “[0..255]” darin, und beten Sie, dass Sie niemals ungültige Eingaben erhalten
– Orwellophil
20. November 2013 um 12:38 Uhr
Markus Harrison
Versuche dies:
#include <stdio.h>
int main()
{
char s[] = "fffffffe";
int x;
sscanf(s, "%x", &x);
printf("%u\n", x);
}
Es ist brillant. Diese Methode habe ich noch nie gesehen.
– Wolke Cho
20. Dezember 2017 um 21:32 Uhr
Wenn Sie die stdlib nicht haben, müssen Sie es manuell tun.
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;
}
Hinweis: Dieser Code setzt AF in Großbuchstaben voraus. Es funktioniert nicht, wenn len über Ihre längste ganze Zahl von 32 oder 64 Bit hinausgeht, und es gibt kein Fehler-Trapping für illegale Hexadezimalzeichen.
Für AVR-Mikrocontroller habe ich die folgende Funktion geschrieben, einschließlich relevanter Kommentare, um sie leicht verständlich zu machen:
/**
* 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;
}
Beispiel:
char *z ="82ABC1EF";
uint32_t x = hex2int(z);
printf("Number is [%X]\n", x);
Ich glaube nicht, aber vielleicht haben Sie vergessen, einige Argumente anzugeben.
– Radhoo
17. Mai 2017 um 18:38 Uhr
Wie so oft leidet Ihre Frage unter einem schwerwiegenden terminologischen Fehler / einer Mehrdeutigkeit. In der Umgangssprache spielt es normalerweise keine Rolle, aber im Zusammenhang mit diesem spezifischen Problem ist es von entscheidender Bedeutung.
Sie sehen, es gibt keinen „Hex-Wert“ und „Dezimal-Wert“ (oder „Hex-Zahl“ und „Dezimal-Zahl“). “Hex” und “dezimal” sind Eigenschaften von Darstellungen von Werten. In der Zwischenzeit haben Werte (oder Zahlen) selbst keine Darstellung, daher können sie nicht “Hex” oder “Dezimal” sein. Zum Beispiel, 0xF
und 15
in C-Syntax sind zwei verschiedene Darstellungen von die gleiche Nummer.
Ich würde vermuten, dass Ihre Frage, wie sie formuliert ist, darauf hindeutet, dass Sie die ASCII-Hex-Darstellung eines Werts (dh einer Zeichenfolge) in eine ASCII-Dezimaldarstellung eines Werts (eine andere Zeichenfolge) konvertieren müssen. Eine Möglichkeit, dies zu tun, besteht darin, eine Ganzzahldarstellung als Zwischendarstellung zu verwenden: Konvertieren Sie zunächst die ASCII-Hex-Darstellung in eine Ganzzahl ausreichender Größe (unter Verwendung von Funktionen aus strto...
Gruppe, wie strtol
), konvertieren Sie dann die Ganzzahl in die ASCII-Dezimaldarstellung (mit sprintf
).
Wenn Sie das nicht tun müssen, müssen Sie Ihre Frage präzisieren, da dies aus der Formulierung Ihrer Frage nicht ersichtlich ist.
Ich glaube nicht, aber vielleicht haben Sie vergessen, einige Argumente anzugeben.
– Radhoo
17. Mai 2017 um 18:38 Uhr
Simon
Wie bereits geschrieben, hängt die Effizienz im Wesentlichen davon ab, worauf man optimiert.
Wenn Sie für Codezeilen optimieren oder einfach in einer Umgebung ohne vollständig ausgestattete Standardbibliothek arbeiten, könnte eine schnelle und schmutzige Option sein:
// 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;
}
… mehr in einem ähnlichen Thread hier: https://stackoverflow.com/a/58253380/5951263