Condizioni: far scegliere al programma
Fino ad ora i programmi eseguivano tutte le istruzioni in ordine. Adesso impari a
decidere: eseguire un pezzo di codice solo se una condizione è vera.
Si impara in due modi: if (se) e when (quando).
if/else/else if;- gli operatori di confronto:
>,<,>=,<=,==,!=; - gli operatori logici:
&&(e),||(o),!(non); ifcome espressione:val x = if (...) a else b;whencon soggetto, con intervalli, conise senza soggetto.
Ripasso lampo: leggere i dati e convertirli
Prima di decidere, il programma deve avere i dati: ripasso del capitolo 3.
L'utente scrive 12. Che cosa stampa questo programma?
fun main() {
val n = readln()
println(n + 1)
}13No: n è testo, quindi n + 1 attacca i due pezzi invece di sommarli.121Esatto: manca toInt(). Con readln().toInt() il risultato sarebbe 13.readln() restituisce sempre testo: senza .toInt() il + unisce invece di sommare. È l'errore più frequente di tutto il manuale.
L'utente scrive ciao. Che cosa stampa questo programma?
fun main() {
val n = readln().toIntOrNull() ?: 0
println(n * 2)
}0Esatto: toIntOrNull() dà null, e ?: mette 0 al suo posto. 0 * 2 è 0.toInt(); con toIntOrNull() il programma continua.ciaociaoNo: ?: scarta il testo non convertibile e usa il valore di riserva.toIntOrNull() non fa mai fermare il programma: quando la conversione non riesce restituisce null, e il valore di riserva lo scegli tu con ?:.
4.1 if: eseguire solo se...
La forma base è if (condizione) { ... }: le istruzioni fra graffe vengono eseguite
solo se la condizione è vera. Con else si indica che cosa fare quando è falsa.
Se il ramo contiene una sola istruzione puoi scrivere if (eta >= 18) println("Maggiorenne").
Per cominciare usa sempre le graffe: il codice resta chiaro e non fai errori quando aggiungi istruzioni.
4.2 Confronti e operatori logici
Una condizione è un'espressione che vale true o false.
Si costruisce con gli operatori di confronto e si combina con quelli logici.
| Operatore | Significato | Esempio |
|---|---|---|
== | uguale a (due segni di uguale!) | voto == 10 |
!= | diverso da | nome != "Anna" |
> >= | maggiore, maggiore o uguale | eta >= 18 |
< <= | minore, minore o uguale | prezzo < 10 |
&& | e: vero solo se lo sono entrambe | eta >= 14 && eta < 18 |
|| | o: vera se lo è almeno una | giorno == "sab" || giorno == "dom" |
! | non: rovescia vero e falso | !haLaSpada |
Che cosa stampa questo programma?
fun main() {
val voto = 9
if (voto >= 6) println("sufficiente")
else if (voto >= 9) println("ottimo")
else println("insufficiente")
}ottimoIl voto 9 soddisfa anche 9 >= 6, e quella condizione viene controllata prima.sufficienteEsatto: Kotlin si ferma alla prima condizione vera, quindi il ramo >= 9 non viene mai raggiunto con questo ordine.insufficienteNo: la prima condizione è vera, quindi si entra in quel ramo.Le condizioni vanno scritte dalla più stretta alla più larga. Qui l'ordine giusto è >= 9 prima e >= 6 dopo.
if (eta = 18) è un errore: con = si assegna un valore.
Per confrontare si usa sempre ==.
4.3 else if: più di due possibilità
Quando le possibilità sono più di due si incatena else if. Kotlin le controlla
dall'alto verso il basso e si ferma alla prima condizione vera.
- Con
voto = 7la prima condizione (7 >= 9) è falsa, la seconda (7 >= 6) è vera: Kotlin stampaPromossoe non guarda le condizioni successive. - Il secondo
ifnon stampa niente: restituisce il testo"promosso/a", che finisce nella variabileesito. - Da qui le due righe di output:
PromossoeEsito: promosso/a.
Con voto = 9 la prima condizione è vera e il programma non guarda le altre.
Se avessi messo per prima voto >= 6, anche un 10 sarebbe finito in "Sufficiente":
si va sempre dal caso più restrittivo a quello più generico.
4.4 if come espressione: assegnare un valore
In Kotlin if può restituire un valore: è il modo più compatto
per scegliere fra due valori e metterli in una variabile.
4.5 when: tanti casi in modo ordinato
when confronta un valore con tanti casi. È come una catena di else if,
ma molto più leggibile. Il caso else è obbligatorio quando nessuna condizione
copre tutti i valori possibili.
in 0..59
in 0..59 si legge "da 0 a 59, estremi compresi": è il modo per dire al
when di scegliere quel ramo quando il valore cade dentro quell'intervallo.
Con il voto 78, il primo intervallo (0-59) non lo contiene, il secondo
(60-100) sì: stampa Sufficiente. Niente funzioni, return o controlli
di tipo: è un when con soggetto e intervalli, che leggerai più in dettaglio
nel capitolo 5.
6non è nella prima riga di casi, ma è nella seconda:Weekend.15 > 10è vero e15 % 5 == 0è vero: con&&servono entrambe vere, quinditrue.15 > 20è falso e15 < 0è falso: con||basta una condizione vera, quindifalse.
Che cosa succede con if (eta = 18) { ... }?
eta con 18No: il confronto si scrive con due uguali.= serve ad assegnare un valore. Per confrontare si usa sempre ==.eta e va avantiL'intenzione sarebbe quella, ma dentro la condizione di un if Kotlin non lo accetta: è quasi sempre un errore di scrittura.Da ricordare: = assegna, == confronta.
val premio = when (punti) { ... else -> 0 } funziona come if:
il valore del ramo scelto diventa il valore di tutta l'espressione.
Quando un when con soggetto restituisce un valore — cioè il suo
risultato finisce in una variabile o dentro una stampa — il caso else non è un
consiglio: è un requisito. Il motivo lo dice il messaggio stesso del motore:
«il suo valore viene usato, quindi deve esistere un caso per ogni possibilità». Se invece il
when è solo una sequenza di istruzioni, come negli esempi 9–11, mancare un caso
non dà errore: semplicemente non succede niente. L'abitudine giusta resta una sola:
metti sempre l'else.
4.6 Riepilogo
| Scrivi | Significato |
|---|---|
if (c) { ... } else { ... } | due strade possibili |
if (c) { ... } else if (c2) { ... } else { ... } | più strade, in ordine |
val x = if (c) a else b | una variabile che prende uno dei due valori |
when (x) { 1 -> ...; else -> ... } | confronto con tanti casi |
when { c1 -> ...; c2 -> ...; else -> ... } | catena di condizioni |
4.7 Esercizi guidati
Leggi un voto da 0 a 10 e stampa: "Insufficiente" se è minore di 6, "Sufficiente" da 6 a 7,
"Buono" da 8 a 9, "Eccellente" se è 10. Usa if / else if / else.
Parti dal caso più alto o dal più basso e prosegui in ordine:
if (voto >= 10) ... else if (voto >= 8) ....
- Le condizioni vanno dal caso più alto al più basso. Con voto = 10 la prima condizione è vera e le altre non vengono nemmeno guardate.
- Se l'input non è un numero,
?: -1assegna -1 e il programma finisce nel ramoelseinvece di fermarsi con un errore. - Ogni ramo ha un solo
println: avresti potuto omettere le graffe, ma così il codice è pronto per aggiungere altre istruzioni.
Leggi un anno e stabilisci se è bisestile. Regola: un anno è bisestile se è divisibile per 4, tranne gli anni divisibili per 100, che sono bisestili solo se divisibili per 400. Prova con 1900 (non bisestile), 2000 (bisestile) e 2024 (bisestile).
Puoi scrivere tutte le condizioni in un unico if con && e
||: anno % 4 == 0 && (anno % 100 != 0 || anno % 400 == 0).
anno % 4 == 0è la condizione principale: senza quella nessun anno può essere bisestile.- Le parentesi attorno a
(anno % 100 != 0 || anno % 400 == 0)sono essenziali:&&ha la precedenza su||, quindi senza parentesi il significato cambierebbe. - 1900 è divisibile per 4 e per 100 ma non per 400 → non bisestile. 2000 è divisibile per 400 → bisestile. 2024 non è divisibile per 100 → bisestile.
- Il risultato viene messo in una
valcon un nome chiaro: il codice che segue si legge come una frase in italiano.
Il distributore automatico ha questo menu: 1 = acqua (0.50), 2 = succo (1.20), 3 = caffè (0.90), 4 = snack (1.50). Leggi il numero scelto e i soldi inseriti, poi stampa cosa è stato scelto e il resto da restituire. Se il numero non è nel menu stampa "Scelta non valida".
Con when assegna il prezzo: val prezzo = when (scelta) { 1 -> 0.50 ... else -> 0.0 }.
Il resto è soldi - prezzo: se il prezzo è 0.0 non c'è nulla da comprare.
- Un
whencome espressione restituisce il valore del ramo scelto: il primo lo usiamo per il nome, il secondo per il prezzo. - L'
elsedelwhenserve sia per il nome sia per il prezzo: se la scelta non è 1-4 il prezzo resta 0.0. - Dopo il
whenci sono tre casi distinti gestiti conif / else if / else: prezzo nullo, soldi sufficienti, soldi insufficienti. soldi >= prezzoconfronta dueDouble: il confronto funziona anche con i decimali.
Questo programma parte senza errori, ma con voto = 9 stampa
Sufficiente invece di Ottimo. Eseguilo, confronta l'output con quello
atteso e correggi solo l'ordine delle condizioni, senza cambiare i testi stampati.
Kotlin si ferma alla prima condizione vera: il caso più stretto
(voto >= 9) deve stare prima di quello più largo (voto >= 6).
- Il codice di partenza compila: l'errore è logico, non di sintassi. Con
voto = 9la prima condizione9 >= 6è già vera. - Kotlin entra nel primo ramo e non guarda gli altri: il ramo
>= 9diventa irraggiungibile. - Mettendo
voto >= 9per primo, il 9 finisce in "Ottimo", il 7 in "Sufficiente" e il 4 in "Insufficiente". - Regola generale: le condizioni vanno scritte dalla più stretta alla più larga.
Il programma deve dire se un voto è sufficiente, ma non funziona. Con 7 deve stampare Sufficiente, con 5 deve stampare Insufficiente.
Per confrontare serve == (due uguali); le due condizioni di un && stanno dentro le stesse parentesi tonde dell'if.
if (voto = 6)usa un solo=, che assegna: per confrontare si scrivevoto >= 6ovoto == 6.- Le graffe non sono obbligatorie con una sola istruzione, ma con
ifeelsesu più righe evitano di sbagliare a quale ramo appartiene l'istruzione. if (voto >= 6) && (voto <= 10)chiude le parentesi troppo presto: la condizione completa va dentro una sola coppia di parentesi,if (voto >= 6 && voto <= 10).- Kotlin controlla tutta la condizione e solo dopo decide: un
&&fuori posto non è "quasi giusto", è un errore.
if, else if e else>, <, >=, <=, ==, !=&&, || e !if come espressione per assegnare un valorewhen con valori, intervalli e casi else