Vai al contenuto
Appunti di InformaticaUniTo · 2026/27

Programmazione I · Teoria · Canale B · Lezione 03D

Dal flusso sequenziale alle decisioni, if ed else

Con le espressioni booleane della 03C il programma sa farsi una domanda. Con if impara a scegliere: se la risposta è sì fa una cosa, se è no ne fa un'altra. È il primo passo per uscire dalla fila di istruzioni sempre uguale.

Slide
03D_decisioni («Dal flusso sequenziale alle decisioni») · 25 pagine
Corso
Prof. Elvio Amparore · A.A. 2026/27
Tempo di studio
75 minuti, meglio con gcc a portata di mano
  • Definizione o risultato da sapere
  • Trappola / errore tipico
  • Conta all'esame
  • Oltre le slide
  • L'idea e il metodo, passo per passo
  • Da ricordare

La lezione in 7 punti

  • Ogni programma si costruisce con tre strutture: sequenza (una istruzione dopo l'altra), selezione (scegliere) e iterazione (ripetere). Bastano per qualunque algoritmo: è il teorema di Böhm-Jacopini del 1966.
  • if (condizione) { … } esegue il blocco solo se la condizione è vera; altrimenti lo salta.
  • if … else sceglie tra due blocchi: uno se la condizione è vera, l'altro se è falsa.
  • else if mette in fila più domande: si entra nel primo blocco con la condizione vera, e gli altri si saltano.
  • Gli errori più comuni: = al posto di ==, le graffe dimenticate, le condizioni nell'ordine sbagliato. Con -Wall -Werror i primi due non compilano.
  • Una variabile dichiarata dentro un blocco esiste solo lì: alla } sparisce dallo stack.
  • Gli schemi da sapere: il massimo di due numeri, il controllo dell'input con scanf, la divisione protetta, il controllo di un intervallo.

Canali A, B e C

Canale B. È la seconda parte della lezione di mercoledì 14/10, dalle 9 alle 11, dopo la 03C sulle espressioni booleane. Lo scambio condizionato riprende la 03A, e il disegno della memoria è quello della 02B.

Canali A e C. Secondo l'elenco delle lezioni 2025/26 nella scheda del corso, nel canale A (Fiandrotti) c'è un deck su if-else dopo quello sui booleani; nel canale C (Mazzei) è la lezione 05 «IF». Le slide 2026/27 dei canali A e C non le ho viste. L'esame è unico.

Un avviso sulle slide. Gli esempi delle slide 13–20 cominciano con void main(). Con gcc 16.1 e -Wall -Werror, come all'esame, non compilano: error: return type of 'main' is not 'int'. In questi appunti li scrivo con int main(void). Senza opzioni compilano, e le stampe sono quelle delle slide.

Tutti i programmi li ho compilati e provati con gcc 16.1, con -Wall -Werror.

§1

Tre strutture bastano

slide 2–3

Pensa a una ricetta. Ci sono passi da fare in fila: «sbatti le uova, aggiungi la farina». Ci sono scelte: «se l'impasto è troppo duro, aggiungi latte». E ci sono ripetizioni: «mescola finché non ci sono più grumi». Con questi tre tipi di passo si scrive qualunque ricetta.

I programmi funzionano allo stesso modo. La programmazione strutturata usa tre strutture di controllo:

StrutturaChe cosa faIn C
sequenzaesegue le istruzioni una dopo l'altra, nell'ordinequello fatto finora
selezionesceglie tra strade diverse con una condizioneif, else
iterazioneripete un blocco finché una condizione è verawhile, for, do-while

Negli anni '60 non era ancora chiaro quali strumenti servissero per descrivere l'ordine delle istruzioni: molti programmi saltavano da un punto all'altro, come la versione V5 della lezione 01A. Nel 1966 Corrado Böhm e Giuseppe Jacopini, due informatici italiani, hanno dimostrato che sequenza, selezione e iterazione bastano per scrivere qualunque algoritmo. È il teorema di Böhm-Jacopini, e da lì vengono i linguaggi di oggi: pochi pezzi semplici, che si mettono uno dentro l'altro per costruire programmi complicati quanto si vuole.

In questa lezione c'è la selezione. L'iterazione arriva con while e for.

Prova tu

Nella frase «ripeti finché non hai letto un numero valido, e se è negativo cambiagli segno», quali strutture ci sono?

Un'iterazione («ripeti finché») e una selezione («se è negativo»). Le due istruzioni, leggere e cambiare segno, sono in sequenza.

Da ricordare

  • Le tre strutture: sequenza, selezione, iterazione.
  • Per il teorema di Böhm-Jacopini bastano per qualunque algoritmo.
§2

Il costrutto if

slide 4–5

L'esempio delle slide: se piove prendo l'ombrello, altrimenti esco senza. Il programma arriva a un bivio, si fa una domanda, e segue una delle due strade. Si chiama controllo di flusso condizionato: il «flusso» è l'ordine in cui le istruzioni vengono eseguite.

La forma più semplice ha una sola strada in più:

if (condizione) {
    // codice eseguito solo se la condizione è vera
}
  • Se la condizione è vera (cioè diversa da 0), il programma entra nel blocco tra le graffe.
  • Se è falsa (cioè 0), salta il blocco e continua dopo la }.

La condizione è un'espressione booleana della 03C, sempre tra parentesi tonde. L'esempio delle slide:

int voto = 25;
if (voto >= 18) {
    printf("Esame superato!\n");
}

Stampa Esame superato!. Con voto = 15 non stampa niente: il blocco viene saltato.

Prova tu

Che cosa stampa questo codice con n = 4? E con n = 9? if (n % 2 == 0) { printf("pari "); } printf("fine");

Con 4 stampa pari fine. Con 9 stampa solo fine: la seconda printf è fuori dal blocco e viene eseguita sempre.

Da ricordare

  • if (condizione) { … }: il blocco si esegue solo se la condizione è vera.
  • Quello che sta dopo la } si esegue sempre.
§3

Due strade: if-else

slide 6

Con else, «altrimenti», il programma ha due strade, e ne percorre sempre esattamente una:

if (condizione) {
    // blocco A: se la condizione è vera
}
else {
    // blocco B: se la condizione è falsa
}

L'esempio delle slide è la batteria del telefono:

int batteria = 15;

if (batteria < 20) {
    printf("Batteria quasi scarica! Collega il caricatore.\n");
}
else {
    printf("Batteria sufficiente.\n");
}

Con 15 stampa il primo messaggio, con 20 o più il secondo. Non succede mai che stampi tutti e due, e nemmeno che non ne stampi nessuno.

Prova tu

Scrivi un if-else che stampa positivo o zero se x è almeno 0, e negativo altrimenti.

if (x >= 0) { printf("positivo o zero\n"); } else { printf("negativo\n"); }.

Da ricordare

  • Con if-else si esegue sempre uno e un solo blocco dei due.
  • else non ha una condizione: vale «in tutti gli altri casi».
§4

Più strade: else if

slide 7–8

A volte le strade sono più di due. Il semaforo dell'esempio ha tre colori, più il caso di un colore sbagliato. Si mettono le domande in fila, con else if:

char colore = 'G';   // R = Rosso, G = Giallo, V = Verde
if (colore == 'R') {
    printf("Fermati!\n");
}
else if (colore == 'G') {
    printf("Attenzione, rallenta.\n");
}
else if (colore == 'V') {
    printf("Puoi passare.\n");
}
else {
    printf("Colore non valido!\n");
}

Il programma fa le domande dall'alto in basso:

  1. il colore è 'R'? No, allora passa alla domanda dopo;
  2. il colore è 'G'? Sì: stampa Attenzione, rallenta. e salta tutto il resto, fino alla fine della catena.

Se nessuna condizione è vera, entra nell'else finale, il caso di default. Ho provato tutti i casi: 'R', 'G' e 'V' danno i loro messaggi; 'g' minuscolo dà Colore non valido!, perché 'g' e 'G' sono caratteri diversi, con codici ASCII 103 e 71.

Nota · I caratteri si confrontano con ==

Un char è un piccolo numero, il codice ASCII del carattere. Per questo colore == 'R' funziona come un confronto tra numeri. Il carattere va tra apici singoli: 'R' è un carattere, "R" è una stringa, che si confronta in un altro modo.

Trappola · All'esame niente switch

Il C ha anche un'istruzione switch per scegliere tra molti valori. Le regole d'esame di Programmazione I la vietano, come break e continue: le catene di scelte si scrivono con if ed else if.

Prova tu

Con il programma del semaforo e colore = 'V', quante condizioni vengono controllate prima di stampare?

Tre: 'R', poi 'G', poi 'V', che è vera.

Da ricordare

  • Le condizioni di una catena else if si controllano dall'alto in basso.
  • Si entra nel primo blocco con la condizione vera; tutti gli altri si saltano.
  • L'else finale raccoglie i casi rimasti.
§5

Gli errori più comuni

slide 9–12

Gli if sono semplici da scrivere e facili da sbagliare. Le slide raccolgono gli errori che si vedono più spesso. Per ognuno ho controllato che cosa fa gcc.

Un uguale solo

if (a = 5) { ... }  // ERRORE: assegnamento

a = 5 non chiede niente: mette 5 in a, e vale 5, cioè vero. Il blocco viene eseguito sempre, qualunque cosa ci fosse in a. gcc con -Wall avvisa: suggest parentheses around assignment used as truth value. Con -Werror non compila, ed è una fortuna.

Le graffe dimenticate

if (x > 0)
    printf("Positivo\n");
    printf("Errore!\n"); // eseguito sempre

Senza graffe, l'if comanda una sola istruzione, la prima. La seconda printf è rientrata come se dipendesse dall'if, ma per il C il rientro non conta niente: viene eseguita sempre. gcc con -Wall avvisa: this 'if' clause does not guard..., e con -Werror non compila. Le slide consigliano di mettere sempre le graffe, anche con una sola istruzione.

L'ordine sbagliato

if (num % 2 == 0) {
    printf("Pari non nullo\n");
}
else if (num == 0) {
    printf("Zero\n");   // Mai raggiunto
}

Lo 0 è pari: con num = 0 la prima condizione è già vera, e il programma stampa Pari non nullo, che è falso. Il blocco Zero non viene mai raggiunto. Si corregge mettendo prima il caso più specifico:

if (num == 0) {
    printf("Zero\n");
}
else if (num % 2 == 0) {
    printf("Pari non nullo\n");
}

Ho provato: con 0 la prima versione stampa Pari non nullo, la seconda Zero. Con 4 tutte e due stampano Pari non nullo.

Condizioni che non diventano mai vere

if (x > 10) {
    ...
}
else if (x > 20) {
    ... // mai eseguito!
}

Ogni numero maggiore di 20 è anche maggiore di 10, quindi entra già nel primo blocco. Il secondo non si raggiunge mai. Qui gcc non avvisa: l'errore è di logica, e lo trovi solo ragionando. Le soglie vanno in ordine dalla più alta alla più bassa (x > 20 prima di x > 10), oppure con intervalli precisi.

L'else mancante

È buona norma gestire tutti i casi, con un else finale anche solo per stampare un errore. Così il programma non arriva mai in una situazione che non hai previsto.

Condizioni troppo lunghe

if (a > 10 && b < 5 || c == 7 && !(d%2)) {
    ...
}

Come nella 03C, una condizione così si spezza in variabili bool con un nome:

bool condA = (a > 10 && b < 5);
bool condB = (c == 7 && d % 2 == 0);

if (condA || condB) { ... }

La prima versione, tra l'altro, con -Wall -Werror non compila: gcc chiede le parentesi intorno agli && dentro l'||.

Erroregcc con -WallCon -Werror
if (a = 5)avviso -Wparenthesesnon compila
graffe dimenticate, rientro ingannevoleavviso -Wmisleading-indentationnon compila
&& dentro \|\| senza parentesiavviso -Wparenthesesnon compila
ordine sbagliato delle condizioninientecompila, risultato sbagliato
condizione mai raggiungibilenientecompila, risultato sbagliato

Prova tu

Che cosa stampa questo codice con x = 25? if (x > 10) { printf("A"); } else if (x > 20) { printf("B"); } else { printf("C"); }

A: 25 è maggiore di 10, quindi si entra nel primo blocco e gli altri si saltano. B non viene mai stampato, per nessun valore.

Da ricordare

  • Sempre le graffe, anche per una sola istruzione.
  • Prima i casi più specifici, poi quelli generali.
  • gcc trova gli errori di scrittura, non quelli di ordine: quelli si trovano provando i casi limite.
§6

Lo scambio condizionato

slide 13–20

L'esempio delle slide: leggere due interi x e y e stamparli dal più piccolo al più grande. La prima idea è stampare in due ordini diversi:

#include <stdio.h>

int main(void) {
    int x, y;
    printf("Inserisci x:");
    scanf("%d", &x);
    printf("Inserisci y:");
    scanf("%d", &y);
    if (y < x) {
        printf("%d %d", y, x);
    }
    else { // y >= x
        printf("%d %d", x, y);
    }
}

La seconda idea è più utile: se sono nell'ordine sbagliato, si scambiano. Dopo l'if le variabili sono in ordine, e basta una sola printf. È lo scambio con la variabile d'appoggio della 03A, fatto solo quando serve: uno scambio condizionato.

#include <stdio.h>

int main(void) {
    int x, y;
    printf("Inserisci x:");
    scanf("%d", &x);
    printf("Inserisci y:");
    scanf("%d", &y);
    if (y < x) {
        //scambio condizionato
        int temp = x;
        x = y;
        y = temp;
    }
    printf("%d %d", x, y);
}

Con 10 e 5 stampa 5 10; con 3 e 8 stampa 3 8, senza scambio.

Che cosa succede nella memoria

Le slide 15–20 seguono il programma con l'input 10 e 5, una riga alla volta. Ogni riga della tabella è lo stato della memoria dopo l'istruzione indicata.

Dopo l'istruzionexytemp
int x, y;??non esiste
le due scanf105non esiste
int temp = x;10510
x = y;5510
y = temp;51010
la } dell'if510non esiste

La cosa nuova è l'ultima colonna. temp è dichiarata dentro il blocco dell'if: nasce sullo stack quando il programma arriva alla sua dichiarazione, e alla } del blocco viene tolta dallo stack. Dopo l'if non esiste più.

Definizione · Visibilità di una variabile

Una variabile dichiarata in un blocco { … } è visibile, cioè si può usare, solo dalla sua dichiarazione alla } che chiude quel blocco. Fuori dal blocco il suo nome non esiste.

Come si legge. È la regola delle variabili locali della 02B, applicata ai blocchi dell'if. Se dopo l'if scrivi printf("%d", temp);, gcc si ferma: error: 'temp' undeclared. L'ho provato.

Questo è utile: temp serve solo per lo scambio, e dichiararla dentro il blocco evita che qualcuno la usi per sbaglio più avanti.

Prova tu

Con l'input 4 e 4, quante volte viene creata temp? Che cosa stampa il programma?

Nessuna: 4 < 4 è falso, quindi il blocco viene saltato e temp non nasce. Stampa 4 4.

Da ricordare

  • Scambio condizionato: si scambia solo se l'ordine è sbagliato.
  • Una variabile dichiarata in un blocco sparisce alla } del blocco.
§7

Niente scale di if inutili

slide 21

Un if dentro un else funziona, ma spinge il codice sempre più a destra e si legge male. L'esempio delle slide è il prezzo del biglietto: gratis sotto i 6 anni, ridotto sotto i 18, intero dai 18 in su.

if (eta < 6) {
    printf("Biglietto gratuito\n");
}
else {
    if (eta < 18) {
        printf("Biglietto ridotto\n");
    }
    else {
        printf("Biglietto intero\n");
    }
}

La stessa scelta con else if sta su un solo livello:

if (eta < 6) {
    printf("Biglietto gratuito\n");
}
else if (eta < 18) {
    printf("Biglietto ridotto\n");
}
else {
    printf("Biglietto intero\n");
}

Le due versioni fanno esattamente la stessa cosa. Ho provato i casi limite, quelli sul confine tra due fasce: 5 dà gratuito, 6 ridotto, 17 ridotto, 18 intero.

Nota che la seconda condizione è solo eta < 18, non 6 <= eta && eta < 18: se il programma arriva lì, eta < 6 è già falso, quindi eta è almeno 6. Un else if porta con sé il «no» di tutte le domande prima.

Prova tu

Aggiungi una fascia: dai 65 anni in su il biglietto è ridotto. Dove metti la condizione?

Prima dell'else finale: else if (eta >= 65) { printf("Biglietto ridotto\n"); }. Oppure, per non ripetere il messaggio, else if (eta < 18 || eta >= 65) al posto di else if (eta < 18).

Da ricordare

  • Un if dentro un else si scrive meglio con else if.
  • Ogni else if sa già che le condizioni precedenti sono false.
§8

Schemi che tornano sempre

slide 22–25

Alcuni if compaiono in quasi tutti i programmi. Vale la pena saperli scrivere senza pensarci.

Il massimo di due numeri

int a, b, max;
scanf("%d%d", &a, &b);
// determina il massimo tra a e b
if (a > b) {
    max = a;
}
else {
    max = b;
}
// in questo punto max contiene il massimo tra a e b

Con 4 e 9, max vale 9. Con due numeri uguali va bene lo stesso: si prende b, che vale quanto a.

Controllare l'input

Prima di usare un valore letto, si controlla che scanf l'abbia letto davvero, come nella 02C:

int valore;
if (scanf("%d", &valore) == 1) {
    printf("Hai inserito: %d\n", valore);
}
else {
    printf("Input non valido\n");
}

Proteggere un'operazione

Prima di dividere, si controlla che il divisore non sia zero:

if (divisore != 0) {
    printf("Risultato: %d\n", dividendo / divisore);
}
else {
    printf("Errore: divisione per zero!\n");
}

Controllare un intervallo

float temperatura;
bool inputOk = scanf("%f", &temperatura) == 1;
// 0 <= temperatura_valida <= 100
if (inputOk && 0 <= temperatura && temperatura <= 100) {
    printf("Temperatura entro i limiti\n");
}
else {
    printf("Temperatura fuori intervallo o lettura errata\n");
}

Qui lavorano insieme tre idee della 03C: l'intervallo con due confronti, il cortocircuito che non guarda temperatura se la lettura è fallita, e una variabile bool con un nome chiaro. Ho provato: 25 e 100 sono entro i limiti; −3, 100.5 e ciao danno il secondo messaggio.

Prova tu

Con il programma della temperatura e l'input 0, che cosa stampa? Perché?

Temperatura entro i limiti: l'intervallo è chiuso, 0 <= temperatura è vero anche con 0.

Da ricordare

  • Massimo: un if-else che sceglie quale copiare in max.
  • Prima di usare un input, controlla che scanf restituisca 1.
  • Prima di dividere, controlla il divisore.
§9

I simboli di questa lezione

SimboloSi leggeVuol direEsempio
if (c) { … }«if», «se»esegue il blocco se c è veraif (voto >= 18) { … }
else { … }«else», «altrimenti»il blocco da eseguire se la condizione è falsa
else if (c) { … }«else if», «altrimenti se»un'altra domanda, solo se le precedenti erano false
{ }«graffe»un blocco di istruzioni; le variabili dichiarate dentro vivono solo lì
'R'«carattere R»un char, tra apici singolicolore == 'R'
§10

Verso l'esame

esame

All'esame, su CodeRunner, quasi ogni esercizio ha degli if. Le cose da avere in mano:

  1. compila con -Wall -Werror e leggi gli avvisi: = al posto di == e le graffe dimenticate vengono fermati qui;
  2. int main(void), non void main();
  3. niente switch, break e continue: le scelte si fanno con if ed else if;
  4. prova i casi limite: lo zero, i numeri uguali, i valori sul confine tra due fasce (17 e 18, 5 e 6);
  5. un else finale per i casi che non ti aspetti, come l'input non valido.

Negli esercizi sullo stato della memoria può comparire un if con una variabile dichiarata dentro: la sua casella esiste solo mentre il programma è nel blocco, e alla } si cancella.

Metodo · Seguire un programma con gli if

  1. Scrivi i valori iniziali delle variabili.
  2. A ogni if, calcola la condizione con i valori di quel momento e scrivi «vero» o «falso».
  3. Segui solo il blocco scelto; in una catena else if, fermati alla prima condizione vera.
  4. Aggiorna la tabella dei valori dopo ogni assegnamento, e cancella le variabili del blocco alla sua }.
§11

Quiz

come all'esame
  1. Che cosa stampa int n = 0; if (n % 2 == 0) { printf("A"); } else if (n == 0) { printf("B"); } else { printf("C"); }?
  2. Che cosa stampa questo codice con x = -3? if (x > 0) printf("P"); printf("Q");
  3. Con int a = 0;, che cosa stampa if (a = 7) { printf("%d", a); } compilato senza opzioni?
  4. Perché void main() { … } non va bene all'esame?
  5. Dopo questo codice, che cosa succede alla riga printf("%d", temp);? int x = 2, y = 1; if (y < x) { int temp = x; x = y; y = temp; } printf("%d", temp);
  6. Quale catena dà il prezzo giusto per ogni età: gratis sotto i 6, ridotto da 6 a 17, intero dai 18?
  7. Con int x = 7, y = 3, z; e poi if (x > y) { z = x - y; } else { z = y - x; }, quanto vale z?
  8. Quale riga legge un intero e lo usa solo se la lettura è riuscita?
§12

Esercizi

con soluzioni

1 · Riscaldamento: che cosa stampa? base

Con int x = 7, y = 3, z = 0; esegui: if (x > y) { z = x - y; } else { z = y - x; } e poi if (z % 2 == 0) { x = x + z; } else if (z > 3) { y = y + z; } else { x = 0; }. Quanto valgono x, y, z?

Soluzione

z = 4. Poi 4 % 2 == 0 è vero, quindi x = 7 + 4 = 11, e il resto della catena si salta. Alla fine x = 11, y = 3, z = 4. Il programma che stampa i tre valori dà 11 3 4.

2 · Riscaldamento: trova gli errori base

Ogni riga ha un errore. Trovalo. (a) if (n = 0) { printf("zero"); } (b) if n > 0 { printf("positivo"); } (c) if (x > 0); { printf("positivo"); } (d) else (x < 0) { printf("negativo"); }

Soluzione

(a) = al posto di ==. (b) Mancano le parentesi tonde intorno alla condizione: if (n > 0). (c) Il ; dopo la parentesi chiude l'if con un'istruzione vuota: il blocco si esegue sempre. gcc con -Wall se ne accorge quando il blocco sta sulla stessa riga (this 'if' clause does not guard...). (d) else non ha condizione: serve else if (x < 0).

3 · Riscaldamento: i casi limite base

Per il codice del biglietto (gratis sotto i 6, ridotto sotto i 18, intero altrimenti), quali età proveresti per controllarlo? Perché proprio quelle?

Soluzione

5 e 6, 17 e 18: sono i valori ai due lati di ogni confine, dove un < scritto al posto di <= cambia il risultato. In più un valore in mezzo a ogni fascia, per esempio 2, 10 e 40, e magari 0.

4 · Il massimo di tre numeri medio

Scrivi un programma che legge tre interi e stampa il più grande. Prova con 4 9 2, con −1 −5 −3 e con 7 7 7.

Soluzione
#include <stdio.h>

int main(void) {
    int a, b, c;
    scanf("%d %d %d", &a, &b, &c);
    int max = a;
    if (b > max) {
        max = b;
    }
    if (c > max) {
        max = c;
    }
    printf("%d\n", max);
    return 0;
}

Stampa 9, −1 e 7. L'idea: si parte da un candidato e lo si aggiorna quando si trova di meglio. Qui gli if sono separati, non in catena, perché ogni confronto va fatto comunque. È lo stesso schema che userai con i cicli per il massimo di un array.

5 · Il voto in parole medio

Scrivi un if-else if che legge un voto da 0 a 30 e stampa insufficiente sotto il 18, sufficiente da 18 a 23, buono da 24 a 27, ottimo da 28 in su. Con quali voti lo provi?

Soluzione
if (v < 18) {
    printf("insufficiente\n");
}
else if (v < 24) {
    printf("sufficiente\n");
}
else if (v < 28) {
    printf("buono\n");
}
else {
    printf("ottimo\n");
}

Provato con 17, 18, 24, 27, 28 e 30: danno insufficiente, sufficiente, buono, buono, ottimo, ottimo. Ogni else if sa già che il voto non è sotto la soglia precedente.

6 · Ordinare tre numeri tipo esame

Scrivi un programma che legge tre interi a, b, c e li stampa dal più piccolo al più grande, usando solo scambi condizionati. Se la lettura non riesce, stampa Input non valido.

Soluzione
#include <stdio.h>

int main(void) {
    int a, b, c;
    if (scanf("%d %d %d", &a, &b, &c) == 3) {
        // porta il piu' piccolo in a
        if (b < a) {
            int temp = a;
            a = b;
            b = temp;
        }
        if (c < a) {
            int temp = a;
            a = c;
            c = temp;
        }
        // ora a e' il minimo: sistema b e c
        if (c < b) {
            int temp = b;
            b = c;
            c = temp;
        }
        printf("%d %d %d\n", a, b, c);
    }
    else {
        printf("Input non valido\n");
    }
    return 0;
}

Provato con 3 1 2, 9 8 7, 5 5 1 e 1 2 3: stampa sempre i numeri in ordine. Con x stampa Input non valido. Ogni temp vive solo nel suo blocco, quindi lo stesso nome si può usare tre volte.

7 · La tariffa del parcheggio tipo esame

Un parcheggio costa: la prima ora gratis, poi 2 euro per ogni ora dopo la prima, fino a 5 ore; oltre le 5 ore 12 euro fissi. Scrivi un programma che legge le ore (un intero) e stampa il prezzo, con un messaggio di errore se l'input non è valido o è negativo.

Soluzione
#include <stdio.h>
#include <stdbool.h>

int main(void) {
    int ore;
    bool letto = (scanf("%d", &ore) == 1);
    if (!letto || ore < 0) {
        printf("Input non valido\n");
    }
    else if (ore <= 1) {
        printf("Gratis\n");
    }
    else if (ore <= 5) {
        printf("%d euro\n", (ore - 1) * 2);
    }
    else {
        printf("12 euro\n");
    }
    return 0;
}

Provato: 0 e 1 danno Gratis, 3 dà 4 euro, 5 dà 8 euro, 6 dà 12 euro, −2 e boh danno Input non valido. Il primo controllo usa il cortocircuito: se letto è falso, ore non viene guardata.

§13

Domande di ripasso

autoverifica

Rispondi a voce alta o per iscritto, poi apri la risposta.

Quali sono le tre strutture della programmazione strutturata?

Sequenza, selezione e iterazione.

Che cosa dice il teorema di Böhm-Jacopini?

Che sequenza, selezione e iterazione bastano per scrivere qualunque algoritmo.

In una catena if … else if … else, quanti blocchi vengono eseguiti?

Uno solo: il primo con la condizione vera, oppure l'else se nessuna è vera.

Perché conviene mettere sempre le graffe?

Perché senza graffe l'if comanda solo l'istruzione dopo, e una seconda riga rientrata sembra dipendere dall'if ma viene eseguita sempre.

In che ordine vanno le condizioni di una catena else if?

Dalla più specifica alla più generale: altrimenti un caso generale cattura prima quello specifico.

Dove si può usare una variabile dichiarata dentro il blocco di un if?

Solo dentro quel blocco, dalla dichiarazione alla }. Fuori non esiste.

Come si controlla che scanf abbia letto un intero?

Con if (scanf("%d", &x) == 1): scanf restituisce quanti valori ha letto.

§14

Glossario

termini
Flusso di controllo
L'ordine in cui il programma esegue le istruzioni.
Programmazione strutturata
Scrivere i programmi solo con sequenza, selezione e iterazione.
Teorema di Böhm-Jacopini
Sequenza, selezione e iterazione bastano per qualunque algoritmo (1966).
Selezione
Scegliere quale blocco eseguire in base a una condizione.
if
Esegue un blocco solo se la condizione è vera.
else
Il blocco da eseguire quando la condizione è falsa.
else if
Una nuova condizione, controllata solo se le precedenti erano false.
Blocco
Istruzioni tra graffe; le variabili dichiarate dentro esistono solo lì.
Visibilità
La parte di programma in cui un nome di variabile si può usare.
Scambio condizionato
Scambiare due variabili solo se sono nell'ordine sbagliato.
Caso limite
Un valore sul confine tra due casi, dove gli errori si vedono meglio.
§15

Checklist

0 su 9

Spunta quando sai fare la cosa senza guardare gli appunti. Le spunte restano salvate in questo browser.