PDA

Visualizza la versione completa : [C]-calcolo da numero decimale a esadecimale


Dheed
13-01-2010, 19:55
Salve,visto che oggi non avevo nulla da fare ho provato a fare un programma che mi calcoli da un numero in input il suo corrispettivo in base esadecimale,ma con scarsissimi risultati:


#include <stdio.h>
#include <stdlib.h>
int main ()
{
int a,i,d,e;
do{
printf("Inserire un numero POSITIVO: ");
scanf("%d", &a);
fflush(stdin);
system("cls");
}
while(a<0);
printf("Il numero %d in base esadecimale e': ",a);
for (;a>0;a=a/16)
{
e=a;
if(e<10)
printf("%d",e);
else if(e==10)
printf("A");
else if(e==11)
printf("B");
else if(e==12)
printf("C");
else if(e==13)
printf("D");
else if(e==14)
printf("E");
else if(e==15)
printf("F");
i=i/16;

}
getchar();
return 0;
}


In pratica non riesca a fare si che il programma calcoli il resto.
Esempio:
913/16=57 con il resto di 1
57/16=3 con il resto di 9
Purtroppo però non ci riesco,qualcuno mi puo aiutare?

Dheed
13-01-2010, 20:19
Ho risolto il problema...
Ultima domanda,c'è un modo per scrivere il numero al contrario?
A me esce F324F e invece deve deve risultare F423F.

antotan
13-01-2010, 22:07
Ciao, ti propongo questa soluzione (l'ho scritta ora, l'ho testata e non dovrebbero esserci problemi. magari fai qualche test con la calcolatrice di windows):



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

#define DEBUG 1

struct hex_struct {
char* nums;
int top;
int size;
};

void reverse(char* nums, int top) {
int i;
for(i=0; i < top/2; i++) {
char swap_var = nums[i];
nums[i] = nums[(top-1)-i];
nums[(top-1)-i] = swap_var;
}

}

int main () {
int dec_num;
struct hex_struct hex_num;

hex_num.top = 0;
hex_num.size = 4;
hex_num.nums = (char*)malloc(hex_num.size*sizeof(char));


do {
printf("Inserire un numero positivo: ");
scanf("%d", &dec_num);
fflush(stdin);
} while (dec_num < 0);
printf("\n\n");

while (dec_num > 0) {

if(hex_num.top == hex_num.size) {
hex_num.size *= 2;
hex_num.nums = (char*)realloc(hex_num.nums, hex_num.size*sizeof(char));
if(DEBUG)
printf("[debug] Memoria riallocata da %d byte a %d byte\n", hex_num.size/2, hex_num.size);
}

int quoz = dec_num % 16;
dec_num /= 16;

char char_quoz;
if (quoz < 10)
char_quoz = (char)(48+quoz);
else if(quoz >= 10)
char_quoz = (char)(55+quoz);

hex_num.nums[hex_num.top] = char_quoz;
hex_num.top++;
}
hex_num.nums[hex_num.top] = '\0';

reverse(hex_num.nums, hex_num.top);
printf("%s\n", hex_num.nums);

printf("Premi un tasto per continuare...");
getchar();
return 0;
}


Non so che familiarità hai con le struct. La struct che ho creato, hex_struct, rappresenta un numero esadecimale. Il vettore nums indica le singole cifre (memorizzate come lettere, per via dei valori A,B, ..., F), top indica la posizione attuale nel vettore, utilizzata per l'inserimento delle singole cifre e per mettere il carattere terminatore '\0'. Size è utilizzato per l'allocare lo spazio per il vettore e per riallocarlo in caso di riempia.
Ovviamente puoi mettere queste tre variabili nel main evitanto l'uso della struct, se non le conosci...

Inizialmente alloco 4 byte (4 cifre esadecimali) per il vettore, do in input il numero intero positivo e inizio le divisioni successive, registrando il resto e ottenendo il nuovo valore da dividere.

Il resto lo trasformo in un char per metterlo in un array.
Se il resto è minore di 10, inserisco il carattere ascii 48+quoz. Se osservi la tabella ascii (http://it.wikipedia.org/wiki/ASCII#Stampabili), noti che lo 0 equivale al valore 48 e il 9 al valore 57. Quoz va da 0 a 9, quindi il range è da 0 (carattere) a 9 (carattere).

Stesso per le lettere. La A è 65 nella tabella ascii. Se il quoziente è maggiore o uguale a 10, sommi il suo valore a 55, ottenendo tutti i valori in carattere dalla A alla F.
Del tipo, se resto=10, (char)(55+10) = 65 = A. (char)(55+15) = F. Nota che 15 è il resto massimo, quindi più in là di F non vai.

Questo passo rende inutile la catena di if, per collegare il resto al carattere desiderato.

Al termine del while, inserisco nell'array delle cifre il carattere terminatore, inverto la stringa e la stampo.

Dheed
13-01-2010, 22:35
Molte grazie :stordita:

MItaly
13-01-2010, 23:11
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.


#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:


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

YuYevon
14-01-2010, 09:27
#include <stdio.h>

int main(void)
{
int numero;

printf("Immettere un numero decimale: ");
scanf("%d", &numero);

printf("%d in esadecimale è %x\n", numero, numero);

puts("1o1");

return 0;
}

MItaly
14-01-2010, 09:32
Be', ma così siamo capaci tutti... credo che lo scopo dell'esercizio fosse un altro. :D

YuYevon
14-01-2010, 09:37
Originariamente inviato da MItaly
Be', ma così siamo capaci tutti... credo che lo scopo dell'esercizio fosse un altro. :D

Certo MItaly, ma con 1o1 intendevo 1o1 :D

Ho postato questa sciocchezza (che in realtà è stato il mio secondo programma in C dopo l'hello world) solo perché ormai la discussione era conclusa


Originariamente inviato da Dheed
Molte grazie

e tu avevi parlato di "semplificazione" :)

MItaly
14-01-2010, 10:13
Originariamente inviato da YuYevon
Certo MItaly, ma con 1o1 intendevo 1o1 :D

Certo, infatti anch'io ero ironico. :)


Ho postato questa sciocchezza (che in realtà è stato il mio secondo programma in C dopo l'hello world)
Quanti anni fa? :zizi:


e tu avevi parlato di "semplificazione" :)
:D

Dheed
14-01-2010, 13:17
Se no ho provato quasta soluzione:


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

int main (int argc, char** argv)
{
char strnum[10];
int cont=0;
int num;
int rest;
do{
printf("Inserisci un numero intero positivo: ");
scanf("%d",&num);
fflush(stdin);
system("cls");
printf("Il numero %d in base esadecimale e' ",num);
}
while(num<0);
while(num>1){
rest = num%16;
switch(rest){
case 10:
strnum[cont++]='A';
break;
case 11:
strnum[cont++]='B';
break;
case 12:
strnum[cont++]='C';
break;
case 13:
strnum[cont++]='D';
break;
case 14:
strnum[cont++]='E';
break;
case 15:
strnum[cont++]='F';
break;
default:
strnum[cont++]='0'+rest;
}
num/=16;
}
while(--cont>=0){
printf("%c",strnum[cont]);
}
printf("\n");
getchar ();
return 0;
}

Loading