FILE DI TESTO e SOTTOPROGRAMMI Prof. Enrico Terrone A. S: 2008/09 I file di testo in C++ I file di testo sono una forma di input/output alternativa alla tastiera e al monitor (con il vantaggio della persistenza). Per utilizzare i file di testo in C++ occorre includere la libreria fstream.h (cfr. libro p. 528) Dopo di che, occorre creare degli oggetti di tipo ifstream per l input e ofstream per l output. Es. ifstream fin; // si può usare un nome diverso da fin ofstream fout; // si può usare un nome diverso da fout I file vanno aperti all inizio del main con open (meglio se con controllo di errore) e si chiudono alla fine con close. All interno del programma, fin e fout (o altri nomi usati) si usano con la stessa sintassi di cin e cout.
I file di testo in C++ int main ifstream fin; fin.open( dati.txt ); if (! fin ) cout << Errore apertura file ; [ ] fin.close(); Note: 1) Il file dati.txt deve essere creato con un editor (p. es. notepad) e salvato nella stessa cartella dell eseguibile creato dal compilatore (file.exe). 2) Di solito i file si usano solo nel main, non nei sottoprogrammi. La funzione eof() La funzione eof (acronimo di End Of File) dà come risultato vero se si è giunti alla fine del file, falso in caso contrario. È utile per caricare dati da file quando non si conosce la quantità di elementi. int main ifstream fin; char v[200][20]; int i; fin.open( dati.txt ); for ( i=0;! fin.eof( ); i++ ) fin >> v[i]; [ ] fin.close();
I sottoprogrammi in C++ Un sottoprogramma è un blocco di istruzioni a sé stante con un proprio nome. Il main (= sottoprogramma principale) è un caso particolare di sottoprogramma, che ha la proprietà di essere eseguito all avvio del programma. Gli altri sottoprogrammi sono eseguiti soltanto se richiamati attraverso il main. Definizione Si può pensare il main come un programma-padrone che chiede al proprio sottoprogramma-servo di fare un lavoro particolare. Oppure si può pensare il sottoprogramma come uno strumento che viene costruito e usato nell ambito del programma principale. A sua volta il sottoprogramma può schiavizzare altri sottoprogrammi esattamente come il main schiavizza lui. In generale, possiamo pensare al sottoprogramma come a un istruzione aggiuntiva che viene creata dal programmatore.
La scrittura del sottoprogramma <tipo_risultato> <nome> (<parametri>) // questa parte si chiama intestazione del // sottoprogramma variabili e istruzioni // questa parte si chiama corpo del sottoprogramma Le variabili definite all interno del sottoprogramma esistono e sono visibili soltanto all interno del sottoprogramma (lo stesso discorso vale per il main). Le uniche variabili che permettono al sottoprogramma di comunicare con l esterno sono i parametri. La scrittura del sottoprogramma I parametri sono variabili speciali definite fra parentesi dopo il nome del sottoprogramma: (<tipo_p1> <nome_p1>, <tipo_p2> <nome_p2>, ) Quando si scrive un sottoprogramma, bisogna per prima cosa capire quali sono i parametri (dati del problema che il sottoprogramma deve risolvere) e quali le variabili interne (valori di supporto per la risoluzione del problema); fra le variabili interne, ce ne deve essere una che contiene il risultato del problema; questa variabile sarà infine restituita al programma chiamante attraverso l istruzione: return <espressione del risultato> ;
L uso del sottoprogramma Nel programma-chiamante (che per noi sarà quasi sempre il main), il sottoprogramma può essere usato come se fosse un istruzione aggiuntiva. Quando lo si vuole usare, occorre scrivere il suo nome e indicare dei valori in corrispondenza dei parametri (importante: l associazione valori-parametri è fatta in base alla posizione nella lista). double media (int a, int b) double m; m = (a+b)/2; return m; x = media (n1, n2); L uso del sottoprogramma A questo punto, il programma-chiamante si interrompe e attende l esecuzione del sottoprogramma; quando il sottoprogramma è terminato, il valore da esso calcolato viene sostituito al suo nome e si continua con l esecuzione del programma principale. Perché il programma-chiamante possa usare il sottoprogramma, occorre che nel file il sottoprogramma (o almeno la sua intestazione, che si chiama prototipo ) sia scritto prima del programmachiamante.
Il passaggio dei parametri Ci sono due modalità di passaggio dei parametri: per valore e per riferimento. Per il momento vediamo soltanto la modalità più basilare: il passaggio per valore. Quando il programma-chiamante usa il sottoprogramma, indica il suo nome e fra parentesi una serie di valori. Questi valori vengono usati in base alla loro posizione per dare un valore iniziale ai parametri, che sono le variabili speciali del sottoprogramma. Le funzioni Una funzione è un oggetto matematico che associa a ogni elemento di un insieme A (dominio) uno e un solo elemento di un insieme B (codominio). La funzione matematica può essere rappresentata con una tabella o con un grafico. Nei linguaggi di programmazione, la funzione è realizzata attraverso un sottoprogramma che ha come parametri l elemento (o gli elementi) di A e come risultato l elemento di B corrispondente.
Le funzioni Una funzione si dice booleana se il suo risultato è del tipo vero/falso (in C/C++ si usa solitamente il numero 1 per significare Vero e il numero 0 per significare Falso ). Una funzione si dice ricorsiva se fra le proprie istruzioni contiene anche una chiamata a se stessa. Una funzione ricorsiva deve sempre avere una selezione che permette di scegliere il caso non ricorsivo (altrimenti andrebbe avanti all infinito). Un esempio tipico di funzione ricorsiva è il calcolo del fattoriale. Le procedure Le procedure sono sottoprogrammi che non calcolano un risultato ma producono altri effetti come ad esempio la stampa su schermo o la modifica di variabili. Il tipo del risultato in questo caso viene indicato come void. Perché una procedura possa modificare le variabili, queste devono essere passate per riferimento (argomento che affronteremo in seguito). Nota: un modo semplice per usare un sottoprogramma consiste nel costruire un main che contiene un ciclo do-while che chiede all utente di inserire numeri di prova per il sottoprogramma, e di andare avanti fino a quando l utente non sceglie di terminare.
Usare i sottoprogrammi nel main Un modo semplice per usare un sottoprogramma consiste nel costruire un main che contiene un ciclo do-while che chiede all utente di inserire numeri di prova per il sottoprogramma, e di andare avanti fino a quando l utente non sceglie di terminare. Un modo più raffinato consiste nel creare un menu di sottoprogrammi e permettere di scegliere un sottoprogramma attraverso l istruzione switch. Le procedure int main() do // Declare variables int choice; float speed, seconds = 0, distance; //Display program details and menu choice printf("menu\n"); printf("1...1n"); printf("2...\n"); printf("3...\n"); printf("4...\n"); printf("5 END \n"); printf("enter a choice 1-5: "); scanf("%i",&choice);
Le procedure switch(choice) case 1:... break; case 2:... break; case 3:... break; case 4:... break; case 5: printf("end of Program\n"); break; default: printf("you entered an invalid number \n"); while (choice!= 5); return 0; Esercizi sulle funzioni 1) Scrivere e usare le funzioni geometriche area del rettangolo, perimetro del rettangolo 2) Scrivere e usare la funzione potenza 3) Scrivere e usare la funzione booleana che dice se due numeri hanno lo stesso segno 4) Scrivere e usare la funzione progressione aritmetica a n termini di origine a e di ragione d, cioè la somma di tutti gli n termini che si trovano partendo da a e aumentando ogni volta di d: a + (a+d) + (a+2d) + 5) Scrivere e usare la funzione progressione geometrica a n termini di origine a e di ragione q, cioè la somma di tutti gli n termini che si trovano partendo da a e moltiplicando ogni volta per q: a + (aq) + (aq²) +
Esercizi sulle procedure 1) Scrivere e usare una procedura che riceve un numero e stampa tanti asterischi quant è il numero. 2) Scrivere e usare una procedura che riceve i valori di base e altezza e stampa un rettangolo fatto di asterischi corrispondente a questi valori. (suggerimento: usare la procedura del punto 1) 3) Scrivere e usare una procedura che stampa un rettangolo che ha gli asterischi soltanto come contorno (suggerimento: usare la procedura del punto 1 per le righe piene e una seconda sottoprocedura per le righe bucate ) Puntatori e passaggio per riferimento A differenza del passaggio per valore (quello visto sinora), il passaggio per riferimento permette di modificare le variabili passate. Il passaggio per riferimento si basa sulla nozione di puntatore. Un puntatore è una variabile speciale che contiene l indirizzo di memoria di un altra variabile. I puntatori si creano specificando il tipo della variabile puntata seguito da asterisco. Es. int x; int *p; [ ] p 195 x
Vettori e puntatori Il nome del vettore è in realtà un puntatore al suo primo elemento. Es. int v[4]; v 39 v[0] 195 v[1] 0 v[2] 74 v[3] Vettori e sottoprogrammi Il passaggio dei vettori a un sottoprogramma avviene sempre come passaggio per riferimento. Nell intestazione del sottoprogramma occorre mettere un puntatore al vettore nella forma <tipo> *pv oppure nella forma <tipo> pv[ ]. Nel programma chiamante basta invece scrivere soltanto il nome del vettore (che abbiamo visto essere un puntatore al suo primo elemento). Trattandosi di un passaggio per riferimento, le modifiche effettuate sul vettore nel sottoprogramma rimangono memorizzate nel vettore originario.
Vettori e sottoprogrammi Esempio void aumenta (int pv[ ], int x, int n) int i; for (i=0; i<n; i++) pv[i] = pv[i] + x; int main () int v[30]; [ ] aumenta(v, 5, 30); [ ] Esercizi Scrivere dei sottoprogrammi per i seguenti procedimenti su vettori di interi; usarli in un unico main con menu. 1) Caricamento del vettore da tastiera 2) Azzeramento del vettore 3) Trovare la posizione del valore più grande 4) Trovare la posizione del valore più piccolo 5) Quante volte è presente nel vettore un valore dato X 6) Somma di tutti gli elementi 7) Conteggio di tutti gli elementi maggiori di un dato X 8) Stampa del vettore sullo schermo