Méthode de conversion de Hex en Integer en C, impossible d'obtenir en minuscule!

StackOverflow https://stackoverflow.com/questions/1416571

  •  06-07-2019
  •  | 
  •  

Question

Coucou tout le monde, bref, j’ai l’hex au chiffre entier, mais j’ai besoin d’obtenir les chiffres en minuscule. Voici ce que j'ai, des idées pour obtenir l'insensible à la casse de A à F?

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

Probablement une petite chose, mais j'aimerais inclure a-f et A-F. Merci pour votre aide!

Était-ce utile?

La solution

Si vous faites cela pour apprendre à le faire, ignorez ce post. Si vous utilisez cette fonction parce que vous devez convertir une chaîne de nombres hexadécimaux en int , vous devriez vous promener dans votre bibliothèque standard. La fonction standard strtol () convertit une chaîne vers un long , qui peut être converti en un int (ou un unsigned int alors qu'il y était). Le troisième argument est la base de conversion - dans ce cas, vous voudriez que la base 16 soit hexadécimale. De plus, si la base 0 est donnée, elle sera considérée hexadécimale si la chaîne commence par 0x , octal si elle commence par 0 et décimale sinon. C'est une fonction très utile.

EDIT: Je viens de le remarquer, mais tant que nous sommes ici, il convient de mentionner qu’il ne faut généralement pas utiliser un int pour indexer des tableaux. La norme C définit un type, appelé size_t , conçu pour stocker des index de tableau. C'est généralement un unsigned int ou un unsigned long ou quelque chose du genre, mais il est garanti que sa taille est suffisante pour stocker tout décalage de tableau ou de pointeur que vous pouvez utiliser.

Le seul problème avec l’utilisation d’un int est qu’en théorie, un jour, quelqu'un pourrait passer une chaîne plus longue que INT_MAX , puis votre int débordera probablement, et la lecture de la mémoire ne devrait probablement pas se faire, car elle utilise un index négatif. Ceci est hautement improbable, en particulier pour une fonction comme celle-ci, car la valeur int que vous renvoyez dépassera le délai d'attente bien avant que votre compteur int ne déborde, mais il est une chose importante à garder à l'esprit.

Pour être techniquement correct, vous ne devez utiliser que des variables de type size_t pour indexer des tableaux, ou du moins uniquement des types unsigned , à moins que vous ne souhaitiez réellement accéder à des valeurs négatives. éléments (ce qui est généralement une mauvaise idée, sauf si vous savez ce que vous faites). Cependant, ce n’est pas un gros problème ici.

Autres conseils

Créez une autre fonction qui convertit un chiffre hexadécimal en entier:

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

Notez comment il gère quatre cas:  * chiffre est une lettre majuscule A..F ,  * chiffre est une lettre minuscule a..f ,  * chiffre est un chiffre décimal 0..9 , et  * chiffre n'est pas l'un des éléments ci-dessus.

Utilisez maintenant la nouvelle fonction dans votre fonction d'origine:

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

Remarquez à quel point la nouvelle fonction a l'air plus propre?

Si vous êtes aventureux, vous pouvez utiliser cette fonction magique (qui ne gère pas les mauvaises entrées, vous devez donc la vérifier au préalable):

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

Remplacez tous les f [z] par une variable dédiée. Assigne cette variable avec toupper (f [z])

Voici du code du package NPS NSRL Bloom:

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

Ce code est conçu pour être ultra-rapide, pour gérer les caractères hexadécimaux majuscules et minuscules, ainsi que pour les chaînes hexagonales de toute longueur. La fonction nsrl_hex2bin () prend un tampon binaire, la taille de ce tampon et la chaîne hexadécimale que vous souhaitez convertir. Il renvoie le nombre de bits réellement convertis.

Oh, si vous voulez juste un entier, vous pouvez multiplier les octets (pour le code indépendant de Endian) ou simplement effectuer un transtypage (pour le code dépendant de Endian).

Vous pouvez essayer sscanf à la place:

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

Deux options:

Convertissez-les en majuscules avant de numériser.

Ajoutez une seconde si dans la boucle qui gère les minuscules.

Essayez plutôt ceci:

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

Il traite toujours l’entrée de la même manière que la vôtre (j’ai tendance à utiliser des pointeurs, mais ils sont parfois difficiles à comprendre pour un débutant), mais introduit trois cas distincts, 0-9, AF et af, les traitant chacun de manière appropriée.

Votre code d'origine autoriserait les caractères erronés (les six entre "9" et "A") et produirait des résultats incorrects en fonction de ces caractères.

Notez que ce nouveau code ne termine normalement que la boucle en fin de chaîne. La recherche d’un caractère hexadécimal invalide sortira de la boucle, fonctionnellement identique à votre condition finale.

Utilisez strtol () s'il vous plait. C'est la fonction standard du C90 et beaucoup plus puissante que la plupart des implémentations naïves. Il prend également en charge la conversion transparente de dec (sans préfixe), hex (0x) et oct (à partir de 0).

Et la mise en œuvre utilisant la rotation à la place de la multiplication.

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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top