E’ possibile evitare di indicare sempre tutti i parametri necessari per le procedure o le funzioni, quando alcuni di essi vengono utilizzati spesso.
Ad esempio una funzione potenza, pot, che ha lo scopo di calcolare la potenza di un numero intero può scriversi:
Mostra codicePossono esistere anche più parametri di default purché ci si attenga alle seguenti considerazioni:
scrivendo sia il prototipo (dichiarazione) che la definizione, i valori di default devono essere scritti soltanto nel prototipo,
se un parametro ha un valore di default, anche tutti gli eventuali parametri successivi che appaiono nella lista formale devono avere un valore di default.
Abbiamo già incontrato una funzione con argomenti inizializzati:
cin.getline(char s[], int n, char ='\n')
s[]
rappresenta la stringa di input,
n
è il numero massimo di caratteri digitati,
il terzo argomento è il carattere di terminazione.
L’input della stringa termina o quando si è raggiunto il numero massimo n di caratteri inseriti o quando si è digitato il carattere finale che, se omesso, è rappresentato da invio. Quindi, se scriviamo
cin.getline(s,100)
il terzo parametro è di default ed è il tasto Invio, mentre scrivendo
cin.getline(s,n,'\t')
l’input terminerà digitando il tasto TAB.
Nella lista dei parametri formali delle funzioni possiamo inserire altre funzioni o procedure.
Possiamo utilizzare la funzione pot nella lista di un’altra funzione;
ad esempio:
int prova(int h, int pot(x,h), int pot(x,k))
può essere richiamata con l’istruzione
y = prova(int 4, int pot(7,4), int pot(3,5))
Supponiamo di avere scritto la seguente procedura presentazione:
void presentazione () {
cout<<''Questo programma è stato scritto da''<<endl;
cout<<''Pinco Pallino''<<endl;
}
Una qualsiasi funzione o procedura può richiamare la procedura presentazione;
Ad esempio:
int prova2(int h, void presentazione())
Segnatura delle funzioni:
E’ la parte del prototipo della funzione che comprende il nome della funzione e il tipo di ciascun argomento.
Non include il tipo di dato restituito.
Le funzioni nello stesso ambito di visibilità devono possedere segnature univoche.
Ex:
void massimo(int, int, int);
int massimo(int, int, int);
Errore!
C++ consente l’esistenza di più funzioni con lo stesso nome, chiamate “funzioni con overload”
Il compilatore distingue una funzione dall’altra in base al numero e/o il tipo degli argomenti
Esempio
int pot(int, int=3)
float pot(float, int)
La tecnica dell’overload é molto usata in C++ perché permette di programmare in modo semplice ed efficiente,
funzioni che eseguono operazioni concettualmente simili possono essere chiamate con lo stesso nome, anche se lavorano su dati diversi.
esercizio11.1.cpp
Non sono ammesse funzioni con overload che differiscano solo per il tipo del valore di ritorno. Es.
void funz(int);
int funz(int);
ambiguità: in una chiamata tipo funz(n); il programma non saprebbe se trasferirsi alla prima oppure alla seconda funzione
Né sono ammesse funzioni che differiscano solo per argomenti di default. Es.
funz(int);
funz(int, double=0.0);
ambiguità: in una chiamata tipo funz(n);
il programma non saprebbe se trasferirsi alla prima funzione (che ha un solo argomento), oppure alla seconda (che ha due argomenti, ma il secondo può essere omesso).
Dato un array di interi contenente n elementi ed un intero k, si vuole cancellare dall’array ogni occorrenza di k.
Ad esempio se l’array in questione contiene i sette elementi: (10,2,8,7,6,8,1)
e l’elemento da cancellare è 8, l’array si trasformerà in (10,2,7,6,1).
Sappiamo che ogni volta che si deve eliminare un elemento da un array occorre spostare tutti gli elementi che lo seguono di un posto verso l’alto.
Nel nostro caso, però, per cancellare il primo 8 è inutile spostare verso l’alto il secondo 8 che comunque dovrà essere in seguito cancellato.
L’idea è di ‘riscrivere’ l’array A a partire da un indice j inizialmente uguale a zero, inserendo in A[j] il primo elemento diverso da 8 che incontriamo e incrementando j di una unità e ripetendo la stessa operazione per ogni elemento di A.
Parametri?
Proviamo dunque a scrivere questa function: l’array A è evidentemente un parametro di input-output, k un parametro di input ed n, il numero di elementi presenti in A prima della cancellazione è un parametro di input-output.
Infatti se n venisse passato per valore non sapremmo più quanti elementi sono effettivamente rimasti in A dopo l’esecuzione della function.
Per verificare se questa function si comporta correttamente basta scrivere un piccolo main, un driver, il cui corpo sarà del tipo riprodotto nella foto a lato.
Regola generale per la scrittura di un driver per una procedura.
Supponiamo che la definizione di procedura contenga come
parametri di input x1,..,xn,
parametri di input-output y1,…,ym
parametri di output z1,…zr.
Allora il corpo del driver sarà:
cin>>x1>>...>>xn>>y1>>...>>ym;
f(x1,...,xn,y1,...,ym,z1,...,zr);
cout<<y1<<...<<ym<<z1...<<zr;
In altri termini il driver leggerà tutti i parametri di input e di input-output e stamperà tutti i parametri di input-output e di output.
Nel caso invece di una funzione del tipo:
float f(x1,x2,...,xn);
il corpo del driver sarà:
cin>>x1>>...>>xn ;
cout<<f(x1,x2,...xn);
Esempio: calcolo delle radici di un’equazione di 2° grado
a x2 + b x + c = 0
Input: i coefficenti a, b, e c Output:
a = 0 – non quadratica
b=c=0 → indeterminata
b=0, c≠0 →c=0 equazione impossibile
b≠0, c≠0 → equazione lineare con soluzione x= -C/B
a ≠ 0 – quadratica degenere: B=0 e/o C=0
b=0, c=0 → monomia ax2 = 0; ammette una soluzione (doppia) x1=2 = 0
b=0, c≠0 → pura ax2 + c = 0; ammette due soluzioni: x2/1 = ≠ √-C/A
b≠0, c=0 → spuria x(ax + b) = 0; ammette due soluzioni: x1=0 e x2=-B/A
a ≠ 0 – quadratica completa: B≠0 e C≠0 (Δ = b2 – 4ac)
Δ> 0 → ammette due soluzioni reali distinte
Δ= 0 → ammette due soluzioni reali coincidenti: -B/2A
Δ< 0 → ammette due soluzioni immaginarie distinte
Esempio: calcolo delle radici di un’equazione di 2° grado
a x2 + b x + c = 0
Il primo, caratterizzato da a=0, porta all’equazione di primo grado, equazione non quadratica, mentre gli altri due casi si distinguono dal valore di c o b, nullo per l’equazione quadratica degenere, tutti diversi da zero nel caso dell’equazione con due radici.
Se il coefficiente a è nullo
risolvi l’equazione non quadratica
altrimenti
se c o b è nullo
l’equazione è degenere
altrimenti è un’equazione con due radici
1. Prime nozioni di Programmazione
2. C++ elementi di un programma
3. Le istruzioni di I/O standard
5. C++ funzioni matematiche ed espressioni booleane
6. Le strutture di controllo - parte seconda
8. Array di caratteri e tipi astratti
9. Astrazione procedurale: Procedure e Funzioni
10. Astrazione procedurale: Procedure e Funzioni -parte seconda
11. Astrazione procedurale: Procedure e Funzioni - parte terza
12. Librerie
13. Le strutture di controllo - parte terza
14. Algoritmi
16. I File di testo
17. La classe string