Tutto quell'ambaradam per convertire un numero in esadecimale? Si può compattare molto: in primo luogo l'allocazione dinamica può essere rimossa, dato che si può sapere con certezza qual è il numero massimo di caratteri della rappresentazione esadecimale di un dato intero, ossia sizeof(valore)*2, dato che ogni byte è rappresentabile in due cifre esadecimali. Si può sfruttare questo fatto anche per rimuovere tutte quelle sottrazioni e ridurre il tutto a qualche shift e and, il che tra l'altro permette di partire a convertire da sinistra, così non c'è necessità di invertire la stringa.
codice:
#include <stdio.h>
int main()
{
int numero,c;
char stringaOut[sizeof(numero)*2+1];
char * writePtr;
char cifre[]="0123456789ABCDEF";
if(scanf("%d", &numero)!=1)
{
fputs("Valore non valido.\n", stderr);
return 1;
}
if(numero<0)
{
numero=-numero;
putchar('-');
}
for(c=0, writePtr=stringaOut;c<sizeof(numero)*2;c++)
{
int valoreCifra=(numero>>((sizeof(numero)*2-c-1)*4))&0xf;
if(valoreCifra==0 && writePtr==stringaOut)
continue;
*(writePtr++)=cifre[valoreCifra];
}
*writePtr='\0';
puts(stringaOut);
return 0;
}
Tra l'altro, l'uso di una stringa per contenere i caratteri delle cifre consente di rimanere indipendenti dal set di caratteri utilizzato sulla macchina su cui viene compilato il programma.
---EDIT---
Tra l'altro si può anche evitare di usare la stringa di appoggio:
codice:
#include <stdio.h>
int main()
{
int numero, c, cifraScritta=0;
char cifre[]="0123456789ABCDEF";
if(scanf("%d", &numero)!=1)
{
fputs("Valore non valido.\n", stderr);
return 1;
}
if(numero<0)
{
numero=-numero;
putchar('-');
}
for(c=0;c<sizeof(numero)*2;c++)
{
int valoreCifra=(numero>>((sizeof(numero)*2-c-1)*4))&0xf;
if(valoreCifra==0 && !cifraScritta)
continue;
cifraScritta=1;
putchar(cifre[valoreCifra]);
}
putchar('\n');
return 0;
}