Konvertieren Sie eine hexadezimale Zeichenfolge in C effizient in eine Ganzzahl?

Lesezeit: 6 Minuten

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 0xFFFFFFFEich möchte ein int mit dem base10-Wert 4294967294.

Benutzer-Avatar
Patrick

Sie wollen strtol oder strtoul. Siehe auch die Unix-Manpage

Benutzer-Avatar
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

Benutzer-Avatar
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);

Wird ausgegeben:
Geben Sie hier die Bildbeschreibung ein

  • 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

Benutzer-Avatar
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

1370050cookie-checkKonvertieren Sie eine hexadezimale Zeichenfolge in C effizient in eine Ganzzahl?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy