Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - tema esame
Forum - C/C++ - tema esame

Avatar
il-david (Normal User)
Newbie


Messaggi: 10
Iscritto: 22/12/2009

Segnala al moderatore
Postato alle 11:01
Martedì, 22/12/2009
Buongiorno a tutti. Sono uno studente di Ing. dell'Informazione e tra 3 settimane circa ho l'esame di Fondamenti. Sto sbattendo da un pò di giorni su questa traccia d'esame:

1-Scrivere una funzione in C che riceve in input 2 interi(b e n con n>0 e 2<=b<=36) . La funzione stampa a video i numeri da 0 a n allineati a destra e su 2 colonne, espressi con la base indicata da b utilizzando, a seconda di b, i simboli 0,1,2...,9,a,b,c,....,z
Es.
b=3, n= 7
0  1
2  10
11 12
20 21

Questo è un mio abbozzo, ma non funzionante:
Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. void f(int b, int n);
  5.  
  6. int main()
  7. {
  8.    int base, numero;
  9.    
  10.    printf("Inserisci la base: ");
  11.    scanf("%d", &base);
  12.    printf("\nInserisci il numero: ");
  13.    scanf("%d", &numero);
  14.    printf("\n");
  15.    
  16.    f(base, numero);
  17.    
  18.    system("pause");
  19.    return 0;
  20. }
  21.  
  22. void f(int b, int n) {
  23.    int i, j, k, r[8], z, **m;   /* r è il vettore che contiene i numeri      
  24.                                         convertiti su  8 bit */
  25.  
  26.    if(n>0 && b>=2 && b<=36) {
  27.       m=(int**)malloc(((n/2)+1)*sizeof(int*));
  28.       for(i=0; i<((n/2)+1); i++)
  29.          m[i]=(int*)malloc(2*sizeof(int));
  30.      
  31.       z=0;
  32.       r[0]=(n%b);
  33.       k=n/b;
  34.       while(k!=0) {
  35.          z++;
  36.          r[z]=(k%b);
  37.          k/=b;
  38.          }
  39.      
  40.       for(i=0; i<((n/2)+1); i++) {
  41.          for(j=0; j<2; i++) {
  42.             for(z=8; z=0; z--)
  43.                m[i][j]=r[z];
  44.             printf("%d", m[i][j]);
  45.          }
  46.          printf("\n");
  47.       }
  48.    }
  49. }



2- Il secondo esercizio è in C++ e lo posto nell'apposita sezione(http://www.pierotofy.it/pages/extras/forum/viewtopic.php?i ...

Vi ringrazio di cuore e vi auguro buone feste:k:

Ultima modifica effettuata da il-david il 22/12/2009 alle 11:08
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 0:26
Mercoledì, 23/12/2009
Ma questo:

Codice sorgente - presumibilmente C/C++

  1. void f(int b, int n) {
  2.    int i, j, k, r[8], z, **m;   /* r è il vettore che contiene i numeri      
  3.                                         convertiti su  8 bit */
  4.  
  5.    if(n>0 && b>=2 && b<=36) {
  6.       m=(int**)malloc(((n/2)+1)*sizeof(int*));
  7.       for(i=0; i<((n/2)+1); i++)
  8.          m[i]=(int*)malloc(2*sizeof(int));
  9.      
  10.       z=0;
  11.       r[0]=(n%b);
  12.       k=n/b;
  13.       while(k!=0) {
  14.          z++;
  15.          r[z]=(k%b);
  16.          k/=b;
  17.          }
  18.      
  19.       for(i=0; i<((n/2)+1); i++) {
  20.          for(j=0; j<2; i++) {
  21.             for(z=8; z=0; z--)
  22.                m[i][j]=r[z];
  23.             printf("%d", m[i][j]);
  24.          }
  25.          printf("\n");
  26.       }
  27.    }
  28. }



Come l'hai tirato fuori? Se mi hai fatto copia-incolla da appunti misti che hai trovato non va mica bene... cosa esattamente non funziona? Hai capito come deve funzionare l'algoritmo?

Comunque per non reinventare la ruota suggerirei di dare un'occhiata alla funzione ltoa. http://www.cs.usyd.edu.au/~kev/pp/RESOURCES/cplusplus/ref/ ...

Ultima modifica effettuata da pierotofy il 23/12/2009 alle 0:29


Il mio blog: https://piero.dev
PM Quote
Avatar
il-david (Normal User)
Newbie


Messaggi: 10
Iscritto: 22/12/2009

Segnala al moderatore
Postato alle 14:47
Giovedì, 24/12/2009
Quell'algoritmo l'avevo elaborato io prendendo spunto da ricerche sul web.
Ora ho modificato il codice utilizzando la funzione che mi hai suggerito ma ancora nulla, non trovo l'inghippo:(

Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. void f(int b, int n);
  5.  
  6. int main()
  7. {
  8.    int base, numero;
  9.    
  10.    printf("Inserisci la base: ");
  11.    scanf("%d", &base);
  12.    printf("\nInserisci il numero: ");
  13.    scanf("%d", &numero);
  14.    printf("\n");
  15.    
  16.    f(base, numero);
  17.    
  18.    system("pause");
  19.    return 0;
  20. }
  21.  
  22. void f(int b, int n) {
  23.    int i, j, k;
  24.    char buffer [sizeof(long)*8+1], **m;
  25.  
  26.    if(n>0 && b>=2 && b<=36) {
  27.       m=(char**)malloc(((n/2)+1)*sizeof(char*));
  28.       for(i=0; i<((n/2)+1); i++)
  29.          m[i]=(char*)malloc(2*sizeof(char));
  30.      
  31.       for(i=0; i<((n/2)+1); i++) {
  32.          for(j=0; j<2; i++) {
  33.             for(k=0; k<=n; k++) {
  34.                ltoa (k,buffer,b);
  35.                m[i][j]=*buffer;
  36.             }
  37.             printf("\t%s", m[i][j]);
  38.          }
  39.          printf("\n");
  40.       }
  41.    }
  42. }


PM Quote
Avatar
Zonzo (Ex-Member)
Rookie


Messaggi: 34
Iscritto: 21/04/2008

Segnala al moderatore
Postato alle 12:16
Mercoledì, 06/01/2010
Il problema della conversione nei sistemi di numerazione possiamo benissimo gestirlo con una semplice ricorsione in modo da ridurre quel pasticcio che hai fatto nella funzione f().
Esempio: Un numero in base 10 per essere convertito in un'altra base, deve essere diviso per la base e il resto della divisione deve essere "conservato", perché rappresenta un valore del numero nell'altro sistema di numerazione.
Il classico esempio è quello in base 2, ovvero in codice binario.
Se volessimo trasformare il numero 52 base 10 in base 2 l'operazione da effettuare è la seguente:

52  /  2  =  26 resto 0  ^
26  /  2  =  13 resto 0  |
13  /  2  =  6  resto 1  |
6   /  2  =  3  resto 0  |
3   /  2  =  1  resto 1  |
1   /  2  =  0  resto 0  |

Quando la divisione da come quoziente il valore 0, l'operazione di conversione è finita.
Se volessimo generalizzare questo algoritmo ad una qualsiasi base avremo che:

n   /  b  = Div(n/b) resto Mod(n/b)

finché Mod(n/b) = 0 , ovvero in altri termini finché n<b.
se volessimo trascrivere questo algoritmo ricorsivamente, dobbiamo individuare:

Condizione:
   Caso banale
Altirmenti:
   Caso ricorsivo

La condizione l'abbiamo già individuata ed è:

Codice sorgente - presumibilmente C/C++

  1. if(Num<Base)
  2. //Caso Banale
  3. else
  4. //Caso ricorsivo



Il caso banale cioè quello che termina il flusso ricorsivo della funzione è la stampa di Num, infatti il resto di una qualsiasi divisione che abbia come dividendo un numero minore del divisore è il dividendo stesso.
Quindi:
Codice sorgente - presumibilmente C++

  1. void Convert(int Num, int Base)
  2. {      
  3.       if(Num<Base)
  4.       {
  5.       if(Num%Base>9)
  6.           printf("%c",(Num-10)+65);
  7.       else
  8.           printf("%d",Num);
  9.       }
  10.       else
  11.       {
  12.       //Caso ricorsivo
  13.       }
  14. }



Dato che le basi sono comprese tra 2 e 36, si utilizzeranno esattamente 10 numeri (da 0 a 9) e 26 lettere (da A a Z) quindi se il resto supera il 9 ovvero se non ci troviamo più in base 10 dobbiamo stampare a video le lettere dell'alfabeto.
Io l'ho fatto con un piccolo artificio.
Codice sorgente - presumibilmente Plain Text

  1. printf("%c",(Num-10)+65);


Ora rimane solamente il caso ricorsivo.
Se il quoziente è ancora diverso da zero allora dobbiamo dividere ancora il Num per la base, e lo facciamo rifare dalla nostra funzione.
passandogli come parametri Convert(Num/base,base), ovvero il quoziente della divisione Num/Base.
Quindi infine l'algoritmo è il seguente.
Codice sorgente - presumibilmente C++

  1. void Convert(int Num, int Base)
  2. {      
  3.       if(Num<Base)
  4.       {
  5.       if(Num%Base>9)
  6.           printf("%c",(Num-10)+65);
  7.       else
  8.           printf("%d",Num);
  9.       }
  10.       else
  11.       {
  12.       Convert((Num/Base),Base);
  13.       if(Num%Base>9)
  14.           printf("%c",((Num%Base)-10)+65);
  15.       else
  16.           printf("%d",Num%Base);
  17.       }
  18. }


Lo stesso artificio per la stampa delle lettere che ho usato nel caso banale l'ho riutilizzato nel caso ricorsivo.
Ora come tutti sanno che tutti i resti della divisione vanno presi nell'ordine dal "basso all' alto" come per l'esempio della base 2 che ho fatto sopra.
Quindi la stampa la inseriamo dopo aver chiamato Convert(), e di conseguenza le stampe saranno in ordine inverso alle operazioni effettuate perché quando chiamiamo la prima volta la funzione Convert() si interrompe, richiama se stessa però effettuando una seconda Convert() (salvata in un'altra zona di memoria) e quindi la prima deve ancora terminare e aspetta che la seconda finisca e questo aspettare dura finchè non si arriva al caso banale. Questo è più o meno la filosofia alla base della ricorsione.

In pratica il tuo programma finale è questo:
Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. void Convert(int Num, int Base);
  5.  
  6. int main()
  7. {
  8.    int i,b,n;
  9.    
  10.    do{
  11.    system("cls");
  12.    printf("Inserisci la base(2<=b<=36): ");
  13.    scanf("%d", &b);
  14.    }while(b<2 || b>36);
  15.    
  16.    do{
  17.    system("cls");
  18.    printf("Inserisci il numero(n>0): ");
  19.    scanf("%d", &n);
  20.    }while(n<=0 );
  21.    
  22.    for(i=0;i<=n;i++)
  23.    {
  24.    printf("%4d in base %d = ",i,b);
  25.    Convert(i,b);
  26.    printf("\n");
  27.    }
  28.    
  29.    system("pause");
  30.    return 0;
  31. }
  32.  
  33. void Convert(int Num, int Base)
  34. {      
  35.       if(Num<Base)
  36.       {
  37.       if(Num%Base>9)
  38.           printf("%c",(Num-10)+65);
  39.       else
  40.           printf("%d",Num);
  41.       }
  42.       else
  43.       {
  44.       Convert((Num/Base),Base);
  45.       if(Num%Base>9)
  46.           printf("%c",((Num%Base)-10)+65);
  47.       else
  48.           printf("%d",Num%Base);
  49.       }
  50. }


Questa funzione già esiste in C e si chiama itoa() ed ha il seguente prototipo:
char *itoa(int num,char*str,int base)
E assegna al valore puntato da str il risultato della conversione di num nella base indicata sempre tra 2 e 36 proprio come il tuo programma.
Siccome siamo qui per capire il procedimento ho voluto spiegarlo.
Però non ho capito cosa intendi per allineamento a destra, ma se riesci a farlo è bene. Altrimenti puoi chiarire cosa vuoi e vedo se posso aiutarti.


Ultima modifica effettuata da Zonzo il 06/01/2010 alle 12:57
PM Quote
Avatar
il-david (Normal User)
Newbie


Messaggi: 10
Iscritto: 22/12/2009

Segnala al moderatore
Postato alle 19:06
Sabato, 09/01/2010
Grazie mille:)

PM Quote