Pensemos aproximadamente la mitad de la tarea por un momento: convirtiendo de una base en cadena n a una longitud sin signo, donde n es una potencia de 2 (base 2 para binario y base 16 para hex).
Si su entrada es sensata, entonces este trabajo no es más que una comparación, una subracta, un cambio y una o por dígito. Si tu opinión no es sensata, bueno, ahí es donde se pone feo, ¿no? Hacer la conversión súper rápida no es difícil. Hacerlo bien en todas las circunstancias es el desafío.
Así que vamos a asumir que su entrada es cuerdo, entonces el corazón de su conversión es la siguiente:
unsigned long PowerOfTwoFromString(char *input, int shift)
{
unsigned long val = 0;
char upperLimit = 'a' + (1 << shift)
while (*input) {
char c = tolower(*input++);
unsigned long digit = (c > 'a' && c < upperLimit) ? c - 'a' + 10 : c - '0';
val = (val << shift) | digit;
}
return val;
}
#define UlongFromBinaryString(str) PowerOfTwoFromString(str, 1)
#define UlongFromHexString(str) PowerOfTwoFromString(str, 4)
Vea lo fácil que es? Y fallará en entradas que no sean cuerdas. La mayor parte de tu trabajo se destinará a hacer que tu entrada funcione, no a la performance.
Ahora, este código aprovecha la potencia de dos cambios. Es fácil de extender a base 4, base 8, base 32, etc. No funcionará en la no potencia de dos bases. Para aquellos, tus matemáticas tienen que cambiar. Usted obtiene
val = (val * base) + digit
que es conceptualmente igual para este conjunto de operaciones. La multiplicación por la base va a ser equivalente al cambio. Por lo tanto, es probable que use una rutina completamente general. Y desinfecte el código mientras desinfecta las entradas. Y en ese punto, strtoul es probablemente tu mejor apuesta. Aquí hay un enlace al a version de strtoul. Casi todo el trabajo consiste en manejar las condiciones de borde, lo que debería darte una pista sobre dónde debes centrar tus energías: código correcto y resistente. El ahorro en el uso de los cambios de bits va a ser mínimo en comparación con el ahorro de, por ejemplo, no se bloquea en la entrada incorrecta.
Eres los primeros dos nombres de función son extremadamente engañosas. No está devolviendo una representación decimal. Usted está devolviendo una longitud sin signo, con una representación interna indefinida, opaca (a menos que usted haga algo definido por la implementación) –
¿Qué propondría que fueran los nombres de las funciones? –
Binary2Int y Hex2Int tienen mucho más sentido. Por supuesto, estas funciones no son necesarias con strtol en la biblioteca c. – jmucchiello