En C, ¿cuál es la forma más eficiente de convertir una cadena de dígitos hexadecimales en un binario? unsigned int
o unsigned long
?
Por ejemplo, si tengo 0xFFFFFFFE
quiero un int
con el valor base10 4294967294
.
En C, ¿cuál es la forma más eficiente de convertir una cadena de dígitos hexadecimales en un binario? unsigned int
o unsigned long
?
Por ejemplo, si tengo 0xFFFFFFFE
quiero un int
con el valor base10 4294967294
.
Patricio
Usted quiere strtol
o strtoul
. Véase también el página del manual de Unix
orwellófilo
Editar: Ahora compatible con compiladores MSVC, C++ y no GNU (ver final).
La pregunta era “la forma más eficiente”. El OP no especifica la plataforma, podría estar compilando para un chip ATMEL basado en RISC con 256 bytes de almacenamiento flash para su código.
Para que conste, y para aquellos (como yo), que aprecian la diferencia entre “la forma más fácil” y la “forma más eficiente”, y que disfrutan aprendiendo…
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;
}
No requiere bibliotecas externas y debería ser deslumbrantemente rápido. Maneja mayúsculas, minúsculas, caracteres no válidos, entrada hexadecimal de tamaño impar (por ejemplo: 0xfff) y el tamaño máximo está limitado solo por el compilador.
Para compiladores que no sean GCC o C++ o compiladores que no acepten la elegante declaración hexadecimal.
Reemplace la primera declaración con esta versión (más larga, pero más conforme):
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
};
¿Tengo razón al pensar en el hextable
el código de inicialización es un pseudocódigo (si es así, vale la pena señalarlo), ¿o es una sintaxis de inicialización de matriz esotérica con la que no estoy familiarizado?
– John Carter
7 de noviembre de 2012 a las 1:02
No está compilando con Android ndk-build.
– hB0
8 de noviembre de 2013 a las 22:53
@ hB0 responderé a esa observación increíblemente vaga y sin sentido respondiendo del mismo modo: se compila bien en sonido metálico. hay 22 advertencias, pero eso es de esperar.
– Orwellófilo
17 de noviembre de 2013 a las 14:45
Usé la herramienta ndk-build en android ndk – desarrollador.android.com/tools/sdk/ndk/index.html y no compila me da un error específicamente en la declaración de la matriz. Aunque me encanta el fragmento de código, pero no pude usarlo, tuve que usar otro método bueno (pero ineficiente). No puedo darte el error de compilación exacto ahora… (ya te di +1 la última vez)
– hB0
19 de noviembre de 2013 a las 10:12
@hB0 solo comenta la segunda línea de código con “[0..255]” en él, y reza para que nunca te pasen una entrada no válida
– Orwellófilo
20 de noviembre de 2013 a las 12:38
marca harrison
Prueba esto:
#include <stdio.h>
int main()
{
char s[] = "fffffffe";
int x;
sscanf(s, "%x", &x);
printf("%u\n", x);
}
Es brillante. Nunca había visto este método antes.
– Nube Cho
20 de diciembre de 2017 a las 21:32
Si no tiene stdlib, debe hacerlo manualmente.
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;
}
Nota: Este código asume AF en mayúsculas. No funciona si len está más allá de su entero más largo de 32 o 64 bits, y no hay captura de errores para caracteres hexadecimales ilegales.
Para los microcontroladores AVR, escribí la siguiente función, incluidos los comentarios relevantes para que sea fácil de entender:
/**
* 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;
}
Ejemplo:
char *z ="82ABC1EF";
uint32_t x = hex2int(z);
printf("Number is [%X]\n", x);
No lo creo, pero tal vez se olvidó de proporcionar algunos argumentos.
– Radhoo
17 mayo 2017 a las 18:38
Como sucede a menudo, su pregunta adolece de un grave error/ambigüedad terminológica. En el habla común por lo general no importa, pero en el contexto de este problema específico es de vital importancia.
Verá, no existe tal cosa como “valor hexadecimal” y “valor decimal” (o “número hexadecimal” y “número decimal”). “Hex” y “decimal” son propiedades de representaciones de valores Mientras tanto, los valores (o números) por sí mismos no tienen representación, por lo que no pueden ser “hexadecimales” o “decimales”. Por ejemplo, 0xF
y 15
en la sintaxis C son dos diferentes representaciones de el mismo numero.
Supongo que su pregunta, tal como está planteada, sugiere que necesita convertir la representación hexadecimal ASCII de un valor (es decir, una cadena) en una representación decimal ASCII de un valor (otra cadena). Una forma de hacerlo es usar una representación entera como intermedia: primero, convertir la representación hexadecimal ASCII en un número entero de tamaño suficiente (usando funciones de strto...
grupo, como strtol
), luego convierta el entero a la representación decimal ASCII (usando sprintf
).
Si eso no es lo que necesita hacer, entonces debe aclarar su pregunta, ya que es imposible averiguarlo por la forma en que está formulada.
No lo creo, pero tal vez se olvidó de proporcionar algunos argumentos.
– Radhoo
17 mayo 2017 a las 18:38
Comunidad
@Eric
¿Por qué se rechaza una solución de código que funciona? Claro, es feo y puede que no sea la forma más rápida de hacerlo, pero es más instructivo que decir “strtol” o “sscanf”. Si lo prueba usted mismo, aprenderá algo sobre cómo suceden las cosas debajo del capó.
Realmente no creo que su solución debería haber sido rechazada, pero mi suposición de por qué está sucediendo es porque es menos práctica. La idea de votar es que la “mejor” respuesta flotará en la parte superior, y aunque su respuesta puede ser más instructiva sobre lo que sucede debajo del capó (o la forma en que podría suceder), definitivamente no es la mejor manera de analizar números hexadecimales. en un sistema de producción.
Una vez más, no creo que haya nada de malo en su respuesta desde un punto de vista educativo, y ciertamente no la votaría (y no lo hice). No se desanime y deje de publicar solo porque a algunas personas no les gustó una de sus respuestas. Sucede.
Dudo que mi respuesta te haga sentir mejor acerca de que la tuya haya sido rechazada, pero sé que no es especialmente divertido cuando preguntas por qué algo está siendo rechazado y nadie responde.
En agosto de 2008, el sitio era completamente nuevo y los comentarios no fueron implementados.
– Parque Derek
29/10/2010 a las 20:38