Flow chart : diagrammi di flusso
Esistono diversi modi per scrivere e rappresentare un algoritmo, un metodo molto diffuso, è quello che utilizza i diagrammi a blocchi anche chiamati flow chart o diagrammi di flusso. La diagrammazione a blocchi è una rappresentazione grafica, di facile interpretazione per chiunque ed è molto efficace perché permette di definire in maniera visuale la struttura di un algoritmo e i suoi costrutti di programmazione.
Vengono utilizzati simboli grafici (chiamati blocchi) che contengono le istruzioni: esistono quattro tipi di blocchi aventi forme geometriche diverse per distinguere le quattro tipologie possibili di operazioni. Un diagramma di flusso che descrive un algoritmo viene disegnato usando esclusivamente questi solo quattro simboli. Le quattro tipologie di blocchi sono:
blocco di inizio/fine: è un blocco di forma ovale, cioè senza spigoli, che viene utilizzato solo come primo e ultimo blocco del diagramma; al suo interno viene scritto "start" oppure "stop"; serve per indicare il punto iniziale e finale dell'algoritmo.
blocco di trasferimento di informazione (comunicazione I/O): è un blocco a forma di parallelogramma che viene utilizzato per comunicare informazioni all'utente o per inserire dati nella procedura, cioè per eseguire operazioni di INPUT e OUTPUT; si usa indifferentemente per input da tastiera ed output a video;
serve dunque per la lettura dati, scrittura risultati, visualizzazione dati intermedi .
blocco di elaborazione: è un blocco di forma rettangolare che viene usato per contenere istruzioni che effettuano trasformazione di dati; operazioni aritmetiche, assegnazioni etc..
serve dunque all'esecuzione di calcoli e all'elaborazione.
blocco di decisionale (condizionale): è un blocco di forma romboidale, al suo interno vengono effettuate operazioni di confronto (test) che si riassumono in domande che possono avere come risultato esclusivamente due valori: true (T) oppure false (F) cioè vero oppure falso.
I blocchi vengono collegati tra di loro nei flow chart con delle linee terminanti con frecce (arco orientato), in modo da indicarne il verso di percorrenza:
In ogni diagramma deve essere presente un solo blocco di inizio e, soprattutto, un solo blocco di terminazione: anche se nel diagramma saranno presenti percorsi alternativi proprio in base ai risultati della istruzione di decisione, tutti i percorsi alternativi devono ricongiungersi prima della fine del diagramma.
Costrutto if
Costrutto if è la struttura di alternativa per la selezione, ed è ditato della seguente sintassi:
if(condizione){
istruzioni-a;
} else{
istruzioni-b;
}
Se la condizione assume valore logico vero sarà eseguito il blocco di istruzioni-a (o il blocco di istruzioni corrispondenti all'if); nel caso la condizione assume valore logico falso, se è presente il ramo else verrà eseguito il blocco di istruzioni corrispondente (istruzioni-b). Si deve osservare che l'esecuzione di una delle due parti esclude l'altra.
La clausola else è opzionale, in tal caso non esiste un eventuale ramo else da eseguire.
if(condizione){
istruzioni-a;
}
Costrutto if-else-if
E' un'istruzione comune nella programmazione ed è costituito da una serie di if-else-if riuniti a formare una struttura a scala:
if(condizione-a){istruzioni-a;}
else if(condizione-b){istruzioni-b;}
else if(condizione-c){istruzioni-c;}
...
else {istruzioni-n;}
il calcolatore inizia la valutazione delle espressioni condizionali dall'alto verso il basso, esegue la prima istruzione corrispondente al verificarsi di una condizione e abbandona la catena di if. Se non si verifica nessuna condizione viene eseguito l'else finale che ha il significato concettuale di condizione di default. Se non è presente l'else finale, qualora non si sia verificata nessuna delle condizioni non viene intrapresa alcuna azione.
Espressioni condizionali
Le espressioni condizionali possono essere facilmente formulate più genericamente con la sintassi
(condizione) ? ramoIf : ramoElse;
Viene dapprima valutata la condizione logica, se è vera viene eseguito il blocco di istruzioni costituito dal ramoIf altrimenti viene eseguito il ramoElse. Ad esempio l'espressione
(a>b) ? max=a : max=b;
determina il massimo tra i valori delle due variabili a e b assegnandolo alla variabile max.
Nelle espressioni condizionali non si è vincolati ad usare espressioni operatori relazionali e logici, è richiesto soltanto che la valutazione dell’espressione condizionale porti soltanto ad un valore uguale a zero (falso) o diverso da zero (vero). Ad.es. nel seguente programma si esegue la divisione fra due interi e si usa un’espressione if per evitare la divisione per zero:
main(){
int a=3, b=2;
if(b) cout<<a/b;
else cout<<"impossibile";
}
Bisogna quindi considerare che l'espressione come if(b) equivale all'espressione if(b!=0) e l'espressione if(!b) equivale a if(b==0).
Costrutto switch
Nonostante if-else-if consenta di realizzare dei
test multipli è da considerare una struttura poco elegante e di difficile
lettura.
L'istruzione ufficiale per eseguire un test multiplo è lo switch.
In tal caso il valore di una variabile viene confrontato con una lista di
costanti che possono essere di di tipo
intero o char, quando si verifica l'uguaglianza si esegue il blocco di istruzioni
corrispondenti. Sintassi:
switch(variabile){
case costante1:istruzioni-1;break;
case costante2:istruzioni-2; break;
...
case costante-n:istruzioni-n; break;
default:istruzioni;
}
La parte default è opzionale, se è presente viene eseguita nel caso in cui non si verifichi alcuna corrispondenza. Se non è presente la clausola di default e non ci sono corrispondenze, non viene eseguita alcuna azione. Quando viene trovata una corrispondenza sono esegute le istruzioni associate al case fino all'istruzione break che causa un'uscita forzata dal costrutto. E' bene specificare quanto segue:
1 I test eseguiti nello switch
possono verificare solo uguaglianze, a differenza di quelli eseguiti nell'if-else-if
che possono verificare condizioni di qualsiasi tipo.
2 Non possono esserci due case
con lo stesso valore di costante nello stesso switch.
Possono invece avere lo stesso valore due case collocati
in due switch diversi.
Un tipico esempio dell'uso di switch lo abbiamo nelle operazioni gestite
tramite un bancomat.
char ch;
cout<<"1.prelievo\n";
cout<<"2.lista movimenti\n";
cout<<"3.saldo\n";
cin>>ch;
switch(ch){
case '1':prelievo();break;
case '2':lista();break;
case '3':saldo();break;
default:cout<<"nessuna opzione selezionata";
}//end switch
Ciclo for
Il ciclo for è un costrutto presente in tutti i linguaggi di programmazione procedurale. La sua forma generale è la seguente:
for(inizializzazione;
condizione; incremento){
istruzioni;
}
l'inizializzazione è, nella sua forma più semplice un istruzione di assegnamento
con la quale il compilatore posiziona il valore iniziale della variabile
di controllo del ciclo.
La condizione è una espressione relazionale usata per valutare la variabile
di controllo al fine di determinare il momento di uscita dal ciclo; l'esecuzione
prosegue fintanto che la condizione è vera, mentre quando diviene falsa
l'esecuzione del programma continua dall'istruzione successiva al for.
L'incremento definisce il modo in cui la variabile di controllo cambia il
suo valore ad ogni ripetizione del ciclo. Queste
tre parti devono essere separate da un punto e virgola. le istruzioni
da eseguire in modo iterativo possono anche essere più di una.
In presenza di più istruzioni è necessario racchiuderle tra una coppia di
parentesi graffe. Negli esempi seguenti i è la variabile
di controllo (sempre di tipo int).
l'esempio seguente scrive i numeri dall' 1 al 10 sullo schermo:
int i;
for(i=1;i<=10;i++) cout<<i;
il programma pone la variabile i a 1 chiama l'istruzione cout fino a quando i rimane minore o uguale a 10; questa operazione si ripete sino a quando i non diventa maggiore di 10, momento in cui il ciclo ha fine.In questo caso le parentesi graffe non sono indispensabili in quanto il corpo del ciclo è costituito da un unica istruzione.
int x;
for(int i=0;i<10;i++) {
cout<<"inserisci un numero:";
cin>>x;
}
Uscita prematura da un ciclo for
Le considerazioni precedenti non implicano che un dato ciclo debba eseguire
necessariamente le sue n iterazioni previste, questo perchè l'istruzione
break ne provoca la terminazione forzata
char ch;
for(int i=0;i<10;i++) {
cout<<"inserisci una lettera:";
cin>>ch;
if(ch=='Z') break;
}
il programma accetterà l'inserimento di 10 lettere da tastiera, ma non ci saranno necessariamente 10 iterazioni, infatti, se venisse inserita la lettera 'Z' il ciclo terminerebbe istantaneamente senza necessariamente eseguire 10 acquisizioni.
Ciclo while
Un ciclo con ripetizione precondizionale prevede il controllo iniziale della condizione; esso si rappresenta con l'istruzione while
while(condizione){
istruzioni;
}
Interessante notare come il listato seguente stampi tutti i numeri da 10 a 20;
int x=9;
while(x<20){
x++;
cout<<" "<<x;
}//fine while
mentre il listato seguente stampa solo 50:
int x=50;
while(x<20){
x++;
cout<<" "<<x;
}//fine while
il ciclo while non viene eseguito neanche una volta. In tal caso la variabile di controllo non soddisfi sin da subito la condizione logica del while.
Ciclo do-while
Il costrutto di ripetizione condizionale si rappresenta con il ciclo do-while:
do{
istruzioni;
}while(condizione);
la sequenza di istruzioni compresa tra il do e il
while viene ripetuta tante volte mentre la condizione
scritta dopo il while si mantiene vera; in altre
parole la ripetizione termina quando la condizione diventa falsa.
A differenza dei cicli for e while
che verificano la condizione all'inizio del ciclo, il do-while
la verifica alla fine, con la conseguenza che il do-while
viene eseguito almeno sempre una volta.
Il listato seguente, stampa la serie di numeri da 10 a 20.
int x=9;
do{
x++;
cout<<" "<<x;
}while(x<20);
Il listato seguente stampa 51 a dimostrazione del fatto che il ciclo do-while viene eseguito, comunque, almeno una volta
int x=50;
do{
x++;
cout<<" "<<x;
}while(x<20);