LE STRUTTURE DI CONTROLLO 3 Come effettuare una scelta Alcuni problemi possono essere risolti utilizzando un approccio sequenziale, in cui le istruzioni da eseguire vengono elencate una dopo l’altra all’interno del codice sorgente e, al momento dell’esecuzione del programma, vengono eseguite nello stesso ordine. Molto spesso, però, l’ per risolvere un problema. approccio sequenziale non è sufficiente esempio Lancia un dado. Se esce 6, allora hai vinto! L’algoritmo che risolve questo problema  deve valutare una condizione ponendosi  la domanda “È uscito 6?” e, in base  alla risposta, può dichiarare che cosa sia  successo. Se vogliamo rappresentare il  diagramma a blocchi dobbiamo scriverlo  come nella figura a lato. La disposizione dei blocchi introdotta nell’esempio precedente prende il nome di , indicata anche come “ ” o in inglese “ ”, o più brevemente (o ). struttura di selezione se… allora… altrimenti… if… then… else… se if La consente di fare una inserendo una condizione di tipo booleano all’interno del blocco di scelta. Nel diagramma , in fase di simulazione il valore di verità della condizione consente di scegliere e percorrere solo una delle due strade possibili. struttura di selezione scelta tra due possibili alternative deve essere indicato come comportarsi in entrambi i casi LINGUAGGIO C La sintassi dell’istruzione if è la seguente: if(condizione) { blocco da eseguire quando la condizione è VERA; } else { blocco da eseguire quando la condizione è FALSA; } esempio Data la massa m (in g) e il volume V (in cm )  3 di un oggetto, calcoliamone la densità (d = m : V)  e stabiliamo se può trattarsi di vetro (d = 2,5 g/cm ). 3 Scriviamo il diagramma a blocchi. LINGUAGGIO C La traduzione del diagramma a blocchi è: #include <stdio.h> int main() { float m, V, d; printf("Inserisci la massa"); scanf("%f",&m); printf("Inserisci il volume "); scanf("%f",&V); d = m/V; if (d == 2.5) {printf("Vetro");} else {printf("Altro");} return 0; } attenzione   In linguaggio C la divisione si indica con /. Con il è possibile indicare chiaramente il punto dell’algoritmo in cui avviene la valutazione della condizione e la conseguente dello schema. Disegnando i due rami alternativi è possibile evidenziare facilmente quali istruzioni devono essere eseguite nei due diversi casi. diagramma a blocchi biforcazione I come il C, invece, gestiscono la biforcazione effettuando dei nel codice. Al momento dell’ se la scritta all’interno delle parentesi tonde risulta essere , allora viene eseguito il primo blocco di istruzioni e il secondo blocco viene saltato. Se invece la risulta essere , allora viene eseguito il secondo blocco di istruzioni e il primo blocco viene saltato. linguaggi di programmazione salti esecuzione del programma condizione vera condizione falsa ApprofondiMENTO   INDENTAZIONE E ANNIDAMENTO Se le istruzioni vengono scritte come un elenco, il codice può risultare difficile da leggere “a colpo d’occhio”. La leggibilità può essere migliorata usando l’ , cioè inserendo nel codice dei rientri che evidenzino visivamente sia i blocchi logici contenuti nei programmi, sia l’eventuale presenza di  , cioè di sotto-blocchi inseriti dentro ad altri blocchi di istruzioni. Per questi rientri (ininfluenti per il computer, ma utili al programmatore) si può scegliere qualunque stile che, però, deve essere mantenuto coerente in tutto il codice. indentazione ▶  annidamento   / annidamento nesting Esempio di indentazione e annidamento nell’istruzione if.  >> pagina 405  Lo “spaghetti code” Alcuni problemi possono essere risolti in modo sequenziale. Per esempio il problema “prepara il caffè usando la caffettiera” potrebbe essere risolto dalla sequenza di istruzioni contenute nell’algoritmo seguente. Tuttavia, non appena il problema si complica, l’ per essere risolto potrebbe diventare piuttosto . algoritmo complesso e contorto I , incluso il linguaggio C, supportano la traduzione di algoritmi, come il precedente, in cui sono presenti diverse diramazioni fornendo le che possono essere di due tipi: linguaggi di programmazione istruzioni di salto 1.   salto condizionato : eseguito o no in base che al verificarsi o meno una determinata condizione (per esempio l’istruzione if); 2.   salto incondizionato : che viene eseguito comunque, essendo privo di condizione. All’interno del codice vengono inserite delle ▶  etichette , come per esempio i nizio : e fine : , e un’istruzione ▶  goto , durante l’esecuzione, permette di saltare direttamente alla posizione indicata dall’etichetta. Il dei programmi che viene definito, in modo dispregiativo, , facendo riferimento all’ che si trova in un piatto di spaghetti: un mucchio di fili (logici) intrecciati e annodati tra loro. codice sorgente contengono salti incondizionati spaghetti code assenza di struttura Lo spaghetti code, in generale, risulta del susseguirsi delle istruzioni che risolvono il problema. Lo scarso controllo sulla logica risolutiva può introdurre nell’algoritmo una serie di difficili da individuare. difficilmente leggibile e impedisce di avere una buona percezione errori logici Negli anni Sessanta la struttura di controllo del salto incondizionato (goto) era molto diffusa. In contrapposizione a questa tendenza, nello stesso periodo, si affermò il paradigma (cioè un modello al quale fare riferimento come termine di paragone) della , che ha come obiettivo quello di del codice sorgente, oltre che semplificarne la manutenzione. programmazione strutturata migliorare la leggibilità e la qualità Oltre ad (estremamente deprecati), la programmazione strutturata stabilisce che il programma deve essere fondamentali, che possono anche essere composte fra di loro nel rispetto di alcune regole prestabilite. abolire i salti incondizionati costruito utilizzando solo le strutture di controllo   / etichetta label   / go to vai a Lo sapevi che Il termine programmazione strutturata venne introdotto dall’informatico olandese Edsger W. Dijkstra il quale affermò, in un documento del 1968, che l’istruzione goto presente in molti linguaggi di programmazione ad alto livello è una delle principali fonti di errori di tipo logico.  >> pagina 407  Il teorema di Böhm-Jacopini Il paradigma della programmazione strutturata si affermò a partire dagli anni Sessanta grazie al contributo dei due matematici e informatici italiani Corrado Böhm (1923 - 2017) e Giuseppe Jacopini (1936 - 2001) che dimostrarono, con il loro teorema (divenuto fondamentale per la programmazione), che contenente dei goto utilizzando solo tre strutture di controllo fondamentali. qualsiasi programma può essere riscritto Il teorema di Böhm-Jacopini afferma che qualsiasi algoritmo può essere scritto utilizzando e combinando fra loro solo tre strutture di controllo: 1. sequenza; 2. selezione; 3. iterazione. Si chiamano perché servono a controllare il percorso all’interno del procedimento risolutivo, per ottenere i risultati desiderati. strutture di controllo Le prime due strutture sono già state introdotte nei paragrafi precedenti; ora formalizziamo i concetti che le riguardano.  >> pagina 408  1 la sequenza La struttura è la più semplice e . sequenza indica l’ordine in cui devono essere eseguite le istruzioni Le contenute nel blocco possono essere di : assegnazioni, input, output, istruzioni di selezione, istruzioni di iterazione o combinazioni di queste. istruzioni varia natura esempio Data la base  e l’altezza,  calcolare l’area  del triangolo. 2 La selezione La è la struttura di controllo che tra due possibili alternative. Per decidere come proseguire nel percorso dell’algoritmo, occorre determinare il valore di verità della condizione contenuta nel blocco di scelta. Se è vera, vengono eseguite le istruzioni del ; viceversa, se è falsa, vengono eseguite quelle del . selezione consente di fare una scelta ramo vero ramo falso Se viene eseguito il blocco di istruzioni A, allora non vengono eseguite quelle del blocco B, che si trovano sull’altro ramo, e viceversa. Le due sono poi il diagramma si ricongiunge e prosegue verso il basso. opzioni in alternativa Solitamente il ramo vero viene disegnato sulla sinistra e quello falso sulla destra, ma nei diagrammi a blocchi è consentita anche l’eventuale , di vero e falso e dei relativi blocchi. Inoltre uno dei due rami, di solito il ramo falso, . inversione può non contenere istruzioni esempio Dati due numeri, visualizzare quello più  piccolo.  >> pagina 409  3 L’iterazione L’iterazione (o ), è la che termina in base al valore di verità della condizione scritta nel blocco di scelta. ▶  ciclo ripetizione di un blocco di istruzioni Nei sono valide entrambe le seguenti possibilità. diagrammi a blocchi Questa struttura può essere considerata la forma più generica di iterazione: può essere utilizzata sia nel caso in cui il nel ciclo sia , sia quando quante volte verranno eseguite le istruzioni contenute all’interno del ciclo; numero di iterazioni conosciuto a priori non è noto il blocco contenuto nel ciclo, potrebbe anche nel caso in cui la condizione verificasse immediatamente l’uscita dal ciclo. non essere mai eseguito   / ciclo loop LINGUAGGIO C Il linguaggio C richede che il ramo  vero sia sempre interno al loop. In fase di esecuzione, l’ istruzione  esamina la condizione e,  while mentre si mantiene vera, esegue  le istruzioni contenute nel ciclo. Se la condizione diventa falsa, il  ciclo termina. Se invece risulta  immediatamente falsa, le istruzioni  nel ciclo non vengono mai  eseguite. La sintassi del è: while while(condizione) { blocco da eseguire mentre la condizione è VERA; }   Approfondimento – Le istruzioni if e while in linguaggio C esempio Data in input una sequenza di numeri  interi che termina quando viene immesso  il valore 0, calcoliamo quanti  numeri sono positivi e quanti negativi,  visualizzando i risultati ottenuti.   Video – Traduzione da algoritmo e pseudocodice   Video – Esempio di algoritmo con utilizzo di diagrammi di flusso LINGUAGGIO C #include <stdio.h> int main()  {  int N, POS, NEG;  printf("Inserisci un numero ");  scanf("%d",&N);  POS = 0;  NEG = 0;  while (N != 0) // in C "diverso" si scrive !=  {  if (N>0)                {POS = POS + 1;}  else                {NEG = NEG + 1;}  printf("Inserisci un numero ");  scanf("%d",&N);  }  printf("positivi = %d, negativi = %d", POS, NEG);  return 0;  }   Approfondimento – Le funzioni in linguaggio C attenzione   In linguaggio C si entra nel ciclo  solo se la condizione è vera. prova tu   Scrivi il diagramma a blocchi. Facendo riferimento al  I: 1 - 7 6 18 -3 2 0 diagramma a blocchi  dell’esempio e utilizzando  l’input seguente, fai una  simulazione dell’algoritmo  seguendo il diagramma e  modificando il valore delle  variabili.  >> pagina 411  I sottoprogrammi I che risolvono problemi nel mondo reale sono generalmente e quindi, per essere realizzati, vengono , collegati logicamente fra loro e richiamati da un programma principale. Il viene che vengono utilizzando una tecnica di analisi e di raffinamento successivo che prende il nome di . programmi molto complessi scomposti in più sottoprogrammi problema suddiviso in sottoproblemi analizzati separatamente metodo ▶  top-down Nella programmazione un sottoprogramma è una sequenza di istruzioni che esegue un compito specifico e può essere utilizzata nei programmi, anche più volte, ovunque occorra eseguire quel particolare compito. esempio Usare i sottoprogrammi introduce due : principali vantaggi 1.   sintesi : lo stesso codice non viene riscritto più volte nel programma, viene solo richiamato ogni volta che occorre ( riuso del codice ). Il programma diventa più compatto e leggibile. La manutenzione del codice diventa più facile e i costi si riducono; 2.   semplicità : suddividendo il problema in sottoproblemi, sviluppare il codice diventa più semplice e meno costoso, si riducono le possibilità di introdurre errori e la qualità del software migliora. In generale nei sottoprogrammi possono essere definite delle , cioè delle variabili che possono essere . Le variabili visibili da tutti i sottoprogrammi e dal programma principale prendono il nome di variabili globali. variabili locali viste solo dal sottoprogramma   / top-down dall’alto verso il basso Diagrammi a blocchi Linguaggio C + + – – x * : / = = = <- = NOT ! AND && OR || ≠ != ≥ >= ≤ <= LINGUAGGIO C I sottoprogrammi vengono implementati  dalle funzioni. Lo sapevi che Il metodo individua le  top-down e le  problematiche più complesse via via in sottoproblemi  suddivide più semplici. L’approccio top-down  è opposto al metodo ,  ▶  bottom-up che partendo dal basso procede  verso l’alto.   bottom-up / dal basso verso l’alto