Ciclo while in Rust
Un ciclo while continua a girare finché una condizione resta true. È lo strumento giusto quando sai che cosa stai aspettando, anche se non sai esattamente quante ripetizioni serviranno.
Ciclo while di base
Sezione intitolata “Ciclo while di base”fn main() { let mut count = 1;
while count <= 5 { println!("{count}"); count += 1; }}Output:
12345La condizione (count <= 5) viene controllata prima di ogni giro del ciclo. Appena diventa false, il ciclo finisce: qui, dopo che count è diventato 6.
while o loop?
Sezione intitolata “while o loop?”Potresti scrivere la stessa cosa con loop e un if/break a mano, ma while dice in modo più diretto quello che intendi: «continua finché questo è vero». Tieni loop per i casi in cui la condizione di uscita non sta bene in cima al ciclo.
// con while: chiaro e direttolet mut n = 0;while n < 3 { println!("{n}"); n += 1;}
// la stessa cosa con loop: funziona, ma c'è più da leggerelet mut n = 0;loop { if n >= 3 { break; } println!("{n}"); n += 1;}Un esempio più realistico
Sezione intitolata “Un esempio più realistico”while si usa spesso per aspettare che un valore raggiunga un obiettivo:
fn main() { let mut balance = 100;
while balance < 200 { balance += 25; println!("Il saldo ora è {balance}"); }
println!("Obiettivo raggiunto!");}Output:
Il saldo ora è 125Il saldo ora è 150Il saldo ora è 175Il saldo ora è 200Obiettivo raggiunto!La condizione può essere qualsiasi espressione che dà un bool, quindi puoi combinare più controlli con && e || della pagina sugli Operatori, per esempio while balance < 200 && months < 12.
Rust non ha il do-while
Sezione intitolata “Rust non ha il do-while”Alcuni linguaggi hanno un ciclo do { ... } while (condizione). Esegue il corpo prima e controlla la condizione dopo, quindi il corpo gira sempre almeno una volta. Rust non ce l’ha. Al suo posto usi loop e metti il controllo alla fine.
Ecco un caso in cui la differenza conta. Per contare le cifre di un numero puoi continuare a dividerlo per 10 finché non resta niente. Però il numero 0 ha comunque una cifra, e un semplice ciclo while per lui non parte mai:
fn main() { let number = 0;
// Un ciclo while controlla prima, quindi con 0 non gira mai. let mut n = number; let mut digits = 0; while n > 0 { digits += 1; n /= 10; } println!("secondo while {number} ha {digits} cifre");
// loop + un controllo alla fine esegue il corpo almeno una volta. let mut n = number; let mut digits = 0; loop { digits += 1; n /= 10; if n == 0 { break; } } println!("secondo loop {number} ha {digits} cifra");}Output:
secondo while 0 ha 0 cifresecondo loop 0 ha 1 cifraCambia number in 4096 e le due versioni vanno d’accordo: 4 cifre. La differenza si vede solo quando la condizione è falsa fin dall’inizio. Quindi la regola pratica è: se il corpo deve girare almeno una volta, scrivi loop con if ... { break; } in fondo.
Esiste anche un altro tipo di ciclo while, while let, che continua finché un valore corrisponde a un pattern. Lo trovi nella pagina If let e while let.
Pratica
Sezione intitolata “Pratica”1. Somma finché superi 100
Sezione intitolata “1. Somma finché superi 100”Somma 1 + 2 + 3 + … e fermati appena il totale è maggiore di 100. Stampa quanti numeri hai sommato e il totale. Suggerimento: ti servono due variabili mut, una per il prossimo numero e una per il totale.
Mostra la soluzione
fn main() { let mut next = 1; let mut total = 0;
while total <= 100 { total += next; next += 1; }
println!("Sommati {} numeri, il totale è {total}", next - 1);}Output:
Sommati 14 numeri, il totale è 105Dopo l’ultimo giro, next è già andato avanti di un passo: per questo stampiamo next - 1. Vale la pena controllare questi dettagli «sfasati di uno» con un piccolo esempio a mente.
2. Dimezza finché arrivi a 1
Sezione intitolata “2. Dimezza finché arrivi a 1”Parti da 1000. Finché il numero è maggiore di 1, dividilo per 2 (divisione intera) e stampalo. Alla fine stampa quanti dimezzamenti ci sono voluti. Suggerimento: n /= 2 divide n per 2 e scarta il resto.
Mostra la soluzione
fn main() { let mut n = 1000; let mut steps = 0;
while n > 1 { n /= 2; steps += 1; println!("{n}"); }
println!("Ci sono voluti {steps} dimezzamenti per arrivare a 1");}Output:
500250125623115731Ci sono voluti 9 dimezzamenti per arrivare a 1125 / 2 fa 62, non 62.5, perché entrambi i numeri sono interi. È proprio questo che fa finire il ciclo esattamente a 1.
Riepilogo
Sezione intitolata “Riepilogo”while condizione { ... }ripete finché la condizione ètrue, e la controlla prima di ogni giro.- Assicurati che qualcosa dentro il ciclo prima o poi renda la condizione
false, altrimenti girerà per sempre. - Preferisci
whilealoopquando la condizione di uscita si esprime in modo naturale come «finché X è vero». - Rust non ha il do-while. Quando il corpo deve girare almeno una volta, usa
loopcon il controllo delbreakalla fine.
Verifica veloce
Sezione intitolata “Verifica veloce”Verifica veloce
1. Qual è l'errore classico che causa un ciclo while infinito?
2. Secondo questa pagina, quando conviene preferire while a loop?
3. Come scrivi un ciclo il cui corpo gira sempre almeno una volta?
Punteggio: 0 / 3
Per approfondire
Sezione intitolata “Per approfondire”- Conditional Loops with while — The Rust Book (in inglese): l’introduzione ufficiale, che confronta
whileconloop. - while — Rust by Example (in inglese): un FizzBuzz eseguibile scritto con un ciclo
while. - Predicate loops — The Rust Reference (in inglese): le regole esatte con cui gira un ciclo
while. - La parola chiave
while— documentazione della libreria standard (in inglese): un breve riassunto diwhileewhile let, con esempi.