OBIETTIVO DELLA LEZIONE
Capire come si scrivono programmi corretti, leggibili, portabili e di facile manutenzione.
Capire il controllo di programma
Esercizio Istruzioni ed espressioni
Individuate le espressioni e le istruzioni nel codice sottostante
#include <stdio.h> int main() { char sex; int eta; printf("Inserire il proprio sesso:\n M sta per maschio:\n F sta per femmina:\n"); scanf("%c", &sex); printf("Inserire l'eta\n"); scanf("%d", &eta); if((sex=='M') || (sex=='m')) printf("Sei un maschio e hai %d anni", eta); else printf("Sei una femmina e hai %d anni",eta - 1); // sconto per signore printf("\n\nPremi un tasto per uscire"); fflush(stdin); getchar(); // trucco per far rimanere aperta la finestra di testo }
int a, b; .... { int temp; temp = a; a = b; b = temp; } /*qui la variabile temp cessa di esistere*/Gli unici blocchi che usiamo sono quelli che vedremo negli if, for e while
... temp = a; a = b; b = temp; // banale sequenza di inversione del valore di due variabili // se inverti la sequenza potresti perdere il valore di una delle due variabili ...
if (espressione) istruzione1oppure
if (espressione) istruzione1 else istruzione2oppure
if (expr1) istr1 else if (expr2) istr2 else if (expr3) istr3 else if (expr4) istr4ricordando che le istruzioni terminano con il ;
// conteggio dei tipi di caratteri char c; int n_cifre, n_separatori, n_altri; ... c = ....; // sia c il carattere da esaminare switch (c) { case '0': n_cifre = n_cifre + 1; break; case '1': n_cifre = n_cifre + 1; break; ..... case '9': n_cifre = n_cifre + 1; break; case ' ': n_separatori = n_separatori + 1; break; case '\n': n_separatori = n_separatori + 1; break; case '\t': n_separatori = n_separatori + 1; break; default: n_altri++; } ... altre
while (espressione) istruzioneoppure
while (espressione) { istruzione1 istruzione2 .... istruzionen }
for ( expr1 ; expr2 ; expr3 ) istruzioneoppure
for ( expr1 ; expr2 ; expr3 ) { istruzione1 istruzione2 .... istruzionen }
expr1; while (expr2) { istruzione1 istruzione2 .... istruzionen expr3; }Di solito expr1 inizializza un contatore (i = 1 ;)
for ( i=1 ; i<=10 ; i=i+1 ) { istruzione1 istruzione2 .... printf(" Indice = %d" , i); }
Esercizio Iterazioni
Sincerarsi che i due blocchi di codice SONO EQUIVALENTI simulando l'output del programma su carta
... for ( i=1 ; i<=10 ; i=i+1 ) { printf(" Indice = %d" , i); } ... i=1; while (i<=10) { printf(" Indice = %d" , i); i=i+1; }
Esercizio ALLOCAZIONE MEMORIA tipi di dato built in
Allochiamo variabili dei diversi tipi e semplicemente stampiamo con printf il loro indirizzo di memoria
Ricordo che "d" stampa un numero come un intero e "p" lo stampa in esadecimale
(Es: 0x00000A e' 10 )
// Occupazione di memoria dei tipi di dato .... include int main() { char c1; char c2; char c3; char c4; int i1; int i2; int i3; int i4; long l1; long l2; long l3; long l4; double d1; double d2; double d3; double d4; // SOLO per stavolta non inizializziamo le celle di memoria printf("\n********************************************\n"); printf("* Occupazione in memoria \n"); printf("********************************************\n\n"); printf(" il char c1 si trova in 0x %p (%d) \n", &c1 , &c1); printf(" il char c2 si trova in 0x %p (%d) \n", &c2 , &c2 ); printf(" il char c3 si trova in 0x %p (%d) \n", &c3 , &c3 ); printf(" il char c4 si trova in 0x %p (%d) \n", &c4 , &c4 ); printf(" l' int i1 si trova in 0x %p (%d) \n", &i1 , &i1 ); printf(" l' int i1 si trova in 0x %p (%d) \n", &i2 , &i2 ); printf(" l' int i1 si trova in 0x %p (%d) \n", &i3 , &i3 ); printf(" l' int i1 si trova in 0x %p (%d) \n", &i4 , &i4 ); printf(" il long l1 si trova in 0x %p (%d) \n", &l1 , &l1); printf(" il long l2 si trova in 0x %p (%d) \n", &l2 , &l2 ); printf(" il long l3 si trova in 0x %p (%d) \n", &l3 , &l3 ); printf(" il long l4 si trova in 0x %p (%d) \n", &l4 , &l4 ); printf(" il double d1 si trova in 0x %p (%d) \n", &d1 , &d1); printf(" il double d2 si trova in 0x %p (%d) \n", &d2 , &d2 ); printf(" il double d3 si trova in 0x %p (%d) \n", &d3 , &d3 ); printf(" il double d4 si trova in 0x %p (%d) \n", &d4 , &d4 ); getchar(); }
...... a = b = c = d + 1; // NOOO a = ( b = (c = d + 1)); // si !! a [x = n *2, y = n++] = (b = 27) + (c = (f = e - 3)); // ok hai usato le parentesi... // magari pero' e' meglio usare piu' righe....
// un esempio: CAMERA CAFE ... int no_caffe; int no_bicchieri; ... no_caffe = controlla_prenza_cialde(); no_bicchieri = controlla_bicchieri(); if ( no_caffe' || no_bicchieri ) { accendi_spia_errore (); manda_sms_assistenza(" Aiuto, mandare rifornimenti !"); } ....
Esercizio 1 (Occupazione in memoria dei tipi di dato)
1) Usando NOTEPAD, creare il file memoria.c copiando il programma nell'esercizio visto a lezione e compilarlo con DEV-C
Verificare cosa cambia sulla macchina in laboratorio rispetto all'esempio visto a lezione
2) Modificare il programma e stampare il CONTENUTO di una cella int, char, long, double come i parametri "%p" "%d" della printf.
Perche' ci sono dentro dei valori se nessuno ha inizializzato le celle? Cosa significano quei valori?
Esercizio 2 (DEBUG)
1) Debuggare il programma memoria.c verificando con addwatch se le variabili stanno EFFETTIVAMENTE AGLI INDIRIZZI DI MEMORIA stampati nell'esercizio precedente.
2) Se una cella contiene un byte quanto secondo te e' grande la memoria disponibile al programma?
3) E se una cella contenesse invece 32 bit?
Esercizio 3
Usando NOTEPAD, creare il file capitale1.c copiando il programma sotto riportato e compilarlo con DEV-C
E' necessario capire perche' se usiamo il tipo di dato intero per la variabile interesse, il calcolo dell'interesse non avviene in modo corretto
//Capitalizzazione Annua fatta con interi #include <stdio.h> #include <stdlib.h> /* Ecco una definizione di una costante se servisse #define N_MAX 10 */ /* Sin puo' commentare UNA RIGA anche cosi //mio commento...... */ // ecco qui un esempio void main() { int conto; int interesse; // double num_random; // il carattere '\n' semplicemente manda a capo printf("\n********************************************"); printf("\n* Capitalizzazione del mio conto corrente\n"); printf("\n********************************************\n"); //Stampo le istruzioni per l'utente printf("\nValore del conto all'inizio dell'anno:\n"); scanf("%d",&conto); // Cosa fa scanf? // Prende i caratteri che mi passa l'utente prima del suo "enter" // li legge come un numero (la modalita' "%d") e li mette // all'indirizzo della variabile conto (modalita' &NomeVariabile) // INFATTI VOGLIO SAPERE DOVE SCRIVERE il numero dato dall'utente (&conto) // e non me faccio nulla di quanto vale il conto adesso (conto) // infatti scanf("%d", conto); sarebbe SBAGLIATO!!!! printf("\nInserire l'interesse della banca annuale\n"); scanf("%d",&interesse); // faccio notare che questa volta non INIZIALIZZO le // variabili perche' me le ha passate proprio l'utente // e con scanf ho messo i valori proprio nelle celle di memoria giuste // IN UN CERTO SENSO SONO STATE INIZIALIZZATE DALL'UTENTE //calcolo il risultato in capitalizzazione annua conto = conto * (1 + interesse/100 ); //Stampo il risultato passando del "buco per interi" %d il VALORE della variabile conto printf("\nValore del conto all'FINE dell'anno (CAP. ANNUA): %d \n", conto ); printf("\n********************************************\n\n"); // Discussione sul tipo di dato. // Ci chiediamo infatti, ma un coefficiente (tipo 0.01) puo' essere // rappresentato come un intero (1,2,312, ....) ?? // Ovviamente no allora FORZO il rapporto di interi venga visto come // un numero che possa essere frazionario (il tipo float) // conto = conto * (1 + interesse/100 ); diventa // conto = conto * (1 + (float) interesse/100 ); printf("\nSe invece il coeffic. \n(1 + interesse/100 ) \n lo uso come un float (doppia precisione)....)\n"); conto = conto * (1 + (float)interesse/100 ); //Stampo il risultato passando del "buco per interi" %d il VALORE della variabile conto printf("\nValore del conto all'FINE dell'anno (CAP. ANNUA): %d \n", conto ); printf("\n********************************************\n\n"); }
Esercizio 4
Svolgere gli esercizi contenuti nei due file seguenti (seguire i commenti riportati nei files): Capitale2.c e Capitale3.c.
Esercizio 5: IMPORTANTE (DEBUG)
1) Debuggare il programma Capitale4Bacato.c finche' non sia possibile compilarlo
2) Verificarne il funzionamento (ok si compila, ma produce uscite corrette?).
Esercizio PER CASA
Questo è un esercizio per casa. E' importante che tu lo svolga PRIMA della prossima lezione. Se hai già finito gli altri esercizi assegnati per oggi pomeriggio, lo puoi iniziare anche ora.
Svolgere gli esercizi contenuti nei seguenti files: Capitale5COMPITO.c, AnniBisestili.c, EquazioniSecondoGrado.c e Media.c.
©2003 Roberto Sassi