Une boucle while répète son corps tant qu'une condition reste vraie. Utilisez-la quand vous ne savez pas à l'avance combien d'itérations il faudra : continuer jusqu'à ce qu'un solde atteigne un objectif, qu'une file soit vide ou que l'entrée soit épuisée.
Sortie :
Year 1: 1070.00
Year 2: 1144.90
Year 3: 1225.04
Year 4: 1310.80
Year 5: 1402.55
Year 6: 1500.73
Goal reached after 6 years
La condition est vérifiée avant chaque itération, y compris la première. Si savings atteignait déjà l'objectif, le corps ne s'exécuterait jamais et le programme afficherait « after 0 years ». La boucle dépend du fait que le corps modifie quelque chose que lit la condition ; ici, savings augmente chaque année jusqu'à ce que savings < goal devienne faux.
do while : s'exécuter au moins une fois
Une boucle do while déplace le test à la fin, donc le corps s'exécute toujours au moins une fois :
Sortie :
Attempt 1: got 7
Attempt 2: got 4
Attempt 3: got 1
Done after 3 attempts
La première valeur de code n'existe qu'une fois le corps exécuté, ce qui est exactement le cas où un do while convient. Deux détails de syntaxe piègent les développeurs :
- Le point-virgule après
while (code != 1)est obligatoire. L'oublier est une erreur de compilation. - Les variables utilisées dans la condition doivent être déclarées avant
do. Une variable déclarée dans les accolades n'est plus visible au moment où la condition s'exécute, doncdo { int code = ...; } while (code != 1);ne compile pas.
La même boucle écrite avec while demande soit un premier appel dupliqué avant la boucle, soit une valeur de départ factice qui force le premier passage. do while exprime directement « essayer, puis décider s'il faut réessayer ».
Lire une saisie jusqu'à une valeur d'arrêt
Lire des lignes jusqu'à un mot d'arrêt, ou jusqu'à la fin de l'entrée, est la boucle while par excellence. Console.ReadLine() renvoie null quand il n'y a plus d'entrée, donc testez les deux :
Sortie :
skipping "abc": not a number
3 amounts, total 49.50
(line = Console.ReadLine()) != null affecte la ligne suivante et la teste en une seule expression ; les parenthèses autour de l'affectation sont obligatoires, car != lie plus fortement que =. La boucle s'arrête à done, donc le 99 qui suit n'est jamais lu. decimal.TryParse rejette abc sans lever d'exception, et continue passe à la ligne suivante. Sans le test de null, atteindre la fin de l'entrée passerait null à TryParse indéfiniment, puisque ReadLine continue de renvoyer null.
Un do while convient au schéma demander puis valider, où l'invite doit apparaître au moins une fois :
Sortie :
Enter your age:
"-4" is not a valid age
Enter your age:
"fifteen" is not a valid age
Enter your age:
Age accepted: 15
L'invite se trouve dans la boucle, elle se répète donc après chaque réponse rejetée, et age est déclaré avant do pour que le code situé après la boucle puisse l'utiliser. Avec un utilisateur au clavier, chaque réponse apparaît dans la console après son invite ; avec une entrée redirigée, comme ici, seule la sortie du programme lui-même s'affiche.
while (true) avec break
Parfois, le point de sortie naturel se trouve au milieu du corps, après une partie du travail et avant le reste. Écrivez la boucle sous la forme while (true) et sortez avec break :
Sortie :
processing: resize photo
processing: send email
stop signal received
1 job(s) left in the queue
Dequeue retire la tâche suivante en tête de la file, et la boucle se termine dès qu'elle voit le marqueur d'arrêt, donc la dernière tâche reste dans la file. while (true) n'est pas un mauvais signe quand la sortie est claire et proche du début du corps. Il le devient quand plusieurs break sont éparpillés dans un long corps ; une condition bool nommée ou une méthode avec return est alors plus facile à suivre. La page sur break et continue explique comment sortir de boucles imbriquées.
Les boucles qui ne se terminent jamais
Une boucle infinie involontaire a l'une de trois causes.
Le corps ne modifie jamais la condition. Le compteur n'est jamais incrémenté, ou c'est la mauvaise variable qui l'est :
int i = 0;
while (i < 5)
{
Console.WriteLine(i); // i++ forgotten: prints 0 forever
}
Un point-virgule après la condition. Le point-virgule constitue tout le corps de la boucle, et le bloc situé en dessous s'exécute après la boucle (qui ne se termine jamais) :
while (retries < 3); // warning CS0642: Possible mistaken empty statement
{
retries++;
}
Une condition qui dépasse sa cible. Tester != quand la variable avance par pas peut sauter la valeur d'arrêt. while (x != 10) x += 3; passe par 0, 3, 6, 9, 12 et dépasse 10 (elle ne tombe sur 10 que par accident, après que l'int a débordé et bouclé des milliards de pas plus tard). Testez avec < ou > au lieu de != dès que le pas n'est pas 1. Il en va de même pour les valeurs double, qui tombent rarement sur une cible exacte : while (x != 1.0) x += 0.1; ne se termine jamais.
Choisir entre while, do while et for
| Situation | Boucle |
|---|---|
| Nombre d'itérations connu, ou un index | for |
| Chaque élément d'une collection | foreach |
| Répéter tant qu'une condition est vraie, éventuellement zéro fois | while |
| Le corps doit s'exécuter une fois avant que la condition ait un sens | do while |
| Test de sortie au milieu du corps | while (true) avec break |
Toute boucle for peut être réécrite en boucle while et inversement ; le choix consiste à placer la logique de la boucle là où le lecteur s'attend à la trouver. Quand le compteur, le test et le pas existent tous, for les garde sur une ligne. Quand la boucle est pilotée par un état qui change dans le corps, while le dit.
Questions fréquentes
Quelle est la différence entre while et do while en C# ?
Une boucle while vérifie sa condition avant chaque itération, donc son corps peut s'exécuter zéro fois. Une boucle do { } while (condition); la vérifie après chaque itération, donc son corps s'exécute toujours au moins une fois. Utilisez do while quand le premier passage produit la valeur que teste la condition, par exemple lire une saisie puis la valider.
Quelle est la syntaxe d'une boucle do while en C# ?
do { body } while (condition);. Notez le point-virgule après la parenthèse fermante : il est obligatoire, et l'oublier est une erreur de compilation. La condition peut utiliser des variables affectées dans le corps, mais elles doivent être déclarées avant le do, car les accolades du corps forment une portée séparée.
Comment écrire while (true) en C# ?
while (true) { ... } boucle indéfiniment jusqu'à ce que quelque chose à l'intérieur en sorte avec break, return ou une exception. C'est la forme naturelle quand le test de sortie se trouve au milieu du corps, par exemple lire une ligne et s'arrêter quand elle est vide.
Comment lire une saisie jusqu'à ce que l'utilisateur tape un mot ou que l'entrée se termine en C# ?
Bouclez sur Console.ReadLine(), qui renvoie null à la fin de l'entrée : string line; while ((line = Console.ReadLine()) != null && line != "done") { ... }. L'affectation dans la condition lit la ligne suivante et la teste en une seule étape.
Pourquoi ma boucle while C# ne se termine-t-elle jamais ?
En général, le corps ne modifie jamais ce que teste la condition (un i++ oublié), ou il y a un point-virgule juste après la condition : while (count < 10); est une boucle au corps vide qui tourne indéfiniment. Le compilateur signale ce second cas par l'avertissement CS0642, Possible mistaken empty statement.