Frage

Was ist in C der effizienteste Weg, eine Folge von Hexadezimalziffern in eine Binärzahl umzuwandeln? unsigned int oder unsigned long?

Zum Beispiel, wenn ich es getan habe 0xFFFFFFFE, ich möchte ein int mit dem Basiswert 10 4294967294.

War es hilfreich?

Lösung

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

Andere Tipps

Bearbeiten: Jetzt kompatibel mit MSVC, C++ und Nicht-GNU-Compilern (siehe Ende).

Die Frage war "effizientesten". Das OP gibt keine Plattform an, er könnte für einen RISC -basierten Atmel Chip mit 256 Bytes Flash -Speicher für seinen Code zusammenstellen.

Nur fürs Protokoll und für diejenigen (wie mich), die den Unterschied zwischen „dem einfachsten Weg“ und dem „effizientesten Weg“ schätzen 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ß- und Kleinschreibung, ungültige Zeichen und hexadezimale Eingaben mit ungerader Größe (z. B.:0xfff) und die maximale Größe wird nur durch den 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
};

Versuche dies:

#include <stdio.h>
int main()
{
    char s[] = "fffffffe";
    int x;
    sscanf(s, "%x", &x);
    printf("%u\n", x);
}

Wenn Sie nicht über die stdlib verfügen, müssen Sie dies 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;
}

Notiz:Dieser Code geht von Großbuchstaben A-F aus.Es funktioniert nicht, wenn len über Ihrer längsten Ganzzahl von 32 oder 64 Bit liegt, und es gibt keine Fehlererkennung für unzulässige Hexadezimalzeichen.

Für AVR-Mikrocontroller habe ich die folgende Funktion geschrieben, einschließlich relevanter Kommentare, um das Verständnis zu erleichtern:

/**
 * 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);

Gibt aus:enter image description here

Wie so oft weist Ihre Frage einen schwerwiegenden terminologischen Fehler/eine Unklarheit auf.Im allgemeinen Sprachgebrauch spielt es normalerweise keine Rolle, aber im Kontext dieses spezifischen Problems ist es von entscheidender Bedeutung.

Sie sehen, so etwas wie „Hex-Wert“ und „Dezimalwert“ (oder „Hex-Zahl“ und „Dezimalzahl“) gibt es nicht.„Hex“ und „Dezimal“ sind Eigenschaften von Darstellungen von Werten.Werte (oder Zahlen) hingegen haben keine eigene Darstellung und können daher nicht „hex“ oder „dezimal“ sein.Zum Beispiel, 0xF Und 15 in der C-Syntax sind zwei verschiedene Darstellungen von die gleiche Nummer.

Ich würde vermuten, dass Ihre Frage, so wie sie formuliert ist, darauf hindeutet, dass Sie die ASCII-Hexadezimaldarstellung eines Werts konvertieren müssen (d. h.eine Zeichenfolge) in eine ASCII-Dezimaldarstellung eines Werts (einer anderen Zeichenfolge).Eine Möglichkeit, dies zu erreichen, besteht darin, eine Ganzzahldarstellung als Zwischendarstellung zu verwenden:Konvertieren Sie zunächst die ASCII-Hex-Darstellung in eine Ganzzahl ausreichender Größe (mithilfe der Funktionen von strto... Gruppe, wie strtol), dann konvertieren Sie die Ganzzahl in die ASCII-Dezimaldarstellung (mit sprintf).

Wenn dies nicht das ist, was Sie tun müssen, müssen Sie Ihre Frage klären, da es aus der Formulierung Ihrer Frage nicht möglich ist, dies herauszufinden.

@Eric

Warum wird eine Codelösung, die funktioniert, abgelehnt?Sicher, es ist hässlich und vielleicht nicht der schnellste Weg, aber es ist lehrreicher, als „strtol“ oder „sscanf“ zu sagen.Wenn Sie es selbst ausprobieren, erfahren Sie etwas darüber, wie die Dinge unter der Haube ablaufen.

Ich denke nicht wirklich, dass Ihre Lösung hätte abgelehnt werden sollen, aber ich vermute, dass der Grund dafür darin liegt, dass sie weniger praktisch ist.Der Grundgedanke bei der Abstimmung ist, dass die „beste“ Antwort an die Spitze gelangt, und obwohl Ihre Antwort möglicherweise aufschlussreicher darüber ist, was unter der Haube passiert (oder wie es passieren könnte), ist es definitiv nicht die beste Methode, Hex-Zahlen zu analysieren in einem Produktionssystem.

Auch hier glaube ich nicht, dass aus pädagogischer Sicht etwas an Ihrer Antwort falsch ist, und ich würde sie auf keinen Fall ablehnen (und habe es auch nicht getan).Lassen Sie sich nicht entmutigen und hören Sie mit dem Posten auf, nur weil einigen Leuten eine Ihrer Antworten nicht gefallen hat.Es passiert.

Ich bezweifle, dass Sie sich durch meine Antwort besser fühlen, wenn Ihre Antwort abgelehnt wird, aber ich weiß, dass es besonders keinen Spaß macht, wenn Sie fragen, warum etwas abgelehnt wird und niemand antwortet.

Für größere Hex-Strings wie im Beispiel musste ich sie verwenden strtoul.

Hexadezimal zu Dezimal.Führen Sie es nicht auf Online-Compilern aus, da es sonst nicht funktioniert.

#include<stdio.h>
void main()
{
    unsigned int i;
    scanf("%x",&i);
    printf("%d",i);
}

Warum ist eine Codelösung, die funktioniert?Sicher, es ist hässlich ...

Vielleicht, weil es nicht nur hässlich ist, sondern auch nicht lehrreich ist nicht arbeiten.Außerdem vermute ich, dass die meisten Menschen, genau wie ich, derzeit nicht die Befugnis haben, etwas zu bearbeiten (und wenn man den benötigten Rang annimmt, werden sie das auch nie tun).

Die Verwendung eines Arrays kann sich positiv auf die Effizienz auswirken, wird in diesem Code jedoch nicht erwähnt.Außerdem werden Groß- und Kleinschreibung nicht berücksichtigt, sodass es für das in der Frage angegebene Beispiel nicht funktioniert.FFFFFFFE

@Eric

Eigentlich hatte ich gehofft, dass ein C-Assistent etwas wirklich Cooles posten würde, ähnlich wie ich es getan habe, aber weniger ausführlich, während ich es immer noch „manuell“ mache.

Nun, ich bin kein C-Guru, aber hier ist, was ich mir ausgedacht habe:

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;
}

Ich hatte ursprünglich mehr Bitmasking anstelle von Vergleichen im Einsatz, aber ich bezweifle ernsthaft, dass Bitmasking auf moderner Hardware schneller ist als Vergleiche.

Versuchen Sie dies, um von Dezimal in Hex umzuwandeln

    #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;
}
#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);
}

In C können Sie eine Hexadezimalzahl auf viele Arten in eine Dezimalzahl umwandeln.Eine Möglichkeit besteht darin, die Hexadezimalzahl in eine ganze Zahl umzuwandeln.Ich persönlich fand das einfach und klein.

Hier ist ein Beispielcode zum Konvertieren einer Hexadezimalzahl in eine Dezimalzahl mithilfe von 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;
}

Dies funktioniert derzeit nur mit Kleinbuchstaben, aber es ist super einfach, es mit beiden zum Laufen zu bringen.

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";
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top