Les boucles : jusqu'au stop !

boucle2.cpp


Vous souvenez-vous de notre problème de la semaine dernière : nous voulions faire une saisie contrôlée d'un entier compris entre 0 et 99 ? Je vous avais suggéré de le faire grâce à une boucle for dans laquelle il n'y avait qu'une condition de continuation (pas d'initialisation ou d'incrémentation). Si vous y avez un peu réfléchi, vous avez du vous rendre compte qu'il est un peu inutile de faire une boucle for, qui nécessite à priori de savoir combien de tours on va faire, alors qu'on ne sait pas du tout combien de tours sont prévus.

Il existe deux boucles en C/C++ qui permettent de recommencer des instructions tant qu'une condition est remplie : while et do...while. Les deux sont très similaires, mais leur principale différence est subtile et importante. Les voici, dans l'ordre d'apparition :

While

La boucle while est l'équivalent de l'algorithme suivant :

Comme pour la boucle for, la condition est testée avant chaque entrée dans la boucle. Si la condition est fausse, la boucle n'est pas exécutée, et le programme continue juste après la boucle. On dit qu'une boucle est prétestée lorsque le test s'effectue avant le corps de la boucle. La boucle while est donc une boucle prétestée.

Voici un exemple :

int nombre = 14453;

cout << nombre << " à l'envers s'écrit ";

while(nombre)
{

    cout << (nombre % 10);
    nombre /= 10;

}

cout << ". Rigolo, non?";

Ce petit programme est intéressant. Je vous rappelle que 153%10 = 3 et que 153/10 = 15. Partant de ces deux propriétés, nous pouvons expliquer le fonctionnement du programme :

Et hop! En trois coups de cuiller à pot, on vient d'inverser les chiffres d'un nombre. Facile, non? Voici donc l'affichage produit :

14453 à l'envers s'écrit 35441. Rigolo, non?

Comme pour la boucle for, la boucle while peut être contrôlée à l'aide des instructions break et continue.

Do...while

La boucle do...while est légèrement différente de la boucle while : elle est posttestée, c'est-à-dire qu'elle effectue son test de continuation à la fin de la boucle. Ceci implique que, contrairement à la boucle while, on est sûr d'entrer au moins une fois dedans. Voici l'algorithme correspondant :

Elle semble parfaitement adaptée à la saisie contrôlée dont nous parlions au début du cours :

int proposition = 0;

do
{

    cout << "Entrez votre proposition (0-99): ";
    cin >> proposition;

} while((proposition < 0) || (proposition > 99));

    Notez bien le point-virgule (;)qui termine l'instruction do...while!!!

Si une mauvaise valeur est entrée, on recommence tout simplement la saisie, sinon on continue.

Les instructions break et continue s'appliquent également à cette boucle.

Le programme du jour

Vous rappelez-vous des nombres premiers ? Les nombres premiers sont ceux qui n'admettent pas d'autres diviseurs que 1 et eux-même (rappelons aussi que 1 n'est pas un nombre premier). Un moyen de savoir alors si un nombre est premier est de tenter de le diviser par tous les autres nombres avant lui.  Voici donc le programme en question :

1

2
3

4
5
6

7
8
9

10
11

12
13

14

15
16

17
18

19

20

21

22

#include <iostream.h>

main()
{

    int nombre = 0;
    int n = 0;
    int diviseur = 0;

    cout << "--- Calcul de nombres premiers ---\n";
    cout << "Combien souhaitez vous en calculer: ";
    cin >> nombre;

    do
    {

      n++;
      for(diviseur = 2; diviseur < n; diviseur++)

        if(!(n%diviseur)) break;

      if(diviseur == n)
      {

        nombre--;
        cout << "Trouvé : " << n << endl;

      }

    } while(nombre);

    cout << "Fini!\n";

}

J'ai mixé un peu les boucles pour vous montrer que les boucles travaillent bien ensemble. Expliquons un peu les variables : nombre représente le nombre de premiers à trouver. On le décrémente à chaque fois qu'on en trouve un, donc quand il vaut zéro, c'est qu'on les a tous trouvé. n, c'est le nombre a tester. n est incrémenté de 1 à chaque fois, et on lui cherche à nouveau des diviseurs. diviseur, c'est le nombre par lequel on tente de diviser n pour voir s'il division il y a.

Voici les points importants :

  • La boucle while est prétestée : on n'est pas sûr de rentrer dedans.
  • La boucle do...while est posttestée : on est sûr de rentrer dedans au moins une fois
  • Les boucles while et do...while peuvent être contrôlées par break et continue de la même façon que les boucles for.

  • Essayez de simuler une boucle for avec une boucle while.
  • Pour les mathématiciens, doit-on vraiment tenter de diviser n par toutes les valeurs de 2 à n-1 ? Ne peut-on pas s'arrêter avant, de manière sûre?
  • Que se passe-t-il si vous utilisez while(1) ?
  • Aucun nombre pair supérieur à 2 ne peut être premier. Pouvez-vous éliminer des calculs grâce à cette propriété ?
  • Le premier programme d'aujourd'hui affiche les chiffres d'un nombre dans l'ordre inverse. Au lieu de les afficher un par un, pourriez-vous construire un deuxième int dont les chiffres soient inversés par rapport au premier, et l'afficher à la fin du programme ?
  • Un nombre entier étant donné, pourriez-vous faire un programme qui affiche la liste des nombres par lequel il est divisible ? Exemple : 6 est divisible par 1, 2, 3 et 6.
  • On dit qu'un nombre est parfait s'il est égal à la somme de ses diviseurs autres que lui-même. Exemple : 6 est parfait, car 6 = 1 + 2 + 3. Pourriez-vous, à l'aide d'un programme, trouver les trois premiers nombres parfaits (sur le même modèle que le programme du jour) ?

Voilà, vous avez de quoi vous amuser pour un petit moment. Si vous n'avez pas l'habitude de faire ces exercices (après tout, vous n'y êtes pas obligés), je conseille tout de même vivement de faire ceux que je vous proposent aujourd'hui. En effet, c'est le genre de calculs qu'on se retrouve constamment en train de faire dans des programmes, et il serait dommage que vous perdiez un temps fou à trouver comment faire l'un de ses calculs, alors que vous pourriez le faire en 30 secondes si vous étiez un peu à l'aise avec les boucles. Les boucles ne sont pas évidentes à comprendre au premier abord, surtout dans un cours comme celui-ci, alors il est important de bien prendre le temps de revenir dessus de temps à autre.

La semaine prochaine, nous allons voir les méthodes (ou fonctions), qui sont le dernier ingrédient important d'un programme digne de ce nom. C'est une nouvelle approche de la programmation, et une fois que nous les aurons vues, nous ne pourrons plus nous en passer. Alors accrochez votre ceinture, dépoussierez vos lunettes, et c'est parti !!!


Voir aussi : Les boucles : de 1 à 10