Aller au menu - Aller au contenu

Icône Les boucles

Par Avatar Yno
Mise à jour : 09/07/2010
Difficulté : Facile Facile
170 visites depuis 7 jours, dont 2 sur ce chapitre classé 446/786
Il est fréquent de vouloir répéter un code. Par exemple, nous pourrions demander son âge à l'utilisateur (comme nous savons déjà le faire), et nous assurer que celui-ci rentre un âge valide. Pour cela, nous vérifions une condition (ça aussi nous savons le faire) sur cet âge, et, si elle n'est pas vérifiée, nous recommençons.

Ce genre de répétition d'instructions pourrait se faire en dupliquant le code ; mais cela serait bien peu pratique, car comment faire, si l'utilisateur se trompe à nouveau, pour prévoir de répéter le code une nouvelle fois ? La solution réside donc en une nouvelle construction du langage : les boucles de code.

Si Vala n'est pas vote premier langage de programmation, vous n'allez sans doute pas apprendre grand-chose de nouveau ici. À vous de voir si vous sautez le chapitre, ou si vous préférez réviser un peu ;) .
Sommaire du chapitre :
Icône du chapitre
Chapitre précédent Sommaire Chapitre suivant

Boucles conditionnelles

Comme le titre de cette section le laisse supposer, nous allons d'abord nous intéresser à des boucles qui répètent un ensemble d'instructions tant qu'une certaine condition est vérifiée. Il y a deux boucles très semblables pour jouer ce rôle en Vala : while et do...while . Si vous connaissez un langage semblable au C qui dispose aussi de ces boucles, vous ne serez pas dépaysé.

Si vous êtes débutant, voici le principe : ces mots clefs sont suivies d'une condition et d'un bloc de code. Tant que la condition est évaluée comme vraie, le bloc de code est exécuté, c'est à dire que les lignes qui le composent sont exécutées les unes après les autres, et qu'à la fin de ce bloc on évalue à nouveau la condition. Si elle vaut encore vrai, on repart au début :) . Cela donne à peu près ceci pour while (nous verrons l'autre dans un instant) :

Code : Vala
1
2
3
4
5
6
while (condition) 
{
        Instruction 1;
        Instruction 2;
        etc.
}


Les conditions de ces boucles ne sont pas différentes de celles que nous avons déjà rencontrées dans le chapitre sur les tests conditionnels. Ce sont des formules logiques comme les autres. Attention, donc, à ne pas écrire de conditions qui ne changeront jamais de valeur, car la boucle correspondante serait alors exécutée jusqu'à ce que vous interrompiez le programme (avec ctrl-c, le gestionnaire des tâches (ctrl-alt-suppr) sous Windows ou la commande kill sous un Unixoïde).

Nous allons donc appliquer ce que nous avons appris sur les chaînes pour par exemple lire l'âge de l'utilisateur en nous assurant qu'il écrit bien quelque chose de valable. Par "valable", nous voulons dire au dessus de 7 ans. Pour cela, nous utilisons deux variables : une de type string , qui sert à lire l'entrée, et une de type int , qui représente l'âge de l'utilisateur. Cela n'est autre que la chaîne précédente, convertie à l'aide de la méthode to_int.

Quelle est la condition de la boucle ? Nous utilisons une boucle tant que, donc nous voulons une condition qui ressemble à "tant que age est strictement inférieur à 7". Hé bien, il nous suffit de l'écrire ainsi. Voici le programme :

Code : Vala
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class Main
{
  public static int main (string[] args)
  {
    string entree = "";
    int age = 0;
    
    while (age < 7) 
    {
        stdout.printf("Veuillez rentrer un âge valable s'il vous plaît : ");
        entree = stdin.read_line();
        age = entree.to_int();
    }
    
    return 0;
  }
}


Notez que nous avons initialisé la variable age à 0, afin de rentrer dans la boucle au moins une fois. En effet, si nous avions initialisé cette variable à 8, dès le début la condition de la boucle n'aurait pas été respectée, et rien n'aurait été exécuté.

Profitons-en pour présenter l'autre boucle conditionnelle, do...while, qui exécute au moins une fois son bloc de code. Elle n'a pas vraiment la même forme que while :

Code : Vala
1
2
3
4
5
6
do
{
    stdout.printf("Veuillez rentrer un âge valable s'il vous plaît : ");
    entree = stdin.read_line();
    age = entree.to_int();
} while (age < 7);


En réalité, la différence entre les deux boucles est que while teste la condition au début d'un tour de boucle, alors que do...while la teste à la fin. Ceci explique qu'elle soit exécutée au moins une fois ! Attention au point virgule final dans le cas de do...while.

Boucles avec compteurs

Il existe un autre type de boucle en Vala, qui permet de maintenir un (ou même plusieurs) compteurs qui est mis à jour à chaque tour, et qui permet donc d'effectuer un nombre de tours prévisible. C'est un peu vague, alors passons directement à la pratique :

Code : Vala
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public class Main
{
  public static int main (string[] args)
  {
    
    int i; // On appelle souvent 'i' ou 'j' les compteurs...
             // Mais ça n'a bien sûr rien d'obligatoire.
    
    for (i = 0; i < 10; i = i + 1)
    {
        stdout.printf("i = %d \n", i);
    }
    
    stdout.printf("Fin de la boucle, i vaut %d !\n", i);
    
    return 0;
  }
}


Exécutez ce code. Comme vous pouvez le voir, la boucle est exécutée 10 fois, et s'arrête quand i vaut 10. La partie "conditionnelle" de la boucle for ressemble un peu à ce que nous connaissons. Elle contient trois sous-parties, séparées par des ";".

  • La première, i = 0 , est appelée initialisation. Elle est exécutée une seule fois, au début de la boucle, pour initialiser les compteurs (ici, donner à la valeur 0 à i).
  • La deuxième, i < 10 , est une condition comme nous les connaissons déjà ! Dès qu'elle n'est plus respectée, la boucle se termine.
  • La troisième, i = i + 1 , est une instruction effectuée à chaque tour de boucle : ici, on met à jour le compteur de boucle pour pouvoir avancer. Si nous avions omis cette instruction, la boucle aurait été répétée inlassablement, car i n'aurait jamais atteint la valeur de 10 !


Si vous avez fait du C, vous avez du voir que l'on écrivait souvent i++ au lieu de i = i + 1 . C'est toujours valable en Vala, et nous utiliserons parfois cette notation. De même, i = i - 1 peut s'écrire i--.


Comme vous pouvez le voir, les boucles for ne sont pas tellement plus géniales que les boucles while ... elles permettent de faire la même chose, mais toutefois il est conseillé de savoir les utiliser : en écrivant une boucle for dans votre code, vous donnez plus d'informations dans votre code, car vous dites "cette boucle-ci maintient un compteur", c'est une information mise en évidence.

C'est important pour deux raisons : premièrement, vous donnez plus d'informations à un lecteur éventuel. Dans le cas d'un projet collaboratif ou open source, c'est donc profitable. Et ça l'est aussi pour vous, d'ailleurs, si vous relisez votre code quelques mois après ! L'autre raison est que, au moment où vous écrivez votre programme, vous avez moins de chances de vous tromper qu'en écrivant une boucle while , où vous auriez pu oublier de mettre à jour le compteur (et provoquer une boucle infinie)...

    Exercices :
  • Ecrivez un programme qui compte de 10 à 0 en décroissant, et qui affiche à chaque fois 10... 9... et ainsi de suite. À la fin de la boucle, faites-lui afficher la ligne "Décollage !".
  • Réécrivez l'exemple donné plus haut avec une boucle while plutôt qu'une boucle for.
  • Ecrivez un programme qui compte de 1 à 50 en écrivant la valeur de son compteur i tout le temps, sauf quand i est divisible par 3 où il écrira "Fizz", et quand i est divisible par 5 où il écrira "Buzz". Quand i sera divisible par 3 et par 5 (par exemple à 15), le programme écrira FizzBuzz. Si vous débutez totalement la programmation, ce programme va vous demander un peu de réflexion !


Correction du troisième exercice :
Secret (cliquez pour afficher)
Ce programme n'est pas extrêmement compliqué, mais il fait intervenir beaucoup de notions qui peuvent être encore nouvelles pour vous. Il est évident que nous allons utiliser une boucle pour maintenir le compteur, et nous allons utiliser des tests conditionnels pour tester la divisibilité du compteur. Rappelez-vous que pour vérifier que i est divisible par 3, nous écrivons if (i % 3 == 0) .

Il y a deux points qui méritent réflexion : d'une part, nous voulons que notre programme soit assez souple pour écrire "FizzBuzz" quand le compteur est divisible par 3 et par 5. Nous comprenons donc que le retour à la ligne doit être fait indépendamment de l'écriture de "Fizz", et nous allons même le faire indépendamment de "Buzz" ou de l'écriture du compteur.

D'autre part, quand nous écrivons "Fizz", "Buzz", ou "FizzBuzz", nous n'écrivons pas la valeur du compteur. Cela demande donc une variable supplémentaire servant à vérifier si, pendant un tour de la boucle, nous avons déjà écrit l'un de ces mots ou pas. Nous l'appelerons t. Voici le code :

Code : Vala
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Main
{
  public static int main (string[] args)
  {
    
    int i = 0; 
    bool t;
    
    for (i = 1; i <= 50; i++)
    {
        t = false; // Pour l'instant, rien n'a été écrit
        if (i % 3 == 0) 
        {
            stdout.puts("Fizz");
            t = true; // On a écrit quelque chose
        }
        if (i % 5 == 0)
        {
            stdout.puts("Buzz");
            t = true; // On a écrit quelque chose
        }
        if (!t) // Si rien n'a été écrit...
        {
            stdout.printf("%d", i);
        }
        
        stdout.puts("\n"); // On saute une ligne indépendamment de ce qui a été écrit
    }
    
    return 0;
  }
}

Deux mot-clefs de contrôle

Les mots break et continue


Il y a encore deux mot-clefs que nous devons étudier pour bien connaître les boucles en Vala. Ils servent à contrôler le déroulement d'une boucle, en interrompant immédiatement son déroulement ou en la faisant repartir au début du bloc d'instructions pour le tour de boucle suivant (sans finir d'exécuter le bloc). Le premier mot-clef est break , que nous avons déjà rencontré en utilisant switch . Le second est continue .

Il n'y a rien de compliqué à comprendre. Testez donc le programme suivant :

Code : Vala
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
int i; 

for (i = 1; i <= 5; i++)
{
    if (i == 3)
        break;
    stdout.printf("%d \n", i);
}

stdout.printf("Après la boucle, i = %d.\n", i);


Voici le résultat obtenu :

Code : Console
1 
2 
Après la boucle, i = 3.


Que se passe-t-il si nous remplaçons le break par un continue ? Arrivé à 3, la boucle va simplement "sauter" la fin de cette étape et passer à la suite. On obtient alors la sortie

Code : Console
1 
2 
4 
5 
Après la boucle, i = 6.


Pas d'étape 3 ;) .

Quand les utiliser ?



Vous l'aurez deviné, les exemples précédents ne sont que des démonstrations de break et continue. Dans le prochain chapitre, nous verrons des exemples pertinents d'utilisation.

Pour l'instant, remarquez une chose : quand nous utilisons une boucle sans ces mots, nous savons où elle se termine, et même si parfois il est difficile de prévoir combien de tours de boucle seront réalisés, au moins on sait que tous seront exécutés en entier. Avec continue et surtout break, vous cassez ce sens.

Dans certains cas, ces mots correspondent exactement au comportement que l'on peut attendre, et leur présence est donc facile à comprendre. Dans d'autres cas, ils complexifient grandement la compréhension du code, et peuvent même, si vous êtes trop distraits, vous faire écrire du code bugué (qui ne se comporte pas comme prévu) sans que vous compreniez bien pourquoi. Méfiance ;) !
Chapitre précédent Sommaire Chapitre suivant

Partager

3 commentaires pour "Les boucles"
Note moyenne : 3.63 / 4 (35 votes)
Pseudo Commentaire
Hors ligne Trademark # Posté le 24/06/2010 à 12:33:45
Avatar

Salut et bravo pour ce tutoriel, continue comme ça. Enfin comme ça sauf pour un point où j'ai cru avoir une crise cardiaque :D

Code : Autre
1
2
3
4
5
6
7
8
9
10
int i = 0; 

for (i = 1; i <= 5; i++)
{
    if (i == 3)
        break;
    stdout.printf("%d \n", i);
}

stdout.printf("Après la boucle, i = %d.\n", i);


Même si ce code a pour but de faire comprendre la différence entre un break et un continue je trouve qu'il est pas très intelligent. Vu que ce sera majoritairement des débutants qui liront ce tutoriel tu devrais leur faire prendre des bonnes habitudes :

1) Initialisation de i à 0 et puis de i à 1 juste après dans le for o_O
2) Et surtout on évite le plus possible de forcer l'arrêt d'une boucle avec un if et un break, ca n'a aucun interêt ici.

Fait attention dans tes exemples, essaye d'en trouver des plus pertinents et ton tutoriel ne s'en portera que mieux ;)

Bonne chance, bye bye
Hors ligne bluestorm # Posté le 25/06/2010 à 11:02:14
dont ask to ask
Avatar
Groupe : Anciens
Flux RSS

L'idée de dire aux gens "testez vous-mêmes et vous verrez bien le résultat" pour comprendre break et continue est audacieuse, et à mon avis un peu téméraire.

C'est bien de pousser les gens à être actifs pendant la lecture, mais une grande partie ne le sera pas (ou ne le pourra pas : lecture des documents imprimés dans le bus, etc.). Il me semble un peu dommage de pénaliser ces lecteurs.

Je pense qu'il vaudrait mieux mettre une explication claire après cette partie de devinette, pourquoi pas en [secret] pour essayer de forcer un peu les gens quand-même. De plus, contrairement à ce que dit le tutoriel, le comportement de break/continue n'est pas si "évident" que ça, et comme le soulève Trademark il pourrait être intéressant de mentionner les bonnes/mauvaises pratiques liées à ces constructions (éventuellement, ça pourrait faire l'objet d'un tutoriel à part, indépendant du langage).
 
Hors ligne anonyme # Posté le 25/06/2010 à 14:23:45

En fait il manque surtout des exercices (et leurs corrections) à ce chapitre. L'exemple n'est en effet pas irréprochable, mais il illustre très bien la différence entre break et continue. Cependant, il est vrai que chacun ne pourra pas nécessairement tester pendant sa lecture, j'en tiendrai compte.

Voir tous les commentaires