Frage

Hey everyone, nur eine kurze Sache, ich die hex müssen integer arbeiten, aber ich brauche die Zahlen Klein zu bekommen. Hier ist, was ich habe, um alle Ideen, die A bis F Groß- und Kleinschreibung zu bekommen zu bekommen?

int htoi(char f[]) {
    int  z, n;
    n = 0;

    for (z = 0; f[z] >= '0' && f[z] <= 'F'; ++z) 
        if (f[z] >= 'A' && f[z] <= 'F')
            n = 10 + 16 * n + (f[z] - 'A');
        else
            n = 16 * n + (f[z] - '0');
}

Wahrscheinlich nur eine kleine Sache, aber ich möchte ein-f und A-F enthalten. Vielen Dank für Ihre Hilfe!

War es hilfreich?

Lösung

Wenn Sie tun, um das zu lernen, wie es geht, ignorieren Sie diesen Beitrag. Wenn Sie diese Funktion verwenden, weil Sie eine Reihe von Hex-Zahlen auf einen int konvertieren müssen, sollten Sie einen Spaziergang in der Standard-Bibliothek nehmen. Die Standardfunktion strtol() wandelt eine Zeichenkette in einem long, die nach unten gegossen werden kann zu einem int (oder einem unsigned int während es war). Das dritte Argument ist die Basis zu konvertieren - in diesem Fall Sie Basis 16 für hexadezimale wünschen würden. wenn auch angesichts Basis 0, wird es hex übernehmen, wenn die Zeichenfolge mit 0x beginnt, Oktal, wenn es mit 0 beginnt, und dezimal anders. Es ist eine sehr nützliche Funktion.


EDIT: Nur soviel bemerkt, aber während wir hier sind, ist es erwähnenswert, dass Sie in der Regel keine int indizierten Arrays verwenden sollten. Der C-Standard definiert einen Typ, genannt size_t, die Array-Indizes speichern soll. Es ist im Allgemeinen ein unsigned int oder unsigned long oder etwas, aber garantiert groß genug sein, jede Array zu speichern oder Zeiger versetzen Sie verwenden können.

Das Problem mit nur einen int ist, dass theoretisch, vielleicht, einen Tag, jemand einen String länger als INT_MAX passieren könnte, und dann wird Ihre int überlaufen, wahrscheinlich umschlingen, und startet Speicher zu lesen es soll wohl nicht, weil es Verwendung eines negativen Index. Dies ist höchst unwahrscheinlich, vor allem für eine Funktion wie diese, weil der int Wert, den Sie überläuft zurückkehren, lange bevor Ihre int Zähler überläuft, aber es ist eine wichtige Sache im Auge zu behalten.

technisch korrekt sein, sollten Sie nur size_t Typ Variablen zu Index-Arrays verwenden, oder zumindest nur unsigned Typen verwenden, es sei denn, Sie wirklich negative Elemente versuchen wollen (für den Zugriff auf die in der Regel eine schlechte Idee, es sei denn, Sie wissen, was Sie‘ wieder tun). Allerdings ist es kein großes Problem hier.

Andere Tipps

Erstellen Sie eine weitere Funktion, die eine Hexadezimalzeichens auf eine ganze Zahl dreht:

int hex_digit_to_integer(char digit) {
    if (digit >= 'A' && digit <= 'F') {
        return digit - 'A' + 10;
    } else if (digit >= 'a' && digit <= 'f') {
        return digit - 'a' + 10;
    } else if (digit >= '0' && digit <= '9') {
        return digit - '0';
    }

    return -1; // Bad input.
}

Beachten Sie, wie es vier Fälle behandelt:  * digit ist ein Großbuchstabe A..F,  * digit ist ein Kleinbuchstabe a..f,  * digit ist eine Nachkommastelle 0..9 und  * digit ist keines der oben genannten.

Sie nun die neue Funktion in Ihrer ursprünglichen Funktion:

int htoi(char f[]) {
    int z, n;
    n = 0;

    /* Loop until we get something which isn't a digit (hex_digit_to_integer returns something < 0). */
    for (z=0; hex_digit_to_integer(f[z]) >= 0; ++z) {
        n = 16 * n + hex_digit_to_integer(f[z]);
    }
}

Beachten Sie, wie viel sauberer die neue Funktion aussieht?

Wenn Sie abenteuerlich sind, können Sie diese magische Funktion verwenden (was nicht schlecht Eingang umgehen kann, so dass man das vorher überprüfen müssen):

int hex_digit_to_integer(char digit) {
    return digit - (digit & 64 ? 55 : 48) & 15;
}

Alle ersetzen f [z] mit einer eigenen Variablen. Zuordnen, die Variable mit toupper (f [z])

Hier ist ein Code aus dem NPS NSRL Bloom Paket:

static int *hexcharvals = 0;

/** Initialization function is used solely for hex output
 */
static void nsrl_bloom_init()
{
    if(hexcharvals==0){
        /* Need to initialize this */
        int i;
        hexcharvals = calloc(sizeof(int),256);
        for(i=0;i<10;i++){
            hexcharvals['0'+i] = i;
        }
        for(i=10;i<16;i++){
            hexcharvals['A'+i-10] = i;
            hexcharvals['a'+i-10] = i;
        }
    }
}

/**
 * Convert a hex representation to binary, and return
 * the number of bits converted.
 * @param binbuf output buffer
 * @param binbuf_size size of output buffer in bytes.
 * @param hex    input buffer (in hex)
 */
int nsrl_hex2bin(unsigned char *binbuf,size_t binbuf_size,const char *hex)
{
    int bits = 0;
    if(hexcharvals==0) nsrl_bloom_init();
    while(hex[0] && hex[1] && binbuf_size>0){
        *binbuf++ = ((hexcharvals[(unsigned char)hex[0]]<<4) |
                     hexcharvals[(unsigned char)hex[1]]);
        hex  += 2;
        bits += 8;
        binbuf_size -= 1;
    }
    return bits;
}

Dieser Code ist so konzipiert, super-schnell zu sein, behandeln sowohl Groß- und Klein Hex und Hex-Strings beliebiger Länge verarbeiten. Die Funktion nsrl_hex2bin () nimmt einen binären Puffer, um die Größe des Puffers und die Hex-String Sie konvertieren möchten. Es gibt die Anzahl der Bits, die tatsächlich bekam umgewandelt.

Oh, wenn Sie nur eine ganze Zahl wollen, dann können Sie die Bytes ausmultiplizieren (für Endian unabhängigen Code) oder einfach eine Besetzung (für Endian abhängigen Code).

Sie könnten versuchen, sscanf statt:

#include <stdio.h>

...

//NOTE: buffer overflow if f is not terminated with \0 !!
int htoi(char f[]){
  int intval = -1;
  if (EOF == sscanf(f, "%x", &intval))
    return -1; //error
  return intval;
}

Zwei Optionen:

Konvertieren

in Großbuchstaben, bevor Sie Ihr Scan tun.

Fügen Sie eine Sekunde, wenn in der vier Schleife, die Kleinschreibung behandelt.

Versuchen Sie stattdessen:

int htoi (char f[]) {
    int  z, n;
    n = 0;
    for (z = 0; f[z] != '\0'; ++z) { 
        if (f[z] >= '0' && f[z] <= '9') {
            n = n * 16 + f[z] - '0';
        } else {
            if (f[z] >= 'A' && f[z] <= 'F') {
                n = n * 16 + f[z] - 'A' + 10;
            } else {
                if (f[z] >= 'a' && f[z] <= 'f') {
                    n = n * 16 + f[z] - 'a' + 10;
                } else {
                    break;
                }
            }
        }
    }
    return n;
}

Es behandelt noch die Eingabe die gleiche Art und Weise wie bei Ihnen (ich würde dazu neigen, Zeiger zu verwenden, aber sie sind manchmal schwer von einem Anfänger zu verstehen), sondern stellt drei verschiedene Fälle, 0-9, AF und af, jeweils in geeigneter Weise zu behandeln.

Ihr Original-Code erlauben würde, tatsächlich fehlerhafte Zeichen (die sechs zwischen ‚9‘ und ‚A‘) und falsche Ergebnisse auf ihnen basieren produzieren.

Beachten Sie, dass dieser neue Code normalerweise nur die Schleife am Ende der Zeichenfolge endet. Die Suche nach einem ungültigen Hex-Zeichen wird aus der Schleife brechen, funktional identisch mit Ihrer Abschlussbedingung.

Mit strtol () bitte. Dies ist die Standard-C90-Funktion und viel mächtiger als die meisten naiver Implementierungen. Es unterstützt auch die nahtlose Umwandlung von Dezember (ohne Vorwahl), hex (0x) und Oktober (beginnend mit 0).

Und Umsetzung mit Shift Rotation anstelle der Multiplikation.

int HexToDec(char *Number)
{

    unsigned int val = 0;

    int i , nibble;
    for(i = strlen( Number ) - 1; i >= 0; --i, nibble += 4)
    {
        const char hex = Number[i];
        if (hex >= '0' && hex <= '9')
            val += (hex - '0')<<nibble;
        else if (hex >= 'A' && hex <= 'F')
            val += (hex - 'A' + 10)<<nibble;
        else if (hex >= 'a' && hex <= 'f')
            val += (hex - 'a' + 10)<<nibble;
        else
            return -1;
    }
    return val;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top