Le funzioni
Cosa fa questo programma? #include <iostream> #include <cmath> using namespace std; int x; float y; int main() { x=rand(); y=sqrt(x); cout<<y; system(“pause”); return EXIT_SUCCESS; }
Le istruzione rand(), sqrt(x); system(“pause”); prendono il nome di : Chiamata a sottoprogramma Esse sono sottoprogrammi, messi a disposizione dalla librerie . Ma noi possiamo definire dei nostri sottoprogrammi? La risposta è si Vediamo come:
Progettare un sottoprogramma Innanzitutto i sottoprogrammi si dividono in Procedure Funzioni Differenze? Le funzioni sono dei sottoprogrammi che restituiscono al codice chiamante un valore Le procedure sono sottoprogrammi le cui istruzioni sono manipolazione di dati che non restituiscono nessun valore. Il valore indefinito in C++ prende il nome di void system è una procedura Rand sqrt sono funzioni
Progettare una procedura Vogliamo disegnare una rettanglo di asterischi. le attribuiremo il nome rettangolo Quando si progetta una procedura si parte dalla sua definizione: La definizione è composta dall’intestazione e dal corpo
Progettare una procedura Intestazione L’intestazione è composta da <tipo_restituito> <nome_sottoprogramma>( ); Esempi void linea( ); è la procedura che disegna una linea di asterichi che occupa una riga void rettangolo(int r, int c); è la procedura che disegna un rettangolo di asterischi dove r indica il numero di righe e c il numero di colonne che la compongono la prima è una procedura senza parametri l’altra ha i parametri.
Progettare una procedura Intestazione I parametri sono quelle variabili che mi permettono di effettuare le stesse operazioni su valori differenti Quando non ho questa esigenza non metto i parametri
Progettare una procedura Intestazione Quando necessito dei parametri devo indicare il tipo e il nome Il numero dei parametri è opzionale da 0 a n Seguendo la seguente sintassi <tipo_restituito> <nome_sottoprogramma>(<tipo_parametro> <nome_parametro>, <tipo_parametro> <nome_parametro>, .. <tipo_parametro> <nome_parametro>) La nostra procedura avrà la seguente intestazione void rettangolo ( int r, int c);
Progettare una procedura Il corpo È quella parte del codice racchiuso tra parentesi graffe che descrive le istruzioni che la procedura esegue e che ha come ultima istruzione return ; In questo caso seguito da nessun valore perché le procedure restituiscono il tipo void altrimenti return dovrà essere seguito da un valore dello stesso tipo restituito dalla funzione Ad esempio il main essendo di tipo int alla fine contiene l’istruzione return 0; Dove 0 è un valore intero
Progettare una procedura La definizione della nostra procedura sarà la seguente void rettangolo ( int r, int c){ for (int i=0;i<r;i++){ for (int j=0;j<c;j++) cout<<‘*’; cout<<endl; } return ;
All’ interno del codice dove va scritta? Subito dopo la fine del main Ma se richiamo il sottoprogramma come siamo abituati a fare nel main e non è un sottoprogramma di libreria il compilatore quando giunge alla riga del richiamo del sottoprogramma dà errore di identificatore non dichiarato come si risolve? Prima del main si inserisce il prototipo
Progettare una procedura Il prototipo È la linea di codice che va inserita prima del main uguale alla definizione seguito dal punto e virgola Indica al compilatore le proprietà del sottoprogramma quali: Tipo restituito Nome Eventuali parametri void rettangolo(int r, int c); Vediamo il programma completo che usa la nostra procedura
#include <iostream> using namespace std; void rettangolo(int r, int c); int main() { int x,y; rettangolo (20,50); cout<<“inserire il numero delle righe e delle colonne”; cin>>x>>y; rettangolo(x,y); system(“pause”); return EXIT_SUCCESS; } void rettangolo ( int r, int c){ for (int i=0;i<r;i++){ for (int j=0;j<c;j++) cout<<‘*’; cout<<endl; } return ;
Costruiamo la funzione fattoriale La funzione fattoriale, come qualsiasi funzione matematica restituisce un valore per un certo parametro di ingresso Vediamo la sua definizione: int fattoriale(int n){ int f=1; for (int i=2;i<=n;i++) f=f*i; return f; }
Costruiamo la funzione primo La funzione ci dice se un certo numero passato come parametro alla funzione è primo o no Vediamo la sua definizione: bool primo (int x){ int i=2; while(x%i!=0) i++; if (x==1||i==x) return true; else return false; }
Esercizio Realizzare il programma di consegna per oggi facendo uso di sottoprogrammi
Esercizio Scrivere un programma C++ che permette di scegliere una delle seguenti funzionalità Visualizzare i primi n numeri Visualizzare i primi n numeri pari Visualizzare i primi n numeri dispari Visualizzare i primi n numeri primi Visualizzare i primi n numeri della serie di Fibonacci Dato in input n calcolare n! Dato in input n stampare le prime n righe del triangolo di Tartaglia Indicazioni e suggerimenti per lo svolgimento Nelle pagine successive
Indicazioni Il programma deve essere realizzato con l’uso di: Selezione multipla e deve contenere un ciclo continuo fino a quando l’utente decide di uscire dal programma Ogni caso di scelta deve essere realizzato con un sottoprogramma Ogni caso deve essere realizzato con il ciclo for
Suggerimenti Serie di Fibonacci 0 1 1 2 3 5 8 13…… n! è il fattoriale di n esso assume i seguenti valori se n=0 fatt(n)=1 Altrimenti fatt(n(= n*n-1*n-2* *2*1 cioè è il prodotto dei numeri da 1 a n Triangolo di Tartaglia Ogni elemento è dato da j!/(k!*(j-k)! Con J che va da 0 a n dove n è il numero delle righe e k va da 0 a j
#include <cstdlib> #include <iostream> using namespace std; float x,y; void scambia(float a, float b); Int main () { cin>>x; cin>>y; scambia (x,y); cout<<“i valori di x e y sono “<<x<<“ “<<y<< endl; system("PAUSE"); return EXIT_SUCCESS; } void scambia(float a, float b) { float app; app=a; a=b; b=app; return; Cosa fa questo programma? Provate a ricopiare questo programma e verificate quanto avete dichiarato
Perché le variabili non sono scambiate? Non è un errore di algoritmo E’ una questione di parametri Alla procedura scambia vengono passati dei parametri per valore Questo vuol dire che quando viene eseguita la procedura essa viene corredata della copia dei valori contenuti nei parametri x,y che sono le effettive variabili su cui viene eseguito lo scambio. Cioè la x e la y del main e quelle della procedura puntano a due celle di memoria differenti pertanto le modifiche apportate alle celle puntate dalle variabili della procedura non sono riportate anche sulle altre e tali modifiche alla chiusura della procedura vengono perse Come si risolve questo problema?
Quando si vuole che le variabili passate come parametri devono conservare le modifiche effettuate dalla procedura occorre anteporre al nome del parametro la & In questo modo la variabile viene passata per indirizzo e quindi sia le variabili del main che quella passata come parametro alla procedura o funzione puntano alla stessa cella di memoria Il prototipo di scambia diventa void scambia(float &a, float &b);
#include <cstdlib> #include <iostream> using namespace std; float x,y; void scambia(float &a, float &b); Int main () { cin>>x;; cin>>y; scambia (x,y); cout<<“i valori di x e y sono “<<x<<“ “<<y<< endl; system("PAUSE"); return EXIT_SUCCESS; } void scambia(float &a, float &b) { float app; app=a; a=b; b=app; return; X e y sono parametri attuali a e b sono detti parametri formali e quando sono accompagnati con la & essi sono passati per indirizzo cioè si punta alla stessa cella di memoria della variabile che viene passata al momento del richiamo. In questo modo conserva le modifi che
void acquisisciraggio(float &r ) {do{ cout<<"inserire il raggio deve essere tale che non superi il valore 100 "; cin>>r; } while (r<0 || r>100); return; } Questo codice permette di inserire un raggio con controllo sul suo valore Il suo richiamo nel main sarà: int main(){ float r; acquisisciraggio( r); cout<< “la circonferenza è “<<2*r*3.14; return 0; Posso realizzare la stessa funzionalità con una funzione?
float acquisisciraggio() { float r; { cout<<"inserire il raggio deve essere tale che non superi il valore 100 "; cin>>r; } while (r<0 || r>100); return r; } In questo caso cambia il modo di richiamare il programma ad esempio : int main(){ float r=acquisisciraggio( ); cout<< “la circonferenza è “<<2*r*3.14; return 0;
void acquisiscilatitriangolo(int &x, int &y , int &z) { do{ cout<<"inserire un valore positivo cin>>x; } while (x<0 ); cin>>y; } while (y<0 ); cin>>z; } while (z<0 ); return; } Questa procedura permette l’acquisizione delle coordinate con cotrollo. Posso trasformarla in funzione?
int acquisiscilatitriangolo(int &x, int &y , int &z) { do{ cout<<"inserire un valore positivo cin>>x; } while (x<0 ); cin>>y; } while (y<0 ); cin>>z; } while (z<0 ); return 0; } Questa volta devo lasciare i parametri perché i lati sono tre e le funzioni restituiscono un solo valore ma essa è comunque una funzione che però deve essere richiamata come una procedura e non come una funzione.