Chapitre 3 - Les instructions conditionnelles (les alternatives) PDF
Document Details
Uploaded by SoftLesNabis7023
Université Virtuelle de Côte d'Ivoire
Tags
Summary
This document provides a foundational explanation of conditional statements in programming, offering examples like conditionals for testing the state of water based on its temperature (solid, liquid, vapor). It explains different forms of conditionals, including simple/reduced and complete form, along with nested conditionals.
Full Transcript
Chapitre 3 - Les instructions conditionnelles (les alternatives) Chapitre 3 - Les instructions conditionnelles (les alternatives) 1. Introduction Les algorithmes comportent généralement deux types d’instructions : - Les instructions simples : qui permettent la manipulation des variables tel...
Chapitre 3 - Les instructions conditionnelles (les alternatives) Chapitre 3 - Les instructions conditionnelles (les alternatives) 1. Introduction Les algorithmes comportent généralement deux types d’instructions : - Les instructions simples : qui permettent la manipulation des variables telles que l’affectation, la lecture et l’écriture. - Les instructions de contrôle : qui précisent l’enchainement chronologique des instructions simples. C’est en particulier le cas des instructions conditionnelles ou les tests. 2. Structure d’un test Il existe deux formes de test : forme simple (ou réduite) et forme complète. 2.1. Forme simple Dans cette forme, une action qui correspond à une ou plusieurs instructions, est exécuté si une condition est vérifiée. Sinon l’algorithme passe directement au bloc d’instruction qui suit immédiatement le bloc conditionnel. Syntaxe : Si (condition) Alors instruction(s) ; // action Finsi Remarque : La condition évaluée après l’instruction « Si » est une variable ou une expression booléenne qui, à un moment donné, est Vraie ou Fausse. par exemple : x=y ; x = 0 et x < 1 qui doivent être vérifiées en même temps. Pour combiner ces deux conditions, on utilise les opérateurs logiques. Ainsi, la condition x ∈ [0, 1[ pourra s’écrire sous la forme : (x >= 0) ET (x < 1). Cette dernière est appelée une condition composée ou complexe. Exemple (sur la forme complète d’un test) : x←5;y←9; Si (x = y) Alors Ecrire (″x est égale à y ″) ; Sinon Ecrire (″x est différente de y ″) ; Avec cette forme, on peut traiter les deux cas possibles. Si la condition (x=y) est vérifiée, le premier message est affiché, si elle n’est pas vérifiée, le deuxième message est affiché. 3. Tests imbriqués La forme « Si … Alors…Sinon » permet deux choix correspondants à deux traitements différents. Dans d’autres situations, on pourra avoir plus de deux cas ce qui rend cette alternative insuffisante pour traiter tous les cas possibles (voir exemple ci-dessous). La forme complète permet de choisir entre plusieurs actions en imbriquant des formes simples selon la syntaxe ci-dessous. Syntaxe : Si (condition1) Alors instruction(s) 1 ; Sinon Si (condition2) Alors instruction(s) 2 ; Sinon Si (condition3) Alors instruction(s) 3 ; - 16 - Chapitre 3 - Les instructions conditionnelles (les alternatives) … Sinon instruction(s) N ; FinSi FinSi FinSi Exemple : Etat de l’eau Dans les conditions normales de température et de pression, l’eau est sous forme de glace si la température est inférieure ou égale à 0° C, sous forme de liquide si la température est comprise entre 0° C et 100° C et sous forme de vapeur au-delà de 100° C. Ecrivons l’algorithme qui permet de vérifier l’état de l’eau selon sa température. La solution pourrait être comme suit : Algorithme Etat_Eau ; Var t : réel ; Début Ecrire ("Donner la température de l’eau :") ; Lire (t) ; Si (t 0 ET t < 100) Alors Ecrire ("Etat liquide") ; Finsi Si (t >= 100) Alors Ecrire ("Etat gazeux") ; Finsi Fin Cet algorithme est correct mais il évalue les trois conditions qui portent sur la même variable et qui sont exclusives. En effet, si (t = 0 et t < 100) ni (t > 100). Il est donc inutile d’évaluer les deux dernières conditions si la première est vérifiée, ou d’évaluer la dernière condition si la deuxième est vérifiée. Pour éviter ce cas de figure, il sera préférable d’utiliser des tests imbriqués comme suit : … Début Ecrire ("Donner la température de l’eau:") ; Lire (t) ; Si (t 2), peuvent être utilisés pour diverses raisons telles que la création et le traitement des objets 3D par exemple qui nécessitent des tableaux de 3 dimensions au minimum. La déclaration de ce type de tableaux est comme suit : Syntaxe : Tableau nom_tableau [taille1][taille2] … [tailleN] : type ; Exemple : Tableau T : réel ; // un tableau T à 3 dimensions La manipulation d’un tableau à plusieurs dimensions suit le même principe que celle des tableaux à deux dimensions. Ceci s’appuie sur l’utilisation des boucles imbriquées pour parcourir le tableau, de sorte qu’il y aura autant de boucles qu’il y a de dimensions. 5. La recherche dans un tableau 5.1. La notion du drapeau Le drapeau (ou flag en Anglais) est une variable booléenne initialisée à Faux (drapeau baissé). Dès qu’un évènement attendu se produit, la variable change de valeur à Vrai (drapeau levé). Donc, la valeur finale du drapeau permet de savoir si un évènement a eu lieu ou pas. Cela devrait s’éclairer à l’aide d’un exemple extrêmement fréquent : la recherche de l’occurrence d’une valeur dans un tableau. Exemple : En supposant l’existence d’un tableau comportant N valeurs entières. On doit écrire un algorithme qui lit un nombre donné et informe l’utilisateur de la présence ou de l’absence de - 32 - Chapitre 5 - Les tableaux ce nombre dans le tableau. La première étape consiste à écrire les instructions de lecture du nombre N et de parcours du tableau : Tableau Tab[N] : Entier ; Var val, i : Entier ; Début Ecrire ("Entrer la valeur à rechercher :") ; Lire (val) ; Pour i de 0 à N-1 … Finpour Fin Illustration : On suppose que N=6 et les valeurs saisies sont celles figurant dans le schéma suivant : indices : i=0 i=1 i=2 i=3 i=4 i=5 Tab valeurs : 10 22 31 46 5 7 Revenons à l’algorithme, maintenant, il faut combler les points de la boucle (le bloc qui devra contenir les instructions de la recherche). Évidemment, il va falloir comparer « val » à chaque élément du tableau, s’il y a une égalité quelque part, alors « val » fait partie du tableau. Cela va se traduire, bien entendu, par l’instruction conditionnelle « Si … Alors … Sinon ». … Début Ecrire ("Entrez la valeur à rechercher ") ; Lire (val) ; Pour i de 0 à N-1 Si (val = Tab[i]) Alors Ecrire (val, "figure") ; Sinon ? Ecrire (val, "ne figure pas") ; Finsi Finpour Fin - 33 - Chapitre 5 - Les tableaux Illustration : On suppose que la valeur à rechercher (val) est égale à 31 : On peut constater qu’on a deux possibilités : - ou bien la valeur « val » figure dans le tableau, - ou bien elle n'y figure pas. Mais dans tous les cas, l'algorithme ne doit produire qu'une seule réponse, quel que soit le nombre d'éléments du tableau. Or, l'algorithme ci-dessus affiche autant de messages qu'il y a de valeurs dans le tableau. Il y a donc une erreur quelque part. En fait, on ne peut savoir si la valeur recherchée existe dans le tableau ou non que lorsque le parcours du tableau est entièrement accompli. Pour pallier à cette erreur, on doit réécrire l’algorithme en plaçant le test après la boucle et en utilisant cette fois-ci une variable booléenne (drapeau) que l’on appelle « Existe ». Cette variable doit être gérée comme suit : - La valeur de départ de « Existe » doit être évidemment Faux (drapeau baissé). - La valeur de la variable « Existe » doit devenir Vrai (drapeau levé), si un test dans la boucle est vérifié (lorsque la valeur de « val » est rencontrée dans le tableau). mais le test doit être asymétrique, c.à.d. qu’il ne comporte pas de "sinon". Donc l’algorithme correct devrait être comme suit : Tableau Tab[N] : entier ; Var val, i : entier ; existe : booléen ; Début Ecrire ("Entrez la valeur à rechercher ") ; Lire (val) ; existe ← faux ; Pour i de 0 à N-1 Si (val = Tab[i]) Alors existe ← vrai; Finsi Finpour - 34 - Chapitre 5 - Les tableaux Si (existe) Alors Ecrire (val, "fait partie du tableau") ; Sinon Ecrire (val, "ne fait pas partie du tableau") ; Finsi Fin Illustration : En utilisant un drapeau (la variable « Existe ») : Question ? Réécrire le même algorithme mais cette fois-ci, la boucle de recherche doit être arrêtée dès que la valeur du drapeau change. 6. Le tri d’un tableau Qu’est-ce qu’un tri ? Le tri est une opération consistant à ordonner un ensemble d’éléments suivant une relation d’ordre prédéfinie. Le problème du tri est un grand classique en algorithmique. Trier un tableau numérique c’est donc ranger ses éléments en ordre croissant ou décroissant. Il existe plusieurs algorithmes de tri, parmi lesquels le tri par sélection, tri par insertion, tri à bulles, tri par fusion, etc. Nous illustrons dans ce qui suit deux types de tri, à savoir le tri par sélection et le tri par insertion. 6.1. Tri par sélection Cette technique est parmi les plus simples, elle consiste à sélectionner, pour une place donnée, l’élément qui doit y être positionné. Par exemple pour trier un tableau en ordre croissant, on met en première position le plus petit élément du tableau et on passe à la position suivante pour mettre le plus petit élément parmi les éléments restants et ainsi de suite jusqu’au dernier. - 35 - Chapitre 5 - Les tableaux Exemple : Soit à trier, en ordre croissant, le tableau suivant : 25 10 13 31 22 4 2 18 Nous commençons par la recherche de la plus petite valeur et sa position. Une fois identifiée (dans ce cas, c’est le nombre 2 en 7ème position), nous l’échangeons avec le 1er élément (le nombre 25). Le tableau devient ainsi : 2 10 13 31 22 4 25 18 Nous recommençons la recherche, mais cette fois, à partir du 2ème élément (puisque le 1er est à sa position correcte). Le plus petit élément se trouve en 6ème position (le nombre 4). Nous échangeons donc le 2ème élément avec le 6ème élément : 2 4 13 31 22 10 25 18 Nous recommençons la recherche à partir du 3ème élément (puisque les deux premiers sont maintenant bien placés), Le plus petit élément se trouve aussi en 6ème position (10), en l’échangeant avec le 3ème, ça donnera: 2 4 10 31 22 13 25 18 Nous recommençons maintenant à partir du 4ème élément et de la même façon nous procédons jusqu’à l’avant dernier : 2 4 10 13 22 31 25 18 2 4 10 13 18 31 25 22 2 4 10 13 18 22 25 31 2 4 10 13 18 22 25 31 Algorithmiquement, nous pouvons décrire ce processus de la manière suivante : Boucle principale : prenant comme point de départ le premier élément, puis le second, etc, jusqu’à l’avant dernier. Boucle secondaire : à partir de ce point de départ mouvant, nous recherchons jusqu’à la fin du tableau le plus petit élément. Une fois trouvé, nous l’échangeons avec le point de départ. - 36 - Chapitre 5 - Les tableaux Donc, cela s’écrit : Pour i de 0 à 6 posmin ← i ; // posmin est la position du minimum initialisée par i Pour j de (i + 1) à 7 Si (T(j) < T(posmin)) Alors posmin ← j ; Finsi Finpour temp ← T(posmin) ; T(posmin) ← T(i) ; T(i) ← temp ; FinPour 6.2. Tri par insertion Soit à trier un tableau d’éléments en ordre croissant. Le principe de ce type de tri repose à chaque itération sur trois phases : a) On prend le premier élément dans la partie non encore triée du tableau (la clé). b) On cherche la place de la clé dans la partie déjà triée du tableau, en commençant par la droite de cette partie. c) Une fois cette place trouvée, on y insère la clé après qu’on ait décalé vers la droite tous les éléments de la partie triée dont la valeur est plus grande ou égale à la valeur de la clé. Il faut noter qu’initialement, la partie triée est constituée seulement du premier élément du tableau, autrement dit, le processus du tri commence à partir du deuxième élément. Exemple : Soit à trier, en ordre croissant, le même tableau précédent en appliquant le tri par insertion : i=1 25 10 13 31 22 4 2 18 Clé Partie non encore triée - 37 - Chapitre 5 - Les tableaux On décale le 1er élément de la partie triée vers la droite puisque sa valeur est supérieure à la clé. Cette dernière est déplacée à la 1ère position : i=2 10 25 13 31 22 4 2 18 On recommence le processus avec une nouvelle clé. Le 1er élément à droite de la partie triée (25) est décalé vers la droite puisque sa valeur est supérieure à la clé. Le 2 ème élément ne sera pas décalé puisqu’il est inférieur à la clé. Par conséquent, la clé est insérée dans la 2ème position du tableau : i=3 10 13 25 31 22 4 2 18 On ne déplace pas cette clé (31) puisque sa valeur est supérieure à celles des éléments qui la précèdent. i=4 10 13 25 31 22 4 2 18 On décale les deux premiers éléments (31 et 25) vers la droite et la clé est insérée à la 3 ème position : i=5 10 13 22 25 31 4 2 18 On décale tous les éléments de la partie triée vers la droite puisque leurs valeurs sont supérieures à celle de la clé. Cette dernière est déplacée à la 1 ère position : i=6 4 10 13 22 25 31 2 18 La même opération est répétée pour cette clé (2) : i=7 2 4 10 13 22 25 31 18 Les trois éléments (22,25 et 31) sont décalés vers la droite et la clé est déplacée vers la 5ème position : 2 4 10 13 18 22 25 31 Nous obtenons donc un tableau qui est trié en ordre croissant. L’algorithme correspondant à ce type de tri est présenté dans ce qui suit : - 38 - Chapitre 5 - Les tableaux Algorithme Tri_Insertion ; Var i, j, n, clé : Entier; // n est la taille du tableauT T : Tableau d’entiers ; Début Pour i de 1 à n-1 // on commence par le 2ème élément (début de la partie non triée) clé T[i] ; j i - 1 ; // indice du 1er élément à droite de la partie triée Tant que ((j >= 0) ET (clé < T[j])) Faire T[j +1] T[j]; // Décalage j j - 1; FinTant que T[j +1] clé; // Insertion de la clé FinPour Fin 6.3. Comparaison Dans l’algorithme de tri par sélection, nous avons dans tous les cas, la boucle interne est exécuté pour i=1, 2, 3 jusqu’à i=(n-1) par conséquent, nous avons (n-1) + (n-2) + (n-3) + … + 1 étant n (n-1) / 2 exécutions. Par exemple, pour un tableau de 100 éléments, la boucle est exécutée 4950 fois dans tous les cas. Dans l’algorithme de tri par insertion, nous avons dans le pire des cas un tableau trié à l’envers (en ordre décroissant dans ce cas), et la boucle interne est exécuté (n-1) + (n-2) + (n-3) + … + 1 fois, étant n (n-1) / 2 exécutions au maximum. Au meilleur des cas, le tableau est trié en ordre voulu (croissant dans ce cas) et la boucle interne ne s’exécutera jamais. En moyenne, le nombre d’exécutions est n (n-1) / 4. Par exemple, pour un tableau de 100 éléments, la boucle est exécutée 4950 fois au maximum et 2475 en moyenne. 7. Conclusion Dans ce chapitre, nous avons vu comment mémoriser et manipuler un ensemble de valeurs représentées par le même nom et identifiées par des numéros à travers la notion du tableau. En fait, un tableau n’est pas un type de données mais plutôt une liste d’éléments d’un type donné. Le problème du tri qui est un grand classique de l’algorithmique, a été abordé par la suite à travers deux algorithmes parmi les plus simples, à savoir le tri par sélection et le tri par insertion. Une comparaison entre les deux algorithmes a été donnée à la fin de ce chapitre. - 39 - Chapitre 6 - Les enregistrements (structures) Chapitre 6 - Les enregistrements (structures) 1. Introduction Nous avons vu dans le chapitre précédent, que les tableaux nous permettent de stocker plusieurs éléments de même type, tel que stocker les notes des étudiants dans un tableau de type réel. Supposons maintenant qu’en plus des notes des étudiants, nous voulons stocker aussi leurs informations (nom, prénom, matricule, …). Il nous faut dans ce cas de figure, une autre structure qui permet de stocker des données de différents types. Donc, une nouvelle structure appelée enregistrement est plus adaptée dans ce cas. 2. Définition Un enregistrement (ou structure) permet de regrouper un ensemble de données de différents types sous le même nom (un seul objet). Il est défini par un ensemble d’éléments appelés champs. Ces derniers sont des données élémentaires ou composées qui peuvent être de types différents. 3. Déclaration et manipulation La syntaxe de déclaration d’une structure est la suivante : Structure nom_structure champ1 : type1 ; champ2 : type2 ;... champN : typeN ; FinStructure ; Tel que « nom_structure » est le nom d’enregistrement défini par l’utilisateur. « champ1, champ2, …, champN » sont les variables membres de la structure déclarée. Exemple : Structure Etudiant num : entier ; nom : chaîne ; moyenne : réel; FinStructure ; Par la suite, des variables de type Etudiant peuvent être déclarées comme suit : Var x,y : Structure Etudiant ; - 40 - Chapitre 6 - Les enregistrements (structures) La manipulation d’une variable structure se fait par champ (membre) et l’accès à une information contenue dans un champ se fait en précisant le nom de la variable structure suivie du champ concerné. Les deux séparés par un point. Exemple : x.num ←123 ; // affecte le nombre 123 au champ num Lire (x.nom) ; // lire le champ nom x.moyenne ←13.5 ; // affecte le nombre 13.5 au champ moyenne 4. Tableau de structures Il est possible de déclarer un tableau dont les éléments sont des structures avec la syntaxe suivante : Tableau nom_tableau [taille] : Structure nom_structure ; Exemple : Tableau T : Structure Etudiant ; Donc, T est un tableau de 10 éléments de type structure (« Etudiant » dans ce cas). L'accès à un champ d’élément i d’un tableau de structure se fait comme suit : nom_tableau [i].champ Par exemple, les instructions : T.nom ← "Mohamed" ; T.num ← 1 ; et T.moyenne ← 12.5 ; affectent respectivement la valeur entière « 1 », la chaîne de caractères « Mohamed » et la valeur réelle « 12.5 » aux champs « num », « nom » et « moyenne » du 1er élément du tableau T. Illustration : indices : i=0 i=1 … i=9 T num : 1 num : num : Eléments : nom : Mohamed nom : … nom : moyenne : 12.5 moyenne : moyenne : De même, les instructions : Ecrire (T.num) ; Ecrire (T.nom) ; Ecrire (T. moyenne) ; Affichent les contenues des trois champs du 1er élément du tableau T. - 41 - Chapitre 6 - Les enregistrements (structures) 5. Structure membre d’une autre structure Une structure peut figurer parmi les champs d'une autre structure. Dans ce cas, elle doit être déclarée avant la structure qui la contient. Exemple : Structure Date jour, mois, annee : entier ; Finstructure ; Structure Compte Ncpt: entier; nom: chaine ; DtOuverture : Date ; Finstructure ; Où « DtOuverture » est une variable structure de type « Date », champ de la structure « Compte ». Donc, la structure « Date » est déclarée obligatoirement avant la structure « Compte ». Lorsqu'un champ d'une structure est lui-même une structure, l’accès à ce champ se fait comme suit : variable_structure.variable_sous_structure.champ Par exemple : c.DtOuverture.annee ← 2019 ; affecte la valeur 2019 au champ année de l’enregistrement « DtOuverture » qui est lui-même un champ de l’enregistrement « c ». Tel que « c » est une variable de type « Compte ». Dans le cas d'un tableau, l'accès se fait comme suit : nom_tableau[indice].variable_sous_structure.champ Par exemple : T[i].DtOuverture.annee ← 2019 ; Où T[i] fait référence au ième élément du tableau T de type « Compte ». 6. Conclusion Nous avons vu dans le cinquième chapitre que les tableaux sont très pratiques, cependant ils ne permettent pas de répondre à tous les besoins de stockage tels que le regroupement de plusieurs données de types différents en un seul objet. A cet effet, la notion de structure (ou d’enregistrement) abordée dans le présent chapitre permet de pallier ce problème en créant un nouveau type permettant le stockage des données de types différents ou non. Un enregistrement qui est composé de plusieurs champs où chaque champ correspond à une donnée, constitue la brique de base pour les structures de données telles que les listes, les piles et les files qui ne font pas l’objet d’étude dans ce polycopié. - 42 - Chapitre 7 - Les fonctions et les procédures Chapitre 7 - Les fonctions et les procédures 1. Introduction La fiabilité, la lisibilité et la réutilisabilité des programmes, reposent sur l’utilisation des sous-programmes. Ces derniers permettent : - La réduction de la taille des programmes : il est possible de déterminer les blocs analogues, les substituer par un sous-programme, ensuite l’appeler dans des points déterminés au niveau du programme principal. - L’organisation du code : le problème initial peut être découpé en sous-problèmes (modules) où chacun sera résolu par un sous-programme. Exemple : Codage en base b Un entier positif en base b est représenté par une suite de chiffres (c n cn−1... c1c0)b où les ci sont des chiffres de la base b (0 ≤ ci < b). L’équivalent décimal de ce nombre est : cnbn + cn-1bn-1 + … + c1b1 + c0b0 = ∑𝑛𝑖=0 𝑐𝑖 𝑏𝑖 On suppose que le nombre x est représenté par un tableau de chiffres (code) en base b ; par exemple si b = 2 et code = [1,0,1], alors en base 10 le nombre entier x correspondant vaudra 1×22 + 0×21 + 1×20 = 4+0+1 = 5. Etant donné code et b, l’algorithme qui permet de calculer x en base 10 est le suivant : x←0; Pour i de 0 à L-1 // L est la longueur du code x ← x + code[i]*b^(L-1-i); Supposons que l’on veut calculer successivement la valeur décimale x des nombres (123)5 et (123)8, on devra donc recopier deux fois l’algorithme ci-dessus. b←5; b←8; code ← [1,2,3] ; code ← [1,2,3] ; x←0; x←0; Pour i de 0 à L-1 Pour i de 0 à L-1 x ← x + code[i]*b^(l-1-i); x ← x + code[i]*b^(l-1-i); - 43 - Chapitre 7 - Les fonctions et les procédures Dans la pratique, il n’est pas souhaitable d’écrire deux fois le même programme, d’autant plus, si celui-ci nécessite de très nombreuses lignes de code source. Pour améliorer la réutilisabilité de l’algorithme la solution est d’encapsuler le code à répéter au sein d’un sous- programme. 2. La notion de sous-programme Un sous-programme est une portion de code analogue à un programme, destiné à réaliser une certaine tâche à l’intérieur d’un autre programme. Il est identifié par un nom unique et un bloc d’instructions qui peut être exécuté plusieurs fois par des appels. Un appel est une instruction qui fait partie d’un autre programme ou sous-programme appelé le (sous-) programme appelant. Pour résumer, un sous-programme est utilisé pour deux raisons essentielles : - Lorsqu’une tâche est répétée plusieurs fois : on écrit un sous-programme pour cette tâche et l’on appelle à chaque endroit où l’on en a besoin c.à.d. on évite de réécrire le même code à plusieurs endroits dans le même programme. - Pour réaliser la structuration d’un problème en sous-problèmes : on divise le problème en sous-problèmes pour mieux le contrôler (diviser pour régner). Il existe deux types de sous-programmes : les fonctions et les procédures. Cependant, avant de détailler ces deux concepts, il sera utile de définir quelques notions utiles. 2.1. La portée d’une variable Dans cette sous-section, nous illustrons une notion appelée portée d’une variable. L'idée principale est qu'il est possible d'avoir deux variables différentes avec le même nom toutefois qu'elles ont des portées différentes. Le cas le plus connus que l'on peut citer, est qu'une variable définie au niveau du programme principal (celui qui résout le problème initial) est appelée variable globale et sa portée est totale, par conséquent, tout sous-programme du programme principal peut utiliser cette variable. Alors qu'une variable définie au sein d'un sous-programme est appelée variable locale dont la portée est limitée au sous-programme dans lequel elle est déclarée. Remarque : Si l’identificateur (le nom) d'une variable locale est identique à celui d’une variable globale, cette dernière est localement masquée. Autrement dit, la variable globale devient inaccessible dans le sous-programme contenant la variable locale de même nom. - 44 - Chapitre 7 - Les fonctions et les procédures Exemple : Supposons qu’une partie de notre programme sera le sous-programme suivant : Algorithme Secondaire ; Var x : entier ; // variable locale Début x←3; Ecrire (x, y) ; Fin Supposons maintenant que nous appelons ce sous-programme « Secondaire » depuis une autre partie du programme « Principal » qui utilise également deux variables globales : Algorithme Principal ; Var x, y : entier ; // variables globales Début x←5;y←8; … ; // Appel au sous-programme Secondaire Ecrire (x, y) ; Fin L’exécution de ce programme peut être illustrée comme suit : Programme Espace mémoire Résultat d’affichage -Principal Début Appel au sous- … programme 5,8 x=5 … Fin y=8 -Secondaire x=3 Début 3,8 … Fin Dans cet exemple, la variable « x », ayant la valeur 5 dans le programme principal, est une variable globale. Une autre variable qui porte le même nom « x » est utilisée au niveau du programme secondaire ayant comme valeur 3. Cet variable locale a masqué la variable globale « x » au niveau du programme secondaire, par conséquent, l’affichage de « x » au niveau de ce sous-programme correspond à la valeur 3. Par contre, la variable globale y est quant à elle accessible, ce qui justifie l’affichage de la valeur 8 au niveau du sous- programme. - 45 - Chapitre 7 - Les fonctions et les procédures 2.2. Les paramètres Les paramètres d'un sous-programme sont un ensemble de variables locales (paramètres formels) associées à un ensemble de variables ou constantes du (sous-) programme appelant (paramètres effectifs). Remarque : - Un paramètre est une variable locale, donc il admet un type. - L’appel d’un sous-programme possédant un ou plusieurs paramètres, implique une association entre ces paramètres et les paramètres effectifs du programme (ou sous- programme) appelant, respectivement de même type. Par exemple, si le sous-programme Racine permet de calculer la racine carrée d'un réel : - Ce sous-programme admet un seul paramètre de type réel positif. - Le programme appelant Racine doit fournir le réel positif dont il veut calculer la racine carrée, cela peut être une variable (Racine (y)) ou une constante (Racine (9)). 2.3. Le passage de paramètres L'association entre les paramètres effectifs et les paramètres formels est appelé passage de paramètres. Il existe deux types de passage de paramètres : - Le passage par valeur. - Le passage par référence (ou adresse). Dans le premier type, la valeur du paramètre effectif est affectée (copiée) au paramètre formel correspondant. Sachant que les paramètres formels ne sont que des variables locales de la fonction. Ce type de passage sera illustré dans la section qui suit. Dans le second type, c’est l’adresse du paramètre effectif qui est affectée au paramètre formel correspondant. Ceci rend possible au sous-programme d’accéder directement à l’adresse de la variable concernée (le paramètre effectif) et par conséquent la modifier si nécessaire. Ce type de passage nécessite d’utiliser la notion des pointeurs. Remarque : Une illustration du passage de paramètre par valeur est donnée dans l’exemple 3 de la section 4. Le passage de paramètre par adresse sera illustré dans le chapitre suivant. 3. Les fonctions Une fonction est un sous-programme qui admet un nom, un type et des paramètres. Une fonction admet un type et retourne toujours un résultat. - 46 - Chapitre 7 - Les fonctions et les procédures 3.1. Définition d’une fonction On définit une fonction comme suit : Fonction nom_fonction (paramètres : types) : type de la valeur retournée Var var1, var2,…: types; // variables_locales Début instructions de la fonction ; Retourner (résultat) ; // (au moins une fois) Fin Où : Les paramètres sont en nombre fixe (n≥0) Le type de la valeur retournée est le type de la fonction. La valeur de retour (ou le résultat) est spécifiée par l'instruction Retourner. 3.2. Appel d’une fonction On fait appel à une fonction comme suit : var ← nom_fonction (paramètres) ; Où les paramètres d’appel peuvent être des variables, des constantes ou même des résultats d’une autre fonction. Remarque : A la définition ou à l’appel d’une fonction, les parenthèses sont toujours présentes même lorsqu'il n'y a pas de paramètres. Exemple 1 : Soit l’algorithme A qui calcule la valeur absolue d’un entier en utilisant une fonction : Algorithme A ; Var a, b : entier ; Fonction Abs (n : entier) : entier Var valabs : entier Début Si (n >= 0) alors valabs ← n ; Sinon valabs ← -n ; FinSi Retourner valabs ; Fin Passage de paramètre par valeur : la valeur de la variable a est copiée dans la variable n. Début Ecrire (" Donner une valeur ") ; Lire (a) ; b ← Abs(a) ; Ecrire (b) ; Fin - 47 - Chapitre 7 - Les fonctions et les procédures Lors de l’exécution de la fonction Abs(), il y a une association entre le paramètre effectif a et le paramètre formel n d’où la valeur de a est copiée dans n. Ce type d’association s’appelle passage de paramètre par valeur. 4. Les procédures Une procédure est un sous-programme qui admet également un nom et des paramètres mais ne retournant aucun résultat. 4.1. Définition d’une procédure On définit une procédure comme suit : Procédure nom_procédure (paramètres : types) Var var1, var2,…: types; // variables_locales Début instructions de la procédure ; Fin 4.2. Appel d’une procédure L’appel d’une procédure se fait comme suit : nom_procédure (paramètres) ; Exemple 2 : Soit l’algorithme B calculant la valeur absolue d’un entier mais cette fois-ci en utilisant une procédure : Algorithme B ; Var a : entier ; Procédure Abs (n : entier) Début Si (n >= 0) alors Ecrire n ; Sinon Ecrire -n ; FinSi Fin Début Ecrire (" Donner une valeur ") ; Lire (a) ; Abs(a) ; Fin - 48 - Chapitre 7 - Les fonctions et les procédures Exemple 3 : Soit un algorithme utilisant une procédure comme suit : Algorithme C ; Var x : entier ; Procédure Modif (x : entier) Début x ← x + 1 ; Fin Début x←1; Ecrire ("Valeur de x avant l’appel :", x) ; Modif (x) ; Ecrire ("Valeur de x après l’appel :", x) ; Fin L’exécution de l’algorithme C peut être illustrée comme suit : Programme Espace mémoire Résultat d’affichage Algorithme C x 1 Début Valeur de x avant l’appel : 1 x←1; Ecrire (…) ; Valeur de x après l’appel : 1 Modif (x) ; Ecrire (…) ; Fin Appel avec passage de paramètre par valeur Procédure Modif() x 12 Début x←x+1; Fin Lorsqu’on passe un paramètre à une fonction (ou à une procédure), cette dernière ne peut pas modifier la variable. La variable est automatiquement recopiée et la fonction travaille sur une copie de la variable. La modification de la copie n’entraîne pas une modification de la variable originale. C’est ce qu’on appelle le passage de paramètre par valeur. - 49 - Chapitre 7 - Les fonctions et les procédures 5. Fonctions et procédures récursives La récursivité est une méthode de description d’algorithmes qui permet à une fonction (ou procédure) de s’appeler elle-même directement ou indirectement. 5.1. Exemple illustratif On peut définir la factorielle d’un nombre N non négatif de deux manières : Définition non récursive : N ! = N * N-1 * …* 2 * 1 Définition récursive : N ! = N * (N – 1) ! et 0 ! = 1 Par conséquent, deux solutions sont possibles pour le calcul de la factorielle. a) Solution itérative : Fonction FACT ( n : entier ) : entier Var i, F: entier ; Début Si (n = 0) alors F ← 1 ; Sinon F←1; Pour i de 2 à n F ← F * i; Finpour Retourner F; Finsi Fin b) Solution récursive : Fonction FACT ( n : entier ) : entier Début Si (n=0) alors Retourner 1 ; Sinon Retourner n * fact (n-1) ; // Appel récursif de la fonction FACT Finsi Fin 5.2. Interprétation Une procédure ou une fonction récursive doit comporter une condition d’arrêt (n=0 dans l’exemple étudié ci-dessus). Cette condition empêche des appels récursifs sans arrêt. Généralement, la condition d’arrêt se présente sous la forme d’une instruction « Si… - 50 - Chapitre 7 - Les fonctions et les procédures Alors…Sinon » qui permet de stopper la récurrence si la condition d’arrêt est satisfaite. Dans le cas contraire, la fonction ou la procédure continue à exécuter les appels récursifs. D’autre part, le paramètre de l’appel récursif doit converger toujours vers la condition d’arrêt. Un processus récursif remplace en quelque sorte une boucle, ainsi tout processus récursif peut être également formulé en tant qu’un processus itératif. 5.3. Mécanisme de fonctionnement Considérons, à titre d’exemple, le calcul de la factorielle de 4 en appliquant la fonction récursive FACT(). Pour calculer FACT(4), il faut calculer FACT(3). Pour calculer FACT(3), il faut calculer FACT(2). Pour calculer FACT(2), il faut calculer FACT(1). Pour calculer FACT(1), il faut connaître FACT(0), ce dernier vaut 1. Ensuite, on revient à rebours pour terminer le calcul pour 1, 2, 3 puis 4. Il y a donc autant d’occurrences de paramètre n et d’appel récursif que de niveaux de récursivité. A chaque niveau, un nouvel environnement, comprenant les paramètres et les variables locales de la fonction, est créé. Cette gestion des variables est invisible à l’utilisateur et effectuée automatiquement par le système si le langage admet la récursivité. Une illustration de ce mécanisme est donnée dans la figure 6. FACT(4) = 24 Si (4=0) alors … Sinon Retourner 4 * FACT (3) ; 6 Si (3=0) alors … Sinon Retourner 3 * FACT (2) ; 2 Si (2=0) alors … Sinon Retourner 2 * FACT (1) ; 1 Si (1=0) alors … Sinon Retourner 1 * FACT (0) ; 1 Si (0=0) alors Retourner 1 ; 6. Conclusion Figure 7. Calcul de la factorielle par récursivité. - 51 - Chapitre 7 - Les fonctions et les procédures 6. Conclusion La notion du sous-programme est très importante en programmation. Elle résulte de la décomposition du programme initial en de plus petites unités ou parties réutilisables qui sont ensuite appelées le moment opportun par le programme principal. Un sous-programme évite la répétition inutile de code et permet de clarifier le programme. En algorithmique, un sous- programme correspond à une fonction ou à une procédure dont la description et le mécanisme de fonctionnement sont présentés plus haut dans ce chapitre. Aussi, une initiation à la notion de récursivité, une des outils puissants de la programmation, a été donnée à la fin de ce chapitre. Le prochain chapitre traite l’un des concepts utiles et indispensables au passage de paramètres par adresse (ou référence), c’est le concept de pointeur. - 52 - Chapitre 8 - Les pointeurs Chapitre 8 - Les pointeurs 1. Introduction Lorsqu’une variable est déclarée et ce, quel que soit le langage de programmation, le compilateur réserve, à une adresse donnée en mémoire, l’espace nécessaire au contenu de cette variable. Donc, toute variable possède : - Un identificateur (nom), - Une valeur (donnée), - Une adresse en mémoire. Une donnée peut s’étaler sur plusieurs octets, donc occuper une plage d’adresses (par exemple 2 octets pour un entier, 4 ou 8 octets pour un réel, plus encore pour une chaîne). Exemple : Var n : entier ; // déclaration d’un entier (sur 2 octets) n ← 5 ; // affectation de la valeur 5 à n Dans cet exemple, le nom de la variable c’est n, la valeur c’est 5 et l’adresse c’est son emplacement dans la mémoire. Espace réservée à l’entier n pour stocker sa valeur 5 Variable n Figure 8. Représentation d’une variable en mémoire. On peut donc accéder à une variable de deux façons : par son identificateur, par l'adresse mémoire à partir de laquelle elle est stockée (pointeur). - 53 - Chapitre 8 - Les pointeurs 2. Notion de pointeur 2.1. Définition Un pointeur est une variable qui contient l’adresse d’une autre variable. Le pointeur pointe sur une autre variable dont il contient l’adresse mémoire, cette dernière étant dite variable pointée. Si l’on affiche le contenu d’un pointeur, on obtient une adresse qui est celle de la variable pointée, tandis que si l’on affiche le contenu de la variable pointée, on obtient la valeur associée à cette dernière. Un pointeur est une variable. De ce fait, elle doit être déclarée, dispose elle-même de sa propre adresse en mémoire, et se voit définir un type. Le type d’un pointeur ne décrit pas ce qu’il contient (c’est une adresse, donc en principe d’une longueur de 32 ou 64 bits selon les architectures) mais le type de la variable qu’il pointe. Un pointeur sur une variable de type réel devrait donc être déclaré avec un type réel. Pointeur p 5 Variable n Figure 9. Le pointeur et la variable pointée en mémoire. Dans ce qui suit, nous décrivons comment déclarer et manipuler un pointeur avec quelques cas d’applications par la suite. 2.2. Opérations sur les pointeurs 2.2.1. Déclaration En algorithmique, un pointeur est déclaré comme suit : nom_pointeur : pointeur sur type ; ou nom_pointeur : *type ; // où type est le type de l’élément pointé. Dans ce qui suit, nous utilisons la deuxième syntaxe qui est plus proche du langage C. - 54 - Chapitre 8 - Les pointeurs Par exemple : p : *entier ; // p est un pointeur vers un entier (il contient l’adresse d’un entier) 2.2.2. Initialisation Lorsqu’un pointeur ne pointe aucune variable, il faut l’initialiser avec la constante symbolique NIL. Un pointeur non initialisé pointe n’importe quoi dans la mémoire. Par exemple : p : *entier ; p ← NIL ; // p est un pointeur qui ne pointe rien 2.2.3. Accès aux données L’accès aux données se fait en utilisant les deux opérateurs suivants : * : opérateur unaire qui permet de déréférencer un pointeur (accéder directement à la valeur de l’objet pointé). & : opérateur unaire permettant d’obtenir l’adresse d’une variable. Il convient de noter que ces opérateurs sont les mêmes utilisés en langage C, d’autres opérateurs peuvent être rencontrés par le lecteur tels que ^ et @ en Pascal à titre d’exemple. Exemple : Algorithme Exemple_pointeur ; Var x : entier ; p1, p2 : *entier ; Début x←3; p1 ← &x ; // p1 contient l’adresse de x p2 ← NIL ; // p2 ne contient aucune adresse Ecrire ("Le contenu de la variable pointé par p1 est :", *p1) ; *p1 ← 5 ; // modification de x à travers p1 Ecrire ("x=", x, "*p1=", *p1) ; p2 ← p1 ; // affectation de l’adresse contenue dans p1 à p2 Ecrire ("Le contenu de la variable pointé par p2 est :", *p2) ; Fin L’exécution de cet algorithme donne : Le contenu de la variable pointé par p1 est : 3 x=5 , *p1=5 Le contenu de la variable pointé par p2 est : 5 - 55 - Chapitre 8 - Les pointeurs Remarque : Avant toute utilisation, un pointeur doit être initialisé : par la valeur générique NIL, par exemple p ← NIL ; par l'affectation de l'adresse d'une autre variable, par exemple p ← &v; par allocation dynamique d'un nouvel espace-mémoire. 3. Allocation dynamique Nous avons vu dans la section précédente qu’un pointeur reçoit l’adresse d’une variable qui existe déjà par affectation. Il est aussi possible de réserver un emplacement mémoire pour une donnée pointée directement. Dans ce cas, on peut créer un pointeur sur un entier par exemple, et réserver un espace mémoire (qui contiendra cet entier) sur lequel la variable pointeur pointera. C’est le principe de l’allocation dynamique de mémoire. On peut employer la syntaxe suivante : pointeur ← nouveau type ; Le type doit bien entendu être celui de la valeur qui sera contenue à l’emplacement mémoire alloué. Après cette instruction, le pointeur reçoit l’adresse mémoire de la zone réservée. En cas d’échec (plus de mémoire disponible par exemple) il reçoit la valeur NIL. Exemple : Dans l’algorithme qui suit, un pointeur « p » sur un entier est déclaré. Pour placer une valeur entière dans la zone mémoire pointée, il faut d’abord réserver l’emplacement nécessaire. Puis on accède à l’élément pointé et on y place un entier. Algorithme allouer ; Var p : *entier Début p ← nouveau Entier ; // allocation d’un espace mémoire dont l’adresse est affectée à p *p ← 12345 ; // affectation d’un entier Ecrire ("Le contenu de p est :", *p) ; Fin Quand une zone mémoire est allouée dynamiquement, elle reste occupée tout le temps de l’existence du pointeur. Sans rien d’autre, la mémoire est récupérée uniquement à la sortie du programme. Il est aussi facile de libérer un espace alloué de la mémoire dès que le ou les pointeurs ne sont plus utiles. Pour ceci on applique la syntaxe suivante : Libérer pointeur ; - 56 - Chapitre 8 - Les pointeurs Exemple : Dans l’algorithme qui suit, un pointeur « p » sur un entier est déclaré. Pour placer une valeur entière dans la zone mémoire pointée, il faut d’abord réserver l’emplacement nécessaire. Puis on accède à l’élément pointé et on y place un entier. Algorithme libérer ; Var p : *entier Début p ← nouveau Entier ; *p ← 12345 ; Ecrire ("Le contenu de p est :", *p) ; Libérer p ; // libérer l’espace mémoire pointé par p p ← NIL ; // réinitialiser p Fin Quand on libère un pointeur, on libère la zone mémoire sur laquelle il pointait, cette zone redevient disponible pour toute autre utilisation. Après chaque libération, il est préférable de réinitialiser le pointeur par la valeur NIL, et de penser à tester le pointeur avant de l’utiliser. Dans le cas où l’adresse de la zone mémoire libérée est conservée dans un autre pointeur, il faut faire attention au fait que ce pointeur pointe sur une zone éventuellement réaffectée à autre chose. Y accéder risque de fournir une valeur arbitraire, y écrire risque d’occasionner des problèmes, voire des plantages. 4. Application des pointeurs Les applications des pointeurs sont nombreuses, à titre d’exemple en langage C : - Une fonction ne peut pas retourner plus d’une valeur, un tableau ou un enregistrement. En utilisant un pointeur, ceci est possible en retournant l’adresse de l’ensemble ou de la structure des données à travers un pointeur. - Les tableaux se manipulent très facilement via des pointeurs, puisqu’il est possible de faire des calculs sur les adresses : +1 va au contenu de l’adresse suivante, et ainsi de suite. - Les pointeurs offrent la possibilité d’utiliser des structures de données plus complexes telles que listes chainées, les arbres, etc. - Le passage de paramètres par adresse n’est possible aussi que par l’utilisation des pointeurs où un sous-programme peut modifier le contenu d’une case mémoire à l’adresse passée via un pointeur (voir l’exemple suivant). - 57 - Chapitre 8 - Les pointeurs Exemple : Nous reprenons dans ce qui suit le même exemple vu dans le chapitre précédent concernant le passage de paramètres en utilisant le deuxième mode : passage par adresse. Algorithme D ; Var x : entier ; Procédure Modif (px : *entier) // Procédure utilisant un pointeur comme paramètre local Début *px ← *px + 1 ; // le contenu pointé par px est modifié Fin Passage de paramètre par adresse : l’adresse de la variable x est affectée au pointeur px. Début x←1; Ecrire ("Valeur de x avant l’appel :", x) ; Modif (&x) ; Ecrire ("Valeur de x après l’appel :", x) ; Fin L’exécution de l’algorithme D peut être illustrée comme suit : Programme Espace mémoire Résultat d’affichage Algorithme D Début x 12 x←1; Valeur de x avant l’appel : 1 Ecrire (…) ; Modif (&x) ; Valeur de x après l’appel : 2 Ecrire (…) ; Fin Appel avec passage de paramètre par adresse Procédure Modif() Début px (&x) *px ←*px + 1 ; Fin Lorsqu’on passe l’adresse d’une variable à une fonction (ou à une procédure), cette dernière peut modifier directement cette variable à travers le pointeur contenant son adresse. Donc l’accès au contenu pointé (*px) est équivalent à l’accès à la variable (x) dans ce cas. La modification se fait directement sur la variable originale. C’est le passage de paramètre par adresse. - 58 - Chapitre 8 - Les pointeurs 5. Conclusion Dans ce dernier chapitre de la partie « cours », nous avons présenté la notion des pointeurs avec des exemples sur leur utilisation. Le lecteur est initié aussi au mécanisme de gestion dynamique de mémoire à travers les opérations d’allocation et de libération. A la fin de ce chapitre, un survol sur les principales applications des pointeurs notamment en langage C a été présenté dans lequel le mode de passage de paramètres par adresse a été pris comme exemple d’application. - 59 - Partie II - Exercices corrigés - 60 - Exercices Série 1 : Initiation aux algorithmes Exercice 1 Soit l’algorithme suivant : Algorithme A ; Var a, b, c : entier ; Début a5 ; ba+1 ; ca+b ; Fin a) Expliquer chaque ligne, mot et symbole dans cet algorithme. b) Sur la base de cette explication, ajouter des commentaires à cet algorithme. c) A quoi servent ces commentaires ? Est-ce qu’ils sont obligatoires ? d) Dérouler l’algorithme et donner les valeurs des variables a, b et c. Exercice 2 Soit l’algorithme suivant : Algorithme B ; Var a, b, c, d : entier ; Début Ecrire (″Donner a et b″) ; Lire (a, b) ; ca+b ; da*b ; Ecrire (c, d) ; Fin a) Que fait cet algorithme ? b) Dérouler l’algorithme pour a=5 et b=6. c) Même question pour a=6 et b=5. - 61 - Exercices Exercice 3 Soit l’algorithme suivant : Algorithme C ; Var x,y :entier ; Début Ecrire (Donner x, y) ; Lire (x,y) ; x y+1 ; z z+x ; Ecrire (‘x,z’) ; Fin a) Corriger l’algorithme s’il y a des erreurs. b) Dérouler l’algorithme pour x=9 et y=3. Exercice 4 Soit l’algorithme suivant : Algorithme D ; Var a, b, c : entier ; Début Ecrire (donner a et b) ; Lire (‘a, b’) ; ca*a ; db*b ; Ecrire (c, d) ; Fin a) L’algorithme contient-il des erreurs ? b) Dérouler l’algorithme pour a=5 et b=7 et déduire qu’est-ce qu’il fait. Exercice 5 Corriger l’algorithme suivant, s’il le faut, et donner son résultat : Algorithme A ; Var x, y, z, s : entier ; Début x ← 10 ; y ← 15 ; - 62 - Exercices z ← 20 ; m ← (x + y + z) / 2 ; Ecrire (m) ; Ecrire (x + y + z / 2) ; Fin Exercice 6 a) Quel résultat produira-t-il le déroulement de l’algorithme suivant ? Algorithme B ; Var val, double, triple : entier ; Début val ← 1000 ; double ← val * 2 ; triple ← val * 3 ; Ecrire val ; Ecrire double ; Ecrire triple ; Fin b) Proposer une simplification de cet algorithme en produisant le même résultat. Exercice 7 Supposons que l’on veut afficher à l’écran de l’utilisateur le message « Bonjour à tous ». a) Essayer d’écrire l’algorithme correspondant. b) Quelle est la sortie (output) de cet algorithme ? et l’entrée (input) ? c) Quelles sont les instructions à utiliser pour manipuler les entrées (et les sorties) d’un algorithme ? d) Reformuler votre algorithme pour qu’il y ait une entrée et une sortie. - 63 - Exercices Série 2 : Instructions algorithmiques de base Exercice 1 a. Ecrire un algorithme qui permet de lire un nombre (donné par l’utilisateur), puis il calcule et affiche son carré. b. Même question pour calculer et afficher le cube, ensuite l’inverse de ce nombre. Exercice 2 a. Ecrire un algorithme qui permet de lire les notes de trois matières ensuite il calcule et affiche leur moyenne. b. Modifier l’algorithme dans le cas où les matières ont des coefficients qui doivent être donnés avec les notes. Exercice 3 Ecrire un algorithme qui permet de lire deux variables numériques a et b et de les afficher avant et après leur permutation. Par exemple, avant : a=5 et b=7, après : a=7 et b=5. Exercice 4 Proposer un algorithme qui réalise la permutation de deux variables numériques sans avoir utiliser une troisième variable. - 64 - Exercices Série 3 : Les instructions conditionnelles Exercice 1 Ecrire un algorithme qui permet d’afficher la valeur absolue d’un nombre donné. Exercice 2 Ecrire un algorithme qui permet de déterminer si un entier donné est pair ou impair. Exercice 3 Ecrire un algorithme qui demande trois lettres à l’utilisateur, et l’informe ensuite si leur ordre de lecture et le même que l’ordre alphabétique. Exercice 4 a) Écrire un algorithme qui lit trois variables au clavier et affiche le maximum des trois. b) Même question pour plus de trois variables. Exercice 5 a) Ecrire un algorithme qui demande deux nombres à l’utilisateur et l’informe ensuite si leur produit est négatif ou positif mais sans le calculer. (On laisse de côté le cas où le produit est nul). b) Même question en incluant cette fois-ci le cas où le produit peut être nul. Exercice 6 Ecrire un algorithme qui permet de lire un numéro du jour de la semaine (numéro entre 1 et 7) et d’afficher le nom du jour correspondant. Par exemple, le dimanche correspond au numéro 1. - 65 - Exercices Série 4 : Les instructions itératives Exercice 1 Donner les affichages produits par l'exécution des algorithmes suivants : Algorithme 1 : Var i : entier ; Début Pour i←2 à 8 Écrire (''Bonjour'') ; Écrire (i) ; Fin pour Écrire (''fin'') ; Fin Algorithme 2 : Var encore : booléen ; Début encore ← Vrai ; Répéter Écrire (''Bonjour'') ; Jusqu'à (encore) Écrire (''fin'') ; Fin Algorithme 3 : Var encore : booléen ; Début encore ← Faux ; Tant que (encore) faire Écrire (''Salut'') ; Fin tant que Écrire (''fin'') ; Fin - 66 - Exercices Exercice 2 Ecrire l’algorithme qui affiche la somme des prix d'une suite d'articles saisie par l'utilisateur et se terminant par zéro (Justifier le choix de la boucle à utiliser). Exercice 3 a) Ecrire l’algorithme qui demande un entier, ensuite il affiche les dix entiers suivants. Par exemple, si l’on entre le nombre 10, l’algorithme affichera les nombres 11, 12,…, 20, 21. b) Modifier l’algorithme pour qu’il affiche les dix nombres pairs suivants. Exercice 4 a) Ecrire l’algorithme qui demande un nombre entier n, ensuite il affiche la somme des entiers positifs jusqu’à n. Par exemple, si n=5, l’algorithme affiche : 1 + 2 + 3 + 4 + 5 = 15 b) Réécrire le même algorithme mais cette fois ci pour le calcul d’un produit. Par exemple, pour n=5, l’algorithme affiche : 1 x 2 x 3 x 4 x 5 = 120 Remarque. On souhaite afficher uniquement le résultat sans la décomposition du calcul. Exercice 5 Ecrire un algorithme qui permet de calculer la factorielle d’un entier (qui doit être positif). Où n! = n x (n-1) x (n-2) x … x 1, si n ≥ 1 et n! = 1 si n = 0. Exercice 6 a) Ecrire un algorithme qui demande successivement dix nombres à l’utilisateur, ensuite il affiche le plus petit parmi eux (le minimum). Exemple : Entrer le nombre numéro 1 : 12 Entrer le nombre numéro 2 : 3... (on suppose que les autres nombres sont ≥ 3) Entrer le nombre numéro 10 : 6 Résultat : Le minimum est : 3 b) Modifier l’algorithme pour qu’il affiche, en plus, la position de ce nombre. Pour l’exemple précédent, le minimum se trouve à la position : 2 - 67 - Exercices c) Réécrire l’algorithme précédent dans le cas où l’on ne connaît pas à l’avance combien de nombres l’utilisateur souhaite saisir, mais la saisie des nombres s’arrête lorsque l’utilisateur entre un zéro. Exercice 7 Ecrire un algorithme qui demande un nombre puis vérifier si ce nombre est premier ou non Exercice 8 a) Supposons que le code pin d’un utilisateur est 5454. Ecrire un algorithme qui demande à cet utilisateur de saisir son code pin jusqu’à ce que la réponse convienne. b) Ajouter une condition qui annule la saisie après trois tentatives erronées. - 68 - Exercices Série 5 : Les tableaux et les structures Exercice 1 a) Ecrire un algorithme qui permet de lire 10 valeurs données par l’utilisateur en les stockant dans un tableau, ensuite l’algorithme doit afficher seulement les valeurs impaires. b) Modifier l’algorithme (a) pour que le nombre de valeurs soit donné par l’utilisateur. c) Réécrire l’algorithme (b) en divisant cette fois-ci le tableau initial en deux tableaux, l’un contenant les valeurs paires et l’autre contenant les valeurs impaires, et en les affichant par la suite. Exercice 2 a) Soit un tableau de 10 éléments réels, écrire un algorithme qui permet de lire ce tableau et rechercher le maximum des éléments ainsi que sa position, ensuite l’afficher. b) Même question pour un tableau de 10 lignes et 5 colonnes. Exercice 3 Ecrire un algorithme qui permet de rechercher une valeur numérique saisie par l’utilisateur dans une matrice de taille N*M (N et M sont données). Exercice 4 Ecrire l’algorithme qui permet de compter le nombre d’occurrences d’un élément donné dans une matrice de taille N*M. Exercice 5 Définir une structure Rationnel permettant de coder un nombre rationnel, avec numérateur et dénominateur. Ecrire ensuite l’algorithme qui permet la saisie, l ’ affichage, la multiplication et l’addition de deux rationnels. Pour l’addition, afin de simplifier, on ne cherchera pas nécessairement le plus petit dénominateur commun. Exercice 6 Soit une structure Compte qui code un compte bancaire défini par un numéro, nom et prénom et date d’ouverture. Donner la définition des structures nécessaires. Ecrire ensuite l’algorithme qui permet de saisir un tableau de N comptes et de l’afficher. - 69 - Exercices Série 6 : Les fonctions et les procédures Exercice 1 Supposons qu’on veut écrire un sous-programme MoySom qui prend en paramètres trois entiers a, b et c, et qui affiche leur somme et renvoie leur moyenne. Quelle est la déclaration correspondante ? - Fonction MoySom (a : entier, b: entier, c: entier) : entier ; - Fonction MoySom (a : entier, b: entier, c: entier) : réel ; - Procédure MoySom (a : entier, b: entier, c: entier, som: entier, moy: réel) ; - Fonction MoySom (a : entier, b: entier, c: entier) : entier, réel ; Justifier la réponse choisie. Exercice 2 a) Écrire deux fonctions Min et Max qui retournent le minimum et le maximum de deux nombres réels donnés comme paramètres. b) Écrire deux autres fonctions Min_4 et Max_4 utilisant les fonctions Min et Max pour retourner le minimum et le maximum de quatre nombres réels passés en paramètres. c) Incorporer ces fonctions dans un algorithme complet. Remarque : On suppose que tous les nombres donnés sont différents. Exercice 3 Ecrire un algorithme qui permet de lire une liste de N étudiants ayant comme informations : numéro, nom, prénoms et moyenne du bac. L’algorithme doit afficher cette liste triée par moyenne en ordre décroissant. Remarque : utiliser une fonction ou une procédure pour le tri. Exercice 4 Un magasin de vente des composants électroniques vend quatre types de produits : Des cartes mères (code 1) ; Des processeurs (code 2) ; Des barrettes de mémoire (code 3) ; Des cartes graphiques (code 4). - 70 - Exercices Chaque produit possède une référence (qui est un nombre entier), un prix en DA et une quantité disponible. a) Définir une structure Produit qui code un produit. b) Ecrire une fonction qui permet la saisie et l’affichage des données d’un produit. c) Ecrire une fonction qui permet à un utilisateur de saisir une commande d’un produit. L’utilisateur saisit la quantité commandée et les données du produit. L’ordinateur affiche toutes les données de la commande, y compris le prix. - 71 - Exercices Exercice de réflexion (sans correction) Exercice A : On se propose de réaliser une calculatrice qui permet de faire les opérations arithmétiques de base (+, -, * et /) de deux nombres a et b, ainsi que de savoir : - si la somme a + b est paire ; - si le produit a*b est pair ; - le signe de la somme a + b ; - le signe du produit a*b. Ecrire l’algorithme correspondant. Exercice B : On se propose de faire la rotation (décalage des positions) des éléments d’un tableau. 1. Proposer un algorithme pour ce problème sachant que le degré de rotation doit être défini par l’utilisateur. Exemple pour un degré de rotation égal à 2 : Avant rotation : 1,3,9,4,5,2 Après rotation : 5,2,1,3,9,4 2. Modifier l’algorithme pour que la rotation puisse être faite dans les deux sens (avant- arrière). Exercice C : Une société désire organiser un concours de recrutement en deux spécialités S1 et S2. Le concours se porte sur trois (03) matières : M1, M2 et M3. Un candidat est retenu si les conditions suivantes sont toutes remplies : - Il doit se classer parmi les dix (10) premiers, - Il ne doit pas avoir eu un zéro dans l’une des trois matières, - Sa spécialité doit correspondre à l’une des deux spécialités concernées. La note de classement est la moyenne des notes des trois matières. Ecrire l’algorithme qui permet de lire les informations nécessaires, de classer tous les candidats par ordre de mérite, ensuite afficher la liste des candidats retenus pour le recrutement. Exercice D : Une entreprise veut gérer la liste de ses employés en les stockant dans un tableau. Sachant que chaque employé possède comme information : un matricule, un nom et prénom, une date de naissance, une situation familiale et une adresse. Cette dernière est définie par un numéro, rue, ville et code postale. - 72 - Exercices 1. Donner la fonction ou la procédure qui permet de : - rechercher un employé par son matricule et afficher ses informations. - afficher les nom et prénoms des employés qui habitent une même ville donnée. 2. Ecrire l’algorithme qui permet de créer la liste des employés et de faire appel à ces fonctions (ou procédures). - 73 - Corrigés Corrigé série 1 Solution 1 : a) Algorithme A ; Var a, b, c : entier ; // déclaration des variables Début a← 5 ; // affectation de la valeur 5 à la variable a b← a+1 ; // affectation du résultat de a+1 à la variable b c← a+b ; // affectation de la somme de a et b à la variable c Fin b) Les commentaires dans un algorithme (ou programme) sont ajoutés à titre indicatif pour le rendre plus lisible et compréhensible mais ils ne sont pas obligatoires. c) Le résultat du déroulement de cet algorithme est comme suit : a=5 b=5+1=6 c=6+5=11 Solution 2 : a) L’algorithme calcule la somme et le produit de deux entiers b) C=5+6=11 c) D=5×6=30 Solution 3 : a) Algorithme C ; Var x,y :entier ; Const z =10 ; Début Ecrire ("donner x, y") ; Lire (x,y) ; x ← y+1 ; z ← z+x ; (z est une constante) Ecrire (’x,z’) ; Fin b) Déroulement de l’algorithme pour x=9 et y=3 x=3+1=4 Affichage : x=4, z=10 - 74 - Corrigés Solution 4 : a) Algorithme D ; Var a, b, c : entier ; Début Ecrire ("donner a et b") ; Lire (a, b) ; c← a ; a← b ; b← c ; Ecrire (a, b) ; Fin b) Déroulement de l’algorithme pour a=5 et b=7 c=5 a=7 b=5 Affichage : a=7 et b=5 Donc, l’algorithme réalise la permutation de a et b. Solution 5 : s : variable déclarée sans être utilisée m : doit être de type réel Affichage : 22.5 ; 35 Solution 6 : a) val=1000 ; double=2000 ; triple=3000 b) Simplification : Var val : entier ; Début val ← 1000 ; Ecrire (val, val*2, val*3) ; Fin - 75 - Corrigés Solution 7 : a) Algorithme Un_Bonjour ; Début Ecrire ("Bonjour à tous") ; Fin Cet algorithme n’a qu’une sortie, le message « Bonjour à tous ». b) Pour manipuler les entrées et les sorties d’un algorithme, on utilise respectivement les deux instructions : Lire() et Ecrire(). c) Algorithme Un_ReBonjour ; Var mge : chaine ; Début Ecrire ("Veuillez saisir un message :") ; Lire (mge) ; Ecrire (mge) ; Fin - 76 - Corrigés Corrigé série 2 Solution 1 : a) Algorithme carré ; Var nb, carr : réel ; Début Lire (nb) ; carr ← nb * nb ; // ou carr ← nb^2 Ecrire (carr) ; Fin b) Algorithme cube ; Var nb, cub : réel ; Début Lire (nb) ; cub ← cub ^ 3 Ecrire (cub) ; Fin Algorithme inverse ; Var nb, inv : réel ; Début Lire (nb) ; inv← 1/ nb ; // tel que nb ≠ 0 Ecrire (inv) ; Fin Solution 2 : a. Algorithme moyenneA ; Var n1, n2, n3, moy : réel ; Début Ecrire ("Donner trois notes :") ; // ce message est optionnel Lire (n1, n2, n3) ; moy ← (n1+n2+n3) / 3 ; Ecrire (moy) ; Fin - 77 - Corrigés b. Algorithme moyenneB ; Var n1, n2, n3, moy : réel ; c1, c2, c3 : entier ; Début Lire (n1, n2,n 3) ; Lire (c1, c2, c3) ; moy ← (n1*c1+n2*c2+n3*c3) / (c1+c2+c3) ; Ecrire (moy) ; Fin Solution 3 : Algorithme permutation ; Var a,b,c : réel ; Début Ecrire (″Entrer la valeur de a :″) ; Lire (a) ; Ecrire (″Entrer la valeur de b :″) ; Lire (b) ; Ecrire (″a=″,a) ; Ecrire (″b=″,b) ; c←a; La permutation est réalisée à travers ces trois affectations. a←b; La variable « c » est une variable temporaire qui doit être de même type que a et b. b←c; Ecrire (″a=″,a) ; Ecrire (″b=″,b) ; Fin Solution 4 : Algorithme permutation2 ; Var x, y : réel ; Début Lire (x,y) ; x←x+y; y←x-y; x←x-y ; Ecrire (x,y) ; Fin - 78 - Corrigés Corrigé série 3 Solution 1 : (L’écriture des entêtes d’algorithmes est omise dans quelques solutions) Var n : réel ; Début Ecrire ("Entrez un nombre : ") ; Lire (n) ; Si (n < 0) Alors n← -n ; FinSi Ecrire ("la valeur absolue est", n) ; Fin Solution 2 : Var n : entier ; Début Ecrire ("Entrez un nombre : ") ; Lire (n) ; Si (n mod 2 = 0) Alors Ecrire ("Ce nombre est pair") ; Sinon Ecrire ("Ce nombre est impair") ; FinSi Fin Solution 3 : Var a, b, c : caractère ; Début Ecrire ("Entrez successivement trois lettres : ") ; Lire (a, b, c) ; Si (a < b ET b < c) Alors Ecrire ("Les lettres sont classées alphabétiquement") ; Sinon Ecrire ("Les lettres ne sont pas classées") ; FinSi Fin Solution 4 : a) Var a, b, c, max ; Début Ecrire ("Entrez trois nombres réels : ") ; Lire (a, b, c) ; - 79 - Corrigés Si (a < b) Alors max ← b; Sinon max ← a; FinSi Si (max < c) Alors max ← c; FinSi Ecrire ("Le maximum des trois nombres est :", max); Fin Autre variante :... Lire (a, b, c) ; max ← a ; Si (max 0) OU (m < 0 ET n < 0)) Alors Ecrire ("Le produit est positif") ; Sinon Ecrire ("Le produit est négatif") ; FinSi Fin b) Var m, n : entier ; Début Ecrire ("Entrez deux nombres : ") ; Lire (m, n) ; Si (m = 0 OU n = 0) Alors Ecrire ("Le produit est nul") ; Sinon Si ((m < 0 ET n < 0) OU (m > 0 ET n > 0)) Alors Ecrire ("Le produit est positif") ; Sinon Ecrire ("Le produit est négatif") ; FinSi FinSi Fin - 80 - Corrigés Solution 6 : Var j : entier ; Début Ecrire ("Donner le numéro du jour :") ; Lire (j) ; Selon j 1 : Ecrire ("Dimanche") ; 2 : Ecrire ("Lundi") ; 3 : Ecrire ("Mardi") ; 4 : Ecrire ("Mercredi") ; 5 : Ecrire ("Jeudi") ; 6 : Ecrire ("Vendredi") ; 7 : Ecrire ("Samedi") ; Défaut : Ecrire ("Donner un numéro de jour valide (entre 1 et 7).") ; FinSelon Fin - 81 - Corrigés Corrigé série 4 Solution 1 : Algorithme 1 : Bonjour 2 Bonjour 3 Bonjour 4 Bonjour 5 Bonjour 6 Bonjour 7 Bonjour 8 Fin Algorithme 2 : Bonjour Fin Algorithme 3 : Fin Solution 2 : Var p, s : réel ; Début s←0; Répéter Ecrire ("Entrer le prix de l'article (0 si fin):"); Lire (p) ; s←s+p; Jusqu'à (p = 0) Ecrire (" La somme des prix des articles est ", s) ; Fin - 82 - Corrigés Puisque le nombre d’articles n’est pas connu à l’avance ainsi qu’il faut faire au moins une saisie pour terminer, la boucle « Répéter » est appliquée dans ce cas. Solution 3 : a) Var N, i : Entier ; Début Ecrire ("Entrer un entier : ") ; Lire (N) ; Ecrire ("Les 10 nombres suivants sont : ") Pour i de (N + 1) à (N + 10) Ecrire (i) ; FinPour Fin b) Pour le deuxième cas, il suffit de remplacer l’instruction : « Ecrire (i) » par « Si (i mod 2 = 0) Alors Ecrire i » dans la 6ème ligne. Solution 4 : (les instructions correspondantes à la question b sont mises en commentaires) Var N, i, som : Entier ; Début Ecrire ("Donner un entier : ") ; Lire (N) ; som ← 0 ; // prod← 1 ; Pour i de 1 à N som ← som + i ; // prod← prod * i ; FinPour Ecrire ("La somme = ", som ); // Ecrire ("Le produit = ", prod ); Fin Solution 5 : Var N, i, F : entier ; Début Ecrire ("Entrer un entier positif : ") ; Lire (N) ; Si (N1) faire Si (N>1) Alors N ← N-1 ; F←F*N; FinTq Fsi - 83 - Corrigés Pour i de 2 à N F←F*i; FinPour Fsi Ecrire ("La factorielle est ", F) ; Fsi Fin Solution 6 : a) et b) Var N, i, min, pmin : Entier ; Début min ← 0 ; // juste pour initialiser la var Pour i de 1 à 10 Ecrire ("Entrer le nombre numéro ", i) ; Lire (N) ; Si (i = 1 ou N < min) Alors min ← N ; pmin ← i ; FinSi FinPour Ecrire ("Le minimum est : ", min ); Ecrire ("Il a été saisi en position :", pmin) ; Fin c/ Var N, i, min, pmin : Entier ; Début i ← 1 ; min ← 0 ; Répéter Ecrire ("Entrer le nombre numéro ", i) ; Lire (N) ; Si (i = 1 ou N < min) Alors min ← N ; pmin ← i ; FinSi i←i+1; Jusqu’à (N=0) Ecrire ("Le minimum est ", min), Ecrire ("Il a été saisi en position numéro ", pmin), Fin - 84 - Corrigés Solution 7 : Algorithme nombre_premier Var i, N : entier ; x : booleen; Début Ecrire ("entrer N"); Lire(N); x ← faux; i ← 2; Tant que (i