Répéter tant que
Faire tourner le programme en rond, jusqu'à ce qu'une condition change.
Après cette fiche, vous saurez :
- écrire une boucle while
- éviter la boucle infinie
- utiliser do…while quand il faut passer au moins une fois
- reconnaître une boucle dans un ordinogramme
1Le problème des lignes répétées
Souvenez-vous de la fiche 5. Pour compter trois évènements, vous avez écrit :
nbEvents = nbEvents + 1; nbEvents = nbEvents + 1; nbEvents = nbEvents + 1;
Trois fois la même ligne. Et pour le bon d'achat, trois fois
totalAchats = totalAchats + ….
Imaginez maintenant qu'il faille compter cent évènements. Ou mille. Ou un nombre qu'on ne connaît pas d'avance.
À retenir
Dès que vous écrivez deux fois la même ligne, pensez « boucle ».
Une boucle fait répéter un bloc de code à l'ordinateur, autant de fois que nécessaire. Vous ne l'écrivez qu'une seule fois.
2while : tant que
int compteur = 1; while (compteur <= 5) { Console.WriteLine($"Tour numéro {compteur}"); compteur = compteur + 1; } Console.WriteLine("Terminé !");
Tour numéro 1 Tour numéro 2 Tour numéro 3 Tour numéro 4 Tour numéro 5 Terminé !
Cinq lignes affichées, alors qu'on n'a écrit qu'un seul
Console.WriteLine.
| Morceau | Rôle |
|---|---|
while | « tant que » en anglais |
(compteur <= 5) | La condition à vérifier avant chaque tour |
{ … } | Ce qu'on répète |
Comment l'ordinateur exécute une boucle
- Il teste la condition
compteur <= 5? Au premier passage, compteur vaut 1. C'est vrai. - Il exécute le bloc Il affiche, puis augmente le compteur.
- Il remonte Et recommence à l'étape 1.
- Quand la condition devient fausse Il saute le bloc et continue en dessous.
| Tour | compteur au début | Condition | Ce qui s'affiche |
|---|---|---|---|
| 1 | 1 | 1 ≤ 5 → vrai | Tour numéro 1 |
| 2 | 2 | 2 ≤ 5 → vrai | Tour numéro 2 |
| 3 | 3 | 3 ≤ 5 → vrai | Tour numéro 3 |
| 4 | 4 | 4 ≤ 5 → vrai | Tour numéro 4 |
| 5 | 5 | 5 ≤ 5 → vrai | Tour numéro 5 |
| — | 6 | 6 ≤ 5 → faux | on sort |
À retenir
Tracez toujours ce tableau quand une boucle ne fait pas ce que vous attendez.
C'est la méthode des professionnels, et c'est la seule qui marche à coup sûr. Trois colonnes suffisent : le numéro du tour, la valeur des variables, et le résultat du test.
3Le piège : la boucle infinie
Attention
Si rien ne change dans la boucle, elle ne s'arrête jamais.
int compteur = 1; while (compteur <= 5) { Console.WriteLine($"Tour numéro {compteur}"); // on a oublié d'augmenter le compteur ! }
compteur vaut toujours 1. La condition est toujours vraie. Le
programme affiche « Tour numéro 1 » indéfiniment, jusqu'à ce que vous le tuiez.
Pour l'arrêter : cliquez dans la fenêtre noire et appuyez sur Ctrl + C. Ou fermez la fenêtre.
À retenir
Toute boucle while a besoin de trois choses.
- Une variable initialisée avant la boucle.
- Une condition qui la teste.
- Une modification de cette variable à l'intérieur du bloc.
Il manque l'une des trois ? Votre boucle est cassée. Vérifiez-les dans cet ordre à chaque fois.
Une boucle qui ne compte pas
La condition n'est pas forcément un compteur. Elle peut dépendre de l'utilisateur.
string reponse = ""; while (reponse != "stop") { Console.Write("Tapez quelque chose (ou 'stop' pour quitter) : "); reponse = Console.ReadLine().ToLower(); Console.WriteLine($"Vous avez tapé : {reponse}"); } Console.WriteLine("Au revoir !");
Ici, c'est l'utilisateur qui décide quand la boucle s'arrête. Le nombre de tours n'est pas connu d'avance.
4do…while : passer au moins une fois
Avec while, la condition est testée avant le premier tour.
Si elle est fausse dès le départ, le bloc n'est jamais exécuté.
Parfois, on veut le contraire.
string reponse; do { Console.Write("Voulez-vous continuer ? (oui/non) "); reponse = Console.ReadLine().ToLower(); } while (reponse == "oui"); Console.WriteLine("Fin du programme.");
La question est forcément posée une première fois. Ce n'est qu'après qu'on teste s'il faut recommencer.
while | do…while | |
|---|---|---|
| La condition est testée | avant le bloc | après le bloc |
| Nombre minimum de tours | 0 | 1 |
| Quand l'utiliser | on peut ne rien faire du tout | il faut faire au moins une fois |
À retenir
La question à se poser : le bloc doit-il s'exécuter au moins une fois, quoi qu'il arrive ?
- Poser une question à l'utilisateur ? Oui, forcément. →
do…while - Afficher les emprunts en retard ? Peut-être qu'il n'y en a aucun. →
while
Attention au point-virgule après le while final du
do…while. Il est obligatoire là, alors qu'il est interdit sur un
while normal.
5L'ordinogramme : la flèche qui remonte
Une boucle n'a pas de forme à elle. Elle se dessine avec le losange de la fiche 8, et une flèche qui remonte.
À retenir
Ce qui fait une boucle sur un ordinogramme : une flèche qui remonte vers un point déjà parcouru.
C'est exactement ce que nous annoncions à la fiche 1 : le chemin ne descend pas toujours tout droit. Le voilà, ce chemin qui remonte.
Notez que le losange de la boucle ressemble à celui d'une condition, mais qu'une de ses sorties revient en arrière au lieu de continuer.
→Exercices
Recopiez ce programme et lancez-le.
int compteur = 1; while (compteur <= 10) { Console.WriteLine($"Compteur : {compteur}"); compteur = compteur + 1; } Console.WriteLine("Fini !"); Console.ReadKey();
- Combien de lignes s'affichent ?
- Que vaut
compteurà la fin ? - Supprimez la ligne
compteur = compteur + 1;et relancez. Que se passe-t-il, et comment arrêtez-vous le programme ?
Solution
1. Dix lignes, de 1 à 10.
2. compteur vaut 11. C'est ce qui a fait échouer le
test 11 <= 10 et permis de sortir.
C'est normal, et c'est important à comprendre : après une boucle, la variable dépasse toujours d'un cran la dernière valeur utilisée.
3. Boucle infinie. « Compteur : 1 » défile sans fin.
Pour l'arrêter : cliquez dans la fenêtre noire et faites Ctrl + C. Ou fermez simplement la fenêtre.
Rassurez-vous, il n'y a aucun danger pour votre ordinateur. C'est une erreur que tout le monde fait, y compris les professionnels.
Reprenez le compteur d'évènements de la fiche 5, où vous aviez écrit trois fois
nbEvents = nbEvents + 1;.
- Écrivez un programme qui demande combien d'évènements Radakass va vivre.
- Utilisez une boucle pour afficher « Évènement numéro X » autant de fois.
- À chaque évènement, Radakass perd 5 HP. Il commence à 100.
- Affichez ses HP après chaque évènement, et son état final.
Solution
int hp = 100; Console.Write("Combien d'évènements ? "); int nbEvents = int.Parse(Console.ReadLine()); int compteur = 1; Console.WriteLine(); Console.WriteLine($"Radakass démarre avec {hp} HP"); Console.WriteLine(); while (compteur <= nbEvents) { hp = hp - 5; Console.WriteLine($"Évènement numéro {compteur} : Radakass a {hp} HP"); compteur = compteur + 1; } Console.WriteLine(); if (hp <= 0) { Console.WriteLine("Radakass n'a pas survécu à l'aventure."); } else { Console.WriteLine($"Radakass s'en sort avec {hp} HP !"); } Console.ReadKey();
Combien d'évènements ? 4
Radakass démarre avec 100 HP
Évènement numéro 1 : Radakass a 95 HP
Évènement numéro 2 : Radakass a 90 HP
Évènement numéro 3 : Radakass a 85 HP
Évènement numéro 4 : Radakass a 80 HP
Radakass s'en sort avec 80 HP !Comparez avec la fiche 5. Là-bas, trois évènements demandaient neuf lignes de code, et il fallait tout réécrire pour en ajouter un quatrième.
Ici, le nombre d'évènements est demandé à l'utilisateur. Le programme fonctionne avec 3, avec 25 ou avec 1000, sans qu'on change une seule ligne.
Testez avec 25 : Radakass meurt. Le if de la fin le détecte
correctement.
Les trois éléments de la boucle sont bien là : compteur = 1
avant, la condition compteur <= nbEvents, et
compteur = compteur + 1 dedans.
Écrivez un petit jeu.
- Choisissez un nombre secret, écrit en dur dans le programme (par exemple 42).
- Demandez à l'utilisateur de deviner, encore et encore, tant qu'il n'a pas trouvé.
- À chaque essai, dites-lui « c'est plus grand » ou « c'est plus petit ».
- Comptez le nombre d'essais.
- Quand il trouve, félicitez-le et affichez le nombre d'essais.
Réfléchissez : faut-il un while ou un do…while ?
Solution
int secret = 42; int proposition; int essais = 0; Console.WriteLine("=== LE NOMBRE MYSTÈRE ==="); Console.WriteLine("J'ai choisi un nombre entre 1 et 100."); Console.WriteLine(); do { Console.Write("Votre proposition : "); proposition = int.Parse(Console.ReadLine()); essais = essais + 1; if (proposition < secret) { Console.WriteLine("C'est plus grand !"); } else if (proposition > secret) { Console.WriteLine("C'est plus petit !"); } } while (proposition != secret); Console.WriteLine(); Console.WriteLine($"Bravo ! Trouvé en {essais} essai(s)."); Console.ReadKey();
=== LE NOMBRE MYSTÈRE === J'ai choisi un nombre entre 1 et 100. Votre proposition : 50 C'est plus petit ! Votre proposition : 25 C'est plus grand ! Votre proposition : 42 Bravo ! Trouvé en 3 essai(s).
Pourquoi do…while ?
Parce qu'il faut forcément demander au moins une proposition avant de pouvoir
tester quoi que ce soit. Avec un while classique, il faudrait initialiser
proposition à une valeur bidon avant la boucle — ça marche, mais
c'est moins élégant.
Le compteur d'essais est incrémenté juste après la saisie, avant les tests. S'il était placé à la fin, le dernier essai gagnant ne serait pas compté.
Remarquez : quand l'utilisateur trouve, aucun des deux messages ne s'affiche.
Ni « plus grand », ni « plus petit ». C'est voulu : le else if ne se
déclenche que si la proposition est différente.
Pour aller plus loin : remplacez int secret = 42; par
Random de = new Random(); suivi de
int secret = de.Next(1, 101);, avant la boucle (voir la fiche 9). Le
nombre change à chaque partie.
Je sais faire
- Je sais écrire une boucle while.
- Je sais pourquoi une boucle peut tourner à l'infini.
- Je connais la différence entre while et do…while.
- Je reconnais une boucle sur un ordinogramme.
Une case qui coince ? Relisez la partie concernée avant de passer à la fiche suivante.