2. Les boucles
Après cette quête, tu sauras itérer de plusieurs manières et seras capable de maîtriser le flux d'exécution de manière plus fine
Objectifs
- Comprendre la notion d'itération
- Écrire des conditions tant que
- Écrire des conditions bornée
- Contrôler le flux d'exécution des boucles avec
breaketcontinue
Ton spectacle de danse classique

Et 1, 2, 3, quaaaatre ... Cela fait maintenant quelque temps que tu t'es mis.e à la danse classique et, que tu le veuilles ou non, une représentation t'attend dans deux jours. Tu te sens fin prêt à enfiler ton tutu et assurer le spectacle, mais ton prof n'a pas l'air du même avis. Il aimerait que tu travailles jour et nuit pour que tu maîtrises bien la répétition des mouvements et la technicité qui leur est associée. Tu aimerais partir pour rentrer chez toi, mais ce prof (diabolique) t'assure avec véhémence que tu as encore besoin de beaucoup d'entraînement avant de pouvoir élancer ton corps avec légèreté et présence.
Ton prof te prend entre quatre yeux à la fin de l'entraînement pour te faire réviser - encore une fois - les bases de la danse et du rythme. Tu répètes, répètes, répètes et répètes encore une fois. La prof te fait danser les phases encore et encore ...
A force de répéter des mouvements, ton esprit divague vers des questions existentielles concernant la nature des répétitions, et ce qui les constitue fondamentalement.
Tu commences alors à construire dans ta tête un programme fait de répétitions et, pour te préparer au spectacle que tu vas donner avec ton équipe de danse, tu veux réviser les fondamentaux théoriques. Ce qui t'amène ici à lire ce présent document.
Une itération
Tu te souviens de ta prof qui te répétait sans cesse : "Encore une itération du pas, et cela quatre fois !". Cette phrase résonne dans ta tête alors que le trac commence à monter.
Mais au fait, c'est quoi, une itération ?
En mathématiques, une itération est le fait de répéter plusieurs fois un processus. Eh bien en programmation, le principe est exactement le même : une itération est le fait de répéter plusieurs fois la même opération. Tu as sûrement déjà entendu et utilisé le mot réitérer plusieurs fois dans ta vie. C'est un mot dont un des synonymes est répéter.
Attention, cependant : en programmation, une itération n'est pas à proprement parler une répétition. Il ne suffit pas de copier-coller un même morceau de code plusieurs fois pour réaliser une ou plusieurs itérations. Je sais, cela semble bizarre, mais il ne faut pas se mélanger les pinceaux : en programmation, des itérations sont réalisées dans des blocs particuliers adaptés à la répétition. Ecrire plusieurs fois le même code dans une fiche de code ne peut pas être appelé une itération. De plus, avoir deux fois le même code qui réalise la même tâche est une mauvaise pratique en programmation. Si tu vois du copier-coller quelque part, ce n'est pas une itération mais une répétition.
Je suppose que tu as déjà abordé le sujet des itérables, ou du moins des conteneurs ?
Oui, les itérables sont des conteneurs. Un conteneur est une suite de valeurs du même type, stockées de manière organisée.
Exactement ! Et si tu as compris le principe d'itération, tu devrais aussi comprendre pourquoi on peut appeler un conteneur un itérable. Puisqu'un conteneur est une suite de valeurs du même type, il est possible de répéter plusieurs fois la même action sur toutes les valeurs du conteneur. Dans ce cas-là, on réalise chaque opérant en itérant dans le conteneur. Ainsi, une même opération sera réalisée une fois sur chaque élément du conteneur.
Ainsi, une itération est une seule et même opération, réalisée plusieurs fois à la suite. C'est aussi simple que cela. Par exemple, en pseudo-code :
Pour chaque pasDeDanse dans la suiteDeMouvements
Exécuter(pasDeDanse)
FinPour
Le pseudo code ci-dessus te permet de danser chaque pas de danse compris dans une suite de mouvements, en itérant pas par pas dans la suite de mouvements.

Et alors, comment je fais pour en écrire en C# ?
Un bloc itératif

Un ensemble de mouvements est réalisé plusieurs fois de suite à chaque partie des musiques sur lesquelles tu déhanches ton corps. Une suite est décomposée mouvement par mouvement. Tu dois répéter plusieurs fois cette même suite pour satisfaire ton prof et le public qui te regardera. Tu dois bien distinguer quels mouvements appartiennent à quelles itérations.
Un bloc itératif contient une suite d'instructions réalisées plusieurs fois. Un bloc est entouré de deux apostrophes et précédé par un mot-clé précisant la nature du bloc. Grâce au mot-clé précédant le bloc, on sait quand et comment le code va s'exécuter à l'intérieur du bloc en question.
Il existe plusieurs types de blocs itératifs. Mais au lieu de parler de blocs itératifs, qui est une expression lourde, je vais parler de boucles. Une boucle est une structure de contrôle, c'est-à-dire qu'elle a la responsabilité de s'occuper du flux d'exécution d'un programme. Par conséquent, une condition est une structure de contrôle tout autant qu'une boucle. Une structure de contrôle redirige du code à un endroit ou l'autre, en fonction d'une condition.
Il existe deux types de boucles principaux:
-
Les boucles while
-
les boucles for
Ces deux types possèdent quelques déclinaisons, que nous allons étudier dans la quête courante.
Et on peut tout faire avec seulement deux structures de contrôle itératives ? J'aurais imaginé ça plus compliqué ...
while

La boucle while effectue une seule et même opération, si et seulement si une expression conditionnelle renvoie vrai. Par exemple :
Tant que (laMusiqueEstIntense)
JeTourneSurMoiMeme()
FinTantQue
Dans le pseudo code ci-dessus, on réalise une itération de l'opération tant que la musique est intense. L'opération est de tourner sur soi-même. En français, on peut représenter ça par: Tant que la musique est intense, je tourne sur moi-même.
C'est bien drôle, mais en C#, ça donne quoi ?
Trêve de plaisanteries, le mot-clé précédant un bloc itératif de type while est ... while. La syntaxe est la même que pour une condition : la boucle while s'exécute tant qu'une condition est satisfaite. La condition à satisfaire suit le mot-clé while entre parenthèses :
while (theMusicIsIntense)
{
ITurnAround();
}
Le code ci-dessus est la traduction du pseudo code précédent. Ce code est un peu simpliste, donc pas besoin de le détailler. En revanche, le code qui suit nécessite un peu plus de détails :
string[] moves = { "jump", "turn around", "done" };
bool movesAreDone = false;
int iterator = 0;
while (!movesAreDone)
{
if (moves[iterator] == "done")
{
movesAreDone = true;
}
else
{
iterator = i + 1;
Console.WriteLine("I " + moves[iterator]);
}
}
Console.WriteLine("Your movement set is done after" + iterator + " moves !");
-
Un tableau
movescontenant des pas de danse est déclaré. A ce tableau, on affecte une liste de mouvements -
Une variable booléenne
movesAreDoneest déclarée, puis on l'instancie en lui affectant la valeurfalse -
Une variable de type entier
iteratorest déclarée et on l'instancie en lui affectant la valeur0. -
Tant que la variable
movesAreDonevautfalse:-
Si la variable du tableau
movesà l'indexiteratorest égale àdone, on affecte true àmovesAreDone -
Sinon, on incrémente
iteratorde1pour que la prochaine valeur testée du tableau soit la suivante et on affiche le pas de danse que tu dois faire
-
-
La boucle s'arrête lorsque tous les mouvements ont été réalisés
-
"Your movement set is done after {valeur de iterator} moves !" est affiché pour te donner le nombre de mouvements de la suite de pas de danse
Le nombre d'itérations de la boucle ne changera qu'en fonction de la taille de l'ensemble de mouvements. Plus le tableau grandit, plus le nombre d'itérations augmente, et inversement. Le nombre d'opérations réalisées par rapport à la taille d'une entrée s'appelle la complexité algorithmique, notion que nous abstrayons pour le moment, mais qui est très utile à connaître pour savoir évaluer la vitesse des algorithmes que l'on écrit.
D'ailleurs, cette boucle a un problème : s’il n'y a pas "done" dans le tableau, que se passera- t-il ?
iteratorsera affecté à une valeur plus grande que le nombre d'éléments du tableau ?
C'est cela. Par conséquent, on aura une erreur qui arrêtera le programme, car la zone mémoire à laquelle on cherche à accéder avec iterator n'a pas été allouée. Il s'agit d'une erreur de segmentation.
On ne connaît pas le nombre d'itérations à l'avance, à moins que l'on connaisse le contenu du tableau moves. C'est pour ces cas-là que l'on utilise une boucle while : lorsqu'on ne connaît pas le nombre d'itérations à l'avance.
Tu m'as parlé d'un deuxième type de boucle, non ?
Tutoriel
Vidéo
for

La boucle for est une boucle bornée. Une boucle bornée est une boucle où l'on connaît le nombre d'itérations à l'avance, avant l'exécution de celle-ci. C'est une boucle qui itère à partir d'un début, jusqu'à une fin. Par exemple, en pseudo code:
Pour i allant de 1 à 10 par pas de 1
Ecrire(i)
FinPour
Cette boucle affiche successivement à l'écran tous les entiers naturels appartenant à l'intervalle [1; 10].
Comment j'écris ça en C# ?
La syntaxe de la boucle for est légèrement plus complexe que les autres. Etant donné que c'est une boucle bornée (qui itère sur un ensemble de valeurs fini), il faut le spécifier dans ce qui précède la déclaration du bloc. Ainsi, une boucle bornée a:
-
Une valeur de départ
-
Une condition tant que
-
Le pas avec lequel on incrémente la valeur de départ à chaque itération
Bon, un peu de code pour montrer tout ça :
for (int i=0; i < 12; i++)
{
Console.WriteLine("Number " + i);
}
La boucle ci-dessus affiche à l'écran des entiers allant de 0 à 11, chacun séparé par un saut de ligne. Décortiquons ce qui précède le bloc :
-
Le mot-clé for qui spécifie que l'on utilise une boucle bornée
-
L'instanciation d'une variable
ià0<= valeur de départ -
Une expression booléenne qui asserte que
iest strictement inférieur à 12 <= condition tant que -
i++: équivalent dei = i + 1. Plus concis que l'affectation complète. A chaque tour de boucle, cette affectation est réalisée. <= pas avec lequel on incrémente à chaque tour de boucle
Tu sais à peu près tout ce qu'il faut savoir sur la boucle for maintenant.
Mais attends, tu m'as dit qu'il existait des déclinaisons des deux types de boucles ?
Lire jusque "Infinite For loop"
Regarder à partir de 1:54
foreach
Une troisième boucle est très utile (et utilisée) en programmation. Il s'agit d'une boucle bornée, mais qui itère sur un conteneur. Je m'explique : dans la boucle for standard que l'on a vue à l'étape précédente, il fallait que tu spécifies une valeur de départ, une condition "tant que" et un pas d'incrémentation. La syntaxe est assez lourde, surtout si tu connais la taille de ton conteneur. Et comme tu peux le voir, ce n'est pas très facile à lire. Il y a une manière plus simple et concise d'itérer sur un ensemble d'éléments, il s'agit de la boucle foreach.
En pseudo code:
Pour chaque élément dans un tableau
Ecrire(élément)
FinPour
La boucle ci-dessus affiche tous les éléments d'un tableau. A chaque itération correspond l'élément suivant dans le conteneur, et la boucle s'arrête lorsqu'elle rencontre la fin du tableau. Plutôt pratique, non ?
Cool, et comment j'écris ça ?
string[] moves = { "jump", "turn around", "turn around", "jump" };
foreach (String moveToDo in moves)
{
Console.WriteLine("I " + moveToDo);
}
Cette boucle est adaptée au cas où tu dois itérer sur un conteneur. Ici, on itère sur un tableau contenant des pas de danse. De plus, pas besoin de "done" à l'intérieur du tableau pour signifier la fin de ton ensemble de mouvements. Par conséquent, la syntaxe de la boucle est beaucoup plus simple et lisible que celle d'une boucle for classique, pour la même opération. Voici l'équivalent du code précédent avec une boucle for classique :
string[] moves = { "jump", "turn around", "turn around", "jump" };
for (int i=0; i < moves.Length; i++)
{
Console.WriteLine("I " + moves[i]);
}
Tu avoueras quand même que la version foreach est un tantinet plus agréable à lire et qu'elle convient bien mieux au cas où l'on veut itérer sur un conteneur.
break & continue
Dans certains cas, il y a des exceptions dans tes suites de pas de danse. Des fois, tu exécutes trois fois une suite de pas, mais à la dernière, tu t'arrêtes à l'avant-dernier pas pour embrayer sur une autre suite de pas. Parfois, tu ne dois pas réaliser un pas de danse si c'est la troisième suite. Deux mots-clés te permettent de contrôler le flux d'exécution d'une boucle pendant son exécution. Il s'agit des deux mots-clés break et continue.
Avant de commencer, j'aimerais que tu réfléchisses quelques minutes à la question suivante. Avec tout ce que tu as appris sur les conditions et les boucles, comment écrirais-tu une boucle infinie ? C'est-à-dire une boucle avec un nombre infini d'itérations ?
while (true) ?
Exactement ! while(true) est une boucle qui s'exécutera à l'infini, car le résultat de l'expression booléenne qui est évaluée en tant que condition de cette boucle sera toujours vrai. Les boucles infinies sont surtout utilisées dans le jeu vidéo, pour créer ce que l'on appelle une boucle de jeu.
Mais il existe un problème. Tu sais comment écrire une boucle infinie, mais sais-tu comment l'arrêter ?
Fermer l'application ? Appuyer sur CTRL-C ?
Oui, ces méthodes marchent, mais parce qu'il y a un événement système qui vient modifier le cours des choses. Et en faisant ça, ton programme s'arrête, tout simplement : il perd son environnement mémoire. Dans certains cas, lorsque l'on sort d'une boucle infinie, on veut réaliser d'autres opérations : détruire des objets, sauvegarder la partie et j'en passe ...
Afin de sortir d'une structure de contrôle itérative, un mot-clé est mis à ta disposition et il s'agit du mot-clé break. Si tu places break à l'intérieur d'une boucle, la boucle s'arrêtera et l'exécution continuera comme si de rien n'était.
Exemple:
while (true)
{
if (ShowIsOver())
{
break;
}
Dance();
}
Le mot-clé continue termine une seule itération, tandis que break termine la boucle tout entière. En clair, continue passe à l'itération suivante sans effectuer les opérations le succédant. Ainsi :
for (int doneMoveSetsCount=0; doneMoveSetsCount < completeDance.Length; doneMoveSetsCount++)
{
string[] moveSet = completeDance[doneMoveSetsCount];
foreach (string move in moveSet)
{
if ((doneMoveSetsCount % 5 == 0) && move == "turn around")
{
Console.WriteLine("I jump");
}
else
{
Console.WriteLine("I " + move);
}
}
}
Attention, ces mots-clés sont très utiles, mais en abuser complexifie énormément un programme. Ces mots-clés doivent être utilisés avec parcimonie et de manière justifiée. Si tu peux éviter de les utiliser, évite. Par contre, si le cas te force ou s'il serait beaucoup trop compliqué de faire différemment, alors tu as le droit d'utiliser un des deux.
Lire la réponse acceptée
Don't repeat yourself !

Il existe, dans le consensus des programmeurs à l’échelle du monde, quelques principes à suivre afin d'écrire du bon code. Les mettre en pratique ne donne pas forcément du code propre, mais y contribue très fortement. Il est important de connaître...les importants.
Un principe de qualité logicielle ultra-important concerne la lisibilité et la maintenabilité du code. Les boucles sont un bon moyen de commencer à le mettre en pratique. Il s'agit du concept DRY pour Don't Repeat Yourself. En effet, il est très mal vu de se répéter inlassablement (copier-coller le même code plusieurs fois à des endroits différents), car cela altère la lisibilité du code, en plus d'impacter les futurs programmeurs qui n'imagineront pas que le même bug est répété plusieurs fois à des endroits différents du code.
Donc, utilise les boucles pour fournir du code lisible et unique. Souviens-toi que copier-coller (du code) est bien souvent une mauvaise pratique qui crée des bugs et de l'incompréhension dans l'équipe. Les boucles sont un allié précieux pour te permettre de commencer à écrire du code propre ! Alors, fais-en bon usage.
Wikipédia
Article
Challenge
Compose ta chorégraphie
Grâce à ce programme, tu vas pouvoir composer tes propres chorégraphies et même t'en souvenir !
-
Crée un tableau
movesde taille 32 -
Une boucle itère en attendant que l'utilisateur rentre un pas de danse de type string. La boucle s'arrête lorsque la taille maximum est atteinte ou que la chaîne de caractères
"done"est spécifiée.- Ajouter dans le tableau
moveschaque pas entré si il est différent de"done"
- Ajouter dans le tableau
-
L'utilisateur choisit ensuite le nombre d'itérations de la suite de pas
-
La suite de pas est répétée autant de fois à l'écran que le nombre d'itérations entré par l'utilisateur
Critères de validation
- Un lien vers ta solution sur GitHub
- La solution itère autant de fois que spécifié par l'utilisateur
- Chaque pas de danse est bien affiché à l'écran à chaque itération