La boucle while en Rust
Une boucle while continue de tourner tant qu’une condition reste true. C’est le bon outil quand vous savez ce que vous attendez, même si vous ne savez pas exactement combien de tours il faudra.
Une boucle while simple
Section intitulée « Une boucle while simple »fn main() { let mut count = 1;
while count <= 5 { println!("{count}"); count += 1; }}Sortie :
12345La condition (count <= 5) est vérifiée avant chaque tour de boucle. Dès qu’elle vaut false, la boucle s’arrête : ici, quand count passe à 6.
while ou loop ?
Section intitulée « while ou loop ? »Vous pourriez écrire la même chose avec loop et un if/break à la main, mais while exprime votre intention plus directement : « continue tant que c’est vrai ». Gardez loop pour les cas où la condition d’arrêt ne trouve pas naturellement sa place en haut de la boucle.
// avec while : clair et directlet mut n = 0;while n < 3 { println!("{n}"); n += 1;}
// la même chose avec loop : ça marche, mais c'est plus long à lirelet mut n = 0;loop { if n >= 3 { break; } println!("{n}"); n += 1;}Un exemple plus concret
Section intitulée « Un exemple plus concret »On utilise souvent while pour attendre qu’une valeur atteigne un objectif :
fn main() { let mut balance = 100;
while balance < 200 { balance += 25; println!("Le solde est maintenant de {balance}"); }
println!("Objectif atteint !");}Sortie :
Le solde est maintenant de 125Le solde est maintenant de 150Le solde est maintenant de 175Le solde est maintenant de 200Objectif atteint !La condition peut être n’importe quelle expression qui donne un bool. Vous pouvez donc combiner plusieurs tests avec && et ||, vus à la page Opérateurs, par exemple while balance < 200 && months < 12.
Rust n’a pas de do-while
Section intitulée « Rust n’a pas de do-while »Certains langages ont une boucle do { ... } while (condition). Elle exécute le corps d’abord et vérifie la condition ensuite, donc le corps s’exécute toujours au moins une fois. Rust ne l’a pas. À la place, on utilise loop et on place le test à la fin.
Voici un cas où ça compte. Pour compter les chiffres d’un nombre, on peut le diviser par 10 jusqu’à ce qu’il ne reste plus rien. Mais le nombre 0 a quand même un chiffre, et une simple boucle while ne s’exécute jamais pour lui :
fn main() { let number = 0;
// Une boucle while vérifie d'abord, donc elle ne tourne jamais pour 0. let mut n = number; let mut digits = 0; while n > 0 { digits += 1; n /= 10; } println!("selon while, {number} a {digits} chiffre(s)");
// loop + un test à la fin exécute le corps au moins une fois. let mut n = number; let mut digits = 0; loop { digits += 1; n /= 10; if n == 0 { break; } } println!("selon loop, {number} a {digits} chiffre(s)");}Sortie :
selon while, 0 a 0 chiffre(s)selon loop, 0 a 1 chiffre(s)Remplacez number par 4096 et les deux versions sont d’accord : 4 chiffres. La différence n’apparaît que lorsque la condition est fausse dès le départ. D’où la règle pratique : si le corps doit s’exécuter au moins une fois, écrivez loop avec le if ... { break; } en bas.
Il existe encore un autre type de boucle while, while let, qui continue tant qu’une valeur correspond à un pattern (motif). Elle est expliquée à la page If let et while let.
Exercices
Section intitulée « Exercices »1. Additionner jusqu’à dépasser 100
Section intitulée « 1. Additionner jusqu’à dépasser 100 »Additionnez 1 + 2 + 3 + … et arrêtez-vous dès que le total est strictement supérieur à 100. Affichez combien de nombres vous avez additionnés et le total. Indice : il vous faut deux variables mut, une pour le prochain nombre et une pour le total.
Voir la solution
fn main() { let mut next = 1; let mut total = 0;
while total <= 100 { total += next; next += 1; }
println!("{} nombres additionnés, le total est {total}", next - 1);}Sortie :
14 nombres additionnés, le total est 105Après le dernier tour, next a déjà avancé d’un cran, c’est pourquoi on affiche next - 1. Ce genre de décalage d’une unité mérite d’être vérifié de tête sur un petit exemple.
2. Diviser par deux jusqu’à 1
Section intitulée « 2. Diviser par deux jusqu’à 1 »Partez de 1000. Tant que le nombre est supérieur à 1, divisez-le par 2 (division entière) et affichez-le. À la fin, affichez combien de divisions il a fallu. Indice : n /= 2 divise n par 2 et laisse tomber le reste.
Voir la solution
fn main() { let mut n = 1000; let mut steps = 0;
while n > 1 { n /= 2; steps += 1; println!("{n}"); }
println!("Il a fallu {steps} divisions par 2 pour arriver à 1");}Sortie :
500250125623115731Il a fallu 9 divisions par 2 pour arriver à 1125 / 2 donne 62, pas 62.5, parce que les deux nombres sont des entiers. C’est pour ça que la boucle s’arrête pile à 1.
Récapitulatif
Section intitulée « Récapitulatif »while condition { ... }répète le corps tant que la condition esttrue, en la vérifiant avant chaque tour.- Assurez-vous que quelque chose dans la boucle finit par rendre la condition
false, sinon elle tournera indéfiniment. - Préférez
whileàloopdès que la condition d’arrêt s’exprime naturellement par « tant que X est vrai ». - Rust n’a pas de do-while. Quand le corps doit s’exécuter au moins une fois, utilisez
loopavec le test dubreakà la fin.
Petit quiz
Section intitulée « Petit quiz »Petit quiz
1. Quelle est l'erreur classique qui provoque une boucle while infinie ?
2. D'après cette page, quand faut-il préférer while à loop ?
3. Comment écrire une boucle dont le corps s'exécute toujours au moins une fois ?
Score : 0 / 3
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Conditional Loops with while — The Rust Book (en anglais) : la présentation officielle, qui compare
whileetloop. - while — Rust by Example (en anglais) : un FizzBuzz exécutable écrit avec une boucle
while. - Predicate loops — The Rust Reference (en anglais) : les règles exactes du fonctionnement d’une boucle
while. - Le mot-clé
while— documentation de la bibliothèque standard (en anglais) : un court résumé dewhileetwhile let, avec des exemples.