Pergunta

Olá a todos, apenas uma coisa rápida, tenho o hexa para trabalho inteiro, mas eu preciso para obter os números de minúsculas. Aqui está o que eu tenho, todas as idéias para chegar a obter o A a F maiúsculas e minúsculas?

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

Provavelmente apenas uma pequena coisa, mas eu gostaria de incluir a-f e A-F. Obrigado pela sua ajuda!

Foi útil?

Solução

Se você está fazendo isso para aprender como fazê-lo, ignore este post. Se você estiver usando esta função, porque você precisa para converter uma seqüência de números hexadecimais para uma int, você deve dar um passeio na sua biblioteca padrão. A função padrão strtol() converte uma string para um long, que pode ser derrubado para um int (ou um unsigned int enquanto estavam no). O terceiro argumento é a base para converter a - neste caso, você gostaria base 16 para hexadecimal. Além disso, se determinada base de 0, ele assumirá hex se a string começa com 0x, octal se ele começa com 0, e decimal contrário. É uma função muito útil.


EDIT: Só notei isso, mas enquanto estamos aqui, vale a pena mencionar que você geralmente não deve usar um int para matrizes de índice. O padrão C define um tipo, chamado size_t, que é concebido para armazenamento de índices de matriz. É geralmente uma unsigned int ou unsigned long ou algo assim, mas é garantido para ser grande o suficiente para armazenar qualquer matriz ou ponteiro deslocamento você pode usar.

O problema com o uso de apenas uma int é que, teoricamente, talvez, algum dia, alguém poderia passar uma cadeia mais longa do que INT_MAX, e então sua int vai transbordar, provavelmente envolver em torno, e começar a ler memória que ele provavelmente não deveria porque é utilizando um índice negativo. Isto é altamente improvável, especialmente para uma função como esta, porque o valor int você voltar vai transbordar muito antes de seu contador int transborda, mas é uma coisa importante para se manter em mente.

Para ser tecnicamente correto, você só deve usar variáveis ??do tipo size_t para matrizes de índice, ou pelo únicos tipos uso unsigned menos importante, a menos que você realmente quer tentar elementos acesso negativos (que geralmente é uma má idéia se você não sabe o que você' está fazendo). No entanto, não é um grande problema aqui.

Outras dicas

Criar outra função que transforma um dígito hexadecimal para um número inteiro:

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

Observe como ele lida com quatro casos: * digit é uma carta A..F maiúsculas, * digit é uma carta a..f minúscula, * digit é um dígito 0..9 decimal, e * digit é nenhuma das opções acima.

Agora, usar a nova função em sua função original:

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

Observe como muito mais limpo os novos olhares função?

Se você é aventureiro, você pode usar esta função mágica (que não manipular a entrada ruim, então você precisa verificar que de antemão):

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

Substituir todos f [z] com uma variável dedicada. Atribuir essa variável com toupper (f [z])

Aqui está um código do pacote NPS CLRS 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;
}

Este código é projetado para ser super-rápido, lidar com ambos maiúsculas e minúsculas hex e cordas punho hexadecimais de qualquer comprimento. O nsrl_hex2bin function () leva um buffer binário, o tamanho desse buffer, ea cadeia hex você deseja converter. Ele retorna o número de bits que realmente se converteu.

Oh, se você quer apenas um inteiro, então você pode multiplicar os bytes (para código endian-independente), ou apenas fazer um elenco (para código endian-dependente).

Você poderia tentar sscanf vez:

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

Duas opções:

converter em maiúsculas antes de fazer a digitalização.

Adicionar um segundo, se nos quatro loop que alças minúsculas.

Tente isto em vez disso:

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

É ainda trata a entrada da mesma forma que o seu (eu tendem a usar ponteiros, mas eles são, por vezes, difícil de entender por um novato), mas introduz três casos separados, 0-9, AF e AF, tratando cada adequadamente.

O seu código original seria realmente permitir caracteres incorretos (seis entre '9' e 'A') e produzir resultados incorretos com base nelas.

Note que este novo código só normalmente termina o loop no final da string. Encontrar um caractere hexadecimal inválido vai sair do loop, funcionalmente idêntica à sua condição de terminação.

Use strtol () por favor. Esta é a função C90 padrão e muito mais poderoso do que a maioria das implementações ingênuas. É também suportes sem costura conversão de dezembro (sem prefixo), hexagonal (0x) e outubro (começando com 0).

E implementação usando rotação turno em vez de multiplicação.

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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top