Vous êtes sur la page 1sur 23

Chapitre 8

Autres boucles

À ce point, nous maîtrisons un certain nombre de concepts et d’outils nous permettant de déve-
lopper un grand nombre d’algorithmes. Ces notions ont été abordées séquentiellement et de façon
séparées mais elles ont vocation à être utilisées de façon conjointes pour permettre l’élaboration
de la diversité des algorithmes que nous souhaiterons développer.
Lors de cette séance, nous procéderons à la révision des notions qui doivent être acquises à ce
stade. Les exercices utiliseront toutes les notions déjà vues, à savoir :
– séquentialité, affectation, typage,
– expressions booléennes, alternatives,
– boucles,
– fonctions,
– tableaux à une dimension.
Les différentes structures de contrôle pourront être imbriquées même si nous veillerons à ne pas
abuser de l’imbrications. Au-delà de 2 ou 3 niveaux d’imbrication il sera toujours préférable de
définir une fonction intermédiaire pour simplifier le développement, l’utilisation et le test de l’al-
gorithme.
Mais avant de rentrer dans le vif du sujet, nous souhaitons introduire quelques nouvelles notions.

8.1 De nouvelles boucles


8.1.1 La boucle Tant que (Rappel)
Cette première boucle, aussi appelée boucle while, a fait l’objet d’un chapitre entier. Nous ne
rappellerons ici que les principes généraux de son fonctionnement.
� �
La syntaxe d’utilisation de la boucle while est la suivante :
1 while ( cond )
2 {
3 instruction B1;
4 instruction B2;
5 ...
6 }

� �
7 instruction Mi ;

On rappelle son fonctionnement séquentiel :


1. on teste la condition cond (ligne 1),
(a) si la condition est vérifiée on exécute le corps de la boucle (instruction ligne 3 et suivantes
jusqu’à la fin des instructions du corps), puis on revient à la ligne 1.
(b) si la condition n’est pas vérifiée, on n’exécute pas le corps de la boucle et on passe à la
suite (ligne 7)
La condition cond est donc une condition d’entrée et de maintien dans la boucle.

141
IUT de Villetaneuse

8.1.2 La boucle Répéter ... Tant que ...


Cette seconde boucle, aussi appelée boucle do-while, est assez similaire à la bouche while. Sa
� �
syntaxe d’utilisation est la suivante :
1 do
2 {
3 instruction B1 ;
4 instruction B2 ;
5 ...
6 }
7 while ( cond ) ;

� �
8 instruction Mi ;

Son fonctionnement séquentiel est le suivant :


1. on exécute les instructions du corps de la boucle (ligne 3 et suivantes), puis arrivé à la fin
du corps de la boucle,
2. on évalue la condition cond
(a) si la condition est vérifiée on revient à la ligne 3. (on boucle).
(b) si la condition n’est pas vérifiée, on n’exécute pas le corps de la boucle et on passe à la
suite (ligne 7)
À la différence de la boucle while, la condition cond de maintien dans la boucle est évaluée après
l’exécution du corps de la boucle. En conséquence le corps de la boucle est toujours exécuté au
moins une fois. À la différence de la condition de la boucle while qui était une condition d’entrée
et de maintien dans la boucle, celle de la boucle do-while est une condition de maintien.

8.1.3 La boucle Pour ...


Cette troisième boucle, aussi appelée boucle for, est sensiblement différente des deux précé-
dentes. Elle permet toujours de répéter l’exécution d’un bloc d’instructions, cette répétition est
toujours soumise à l’évaluation d’une condition, cependant, cette condition porte toujours sur la
valeur d’un itérateur numérique, alors que pour les autres boucles, la condition peut porter sur
n’importe quel type de valeur ou expression booléenne (combinaison logique de plusieurs condi-
tions).
Dans la pratique, la boucle for est utilisée lorsque l’on souhaite répéter un bloc d’instructions
un nombre de fois connu à l’avance (avant d’entrer dans la boucle). Par exemple, pour parcourir
les cases d’un tableau dont on connait la longueur. On utilise pour cela un itérateur numérique
entier que l’on initialise et que l’on fait varier par incrémentation jusqu’à une valeur limite. Voici
� �
sa syntaxe d’utilisation :
1 for ( ini; cond; incr )
2 {
3 instruction B1 ;
4 instruction B2 ;

� �
5 }

Son fonctionnement séquentiel est le suivant :


1. l’instruction d’initialisation de l’itérateur numérique ini est exécutée une seule fois, lors de
l’entrée dans la boucle,
2. la valeur de l’itérateur est évaluée pas la condition cond avant l’évaluation du corps de la
boucle.
(a) Si la condition est remplie,
i. les instructions de la boucle sont exécutées,
ii. l’instruction de variation de l’itérateur incr est évaluée.
� �
Intro à l’algorithmique et à la programmation �142 � 1er semestre
Departement informatique

(b) sinon, on "sort" de la boucle.


On notera que les différents éléments mis entre parenthèses ne sont pas évalués séquentiellement :
– ini est exécuté une seule fois au début,
– cond est évalué à chaque tour avant le corps de la boucle,
– incr est exécuté à chaque tour après le corps de la boucle.
� �
Ils sont regroupés au début pour faciliter la lecture et la définition de la boucle. Ainsi, par exemple :
1 for ( int i = 0; i < 4 ; i = i + 1 )
2 {
3 cout << i << endl;

� �
4 }

se lit comme étant "une boucle affichant tous les entiers i, pour i variant de 0 à 4 exclu par pas
� �
de 1". L’affichage produit est le suivant :
1 0
2 1
3 2

� �
4 3

Initialisation ini
On notera que l’itérateur i est ici déclaré "dans" la boucle for (int i ...). Il s’agit d’une
sécurité qui limite l’utilisation de i au corps de la boucle (i.e. sortie de la boucle, la variable i
� �
n’est plus définie). Ainsi, le programme suivant n’est pas valide :
1 int main()
2 {
3 for ( int i = 0; i < 4 ; i = i + 1 )
4 {
5 cout << i << endl;
6 }
7 cout << i << endl;
8 return 0;

� �
9 }

Si l’on souhaite utiliser la valeur de i hors de la boucle, il faut déclarer la variable hors de la
boucle. Le programme suivant est valide :
� �
1 int main()
2 {
3 int i ;
4 for ( i = 0; i < 4 ; i = i + 1 )
5 {
6 cout << i << endl;
7 }
8 cout << i << endl;
9 return 0;

� �
10 }

� �
et l’affichage produit est le suivant :
1 0
2 1
3 2
4 3

� �
5 4

� �
1er semestre �143 � Intro à l’algorithmique et à la programmation
IUT de Villetaneuse

Vous noterez que la valeur de l’itérateur i en sortie de boucle est 4, ce qui est cohérent avec le
fait que l’incrémentation a lieu après l’évaluation du bloc d’instructions du corps de la boucle et
avant le test.

Le test cond
La nature du test porte sur la variable entière correspondant à l’itérateur. En général on teste
si la variable est inférieure ou supérieure à une borne (la limite). Cependant, il est possible de
tester une inégalité. Ainsi i<10 peut être remplacé par i!=10.

L’incrémentation incr
La portion paramétrant la variation de l’itérateur peut également prendre plusieurs formes.
Il est par exemple possible d’opérer des décréments plutôt que des incréments. Ainsi, la boucle

� �
suivante est parfaitement correcte :

1 for ( int i = 5; i > 0 ; i = i - 1 )


2 {
3 cout << i ;

� �
4 }

� �
elle affichera :

1 5
2 4
3 3
4 2

� �
5 1

D’autre part, il possible de d’incrémenter par des pas différents de 1. Par exemple, en ajoutant

� �
(ou retirant 3) à chaque tour :

1 for ( int i = 0; i < 10 ; i = i + 3 )


2 {
3 cout << i ;

� �
4 }

� �
Ce qui affichera :

1 0
2 3
3 6

� �
4 9

Incrément compact
Dans de nombreux ouvrages de référence, l’instruction d’incrémentation incr est écrite i++ au
lieu de i = i + 1. De la même façon, i-- au lieu de i = i - 1. Vous pourrez utiliser indifférem-
ment ces différents types de notation. À titre d’exemple, les algorithmes suivants sont équivalents :
� � � �
1 for ( int i = 0; i < 10 ; i = i + 1 ) 1 for ( int i = 0; i < 10 ; i++ )
2 { 2 {
3 cout << i ; 3 cout << i ;

� � � �
4 } 4 }

� �
Intro à l’algorithmique et à la programmation �144 � 1er semestre
Departement informatique

Remplacer les littéraux par des variables


Comme à chaque fois dans un algorithme, il sera toujours possible de remplacer un littéral par
le nom d’une variable. Le programme sera correct si la variable est déclarée et initialisée avant son
� �
appel. Ainsi, le programme suivant est correct :
1 int min = 0;
2 int max = 10 ;
3 int pas = 3 ;
4 for ( int i = min; i < max ; i = i + pas )
5 {
6 cout << i ;

� �
7 }

� Sur ce thème : Exercices 1, ??-2, ??-4, ??-6, ??-8

8.2 Les boucles imbriquées


8.2.1 Qu’est-ce que des boucles imbriquées ?
Pourquoi imbriquer des boucles ? Pour la même raison qu’on imbrique des alternatives. Une
alternative permet de traiter une situation, un cas de figure.
Par exemple : "est-ce un homme ou une femme ?" peut très bien se subdiviser en d’autres cas
"a-t-il plus ou moins de 18 ans ?".
De même, une boucle, c’est un traitement systématique, un examen d’une série d’éléments un par
un, par exemple, "prenons tous les employés de l’entreprise un par un". Eh bien, on peut imaginer
que pour chaque élément ainsi considéré, pour chaque employé par exemple, on doive procéder à
un examen systématique d’autre chose, prenons chacune des commandes que cet employé a traité.
Voilà un exemple typique de boucles imbriquées : on devra programmer une boucle principale
(celle qui prend les employés un par un) et à l’intérieur, une boucle secondaire (celle qui prend
les commandes de cet employé une par une). Dans la pratique de la programmation, la maîtrise
des boucles imbriquées est nécessaire.
En conclusion, imbriquer des boucles c’est écrire une boucle à l’intérieure d’une autre boucle.
Dans la suite nous allons étudier quelques exemples de boucles imbriquées sachant qu’il existe une
multitude de combinaisons.

8.2.2 Boucle inconditionnelle dans une autre boucle inconditionnelle


"for à l’intérieur d’un for"
Tout comme les tests, il est tout à fait possible d’imbriquer les boucles, c’est à dire de mettre une
boucle dans une autre boucle, sur autant de niveaux que vous le souhaitez. Vous pouvez envisager
1, 2, 3, n niveaux, mais ça risque de devenir difficilement lisible. Voici un exemple à deux niveaux.
Il s’agit tout simplement de calculer et d’afficher toutes les tables de multiplication de 1 à 9.
Chaque table se présentera comme suit :
TABLE de 4
4 * 1 = 4
4 * 2 = 8
4 * 3 = 12
4 * 4 = 16
4 * 5 = 20
4 * 6 = 24
4 * 7 = 28
4 * 8 = 32
4 * 9 = 36
4 * 10 = 40
� �
1er semestre �145 � Intro à l’algorithmique et à la programmation
IUT de Villetaneuse

Ici encore, plutôt que d’essayer d’écrire directement le détail du programme, il peut être préfé-
rable de procéder par étape. Par exemple, nous pouvons dire que, globalement, notre programme
� �
doit écrire les 9 tables de multiplication de 1 à 9 et qu’il doit donc se présenter ainsi :
1 for (i=1; i<=10; i++)

� �
2 // écrire la table de i

Attention ! Comme i donne le numéro de table, il ne faut pas le modifier à l’intérieur du corps de
cette boucle. Le contenu de la répétition reste à préciser et, pour l’instant, nous l’avons simplement
� �
mentionné sous la forme d’un commentaire. Pour écrire la table i, nous pouvons procéder ainsi :
1 cout <<"TABLE de "<< i <<endl;
2 for (j=1; j<11; j++) // j varie de 1 à 10

� �
3 // écrire la ligne j de la table i

� �
D’où une ébauche plus élaborée de notre programme :
1 for (i=1; i<=10; i++) // i va varier de 1 à 9
2 {
3 cout << "TABLE de "<< i <<endl;
4 for (j=1; j<11; j++) // j varie de 1 à 10
5 // écrire la ligne j de la table i

� �
6 }

Il ne nous reste plus qu’à préciser comment écrire une ligne d’une table, ce qui peut se formuler
� �
ainsi :

� �
1 cout << i << " * " << j << " = " << i*j << endl;

� �
Nous aboutissons à l’algorithme complet :
1 for (i=1; i<=10; i++) // i va varier de 1 à 9
2 {
3 cout << "TABLE de "<< i <<endl;
4 for (j=1; j<11; j++) // j varie de 1 à 10
5 // écrire la ligne j de la table i
6 cout << i << " * " << j << " = " << i*j << endl;

� �
7 }

La démarche utilisée est dite démarche descendante : elle consiste à décomposer le problème posé
en sous-problèmes plus faciles à résoudre, puis à décomposer à son tour chaque sous-problème... et
ceci jusqu’à ce que l’on arrive à une solution entièrement formulée (nous reviendrons sur ce point
à la fin de ce cours).

8.2.3 Boucle inconditionnelle dans une boucle conditionnelle


"for à l’intérieur d’un while”
� �
1 cout << "donnez un entier"<<endl;
2 saisie (x);
3 while (x!=0)
4 {
5 for (i=0; i<2; i++)
6 cout << "merci pour " << x<< endl;
7 cout << "donnez un entier"<<endl;
8 saisie (x);

� �
9 }

� �
Intro à l’algorithmique et à la programmation �146 � 1er semestre
Departement informatique

– Le while permet de répéter la séquence qui en dépend et cela autant de fois que nécessaire...
Jusqu’à ce que l’utilisateur entre une valeur pour x égale à 0,
– le corps de la boucle permet d’afficher deux fois la valeur saisie par l’utilisation d’une boucle
inconditionnelle (boucle for), puis de saisir la prochaine valeur pour x.

Si nous exécutons ces instructions avec les valeurs 3, 5 et 0, nous obtenons ceci :
donnez un entier : 3
merci pour 3
merci pour 3
donnez un entier : 5
merci pour 5
merci pour 5
donnez un entier : 0

8.2.4 Boucle conditionnelle dans une boucle inconditionnelle


"while à l’intérieur d’un for”
On souhaite écrire un programme qui calcule les moyennes de 25 élèves. Pour chaque élève, le
programme lira ses notes (nombres réels) qui pourront être en nombre quelconque ; on conviendra
que l’utilisateur fournira une valeur négative pour signaler qu’il n’y a plus de notes pour un élève.
Commençons tout d’abord par un exemple d’exécution du programme souhaité :
donnez les notes de l’élève numéro 1 (-1 pour finir)
12
15
9
-1
moyenne des 3 notes : 12.00
donnez les notes de l’élève numéro 2 (-1 pour finir)
.....
donnez les notes de l’élève numéro 25 (-1 pour finir)
10
-1
moyenne des 1 notes : 10.00
Compte tenu de la complexité du programme, nous pouvons chercher, dans un premier temps,
à écrire les seules instructions de calcul de la moyenne d’un élève, en supposant que son numéro
� �
figure dans une variable nommée i :
1 cout << "donnez les notes de l’élève numéro "<< i<< "(-1 pour finir)"<<endl;
2 double somme = 0.0;
3 int nb = 0;
4 double note;
5 saisie (note) ;
6 while (note >=0 )
7 {
8 somme = somme + note;
9 nb++;
10 saisie (note) ;
11 }
12 if (nb > 0)

� �
13 cout << "moyenne des "<<nb<< "notes : "<< somme/nb << endl;

Pour obtenir le programme désiré, il nous suffit maintenant de répéter les instructions précé-
dentes, en utilisant la variable i comme compteur, variant de 1 à 25.
Voici le programme complet :
� �
1er semestre �147 � Intro à l’algorithmique et à la programmation
IUT de Villetaneuse

� �
1 int note;
2 for (int i=1; i<25; i++)// i varie de 1 à 25
3 {
4 cout << "donnez les notes de l’élève numéro "<< i<< "(-1 pour finir)"<<endl;
5 double somme = 0.0;
6 int nb = 0;
7 saisie (note );
8 while (note >=0 )
9 {
10 somme = somme + note;
11 nb++;
12 saisie (note );
13 }
14 if (nb > 0)
15 cout << "moyenne des "<<nb<< "notes : "<< somme/nb;

� �
16 }

Remarque : Faites bien attention à la place des deux initialisations somme=0.0 et nb=0. Elles
doivent figurer dans la boucle inconditionnelle gouvernée par le compteur i et avant la boucle
conditionnelle de prise en compte des différentes notes.

8.2.5 Boucle conditionnelle dans une boucle conditionnelle


"while à l’intérieur d’un while”
Considérons une fonction verifiePresenceRoi() qui reçoit deux paramètres entiers et renvoie
True si la fonction a trouvé un roi sur l’échiquier et False sinon. Voici le commentaire de la
� �
fonction verifiePresenceRoi() :
1 /*!
2 * bool verifiePresenceRoi ( int i, int j)
3 *
4 * \param i : désigne l’indice de la ligne de l’échiquier (indice commence à 0)
5 * \param j : désigne l’indice de la colonne de l’échiquier (indice commence à 0)

� �
6 */

Le cahier des charges : Nous souhaitons trouver l’indice de la ligne et l’indice de la colonne du
premier roi trouvé.
1. il est clair qu’il faut parcourir chaque ligne de l’échiquier... et de s’arrêter dès
qu’on trouve un roi ! : "tant que je n’ai pas parcouru toutes les lignes ET que je n’ai pas
trouvé de roi ! ",
2. pour chaque ligne, il faut parcourir les cases... et s’arrêter dès qu’on trouve un roi ! :
"tant que je n’ai pas parcouru tous les éléments de la ligne courante ET que je n’ai pas trouvé
de roi !”,

� �
On abouti à quelque chose comme suit :
1 int i=0; //parcours des lignes
2 int j=0; // parcours des colonnes
3 bool trouve = false ;
4 // tant que je n’ai pas parcouru toutes les les lignes ET que je n’ai pas trouvé de roi !
5 while (i<10 and !trouve)
6 {
7 //tant que je n’ai pas parcouru tous les éléments de la ligne courante
8 // ET que je n’ai pas trouvé de roi !
9 j = 0; // Je recommence à la première colonne
10 while (j<10 and !trouve)
11 {

� �
Intro à l’algorithmique et à la programmation �148 � 1er semestre
Departement informatique

12 //je cherche
13 //et j’avance d’une colonne
14 }
15 // et j’avance d’une ligne

� �
16 }

– le commentaire je cherche doit être substitué par une instruction qui consulte l’espace à deux
dimensions et qui indique si l’information cherchée est trouvée ou pas pour la ligne d’indice
� �
i et la colonne d’indice j.

� �
1 trouve = verifiePresenceRoi (i,j);

� �
– pour avancer d’une colonne, il suffit d’incrémenter j,

� �
1 j++;

� �
– pour avancer d’une ligne, il suffit d’incrémenter i,

� �
1 i ++;

� �
Nous obtenons finalement l’algorithme suivant :
1 int i=0; //parcours des lignes
2 int j; // parcours des colonnes
3 bool trouve = false ;
4 // tant que je n’ai pas parcouru toutes les les lignes ET que je n’ai pas trouvé !
5 while (i<10 and !trouve)
6 {
7 //tant que je n’ai pas parcouru tous les éléments de la ligne courante
8 // ET que je n’ai pas trouvé de roi !
9 j = 0;
10 while (j<10 and !trouve)
11 {
12 trouve = verifiePresenceRoi (i,j);
13 j++;
14 }
15 i ++;

� �
16 }

Dès que que la variable trouve devient true, on sort "naturellement" des deux boucles imbri-
quées.

8.2.6 Un peu plus compliqué... 3 boucles imbriquées... le vertige !


Il existe une multitude d’autrse exemples de combinaisons d’imbrications de boucles (avec les
boucles for et while). Il existe aussi une "infinité" de niveaux d’imbrications. Prenons un dernier
exemple pour illustrer notre propos. Le but de cet anodin algorithme est de trouver pour quelles
valeurs de A, B et C, A ∗ 100 + B ∗ 10 + C = A3 + B 3 + C 3 (ABC représentant un nombre décimal).
La recherche sera limitée pour chaque valeur entière comprise entre 1 et 10 (bien entendu, vous
pouvez augmenter l’intervalle). L’algorithme nécessite trois boucles pour chacune des valeurs. C’est
bien entendu au sein de la dernière boucle que les valeurs sont calculées et les résultats affichés en
� �
cas d’égalité.
1 for ( int a =1; a<11; a++)
2 for (int b =1; b<11; b++)
3 for (int c =1; c<11; c++)
4 {
5 int nb1= a*100+b*10+c ;
6 int nb2 = a*a*a+b*b*b+c*c*c ;

� �
1er semestre �149 � Intro à l’algorithmique et à la programmation
IUT de Villetaneuse

7 if (nb1==nb2)
8 cout<<"a = "<< a <<", b = "<< b << ", c = "<< c <<endl;

� �
9 }

8.2.7 Revenons sur l’exemple des tables de multiplication

� �
Nous vous rappelons l’algortihme obtenu :
1 for ( int i=1; i<10; i++) // i va varier de 1 à 9
2 {
3 cout << "TABLE de " << i << ":" << endl;
4 for ( int j=1; j<11; j++) // j varie de 1 à 10
5 cout<< i << " * " << j <<" = " << i*j <<endl;

� �
6 }

Si nous nous concentrons sur les fonctionnalités des deux deux boucles imbriquées on pourrait
écrire : "je parcours les tables de 1 à 9 (compteur i) et pour chaque table i, je l’affiche".
On pourrait définir une fonction qui permettrait d’afficher n’importe qu’elle table k sans
� �
préjuger de qui l’utilisera :
1 // k est un paramètre formel qui désigne la table à afficher
2 // affiche la table de multiplication de k
3 void afficheTable ( int k)
4 {
5 for ( int i=1; i<11; i++) // i varie de 1 à 10
6 cout<< k << " * " << i << " = " << k*i <<endl;

� �
7 }

� �
Finalement, l’algorithme initial devient :
1 for ( int i=1; i<10; i++) // i va varier de 1 à 9

� �
2 afficheTable (i);

Remarques :
– Bienvenue dans le monde de la décomposition fonctionnelle (démarche descendante) qui
consiste à découper un problème en fonction(s) ; la définition de la fonction afficheTable()
permet de simplifier l’algorithme initial mais surtout permet la réutilisation de cette fonction
dans d’autres contextes,
– vous remarquez que la fonction afficheTable() masque l’imbrication des boucles ayant
pour résultat une fois de plus de simplifier un algorithme,
– souvenez-vous, lors de la séance 1, nous avions affirmé qu’un problème peut être résumé
par une séquence ordonnançant des actions plus ou moins complexe à entreprendre (l’ordre
d’appel de fonctions), c’est l’essence même de la décomposition fonctionnelle d’un cahier des
charges.

Remarque : Une règle de "bonne" programmation consiste à ne jamais écrire un traitement de


plus d’une page ; dans ce cas, le décomposer en appels de fonctions dont on sait ce que chacune
fait.

� �
Intro à l’algorithmique et à la programmation �150 � 1er semestre
Departement informatique

TD8 : Autres boucles (Corrigé)

� Exercice 1 : Les boucles


Question 1.1 : Proposer 3 algorithmes utilisant respectivement les boucles while, do-while et
� �
for permettant d’obtenir la trace suivante.
1 1
2 4
3 7

� �
4 10

� �
Question 1.2 : Répétez le même exercice avec cette nouvelle trace.
1 Countdown
2 Saisir la duree du comte à rebours:
3 6
4 Debut !
5 6
6 5
7 4
8 3
9 2
10 1

� �
11 Mise a feu !!!!

� �
Correction :
1 int main()
2 {
3 int start ;
4 cout << "Countdown" << endl ;
5 cout << "Saisir la durée du comte à rebours:" << endl ;
6 saisie ( start ) ;
7 cout << "Debut !" << endl ;
8 while ( 0 < start )
9 {
10 cout << start << endl ;
11 start = start - 1 ;
12 }
13 cout << "Mise a feu !!!!" << endl ;
14 return 0 ;

� �
}
� �
15

1 int main()
2 {
3 int start ;
4 cout << "Countdown" << endl ;
5 cout << "Saisir la durée du comte à rebours:" << endl ;
6 saisie ( start ) ;
7 cout << "Debut !" << endl ;
8 do
9 {
10 cout << start << endl ;
11 start = start - 1 ;

� �
1er semestre �151 � Intro à l’algorithmique et à la programmation
IUT de Villetaneuse

12 }
13 while ( 0 < start ) ;
14 cout << "Mise a feu !!!!" << endl ;
15 return 0 ;

� �
16 }
� �
1 int main()
2 {
3 int start ;
4 cout << "Countdown" << endl ;
5 cout << "Saisir la durée du comte à rebours:" << endl ;
6 saisie ( start ) ;
7 cout << "Debut !" << endl ;
8 for ( ; start > 0 ; start-- )
9 {
10 cout << start << endl ;
11 }
12 cout << "Mise a feu !!!!" << endl ;
13 return 0 ;

� � �
14 }

� Exercice 2 : Puissance d’un circuit*


Écrire un algorithme qui permet d’afficher la puissance d’un circuit en fonction de la tension
u variant par pas de 0.5V et de l’intensité i i variant par pas de 0.05A sachant que les valeurs
initiales et finales de u et i seront demandées à l’utilisateur.
Exemple d’affichage : (pour u variant de 0 à 2V et i variant de 0 à 0.15A)

u=0 i=0 p=0


u=0 i=0.05 p=0
u=0 i=0.10 p=0
u=0 i=0.15 p=0

u=0.5 i=0 p=0


u=0.5 i=0.05 p=0.025
u=0.5 i=0.10 p=0.050
u=0.5 i=0.15 p=0.075
********************

� �
Correction :
1 double i_initiale , i_finale , u_initiale , u_finale;
2 cout << "valeur initiale de l\’intensité ?";
3 saisie ( i_initiale );
4

5 cout << "valeur finale de l\’intensité";


6 saisie ( i_finale );
7

8 cout << "valeur initiale de la tension";


9 saisie ( u_initiale );
10

11 cout << "valeur finale de la tension";


12 saisie (u_finale);
13

14 double u= u_initiale ;
15 while (u<=u_finale)

� �
Intro à l’algorithmique et à la programmation �152 � 1er semestre
Departement informatique

16 {
17 double i= i_initiale ;
18 while (i<= i_finale )
19 {
20 cout << "u="<<u<< " i="<<i<< " p="<<u*i;
21 endl;
22 i +=0.05;
23 }
24 u+=0.5;

� �
25 }

� Exercice 3 : Calcul de moyennes**


Écrire un algorithme qui permet de calculer la moyenne de chaque étudiant d’une promotion.
On suppose que le nombre d’étudiants n’est pas connu à l’avance, c’est l’utilisateur qui décide de
mettre fin à l’exécution du programme lorsqu’il n’y a plus d”étudiant dont il souhaite calculer la
moyenne. Le nombre de notes de chaque étudiant est fixé 5.

� Exercice 4 : Produit scalaire**


Ecrire une fonction calculant le produit scalaire (double) de deux vecteurs réels (tableau)
Correction :
� �
1 double produit (double vec1[], double vec2[], int dim)
2 {
3 int i;
4

5 double prod;
6 for ( i=0; i<dim; i++)
7 prod = prod +vec[i]*vec2[i];
8

9 return prod;

� �
10 }

Correction :
� �
1 int nbNotes = 5; //Nombre de notes par étudiants
2 char rep=’o’;
3

4 while (rep==’o’)
5 {
6 int som=0;
7 for (int compte=0; compte<nbNotes; compte++)
8 {
9 cout << "Quelle est la "<< compte+1 <<"e note ?";
10 saisie (note);
11 som+=note;
12 }
13 cout << "la moyenne est"<< (double) som/nbNotes << endl;
14 cout << "Voulez vous calculer la moyenne d’un autre étudiant (o/n)?";
15 saisie (rep);

� �
16 }

� �
1er semestre �153 � Intro à l’algorithmique et à la programmation
IUT de Villetaneuse

� Exercice 5 : xy
Ecrire un programme permettant de calculer xy avec x et y entiers positifs. Seule l’addition
est autorisée.

� �
Correction :

1 int main()
2 {
3 int x;
4 int y;
5 int puissance;
6 int i; // compteur qui permet de parcourir les puissances
7 int j; // compteur qui permet de calculer le résultat de x^i*x par addition successive
8 int som; // permet de calculer x^(i)+ x^(i)+ x^(i)+ x^(i)+..+ x^(i) (x fois)
9

10 puissance =1;
11 saisie (x);
12 saisie (y);
13

14 /* Itération */
15 for (i=0; i<y; i++)
16 {
17 som=0;
18 for (j=0; j<x; j++)
19 som += puissance;
20 puissance =som;
21 }
22 cout << "x^y = " << puissance << endl;
23 return 0;

� �
24 }

Relation entre les données en entrées et résultats : Le principe est de considérer que xy est équivalent à x * x
* x* x ... (y fois) et qu’une multiplication (z * x) peut s’écrire z + z + z + z ... (x fois). Il faut donc deux boucles
imbriquées : une qui permet de faire y fois la multiplication et chaque multiplication étant elle même une boucle
de x additions. Cependant ce qui doit être additionné x fois dans la boucle interne évolue. Au premier passage,
c’est x qu’on additionne x fois, au second passage c’est le x*x qu’on additionne x fois, au troisième c’est x*x*x
etc... Il faut donc mémoriser le résultat de la multiplication (variable auxiliaire puissance) précédente pour faire la
multiplication suivante. �

� Exercice 6 : Mystère**
Question 6.1 : Ecrire une fonction void permutation (int T[],int i, int j) qui permet de
faire une permutation de deux éléments d’un tableau d’indice i , j, dans le cas où la valeur de la
case de i est supérieure à la valeur de la case j .

� �
Correction :

1 Void permutation (int T[],int i, int j)


2 {
3 if (T[i]>T[j])
4 {
5 temp=T[i];
6 T[i]=T[j];
7 T[j]=temp;
8 }

� �
9 }

� �
Intro à l’algorithmique et à la programmation �154 � 1er semestre
Departement informatique

Question 6.2 : Ecrire une fonction void echange(int T[], int N) qui permet de parcourir le
tableau T de le l’indice 0 à l’indice N − 1 (inclus) et de permuter les valeurs deux à deux de gauche
à droite en utilisant la fonction précédente permutation. A quoi correspond la valeur d’indice N −1
du tableau ?
� �
Correction :
1 void echange(int T[], int N)
2 {
3 int j;
4

5 for (j=1; j<=N-1; j++)


6 {
7 permutation (T, j,j-1)
8 }

� �
9 }

c’est le maximum de toutes les valeurs d’indice < N �

Question 6.3 : Soit une fonction Mystere prenant en entrée un tableau Tab de taille N {6, 1, 4, 3, 2, 5}),
déroulez la fonction sur l’exemple ci-dessous en expliquant exactement ce que fait la fonction Mys-
� �
tere.
1 void Mystere (int Tab[], int N)
2 {
3 int i;
4 for (i=N; i>1 ; i--)
5 {
6 echange(Tab, i)
7 }

� �
8 }

� �
1er semestre �155 � Intro à l’algorithmique et à la programmation
IUT de Villetaneuse

TP8 : Autres boucles (Corrigé)

� Exercice 7 : Dessins d’étoiles*


1. Écrivez un programme permettant d’afficher n étoiles sur une ligne ; n étant demandé à
l’utilisateur.
Exemple : pour n=8
********

� �
Correction :

1 int main(void)
2 {
3 int i, valeur;
4 cout<<"combien d etoiles ? : ";
5 saisie (n);
6 cout<<endl;
7 for (i=0; i<n; i++)
8 {
9 cout<<"*";
10 }
11 cout<<endl;
12 return 0;

� �
13 }

2. Écrivez un programme permettant d ?afficher un rectangle de N × M étoiles ; N et M étant


demandés à l’utilisateur. Exemple : pour longueur=4 et une largeur =3

****
****
****

� �
Correction :

1 int main(void)
2 {
3 int i, j, largeur , hauteur;
4 cout<<"combien d etoiles sur la ligne ? ";
5 saisie ( largeur );
6 cout<<endl;
7 cout<<"combien de lignes d etoiles ? ";
8 saisie (hauteur);
9 cout<<endl;
10 for (i=0; i<hauteur; i++)
11 {
12 for (j=0; j< largeur ; j++)
13 {
14 cout<<"*";
15 }
16 cout<<endl;
17 }
18 return 0;

� �
19 }

� �
Intro à l’algorithmique et à la programmation �156 � 1er semestre
Departement informatique

3. Écrire un programme qui affiche un triangle rectangle dont la hauteur et la base dépendent
d’un entier n.
Exemples :

pour n=1 pour n=2 pour n=3 pour n=4


* * * *
** ** **
*** ***
****

� �
Correction :

1 int h; /* la hauteur */
2 int i; /* indice de la boucle externe */
3 int j; /* indice de la première boucle interne ( les étoiles ) */
4 saisie (h) ;
5 for (i=1; i<=h; i++) /* itérative externe sur le nombre de lignes à afficher */
6 {
7 for (j=1 ; j<=i ; j++) /* itérative sur le nombre d’étoiles */
8 cout<<"*";
9 cout<<endl;

� �
10 }

4. Ecrire un programme qui prendra la hauteur et qui affiche la figure suivante. Les symboles
utilisés sont des étoiles (*) et des traits(-).

Exemple. La hauteur est 5


*----
**---
***--
****-
******
Correction :

Relation entre données en entrées et résultats. Le nombre d’étoiles et le nombre de traits


à afficher se déduisent l’un de l’autre. La i-ème ligne affichée est formée de i étoiles suivies de (hauteur − i)

� �
traits.

1 int h; /* la hauteur */
2 int i; /* indice de la boucle externe */
3 int j; /* indice de la première boucle interne ( les étoiles ) */
4 saisie ( h) ;
5 for (i=1; i<=h; i++) /* itérative externe sur le nombre de lignes à afficher */
6 {
7 for (j=1 ; j<=i ; j++) /* itérative sur le nombre d’étoiles */
8 cout<<"*";
9 for (k=j ; k<h ; k++) /* itérative sur le nombre de traits */
10 cout<<"-";

� �
11 }

� �
1er semestre �157 � Intro à l’algorithmique et à la programmation
IUT de Villetaneuse

5. Écrire une fonction qui affiche un triangle isocèle dont la hauteur dépend d’un entier n (passé
en paramètre).
Exemples :

pour n=1 pour n=2 pour n=3 pour n=4


* * * *
*** *** ***
***** *****
*******

� �
Correction :

1 void triangle_isocele ( int n)


2 {
3 int i, j;
4 for (i = 0; i < n; i++)
5 {
6 for (j = 0; j < (n - 1) - i; j++)
7 cout<<" ";
8 for (j = 0; j < 2*i + 1; j++)
9 cout<<"*";
10 cout<<endl;;
11 }
12 }
13 void main(void)
14 {
15 cout << "Quelle est la hauteur";
16 saisie (h);
17 triangle_isocele (h);

� �
18 }

6. Écrire une fonction qui affiche un losange dont la longueur des diagonales (nombre impair)
dépend d’un entier n (passé en paramètre). Dans le cas où n est pair, la fonction affichera
un message d’erreur.
Exemples :

pour n=1 pour n=3 pour n=5 pour n=7


* * *
*** *** *
* ***** ***
*** *****
* *******
*****
***
*

� �
Correction :

1 int main()
2 {
3 int n;
4 do
5 {
6 cout << "Entrez un nom impair positif : ";

� �
Intro à l’algorithmique et à la programmation �158 � 1er semestre
Departement informatique

7 saisie (n);
8 }
9 while ( n<0 || n%2==0);
10

11 //Affichage du triangle supérieur


12 int m = (n+1)/2;
13 for (int i = 1; i <= m ; i++)
14 {
15 for (int j = 0 ; j < m-i ; j++)
16 cout << " ";
17 for (int j = 0 ; j < 2 * i - 1 ; j++)
18 cout << "*";
19 cout << endl;
20 }
21

22 //Affichage du triangle inférieur


23 for (int i = m-1; i >= 1 ; i--)
24 {
25 for (int j = 0 ; j < m-i ; j++)
26 cout << " ";
27 for (int j = 0 ; j < 2 * i - 1 ; j++)
28 cout << "*";
29 cout << endl;
30 }
31 return 0;

� �
32 }

� Exercice 8 :
Ecrire le programme qui calcule et affiche la table de vérité de l ?expression booléenne, (b1 or
� �
b2) and not b3, où b1, b2, b3 sont des valeurs booléennes. Compléter le programme ci-dessous.
1 int main(void)
2 {
3 bool b[2] = {true, false} ;
4 ...
5 ....
6 return 0;

� �
7 }

� �
Correction :
1 int main()
2 {
3 bool v;
4 bool b[2] = {true, false} ;
5 for (int i=0; i<2; i++)
6 {
7 for (int j=0; j<2; j++)
8 {
9 v = b[i] && b[j];
10 cout<< b[i] <<"et "<< b[j]<<" "<< v<<endl;
11 }
12 }
13

14 for (int i=0; i<2; i++)


15 {
16 for (int j=0; j<2; j++)

� �
1er semestre �159 � Intro à l’algorithmique et à la programmation
IUT de Villetaneuse

17 {
18 v = b[i] || b[j];
19 cout<< b[i] <<"or"<< b[j]<<" "<< v<<endl;
20 }
21 }
22

23 /* négation */
24 for (int i=0; i<2; i++)
25 {
26 v = ! b[i];
27 cout<<"not" <<b[i] <<" "<< v<<endl;
28 }
29 return 0;

� � �
30 }

� � Exercice 9 : Compression
On veut compresser un tableau binaire (ne contenant donc que des 0 et des 1) de taille N
complètement initialisé. On ne vous demande pas de vérifier que le tableau a correctement été
initialisé. La méthode de compression utilisée consiste a remplacer une suite de n0 (resp. de n1)
par le codage suivant : nx0 (resp. nx1), autrement dit a remplacer les suites de symboles identiques
par le nombre de symboles suivi de x et le symbole concerne. Le tableau est lu ligne par ligne.
Ainsi le tableau : 0 0 0 1 1 1 1 0 0 0 sera déclaré int tab[10] = 0,0,0,1,1,1,1,0,0,0 ; Le résultat de
la compression sera 3x04x13x0.
Question 9.1 : Ecrire une fonction "void affiche (int K, int valeur)" d ?affichage sur écran de la
chaine : K×valeur (sans aucun espace) ;
� �
Correction :
1 affiche (int k,int valeur )
2 {
3 cout<<k<<"x"valeur;

� � �
4 }

Question 9.2 : Ecrire la fonction qui réalise cette compression "void Compression(int tab[], int
taille)" (La sortie est uniquement sur écran)
� �
Correction :
1 void Compression(int tab[], int taille )
2 {
3 int i, j, k=0;
4 int valeur ;
5

6 valeur = tab[0];
7

8 for (i = 0; i < taille ; i++)


9 {
10 if (tab[i]==valeur)
11 k++;
12 else
13 {
14 affiche (k,valeur) ;
15 valeur =tab[i];
16 k=1;
17 }
18 }

� �
Intro à l’algorithmique et à la programmation �160 � 1er semestre
Departement informatique

19 affiche (k,valeur) ;

� � �
20 }

� Exercice 10 :
Écrire un programme qui, étant donné un tableau d’entiers initialisé à des valeurs de votre
choix, demande à l’utilisateur de saisir un entier puis si l’entier saisi est dans le tableau affiche son
indice et sinon affiche " entier absent" du tableau.
� �
Correction :
1 #define TAILLE 5
2 int main()
3 {
4 int tab[TAILLE] = {1, 2, 4, 2, 5};
5 int x; /* valeur cherchée */
6 bool trouve = false ;
7

8 int i=0;/*vardeboucle*/
9 /* saisie utilisateur */
10 cout<<"entier recherché ? ";
11 saisie (x);
12 /* recherche dans le tableau */
13 while ((!trouve) && (i < TAILLE))
14 {
15 if (x == tab[i])
16 {
17 trouve = true;
18 }
19 else
20 {
21 i = i + 1;
22 }
23 }
24 /* affichage du résultat */
25 if (trouve)
26 {
27 cout <<"entier" <<x<< " trouvé à l’indice "<< i<<endl;
28 }
29 else
30 {
31 cout<<"entier absent" <<endl;
32 }
33 return 0;

� � �
34 }

� Exercice 11 :
Question 11.1 : Écrire un programme tables-mult qui calcule et affiche les tables de multiplication
de 1 à 10. Une exécution de ce programme donnera à l’écran ce qui suit.

x | 1 2 3 4 5 6 7 8 9 10
-----------------------------------
1 | 1 2 3 4 5 6 7 8 9 10
2 | 2 4 6 8 10 12 14 16 18 20
3 | 3 6 9 12 15 18 21 24 27 30
� �
1er semestre �161 � Intro à l’algorithmique et à la programmation
IUT de Villetaneuse

4 | 4 8 12 16 20 24 28 32 36 40
5 | 5 10 15 20 25 30 35 40 45 50
6 | 6 12 18 24 30 36 42 48 54 60
7 | 7 14 21 28 35 42 49 56 63 70
8 | 8 16 24 32 40 48 56 64 72 80
9 | 9 18 27 36 45 54 63 72 81 90
10 | 10 20 30 40 50 60 70 80 90 100
-----------------------------------

� �
Correction :
1 int main()
2 {
3 //Affichage de la première ligne
4 cout << "x |";
5 for (int i = 1 ; i <= 10 ; i++)
6 cout << " " << i;
7 cout << endl;
8

9 //Affichage de la ligne de tirets


10 for (int i = 0 ; i < 35 ; i++)
11 cout << "-";
12 cout << endl;
13

14 //Affichage des lignes suivantes


15 for (int i = 1 ; i <= 10 ; i++)
16 {
17 //Affichage de la ligne i
18 cout << i << " |";
19 for (int j = 1 ; j <= 10 ; j++)
20 cout << " " << i*j;
21 cout << endl;
22 }
23

24 //Affichage de la ligne de tirets


25 for (int i = 0 ; i < 35 ; i++)
26 cout << "-";
27 cout << endl;
28

29 return 0;

� � �
30 }

Question 11.2 : Définir une fonction afficheAvecEspaces qui affiche un entier x sur n espaces
aligné à droite (x et n étant les deux paramètres de la fonction). À titre d’exemple, l’affichage du
� �
code
1 afficheAvecEspaces (10,5);
2 afficheAvecEspaces (112,5);
3 afficheAvecEspaces (9,5);

� �
4 afficheAvecEspaces (2222,5);

� �
doit être

� �
1 10 112 9 2222

� �
Modifier alors le code de la table de multiplication pour obtenir l’affichage suivant :
1 x | 1 2 3 4 5 6 7 8 9 10

� �
Intro à l’algorithmique et à la programmation �162 � 1er semestre
Departement informatique

2 --------------------------------------------
3 1 | 1 2 3 4 5 6 7 8 9 10
4 2 | 2 4 6 8 10 12 14 16 18 20
5 3 | 3 6 9 12 15 18 21 24 27 30
6 4 | 4 8 12 16 20 24 28 32 36 40
7 5 | 5 10 15 20 25 30 35 40 45 50
8 6 | 6 12 18 24 30 36 42 48 54 60
9 7 | 7 14 21 28 35 42 49 56 63 70
10 8 | 8 16 24 32 40 48 56 64 72 80
11 9 | 9 18 27 36 45 54 63 72 81 90
12 10 | 10 20 30 40 50 60 70 80 90 100

� �
13 --------------------------------------------

� �
Correction :
1 void afficheNbEspaces( int x, int nbEspaces)
2 {
3 int tmp = x;
4 while (tmp>=10)
5 {
6 nbEspaces--;
7 tmp /= 10;
8 }
9 nbEspaces--;
10 for (int i = 0 ; i < nbEspaces ; i++)
11 cout << " ";
12 cout << x;
13 }
14

15 int main()
16 {
17 //Affichage de la première ligne
18 cout << "x |";
19 for (int i = 1 ; i <= 10 ; i++)
20 afficheNbEspaces(i,4);
21 cout << endl;
22

23 //Affichage de la ligne de tirets


24 for (int i = 0 ; i < 44 ; i++)
25 cout << "-";
26 cout << endl;
27

28 //Affichage des lignes suivantes


29 for (int i = 1 ; i <= 10 ; i++)
30 {
31 //Affichage de la ligne i
32 afficheNbEspaces(i,2);
33 cout << " |";
34 for (int j = 1 ; j <= 10 ; j++)
35 afficheNbEspaces(i*j,4);
36 cout << endl;
37 }
38

39 //Affichage de la ligne de tirets


40 for (int i = 0 ; i < 44 ; i++)
41 cout << "-";
42 cout << endl;
43 return 0;

� �
44 }

� �
1er semestre �163 � Intro à l’algorithmique et à la programmation

Vous aimerez peut-être aussi