3.1 - do while

Boucle do … while … (Répéter …. Tant que)

Syntaxe

do
   instruction 
while (condition);

boucle1 boucle1

L’instruction à répéter peut être simple (une seule action), structurée (une autre instruction de contrôle) ou composée (c’est le cas le plus fréquent).

Exemples pour illustrer la syntaxe :

int somme = 0;
int n = 1;

/* instruction à répéter est composée */
do {
   somme += n;
   n++;
} while (n <= 10);
int indice = 0;

/* instruction à répéter est simple */
do
   indice++;
while (indice < 5);
int age;

/* instruction à répéter est structurée */
do {
   if (age >= 18)
       printf("C'est un adulte");
   else 
       age += 5;
} while (age < 18);
int age;

/* instruction à répéter est composée */
do {
   printf("age = %d\n", age);

   if (age >= 18)
      printf("C'est un adulte");
   else
      age += 5;
} while (age < 18);

Fonctionnement

Étape 1 : Effectuer (d’abord) l’instruction à répéter.

Étape 2 : Vérifier (après) la condition:

a) Si la condition est vrai, on revient à l’étape 1;

b) Si non (la condition est faux), on quitte la boucle.

Conclusion :

Avec la boucle do ... while, on effectue au moins une fois l’instruction à répéter.

Domaines d’utilisation

On utilise la boucle do ... while quand on ne sait pas à l’avance le nombre de fois que l’on doit répéter le même traitement. Les exemples suivants permettent de voir quelques applications possibles avec cette boucle.

Répéter le même traitement en mode conversationnel

C’est le cas le plus fréquent pour le premier travail pratique en IFT 1810.

Exemple :

Écrire un bloc d’instructions permettant de saisir l’âge et le sexe d’une personne. Ensuite, on affiche un message du genre :

C'est un enfant de sexe masculin.

On répète le même traitement tant que l’usager décide de continuer.

Solution :

int  age;
char sexe,
     reponse; /* Oui ou Non l'usager veut continuer */

do {
   printf("\nEntrez le sexe et l'age ");
   scanf(" %c%d", &sexe, &age);

   printf("C'est un ");

   if (age <= 11)
      printf("enfant ");
   else if (age < 18)
      printf("adolescent ");
   else
      printf("adulte ");

 if (toupper(sexe) == 'F')  /* to upper : en majuscule */
    printf("de sexe feminin\n");
   else
      printf("de sexe masculin\n");

   printf("\nVoulez-vous continuer ? (O/N) ");
   scanf(" %c", &reponse);

} while (toupper(reponse) == 'O');

Exercice :

Écrire un bloc d’instructions permettant de saisir le prix d’un article (un réel). Ensuite, on calcule les taxes TPS et TVQ et on affiche à l’écran les informations du genre :

Prix de l'article  : ....
Taxe TPS           : ....
Taxe TVQ           : ....

Prix total à payer : ....

On répète le même traitement tant que l’usager décide de continuer.

Validation de données

La boucle do ... while permet de valider la valeur que l’usager entre au clavier.

Exemple :

Écrire un bloc d’instructions permettant de saisir et de valider :

  • Le sexe d’une personne (‘f’, ‘F’, ’m’ ou ‘M’);

  • L’âge d’une personne (entre 1 et 134).

Une solution possible :

const int MAXI_AGE = 134;

int  age;
char sexe;

/* saisir et valider le sexe */
do {
   printf("Entrez un caractere parmi f, F, m ou M :");
   scanf(" %c", &sexe);

   if (sexe != 'f' && sexe != 'F' &&
       sexe != 'm' && sexe != 'M')
      printf("Erreur! Retapez S.V.P. \n");
} while (sexe != 'f' && sexe != 'F' &&
         sexe != 'm' && sexe != 'M');

/* saisir et valider l'âge */
do {
   printf("Entrez l'age entre 1 et %d : ", MAXI_AGE);
   scanf("%d", &age);

   if (age < 1 || age > MAXI_AGE)
      printf("Erreur! Retapez S.V.P. \n");
} while (age < 1 || age > MAXI_AGE);

Une solution plus élégante :

const int MAXI_AGE = 134;
int   age, valide; /* Oui ou Non la donnée est valide */

char  sexe;

/* saisir et valider le sexe */
do {
   printf("Entrez un caractere parmi f, F, m ou M :");
   scanf(" %c", &sexe);

   sexe = toupper(sexe);

   valide = (sexe == 'F' || sexe == 'M');

   if (!valide)     /* Si Pas valide  */
      printf("Erreur! Retapez S.V.P. \n");
} while (!valide);  /* tant que non valide */

/* saisir et valider l'âge */
do {
   printf("Entrez l'âge entre 1 et %d : ", MAXI_AGE);
   scanf("%d", &age);

   valide = (age >= 1 && age <= MAXI_AGE);

   if (!valide)
      printf("Erreur! Retapez S.V.P. \n");
} while (!valide);

Calcul scientifique

Exemple 1

Écrire un bloc d’instructions permettant de calculer et d’afficher la somme suivante : somme = 10 + 15 + 20 + 25 + ... + 50

Solution

const int BORNE1 = 10,
          BORNE2 = 50,
          LEPAS  = 5;
int   terme, somme;

somme = 0;
terme = BORNE1;

do {
 somme += terme; /*équivalent à : somme = somme + terme ; */
 terme += LEPAS;
} while (terme <= BORNE2);

printf("La somme calculee est : %d\n", somme);

Exemple 2

Écrire un programme permettant d’estimer la valeur de PI (3.1416…) selon la formule suivante :

pi pi

Solution

#include <stdio.h>

void main()
{
   const int LIMITE = 9999,
             LEPAS  = 2;

   int denominateur = 1; /* premier dénominateur vaut 1 */

   float piSur4 = 0.0, signe = 1.0;

   do {
      piSur4 += signe / denominateur;
      signe = -signe;        /* changer de signe */
      denominateur += LEPAS;
   } while (denominateur <= LIMITE);

   printf("La valeur estimee de PI est %12.6f\n",
                4 * piSur4);
}

Exécution

La valeur estimee de PI est     3.141397

Exercices

Exercice 1

Écrire un programme permettant de saisir et de valider si un entier lu (exemple 7234) est positif ou non. Ensuite, on affiche l’entier tel que lu en plus d’afficher cet entier lu à l’inverse (ici 4327).

Solution :

#include <stdio.h>

int main()
{
   int n;

   /* Saisie et validation */
   do {
      printf("Entrez un entier positif : ");
      scanf("%d", &n);

      if (n < 0)
         printf("n = %d est negatif\n", n);
   } while (n < 0);

   printf("L'entier lu :  %d\n", n);

   printf("A l'envers  :  ");

   do {
      printf("%d", n % 10);
      n /= 10;
   } while (n > 0);

   return 0;
}

Exécution

Entrez un entier positif : –8742
n = -8742 est negatif
Entrez un entier positif : 5329
L'entier lu :  5329
A l'envers  :  9235

Exercice 2

Écrire un programme permettant de saisir un entier positif (exemple 5426). Il calcule l’envers du nombre lu (ici 6245) et affiche ces deux valeurs.

Solution :

#include <stdio.h>

int main()
{
   int n, envers;

   printf("Entrez un entier positif : ");
   scanf("%d", &n);
   printf("L'entier lu :  %d\n", n);

   /* Calcul de l'envers */
   envers = 0;
   do {
      envers = 10 * envers + n % 10;
      n /= 10;
      /* Attention au écriture raccourcie,
       * ici on peut écrire
       *   envers *= 10;
       *   envers += nombre % 10;
       * mais on ne doit pas écrire
       *   envers *= 10 + nombre % 10;
       * qui nous donne pas le même résultat
       */
   } while (n > 0);

   printf("A l'envers  :  %d", envers);

   return 0 ;
}

Exécution

Entrez un entier positif :1234
L'entier lu :  1234
A l'envers  :  4321

Exercice 3

Écrire un programme permettant de saisir les informations d’un placement :

  • Le capital (un réel)

  • Le taux d’intérêt (composé) annuel en %

Le programme calcule et affiche l’évolution du placement, année après année. Lorsque notre épargne vaut un million ou plus, l’exécution du programme s’arrête. Ce programme permet donc d’évaluer combien d’années cela prendra pour devenir millionnaire si l’on adopte un tel plan d’épargne.

/*  Dans combien d'années, deviendra-t'on millionnaire ?
    Matière : boucle do ... while (entre autres)    */

#include <stdio.h>

int main()
{
   const float SEUIL_RICHESSE_VOULU = 1000000.00;
   float depotAnnuel,   /* montant fixe de dépôt annuel */
         taux,          /* taux d'intérêt annuel espéré */ 
         interetAnnuel, /* intérêt annuel à la fin de l'année qui              
                           s’ajoute au capital à la fin de l'année 
                           (intérêt composé) */
         capital;       /* capital accumulé, année après année */
   int   nbAnnee;       /* compteur du nombre d'années */ 

   /* Saisie les données : montant de dépôt et le taux d'intérêt */
   printf("Quel est le montant de depot annuel (exemple 1000.00) ? ");
   scanf("%f", &depotAnnuel);
   printf("Quel est le taux annuel fixe espere (ex. 7.5) ? ");
   scanf("%f", &taux);

/* traitement : */
   if (depotAnnuel >= SEUIL_RICHESSE_VOULU)
      printf("Vous avez atteint ou depasse le seuil %10.2f $\n",SEUIL_RICHESSE_VOULU);
   else {
      /* affichage de l'en-tête pour résumer l'évolution du placement */
      printf("\n\nFONDS XYZ inc.\n");
      printf("Montant de depot annuel : %6.2f $\n", depotAnnuel);
      printf("Taux d'interet annuel (suppose fixe) : %4.2f\n", taux);
      printf("\n\nEvolution du placement :\n\n");
      printf("Annee   Capital (au debut)    Interet annuel",
             "     Capital (a la fin de l'annee)\n");
      nbAnnee = 0;
      capital = 0;

      do {
         /* début d'une année de placement */
         nbAnnee++;

         /* capital accumulé au début de l'année de placement */
         capital += depotAnnuel;
         printf("%3d   %12.2f", nbAnnee, capital);

         /* à la fin de l'année de placement : */
         interetAnnuel = taux / 100.0 * capital;

         /* ajouter l'intérêt au capital pour une autre année */
         capital += interetAnnuel;

         printf("%25.2f  %18.2f\n", interetAnnuel, capital);
      } while (capital < SEUIL_RICHESSE_VOULU);

      printf("\nApres %d annee(s), votre capital sera : %12.2f $\n",
             nbAnnee, capital);
   }

  return 0 ;
}

Exécution

Quel est le montant de depot annuel (exemple 1000.00) ? 1234567
Quel est le taux annuel fixe espere (ex. 7.5) ? 5.00
Vous avez atteint ou depasse le seuil 1000000.00 $
Press any key to continue

Quel est le montant de depot annuel (exemple 1000.00) ? 3000
Quel est le taux annuel fixe espere (ex. 7.5) ? 10.0


FONDS XYZ inc.
Montant de depot annuel : 3000.00 $
Taux d'interet annuel (suppose fixe) : 10.00


Evolution du placement :

Annee   Capital (au debut)    Interet annuel     Capital (a la fin de l'annee)
  1        3000.00                   300.00             3300.00
  2        6300.00                   630.00             6930.00
  3        9930.00                   993.00            10923.00
  etc.
. . . . . . . . 
 35      813073.00                 81307.30           894380.30
 36      897380.31                 89738.03           987118.34
 37      990118.38                 99011.84          1089130.21

Apres 37 annee(s), votre capital sera :   1089130.25 $

Autres exemples

Exemple 1

/* Boucle do ... while

   Application 1 :
     "Répéter le même traitement TANT QUE l'usager décide de continuer "
   Ce programme permet :
         de saisir la taille d'une personne en nombre de pieds et de 
               pouces
         de convertir cette taille en mètre
         d'afficher la taille dans les deux systèmes

   Le programme fonctionne pour plusieurs personnes
   tant que l'usager décide de continuer.
 */

#include <stdio.h>

int main()
{
   const float FACTEUR = 0.3048; /* 1 pied = 0.3048 mètre */
   char reponse; /* Oui ou Non si l'usager veut continuer */

   int nbPieds, nbPouces;
   float taille;

   do { /* Répéter */
      /* Saisie la taille en nombre de pieds et de pouces */
      printf("Entrez la taille en nombre de pieds et de pouces : ");
      scanf("%d%d", &nbPieds, &nbPouces);

      /* Conversion en mètre : */
      taille = (nbPieds + nbPouces / 12.0) * FACTEUR;

      /* Affichage : */
      printf("La taille de la personne :\n");
      printf("  %d pied(s) et %d pouce(s)\n", nbPieds, nbPouces);
      printf("  %4.2f metre\n", taille);

      /* Demander si l'usager veut continuer */
      printf("\nVoulez-vous continuer ? (o/n) ");
      scanf(" %c", &reponse); 

   } while (reponse == 'o' || reponse == 'O'); 
   return 0;
}

Exécution

Entrez la taille en nombre de pieds et de pouces : 5 6
La taille de la personne :
  5 pied(s) et 6 pouce(s)
  1.68 metre

Voulez-vous continuer ? (o/n) o
Entrez la taille en nombre de pieds et de pouces : 6 2
La taille de la personne :
  6 pied(s) et 2 pouce(s)
  1.88 metre

Voulez-vous continuer ? (o/n) o
Entrez la taille en nombre de pieds et de pouces : 4 9
La taille de la personne :
  4 pied(s) et 9 pouce(s)
  1.45 metre

Voulez-vous continuer ? (o/n) n

Exemple 2

/* Fichier dowhile2.c
   Deuxième application de la boucle do ... while

   Répéter
      saisir une donnée
      Si la donnée est invalide
         afficher un message pertinent
   Tant que (la donnée est invalide)
   
   Ce programme permet :
     1. de saisir et VALIDER un poste de travail parmi les 4 postes
     2. de saisir et VALIDER l'ancienneté entre 2 bornes
     3. d'afficher un message approprié
 */

#include <stdio.h>
#include <ctype.h>

int main()
{
   const int MIN_ANC = 1,
             MAX_ANC = 25;

   char poste;       /* parmi : A, P, O et S analyste, programmeur,
                        opérateur, secrétaire */
   int  anciennete;  /* nb. d'années d'ancienneté */
   int  valide;      /* Oui ou Non l'ancienneté est valide */

   /* Saisir et valider le poste de travail : */
   do {
      printf("Entrez un caractere representant le poste de travail : ");
     scanf(" %c", &poste); 

      poste = toupper(poste);

      if (poste != 'A' && poste != 'P' && poste != 'O' && poste != 'S')
         printf("Poste invalide, retapez S.V.P.\n\n");

   } while (poste != 'A' && poste != 'P' && poste != 'O' && poste != 'S');

   /* Saisir et valider l'ancienneté, entre 1 et 25 ans */
   do {
      printf("Entrez l'anciennete entre %d et %d : ", MIN_ANC, MAX_ANC);
      scanf("%d", &anciennete);

      /* un bon style de validation : à comprendre */
      valide = anciennete >= MIN_ANC && anciennete <= MAX_ANC;

      if (!valide)
         printf("L'anciennete est en dehors de l'intervalle\n\n");
   } while (!valide);

   printf("\nLe poste saisi : %c, l'anciennete lue : %d\n",
                                          poste, anciennete);

   /* affichage utilisant le if imbriqué :  
        à titre d'exercice : faire une solution avec switch    */

   printf("Cet employe occupe le poste ");

   if (poste == 'A')
      printf("d'analyste");
   else if (poste == 'P')
      printf("de programmeur");
   else if (poste == 'O')
      printf("d'operateur");
   else 
      printf("de secretaire");

   printf("\n\nL'employe a %d annee(s) d'anciennetee\n\n", anciennete);

   return 0 ;
}

Exécution

Entrez un caractere representant le poste de travail : v
Poste invalide, retapez S.V.P.

Entrez un caractere representant le poste de travail : a
Entrez l'anciennete entre 1 et 25: 89
L'anciennete est en dehors de l'intervalle

Entrez l'anciennete entre 1 et 25: -5
L'anciennete est en dehors de l'intervalle

Entrez l'anciennete entre 1 et 25: 12

Le poste saisi : A, l'anciennete lue : 12
Cet employe occupe le poste d'analyste

L'employe a 12 annee(s) d'anciennete

Exemple 3

/* Fichier dowhile3.c
   Troisième application de la boucle do ... while
   Faire certains calculs
   Ce programme permet :
     1. de calculer et d'afficher la somme = 1 + 2 + ... + 100
     2. de comparer avec la formule : 1 + 2 + ... + n = n x (n+1) / 2
     3. d'utiliser certaines écritures raccourcies pour obtenir la même somme
 */
#include <stdio.h>

int main()
{
   const int LIMITE = 100;  /* calcul de 1 + 2 + 3 + ... + 100 */
   int somme = 0,           /* on initialise souvent une somme par 0 */
       valeur = 1;          /* première valeur à ajouter dans la somme */
   /* avec do ... while */
   do {
      somme = somme + valeur;
      valeur = valeur + 1;
   } while (valeur <= LIMITE);

   printf("La somme 1 + 2 + ... + %d = %d (avec do ... while)\n", LIMITE, somme);
   printf("\nLa meme somme avec la formule :\n");
   printf(" 1 + 2 + ... + n = n x (n+1) / 2        : ");
   printf("%d\n", LIMITE * (LIMITE+1) / 2 );
   printf("\nLa meme somme avec l'ecriture raccourcie : ");

   somme = 0;
   valeur = 1;
   do {
      somme += valeur;  /*  <==> somme = somme + valeur ; */
      valeur++;         /*  dans ce contexte :
                            valeur = valeur + 1;
                         ou valeur += 1;
                         ou valeur++; */
   } while (valeur <= LIMITE);
   printf("%d (meme valeur)\n", somme);

   return 0 ;

}

Exécution

La somme 1 + 2 + ... + 100 = 5050 (avec do ... while)

La meme somme avec la formule :
 1 + 2 + ... + n = n x (n+1) / 2        : 5050

La meme somme avec l'ecriture raccourcie : 5050 (meme valeur)

Exemple 4

/* Un autre exemple de do ... while
   Jeu de "devin" :
   L'ordinateur fournit un nombre aléatoire entre 1 et 1000.
   L'usager du jeu a le droit à un maximum de 10 essais pour deviner
   ce nombre caché.
   On le guide dans le processus de la devinette en lui donnant des
   messages pertinents.
 */

#include <stdio.h>
#include <stdlib.h>  /* pour la fonction srand : rendre les valeurs plus
                        aléatoirement possible si le paramètre n'est pas
                        une constante. Dans l'exemple, on prend le temps
                        courant comme paramètre */
#include <time.h>    /* pour le temps courant */
#include <ctype.h>   /* pour la fonction de conversion en majuscule */

int main()
{
   const int BORNE = 1000,  /* valeur cachée (à deviner) entre 1 et BORNE */
             MAX_ESSAIS = 10;  /* nombre maximum d'essais */

   int aDeviner,  /* le nombre caché fourni par l'ordinateur à deviner */
       nombre,    /* le nombre fourni par l'usager du jeu */
       nbEssai,   /* compteur du nombre d'essais */
       trouve;    /* Oui ou Non on trouve le nombre caché */
   char reponse;  /* Oui ou Non l'usager veut continuer */

   srand(time(NULL));

 
   do {
      /* rand() retourne un nombre aléatoire >= 0
      rand() % BORNE donne un nombre aléatoire entre 0 et 999
      rand % BORNE + 1  donne un nombre aléatoire entre 1 et 1000 */
      
      aDeviner =  rand() % BORNE + 1 ;

      printf("On a un nombre cache entre 1 et %d, vous avez "
             "le droit à un maximum %d essais\n", BORNE, MAX_ESSAIS);
      printf("On y va!\n");

      nbEssai = 0;

      do {
         /* saisir le nombre deviné par l'usager */
         nbEssai++;
         printf("Essai # %2d : quel est le nombre ? ", nbEssai);
         scanf("%d", &nombre);

         /* quand le nombre deviné est égal au nombre caché, on a trouvé */
         trouve = nombre == aDeviner;

         if (trouve)
            printf("Bravo, vous avez trouve le nombre cache %d apres %d essai(s)\n",
                   aDeviner, nbEssai);
         else if (nombre < aDeviner)
            printf("%d est inferieur au nombre cache\n", nombre);
         else
            printf("%d est superieur au nombre cache\n", nombre);
      } while (!trouve && nbEssai < MAX_ESSAIS);

      /* après avoir fait 10 essais et non trouvé */
      if (!trouve){
         printf("\nLe nombre cache est : %d\n", aDeviner);
         printf("Bonne chance a la prochaine fois\n");
      }

      printf("\n\nVoulez-vous jouer encore ? (o/n) ");
      scanf(" %c", &reponse);

   } while (toupper(reponse) == 'O');

  return 0 ;

}

Exécution

On a un nombre cache entre 1 et 1000, vous avez le droit à un maximum de 10 essais
On y va!
Essai #  1 : quel est le nombre ? 600
600 est superieur au nombre cache
Essai #  2 : quel est le nombre ? 500
500 est superieur au nombre cache
Essai #  3 : quel est le nombre ? 400
400 est superieur au nombre cache
Essai #  4 : quel est le nombre ? 300
300 est superieur au nombre cache
Essai #  5 : quel est le nombre ? 200
200 est inferieur au nombre cache
Essai #  6 : quel est le nombre ? 210
210 est inferieur au nombre cache
Essai #  7 : quel est le nombre ? 220
220 est inferieur au nombre cache
Essai #  8 : quel est le nombre ? 240
240 est inferieur au nombre cache
Essai #  9 : quel est le nombre ? 260
260 est superieur au nombre cache
Essai # 10 : quel est le nombre ? 250
250 est superieur au nombre cache

Le nombre cache est : 241
Bonne chance a la prochaine fois

Voulez-vous jouer encore ? (o/n) o
On a un nombre cache entre 1 et 1000, vous avez le droit à un maximum 10 essais
On y va!
Essai #  1 : quel est le nombre ? 500
500 est superieur au nombre cache
Essai #  2 : quel est le nombre ? 250
250 est inferieur au nombre cache
Essai #  3 : quel est le nombre ? 350
350 est inferieur au nombre cache
Essai #  4 : quel est le nombre ? 425
425 est superieur au nombre cache
Essai #  5 : quel est le nombre ? 370
370 est inferieur au nombre cache
Essai #  6 : quel est le nombre ? 400
400 est superieur au nombre cache
Essai #  7 : quel est le nombre ? 385
385 est inferieur au nombre cache
Essai #  8 : quel est le nombre ? 390
390 est superieur au nombre cache
Essai #  9 : quel est le nombre ? 387
Bravo, vous avez trouve le nombre cache 387 apres 9 essai(s)


Voulez-vous jouer encore ? (o/n) n

Simulation

Exemple 1

Soient j et k, deux variables déclarées de type int. Quelle est la valeur affichée à l’écran par le segment de programme suivant?

int k = 1, j = 10;

do {
   if (k >= 3)
      j++;
   else
      j--;
      k++;
      printf("%3d%3d\n", j, k);
   } while (j <10);

   printf("%5d\n", j * k);
   printf("FIN");

Solution :

On utilise le symbole ^ pour représenter une espace

  j    |     k    | Affichage à l'écran
  -------------------------------------
 10    |     1    |
  9    |     2    | ^^9^^2
  8    |     3    | ^^8^^3
  9    |     4    | ^^9^^4
 10    |     5    | ^10^^5
       |          | ^^^50
       |          | FIN

Exercice

Soient n et s, deux variables déclarées de type int. Quelle est la valeur affichée à l’écran par la section de programme suivant?

int s = 0, n = 572;
do {
   s = s + n % 10;
   printf("%3d %3d\n", s, n);
   n /= 10;
} while (n > 0);

printf("Fin");