Sottoprogrammi e funzioni

Slides:



Advertisements
Presentazioni simili
C C++ &.
Advertisements

Introduzione al linguaggio C++
Funzioni In C++ le funzioni sono caratterizzate da un nome, dal tipo della variabile ritornata e da una lista di parametri (opzionali) La lista dei parametri.
INFORMATICA Strutture condizionali
Sottoprogrammi: funzioni e procedure
Procedure e funzioni A. Ferrari.
Introduzione alla programmazione A. Ferrari. Il linguaggio C Nel 1972 Dennis Ritchie nei Bell Laboratories progettò il linguaggio C Il linguaggio possiede.
LS Tron Classe 4TC – as 2006/07 LORGANIZZAZIONE DEI PROGRAMMI UD. 8 p. 282.
LE FUNZIONI IN C Sommario 1 Introduzione 2 Moduli di programma in C
ITIS LATTANZIO Unità Didattica Materia Informatica Funzioni in C++
MATLAB. Scopo della lezione Programmare in Matlab Funzioni Cicli Operatori relazionali Esercizi vari.
1 Informatica Generale Susanna Pelagatti Ricevimento: Mercoledì ore presso Dipartimento di Informatica, Via Buonarroti,
Informatica Generale Susanna Pelagatti
Anno accademico Le classi di memorizzazione.
La ricorsione Simulazione. Il Main /* Programma che usa una funzione ricorsiva*/ #include #define MAX_N 8 main() int valore, dato; printf(Introduci n:
1 Istruzioni, algoritmi, linguaggi. 2 Algoritmo per il calcolo delle radici reali di unequazione di 2 o grado Data lequazione ax 2 +bx+c=0, quali sono.
Indirizzi delle variabili A ogni variabile sono associati tre concetti fondamentali: il valore memorizzato; il tipo dati di appartenenza; lindirizzo. Il.
Argomenti dalla linea dei comandi Gli argomenti possono essere passati a qualsiasi funzione di un programma, compresa la main(), direttamente dalla linea.
Funzioni definite dall’utente
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Corso di Fondamenti di programmazione a.a. 2009/2010 Prof.ssa Chiara Petrioli.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Puntatori Marco D. Santambrogio – Ver. aggiornata al 21 Marzo 2013.
Informatica 2. Concetti fondamentali di programmazione Programmare vuol dire scrivere un algoritmo in un linguaggio che faccia funzionare un calcolatore.
Laboratorio di Linguaggi lezione IV Marco Tarini Università dellInsubria Facoltà di Scienze Matematiche, Fisiche e Naturali di Varese Corso di Laurea in.
1 Corso di Informatica (Programmazione) Lezione 12 (19 novembre 2008) Programmazione in Java: i metodi statici.
MATLAB. …oggi… Programmare in Matlab Programmare in Matlab m-file m-file script script Funzioni Funzioni Cicli Cicli Operatori relazionali Operatori relazionali.
Programmazione Un programma descrive al computer, in estremo dettaglio, la sequenza di passi necessari a svolgere un particolare compito L’attività di.
Lezione 4: Costrutti Condizionali Prof. Raffaele Montella.
Fondamenti di Informatica I a.a Il linguaggio C Il controllo di flusso La selezione condizionale Listruzione switch I cicli Le istruzioni break,
Istruzioni di selezione in Java Programmazione Corso di laurea in Informatica.
memoria gestita staticamente:
Le classi Definizione di classe Attributi e metodi di una classe Costruttori e distruttori Private e public Funzioni friend Il puntatore this.
Esercizi FUNZIONI Passaggio di parametri per valore, variabili e tipi locali e globali, prototipo.
La Programmazione Ricorsiva
Le funzioni.
FUNZIONI... Una funzione permette di dare un nome a una espressione rendendola parametrica float f(){ return * sin(0.75); } float f1(int x) { return.
ITIS LATTANZIO Unità Didattica Materia Informatica Funzioni in C++
Il linguaggio C Le funzioni C Language Il passaggio dei parametri
Cicli in Fortran I cicli consentono di eseguire una sequenza di istruzioni più di una volta due tipi: Cicli iterativi Cicli while.
Un esempio: Calcolo della potenza n-esima di un numero reale
Prof.ssa Chiara Petrioli -- Fondamenti di programmazione, a.a. 2009/2010 Corso di Fondamenti di programmazione a.a. 2009/2010 Prof.ssa Chiara Petrioli.
Lo sviluppo top down Le funzioni
Passaggio di parametri per indirizzo
2000 Prentice Hall, Inc. All rights reserved. Capitolo 5 (Deitel) Le funzioni Indice degli argomenti Introduzione Moduli nei programmi C 5.3.
2000 Prentice Hall, Inc. All rights reserved. Attivazione di funzioni La chiamata/attivazione di funzione viene indicata citando il nome della funzione.
I metodi F. Bombi Campi e metodi Abbiamo visto che una classe può contenere – Campi – Metodi stato I campi sono utilizzati per memorizzare.
File e Funzioni Si possono distinguere tre tipi di file che vengono utilizzati in MATLAB: M-file: hanno estensione .m e in essi vengono memorizzati i.
Complessità di un algoritmo
1 Fabio Scotti ( ) Laboratorio di programmazione per la sicurezza Valentina Ciriani ( ) Laboratorio di programmazione Lezione 11 e 12 -
- prof. V. Riboldi - SOTTOPROGRAMMI IN TPASCAL METODO TOP DOWN.
Informatica A.A. 2009/2010 Parte 4 Dai diagrammi di flusso alla programmazione strutturata: le istruzioni if, for, while, … Corso A: Prof. Stefano Berardi.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Funzioni e Procedure Marco D. Santambrogio – Ver. aggiornata al 3 Aprile 2015.
Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.
Parte 3 Lo stato: variabili, espressioni ed assegnazioni
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Puntatori Marco D. Santambrogio – Ver. aggiornata al 11 Ottobre 2014.
Informatica 4 Funzioni. FUNZIONE: definizione MATEMATICA Relazione (o applicazione) binaria tra due insiemi A e B che associa a ogni elemento di A un.
1 Fabio Scotti – Università degli Studi di Milano Fabio Scotti ( ) Laboratorio di programmazione per la sicurezza Valentina Ciriani ( )
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Puntatori Marco D. Santambrogio – Ver. aggiornata al 11 Marzo 2014.
13 ottobre Decisioni F. Bombi 13 ottobre 2002.
1 Il linguaggio C Precisazioni sull’esperienza in laboratorio.
Linguaggio C: Le basi Stefano Cagnoni e Monica Mordonini
Linguaggio C: Le basi Stefano Cagnoni e Monica Mordonini
1 Informatica Generale Marzia Buscemi Ricevimento: Giovedì ore , Dipartimento di Informatica, stanza 306-PS o per posta.
Copyright © Istituto Italiano Edizioni Atlas
Eprogram informatica V anno. Introduzione a PHP Introduzione La diffusione di PHP ha avuto un notevole incremento dalla fine degli anni Novanta a oggi,
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Algoritmi e basi del C Marco D. Santambrogio – Ver. aggiornata al 24 Agosto 2015.
1 Metodo I metodi sono uno strumento che i programmatori usano per strutturare i programmi, sia per renderli più facili da capire che per permettere il.
DIPARTIMENTO DI ELETTRONICA E INFORMAZIONE Funzioni e Procedure Marco D. Santambrogio – Ver. aggiornata al 4 Aprile 2016.
Metodi in Java. Note Identificazione input: (il raggio è un numero reale !!!) Identificazione delle operazioni necessarie al calcolo Area=r*r*PI Circonferenza=2*r*PI.
10. Programmazione Ricorsiva Ing. Simona Colucci Informatica - CDL in Ingegneria Industriale- A.A
Eccezioni in Java. Le eccezioni in Java Exception handling: insieme di costrutti e regole sintattiche e semantiche presenti nel linguaggio allo scopo.
Transcript della presentazione:

Sottoprogrammi e funzioni Parte 5 Sottoprogrammi, funzioni, e passaggio dei parametri. Corso A: Prof. Stefano Berardi http://www.di.unito.it/~stefano Corso B: Prof. Ugo de’ Liguoro http://www.di.unito.it/~deligu

Finalmente arrivano le funzioni …

Indice Parte 5: Funzioni I sottoprogrammi al tempo del GOTO. I sottoprogrammi ai tempi della programmazione strutturata: le funzioni. Variabili locali e globali. Passaggio per riferimento. Come si descrive una funzione? Pre- e Post- condizioni. Le funzioni vengono usate in C++ per scomporre un problema in sottoproblemi e facilitarne così la soluzione.

1. I sottoprogrammi Salvo per le operazioni elementari (ad es. le operazioni aritmetiche) ad ogni operazione di un programma corrisponde un gruppo di istruzioni in C++. Un’operazione più volte ripetuta in un programma (es.: disegnare un cerchio con certe caratteristiche) può essere realizzata da un gruppo di istruzioni che viene eseguito ogni volta che serve: un sottoprogramma. L’idea di sottoprogramma corrisponde all’idea di scomporre un problema in sottoproblemi. 5-Funzioni

Perché i sottoprogrammi? La scomposizione di un programma in sottoprogrammi rende un programma più leggibile e (di solito) più breve, ma il suo scopo principale è quello di correggere separatamente anziché tutte insieme le diverse parti del programma. I sottoprogrammi sono indispensabili per i programmi lunghi. Non è effettivamente possibile scrivere un programma di grandi dimensioni senza scomporlo in sottoprogrammi, perché trovare un errore nascosto in un lungo blocco di istruzioni richiede troppo tempo. 5-Funzioni

Esempi di sottoprogrammi Vedremo nel Laboratorio del corso come anche programmi lunghi poche pagine, come l’implementazione dell’algoritmo di Gauss-Jordan e degli Automi Cellulari, e addirittura programmi brevi come uno che disegna coriandoli diventano molto più semplici da scrivere se scomposti in sottoprogrammi. Un’avvertenza su questa lezione. Per semplicità di esposizione, nei prossimi lucidi scomporremo in sottoprogrammi anche alcuni programmi brevissimi, che non richiederebbero affatto tale scomposizione. 5-Funzioni

Un sottoprogramma per il massimo al tempo dei GOTO 100 LET X = 3 110 LET Y = 5 120 GOSUB 400 130 PRINT MASSIMO ... 400 IF X > Y THEN 430 410 LET MASSIMO = Y 420 GOTO 440 430 LET MASSIMO = X 440 RETURN Assegno 3, 5 a X, Y “Chiamata” al sottopro- gramma: “salto” alle istruzioni del sottopro-gramma per il calcolo di max(x,y) “Ritorno” dal sottoprogram-ma per il massimo: “salto” all’indietro, ora MASSIMO = max(3,5) = 5 5-Funzioni

Come si ritornava al programma principale 120 GOSUB 400 130 ... 400 ... 440 RETURN Quando si eseguiva l’istruzione 120 che “chiama” il sottoprogramma, prima di saltare alla linea 400 veniva memorizzato in una variabile l’indirizzo 120 da cui si proveniva. Quando poi si eseguiva RETURN (ultima istr. 440 del sottoprogramma), si eseguiva un JUMP o “salto” all’istruzione 130, quella immediatamente successiva all’istruzione 120 ricordata. 5-Funzioni

I parametri dei sottoprogrammi La X e la Y sono dette i valori in ingresso del sottoprogramma,MASSIMO è detto il valore in uscita. X, Y sono detti parametri del sottoprogramma I sottoprogrammi avevano un difetto: supponiamo di aver gia’ utilizzato X, Y altrove per salvare dei valori 100 LET X = 3 110 LET Y = 5 120 GOSUB 400 130 PRINT MASSIMO ... 400 IF X>Y THEN 430 410 LET MASSIMO = Y 420 GOTO 440 430 LET MASSIMO = X 440 RETURN L’uso di variabili X, Y per “passare” i valori 3, 5 verso un sottoprogramma provocava la perdita dei valori precedenti di X, Y. 5-Funzioni

2. I sottoprogrammi ai tempi della programmazione strutt. Una funzione è un sottoprogramma con parametri propri (non appartenenti al programma principale) attraverso le quali riceve l’ingresso (e a volte può anche restituire l’uscita). L’uso di un sottoprogramma con parametri propri evita il rischio di cancellare senza volerlo il contenuto di altre variabili del programma. Questa era una fonte comune di errori quando i sottoprogrammi non avevano parametri propri. 5-Funzioni

I sottoprogrammi ai tempi della programmazione strutt. Una “chiamata” a una funzione produce un salto alle righe che contengono la funzione, mentre l’indirizzo dell’istruzione che chiama la funzione viene memorizzato. Terminata l’esecuzione della funzione, il flusso del programma riprende dall’istruzione successiva alla quella dove era avvenuta la chiamata. Tutto questo oggi avviene senza dover scrivere esplicitamente istruzioni di salto né indirizzi: ci pensa il compilatore ad aggiungerli nell’eseguibile. 5-Funzioni

Funzioni: sintassi <tipo> <nome funzione> (<lista param.>) {<corpo>} <tipo> è il tipo del valore restituito (si usa il tipo void (vuoto) se non viene restituito alcun valore) <lista param.> (eventualmente vuota) è una sequenza di dichiarazioni di variabili, separate da virgole, della forma: <tipo> <nome variabile> int max (int x, int y) { if (x > y) return x; else return y; } Tipo valore di ritorno Lista parametri Valore di ritorno: viene definito da un comando return. Il suo tipo deve essere uguale al tipo del valore di ritorno corpo della funzione

Funzioni: dichiarazioni, definizioni e chiamate Le funzioni in C++ compaiono in tre modi: Dichiarazioni (fuori dal main). Corpo ridotto a “;” double sq(double x); Una dichiarazione precisa solo i tipi della funzione. Definizioni (fuori dal main). Sono dichiarazioni seguite dal corpo {…} della funzione. double sq(double x) {return x*x; /*corpo funzione*/} Chiamate (nel main o in una funzione). Devono essere precedute almeno dalla dichiarazione, non dichiarano i tipi: scrivete b = sq(a); e non: b = sq(double a);

I parametri di una dichiarazione o definizione sono detti “formali” La dichiarazione o definizione di una funzione sta prima o dopo il main e richiede i tipi int max (int x, int y) {if (x > y) return x; else return y;} } In una dichiarazione o definizione, x, y sono detti parametri formali sono propri della funzione I parametri formali x, y vengono usati per passare alla funzione le informazioni di cui ha bisogno per il calcolo richiesto.

I parametri di una chiamata di funzione sono detti “attuali” int main () { int n = 7, m = 14, k; k = max(n, m); cout<< " il massimo tra " << n << " e " << m << " vale " << k << endl; } } In una chiamata, n, m sono detti parametri attuali. Sono parametri propri del main Una chiamata copia i valori parametri attuali n, m del main nei parametri formali x, y della funzione, che riceve così tutte le informazioni di cui ha bisogno per il calcolo. La chiamata di una funzione sta nel main o dentro un’altra funzione e non richiede di ripetere i tipi dei parametri

Chiamate di funzione in dettaglio La chiamata di funzione k = max(n, m); crea gli indirizzi di memoria per i parametri formali x,y e assegna loro i valori dei parametri attuali n,m n x 7 7 7 max(int x, int y) m 14 y 14 14 main() Return value k 14 14 14 Alla fine della chiamata gli indirizzi di x, y vengono riutilizzati per altre variabili. Il valore di ritorno di max(n,m) viene assegnato a k. 5-Funzioni

Funzioni: l’istruzione return Una funzione normalmente restituisce un valore attraverso l’istruzione return, che compare nel corpo della definizione della funzione, come segue: return <espressione>; double cube (double x) { return x*x*x; } Il tipo dell’espressione x*x*x argomento del return deve coincidere con il tipo del valore di ritorno (in questo caso devono essere entrambi double). 5-Funzioni

Attenti a non perdere il valore di una funzione Se ci dimentichiamo di salvare il valore di ritorno di una funzione lo perdiamo. Infatti il valore restituito da una funzione di solito sta in un registro della CPU, e può essere salvato solo assegnandolo ad una variabile, per esempio scrivendo: k = max(n, m); In questo caso, il massimo tra i valori di n ed m è ora il nuovo valore di k. Se invece scrivo soltanto: max(n,m); allora il valore di max(n,m) viene perso. 5-Funzioni

Le funzioni si possono usare dentro espressioni Una funzione di tipo T definisce un’espressione di tipo T. Quindi una funzione di tipo T può essere usata in combinazione con qualunque funzione definita o di libreria, e con qualunque operazione aritmetica, per costruire nuove espressioni. Un esempio: 7 + max(3, max(5, m*2) ); In una chiamata di funzione, il parametro attuale di max può anche essere un’espressione come max(5, m*2) che contiene max 5-Funzioni

Le funzioni con tipo void non indicano un valore Esistono funzioni C++ che non restituiscono un valore, ma si limitano a svolgere un’azione (ad esempio la stampa di un valore). Non hanno nessun corrispondente tra le funzioni matematiche. Se una funzione svolge un’azione e non restituisce alcun valore viene definita con il tipo void (vuoto): Ciao(); e Pi(); sono comandi di stampa, non indicano nessun valore. È un errore scrivere cout<<Ciao(); oppure Pi()+1; Non c’è un valore di ritorno di Ciao() da stampare, né un valore di Pi() a cui aggiungere 1. void Ciao () {cout << "ciao! " << endl;} void Pi () {cout << 3.14159265 << endl;}

Funzioni: errori frequenti Il meccanismo di comunicazione tra una funzione e il resto del programma non è semplice, ma deve venir capito a fondo, altrimenti rischiamo errori come i seguenti: Usare una funzione senza valore di ritorno per indicare un valore (abbiamo appena visto un esempio); Leggere da tastiera il valore di un parametro formale. Dimenticarci di salvare il valore di ritorno di una funzione. Nei prossimi lucidi spieghiamo gli errori 2 e 3.

È un errore leggere da tastiera il valore di un parametro formale La comunicazione tra una funzione e il resto del programma avviene quando una chiamata assegna i parametri attuali ai parametri formali. È un errore assegnare noi stessi i parametri formali, per esempio è un errore usare l’istruzione cin >> … come segue: int sq(int n){cout<<"dammi un valore per n: ";cin>>n; return n*n; } // sq e’ scritta in modo errato Infatti quando scriviamo sq(3), il valore 3 passato ad sq attraverso il parametro formale n viene sovrascritto da un altro valore, per es. 10, inserito da noi. Così sq(3) non vale 3*3 come dovrebbe ma 10*10. 5-Funzioni

È un errore dimenticare di salvare il valore di una funzione Abbiamo già visto che se dimentichiamo di salvare il valore di ritorno di una funzione lo perdiamo: int f(int n){ ... return ... } int main() {int num; cin >> num; f(num);} /* il valore restituito da f(num) viene si’ calcolato, ma non viene assegnato a una variabile, quindi va perso. */ 5-Funzioni

3. Variabili locali All’interno del corpo di una funzione può essere utile avere variabili che esistano solo durante l’esecuzione, per evitare di sovrascrivere variabili già in uso. Queste variabili si dicono “variabili locali”: sono proprie alla funzione come i parametri formali, e come essi nascono (nel senso che ricevono un indirizzo di memoria) e muoiono (nel senso che il loro indirizzo viene riciclato) ad ogni chiamata della funzione. int f(int n) { int r, s; ... } Ambito di visibilità delle variabili locali r ed s e del parametro formale n: queste variabili r,s,n esistono solo qui 5-Funzioni

Quali variabili dobbiamo definire come “locali”? Più variabili possibile! Per rendere indipendenti sottoprogramma e programma, dobbiamo definire come variabile locale di una funzione qualunque variabile contenga un risultato intermedio delle funzione, come un contatore o un accumulatore. Inseriamo invece tra i parametri della funzione solo le variabili indispensabili alla funzione. SI: indispensabile NO: contatore NO: accumulatore int fattoriale(int n, int i, int prod) { for(i=2,prod=1;i<=n;++i)prod=prod*i return prod;} 5-Funzioni

Cosa succede se inseriamo una variabile locale tra i parametri? Il programma diventa inutilmente complicato, illeggibile e a rischio di errore. Nell’esempio del fattoriale, se dichiariamo una funzione fattoriale(n,i,prod), per calcolare il fattoriale di 3 dobbiamo scrivere fatt(3,2,1), fornendo non solo il 3, ma anche i valori iniziali i=2 e prod=1. int fattoriale(int n) {int i; int prod; for(i=2,prod=1;i<=n;++i)prod=prod*i; return prod;} SI: indispensabile Contatore locale Accumul. locale 5-Funzioni

A cosa servono le variabili locali? Riassumendo, le variabili locali di una funzione: Sono visibili solo dalle istruzioni nel corpo della funzione. Esistono solo finché la funzione è in esecuzione, quindi spariscono. Lo spazio di memoria che esse occupano viene indicato come “disponibile” e viene assegnato ad altre variabili. Questa operazione viene detta “riciclo” della memoria. Evitano sovrascritture accidentali di variabili con lo stesso nome in altre funzioni o nel main, e nascondono i passi di calcolo della funzione all’interno della funzione stessa. 5-Funzioni

Variabili locali e Stack di sistema (cenni) Per capire meglio come funzionano le variabili locali, vediamo come avviene la creazione e il “riciclo” delle variabili locali. Il sistema gestisce un gruppo di bytes consecutivi detto stack (pila). Ogni volta che dichiariamo una variabile nel main o nella funzione appena chiamata, aggiungiamo alla pila uno spazio di memoria con il valore della variabile. Parte della pila con le variabili generate da una chiamata a una funzione f x  1200CF (indirizzo esadec.) z  1205B1A Parte della pila con le variabili del main() x  06A231 y  105BA3 5-Funzioni

La ricerca di una variabile locale nello Stack di sistema double f(double z) { float x; …} La sola x visibile durante l’esecuzione di f(…) e’ quella nel riquadro più in alto, la x di f int main() { double x, y; … f(x); … } Per cercare il valore di x, leggiamo dall’alto in basso, fermandoci la prima volta che incontriamo x La x del main() non e’ visibile durante l’esecuzione di f(…), ma continua ad esistere x  1200CF (x di f) z  1205B1A x  06A231 (x del main) y  105BA3 5-Funzioni

Parametri e variabili locali: un errore tipico Per errore usiamo due volte lo stesso nome x in f: cosa succede? double f(double x) { float x; …} int main() {double x, y; … f(x); …} Per saperlo, leggiamo lo stack di sistema “dall’alto al basso”, fermandoci alla prima x che troviamo La x variabile locale, dichiarata per ultima, viene trovata per prima e nasconde (in inglese: “shadows”) il parametro formale x x  1200CF x  1205B1A x  06A231 y  105BA3

Variabili locali nei Blocchi La dichiarazione delle variabili locali può anche essere annidata in blocchi delimitati da { } : int f(int n) { int s = 0; { int r, s = 1; /* la seconda s, definita in questo blocco, “fa ombra” alla prima locale alla f */ cout << s; }; cout << r; /* ERRORE: fuori dal blocco in cui è definita, r non esiste più! E se anche esistesse, sarebbe un’altra r … */ cout << s; /* s vale ancora 0, la s che ha preso valore 1 e’ un’altra s */ } 5-Funzioni

Errori frequenti int f(int n) { int s; ... s = ...} int main() { int m = f(7); int p = s; /* ERRORE: fuori dalla funzione f in cui è definita, s non esiste più! E se anche esistesse, sarebbe un’altra s … */ ... } Come il passaggio dei parametri, anche la visibilità è un meccanismo importante nell’uso delle funzioni, e va capita a fondo, altrimenti rischiamo errori come questo: 5-Funzioni

Variabili globali Tutte le variabili sin qui viste sono parametri oppure variabili locali: alcune sono locali al main(), ma in C++ anche il main() è una funzione. Le variabili definite fuori dalle funzioni sono visibili ovunque (tranne in blocchi che abbiano variabili locali omonime) e sono persistenti per tutta l’esecuzione del programma. Sono dette variabili globali. Per esempio, costanti e parametri del programma dovrebbero essere variabili globali. #include <iostream> double pi = 3.14159265; /* pi esisterà per tutto il programma */ 5-Funzioni

Variabili globali: evitare un uso eccessivo Le variabili globali servono per violare le limitazioni di visibilità tipiche delle variabili locali, limitazioni a volte troppo restrittive. L’uso delle variabili globali deve essere moderato, perchè può causare riscritture accidentali di variabili con lo stesso nome, e perchè produce programmi poco leggibili, come nel seguente esempio: double k=0.0; // k esiste per tutto il programma void C(double x) { … k = sqrt(x);… … } int main(){C(25); cout << k;} /* eseguire C(25) assegna k=5.0, ma leggendo la sola riga: C(25); questo non è affatto evidente!! */ 5-Funzioni

5. Passaggio per riferimento Il passaggio dei parametri è detto per valore perche’ comporta una copia del parametro attuale in quello formale. Questo è un difetto quando vogliamo usare una funzione per produrre una modifica permanente: scambia dovrebbe scambiare i suoi argomenti ma agisce solo sulle variabili temporanee x, y void scambia (int x, int y) {int temp = x; x = y; y = temp;} int main() { int n = 45, m = 0; scambia(n, m); cout << n << " \t " << m;} /* i parametri formali x,y, copie di n,m, sono stati scambiati, ma i parametri attuali n,m no!!*/ 5-Funzioni

Passaggio per riferimento In C++ si può passare l’indirizzo di parametro attuale x definendo il parametro formale della funzione come &x. &x denota l’indirizzo di x. Questo passaggio di parametri e’ detto per riferimento e ed è usato per violare le limitazioni di visibilità tipiche dei parametri di una funzione, e per modificare il valore originale dell’argomento x. void scambia (int & x, int & y) { int temp = x; x = y; y = temp; } indirizzo x indirizzo y 5-Funzioni

Passaggio per riferimento scambia() main() n temp x 45 45 m y x ed y in scambia() assumono lo stesso indirizzo di n, m nel main(). x e n sono sinonimi, cioè sono la “stessa” variabile con due nomi diversi (condividono l’indirizzo di memoria). Questo accorgimento consente a scambia() di modificare le x, y originali. 5-Funzioni

Usi del passaggio per riferimento Anche il passaggio per riferimento puo’ creare errori difficili da scoprire: viola le limitazioni di visibilità e consente riscritture accidentali di variabili, quindi va usato con moderazione. Il passaggio per riferimento può essere utile quando si deve restituire più di un valore, per es., q=quoziente e r=resto di n/m. In tal caso si passano gli indirizzi delle variabili q, r in cui vogliamo che siano scritti i risultati. Le variabili q, r originarie vengono modificate. void Div (int n, int m, int & q, int & r) { r = n%m; // calcola quoziente e resto n:m q = n/m; } 5-Funzioni

Usi del passaggio per riferimento Nell’esempio seguente, la chiamata a Div modifica i valori di quoziente e resto: void Div (int n, int m, int & q, int & r) // calcola quoziente e resto di n div. m { … } int main() {int resto=0, quoziente=0; Div(20, 3, quoziente, resto); cout<<quoziente<<"\t"<<resto<<endl;} 5-Funzioni

Errori frequenti Non possiamo passare per riferimento una costante o una espressione. Un argomento passato per riferimento deve avere un indirizzo di memoria, dunque, per quanto ne sappiamo fin qui, può solo essere una variabile: int main () { scambia(7, 5+9); } // ERRORE; né 7 né 5+9 // hanno un indirizzo di memoria 5-Funzioni

6. Come si descrive una funzione? In altre parole, “che cosa” calcola una funzione? La risposta viene chiamata una specifica dell’algoritmo, ed è fatta di due parti: una pre-condizione e una post-condizione Vorrei calcolare valori con la proprietà  Sig. Utente Sig. Funzione  Pre-condizione  Post-condizione Posso farlo purché i dati soddisfino  5-Funzioni

Pre e Post condizioni La pre-condizione è una richiesta, ossia un’ipotesi sull’ingresso (spetta a chi fornisce i dati controllarla) La post-condizione è una proprietà dell’uscita di una funzione, che si deve garantire che valga dopo l’esecuzione. Quando inseriamo nella funzione dei dati che non rispettano la precondizione, otteniamo delle risposte imprevedibili. Il calcolo della funzione può anche continuare per sempre, o produrre un “crash”. 5-Funzioni

Esempi di Pre e Post condizioni int MCD (int n, int m) // pre: n, m >=0 e non entrambi nulli // post: MCD restituisce il massimo comun // divisore tra n ed m void Div (int n, int m, int & q, int & r) // pre: m != 0 // post: q quoziente, r resto della div. n:m 5-Funzioni

Riepilogo I sottoprogrammi sono parti di un programma la cui esecuzione può essere ripetuta in punti diversi del programma principale, o di altri sottoprogrammi. Le funzioni sono sottoprogrammmi con parametri propri, parametri che esistono solo per la durata di una esecuzione della funzione. Le funzioni compaiono in un programma in tre modi diversi: in una dichiarazione, in una definizione e in una o più chiamate. Le funzioni possono avere variabili locali. Le funzioni si descrivono con una specifica, fatta di pre- e post-condizioni. 5-Funzioni

Riepilogo Le funzioni possono restituire un valore, oppure no (in tal caso sono di tipo void) I parametri sono passati per valore oppure per riferimento Le variabili locali oscurano sia le variabili globali che i parametri Se una funzione restituisce un valore, allora la funzione può essere usata in un’espressione per indicare il valore da essa restituito. Altrimenti no. 5-Funzioni