Lo scope (visibilità) di elementi del linguaggio (funzioni, variabili, costanti, …) è la regione del programma in cui la variabile può essere usata.
Finora abbiamo incontrato elementi con visibilità:
for
in C++ è possibile dichiarare elementi del linguaggio in qualsiasi punto del programma.
Lo scope di elementi del linguaggio (funzioni, variabili, costanti, …) è dato dalla più piccola istruzione composta (gruppo di istruzioni racchiuso tra due parentesi graffe) che include la sua dichiarazione.
Per questo motivo la variabile i
definita in un for
ha come scope solo il blocco o la singola istruzione che segue il for
ed è sconosciuta all’esterno.
Sempre per questo motivo il parametro di una function
può avere lo stesso nome del parametro effettivo del processo chiamante.
Possiamo definire anche delle variabili globali e delle costanti globali: esse vanno dichiarate all’esterno di qualsiasi function
, compreso il main
.
Il loro scope comprende tutto il programma sorgente in cui è presente.
Se una variabile v
viene definita come globale e poi dichiarata nuovamente locale in una funzione, si dice che la variabile locale v
nasconde la variabile globale v
.
Le dichiarazioni fatte in uno scope nascondono quelle fatte in scope più esterni
Una variabile locale a uno scope ha associata un’area di memoria allocata prima dell’esecuzione dello scope e distrutta al suo termine
Un side-effect è la modifica nel corpo di una funzione di una variabile globale.
Una funzione non dovrebbe avere side-effect:
In un programma è buona norma dichiarare una costante come globale: ogni tentativo di modificarne il valore causa un errore di compilazione.
Esempio: definire le dimensioni di array come costanti globali all’inizio del programma rende più facile ritrovarle per la modifica in un secondo momento
I namespace sono molto utili quando si creano librerie di funzioni:
Possiamo definire un namespace dichiarando e inizializzando nel suo corpo tutti gli elementi che vi appartengono:
Mostra codicePossiamo usare in ogni programma gli elementi di un namespace con l’operatore di scope ::
(risolutore di visibilità)
Se occorre usare spesso gli elementi di un namespace
using namespace nome-namespace;
Tutte le variabili globali possono essere richiamate da ogni funzione o procedura ma non è consigliabile utilizzare le variabili globali così che ogni procedura è autosufficiente
Non ha bisogno di altre variabili oltre le locali e quelle di input/output assegnate nella lista dei parametri formali.
Se tutte le procedure di un programma sono autosufficienti, il programma si dice modulare.
Un programma modulare non ha effetti collaterali (side-effects).
Scrivere del codice senza effetti collaterali è molto semplice: basta fare in modo di servirsi soltanto di variabili che fanno riferimento a termini che o sono dichiarati localmente o sono definiti nella lista dei parametri formali
non deve essere richiamata nessuna variabile globale.
Esiste un particolare operatore, detto operatore condizionale, che rappresenta un’istruzione if... else...
estremamente compattata.
Supponiamo di voler inserire nella variabile intera x il più grande dei valori interi tra a e b:
if (a > b)
x=a;
else
x=b;
Invece adoperando l’operatore condizionale ?
scriveremo:
(a > b) ? x=a : x=b;
L’operatore condizionale è l’unico operatore ternario:
condizione ? espressione A : espressione B
dove condizione è un’espressione logica. L’operazione restituisce il valore dell’espressione A
se la condizione è true
o il valore dell’espressione B
se la condizione è false
Esempio: minimo = a < b ? a : b;
(n % 2==0) ? cout << "pari" : cout << "dispari";
L’operatore condizionale può* restituire un l-value
Esempio:
(m < n ? a : b) = c ;
memorizza il valore di c
in a
se m
è minore di n
, altrimenti memorizza il valore di c
in b
) in questo caso però a e b non possono essere né espressioni né costanti, ma soltanto l-values
.
* non in tutti i compilatori, però!
switch
L’istruzione switch
offre un altro modo per implementare strutture di selezione con diverse alternative.
Occorre riprendere il concetto di tipo ordinale
Tipo per il quale è possibile definire il precedente (tranne il primo) ed il successivo (tranne l’ultimo) di ogni valore.
Alcuni tipi standard sono ordinali:
int
, long int
, char
, bool
sono ordinalifloat
, double
non sono ordinaliswitch
L’istruzione switch
offre un altro modo per implementare strutture di selezione con diverse alternative.
switch
L’istruzione switch è equivalente ad una sequenza di istruzioni if ... else
annidati
Non introduciamo nello pseudocodice una istruzione corrispondente allo switch
, ma lo esprimeremo sempre con istruzioni se … altrimenti annidate
switch
Attenzione alla istruzione break
. La sua omissione permette la verifica dei rimanenti blocchi case
e la conseguente esecuzione delle istruzioni
switch
Attenzione alla istruzione break
. La sua omissione permette la verifica dei rimanenti blocchi case
e la conseguente esecuzione delle istruzioni
switch
Esercizio:
Scrivere un programma che dato in input un voto da 0 a 10 stampi un giudizio secondo la tabella
switch
Esercizi:
Il termometro:
n1 p n2
(n1 p n2) p' n3
…L’istruzione ciclica do … while:
do {
istruzione;
...
} while (condizione);
dove:
condizione
è un’espressione logicafunziona come l’istruzione while
, con la differenza che la condizione è verificata alla fine di ogni iterazione e pertanto il ciclo è sempre eseguito almeno una volta.true
il programma torna all’inizio del ciclo ed esegue una nuova iterazione, se è false, passa all’istruzione successivaEsempio :
dato un array A
contenente n
elementi si vuole verificare se la somma dei suoi elementi è maggiore di un certo valore k
.
In definitiva utilizziamo:
while ( ) ...
quando il corpo del ciclo può anche non essere mai eseguito;do ... while ( )
quando il corpo del ciclo deve essere eseguito almeno una volta.Esercizi:
a) Scrivere un programma che propone le tabelline per un bambino delle elementari. I due fattori da moltiplicare sono generati in modo random ed il computer deve controllare che l’utente risponda esattamente. Quando risponde esattamente, il programma deve generare a caso una delle seguenti risposte:
1) Bravo!! 2) Ottima risposta. 3) Continua così!! 4) Stai nettamente migliorando.
Nel caso di una risposta errata deve rispondere, sempre a caso, con una delle seguenti:
1) Errato. Riprova. 2) Non è la risposta esatta. 3) Fai più attenzione. Riprova 4) Non arrenderti. Prova ancora.
b) Scrivere un main che legge due numeri reali ed un carattere: se il carattere è ‘T’ chiama la prima procedura, se il carattere è ‘R’ chiama la seconda, se è ‘E’ chiama la terza, se è ‘N’ esce dal ciclo inviando un messaggio di saluto, altrimenti stampa: ‘carattere errato’.
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