G. Mecca – Università della Basilicata – mecca@unibas.it
Programmazione Procedurale in Linguaggio C++
Sottoprogrammi Parte 7 Conclusioni
versione 2.1
Questo lavoro è concesso in uso secondo i termini di una licenza Creative Commons (vedi ultima pagina)
Sommario
m
Ricapitolazione
m
Convenzioni di Stile
m
Alcune Tecniche Notevoli
ðUtilizzo delle Costanti Numeriche ðGenerazione di Numeri Casuali
m
Errori Frequenti
Sottoprogrammi: Conclusioni >> Sommario
G. Mecca - Programmazione Procedurale in Linguaggio C++ 3
Ricapitolazione
m
Sottoprogrammi
ðuna funzionalità essenziale dei linguaggi di programmazione procedurale
ðconsentono di dividere un’applicazione in moduli (programma principale e
sottoprogrammi)
ðche comunicano attraverso il passaggio dei parametri (meccanismo fondamentale)
Sottoprogrammi: Conclusioni >> Ricapitolazione
Ricapitolazione
m
Due categorie
ðfunzioni: blocchi di istruzioni per il calcolo di un valore
ðprocedure: blocchi di istruzioni che realizzano opportune operazioni
m
In entrambi i casi
ðpossono essere predefiniti (parte di una libreria di sistema)
ðoppure definiti dall’utente
Sottoprogrammi: Conclusioni >> Ricapitolazione
G. Mecca - Programmazione Procedurale in Linguaggio C++ 5
Ricapitolazione
m
Definizione di un sottoprogramma
ðintestazione e corpom
Intestazione
ðtipo del risultato o void ðnome
ðelenco dei parametri (tipo e nome)
m
Corpo
ðblocco di istruzioni
Sottoprogrammi: Conclusioni >> Ricapitolazione
Ricapitolazione
m
Utilizzo di un sottoprogramma
ðchiamataðnome e argomenti
m
Utilizzo delle funzioni
ðall’interno di espressioni per calcolare un valore
m
Utilizzo delle procedure
ðcome istruzioni a sé stanteSottoprogrammi: Conclusioni >> Ricapitolazione
G. Mecca - Programmazione Procedurale in Linguaggio C++ 7
Ricapitolazione
m
Parametri
ðspazi nella memoria
m
Parametri standard (o “per valore”)
ðvengono usati come dati ordinari del modulo
m
Parametri per riferimento (“per variabile”)
ðsono intermediari tra il proc. e un altro dato ðpossono essere utilizzati per modificare ilcorrispondente argomento
Sottoprogrammi: Conclusioni >> Ricapitolazione
Ricapitolazione
m
Programmazione modulare
ðapproccio alla programmazione procedurale basato sui sottoprogrammi
m
Idea
ðindividuare i passi (le funzionalità) fondamentali dell’applicazione
ðcostruire un opportuno sottoprogramma per ciascuna funzionalità
ðmetodologia incrementale
Sottoprogrammi: Conclusioni >> Ricapitolazione
G. Mecca - Programmazione Procedurale in Linguaggio C++ 9
Ricapitolazione
m
Funzionalità avanzate
ðpossibilità offerte dalla prog. modulare
m
Utilizzo di dati globali
ðutile per definire costanti globali ðregole di visibilità
m
Compilazione separata
ðcreazione di librerie (file di intestazioni) ðriuso del codice
Sottoprogrammi: Conclusioni >> Ricapitolazione
La Metodologia di Sviluppo
m Analisi delle specifiche
ðeliminazione delle ambiguità ðdati di ingresso e dati di uscita
m Scelta dell’algoritmo
ðstrategia per la rappresentazione dei dati ðstrategia per le operazioni
m Scrittura del codice
m Compilazione e collegamento
m Esecuzione e verifica
Sottoprogrammi: Conclusioni >> Ricapitolazione
approccio integrato e incrementale
G. Mecca - Programmazione Procedurale in Linguaggio C++ 11
La Metodologia di Sviluppo
Sottoprogrammi: Conclusioni >> Ricapitolazione
Analisi dei Requisiti
Scelta dell’Algoritmo e Scrittura del Programma
Compilazione e Collegamento
Esecuzione e Verifica
Uso e Manutenzione errori
sintattici
errori logici codice
sorgente
codice eseguibile - eliminazione
delle ambiguità - analisi dei dati
di ingresso e uscita
- strategia di rappresentazione - strategia di
operazioni
Convenzioni di Stile
m
Ulteriori convenzioni di stile
ðorganizzazione del file e spazi bianchi ðnomi delle costanti
ðnomi dei sottoprogrammi
m
Si aggiungono a quelle precedentemente definite
Sottoprogrammi: Conclusioni >> Convenzioni di Stile
G. Mecca - Programmazione Procedurale in Linguaggio C++ 13
Organizzazione del File
m Commento iniziale
ðlinea vuota
m Direttive import
ðlinea vuota
m Definizione delle costanti globali
ðlinea vuota
m Prototipi
ðlinea vuota
m main
ðlinea vuota
m Codice delle procedure e delle funzioni
Sottoprogrammi: Conclusioni >> Convenzioni di Stile
>> morraCinese4.cpp
Convenzioni di Stile
m
Nome delle costanti
ðmaiuscoloðes: VINCEILCOMPUTER
m
Nome dei sottoprogrammi
ðnotazione “cammello”ðlettere minuscole (come le variabili) ðes: schermoIniziale
Sottoprogrammi: Conclusioni >> Convenzioni di Stile
G. Mecca - Programmazione Procedurale in Linguaggio C++ 15
Alcune Tecniche Notevoli
m
La Morra Cinese
ðdue tecniche notevolim
Oggetto da giocare ed esito della mano
ðutilizzo di costanti simboliche intereðper migliorare la leggibilità del codice
m
Giocata del computer
ðgenerazione di numeri casuali
ðtecnica frequentemente usata nei giochi
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
Utilizzo di Costanti Simboliche Intere
m
Nel programma
ðè necessario gestire dati con valori particolari ðinsieme finito e limitato di valori possibili
m
Finora
ðdati tradizionali; es: raggio di una circonferenza, coordinata di un punto
ðpossono assumere un insieme molto ampio di valori che variano con continuità
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
G. Mecca - Programmazione Procedurale in Linguaggio C++ 17
Utilizzo di Costanti Simboliche Intere
m
Oggetti della giocata
ðvalori possibili: carta, forbici, sasso
m
Esito della giocata
ðvalori possibili: vince il computer, vince il giocatore, pareggio
m
Dati particolari
ðdati discreti con valori “enumerabili”
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
Utilizzo di Costanti Simboliche Intere
m
Dati di tipo enumerabile
ðo “enumerazioni”ðdati che possono assumere un insieme limitato di valori discreti
ði valori possono essere elencati
m
Altri esempi
ðgiorni della settimana, mesi dell’anno ecc.
m
Come rappresentarli nel programma ?
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
G. Mecca - Programmazione Procedurale in Linguaggio C++ 19
Utilizzo di Costanti Simboliche Intere
m Soluzione 1: stringhe
ðidea: descrivo ciascun valore con una stringa ðstring giocata; es: “carta”, “forbici”, “sasso”
ðstring esitoMano; es: “pareggio”, “vince il computer”
m Vantaggi
ðmodo naturale per rappresentare i valori
m Svantaggi
ðmanipolare le stringhe è poco naturale (es: il giocatore deve digitare ogni volta il nome dell’oggetto che vuole giocare)
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
Utilizzo di Costanti Simboliche Intere
m Soluzione 2: numeri interi
ðidea: associo un valore intero a ciascun valore ðint giocata; es: 1=carta, 2=forbici, 3=sasso
ðint esitoMano; es: 1=vince il computer, 2=vince il giocatore, 3=pareggio
m Vantaggi
ðmanipolare i numeri è più naturale
m Svantaggi
ðbisogna ricordarsi il significato dei valori (quale numero è associato a ogni valore)
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
G. Mecca - Programmazione Procedurale in Linguaggio C++ 21
Utilizzo di Costanti Simboliche Intere
m
Una soluzione di compromesso
ðutilizzare costanti globali interem
Esempio
const int CARTA=1;
const int FORBICI=2;
const int SASSO=3;
const int VINCEILCOMPUTER=1;
const int VINCEILGIOCATORE=2;
const int PAREGGIO=3;
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
Utilizzo di Costanti Simboliche Intere
m
Questa soluzione
ðha i vantaggi dell’utilizzo dei numeri interi ði dati sono più semplici da utilizzare delle
stringhe
ðsenza gli svantaggi
ðil nome della costante consente di disinteressarsi del valore intero scelto
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
G. Mecca - Programmazione Procedurale in Linguaggio C++ 23
Esempio: Esito di una Mano
int controllaEsito(int giocataComp, int giocataGioc) { int esito = VINCEILCOMPUTER;
if (giocataGioc == giocataComp) { esito = PAREGGIO;
} else if ((giocataGioc == CARTA) && (giocataComp == SASSO)) { esito = VINCEILGIOCATORE;
} else if ((giocataGioc == FORBICI)&&(giocataComp == CARTA)) { esito = VINCEILGIOCATORE;
} else if ((giocataGioc == SASSO)&&(giocataComp == FORBICI)) { esito = VINCEILGIOCATORE;
}
return esito;
}
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
Utilizzo di Costanti Simboliche Intere
m
Annotazione
ðil sottoprogramma precedente è scritto secondo una tecnica particolare, detta
“ipotesi e verifica”
m
Ipotesi e Verifica
ðper semplificare il controllo formulo un’ipotesi iniziale (es: ha vinto il computer)
ðpoi verifico solo se l’ipotesi è vera o meno ðquesto mi evita di scrivere vari if in più
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
G. Mecca - Programmazione Procedurale in Linguaggio C++ 25
Generazione di Numeri Casuali
m
Molto spesso nei programmi
ðè necessario effettuare scelte casuali ðprogrammi che simulano il mondo reale
m
Soluzione tipica
ðviene generato un numero a caso
ðal numero a caso viene associata la scelta ðcon una tecnica simile a quella appena
discussa
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
Generazione di Numeri Casuali
m
Generazione di numeri casuali in C++
ðbasata su sottoprogrammi predefiniti ðun processo a due passi
m
Primo passo: inizializzazione
ðscegliere un valore casuale iniziale per
“inizializzare” l’algoritmo di generazione
m
Secondo passo: generazione dei numeri
ðutilizzare la funzione predefinita rand() pergenerare la sequenza di numeri casuali
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
G. Mecca - Programmazione Procedurale in Linguaggio C++ 27
Generazione di Numeri Casuali
m
Primo passo: inizializzazione
ðdeve essere effettuato una sola volta,
all’inizio dell’applicazione, prima di generare il primo numero casuale
ðserve a fornire al calcolatore una “base”
(“seme”) da cui partire per generare tutti gli altri numeri della serie
ðaltrimenti il calcolatore genererebbe sempre gli stessi numeri (comportamento
“deterministico”)
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
Generazione di Numeri Casuali
m
Problema
ðcome scegliere un valore iniziale (o “seme”) davvero casuale che vari tra un’esecuzione all’altra del programma ?
m
Risposta
ðè possibile utilizzare l’orologio di sistema (ora in millisecondi)
ðil valore cambia sicuramente da esecuzione a esecuzione
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
G. Mecca - Programmazione Procedurale in Linguaggio C++ 29
Generazione di Numeri Casuali
m
I sottoprogrammi necessari
ðint time(): funzione che restituisce il valore dell’orologio di sistema
ðvoid srand(int valore): procedura che
inizializza la generazione di numeri casuali con il valore iniziale specificato
m
Esempio
int seme = time(NULL);
srand(seme);
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
Generazione di Numeri Casuali
m
Secondo passo: generazione dei numeri
ðgenerare i numeri usando la funzionepredefinita int rand()
ðogni volta che la funzione viene chiamata, restituisce un numero intero diverso
uniformemente distribuito tra 0 e una
costante RAND_MAX (normalmente 32767)
m
Nota: apparentemente...
ðcomportamento diverso dalle altre funzioni
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
G. Mecca - Programmazione Procedurale in Linguaggio C++ 31
Generazione di Numeri Casuali
m
Esempio:
ðsupponendo di avere inizializzato il generatore di numeri casuali
cout << rand();
cout << rand();
cout << rand();
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
I esecuzione 29
123 76
II esecuzione 12
333 3245
Generazione di Numeri Casuali
m
In generale
ðserve ottenere numeri compresi tra 1 ed n ðes: Morra Cinese: tra 1 e 3
m
Per ottenere numeri tra 1 ed n
rand()% n + 1
m
Esempio
cout << rand() % 3 + 1;
cout << rand() % 3 + 1;
cout << rand() % 3 + 1;
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
il modulo restituisce valori tra 0 e n-1
2 76
1 123
3 29
rand() % 3 + 1 rand()
G. Mecca - Programmazione Procedurale in Linguaggio C++ 33
Generazione di Numeri Casuali
void inizioGioco(string& nome) { int seme = time(NULL);
srand(seme);
schermoIniziale(nome);
return;
}
int generaGiocataComputer() { int giocata;
giocata = rand() % 3 + 1;
return giocata;
}
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
Generazione di Numeri Casuali
m
Nota
ðnonostante la funzione rand() abbia
apparentemente un funzionamento diverso da quello delle altre funzioni, non è così ðanche rand() è basata su un algoritmo
preciso, ovvero a parità di valore del seme, genera sempre la stessa sequenza
ðquello che cambia è il valore del seme
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
G. Mecca - Programmazione Procedurale in Linguaggio C++ 35
Generazione di Numeri Casuali
m
Un esempio
Sottoprogrammi: Conclusioni >> Tecniche Notevoli
#include <iostream.h>
void main() { srand(100);
cout << rand() << endl;
cout << rand() << endl;
cout << rand() << endl;
}
I esecuzione 11548 3973 4846
II esecuzione 11548 3973 4846
Errori Frequenti
m
Alcuni errori frequenti
m
Errori sintattici
ðerrori nelle chiamate
ðerrori nella definizione e nei prototipi
m
Errori logici
ðerrori nell’uso delle proc. e delle funzioni ðerrori di duplicazione del codice
ðerrori nell’uso dei parametri
Sottoprogrammi: Conclusioni >> Errori Frequenti
G. Mecca - Programmazione Procedurale in Linguaggio C++ 37
Errori Sintattici
m Nome scorretto del sottoprogramma
ðes: d = discriminate(a1, b1, c1);
ðError E2268 prova.cpp 10: Call to undefined function 'discriminate' in function main()
m Errore nel numero dei parametri
ðes: d = discriminante(a1, b1);
ðError E2193 prova.cpp 10: Too few parameters in call to 'discriminante(float,float,float)' in function main()
Sottoprogrammi: Conclusioni >> Errori Frequenti
Errori Sintattici
m
Errore nel tipo dei parametri
ðes: float a1, b1; string c1;ðd = discriminante(a1, b1, c1);
ðError E2034 prova.cpp 10: Cannot convert 'char *' to 'float' in function main()
ðError E2342 prova.cpp 10: Type mismatch in parameter 'c' (wanted 'float', got 'char *') in function main()
Sottoprogrammi: Conclusioni >> Errori Frequenti
G. Mecca - Programmazione Procedurale in Linguaggio C++ 39
Errori Sintattici
m
Attenzione
ðutilizzando i prototipi, a volte si verificano errori se viene modificato il sottoprogramma e non il prototipo
m
Esempio:
void sceltaMenu(int &scelta);
void main() {...}
int schermoSceltaMenu(string nome) { ...
}
Sottoprogrammi: Conclusioni >> Errori Frequenti
prototipo e intestazione sono disallineati (nome, parametri,
tipo di ritorno)
Errori Sintattici
m Caso n.1
ðse le chiamate rispecchiano il prototipo, la compilazione si verifica senza problemi ðma c’è un errore a tempo di collegamento ðError: Unresolved external ‘sceltaMenu(int&)'
referenced from E:\TMP\PROVA.OBJ
m Caso n.2
ðse le chiamate rispecchiano l’intestazione
ðError E2268 prova.cpp 10: Call to undefined function
‘schermoSceltaMenu' in function main()
Sottoprogrammi: Conclusioni >> Errori Frequenti
G. Mecca - Programmazione Procedurale in Linguaggio C++ 41
Errori Logici
m
Errore principale
ðutilizzare le funzioni come se fossero procedure
ðes: void main() {
float a1, b1, c1;
leggiEquazione(a1, b1, c1);
discriminante(a1, b1, c1);
...
ðquesto tipo di chiamata non ha senso: non viene utilizzato il valore della funzione
Sottoprogrammi: Conclusioni >> Errori Frequenti
Errori Logici
m
Un altro errore frequente
ðduplicazione del codicem
Obiettivi dei sottoprogrammi
ðguidare il processo di scrittura del codice (ogni passo un sottoprogramma)
ðevitare di riscrivere il codice più volte
m
Di conseguenza
ðdurante la scrittura bisogna evitare di riscrivere due volte lo “stesso” sottoprog.
Sottoprogrammi: Conclusioni >> Errori Frequenti
G. Mecca - Programmazione Procedurale in Linguaggio C++ 43
Errori Logici
m Esempi
ð“acquisire dalla tastiera i dati di due rettangoli nel piano e analizzarli”
ð“acquisire da un file i dati di una serie di giocate del totocalcio e calcolare i punteggi”
ð“acquisire i dati di un triangolo, stamparli, modificare i vertici e stampare i dati del nuovo triangolo” (un solo sottoprogramma di stampa)
m In tutti questi casi
ðgli stessi sottoprogrammi possono essere utilizzati con argomenti diversi (vedi equazioni)
Sottoprogrammi: Conclusioni >> Errori Frequenti
Errori Logici
m
Altri errori nell’uso dei parametri
ðnumero eccessivo di parametri per unsottoprogramma (parametri inutili) – già discusso
ðscambiare parametri standard e parametri per riferimento – già discusso
Sottoprogrammi: Conclusioni >> Errori Frequenti
G. Mecca - Programmazione Procedurale in Linguaggio C++ 45
Esempio di Parametro Inutile
float discriminante (float a, float b, float c float d) {
d = b*b-4*a*c;
return d;
}
void main() {
float a1, b1, c1;
float a2, b2, c2;
float d;
...
if (discriminante(a1, b1, c1, d) >= 0 ...
Sottoprogrammi: Conclusioni >> Errori Frequenti
d dovrebbe essere una variabile locale
void nuovaMano( string nome, int& punteggioComputer, int& punteggioGiocatore, int& pareggi int giocataComputer ) {
int giocataGiocatore;
int esito;
giocataComputer = generaGiocataComputer();
giocataGiocatore = schermoMenuMano(nome);
esito = controllaEsito(giocataComputer, giocataGiocatore);
schermoEsitoMano(nome,esito,giocataComputer,giocataGiocatore);
if (esito == 1)
punteggioComputer++;
else if (esito == 2) punteggioGiocatore++;
else
pareggi++;
return;
}
Esempio di Parametro Inutile
Sottoprogrammi: Conclusioni >> Errori Frequenti
giocataComputer dovrebbe essere
una variabile locale
G. Mecca - Programmazione Procedurale in Linguaggio C++ 47
Esempio di Errore
le1. void leggiEquazione
(float a, float &b, float &c) { le2. cout << “Coefficienti ? ";
le3. cin >> a;
le4. cin >> b;
le5. cin >> c;
le6. return;
le7. }
m1. void main() {
m2. float a1, b1, c1;
m3. float a2, b2, c2;
m4. float x1, y1, x2, y2;
m5. leggiEquazione(a1, b1, c1);
m6. leggiEquazione(a2, b2, c2);
m7. if (...)
Sottoprogrammi: Conclusioni >> Errori Frequenti
Al termine dell’esecuzione - il primo valore acquisito dalla tastiera nella procedura viene perso
- il valore di a1 e di a2 non è cambiato
Riassumendo
m
Ricapitolazione
m
Convenzioni di Stile
m
Alcune Tecniche Notevoli
ðUtilizzo delle Costanti Numeriche ðGenerazione di Numeri Casuali
m
Errori Frequenti
Sottotitolo >> Sommario
G. Mecca - Programmazione Procedurale in Linguaggio C++ 49
Termini della Licenza
m This work is licensed under the Creative Commons Attribution- ShareAlike License. To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/1.0/ or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
Termini della Licenza
m Questo lavoro viene concesso in uso secondo i termini della licenza “Attribution-ShareAlike” di Creative Commons. Per ottenere una copia della licenza, è possibile visitare
http://creativecommons.org/licenses/by-sa/1.0/ oppure inviare una lettera all’indirizzo Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.