Prendere decisioni con if
I programmi reagiscono di continuo ai dati: promosso o bocciato, disponibile o esaurito, valido o no. L'istruzione if è il modo in cui C++ sceglie quale codice eseguire in base a una condizione.
Un if riceve una condizione tra parentesi ed esegue il blocco tra graffe solo quando quella condizione è vera:
La condizione score >= 60 è vera, quindi il messaggio viene stampato. La riga dopo la graffa di chiusura viene eseguita sempre: sta fuori dall'if. Cambia score in 40 e la riga "passed" viene saltata del tutto.
La condizione viene convertita in bool. I confronti come >, >=, ==, != producono già un bool, ma C++ tratta anche qualsiasi numero diverso da zero come vero e 0 come falso: quindi if (count) significa "se count non è zero". Questa conversione implicita è comoda, ma è anche la fonte di alcuni bug classici che vedrai più avanti.
Aggiungere un else
else ti dà il percorso "altrimenti", cioè il codice che viene eseguito solo quando la condizione è falsa:
Viene eseguito esattamente uno dei due blocchi: mai entrambi, mai nessuno. else non ha una condizione propria; raccoglie semplicemente tutto ciò che l'if non ha preso.
Concatenare con else if
Quando i risultati possibili sono più di due, concatena le condizioni con else if. C++ le controlla dall'alto verso il basso ed esegue il primo blocco la cui condizione è vera, poi salta il resto:
L'ordine conta. Poiché 84 viene confrontato prima con >= 90 (falso), poi con >= 80 (vero), si ferma a B e non controlla mai le soglie più basse. Per questo non ti serve score >= 80 && score < 90: arrivare al secondo ramo garantisce già che score fosse sotto 90. Metti per prima la condizione più stretta o con priorità più alta.
Nota che in C++ non esiste la parola chiave elif: else if è letteralmente un else il cui corpo è un altro if. Le graffe lo fanno solo leggere come un'unica scala.
Una grande trappola: = vs ==
Il bug più comune in assoluto con gli if in C e C++ è scrivere = (assegnazione) quando intendevi == (confronto):
x = 5 assegna 5 a x e l'intera espressione vale 5, che si converte in true: così il ramo viene eseguito sempre e hai sovrascritto x senza accorgertene. Il codice compila; la maggior parte dei compilatori emette solo un avviso. Due difese: attiva gli avvisi (-Wall) così il compilatore lo segnala, e valuta di mettere la costante per prima, if (5 == x), perché if (5 = x) è un errore vero e proprio che il compilatore intercetta subito.
La stessa trappola si nasconde con bool: if (ready = true) compila e assegna, mentre if (ready == true) (o semplicemente if (ready)) confronta.
Combinare e annidare condizioni
Combina le condizioni con && (e), || (o) e ! (non), oppure annida un if dentro un altro quando un controllo ha senso solo dopo che il precedente è passato:
&& e || sono a cortocircuito: in a && b, se a è falso C++ non valuta mai b. È essenziale per proteggersi da accessi alla memoria non validi: if (ptr != nullptr && ptr->ready) è sicuro perché la dereferenziazione del puntatore viene saltata quando ptr è nullo. Quando puoi, preferisci appiattire con && invece di annidare in profondità; una condizione piatta si legge meglio di una piramide di graffe.
Attenzione ai confronti concatenati che non significano quello che sembrano: if (0 < x < 10) non verifica un intervallo. Valuta 0 < x come bool (0 o 1), poi confronta quel risultato con 10: sempre vero. Scrivi invece if (0 < x && x < 10).
L'operatore ternario
Quando ti basta scegliere tra due valori, l'operatore ternario ?: è una riga compatta. Leggi condition ? a : b come "se condition allora a, altrimenti b":
Il ternario produce un valore che puoi assegnare, passare o stampare direttamente, cosa che un semplice if non può fare. Riservalo alle selezioni semplici: se uno dei rami richiede più istruzioni o vera logica, un if-else completo resta leggibile, mentre un ternario annidato diventa presto un rompicapo. (Una sottigliezza: entrambi i rami devono avere un tipo comune, quindi non mescolare, per esempio, una stringa e un int.)
if con inizializzatore (C++17)
Da C++17 puoi dichiarare una variabile direttamente dentro l'if, con visibilità limitata all'if/else. Così gli aiutanti di breve durata non finiscono nel codice circostante:
La parte prima del ; viene eseguita una sola volta e il suo risultato è visibile sia nella condizione sia nell'else. È perfetto per gli schemi "calcola qualcosa, poi dirama in base al risultato", e poiché il cast o la conversione del risultato avviene una volta sola all'inizio, eviti di ricalcolarlo o di riusare per sbaglio un valore non aggiornato più avanti. Usalo ogni volta che una variabile temporanea serve solo per il ramo.
Una trappola: le graffe mancanti
C++ ti permette di omettere le graffe quando un ramo ha una sola istruzione, ma questo apre la porta a un bug subdolo, perché l'indentazione mente:
if (loggedIn)
cout << "Welcome\n";
cout << "Loading dashboard\n"; // NON fa parte dell'if!
Solo la prima riga è controllata dall'if; la seconda viene eseguita sempre, qualunque sia il valore di loggedIn, anche se l'indentazione suggerisce il contrario. Un altro classico è il punto e virgola di troppo: if (x > 0); chiude l'if con un corpo vuoto, quindi il blocco che segue viene eseguito senza condizioni. Usa sempre le graffe, anche per una sola riga, e la maggior parte di questi errori sparisce.
Prossimo passo: switch
Le catene if-else if sono perfette quando ogni ramo verifica una condizione diversa. Ma quando confronti un solo valore con molte possibilità fisse (una scelta di menu, un enum, un codice di stato), una lunga scala di else if diventa ripetitiva e facile da ordinare male. L'istruzione switch è fatta apposta per questo, ed è l'argomento della prossima pagina.
Domande frequenti
Come si scrive un'istruzione if-else in C++?
Metti una condizione tra parentesi dopo if, il codice da eseguire tra parentesi graffe e un blocco else facoltativo per quando la condizione è falsa: if (score >= 60) { cout << "Pass"; } else { cout << "Fail"; }. La condizione viene convertita in bool, quindi qualsiasi numero diverso da zero vale come vero e 0 vale come falso.
Qual è la differenza tra = e == in un if in C++?
== confronta due valori per verificarne l'uguaglianza, mentre un singolo = assegna. Scrivere if (x = 5) assegna 5 a x e poi valuta 5 (sempre vero): un bug classico. Compila con al massimo un avviso, quindi attiva gli avvisi e valuta di scrivere prima la costante: if (5 == x).
Cos'è l'operatore ternario in C++?
L'operatore ternario condition ? valueIfTrue : valueIfFalse è un if-else compatto che produce un valore. Per esempio string label = age >= 18 ? "adult" : "minor"; sceglie uno di due valori. Usalo per selezioni semplici; passa a un if-else completo quando ogni ramo contiene vera logica.