Sottoprogrammi: funzioni e procedure Informatica 7 Sottoprogrammi: funzioni e procedure
Definizione di sottoprogramma Sappiamo che un programma è un algoritmo scritto in un linguaggio comprensibile al calcolatore Un algoritmo è una sequenza finita e deterministica di istruzioni per risolvere un problema Un problema può essere talvolta scomposto in parti, chiamate sottoproblemi, che possono essere risolte in maniera indipendente per ottenere una soluzione al problema di partenza Se un programma è suddiviso in diverse parti, ognuna delle quali risolve un sottoproblema, allora ciascuna parte è chiamata sottoprogramma se esplicitamente separata dalle altre
Esempio: calcolo della media Problema: chiedere all’utente 3 interi, calcolarne la media aritmetica, e stamparla su schermo Il problema può essere scomposto nei seguenti sottoproblemi: richiesta numeri calcolo media stampa del risultato
Funzioni e procedure Un sottoprogramma è un algoritmo per la soluzione di un sottoproblema scritto in un linguaggio di programmazione Sottoprogrammi che restituiscono un risultato parziale tramite l’istruzione return prendono il nome di funzioni Sottoprogrammi che prevedono solo l’esecuzione di un blocco di istruzioni senza l’esplicita restituzione di un risultato si chiamano procedure
Funzioni e procedure per il calcolo della media Modelliamo come funzione il sottoprogramma per: calcolo media Risolviamo il seguente sottoproblema per mezzo di una procedura: stampa del risultato La scrittura di questi sottoprogrammi in riferimento allo stesso programma principale (main) riflette il fatto che essi sono parte della soluzione a un unico problema
Funzione: esempio nome della funzione inizio del blocco di istruzioni della funzione float media (int a, int b, int c){ int somma = a + b + c; float risultato = somma/3; return risultato; } lista dei tipi e dei nomi dei parametri formali istruzione return con cui si conclude l’esecuzione della funzione e si restituisce il risultato fine del blocco di istruzioni della funzione tipo del risultato restituito
Procedura: esempio void stampa(int m){ cout << “La media è: ” << m << “\n”; } non c’è alcun risultato restituito dal sottoprogramma, quindi il tipo del risultato è void (vuoto) non c’è alcun risultato da restituire, e infatti il blocco di istruzioni non include una istruzione return
Uso della funzione e della procedura nel programma finale … float media (int a, int b, int c){ int somma = a + b + c; float risultato = somma/3; return risultato; } void stampa(int m){ cout << “La media è: ” << m << “\n”; int main(){ int x,y,z; float r; cout << “inserisci 3 numeri:\n”; cin >> x >> y >> z; r = media(x,y,z); stampa(r); il risultato restituito dalla funzione va salvato in una variabile l’esecuzione di una procedura, invece, non prevede alcun risultato se non l’effetto delle istruzioni che la compongono
Passaggio dei parametri Nell’esempio precedente, a, b, e c sono i parametri formali della funzione media, a cui, al momento della chiamata della funzione nel main, vengono associati i valori dei parametri attuali x, y, e z Tale corrispondenza è posizionale: ad a viene associato il valore di x perché sono entrambi i primi della lista, e così via
Passaggio di parametri per valore Il passaggio del valore di x ad a consiste, di fatto, nella creazione di una variabile temporanea con lo stesso valore di x che viene usata nelle istruzioni della funzione al posto di a Per tutta l’esecuzione della funzione, la variabile x, quindi, non viene minimamente modificata: al termine della funzione sarà rimasta come prima
Possibile problema A volte, il fatto che un parametro attuale non subisca modifiche da parte della funzione può non essere ciò che desideriamo Ad es: void azzera (int n){ n = 0; } int main(){ … azzera(x); /* x rimane uguale e non viene azzerato*/ …
Passaggio di parametri per indirizzo Si ha questo tipo di passaggio quando alla funzione non è fornita una copia del valore del parametro attuale (come nel passaggio per valore) bensì l’indirizzo della cella di memoria contenente il parametro attuale In questo modo, la funzione non esegue le sue istruzioni su una copia, ma direttamente sul parametro attuale, cosicché ogni modifica del suo valore ha effetto
il simbolo & indica che il passaggio del parametro è per indirizzo Esempio void azzera (int& n){ n = 0; } int main(){ … azzera(x); cout << x; … il simbolo & indica che il passaggio del parametro è per indirizzo questa volta la variabile x è veramente azzerata e su schermo compare ‘0’
Passaggio di parametri strutturati Attenzione: nel linguaggio C++, se un parametro è un dato strutturato, viene sempre passato per indirizzo, per risparmiare la memoria che verrebbe occupata da una copia del parametro attuale Data questa regola, nella scrittura della lista dei parametri formali di un sottoprogramma si omette il simbolo ‘&’
Array come parametri In particolare, quando un array viene passato come parametro, l’informazione che il sottoprogramma riceve è solo l’indirizzo della prima cella dell’array Sarà cura del programmatore aggiungere un altro parametro che indichi la dimensione dell’array in modo che il sottoprogramma possa eseguire le istruzioni sull’array in maniera corretta
nel parametro attuale, solo il nome dell’array viene specificato Esempio int somma_valori (int v[], int dim){ int i; int somma = 0; for (i = 0; i < dim; i++) somma = somma + v[i]; return somma; } int main(){ int vettore[10]; int s; … s = somma_valori(vettore, 10); cout << “la somma dei valori dell’array e’: ” << s << “\n”; … viene segnalato che il parametro è un array, ma la sua dimensione è un parametro separato nel parametro attuale, solo il nome dell’array viene specificato