Chapitre 2:
Les structures de contrôle:
notions fondamentales
!"
Introduction
!"
Les structures conditionnelles
!"
Les boucles
!"
La démarche itérative
Introduction
En programmation procédurale comme en algorithmique (qui respecte les contraintes fondamentales de la programmation!), l'ordre des instructions est primordial.
Le processeur exécute les instructions dans l'ordre dans lequel elles apparaissent dans le programme. On dit que l'exécution est séquentielle.
Une fois que le programme a fini une instruction, il passe à la suivante. Tant qu'une instruction n'est pas terminée, il attend avant de continuer. Par exemple, une instruction de saisie va attendre que l'utilisateur rentre une valeur au clavier avant de continuer.
Parfois, il est nécessaire que le processeur n'exécute pas toutes les instructions, ou encore qu'il recommence plusieurs fois les mêmes instructions. Pour cela, il faudra casser la séquence. C'est le rôle des structures de contrôle.
Il existe deux grands types de structures de contrôle:
- les structures conditionnelles vont permettre de n'exécuter certaines instructions que sous certaines conditions
- les structures répétitives, encore appelées boucles, vont permettre de répéter des instructions un certain nombre de fois, sous certaines conditions
I. Les structures conditionnelles A. Présentation
Les structures conditionnelles permettent d'exécuter des instructions différentes en fonction de certaines conditions. Une condition (encore appelée expression conditionnelle ou logique) est évaluée, c'est à dire qu'elle est jugée vrai ou fausse. Si elle est vraie, un traitement (une ou plusieurs instructions) est réalisé; si la condition est fausse, une autre instruction va être exécutée, et ensuite le programme va continuer normalement.
Il existe 2 types principaux de structures conditionnelles - les structures alternatives (Si…Alors…Sinon)
- les structures conditionnelles au sens strict (Si…Alors)
Dans le déroulement d'un algorithme, on doit souvent choisir entre deux actions, suivant une condition concernant la valeur de certaines données. La structure alternative va permettre d'effectuer des choix.
Supposons que nous ayons besoin, dans un programme, d'écrire un message précisant si la valeur d'une variable, nommée a, est positive ou négative.
Pour cela on va utiliser la structure alternative Afficher "entrez un nombre"
Saisir n Si n > 0
Alors //dans le cas où l’expression n>0 est vraie Afficher "valeur positive"
Sinon //dans le cas où l’expression n>0 est fausse Afficher "valeur négative ou nulle"
Finsi
Si la condition n < 0 mentionnée après le mot Si est vraie, on exécute ce qui figure après le mot Alors; si la condition est fausse, on exécute ce qui figure après le mot Sinon.
La syntaxe générale de cette structure est la suivante:
Si <condition>
Alors <traitement1>
Sinon <traitement2>
Finsi
Pour une meilleure lisibilité du programme, on décale le Alors et le Sinon par rapport au Si. On faire apparaître un trait vertical Si et Finsi.
Pour l'instant cela peut paraître superflu, mais en fait quand les programmes se compliquent, ces règles d'écriture facilitent grandement leur relecture.
Rappelons que les traitements apparaissant après les mots Alors et Sinon peuvent être constitués d'une instruction simple, comme dans notre premier exemple, mais aussi d'un ensemble d'instructions, appelé bloc d'instruction.
ε Exemple de structure alternative avec bloc d'instruction
Nous voulons un programme qui mémorise et affiche la somme ou le produit de 2 nombres,
suivant le choix de l'utilisateur. Ce programme doit saisir les deux nombres voulus ainsi
que la lettre représentant l'opération à effectuer. Si la lettre est s (comme somme), il calcule
et affiche la somme, et si la lettre est p (ou tout autre caractère), le programme doit calculer
et afficher le produit.
Programme choix var
nb1,nb2, res: entiers op : caractère
Début
Afficher "Entrez deux nombres"
Saisir nb1, nb2
Afficher "entrez la première lettre de l'opération voulue"
Saisir op Si op = "s"
Alors res # nb1 + nb2
afficher "la somme est", res Sinon res # nb1 * nb2
afficher "le produit est", res Finsi
Fin
B. Les expressions conditionnelles
Une expression conditionnelle (ou expression logique, ou expression booléenne) est une expression dont la valeur est soit VRAI soit FAUX. Il existe plusieurs types d’expressions conditionnelles.
1. Les comparaisons simples
Dans nos deux exemples, les conditions que nous avons rencontré (a < 0) et (op ="s") sont des conditions simples. Une condition simple est une comparaison de deux expressions de même type. (a<0 type entier ou réel, op = "s" type caractère)
Les symboles de comparaison utilisable en algorithmique sont:
< , > , = , ≤ , ≥ ,
≠Pour les comparaisons de caractères, on utilise l'ordre ASCII, qui respecte l’ordre alphabétique. Une lettre placée avant une autre dans l'ordre alphabétique sera inférieure à l'autre.
"a" est inférieur à "b", mais "s" est supérieur à "m".
Attention, une condition simple ne veut pas dire une condition courte. Une condition simple peut être la comparaison de deux expressions comme:
(a + b - 3) * c ≤ (5 * y –2) / 3
! Application
Supposons que nous voulions afficher la valeur absolue de la différence entre deux nombres entiers. Ces nombres entiers seront notés x et y.
Nous voulons donc afficher x – y si x est plus grand que y et y – x sinon.
bloc n°1
bloc n°2
Nous écririons pour ce faire:
Si x > y
Alors Afficher x – y Sinon Afficher y – x Finsi
2. Les conditions complexes
Les conditions (ou expressions conditionnelles) peuvent aussi être complexes, c'est à dire formées de plusieurs conditions simples ou variables booléennes reliées entre elles par les opérateurs logiques et, ou, non.
Exemples:
Si a < 0 et b < 0 Alors…
Si (a +3 = b et c < 0) ou (a = c *2 et b ≠ c) Alors …
!"
Et
Une condition composée de deux conditions simples reliées par et est vraie si les deux conditions sont vraies.
La condition
a < 0 et b < 0
est vraie si a < 0 est vraie et si b < 0 est vraie
!"
Ou
Une condition composée de deux conditions simples séparées par ou est vraie si au mois l'une des conditions simples est vraie.
a <0 ou b < 0
est vraie si a < 0 ou si b < 0 ou si a et b sont négatifs.
!"
Non
Une conditions précédée par non est vraie si la condition simple est fausse et inversement.
non (a < 0) est vraie si a >=0
L'usage des parenthèses permet de régler d'éventuels problèmes de priorités des opérateurs logiques.
3. Les variables booléennes
Les variables booléennes, comme les expressions conditionnelles, sont soit vraies, soit fausses. On peut donc affecter une expression conditionnelle à un booléen et on peut aussi trouver une variable booléenne à la place d’une expression conditionnelle.
Les variables booléennes et les expressions conditionnelles sont équivalentes. A chaque fois
que l’on peut trouver une expression conditionnelle, on peut aussi trouver une variable
booléenne.
Ex :
Programme intervalles Var
appartient : booléen nb : réel
Début
Afficher « veuillez entrer un nombre réel » Saisir nb
appartient = (nb<10 ET nb> 5) OU (nb >15 ET nb <20) Si appartient
Alors « Le nombre appartient aux intervalles définies » Sinon « Le nombre n’appartient pas aux intervalles définies » Finsi
Fin
Ce programme saisit un nombre et affiche si ce nombre est compris dans les intervalles 5- 10 ou 15-20
II. La structure Si…Alors (conditionelle)
Cette structure est utilisée si on veut exécuter une instruction seulement si une condition est vraie et ne rien faire si la condition est fausse. Elle évite d’écrire Sinon rien.
La syntaxe d'une structure conditionnelle est la suivante:
Si <condition> Alors <traitement>
Finsi
$ Exemple:
Dans un programme de calcul d'une facture, on veut effectuer une remise de 1% si le montant de la facture dépasse 1000F.
Supposons que la variable qui contient le montant de la facture s'appelle mont. On veut écrire l'algorithme qui affiche le montant à payer.
Si le montant est inférieur à 1000F, on veut juste afficher le montant tel quel. Mais si le montant est supérieur à 1000F, il faut prendre en compte la remise et calculer le nouveau montant.
Le morceau d'algorithme concerné est:
Si mont > 1000 Alors mont = mont * 0.9 Finsi
Afficher mont
Le programme effectue la réduction seulement si le montant est supérieur à 1000F. Sinon,
il ne fait aucun traitement particulier et passe à l'instruction suivante. Dans tous les cas, le
montant est affiché.
III. Les structures répétitives ou boucles
Les structures répétitives aussi appelées boucles, permettent de répéter un traitement ( c'est à dire une instruction simple ou composée) autant de fois qu'il est nécessaire: soit un nombre déterminé de fois, soit tant qu'une condition est vraie.
Il existe trois grands types principaux de structures répétitives:
- la structure Tant que…Faire, qui permet d'effectuer une instruction tant qu'une condition est satisfaite
- la structure Pour qui permet de répéter une instruction un certain nombre de fois
- la structure Répéter…Jusqu'à, qui comme son nom l'indique, permet de répéter une instruction jusqu'à ce qu'une condition soit satisfaite.
Seule la boucle Tant que est fondamentale. Avec cette boucle, on peut réaliser toutes les autres boucles alors que l'inverse n'est pas vrai. La boucle Pour est très utilisée aussi car elle permet de simplifier la boucle Tantque lorsque le nombre de tour de boucle est connu d’avance. La boucle Répéter, très peu utilisée, sera étudiée au chapitre suivant.
A. La boucle Tant que … Faire
La boucle Tant que … Faire permet de répéter un traitement tant qu'une expression conditionnelle est vraie. Si d'emblée, la condition n'est pas vraie, le traitement ne sera pas exécuté. On voit donc que la boucle Tant que a un point commun avec la structure conditionnelle où si la condition n'est pas vraie, le traitement n'est pas exécuté.
Syntaxe:
Tant que <condition d'exécution> Faire
<traitement> // instruction simple ou bloc d'instructions FinTantque
Supposons que l'on veuille que l'algorithme calcule le cube des nombres qu'on lui fournit et que pour arrêter, l'utilisateur doive entrer 0.
Si le nombre saisi est 0, on ne veut pas afficher le cube et le traitement est terminé. Si le nombre saisi est différent de 0, on affiche son cube et on recommence (on demande d'entrer un nombre, on le saisit, etc)
On veut donc exécuter les instructions dans l'ordre suivant:
!"
saisir un nombre
!"
vérifier la condition d'exécution (x ≠ 0)
!"
si x vaut 0, on sort de la boucle
sinon on affiche le cube et on attend que l'utilisateur entre un autre nombre
!"
On vérifie la condition d'exécution (x ≠ 0)
!"
si x vaut 0, on sort de la boucle
sinon on affiche le cube et on attend que l'utilisateur entre un autre nombre
On voit donc qu'après la saisie du premier nombre, on répète les trois dernières …
instructions. On va donc pouvoir les inscrire dans une boucle. La condition de continuation
(x
≠0) est inscrite après le tant que. Cette condition est vérifiée à chaque fois qu'on a
terminé les traitements de la boucle.
Programme cube
Var x : Entier
Début
Afficher "Ce programme calcul le cube des nombres que vous entrez. Pour arrêter tapez 0."
Afficher "Entrez un nombre"
Saisir x
Tant que x
≠0 Faire
Afficher "le cube de " , x , " est ", x*x*x Afficher "Entrez un nombre ou 0 pour arrêter"
Saisir x FinTQ
Afficher "Fin"
Fin
Le nombre de répétition du traitement n'est pas indiqué explicitement; il dépendra des données fournies au programme, en l'occurrence les nombres entrés.
Fonctionnement de ce programme
Il affiche tout d'abord le libellé de saisie et attend que l'utilisateur entre un nombre, qui est alors saisi dans la variable x.
Ensuite, la condition qui suit le Tant que est évaluée. Si l'utilisateur rentre comme premier nombre 0, la condition est fausse et le corps de la boucle ne sera pas exécuté et le processeur continuera à la première instruction suivant le FinTQ (Afficher "Fin"). Si l'utilisateur entre un nombre différent de 0, son cube est calculé et affiché et un nouveau nombre est saisi. Au niveau du FinTQ, le processeur effectue un branchement, c'est à dire qu'il n'effectue pas l'instruction suivante mais retourne au début de la boucle et réévalue l'expression conditionnelle.
L'utilisateur peut calculer autant de cubes qu'il désire et quand il veut arrêter, il lui suffit de taper 0. On dit que 0 est une valeur drapeau, c'est-à-dire une valeur qui indique la fin d'un traitement.
La trace d'un algorithme
La trace d'un algorithme représente la valeur des différentes informations d'un programme durant son exécution. Il est vivement conseillé d'effectuer la trace d'un algorithme afin de vérifier qu'il fonctionne.
La première chose à faire est de choisir des données sur lesquelles ont va effectuer le test de l'algorithme. Pour ces données, on calcule à la main le résultat attendu. Puis on effectue la trace et on compare le résultat attendu avec le résultat de la trace qui doivent être les mêmes (sinon, il y a une erreur quelque part…)
Effectuons la trace de l'algorithme précédent avec les données suivantes donnée x résultat attendu
10 affichage de 100
-3 affichage de -9
0 affichage de Fin et arrêt du programme
Instruction exécutée variable ou valeur après affichage expression évaluée l'instruction à l'écran
Afficher "Ce programme … Ce programme calcule le cube…
Afficher "Entrez un nombre" Entrez un nombre
saisir x x 10 10
Tant que x ≠ 0 x ≠ 0 VRAI
afficher x*x*x x*x*x 100 100
Afficher "Entrez un nombre… Entrez un nombre ou 0 pour…
saisir x x -3 -3
Tant
que x ≠ 0 x
≠0 VRAI
afficher x*x*x x*x*x -9 -9
Afficher "Entrez un nombre…
x -3
Entrez un nombre ou 0 pour…saisir x x 0 0
Tant que x
≠0 x
≠0 FAUX
Afficher "Fin" Fin
B. La boucle Pour
La boucle Pour permet de répéter une instruction un nombre connu de fois. Elle a le formalisme suivant:
Pour < compteur> de <valeur initiale> jqà <valeur finale> [pas de <incrément>] Faire <traitement>
FinPour
Elle permet de faire la même chose que la boucle Tant que mais de façon plus rapide, du moins lorsque le nombre de répétition est connu.
La variable compteur est de type entier. Elle est initialisée à la valeur initiale. Le compteur augmente (implicitement) de l'incrément à chaque répétition du traitement. Lorsque la variable compteur vaut la valeur finale, le traitement est exécuté une dernière fois puis le programme sort de la boucle.
Par défaut, l’incrément est de 1 Exemple:
Pour x de 1 jqà 20 Faire
<traitement>
FinPour
Grâce à une telle structure, le traitement va être répétée 20 fois. On pourrait faire la même chose avec une boucle tant que, mais il faudrait initialiser la variable compteur et l'incrémenter explicitement.
x# 1
Tant que x <= 20 Faire <traitement>
x
# x+1FinTantQue
x#x+1 incrémentation
automatique
La boucle Pour est en fait une simplification de la boucle TantQue.
% Application
Affichons la table de multiplication du 7. Pour cela on va utiliser une variable a qui varie de 1 à 10 et multiplier cette variable par 7 à chaque incrémentation. Cette variable va aussi servir de compteur pour la structure Pour.
Programme multiplication7 Var
a: Entier Début
Pour a de 1 à 10 pas de 1 Afficher a, " * 7 = ", a * 7 FinPour
Fin
IV. La démarche itérative
Une itération est une boucle où la valeur d’une variable dépend de sa valeur au tour précédent. La variable en question se trouve à la fois à gauche et à droite d’une affectation.
La démarche itérative (l’utilisation d’itérations) est utilisée pour résoudre beaucoup de problèmes de programmation. Pour se familiariser avec cette démarche complexe, nous allons étudier des problèmes algorithmiques simples et fondamentaux.
A. Compter et Accumuler
1. Comment faire pour compter le nombre de tour de boucle dans une boucle Tantque ? (comptage systématique)
Reprenons le programme cube. Supposons maintenant que nous ayons besoin de compter combien de cube ont été calculé. Comment procéder ?
Il suffit d’utiliser une variable qui va servir de compteur. Avant l’entrée dans la boucle, le compteur est mis à 0. Ce compteur est incrémenté de 1 à chaque tour de boucle. Pour cela, on ajoute l’instruction compteur #
### compteur + 1 à l’intérieur de la boucle:Une telle instruction s’appelle incrémentation.
Programme cube Var
x : Entier compteur : entier Début
… (cf III)
Tant que x ≠ 0 Faire
Afficher "le cube de " , x , " est ", x*x*x compteur # compteur + 1
Afficher "Entrez un nombre ou 0 pour arrêter"
Saisir x FinTantque
Afficher « Vous avez demandé », compteur, « cubes »
Fin
2. Comment faire pour compter seulement les cubes négatifs ? (comptage sélectif)
Si on ne veut augmenter le compteur que dans une certaine condition (ici, dans le cas où le nombre saisi est négatif), il suffit de placer l’incrémentation à l’intérieur d’une structure conditionnelle.
Programme cube Var
x : Entier compteur : entier Début
… (cf III)
Tant que x
≠0 Faire
Afficher "le cube de " , x , " est ", x*x*x Si x<0 Alors
compteur # compteur + 1 FinSi
Afficher "Entrez un nombre ou 0 pour arrêter"
Saisir x FinTantque
Afficher « Vous avez obtenu », compteur, « cubes négatifs » Fin
3. Comment faire pour compter plusieurs choses à la fois ? (comptage multiple)
On peut vouloir compter plusieurs choses simultanément dans la même boucle. Pour reprendre notre exemple, nous pourrions vouloir compter les cubes négatifs mais aussi les cubes pairs. Dans ce cas, un seul compteur ne suffit plus. Il faut utiliser autant de compteur que l’on a de choses à compter.
Programme cube Var
x : entier
cptneg : entier // compteur des cubes négatifs cptpair :entier // compteur des cubes pairs
Début
… (cf III)
Tant que x ≠ 0 Faire
Afficher "le cube de " , x , " est ", x*x*x Si x<0 Alors
cptneg # cptneg + 1 FinSi
Si x*x*x mod 2 = 0 Alors cptpair
## cptpair + 1 ##FinSi
Afficher "Entrez un nombre ou 0 pour arrêter"
Saisir x FinTantque
Afficher « Vous avez obtenu », cptnegr, « cubes négatifs, et », cptpair, « cubes pairs »
Fin
4. Calculer le résultat de x
navec une itération
Dans certains langages, l’opérateur exposant n’existe pas. Supposons que nous ne pouvons pas l’utiliser en algorithmique. Nous allons écrire l’algorithme qui permet de calculer un nombre à un exposant donné. Le nombre x et l’exposant n sont saisis.
Rappel : x
1=x
x
2= x*x & x
1*x x
3= x*x*x & x
2*x x
4= x*x*x*x & x
3*x …
On ne peut pas faire tout d’un coup le nombre de multiplication nécessaire car on ne sait pas combien vaut l’exposant au moment d'écrire le programme. Le programmeur ne sait pas quel exposant va taper l’utilisateur. Il y a une infinité de possibilités.
Pour contourner cette difficulté, on va répéter n fois la multiplication par x dans une boucle.
On utilise la boucle pour car on sait combien de fois on répète la multiplication : n fois.
Que fait-on du résultat de la multiplication par x: on l’affecte dans une variable résultat, que l’on va utiliser au tour suivant. Qu’est-ce qu’on multiplie par x à chaque tour : le résultat du tour précédent.
Et au premier tour ? Il n’y a pas encore de résultat. Il suffit d’initialiser la variable résultat avec 1.
D’où la solution suivante : Programme exposant Var
x, n : entier //x le nombre et n l’exposant Début
Aff « veuillez entrez un nombre puis son exposant » Saisir x, n
res # 1 //initialisation du résultat Pour i de 1 jusqu’à n Faire
res # res * x //itération FinPour
Aff x, « puissance », n, « vaut », res Fin
La variable résultat ne vaut véritablement le résultat recherché qu’à la sortie de la boucle.
Entre temps, elle prend des valeurs intermédiaires qui servent à avancer d’une valeur initiale connue vers la valeur finale recherchée.
Effectuons la trace du morceau d’algorithme grisé dans le cas où l’utilisateur entre 5 pour x et 4 pour n.
tour de boucle valeur de res (valeur du compteur)
avant 1 grâce à l’initialisation
1
er(i#1) 5 1 * x (x vaut 5)
2
ième(i#2) 25 x * x
3
ième(i#3) 125 x² * x
4
ième(i#4) 525 x
3* x soit x
4i vaut n donc arrêt de la boucle
après 525 le résultat voulu
état intermé- diaire n°1
état intermé- diaire n°2