OBIETTIVO DELLA LEZIONE
- Conoscere approfonditamente l'uso dei tipi di dato nella programmazione
- Essere in grado di utilizzare adeguatamente vettori, matrici, stringhe
int x[100];
Definisce un array x costituito da 100 numeri interi.
Che spazio occupa nella memoria? Lo spazio occupato da 100 numeri interi
(400byte). x e' l'etichetta della prima cella di memoria.
...
for(i=0; i<100; i++) x[i]=i+1;
...
char s[6];
s[0]='C';
s[1]='r';
s[2]='e';
s[3]='m';
s[4]='a';
s[5]='\0';
Nota che la stringa s e' composta da 6 caratteri.
Il terminatore di stringa e' un carattere come gli altri!
Il simbolo '\0' assomiglia a quello che usiamo per andare a
capo '\n'.
char s[]="Laboratorio di Informatica applicata";
E' un esempio di array non dimensionato a cui si assegna una costante stringa. ATTENZIONE:
La costante stringa "M" è diversa dal carattere 'M' ! "M" e' composta da due caratteri: ''M'+'\0' |
printf("Il risultato di i=x+3 e' %d" , i);
#include <stdio.h> main() { char s[128]; // strcpy(s_to,s_from) copia la stringa s_from in s_to // fino a quando trova un terminatore di stringa strcpy(s,"Laboratorio di Informatica applicata"); printf("%s",s); }Non fare lavoro inutile: se c'e' una funzione gia' pronta usala!
Esercizio Array in memoria
Che indirizzo hanno le celle di un array?
main() { int i, x[100]; for(i=0; i<100; i++) x[i]=i+1; printf("Il valore di x e' %d\n", x); printf("Il valore di x[0] e' %d\n", x[0]); printf("L'indirizzo di x[0] e' %d\n", &x[0]); printf("Il valore di x[99] e' %d\n", x[99]); printf("L'indirizzo di x[99] e' %d\n", &x[99]); printf("La memoria occupata dal vettore e' %d\n", (void *)&x[99]+sizeof(int)-(void *)&x[0]); }
#define TOTALE = 5 // Ecco un'etichetta // 1) Le etichette vanno qui, prima del main (per motivi di buona programmazione) // 2) Non termina con punto e virgola // 3) Le etichette non sono variabili, non vengono allocate in memoria! // 4) Il precompilatore (prima della compilazione) sostituisce nel programma la stringa TOTALE con la stringa 5. // Tutte le etichette dopo la precompilazione SPARISCONO !! ... int main() char c; int intero; const float pi = 3.14; // Ecco una costante !! // 1) Va qui necess. sotto il main ma prima della parte esecutiva // 2) E' una variabile come tutte le altre, e' definita con un tipo ed un valore // 3) Non e' possibile assegnare un nuovo valore ad una costante
Rileggi velocemente il riassunto della lezione di stamattina che trovi in questa pagina (sezione Note). I costrutti presentati saranno molto utili per risolvere gli esercizi di oggi.
Esercizio 1 (Allocazione in memoria dei tipi di dato)
1. Usando NOTEPAD, creare il file memoria.c copiando il programma sotto riportato
Rendilo funzionante modificandolo opportunamente e poi compilalo con DEV-C: verifica cosa cambia sul tuo elaboratore rispetto alla figura sottostante?
// Occupazione di memoria dei tipi di dato .... include int main() { char c1 = 'a'; char c2 = 97 ; char c3; char c4; int i1 = 1 ; int i2 = 1.0; int i3; int i4; long l1 = 1 ; long l2 = 1.0; long l3; long l4; double d1 = 1.0; double d2 = 1; 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(); return 0 ; }2. Aggiungi le necessarie righe di codice per stampare il CONTENUTO di una cella int, char, long, double con i parametri "%p" "%d" della printf.
- Perchè nelle celle di memoria sono presenti dei valori se le celle non sono state inizializzate?
- Cosa rappresentano quei valori?
Suggerimento:
1. Aggiunti gli include mancanti e compilato il codice, potrai notare quanto segue:
- la base di partenza degli indirizzi può essere diversa ma la distanza fra le celle di memoria rimane costante;
- il compilatore alloca le celle di memoria seguendo l'ordine con cui le variabili sono dichiarate nel codice.
2. Le celle di memoria contengono sempre dei valori, o dal momento di accensione dell'elaboratore (valori casuali) , oppure possono provenire da precedenti allocazioni di altri programmi caricati dal sistema operativo nelle medesime celle di memoria.
soluzione.
Esercizio 2 (Ripasso teoria tipi di dato BUILT-IN)
Prova a rispondere alle seguenti domande.
Se non trovi le risposte o non sei sicuro, rivedi la lezione.
-------------------------------------------------------------------------------- 1. Qualunque dato allocato in un programma C in esecuzione è semplicemente un insieme di bit: - sì - no -------------------------------------------------------------------------------- 2. Una variabile carattere memorizzata in un programma C in realtà è scritta come un numero intero: - no - sì -------------------------------------------------------------------------------- 3. Quale delle seguenti parole riservate serve per dichiarare variabili di tipo built-in? - if - union - enum - void - double
Esercizio 3: Studio dei caratteri
Completa il programma sotto riportato e prova ad eseguire le istruzioni di seguito elencate:
- utilizzando delle printf con il segnaposto %c e il segnaposto %d e passando la variabile c1 dimostra che un carattere è memorizzato come un numero intero;
- evidenzia l' occupazione di memoria delle variabili di tipo carattere stampando gli indirizzi delle celle c1, c2 e c3 e controllando quanto distano l'una dall'altra;
- visualizza il carattere come float usando le opportune opzioni della printf.
// Occupazione di memoria dei tipi di dato CARATTERE ... include ... int main() { char c1; char c2; char c3; c1 = 'a'; c2 = 62; // e' corretto? // visualizza il carattere come carattere // visualizza il carattere come intero // stampa gli indirizzi di memoria delle celle // visualizza il carattere come float getchar(); return 0 ; }soluzione.
Esercizio 4: Calcolo interessi su un contro corrente. Errori derivanti da un errato uso dei tipi di dato
Usando NOTEPAD, creare il file capitale1.c copiando il programma sotto riportato e compilandolo con DEV-C.
Esegui i seguenti controlli utilizzando il programma che hai compilato.
- Immagina di depositare 1000 euro sul tuo c/c con il 10% di interesse annuo a capitalizzazione annua: quanto avrai alla fine dell'anno (montante)?
- Immagina di depositare 1001 euro sul tuo c/c con il 10% di interesse annuo a capitalizzazione annua: quanto avrai alla fine dell'anno (montante)?
- Immagina di depositare 1 euro sul tuo c/c con il 10% di interesse annuo a capitalizzazione annua: quanto avrai alla fine dell'anno (montante)?
//Capitalizzazione Annua fatta con interi ... include ... int main() { int conto; int interesse; // 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); printf("\nInserire l'interesse della banca annuale\n"); scanf("%d",&interesse); // calcolo il risultato in capitalizzazione annua conto = conto * (1 + interesse/100 ); // Stampo il risultato passando del "segnaposto per interi" %d // il VALORE della variabile conto printf("\nValore del conto alla 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 "segnaposto per interi" %d // il VALORE della variabile conto printf("\nValore del conto alla FINE dell'anno (CAP. ANNUA): %d \n", conto ); printf("\n********************************************\n\n"); fflush(stnin); getchar(); return 0 ; } E' di estrema importanza comprendere perché se si utilizza il tipo di dato intero per la variabile interessi, il calcolo degli stessi avviene in modo errato.soluzione.
Esercizio 5: Calcolo interessi su base trimestrale
Usando NOTEPAD, creare il file capitale2.c copiando il programma sotto riportato e compilandolo con DEV-C.
Esegui i seguenti controlli utilizzando il programma che hai compilato.
- controllane la correttezza nel caso della capitalizzazione degli interessi su base trimestrale;
- esegui le eventuali modifiche al codice;
- compila il programma con DEV-C;
- individua degli adeguati dati di prova ed effettua il testing di correttezza del programma.
... include.... //Capitalizzazione fatta con float // void main() non verra' piu' impiegato nelle prossime versioni del codice, // useremo "int main()" // e, prima della graffa finale del main, return 0; // In questo modo il main diventa una funzione che ritorna 0. int main() { float contoIniziale; float conto; float interesse; int i; //l'indice per i nostri cicli for 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("%f",&contoIniziale); conto=contoIniziale; // INIZIALIZZO LA VARIABILE // dopo prova a togliere questa riga e vedi cosa succede a non inizializzare // le variabili..... printf("\nInserire l'interesse della banca annuale\n"); scanf("%f",&interesse); // se lascio due buchi nella stringa di controllo " bla bla %d bla %d " // posso copiare per valore due variabili printf("conto: %6.2f, interesse ANNUALE : %6.2f \n", conto, interesse); //calcolo il risultato in capitalizzazione annua conto = contoIniziale * (1 + interesse / 100 ); // adesso non ho problemi, sono tutti float!! printf("\n Valore del conto alla FINE dell'anno (CAP. ANNUA): %6.2f \n", conto ); // posso far vere solo le cifre prima e dopo la virgola che voglio io... // facciamo vedere 6 cifre di cui due dopo il punto per i centesimi // usando %6.2f SEMPLICE !!! /******** capitalizzazione trimestrale **********/ conto= contoIniziale; // Osservazione : senza la riga sopra il codice non era corretto // perche' in conto avevamo gia' il conto capitalizzato NON L'INIZIALE for (i=1; i<=5; i=i+1) { conto = conto * (1 + interesse / 100 * 3 / 12 ); // abbasso il tasso di interesse al quello trimestrale } printf("\n Valore del conto alla FINE dell'anno (CAP. TRIMESTRALE): %6.2f \n", conto ); /******** capitalizzazione quotidiana (Tipico Conto On-line) **********/ conto= contoIniziale; for (i=1; i<366; i=i+1) { conto = conto * (1 + interesse / 100 * 1 / 365 ); // abbasso il tasso di interesse a quello quotidiano } printf("\n Valore del conto alla FINE dell'anno (CAP. QUOTIDIANA): %6.2f \n", conto ); printf("\n********************************************\n\n"); fflush(stnin); getchar(); return 0 ; }soluzione.
Esercizio 6: DEBUG programma interessi
Usando NOTEPAD, creare il file capitale3.c copiando il programma sotto riportato
- controllane la correttezza nel caso della capitalizzazione degli interessi su base trimestrale;
- esegui le eventuali modifiche al codice;
- compila il programma con DEV-C;
- individua degli adeguati dati di prova ed effettua il testing di correttezza del programma.
#include <stdio.h> #include <stdlib.h> //Capitalizzazione Trimestrale fatta con float // IL PROGRAMMA E' VOLUTAMENTE BACATO (4 errori....) // ATTENZIONE GLI ERRORI DEL COMPILATORE SUCCESSIVI // AL PRIMO POTREBBERO INGANNARVI.... // METTETE A POSTO IL CODICE PARTENDO DALL'INIZIO int main() { float contoIniziale; float conto; float interesse; int i; //l'indice per i nostri cicli for printf("\nValore del conto all'inizio dell'anno:\n"); scanf("%f",&contoIniziale); conto=contoIniziale printf("\nInserire l'interesse della banca annuale\n"); scanf("%f",&interesse); conto = contoIniziale * (1 + interesse / 100 ); /******** capitalizzazione trimestrale **********/ conto= contoIniziale; for (i=1; i<5; i=i+1;) { // abbasso il tasso di interesse al quello trimestrale conto = conto * (1 + interesse / 100 * 4 / 12 ); } printf("\n Valore del conto all'FINE dell'anno (CAP. TRIMESTRALE): %6.2f \n", conto ); printf("\n********************************************\n\n"); getchar(); return 0 ; }soluzione.
Esercizio 7 (Array)
Usando la seguente traccia
// stampavettore.c include... int main() { int B[5]; B[0]= 4; B[1]= 3; B[2]= 2; B[3]= 1; B[4]= 0; // aggiungi il codice che manca (1 ciclo for contenente una printf) }Salva il tuo programma con il nome di stampavettore.c. Scrivi il codice che permette di visualizzare l'array B producendo a monitor il seguente output:L'elemento 0 del vettore B contiene 4 L'elemento 1 del vettore B contiene 3 L'elemento 2 del vettore B contiene 2 L'elemento 3 del vettore B contiene 1 L'elemento 4 del vettore B contiene 0soluzione.
Esercizio 8 (Potenze)
Usando la seguente traccia
//potenze.c include .. #define N 9 //perche' servono 9 celle ? int main() { int P[N]; // scrivi qui il ciclo che calcola le potenze // attento! per calcolare una SINGOLA potenza TOT di 2 // serve fare TOT volte una moltiplicazione // scrivi qui il ciclo che stampa l'array. // NON MISCHIARE MAI IL CALCOLO DEI DATI CON LA LORO VISUALIZZAZIONE // MAGARI METTENDO TUTTO IL CODICE IN UNICO CICLO FOR // NON SEPARARE DISTINTAMENTE LE FASI DEL TUO PROGRAMMA TOGLIE PUNTI ALL'ESAME }scrivi il codice che :1) calcola le potenze di 2 di ordine da 0 a 8; 2) memorizza i valori delle potenze nell'array P; 3) stampa tutti gli elementi dell'array P.Il programma deve produrre a monitor il seguente output:TABELLA DELLE POTENZE DI 2 2 elevato alla 0 e' -->1 2 elevato alla 1 e' -->2 2 elevato alla 2 e' -->4 ... 2 elevato alla 8 e' -->256Salva il tuo programma con il nome di potenze.c.soluzione.
Esercizio 9 (Matrici)
Usando la seguente traccia
// inizializzaMatrice1.c #include <stdio.h> #include <stdlib.h> int main() { int A1[2][3] = { {1 ,2, 3} , {4, 5 , 6} } ; int A2[2][3] = { 1 ,2, 3 , 4, 5 , 6 } ; int A3[2][3] = { {1 ,2 } , {4} } ; // aggiungi qui il ciclo che stampa A1 // aggiungi qui il ciclo che stampa A2 // aggiungi qui il ciclo che stampa A3 }stampa il contenuto delle matrici A1, A2, A3 usando una printf ("%d",…) e due cicli for annidati, producendo a monitor il seguente output:L'array A1 contiene i seguenti valori 1 2 3 4 5 6 L'array A2 contiene i seguenti valori ...Salva il tuo programma con il nome di inizializzaMatrice1.c.soluzione.
Esercizio 10 (Stringhe)
Scrivi il programma immettistringa1.c che presenti i seguenti requisiti:
1) definisce una stringa di 20 caratteri di nome stringa1 2) chiede all'utente di inserire una stringa e la memorizza all'indirizzo di stringa1 scanf("%s", .. ) 3) stampa a monitor stringa1Inoltre, cosa succede se: inserisci più di 20 caratteri o inserisci uno spazio?soluzione.
Esercizio 11 (Inversione stringa)
Scrivi il programma inverti_stringa.c che presenti i seguenti requisiti:
1) dichiara una variabile intera lunghezza ed una stringa s di 30 caratteri 2) inverte la stringa CARATTERE PER CARATTERE con un ciclo 3) stampa la stringa con printf("%s", ..)Attenzione questo programma e' puo' essere in un tema di esame.soluzione.