Strutture di controllo in C++
Le strutture di controllo determinano il flusso di esecuzione di un programma, cioè l'ordine in cui le istruzioni vengono eseguite. Senza di esse un programma eseguirebbe le istruzioni una dopo l'altra in sequenza rigida. Grazie alle strutture di controllo, invece, è possibile prendere decisioni in base a condizioni e ripetere blocchi di codice più volte. Si dividono in due grandi famiglie: le istruzioni condizionali e i cicli.
L'istruzione if
L'istruzione if esegue un blocco di codice solo se una determinata condizione risulta vera. Può essere accompagnata dalla clausola else, che indica cosa fare quando la condizione è falsa, e da una o più clausole else if per gestire più casi alternativi in cascata.
#include <iostream>
int main() {
int score = 75;
if (score >= 90) {
std::cout << "Eccellente" << std::endl;
} else if (score >= 60) {
std::cout << "Sufficiente" << std::endl;
} else {
std::cout << "Insufficiente" << std::endl;
}
return 0;
}
Le condizioni vengono valutate dall'alto verso il basso e viene eseguito il primo blocco la cui condizione è vera; tutti gli altri vengono ignorati. Se nessuna condizione è soddisfatta, viene eseguito il blocco else, qualora presente.
L'istruzione switch
Quando si deve confrontare una stessa variabile con molti valori costanti, l'istruzione switch offre un'alternativa più leggibile rispetto a una lunga catena di else if. Ogni caso è introdotto dalla parola chiave case, e l'istruzione break impedisce che l'esecuzione prosegua nei casi successivi. La clausola default gestisce tutti i valori non previsti esplicitamente.
int dayNumber = 3;
switch (dayNumber) {
case 1:
std::cout << "Lunedi" << std::endl;
break;
case 3:
std::cout << "Mercoledi" << std::endl;
break;
default:
std::cout << "Giorno non gestito" << std::endl;
break;
}
Dimenticare l'istruzione break è un errore frequente: senza di essa l'esecuzione prosegue nel caso successivo, fenomeno noto come fall-through, che a volte è voluto ma più spesso è una svista.
Il ciclo while
Il ciclo while ripete un blocco di codice finché una condizione rimane vera. La condizione viene verificata prima di ogni iterazione: se è falsa fin dall'inizio, il corpo del ciclo non viene eseguito nemmeno una volta. È fondamentale che qualcosa all'interno del ciclo, prima o poi, renda falsa la condizione, altrimenti si genera un ciclo infinito.
int countdown = 5;
while (countdown > 0) {
std::cout << countdown << std::endl;
countdown--; // Senza questa riga il ciclo non terminerebbe mai
}
Il ciclo do-while
Il ciclo do-while è simile al while, ma verifica la condizione al termine di ogni iterazione anziché all'inizio. Questo garantisce che il corpo del ciclo venga eseguito almeno una volta, indipendentemente dalla condizione. È utile quando si vuole eseguire un'operazione e solo successivamente decidere se ripeterla.
int attempts = 0;
do {
std::cout << "Tentativo numero " << attempts << std::endl;
attempts++;
} while (attempts < 3);
Il ciclo for
Il ciclo for raccoglie in un'unica riga tre elementi: l'inizializzazione di una variabile contatore, la condizione di continuazione e l'aggiornamento del contatore. È la scelta ideale quando si conosce in anticipo il numero di iterazioni da eseguire, perché concentra in un solo punto tutta la logica di controllo del ciclo.
// Stampa i numeri da 0 a 4
for (int i = 0; i < 5; i++) {
std::cout << i << std::endl;
}
Il ciclo for basato su intervallo
Il C++ moderno introduce una forma di ciclo for pensata per scorrere tutti gli elementi di una collezione, senza dover gestire manualmente un indice. Questa sintassi rende il codice più chiaro e meno soggetto a errori, perché elimina la necessità di calcolare i limiti dell'intervallo.
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers = {10, 20, 30};
// Scorre ogni elemento del contenitore
for (int value : numbers) {
std::cout << value << std::endl;
}
return 0;
}
Interrompere e saltare iterazioni
All'interno di qualsiasi ciclo è possibile alterarne il flusso normale. L'istruzione break interrompe immediatamente il ciclo e prosegue con il codice successivo, mentre continue salta la parte restante dell'iterazione corrente e passa direttamente alla successiva. Vanno usate con misura, perché un uso eccessivo può rendere il flusso del programma difficile da seguire.
for (int i = 0; i < 10; i++) {
if (i == 5) {
break; // Esce dal ciclo quando i vale 5
}
if (i % 2 == 0) {
continue; // Salta i numeri pari
}
std::cout << i << std::endl;
}
Le strutture di controllo sono il cuore della logica di ogni programma. Combinando condizioni e cicli è possibile esprimere comportamenti arbitrariamente complessi. Nel prossimo articolo vedremo come organizzare il codice in funzioni, per renderlo riutilizzabile e più ordinato.