hexadecimal a decimal

rot
06 de Mayo del 2008
Realizar una funcion que dado un numero en formato hexadecimal (ingresado
como string) y de hasta 2 cifras entregue su valor decimal.

estoy estancado


#include <stdio.h>
#include <stdlib.h>


char hexa[3];
char resultado;

int main()
{
printf("introdusca valor hexa de 2 digitos: n");
scanf("%s", hexa);
hexa_a_decimal();
printf("el resultado es %d", resultado);
getch();
return 0;
}

int hexa_a_decimal()
{
char i=0;
while(hexa[i] != '')
{
if (hexa[i]=97) /*si hexa es a b c o d lo cambia*/
{
hexa[i]=10;
}
else if (hexa[i]=98)
{
hexa[i]=11;
}
else if (hexa[i]=99)
{
hexa[i]=12;
}
else if (hexa[i]=100)
{
hexa[i]=13;
}
else if (hexa[i]=101)
{
hexa[i]=14;
}
else if (hexa[i]=102)
{
hexa[i]=15;
}
i++; /*me aseguro que lo busque en los dos digitos*/
}

resultado=hexa[0]*16+hexa[1]*1;
return 0;
}

PoWeRsgame
06 de Mayo del 2008
Hola, El problema es mas bien sencillote.
Buscando entre los cientos de programas que tengo he conseguido encontrar uno igual pero con la diferencia que recive un numero hexadecimal de cualquier longuitud. Es facil adaptarlo a tus necesidades.
Otra diferencia que quizás te lie un poco es que hago un tratamiento del vector por direcciones de memoria (como si fuera un puntero) para esto se ha de tener incluida la biblioteca stdlib.h. Si quieres tratarlo como un vector normal en vez de poner *(cadena + cont) sería cadena [cont] no tiene complicación.

//Cabecera: int hexadicimal_ entero (char *cadena)
//Postcondicion: Devuelve un entero decimal correspondiente a la cadena hexadecimal

int hexadecimal_entero (char *cadena){
int resultado = 0, cont = 0, potencia;
/*Lo Primero es situarnosen el último elemento del vector en tu caso
* sabemos que el número tiene solo dos diguitos por lo que ya sabemos cual
* es el último elemento. También se podría haber usado aqui la función strlen de
* la biblioteca string.h, pero con esto nos vale*/
while (*(cadena + cont) != '')
cont ++;
cont --;
/* Lo siguiente sera recorrer el vector de derecha izquierda sumando los valores de
* cada diguito multiplicado por la base elevada al exponente correspondiente a la posicion.
* Por ejemplo el numero 12A será 10 * 16^0 + 2 * 16^1 + 1 * 16^2 */
potencia = 0;
while (cont >= 0){
if (*(cadena + cont) < 'A') //Si el diguito es menor que el codigo ascii del caracter A entonces es un numero
resultado = resultado + ((*(cadena + cont) - '0') * pow (16, potencia)); //Al ser un numero para hallar el equivalente entero le restamos el valor del caracter '0'
else{
if (*(cadena +cont) < 'a') //Si es menor que el caracter a entonces es una letra mayuscula
resultado = resultado + ((*(cadena + cont) - 'A' + 10) * pow (16,potencia)); //le restamos el valor del caracter A y le sumamos 10 para asi obtener los valores 10, 11, 12..
else //Si llega hasta aqui esque es una letra minuscula
resultado = resultado + ((*(cadena + cont) - 'a' + 10) * pow (16, potencia)); //Le restamos el valor de 'a' y le sumamos 10
}
potencia ++;
cont --;
}
return (resultado);
}

Esta función se podría mejorar, haciendo que detecte si se ha introducido un carater incorrecto.
Este planteamiento te puede servir también para hacer el cambio de otra base a decimal.
Espero que te haya servido de ayuda, si tienes algún problema dimelo.
Por cierto el Prototipo de la función viene ha ser la cabecera, precondición (restrinciones de los parametros de entrada) y la postcondición (qué es lo que hace la función)
Saludos.

PoWeRsgame
06 de Mayo del 2008
Si me permites voy hacer unas correcciones en tu código para que así aprendas de tus errores y cojas mejor práctica a la hora de programar

Variables globales:
Aunque a veces sea mucho más cómodo el uso de variables globales pueden llevarnos a la destrucción. Las variables globales son aquellas que se declaran fuera de cualquier función. Esas variables van a durar en memoria hasta que termine la ejecución del programa y además si usamos una variable local con el mismo nombre se oculta el valor de la global.
En tu programa guardas el valor de la cadena hexadecimal en una variable local y creas una función que trata esta variable. Imaginate que un día necesitas una función para pasar una cadena de caracteres hexadecimal, pero esta función es parte de un programa más grande que trata millones de cadenas en hexadecimal. La funcion que has escrito no funcionaria pues solo funciona con una variable gloabal. Lo ideal sería implementar una funcion igual que la tuya pero que reciva una cadena de caracteres que representa un número hexadecimal. Algo tal que así:
int hexa_a_decimal(char * cadena)
Como puedes imaginar esta funcion es mucho más portable que la tuya pues no trata con variables globales sino con variables que se pasan como parametros.

Declaración de funciones:
Otra cosa que te conviene saber es que las funciones o procedimientos deben estar declarados antes de su utilización.
A ver, el compilador solo conoce lo que lleva leido. En tu funcion main llamas a hexa_a_decimal(); pero la declaracion de esta función está más abajo por lo que el compilador no sabe que quiere decir esta línea y dará error en tiempo de compilación. Para solucionar esto es buena practica realizar una declaracion de las funciones antes de cualquier implementación, vendría a hacer algo así:
...
#include <stdio.h>

int hexa_a_decimal(void); //<----------------Declaración de función
hexa_a_decimal();
int main (){
...
}
int hexa_a_decimal(){
...
}

Así ya habrá constancia en el main de que existe una función llamada hexa_a_decimal()

La función hexa_a_decimal() siempre devuelve 0.
Al trabajar con variables globales la función no devuelve nada, pero lo suyo sería que devolviera el resultado en decimal.

Sobreescribes el valor hexadecimal:
Una buena práctica tambien es utilizar varibles intermedias, por ejemplo en tu código cambias los valores de la variable local hexa para poner los correspondientes en decimal. ¿qué crees que pasaría si luego quieres utilizar el número en hexadecimal? pues que tendrias que volver a pasar del 10 a la 'a' del 11 al ' b... Lo suyo sería utilizar un vector de enteros intermedio que guarde los valores coreespondientes, así la cadena original en hexadecimal no sufrirá ningún cambio

Pasar de caracteres a enteros.
En la función hexa_a_decimal() solo te encargas de pasar el valor de las letras a su correspondiente entero pero si tienes una cadena de caracteres por ejemplo 9A el 9 tambien esta en forma de caracter por lo que tendra su valor correspondiente ascii para arreglar esto como en el programa que te puse arriba basta con quitarle a el caracter 9 el valor del caracter 0 y si es una letra basta con quitarle el valor de 'a' pero habrá que sumarle 10.

Al resultado siempre le sumas los dos diguitos:
Eso, si el número solo es de un digito o de ninguno siempre sumaras los dos, dando un resultado incorrecto. Tendras que comprobar cuantos digitos tiene el numero, antes de sumarlos

Funciones Generales:
Lo suyo es hacer las funciones para casos generales, por eso te puse antes mi código. Es una lástima restringir una función como esta a una cadena de solo dos elementos, pero si es lo que te pide el problema que le vamos a hacer. No obstante quizás un día te haga falta hacer esto para 3 cifras, y ya no te valdrá este código

Por último aquí te dejo el código modificando todo lo que te he dicho:

#include <stdio.h>
#include <stdlib.h>

int hexa_a_decimal(char *hexa);

int main()
{
char hexa[3];
printf("introduzca valor hexa de 2 digitos: n");
scanf("%s", hexa);
printf("%s en hexadecimal es %d en decimaln", hexa, hexa_a_decimal(hexa));
getchar();
return 0;
}

int hexa_a_decimal(char * hexa)
{
int i=0, resultado = 0, dig [2];
while(hexa[i] != '')
{
if (hexa[i] >=97)
dig [i] = hexa [i] - 'a' + 10;
else
dig [i] = hexa [i] - '0';
i++;
}
if (hexa [0] != '' && hexa [1] != '' )
resultado= dig[0]*16 + dig[1];
else
resultado = dig[0];
return resultado;
}

Espero haberte servido de ayuda. Suerte

rot
06 de Mayo del 2008
Te agradesco la ayuda, en cuanto a lo de las globales el profesor nos pidio que hagamos los strings globales como un capricho pero igualmente nos habia dicho que solo hay que declararlas globales solo si es necesario.