2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi...

31
2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 - Gli algoritmi 3.3 - Lo pseudocodice 3.4 - Le strutture di controllo 3.5 - La struttura di selezione If 3.6 - La struttura di selezione If/Else 3.7 - La struttura di iterazione While 3.8 - Formulare algoritmi: ciclo controllato da un contatore 3.9 - Formulare algoritmi: ciclo controllato da un valore sentinella 3.10 - Formulazione degli algoritmi: processo top-down a raffinamenti successivi 3.11 - Strutture di controllo annidate 3.12 - Gli operatori di assegnamento 3.13 - Gli operatori di incremento e decremento

Transcript of 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi...

Page 1: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

Capitolo 3 (Deitel)Lo sviluppo di programmi strutturati

Indice degli argomenti

3.1 - Introduzione3.2 - Gli algoritmi3.3 - Lo pseudocodice3.4 - Le strutture di controllo3.5 - La struttura di selezione If3.6 - La struttura di selezione If/Else3.7 - La struttura di iterazione While3.8 - Formulare algoritmi: ciclo controllato da un contatore3.9 - Formulare algoritmi: ciclo controllato da un valore sentinella3.10 - Formulazione degli algoritmi: processo top-down a raffinamenti successivi3.11 - Strutture di controllo annidate3.12 - Gli operatori di assegnamento3.13 - Gli operatori di incremento e decremento

Page 2: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.1 - Introduzione

• Prima di scrivere un programma è importante:– Aver capito bene il problema da risolvere (analisi dei requisiti)

– Evitare di “buttarsi” a scrivere direttamente il codice applicativo

– Avere un approccio pianificato con cura per risolvere il problema

– Spesso torna molto utile risolvere prima il problema “su carta”

• Mentre si scrive un programma è importante:– Sapere quali sono i “mattoni elementari” disponibili per costruirlo

– I mattoni sono dati dai costrutti e dalle funzioni principali offerte dal linguaggio di programmazione scelto per scrivere il programma

– Oltre a conoscere la sintassi del linguaggio, è bene fare uso di buoni principi di programmazione (programmazione strutturata)

Page 3: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.2 - Gli algoritmi

• Problemi computazionali– Qualsiasi problema può essere risolto eseguendo una determinata

sequenza di azioni in un ordine specifico

• Un algoritmo è una procedura risolutiva, cioè un metodo per risolvere un problema– Un algoritmo viene visto in termini di:

• Un insieme di azioni da eseguire

• Un ben definito ordine in cui tali azioni vanno eseguite

– In questa ottica risulta molto simile una “ricetta di cucina”

– Permette di ottenere il risultato desiderato eseguendo in un certo ordine un insieme di istruzioni elementari

• Definire il controllo di un programma – Significa specificare l’ordine in cui le istruzioni devono essere eseguite

Page 4: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.3 - Lo pseudocodice

• Pseudocodice:– E’ un linguaggio artificiale e non formale che aiuta durante lo sviluppo

degli algoritmi– È un linguaggio molto simile alla nostra lingua scritta odierna– E’ indipendente dalla sintassi di qualsiasi linguaggio di programmazione– Non può essere effettivamente eseguito dai calcolatori (non è compilabile)– Viene scritto con un livello di dettaglio molto simile a quello dei comuni

linguaggi di programmazione

– Aiuta a sviluppare l’algoritmo da realizzare e successivamente a formalizzarlo mediante un linguaggio di programmazione:

• Consente di “pensare” il programma ancora prima di scriverlo • E’ facile da tradurre in un programma C corrispondente• Consiste solo di istruzioni eseguibili

Page 5: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.4 - Le strutture di controllo (1/3)

• Esecuzione sequenziale di un programma– Si ha quando le istruzioni vengono eseguite nell’ordine in cui sono scritte

• Trasferimento del controllo– Si ha quando la nuova istruzione eseguita non è quella successiva nella

sequenza fisica di istruzioni scritte nel programma– L’uso eccessivo uso di istruzioni “goto” (salti espliciti, non condizionali)

può creare numerosi problemi:• Gli algoritmi diventano troppo complessi e poco leggibili• L’uso esplicito del “goto” è considerato indice di cattiva programmazione, non

errata ma inutilmente complessa • Per alterare il flusso sequenziale è necessario fare dei salti, ma è bene farli

in modo più “controllato”, semplificando così la struttura del programma

• Strutture di controllo– Sono particolari istruzioni che permettono di alterare in modo controllato il

normale flusso di esecuzione, dove normale significa sequenziale• I salti così ottenuti non complicano la leggibilità del codice dei programmi• Ogni linguaggio di programmazione moderno ha le proprie strutture di controllo

Page 6: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.4 - Le strutture di controllo (2/3)

• Teorema di Bohm-Jacopini: tutti i programmi possono essere scritti usando le 3 seguenti strutture di controllo– Strutture di sequenza: si eseguono le istruzioni nella sequenza scritta

• In C le istruzioni dei programmi sono eseguite sequenzialmente di default

– Strutture di selezione: si eseguono 2 o più blocchi di istruzioni in modo alternativo in base al verificarsi di specifiche condizioni

• In C ce ne sono di 3 tipi: if, if/else e switch (parole chiave/riservate del C)

– Strutture di iterazione: si ripete ciclicamente l’esecuzione di un blocco di istruzioni fino al verificarsi di una determinata condizione

• In C ce ne sono di 3 tipi: while, do/while, e for (parole chiave del C)

• E’ un teorema fondamentale– Dimostra che ogni algoritmo può essere implementato combinando

blocchi di istruzioni sequenziali con salti condizionali (strutture di selezione e cicli)

– Prova che con un’attenta scrittura del codice si evita di ricorrere ai “goto”– Pose le basi della “programmazione strutturata”, che scompone i problemi in

sottoproblemi meno complessi evitando l’uso di salti non condizionali

Page 7: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.4 - Le strutture di controllo (3/3)

• Diagramma di flusso (o a blocchi)– E’ un linguaggio formale per rappresentare graficamente gli algoritmi

• Fornisce uno schema del flusso di esecuzione del programma• Viene costruito usando un insieme di opportuni simboli grafici (blocchi)

connessi tra loro tramite frecce, chiamate “linee di flusso”

– I rettangoli servono ad indicare qualsiasi tipo di azione, tra cui rientrano anche i parallelogrammi per specificare operazioni di I/O

– Gli ovali indicano i punti di inizio e di fine di un programma o di una sezione di codice (nel caso, sono circolari)

– I rombi segnalano la presenza di strutture di controllo:• Si usano sempre e solo le strutture di selezione• I cicli si rappresentano usando in modo opportuno i blocchi di selezione• Per creare strutture complesse si fa uso di vari blocchi di selezione in cascata

• Strutture di controllo a singola-entrata e singola-uscita– Ogni uscita di una struttura di controllo è collegata con l’ingresso della

successiva (pila di strutture di controllo)• I rombi hanno 2 uscite, ma sono mutuamente esclusive a livello di flusso

– In questo modo diventa semplice sviluppare concettualmente i programmi

Page 8: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.5 - La struttura di selezione If (1/2)

• Costrutto di selezione in C: – In generale “If” è usata per scegliere tra 2 sequenze di azioni alternative– Nel caso di If semplice, l’alternativa consiste nel non fare nulla, che

significa proseguire con il normale flusso di esecuzione sequenziale– Esempio in pseudocodice:

Se il voto dello studente è maggiore o uguale a 60 scrivi: “Promosso”

• Se la condizione è vera (true) – Si esegue la stampa dell’affermazione e si passa alla prossima fase– Se invece è false, non si esegue la stampa dell’affermazione e si passa

all’istruzione successiva, ignorando quella di stampa

• Pseudocodice tradotto in Cif ( voto >= 60 )

printf(“Promosso\n");

– Come si può notare, il codice C corrispondente è davvero molto vicino allo pseudocodice che esprime istruzione

– Nel codificare le strutture di controllo, fare uso di rientri e spazi rende i programmi più semplici da leggere

• Comunque il compilatore C ignora rientri e spazi bianchi

Page 9: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.5 - La struttura di selezione If (2/2)

vero

falso

voto >= 60 scrivi Promosso

Una decisione può essere presa considerando qualsiasi espressione ma il risultato sarà sempre di tipo Vero/Falso (2 rami).

In caso di espressioni aritmetiche:

zero - falso

Non zero - vero

Esempio: (3 – 4)dà vero

• Con i diagrammi di flusso:– Si usa il blocco a rombo (simbolo di decisione), per indicare che a questo punto del flusso di

esecuzione si deve prendere una decisione– All’interno del simbolo è contenuta una espressione logica con cui si rappresenta una condizione

che può essere vera o falsa– Il flusso prosegue seguendo l’opportuna linea di flusso in uscita dal rombo– L’uscita da seguire dipende dal verificarsi o meno della condizione– If è comunque una struttura a singola entrata e singola uscita

• Come si nota, i 2 percorsi alternativi conducono al medesimo punto di uscita

Page 10: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.6 - La struttura di selezione If/Else (1/5)

• if– Svolge un blocco di istruzione solo se la condizione è vera

• Altrimenti lo ignora e prosegue con l’esecuzione del resto del codice

• if/else– Esegue sequenze di azioni differenti qualora la condizione sia vera o falsa

• Esegue uno dei due blocchi di codice, il caso “non faccio nulla” qui non esiste • A fine esecuzione del blocco di istruzioni scelto, riprende col resto del codice

• Esempio in pseudocodice: Se il voto dello studente è maggiore o uguale a 60

scrivi“Promosso”altrimenti

scrivi “Bocciato”

• Traduzione nel codice C corrispondente:if ( voto >= 60 ) printf("Promosso\n"); else printf(“Bocciato\n");

%

– Anche in questo caso, notare l’uso opportuno di spazi e rientri del codice

 

Page 11: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.6 - La struttura di selezione If/Else (2/5)

• Operatore condizionale ternario (?:) – E’ un costrutto C equivalente per esprimere una struttura di selezione– Prende tre argomenti (condizione, valore se è vera, valore se è falsa)– Il codice C equivalente all’if/else precedente può essere scritto come segue: printf("%s\n", voto>=60 ? “Promosso" : “Bocciato" ); oppure voto >= 60 ? printf(“Promosso\n”): printf(“Bocciato\n”);

verofalso

“Bocciato” “Promosso”

Voto >= 60

• Diagramma di flusso corrispondente:– I rettangoli rappresentano le azioni e il rombo la decisione da prendere

Page 12: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.6 - La struttura di selezione If/Else (3/5)

• Strutture di if/else annidate– Si controllano diverse condizioni in cascata utilizzando una serie di

strutture di selezione if/else annidate (una dentro l’altra)– Nell’ordine in cui sono scritte, non appena si incontra una condizione

vera, si esegue il relativo blocco di istruzioni e si salta tutto il resto • L’esecuzione poi riprende da dove finisce la serie di if/else annidati

– Esempio in pseudocodice:Se lo studente ha un voto maggiore o uguale a 90

scrivi“A”altrimenti

Se lo studente ha un voto maggiore o uguale a 80 scrivi “B”

altrimenti Se lo studente ha un voto maggiore o uguale a 70 scrivi “C”

altrimenti Se lo studente ha un voto maggiore o uguale a 60 scrivi “D”

altrimenti scrivi “F”

– Rientri del codice così profondi in genere non si usano nella pratica– Non va usata come tecnica per implementare strutture di selezione in cui

la condizione ha più “valori discriminanti”, esiste un apposito costrutto C

Page 13: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.6 - La struttura di selezione If/Else (4/5)

• Istruzioni composte: – Le istruzioni da eseguire in base all’esito della condizione di If/Else

possono essere anche più di una – In tal caso la sequenza di istruzioni sta all’interno di due parentesi graffe

– Esempio:if ( voto>= 60 ) printf( “Promosso.\n" );

else { printf( “Bocciato.\n" ); printf( “Devi ripetere il corso.\n" );}

– Nell’esempio, se le parentesi graffe venissero omesse, l’istruzione printf( “Devi ripetere il corso.\n" );

verrebbe automaticamente eseguita comunque, indipendentemente dall’esito del test della condizione

– Se il gruppo di istruzioni tra le graffe comprende anche dichiarazioni di variabili, si parla di blocco di istruzioni (non più di istruzione composta)

Page 14: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.6 - La struttura di selezione If/Else (5/5)

• Spesso nello scrivere strutture di controllo si fanno errori

• Errori di sintassi:– Causati da una scrittura errata del codice a livello sintattico

– Vengono rilevati dal compilatore

– Impediscono fisicamente l’esecuzione del programma, non si arriva neanche a generarne il codice oggetto (.out)

• Errori logici: – Il codice è scritto correttamente a livello sintattico, ma la sequenza di

istruzioni è mal progettata (concettualmente)

– Se ne vedono gli effetti solo durante l’esecuzione (il compilatore da l’ok)

– Se sono fatali, il programma termina prematuramente (ovvero non riesce ad eseguire tutte le istruzioni previste dal codice) ed in modo anomalo

– Se non sono fatali, il programma funziona comunque, ma non restituisce l’output desiderato/atteso

– Creando cicli mal controllati, possono anche verificarsi dei loop infiniti

Page 15: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.7 - La struttura di iterazione While

• E’ una struttura iterativa– While consente al programmatore di specificare un azione che viene

ripetuta finché una determinata condizione rimane vera

– Più in generale, While crea un ciclo (loop) di esecuzione di un blocco di istruzioni da cui è possibile uscire solo quando la condizione diventa falsa

– Quando si esce dal ciclo, si riprende con l’esecuzione del resto del codice

– Esempio in pseudocodice: Finché ci sono articoli sulla mia lista della spesa compra l’articolo successivo e cancellalo dalla mia lista

• Esempio (diagramma di flusso e codice C):

 

prodotto=2*prodottoprodotto<=1000vero

falso

int prodotto = 2;

while ( prodotto <= 1000 ) prodotto = 2 * prodotto;

Page 16: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.8 - Formulare algoritmi: ciclo controllato da un contatore (1/3)

• Iterazione controllata tramite contatore– E’ una tecnica comunemente usata per risolvere un certo tipo di problemi

e fa uso del costrutto While– Si usa una variabile, detta contatore, per specificare il numero di iterazioni– Il ciclo viene ripetuto finché il contatore non raggiunge il valore designato– E’ un’iterazione definita: il numero di ripetizioni del ciclo è noto a

priori– Esempio di applicazione ad un problema: Una classe di 10 studenti sostiene un esame. Conoscendo le votazioni (numeri

interi da 0 a 100), determinare la media della classe in questo esame.

• Soluzione in pseudocodice: Inizializza il totale a zeroInizializza il contatore dei voti a unoFinché il contatore dei voti resta minore o uguale a 10

Acquisisci in input il prossimo votoAggiungi il voto al totaleAggiungi uno al contatore

Assegna alla media il totale dei voti diviso 10Visualizza la media

Page 17: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.8 - Formulare algoritmi: ciclo controllato da un contatore (2/3)

1 /* Fig. 3.6: fig03_06.c2 Programma per il calcolo della media di una classe

3 tramite un ciclo controllato da un contatore */4 #include <stdio.h>56 int main(){7 int contatore, voto, totale, media;

8

9 totale = 0; /* fase di inizializzazione */

10 contatore = 1;

11

12 while ( contatore <= 10 ) { /* fase di elaborazione */13 printf( “Inserisci il voto: " );14 scanf( "%d", &voto );15 totale = totale + voto;16 contatore = contatore + 1; 17 }1819 media = totale / 10; /* fase di terminazione */20 printf( “La media della classe è %d\n", media );

2122 return 0; /* indica che il programma e` terminato con successo */23 }

1. Inizializzazione delle variabili

2. Esecuzione del ciclo

3. Output del risultato

Page 18: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.8 - Formulare algoritmi: ciclo controllato da un contatore (3/3)

Inserisci il voto: 98Inserisci il voto: 76Inserisci il voto: 71Inserisci il voto: 87Inserisci il voto: 83Inserisci il voto: 90Inserisci il voto: 57Inserisci il voto: 79Inserisci il voto: 82Inserisci il voto: 94La media della classe è 81

Visualizzazione del programma

Page 19: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.9 - Formulare algoritmi: ciclo controllato da un valore sentinella

• Variante del problema precedente:Sviluppare un programma per il calcolo della media di una classe, che elabori un numero arbitrario di votazioni ogni volta che il programma viene eseguito.

– In questo caso non si conosce a priori il numero di studenti/voti – Come fa il programma a sapere quando termina l’inserimento dei voti?

• Si deve usare un valore sentinella – Anche chiamato valore di segnalazione, dummy (fittizio) o flag (bandiera)– Qui serve ad indicare esplicitamente la “fine dell’immissione dei dati”– Il numero di iterazioni da compiere non è noto a priori per cui il ciclo

termina solo quando viene inserito in input tale valore– Il valore sentinella deve essere scelto in modo da non essere confuso con

un valore di input accettabile (-1 è adeguato per questo esempio)

Page 20: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.10 - Formulazione di algoritmi: processo

Top-Down a raffinamenti successivi (1/4)• Tecnica Top-down (dall’alto in basso)

– Si inizia con una rappresentazione in pseudocodice del top (istruzione con cui si specifica il requisito principale del programma) Determina la media della classe per l’esame

– Si divide il top in una serie di attività più piccole e semplici da realizzare, elencate nell’ordine in cui vanno eseguite (processo di raffinamento):

Inizializza le variabiliAcquisisci i valori di input, somma e conta i voti dell’esameCalcola e visualizza la media della classe

• Molti programmi consistono di tre fasi principali:– Inizializzazione: dichiara ed inizializza le variabili del programma– Elaborazione: acquisisce i dati in input e aggiorna i valori delle variabili

in gioco sulla base dati acquisiti– Terminazione: calcola e visualizza i risultati finali (output)– Questo regola generale aiuta a scomporre i programmi applicando la

tecnica del processo top-down per raffinamenti successivi

Page 21: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.10 - Formulazione di algoritmi: processo

Top-Down a raffinamenti successivi (2/4)• Raffinamento della fase di inizializzazione:

– Scomponendo l’istruzione Inizializza le variabili si ottiene:Inizializza il totale a zeroInizializza il contatore a zero

• Raffinamento della fase di elaborazione: – Scomponendo l’istruzione Acquisisci i valori in input, somma e conta

i voti dell’esame si ottiene: Aquisisci in input il primo voto (che potrebbe già essere il valore sentinella)Finchè l’utente non ha ancora inserito il valore sentinella

Aggiungi il voto al totale correnteAggiungi uno al contatore dei votiAquisisci in input il prossimo voto (che potrebbe essere il valore

sentinella)

• Raffinamento della fase di terminazione: – Scomponendo l’istruzione Calcola e visualizza la media della classe si

ottiene:Se il contatore dei voti non è uguale a zero

Imposta la media con il totale diviso per il contatore dei votiVisualizza la media

altrimentiVisualizza “Non è stato inserito nessun voto”

Page 22: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.10 - Formulazione di algoritmi: processo

Top-Down a raffinamenti successivi (3/4)

1 /* Fig. 3.8: fig03_08.c

2 Programma per il calcolo della media di una classe

3 tramite un ciclo controllato da un valore sentinella */

4 #include <stdio.h>

5

6 int main(){7 float media; /* nuovo tipo di dato */

8 int contatore, voto, totale;

9

10 totale = 0; /* fase di inizializzazione */

11 contatore = 0;

12

13 /* fase di elaborazione */

14 printf( “Inserisci il voto, -1 per terminare: " );

15 scanf( "%d", &voto );

16 while ( voto != -1 ) {

17 totale = totale + voto;

18 contatore = contatore + 1;

19 printf( “Inserisci il voto, -1 per terminare: " );

20 scanf( "%d", &voto );

21 }

1. Inizializzazione delle variabili

2. Acquisizione del primo valore in input

3. Esecuzione del ciclo (solo se il primo input non è già il flag)

Page 23: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.10 - Formulazione di algoritmi: processo

Top-Down a raffinamenti successivi (4/4)

4. Calcolo della media

5. Output dei risultati

23

24 /* fase di terminazione */

25 if ( contatore != 0 ) {

26 media = ( float ) totale / contatore;

27 printf( “La media della classe è %.2f", media );

28 }

29 else

30 printf( “Non è stato inserito nessun voto\n" );

31 return 0; /*indica che il programma è terminato con successo*/

32 }

Inserisci il voto, -1 per terminare: 75Inserisci il voto, -1 per terminare: 94Inserisci il voto, -1 per terminare: 97Inserisci il voto, -1 per terminare: 88Inserisci il voto, -1 per terminare: 70Inserisci il voto, -1 per terminare: 64Inserisci il voto, -1 per terminare: 83Inserisci il voto, -1 per terminare: 89Inserisci il voto, -1 per terminare: -1La media della classe è 82.50

Visualizzazione del programma

Nota: se si omette (float) davanti alla divisione, essa ritornerà un numero intero, invece che con virgola, ovvero float, come desiderato nell’esempio

Page 24: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.11 - Strutture di controllo annidate (1/5)

• Altra variante del problema iniziale– Un college ha la lista dei risultati (1 = promosso, 2 = bocciato) degli

esami di 10 suoi studenti – Si vuole scrivere un programma che analizzi i risultati e, se più di 8

studenti sono stati promossi, scriva “Si devono aumentare le tasse!“

• Va notato che:– Il programma deve processare 10 risultati d’esame

• Sarà quindi necessario usare un ciclo controllato da un contatore

– Si possono usare due contatori separati• Uno che conta il numero di promossi, l’altro per il numero di bocciati

– Ogni esito d’esame consiste in un numero (1 oppure 2)• Quindi se tale numero non è 1, allora si suppone che sia un 2

– Il problema può essere risolto annidando tra loro diversi tipi di strutture di controllo (while e if/else)

– Si può anche usare un solo contatore e ottenere il numero dei bocciati come differenza rispetto ai 10 risultati totali (o viceversa)

Page 25: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

• Rappresentazione in pseudocodice del top:Analizza i risultati dell’esame e decidi se vanno aumentate le tasse scolastiche

• Esito del primo raffinamento (standard)Inizializza le variabili

Acquisisci in input le dieci valutazioni dell’esame e conta il numero di promossi e di bocciati

Visualizza un riassunto dei risultati d’esame e decidi se aumentare o meno le tasse scolastiche

• Raffinamento della fase di inizializzazione– Scomponendo l’istruzione Inizializza le variabili si ottiene:

Inizializza il contatore delle promozioni a zeroInizializza il contatore delle bocciature a zero

Inizializza il contatore degli studenti a uno

3.11 - Strutture di controllo annidate (2/5)

Page 26: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

• Raffinamento della fase di elaborazione– Scomponendo l’istruzione Acquisisci in input le dieci valutazioni dell’esame

e conta il numero di promossi e di bocciati si ottiene: Finché il contatore degli studenti è minore o uguale a dieci

Acquisisci in input il prossimo risultato d’esame Se lo studente è stato promosso

Aggiungi uno al contatore dei promossialtrimenti Aggiungi uno al contatore dei bocciati

Aggiungi uno al contatore degli studenti

• Raffinamento della fase di terminazione– Scomponendo l’istruzione Visualizza un riassunto dei risultati d’esame e

decidi se aumentare o meno le tasse scolastiche si ottiene:Visualizza il numero dei promossiVisualizza il numero dei bocciati

Se più di otto studenti sono stati promossi Visualizza “Si devono aumentare le tasse!”

3.11 - Strutture di controllo annidate (3/5)

Page 27: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.11 - Strutture di controllo annidate (4/5)

1 /* Fig. 3.10: fig03_10.c2 Analisi dei risultati dell’esame */3 #include <stdio.h>45 int main(){6 /* inizializza le variabili nelle dichiarazioni */7 int promossi = 0, bocciati = 0, studente = 1, risultato;89 /* elabora 10 studenti; ciclo controllato da un contatore */10 while ( studente <= 10 ) {11 printf( “Inserisci il risultato ( 1=promosso,2=bocciato ):" );12 scanf( "%d", &risultato );13 if ( risultato == 1 ) /* if/else annidato nel while */14 promossi = promossi + 1;15 else16 bocciati = bocciati + 1;

17 studente = studente + 1;18 }1920 printf( “Promossi %d\n", promossi ); /* stampa dei risultati */21 printf( “Bocciati %d\n", bocciati );22 if ( promossi > 8 )23 printf( “Si devono aumentare le tasse\n" );24 return 0; /* il programma termina con successo */

35 }

1. Inizializzazione delle variabili

2. Inserimento dati e conteggio del numero di promossi e bocciati

3. Output dei risultati

Page 28: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.11 - Strutture di controllo annidate (5/5)

Visualizzazionedel programma

Inserisci il risultato (1=promosso,2=bocciato): 1Inserisci il risultato (1=promosso,2=bocciato): 2Inserisci il risultato (1=promosso,2=bocciato): 2Inserisci il risultato (1=promosso,2=bocciato): 1Inserisci il risultato (1=promosso,2=bocciato): 1Inserisci il risultato (1=promosso,2=bocciato): 1Inserisci il risultato (1=promosso,2=bocciato): 2Inserisci il risultato (1=promosso,2=bocciato): 1Inserisci il risultato (1=promosso,2=bocciato): 1Inserisci il risultato (1=promosso,2=bocciato): 2Promossi 6Bocciati 4

Page 29: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.12 - Gli operatori di assegnamento

• Sono operatori che permettono di abbreviare la scrittura delle espressioni di assegnamento– Esempio: c = c + 3; può essere abbreviato con c += 3; usando

l’operatore di assegnamento per la somma

• Più in generale, ogni istruzione nella formavariabile = variabile operatore espressione;

può essere riscritta con gli operatori di assegnamento comevariabile operatore= espressione;

• Gli operatori aritmetici di assegnamento sono:c += 3 equivalente a (c = c + 3)d -= 4 equivalente a (d = d - 4)e *= 5 equivalente a (e = e * 5)f /= 3 equivalente a (f = f / 3)g %= 9 equivalente a (g = g % 9)

Page 30: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.13 - Gli operatori di incrementoe decremento (1/2)

• Operatore di incremento (++)– Esempio: c+=1; può essere abbreviato con c++; ma solo per

incrementi unitari

• Operatore di decremento (--) – Esempio: c-=1; può essere abbreviato con c--; ma solo per

decrementi unitari

• Pre-incremento– L’operatore è anteposto alla variabile (++c o --c) – Prima di tutto si incrementa la variabile su cui agisce l’operatore– Poi si esegue l’intera espressione contenente l’operatore, utilizzando

quindi il nuovo valore della variabile, già incrementato/decrementato

• Post-incremento– L’operatore è messo dopo la variabile (c++ o c--)– Prima si esegue l’intera espressione contenente l’operatore,

utilizzando il valore corrente della variabile – Solo successivamente la variabile viene incrementata/decrementata

Page 31: 2000 Prentice Hall, Inc. All rights reserved. Capitolo 3 (Deitel) Lo sviluppo di programmi strutturati Indice degli argomenti 3.1 - Introduzione 3.2 -

2000 Prentice Hall, Inc. All rights reserved.

3.13 - Gli operatori di incrementoe decremento (2/2)

• La differenza sta nel valore assunto dalla variabile all’interno dell’espressione in cui compare l’operatore– Assume lo stesso valore che aveva prima (post) – Oppure assume il valore già aggiornato (pre)– Esempio: se si assume che, prima delle seguenti istruzioni, c = 5, allora

printf( "%d", ++c); Visualizza 6 printf( "%d", c++); Visualizza 5

– In entrambi i casi, dall’istruzione successiva a quella contenente l’operatore, si userà sempre e comunque il valore incrementato

• Nell’esempio, dopo la printf c vale 6 in entrambi i casi

• Quando la variabile pre/post-incrementa non è all’interno di una espressione, pre/post-incremento hanno lo stesso effetto

– Le due coppie di istruzioni seguenti sono hanno lo stesso effetto:

++c; c++; printf( "%d", c); printf( "%d", c);