2
MIC
2G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Ce que vous savez faire (1/2)
� Sur le plan algorithmique� Utiliser à bon escient les structures de contrôle
� Séquence
� Répétitions (boucles) � Structure « for … loop … end loop»
� Structure « while … loop … end loop»
� Structures de choix� Alternative : « if … then … else …end if »
� Choix multiple : « case … when … end case »
� Ecrire des algorithmes « classiques »� Parcourir un tableau
� Chercher la valeur min[max] du tableau (indiquer la 1ere place qui le contient)
� Trier un tableau
� Ecrire des sous-programmes déjà spécifiés� La fonctionnalité du sous-programme est définie
� Les paramètres du sous-programme sont fixés
3G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Ce que vous savez faire (2/2 )
� Sur le plan des structures de données� Utiliser des types simples� Utiliser des types composés
� Tableaux (array)
� Articles (record)
� Naviguer dans des structures composées� Tableaux d’articles, Articles contenant des tableaux,
� Matrices
� Tableaux de records, records de tableaux …
� …
� Sur le plan de la mise au point de programmes (en T P)� Utiliser l’environnement de programmation (Linux, Emacs, Gnat)� Mettre en œuvre une méthodologie de développement progressive
� écriture d’un sous-programme + sous-programmes de test
4G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Objectifs du module (1/2)
� Sur le plan algorithmique, vous serez capable de :
� Concevoir et formaliser des algorithmes complexes selon la méthode de l’analyse descendante
� Maîtriser la spécification et le développement de sous-programmes� Ecrire des algorithmes « classiques »
� Recherche du min (ou du max) dans un tableau ou une liste
� Recherche d’une valeur dans un tableau ou une liste
� Tri croissant ou décroissant d’un tableau (différents algorithmes)
� Mettre en œuvre une analyse récursive et concevoir des sous-programmes récursifs
� Travailler sur des structures de données dynamiques (listes basées sur des pointeurs)
� Insérer[Supprimer] un élément en tête[fin] de liste
5G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Objectifs du module (2/2)
� Sur le plan des structures de données, vous serez ca pable de :
� Maîtriser la déclaration et l’utilisation de tableaux notamment leur dimensionnement
� Définir des structures de données dynamiques en utilisant des pointeurs
� Choisir et concevoir les structures de données les mieux adaptées à un problème donné (suite au module du semestre 2)
� Sur le plan du développement de programmes en TP, v ous serez capable de :
� Mettre au point progressivement un programme répondant à un cahier des charges (analyse, conception, codage et tests)
� Réaliser les tests unitaires et fonctionnels
� Intégrer des données dans un programme à partir de saisies ou de fichiers textes.
� Travailler en autonomie et développer le programme complet
6G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
7
Organisation et plan du cours
� Organisation� Cours : 5 séances de 1h15� TD : 10 séances de 1h15� TP : 5 séances de 2h45 (en binôme ou monôme)
� Contrôles : 1 évaluation individuelle� 1 Contrôle sur machine (sans documents)
� Plan du cours (prévisionnel)� Cours 1 Analyse descendante et rappels sur les sous-programmes� Cours 2 Tableaux et problèmes de dimensionnement� Cours 3 Récursivité� Cours 4 Pointeurs � Cours 5 Pointeurs et Conclusion
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
8
Bibliographie et logiciels
� Bibliographie� « Programmation Séquentielle avec Ada95 »
P. Breguet – L. Zaffalon
Presses Polytechniques et Universitaires Romandes
� « Programmer avec Ada95 »J. Barnes, Adison Wesley
� Pour faire de l’ADA � Compilateur gratuit et IDE
� Windows : Gnat et Adagide/Emacs
� Linux : Gnat et Emacs
� Mac : http://www.macada.org/
� Manuel officiel� Ada95 Reference Manual
� http://www.adahome.com/rm95/
� Sites internet : www.adapower.com/ www.ada-france.org/
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
9
Forme générale d’un programme avec S/P
-- Entête du programmeWITH ... ; USE ……. ;PROCEDURE Nom_Programme IS
-- Déclarations des constantes, types et sous-types…….
-- Spécifications et corps des S.-P.…….…….
-- Déclarations des variables du programme principal…….
BEGIN-- Instructions (dont appels aux S.-P.)…….
END Nom_Programme ;G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
10G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
G.AURIOL, C. MERCE, P. ESQUIROL
11
Chapitre 1
Rappels sur les sous-programmes
2
MIC
12
Chap 1 – SP - Pourquoi faire des S/P?
� Améliorer � La lisibilité des programmes réalisés
� Programmes moins longs et plus clairs (1 page chacun au plus)
� La fiabilité et la maintenance des programmes� 1 fois le S.-P. écrit et testé, plus besoin d’y revenir
� Développer plus rapidement
� Réutiliser les S.-P. existants� Trouvés sur Internet, déjà développés au sein de l’entreprise,…
� Partager le développement entre équipes� Chaque équipe a en charge un ou plusieurs S.-P.
� Attention à la conception
� Comment décomposer en sous-programmes ?
� Quels paramètres ?
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
13
Chap. 1 : SP - Concepts de base
� Deux catégories de sous-programmes� Fonction
� Retourne 1 résultat unique
� Appel de fonction ≈ Expression
� Procédure� Effectue une action qui peut générer 0, 1 ou plusieurs résultats
� Appel de procédure (« invocation ») -> 1 Instruction
� Concepts de base
� Déclaration d’un S.-P. / Appel d’un S.-P.
� Echanges d’informations entre S.-P. et programme appelant� Paramètres formels / Arguments d’appel
� Portée des variables� Variables locales / variables globales
� Imbrication de sous-programmes
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
14
Chap. 1 : SP - Déclaration et appel d’une fonction
� Déclaration d’une fonction
� Appels de fonction, exemples :
function Nom_de_Fonction ( Parametres_Formels ) return Type_Resultat is
-- Déclaration de constantes, types, ss-types et variables locales
begin-- instructions….
return Expression ; -- de type Type_Resultatend Nom_de_Fonction;
Variable := Nom_de_Fonction ( Parametres_D_Appel ) ;
Put ( Nom_De_Fonction ( Parametres_D_Appel ) ) ;
if Nom_de_Fonction ( Parametres_D_Appel ) then
Ne pas oublier
Ou rien !
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
15
Chap. 1 : SP - Exemple d’une fonction Calculer_Somm e
Corps du sous-programme-- calcule la somme des valeurs rangées dans un tableau
function Calculer_Somme (T : in Tab_Entier) return Integer is
S : Integer; -- variable locale résultat
begin
S := 0;
for I in T’range loop
S := S + T(I) ;
end loop ;
return S;
end Calculer_Somme;
---------------------------------------------------------------------
Appel du sous-programme
….Resu := Calculer_Somme ( Mon_Tableau );
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
16
Chap. 1 : SP - Exemple de déclaration d’une procédur e
� Spécification d’un sous-programme de facturation � Ecrire un sous-programme qui à partir
� Du prix unitaire d’un article
� Du nombre d’articles achetés
� Du taux de TVA appliqué
� Retourne� Le prix HT et le prix TTC
procedure Facture (PU : in float; N : in natural; TVA : in Float ;
PHT : out Float ; PTTC : out Float ) isbegin
PHT := PU * Float (N) ;
PPT := PHT + PHT * TVA ;
end Facture ;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
17
Chap. 1 : SP - Exemples d’appel de la procédure
PROCEDURE Main IS
-- Declaration du sous-programme
procedure Facture(Pu : in float; N : in natural; TVA : in Float ; Pht , Pttc : out Float) is
…begin
…end Facture ;
-------------------------------------------------------------------------- Declarations des variables du programme principal (juste avant le begin)P1 : Float := 23.45 ;Montant_HT, Montant_TTC, X, Y : Float ;
begin…. --Pu N TVA Pht PttcFacture (P1 , 100 , 0.20, Montant_HT , Montant_TTC ) ;Facture ( 99.9 , 50 , 0.5, X, Y );….
end Main;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
18
Chap. 1 : SP – Décl. et appel d’une procédure : form e générale
� Déclaration d’une procédure
� Appel de la procédure ( ≈ instruction)
procedure Nom_de_procedure ( Parametres_Formels ) is
-- Partie déclarative
begin
-- instructions….
end Nom_de_procedure;
Nom_de_procedure ( Parametres_D_Appel ) ;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
19
Chap. 1 : SP - Paramètres formels et paramètres d’ap pel
� Paramètres formels
� Matérialisent les échanges d’information entre S.-P. et programme d’appel
� Permettent de décrire le traitement effectué par le S.-P.
� Paramètres d’appel (valeurs ou variables figurant d ans l’appel)
� Valeurs ou variables échangées au moment de l’appel
� Sens des échanges (modes de passage) (page 29)
� in : valeur reçue par le S.-P. Le paramètre se comporte comme une constante dans le S.-P. (il ne peut pas modifier sa valeur)
� out : valeur uniquement fixée par le S.-P. Le paramètre se comporte comme une variable affectée par le S.-P. La valeur précédant l’appel du S.-P. est inutilisée et de toutes façons écrasée par la valeur fixée par le S.-P.
� in out : valeur modifiée par le S.-P. Le paramètre se comporte comme une variable dont la valeur est transmise au S.-P. puis modifiée par lui.
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
20
Chap. 1 : SP – Exemples de spécification de SP
� Si le mode de passage n’est pas spécifié � c’est le mode IN par défaut
� Si le S.-P. est une fonction, TOUS les paramètres formels sont
� Obligatoirement en mode IN
� Exemples : donner la spécifications d’un sous-progr amme qui
� affiche à l’écran le contenu d’une variable de type Tab
� fait le tri d’un tableau de type Tab
� permute les valeurs contenues dans 2 variables entières
� lit des valeurs fournies au clavier et les range dans un tableau
� Calcule le produit scalaire de 2 vecteurs
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 1 : SP - Portée d’un objet ( variable ou sous- programme)
� Définition� Portée d’un objet dans un programme = zone du programme dans laquelle
l’objet est vu (et donc utilisable)� La portée d’un objet
� Commence à la déclaration de cet objet� Se termine au « end » du bloc dans lequel l’objet est déclaré
� Exemple
21
procedure Mon_Prog is
A , X : Integer ;
procedure Toto is
I, X : Float ;begin
end Toto;
begin
end Mon_Prog ;
Portée de I et X (2)
Portée de A et X (1)
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 1 : SP - Effet de bord (exemple) 1/2
22
procedure Exemple isA, B : Integer ;
------------------------------------------------procedure Permuter(X, Y : in out Integer ) is
Aux : Integer;begin
Aux := X; X := Y; Y := Aux;
end Permuter ; ----------------------------------------------------begin
A:=10 ; B :=20 ;Permuter (A, B) ; put (« A = ") ; put (A) ; put (« B = ") ; put (B) ;
end Exemple ;
procedure Exemple isA, B : Integer ;
------------------------------------------------procedure Permuter is
Aux : Integer;begin
Aux := A; A := B ; B := Aux ;
end Permuter ; ------------------------------------------------begin
A:=10 ; B :=20 ;Permuter ; put (« A = ") ; put (A) ; put (« B = ") ; put (B) ;
end Exemple ;
Effets de bord
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 1 : SP - Effet de bord (exemple) 2/2
23
procedure Exemple is
procedure Permuter(X, Y : in out Integer ) isAux : Integer;
beginAux := X; X := Y; Y := Aux;
end Permuter ; ---------------------------------
A, B : Integer ;
beginA:=10 ; B :=20 ;Permuter (A, B) ;
put (A) ; put (B) ; end Exemple ;
procedure Exemple is
procedure Permuter isAux : Integer;
beginAux := A; A := B; B := Aux;
end Permuter ; ------------------------
A, B : Integer ;
beginA:=10 ; B :=20 ;Permuter ; put (A) ; put (B) ;
end Exemple ;
INCORRECT
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
24
Chap. 1 : SP - Emboîtement de S/P
G.AURIOL, C. MERCE, P. ESQUIROL
Variables et S.-P. visibles
procedure PRINCIPALE isToto : Integer ; procedure SP1(Params1 ….) is
Toto1 : Integer ;begin --SP1
-- Instructionsend SP1 ;procedure SP2(Params2 ….) is
Toto2 : integer;procedure SP2_1(Params21) is
Toto21 : Integer ;begin -- SP2_1
-- Instructionsend SP2_1;
begin --SP2-- Instructions
end SP2 ;begin -- PRINCIPALE
-- Instructionsend PRINCIPALE ;
Toto, Params1, Toto1SP1
Toto, Params2, Toto2Params21, Toto21,SP1, SP2_1
Toto, Params2, Toto2 SP1, SP2
Toto,SP1, SP2
2
MIC
G.AURIOL, C. MERCE, P. ESQUIROL
25
Chapitre 2
Analyse descendante et méthodologie de développement d’un programme
2
MIC
Chap. 2 : Méthodologie de développement d’un progra mme
� Analyse et Conception � Analyse et compréhension du cahier des charges
� identifier les données d’entrée du programme, les fonctionnalités à développer et les résultats attendus
� Choix des structures de données adaptées aux besoins� Elaboration de l’algorithme principal
� Décomposition en fonctionnalités
� Implémentation de certaines fonctionnalités par app el à des sous-programmes (abstraction).
� Spécification de ces sous-programmes (? Nom, Paramètres formels ?)
� Identification des jeux de tests afin de valider le bon fonctionnement du programme final lorsqu’il sera terminé
� Elaboration de l’algorithme de chaque sous-programme
� Codage et mise au point� Codage de chaque sous-programme et tests unitaires
� Décomposition en s.-p. (etc)
� Codage de l’algorithme principal et tests fonctionnels
26G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
27
Chap. 2 : Analyse descendante - mise en œuvre sur un exemple
� Cahier
des charges
Mon_Programme
Saisir une nouvelle suitede10 éléments
Calculer la somme des éléments de la suite
Calculer la moyenne des éléments de la suite
Afficher la suite
� Pour une suite donnée, l’utilisateur du programme pourra choisir l’action qu’il souhaite exécuter à partir d’un menu qui s’affichera à l’écran
� Plusieurs suites pourront être traitées séquentiellement
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 2 : Analyse descendante - mise en œuvre sur un exemple
� Phase d’analyse et de conception � Analyse du cahier des charges
� identifier les données d’entrée du programme, les fonctionnalités à développer et les résultats attendus
� Pour cet exemple simple :� Données d’entrée du programme
� 10 valeurs fournies par l’utilisateur (saisies au clavier)
� Résultats attendus (� affichés à l’écran)� La somme des valeurs
� La moyenne des valeurs
� Fonctionnalités � Acquisition et stockage des 10 valeurs fournies dans un tableau
� Calcul de la somme d’un tableau
� Calcul de la moyenne d’un tableau
28G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 2 : Analyse descendante - mise en œuvre sur un exemple
� Analyse et Conception � Analyse du cahier des charges
� identifier les données d’entrée du programme, les fonctionnalités à développer et les résultats attendus
� Choix des structures de données adaptées aux besoins� Elaboration de l’algorithme principal
� Décomposition en fonctionnalités
� Implémentation de ces fonctionnalités par des sous-programmes.
� Spécification de ces sous-programmes
29G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 2 : Analyse descendante - mise en œuvre sur un exemple
Structures de données et variables
Mon_Tableau : tableau de 10 composantes entières
Arret_Demande : booléen
Algorithme
Arret_Demandé false Saisie_Faite false
Tant que Arret_Demandé = false répéter
afficher le menu des actions possibles
lire (saisir) l’action souhaitée par l’utilisateur
en fonction de l’action souhaitée
lire (saisir) une suite des 10 valeurs fournies par l’utilisateur
Saisie_Faite true
afficher la suite à l’écran (si Saisie_Faite)
afficher la somme des valeurs (si Saisie_Faite)
afficher la moyenne des valeurs (si Saisie_Faite)
arrêter le programme :
Fin tant que
30
Arret_Demandé true
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 2 : Analyse descendante - mise en œuvre sur un exemple
Structures de données et variables
Mon_Tableau : tableau de 10 composantes
Arret_Demande : booleen
Algo
Arret_demandé false
Tant que Arret_Demandé = false répéter
afficher le menu
lire (saisir) l’action souhaitée par l’utilisateur
en fonction de l’action souhaitée
saisir et enregistrer la suite de valeurs
Saisie_Faite true
afficher la suite à l’écran
afficher (la somme des valeurs)
afficher (la moyenne des valeurs)
Arret_Demandé true
Fin tant que
31
� Appel à un sous-programme Afficher_menu
� Appel à un s-p Afficher_Suite
� Appel à un s-p Calculer_Somme
� Appel à un s-p Calculer_Moyenne
� Appel à un s-p Saisir_Suite
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
32
Chap. 2 : Spécification des sous-programmes
� Spécifier un sous-programme c’est définir
� Le Nom et l’objectif du sous-programme
� Les informations qu’il va utiliser (paramètres en entrée)
� Les informations qu’il va générer (paramètres en sortie)
� Les informations qu’il va modifier (paramètres en entrée-sortie)
� Bonnes pratiques
� Un seul traitement par sous-programme
� Ne pas mélanger entrées/sorties (interface utilisateur) et traitement
� Choisir des noms de sous-programmes représentatifs
� Écrire le corps du sous-programme revient à écrire l’algorithme correspondant au traitement que doit faire le sous- programme
� Si l’algorithme est complexe, on applique à nouveau une analyse descendante
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 2 : Spécification des sous-programmes de l’ex emple
� Afficher_Menu� Objectif : afficher les différentes actions offertes à l’utilisateur� Données d’entrée : aucune� Résultats générés : aucun
� Saisir_Suite� Objectif : saisir un tableau de valeurs � Données d’entrée : aucune (les donnée sont fournies par l’utilisateur via le
clavier) � Résultats générés : le tableau de valeurs
� Calculer_Somme� Objectif : calculer la somme des éléments d’‘un tableau� Données d’entrée : le tableau de valeurs� Résultats générés : la somme
� Remarque : � Algorithmes associés très simples � pas de décomposition supplémentaire
33G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 2 : Analyse descendante - mise en œuvre sur un exemple
� Phase d’analyse
� Globalement indépendante du langage support
� Codage et tests
� Développer PROGRESSIVEMENT chaque sous-programme
� Ecrire pour chaque sous-programme développé un sous-programme de test qui
� Définit et initialise les variables qui servent au test
� Affiche le résultat attendu pour ces valeurs
� Appelle le sous-programme
� Affiche les valeurs obtenues
34G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
G.AURIOL, C. MERCE, P. ESQUIROL
35
Chapitre 3
Types Tableaux Non Contraints Algorithme de recherche dans un tableau
2
MIC
Chap. 3 - Type tableau contraint ou non contraint
� Un tableau permet de regrouper des éléments de même nature
� Pour déclarer un type tableau, on précise� Le type de l’indice qui permet de le parcourir (plusieurs dim. possibles)� Le type des éléments contenus dans le tableau (les composantes)
� 2 possibilités pour déclarer un type tableau� Déclaration d’un type contraint
� �on fixe définitivement la taille de ce type de tableaux
� Déclaration d’un type non contraint � �on ne fixe pas une taille unique à la déclaration du type. Des tableaux
distincts pourront avec des tailles différentes
36
type Nom_Du_Type is array (type_de_l’indice ) of type_des_composantes ;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
37
Chap. 3 - Type tableau contraint
� Déclaration : Le nombre de composantes est fixé à l a déclaration du type
� Déclaration des variables
� Bien adapté lorsque toutes les variables de type tableau ont toujours le même dimensionnement et la dimension est connue avant l’ exécution du programme
� Lourdeur si ce n’est pas le cas
type Un_Tab_contraint is array (Integer range 1..20) of Float ;
type Un_Autre_Tab_Contraint is array (Character range ‘A’..’Z’) of Float ;
A, B : Un_Tab_contraint ; -- A et B de même taille : 20 float chacun
X,Y : Un_Autre_Tab_Contraint ; -- X et Y de même taille : 26 character chacun
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
38
Chap. 3 - Type tableau non contraint (NC)
� Déclaration du type
� Exemples
� Caractéristiques importantes
� Les paramètres formels d’un ss-programme peuvent être non contraints� Comment écrire ce sous-programme ?
� Une variable d’un type tableau doit être dimensionnée lors de sa déclaration
� pb du dimensionnement
type identificateur_du_type is array (type_indice range <>) of type_composantes ;
type Un_Vecteur is array (Integer range <>) of Integer ;type Un_Tab is array (Character range <>) of Float ;
Vec1 : Un_Vecteur(0..9); Vec2 : Un_Vecteur(1..1000);
Tab1 : Un_Tab(‘a’ ..’z’); Tab2 : Un_Tab(‘A’..’E’);
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 3 – Sous-programmes et types tab non contraint (1/2)
39
procedure Exemple is
type Un_Vecteur is array (Integer range <>) of Integer ;
function Indice_Du_Min (De : in Un_Vecteur ) return Integer is-- retourne l’indice du min du vecteur De
begin…
end Indice_Du_Min ;
X : Un_Vecteur ( 1..10) ;Y : Un_Vecteur ( 0..100) ;
begin --Exemple-- Saisie de X et de Y
…-- afficher l’indice du min de X ?
Put(Indice_Du_Min(X)) ;
-- afficher l’indice du min de Y ?Put(Indice_Du_Min(Y)) ;
-- afficher l’indice du min dans la portion (tranche) 20..50 de YPut(Indice_Du_Min(Y(20..50))) ;
end Exemple ;
Exemple : SP qui retourne l’indice de la valeur minimum d’un tableau de type non contraint
1- spécification du SP et exemples d’appel
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 3 – Sous-programmes et types tab non contraint (2/2)
40
procedure Exemple istype Un_Vecteur is array (Integer range <>) of Integer ;function Indice_Du_Min(De : in Un_ Vecteur ) return Integer is
Imin : integer; -- retourne l’indice du minimumbegin
Imin := De’first;for I in De’firtst+1..De’last loop
if De(I) < De(Imin) thenImin := I;
end if;end loop;
…return Imin;
end Indice_Du_Min ;X : Un_Vecteur (1..10) ;Y : Un_Vecteur (0..100) ;
begin…
end Exemple ;
Exemple : SP qui retourne l’indice de la valeur minimum d’un tableau de type non contraint
1- spécification du SP et exemples d’appel
2- écriture du SP
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap3 - Problème du dimensionnement d’une variable t ableau (1/5)
� Différentes situations� On connait la dimension du tableau lorsqu’on écrit le programme
� pas de problème
� On ne connait pas la dimension du tableau lorsqu’on écrit le programme� on ne peut déclarer la variable de type tableau
il faut d’abord déterminer la dimension de ce tableau
41
procedure Exemple istype Un_Vecteur is array (Integer range <>) of Integer ;…
X : Un_Vecteur (1..10) ;Y : Un_Vecteur (0..100) ;
begin…
end Exemple ;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap3 - Problème du dimensionnement d’une variable t ableau (2/5)
42
procedure Exemple istype Un_Vecteur is array (Integer range <>) of Integer ;
procedure Saisir (T : out Un_Vecteur) is
…end Saisir ;function Indice_Du_Min (De : in Un_Vecteur ) return Integer is
…end Indice_Du_Min ;Dim : Integer ;Mon_Tab : Un_Vecteur (1..Dim ) ;
beginput (« entrez la dimension »);Get (Dim ) ;
…Saisir(Mon_Tab) ;
…put(Indice_Du_Min(Mon_Tab));
…end Exemple ;
valeur ???
1ère tentative :
La dimension du tableau est fournie par l’utilisateur en début d’exécution
=> échec
G.AURIOL, C. MERCE, P. ESQUIROL
C’est trop tard ! Mon_Tab a été créé avec une taille indéterminée …
2
MIC
Chap3 - Problème du dimensionnement d’une variable t ableau (3/5)
43
procedure Exemple istype Un_Vecteur is array (Integer range <>) of Integer ;
procedure Saisir (T : out Un_Vecteur) is
…end Saisir ;function Indice_Du_Min (De : in Un_Vecteur ) return Integer is
…end Indice_Du_Min ;Dim : Integer;
beginput (« entrez la dimension »);Get (Dim);declare
Mon_Tab : Un_Vecteur(1..Dim ); begin
Saisir(Mon_Tab) ;…
put(Indice_Du_Min(Mon_Tab));…
end ;end Exemple ;
2ème tentative :
La dimension est fixée avant la déclaration
� Utiliser un bloc declare
…� begin
…� end;
=> Ok
G.AURIOL, C. MERCE, P. ESQUIROL
Mon_Tab est déclaré APRES
On fixe d’abord Dim
2
MIC
Chap3 - Problème du dimensionnement d’une variable t ableau (4/5)
44
procedure Exemple istype Un_Vecteur is array (Integer range <>) of Integer ;
procedure Saisir (T : out Un_Vecteur) is
end Saisir ;function Indice_Du_Min (De : in Un_Vecteur ) return Integer isend Indice_Du_Min ;
function Donne_La_Dimension return Integer isD: integer;
beginput (« entrez la dimension »);Get(D);
return D;end Donne_La_Dimension ;
Mon_Tab : Un_Vecteur (1.. Donne_La_Dimension ) ;
beginSaisir(Mon_Tab) ;
…put(Indice_Du_Min(Mon_Tab));
…end Exemple ;
3ème tentative :
La dimension est fixée par une fonction
� Avantage : ne nécessite pas le bloc
declare…begin…end;
=> Ok
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap3 - Problème du dimensionnement d’une variable t ableau (5/5)
45
procedure Exemple istype Un_Vecteur is array (integer range <>) of Integer ;
positivefunction Donne_La_Dimension return Integer is
…end Donne_La_Dimension ;
function Saisir return Un_Vecteur is-- retourne un vecteur dont la dimension et -- les valeurs sont saisies au clavier
V : Un_Vecteur (1..Donne_La_Dimension );begin
put("Saisir " & integer’image(V’last) & " entiers : " );for I in V’range loop
get(V(I));end loop;
return V;end Saisir;MonTab : Un_vecteur := Saisir ;
begin… put(Indice_Du_Min(Mon_Tab));…
end Exemple;
4ème tentative :
La dimension ET le tableau sont fixés par des fonctions
=> Ok
G.AURIOL, C. MERCE, P. ESQUIROL
Mon_Tab est dimensionnélors de l’affectation parla fonction Saisir.
Attention, MonTab’first =positive ’first = 1maissi l’indice de Un_Vecteurétait integer , MonTab’first =integer ’first = -2147483648
2
MIC
46
Chap. 3 : À retenir (1/2)
� Souplesse des types « tableau non contraint »� Algorithmes généraux basés sur les attributs ‘first, ‘last, ‘range, ‘length� Possibilité de manipuler des « tranches de tableaux »
� Intérêt à utiliser des paramètres formels de S/P d’ un type tableau non contraint � Intérêt : sous-programme réutilisable pour des tableaux de toute dimension� Pousse à la généralisation (utilisation des attributs et non de valeurs particulières)
� Les variables (en particulier les paramètres d’appe l du S/P) sont obligatoirement contraintes lors de leur déclaratio n.
procedure Exemple istype Un_Vecteur is array (Integer range <>) of Integer ;
X : Un_Vecteur (1..10) ;Y : Un_Vecteur (0..100) ;
beginY( 50..55 ) := X( 3..8) ; -- 6 éléments copiésif X (1..4) < Y (5..8) then … -- 4 éléments comparés…
end Exemple ;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
47
Chap. 3 - À retenir (2/2)
� Toute variable doit être contrainte lors de sa décl aration
� Plusieurs solutions pour « contraindre » une variable de type tableau n on contraint
� Technique 1 : Utiliser un bloc DECLARE dans le programme principal pour déclarer la variable après avoir déterminé sa dimension.
� Technique 2 : Utiliser une fonction de dimensionnement au moment de la déclaration, ex : Var : Un_Vecteur(1 .. Donner_Dimension);
� Technique 3 : Utiliser une déclaration+affectation à l’aide d’une fonctiond’initialisation, du type Var : Un_Vecteur := Saisir; La fonction d’initialisation peut elle-même utilsier une fonction de dimensionnement
� Un Type prédéfini non contraint important : le type STRING
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
48
Chap. 3 - Type prédéfini String ( chaîne de caractèr es)
� Déclarations� Le type String est un type non contraint prédéfini (connu du langage)
� Littéraux (valeurs de) chaînes de caractères �
� Déclarations de variables (il faut TOUJOURS que la dimension soit connue !)
"c'est une chaine" -- C'est une valeur de type string"s" -- C'est aussi une valeur de type string
type String is array ( Positive range <> ) of Character ;
Ch : String (1 .. 4) ;
Mess : String (1 .. 7) := "bonjour ";Texte1 : String := " ça va ?" ;Texte2 : String := Mess & Texte1;Faux : String ; -- erreur !!
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
49
Chap. 3 - Type prédéfini String ( chaîne de caractèr es)
� Opérations sur les String
(identiques à celles disponibles sur des tableaux à 1 dimension)� Attributs
� first , last , length , range
� Image , value
� AffectationRemarque : même longueur de part et d'autre de l'affectation
Integer'Image(123) = " 123"Integer'Value(" -123") = -123
type Couleur is (rouge, jaune, vert, bleu);Couleur'Image(rouge) = " ROUGE"
Ch : String (1 .. 5) ;Mess : String (1 .. 7) := "bonjour";
beginCh := "salut" ;Mess := "salut--" ;Ch := Mess(1.. 4) ; --erreur !!
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
50
Chap. 3 - Type prédéfini String (chaîne de caractère s)
� Opérations sur les String � Égalité
� Il faut des chaînes de même longueur de part et d’autre de l’égalité
� Ordre lexicographique� Chaînes quelconques
� Concaténation
"ABC" > "AB" ;"ABC" < "CD" ;
Mess : String (1 .. 7) := ("bonjour") ;Texte : String := (" ca va?") ;
beginPut_Line (Mess & Texte);Put_Line (Mess & '!');Put_line('A '& 'B');
end Exemple;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
51
Chap. 3 – Le paquetage Ada.Text_IO
procedure Put(Item : in Character); -- affichage d’un caractèreprocedure Put(Item : in String); -- affichage d’un stringprocedure Put_Line(Item : in String) ; -- affichage puis retour-ligne
procedure New_Line(spacing : in positive_count := 1) ;-- spacing retours-ligne (par défaut : 1)
procedure Get(Item : out Character) ; -- lecture d’un caractèreprocedure Get(Item : out String) ; -- lecture d’un string -- il faut fournir autant de caractères que la longueur de Itemprocedure Get_Line(Item : out String ; Last : out Natural) ;-- lit les caractères fournis jusqu'à ce qu’une fin de ligne soit rencontrée-- ou que la longueur de Item soit atteinte.-- Last donne l'indice dans la chaîne du dernier caractère lu
procedure Skip_Line; -- « saute » tous les caractères jusqu’au retour-ligneG.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 3 - Algorithmique : recherche d’une valeur dan s un tableau
� Problème : � On souhaite écrire un sous-programme qui détermine si une valeur donnée
figure dans un tableau. � Si oui, on veut connaitre l’indice de la première occurrence de cette valeur
dans le tableau.� Spécification du sous-programme
� Données en entrée� La valeur cherchée
� Le tableau de valeurs
� Résultats en sortie� Un booléen qui indique si la valeur a été trouvée
� L’indice de la 1ère occurrence de la valeur cherchée
52G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 3 - Recherche d’une valeur dans un tableau - 1 ere version
53
type Un_Vecteur is array (Integer range <>) of Integer ;
procedure Chercher ( Val : in Integer ; Dans : in Un_Vecteur;Trouve : out Boolean ; Pos : out Integer ) is
-- cherche Val dans le tableau Dans ; -- Trouve contient True si Val appartient à Dans ; Pos est l’indice de Val dans Dans
beginTrouve := FALSE;for I in Dans’range loop
if Dans(I) = Val thenTrouve := TRUE;Pos := I ;
end if;end loop ;
end Chercher ;
Commentaires: � cet algo fournit en réalité l’indice de la dernière occurrence car ilcontinue à parcourir le vecteur même lorsqu’on a tr ouvé la valeur
G.AURIOL, C. MERCE, P. ESQUIROL
Algorithme incorrect !!
2
MIC
Chap. 3 - Recherche d’une valeur dans un tableau - 2 ème version
54
type Un_Vecteur is array (Integer range <>) of Integer ;
procedure Chercher ( Val : in Integer ; Dans : in Un_Vecteur;Trouve : out Boolean ; Pos : out Integer ) is
-- cherche Val dans le tableau Dans ; -- Trouve contient True si Val appartient à Dans ; Pos est l’indice de Val dans Dans
beginI := Dans’first ;while Dans (I) /= Val loop
I := I+1 ;end loop;...
end Chercher ;
Que se passe t-il si Val ne se trouve pas dans le vecteur Dans ??
Algorithme incorrect !!
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 3 - Recherche d’une valeur dans un tableau - 3 ème version
55
type Un_Vecteur is array (Integer range <>) of Integer ;
procedure Chercher ( Val : in Integer ; Dans : in Un_Vecteur;Trouve : out Boolean ; Pos : out Integer ) is
-- cherche Val dans le tableau Dans ; -- Trouve contient True si Val appartient à Dans ; Pos est l’indice de Val dans Dans
beginI := Dans’first ;while I <= Dans’last and then Dans (I) /= Val loop
I := I+1 ;end loop ;if I > Dans’last then
Trouve := False ; else
Trouve := True; Pos := I ;end if ;
end Chercher ;
Algorithme correct et élégant … maisspécifique à ADA !!
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 3 - Recherche d’une valeur dans un tableau - 4 ème version
56
type Un_Vecteur is array (Integer range <>) of Integer ;
procedure Chercher ( Val : in Integer ; Dans : in Un_Vecteur;Trouve : out Boolean ; Pos : out Integer ) is
-- cherche Val dans le tableau Dans ; -- Trouve contient True si Val appartient à Dans ; Pos est l’indice de Val dans Dans
beginI := Dans’first ; Trouve := false ;while I <= Dans’last and not trouve loop
if Dans(I) = Val thenTrouve := true;Pos := I ;
elseI := I+1;
end if ;end loop ;
end Chercher ;
Algorithme de recherche classiqueA RETENIR !
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
G.AURIOL, C. MERCE, P. ESQUIROL
57
Chapitre 4
Récursivité
2
MIC
58
Chap. 4 : Récursivité - Introduction
� Définition récursive� "Un sous-programme récursif est un sous-programme récursif"
� Définition plus sérieuse� Un sous-programme est dit récursif lorsqu'il fait appel à lui-même
� Vous connaissez déjà!
Exemple en math : calcul de factorielle n� Définition de n! : n! = n × (n-1)!
0! = 1� Exemple 4! = 4 × 3!
3! = 3 × 2!
2! = 2 × 1!
1! = 1 × 0!
0! = 1
Cas trivial
La dimension change
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
59
Chap. 4 : Récursivité - 1 er exemple
� Écriture récursive de factorielle
procedure Test_Facto is
function Facto (N: in Natural) return Positive is…end Facto ;
Nb : natural; -- nombre lu
beginput ("entrer un nombre positif ou nul");get ( Nb ); put ( Nb ); put( " ! = " ); put (Facto(Nb) );
end Test_Facto;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
60
Chap. 4 : Récursivité - 1 er exemple
� Écriture récursive de factorielle
function Facto (N: in Natural) return Positive isResu : Positive ;
begin
return Resu;end Facto;
-- 0! = 1
-- n! = n×(n-1)!
G.AURIOL, C. MERCE, P. ESQUIROL
if N=0 thenResu := 1;
elseResu := N*Facto(N-1):
end if;
2
MIC
61
Chap. 4 : Récursivité - Principe d’un fonctionnemen t récursif
� Un sous-programme récursif a le même fonctionnement qu’un sous-programme non récursif.
� Principe de fonctionnement� Exécution du sous-programme récursif(version 1)
� Appel récursif � interruption de la version en cours
� Le système sauvegarde dans une pile l'environnement du ss-prgme� Adresse de retour
� Valeur des paramètres de mode in de la version en cours
� Valeur des variables locales de la version en cours
� Une nouvelle version du sous-prgme (version 2) s’exécute avec une nouvelle version des paramètres formels in (leur valeur est celle spécifiée dans l’appel) ;
� Fin d'exécution de cette nouvelle version (version 2) ; retour des valeurs des paramètres de mode out et in out . ou du résultat de la fonction
� Reprise de la version appelante (version 1) là où elle s'était interrompue au moment de l’appel avec son environnement restauré tel qu’elle l’avait laissé
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
62
Chap. 4 : Récursivité - Fonctionnement de la Pile
� Qu’est ce que la pile ?� Zone mémoire particulière réservée à chaque programme
� Rôle� Stocker les valeurs des variables locales et des paramètres d'un s-p et
l’adresse de retour avant tout appel à un autre sous-programme� Gestion transparente pour l'utilisateur
� S/P récursif : à chaque appel récursif, toutes les variables locales sont stockées dans la pile (empilées) autant de fois qu' il y a d'appels récursifs
� En fin d’exécution d’une version, les variables son t « dépilées » pour que l’on retrouve l’environnement de la version précéde nte
� Attention au "débordement de pile" : Exception « Sto rage_Error »
C’est la manifestation d’une récursion infinie :
- l’arrêt de la récursion est mal défini
- l’appel récursif est erroné
…
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
63
Chap. 4 : Récursivité - Arbre d’appel de Facto pour N=3
function Facto (N: in Natural) return Positive isResu : Positive;
beginif N=0 then
Resu := 1;else
Resu := N * Facto (N-1);end if;return Resu;
end Facto;
begin
put (Facto (3) ) ;
end Test_facto;
G.AURIOL, C. MERCE, P. ESQUIROL
Programme Principal
put( ? )
Facto(N1) N1=3 Resu1=
Facto(N2) N2=2 Resu2=
Facto(N3) N3=1 Resu3=
Facto(N4) N4=0 Resu4= 1
1*1=1
2*1=2
3*2=6
put(6)
2
MIC
64
Chap. 4 : Récursivité - version itérative / version récursive
� Pour des problèmes simples, il existe une version i térative simple
� Comparer version itérative et version récursive
function Facto ( N : in Natural) return Positive isResu : Positive := 1;
beginfor J in 1..N loop
Resu := J * Resu ;end loop;return Resu;
end Facto;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
G.AURIOL, C. MERCE, P. ESQUIROL
65
Chap. 4 : Récursivité – Exemples
� Qu’affiche la procédure?
procedure Test_Toto2 is
procedure Toto (N: in Integer) isbegin
if N > 0 thenToto ( N-1);
end if ;put ( N , 5);
end Toto ;
beginToto ( 4 ) ;
end Test_Toto2;
procedure Test_Toto3 is
procedure Toto (N: in out Natural) isbegin
if N > 0 thenN := N-1;Toto (N);
end if ;put (N, 5);
end Toto ;
X: Integer :=4;
beginToto (X) ; put ( X ) ;
end Test_Toto3;
2
MIC
66
Chap. 4 : Récursivité - Analyse récursive d'un probl ème
� Quand envisager une conception récursive?� Lorsque l’algo itératif n’est pas évident� Lorsqu'il est facile de décomposer le problème en un ou plusieurs sous-
problèmes de même nature mais de taille plus petite � Une conception récursive comprend souvent 3 étapes non forcément
séquentielles� Décomposition du problème (la taille doit diminuer!)� Paramétrage (la taille est un paramètre)� Identification du (des) cas trivial(aux)
� Forme générale d'un algorithme récursif
� Il faut qu'un algorithme récursif se termine. Il fa ut montrer que
� la décomposition simplifie le problème et converge vers le cas trivial !
if cas trivial thenCalcul direct
else Appels récursifs
end if ;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
67
Chap. 4 : Récursivité - Exemple : Inversion d’un vec teur (1/6)
� Quel est le problème?
� On a
� On veut
� Une analyse récursive comprend souvent 3 étapes non forcément séquentielles� Paramétrage du S/P
� Le vecteur à inverser� Rmq. : la taille d’un vecteur est intrinsèque à celui-ci � ce n’est pas
un paramètre (si on connaît X, on connaît aussi X’length)
� Identification du (des) cas trivial(aux)� Vecteur de taille nulle ou de taille 1
(dans ces cas l’inversion ne fait rien)
� Décomposition en ss-pbs de plus petite taille
10 30 20 15 40
40 15 20 30 10
X
Y
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
68
Chap. 4 : Récursivité - Exemple : Inversion d’un vec teur (2/6)
� Structure de données
� Obligatoirement un tableau non contraint car le S/P va manipuler des vecteurs de tailles dégressives
� Paramétrage du sous-programme� Lié au besoin : veut-on conserver le vecteur initial ?
� si procédure
� si fonction
type Vecteur is array (Integer range <>) of Integer ;
procedure Inversion ( V : in out Vecteur ) ;
function Inversion ( V : in Vecteur ) return Vecteur ;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
69
Chap. 4 : Récursivité - Exemple : Inversion d’un vec teur (3/6)
type Vecteur is array ( Integer range <> ) of Integer;
function Inversion ( V : in Vecteur ) return Vecteur isW : Vecteur(V’range);
beginif V’length <=1 then -- cas trivial
W := V; else -- appels récursifs
W(W’first) := V(V’last);W(W’last) := V(V’first);W(W’first+1..W’last-1) :=
Inversion(V(V’first+1..V’last-1));end if;
return W;end Inversion;
Fonction récursive
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
70
Chap. 4 : Récursivité - Exemple : Inversion d’un vec teur (4/6)
procedure Test_Inversion isX,Y : Vecteur (1..5);begin
X := (10, 30, 20, 15, 40) ;put ( " attendu apres inversion : 40 15 20 30 10 " ); Y := Inversion ( X ) ;-- affichage du vecteur inverséput ( " obtenu apres inversion : " ) ; for I in Y'range loop
put ( Y(I) ) ;end loop;
end Test_Inversion;
Test de la fonction récursive
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
71
Chap. 4 : Récursivité - Exemple : Inversion d’un vec teur (5/6)
procedure Inversion ( V : in out Vecteur ) is
Temp : Integer ;
begin
if V'length = 0 then
null ;
else
Temp := V (V'last) ;
V (V'last) := V (V'first) ;
V (V'First) := Temp ;
Inversion ( V ( V'first+ 1 .. V'last- 1) ) ;
end if ;
end Inversion;
Procédure récursive
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
72
Chap. 4 : Récursivité - Exemple : Inversion d’un vec teur (6/6)
procedure Test_Inversion isX : Vecteur (1..5);
beginX := (10, 30, 20, 15, 40) ;put ( " attendu apres inversion : 40 15 20 30 10 " ); Inversion(X) ;-- affichage du vecteur inverséput ( " obtenu apres inversion : " ) ; for I in X'range loop
put(X(I)) ;end loop;
end Test_Inversion;
Test de la procedurerécursive
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
73
Chap. 4 : Récursivité - Exemple : Les tours de Hanoi
� La fin du monde!� Une légende asiatique raconte que dans un temple se trouvent trois
poteaux sur lesquels s'empilent 64 disques d'or. Les prêtresdéplacent continuellement les disques selon les règles édictées ci-après. D'après cette même légende, le dernier déplacement dedisque marquera la fin du monde
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
74
Chap. 4 : Récursivité - Exemple : Les tours de Hano i
� Règles de déplacement
� On ne déplace qu'un seul disque à la fois
� On ne peut déplacer que le disque situé au sommet d'un poteau
� On ne peut poser un disque que sur un poteau vide ou sur un poteau contenant des disques plus grands
� On souhaite écrire un programme qui écrit la suite des déplacements à effectuer
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
75
Chap. 4 : Récursivité - Les tours de Hanoi avec 1 di sque
� Exemple : déplacer 1 disque du socle ‘A’ vers le so cle ‘B’
� Liste des déplacements :
A � B
Socle A Socle B Socle C Socle A Socle B Socle C
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
76
Chap. 4 : Récursivité - Les tours de Hanoi avec 2 di sques
� Exemple : déplacer 2 disques du socle ‘A’ vers le s ocle ‘B’ (en utilisant ‘C’ comme socle intermédiaire)
� Déplacements:
A � C
A � B
C � B
A B C
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
77
Chap. 4 : Récursivité - Les tours de Hanoi avec 3 d isques !
� Exemple avec 3 disques
A B C
� DéplacementsA � BA � CB � CA � B
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
78
Chap. 4 : Récursivité - Les tours de Hanoi avec 3 disques !
A B C
C � AC � BA � B
� DéplacementsA � BA � CB � CA � B
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
Chap. 4 : Récursivité - Les tours de Hanoi : analys e récursive
� Une analyse récursive comprend souvent 3 étapes non forcément séquentielles
� Identification du (des) cas trivial(aux)
� Tour n’ayant aucun disque ! (il n’y a rien à faire)
� Paramétrage du S/P
� Le nombre de disques à déplacer � N
� Le nom des socles
� Socle de départ � Dep
� Socle d’arrivée � Arr
� Socle intermédiaire � Int
� Décomposition du problème initial en sous-problèmes de même nature mais de plus petite taille
79G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
80
Chap. 4 : Récursivité - Les tours de Hanoi : décompo sition récursive
Pour déplacer N disques d’un socle de départ Dep vers un socle d’arrivée Arren utilisant un socle intermédiaire Int , il faut
- Déplacer N-1 disques de Dep vers Int en utilisant Arr comme socle intermédiaire
- Déplacer un disque de Dep vers Arr
- Déplacer N-1 disques de Int vers Arr en utilisant Dep comme socle intermédiaire
Dep Arr Int
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
81
Chap. 4 : Récursivité - Les tours de Hanoi
procedure Test_Hanoi is
procedure Hanoi (N : in Natural; Dep, Arr, Int : in Character) isbegin
if N /= 0 thenHanoi( N-1, Dep, Int, Arr);put (" déplacer un disque de "); put (Dep);put(" vers "); put (Arr); new_line;Hanoi( N-1, Int, Arr, Dep);
end if;end Hanoi;
Nb: natural;
beginput (" Nombre de disques ? "); get (Nb) ; Hanoi (Nb, 'A', 'B', 'C');
end Test_Hanoi;
Dép Arr Int.
Dép Arr Int
Dép Arr Int
Dép Arr Int.
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
82
Chap. 4 : Récursivité - Les tours de Hanoi : arbre d ’appel
3,A,B,C
2,A,C,B 2,C,B,A
1,B,C,A1,A,B,C
0,C,B,A0,A,C,B
2
Socle A
Socle B
Socle C
G.AURIOL, C. MERCE, P. ESQUIROL
1
0,B,A,C
4
3
0,A,C,B
1 : A vers B 2 : A vers C 3 : B vers C 4 : A vers B 5 : C vers A
1,C,A,B
6
5
1,A,B,C
0,C,B,A
7
0,B,A,C 0,A,C,B 0,C,B,A
6 : C vers B 7 : A vers B
2
MIC
Chap. 4 : Récursivité - Les tours de Hanoi et la fin du monde !
83
� Calcul du nombre de déplacements à effectuer pour n disquesND(n) = 2 × ND (n-1) +1ND(0) = 0
Ce qui donne en « dérécursivisant »ND(1) = 1ND(2) = 2 × ND (1) + 1 = 2 + 1ND(3) = 2 × ND (2) + 1 = 22 + 2 + 1
ND(n) = 2n-1 + … + 2 + 1 = ∑ 2� =2� − 1����
� Calcul du temps mis pour déplacer 64 disques� On suppose 1 déplacement = 1 sec� Temps total ≈ 264 sec ≈ 0,2 × 1020 sec
� 1 année = 31 536 000 sec ≈ 0.3 × 108 sec
� 1 siècle ≈ 0.3 × 1010 sec
� Il faudra ≈ 1010 siècles pour déplacer les tours
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
84G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
G.AURIOL, C. MERCE, P. ESQUIROL
85
Chapitre 5
Les pointeurs
2
MIC
86
Chap. 5 : Les pointeurs - Introduction
� Les variables manipulées jusqu’à présent sont dites statiques
� Statiques car explicitement déclarées� Déclarées en précisant
� Leur nom
� Leur type � Réservation figée d'un espace mémoire
� Exemple avec des tableaux
Type Un_Tab_Contraint is array (Integer range 1..5) of Float ;
Type Un_Tab_NON_Contraint is array (Integer range <>) of Float ;
X : Un_Tab_Contraint ;
Y : Un_Tab_Non_Contraint (1..10) ;
� Attention : une fois déclarées, X et Y ne peuvent pas changer de taille � LIMITATION
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
87
Chap. 5 : Les pointeurs – Exemple de liste
� Gérer la liste des personnes s'inscrivant pour une course à pieds et maintenir l’ordre alphabétique de la liste� On ne sait pas a priori combien de personnes vont participer à cette
course� Des nouveaux participants peuvent arriver à tout moment
� Des participants peuvent annuler à tout moment
� Difficile dans ces conditions de dimensionner une variable de type tableau
� � Besoin : on veut pouvoir créer des variables au fur et à mesure des besoins en cours d’exécution du programme � variables dynamiques
� � La notion de pointeur répond à ce besoin
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
88
Chap. 5 : Les pointeurs - Allocation dynamique
� Allocation dynamique� Mécanisme permettant de réserver « dynamiquement » de la mémoire
c’est à dire de créer « dynamiquement » une variable� Dynamiquement � en cours d’exécution du programme (au fur et à mesure
des besoins)� La réservation se fait dans une zone mémoire particulière de la machine
(appelée tas)� Les variables créées dynamiquement peuvent changer de place en mémoire
� Les variables de cette zone mémoire ne sont accessib les que par l’intermédiaire de leur adresse (par des pointeurs)
� Définition� Pointeur : variable contenant l’adresse d’une autre variable (ou d’un sous
programme- hors contexte de ce module) ;� On dit qu’elle « pointe » sur une autre variable
� Exemple : liste des coureurs
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
89
Chap. 5 : Les pointeurs – Utilisation de variables d ynamiques
� Rappels : utilisation de variables statiques (ex. t ableau)� Déclaration d’un type
� Déclaration d’une variable de ce type
� Accès à la variable par son nom
� Pointeurs et variables dynamiques� Déclaration d’un type « pointeur »� Déclaration d’une variable de type « pointeur »� Création et affectation d’une variable dynamique (allocation mémoire)� Accès au contenu� Libération espace mémoire (désallocation)
type Un_Vect is array (Integer range 1..10) of Integer ;
Mon_Vecteur : Un_Vect ;
Mon_Vecteur ( 1 ) := 8 ;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
90
� Déclaration d’un type pointeur
� Forme générale
� Exemples
� Déclaration d’une variable d'un type pointeur
� Par défaut, en ADA, la valeur d’une variable de typ e pointeur est « null » lors de la déclaration
� Le pointeur pointe sur « rien »
� Il n’y a pas eu de réservation mémoire
Chap. 5 : Les pointeurs : déclarations
type Ptr_Int is access Integer ;type P_String is access String;
type Tab is array(1..6) of Boolean ;type Ptr_Tab is access Tab ;
type NomType is access TypePointé ;
P : Ptr_Int ;
M : Ptr_Tab ;
P : Ptr_Int := null ;
M : Ptr_Tab := null ;
P
M
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
91
Chap. 5 : Les pointeurs : Allocation mémoire (1/3)
� Création d’une variable dynamique � réservation mémoire
� Forme générale
La variable dynamique de NomPointeur est une adresse mémoire.
Le contenu est dénotée par l’expression NomPointeur .all
type NomType is access TypePointé ;
NomPointeur : NomType ;
begin
NomPointeur := new TypePointé ;
-- accès à la variable
NomPointeur.all := xxxx ;
new = « Allocateur »- Cherche une zone disponible en mémoire, de taille adaptée au type pointé.- Réserve cette zone- Retourne l’adresse de la zone
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
92
Chap. 5 : Les pointeurs : Allocation mémoire (2/3)
� Exemple de création d’une variable dynamique non in itialisée
(ou Allocation d’un pointeur)
type Un_Ptr_Int is access Integer ;
type Tab is array (1..6) of Boolean ;
type Un_Ptr_Tab is access Tab ;
P : Un_Ptr_Int ; M : Un_Ptr_Tab ;
beginP := new Integer ;M := new Tab ;
P M?
?
?
?
?
?
?
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
93
Chap. 5 : Les pointeurs : Allocation mémoire (3/3)
� Création d’une variable dynamique initialisée
beginP := new Integer'(23) ;M := new Tab'(others => true) ;
P
M
23
true true true true true true
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
94
Chap. 5 : Les pointeurs : Accès à la variable dynam ique (1/4)
� Utilisation des pointeurs : accès aux variables dyn amiques� Forme générale
� Exemple
beginP.all := 23 -- variable pointée par P (dont l’adresse est dans P)M.all(2) := False : -- variable pointée par M (c’est un tableau)
NomPointeur.all « zone pointée » par NomPointeur
P 23
P.all (variable pointée par P ; contient 23)
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
95
Chap. 5 : Les pointeurs : Accès à la variable dynam ique(2/4)
� Réservation mémoire et initialisation de la zone mém oire réservée
type Ptr_Int is access Integer ;
P : Ptr_Int ; begin
P := new Integer'(23) ;
type Ptr_Int is access Integer ;
P : Ptr_Int ; begin
P := new Integer ;P.all := 23 ;
P 23 P ?23
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
96
Chap. 5 : Les pointeurs : Accès à la variable dynam ique (3/4)
� variables dynamiques d’un type composé (tableau ou structure)
type Tab is array (1..8) of Boolean ;
type Ptr_Tab is access Tab ;
M : Ptr_Tab := null ;
beginM := new Tab'(others => True) ;for i in Tab'range loop
if M.all(i) then….
end if ;end loop;
type Tab is array (1..8) of Boolean ;type Ptr_Tab is access Tab ;
M : Ptr_Tab := null ;
beginM := new Tab'(others => True) ;for i in Tab'range loop
if M(i) then….
end if ;end loop ; Omission de « .all »
M null ;
M true true true true true true
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
97
Chap. 5 : Les pointeurs : Accès aux variables dynam iques (4/4)
� Accès aux variables dynamiques d’un type composé (s uite)
type Tab is array (1..8) of Boolean ;type Ptr_Tab is access Tab ;
M : Ptr_Tab := null ;
beginM := new Tab'(others => True) ;for i in M.all' range loop
if M.all(i) then…
end if ;end loop;
type Tab is array (1..8) of Boolean ;type Ptr_Tab is access Tab ;
M : Ptr_Tab := null ;
beginM := new Tab'(others => True) ;
for i in M'range loopif M(i) then
…end if ;
end loop ;
Attribut classique de la variable M.all ( qui est de type Tab)
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
98
Chap. 5 : Les pointeurs : pointeur vs. variable dyn amique (1/3)
� Ne pas confondre pointeur et la variable pointée
� Que se passe-t-il à l’exécution ?
type Ptr_Int is access Integer ;
P : Ptr_Int ; begin
P := new Integer'(23) ;put ( P ) ;
type Ptr_Int is access Integer ;
P : Ptr_Int ; begin
P := new Integer'(23) ;put ( P.all ) ;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
99
Chap. 5 : Les pointeurs : pointeur vs. variable dyn amique (2/3)
� Contenu de P1 et P2 après exécution ? Contenu de P1 .all et P2.all ?
� Dessiner les boîtes !
type Ptr_Int is access Integer ;
P1, P2 : Ptr_Int; begin
P1 := new Integer’(23) ; P2 := P1;put ( P1.all ) ;put ( P2.all ) ;
type Ptr_Int is access Integer ;
P1, P2 : Ptr_Int; begin
P1 := new Integer’(23) ; P2 := P1 ;P2.all := 21 ;put ( P1.all ) ;put ( P2.all ) ;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
100
Chap. 5 : Les pointeurs : pointeur ou variable dyna mique (3/3)
� Contenu de P1 et P2 après exécution dans chaque cas ? Contenu de P1.all et P2.all ?
� Dessiner les boîtes !
type Ptr_Int is access Integer ;
P1, P2 : Ptr_Int;
beginP1 := new Integer’(23) ;P2 := new integer’(21);P2.all := P1.all ;put ( P1.all ) ;put ( P2.all ) ;
type Ptr_Int is access Integer ;
P1, P2 : Ptr_Int;
beginP1 := new Integer’(23) ;P2 := new integer’(21);P2 := P1 ;put ( P1.all ) ;put ( P2.all ) ;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
101
Chap. 5 : Les pointeurs : Egalité entre ptrs ou entr e var. pointées
type Ptr_Int is access Integer ;
P1, P2 : Ptr_Int; begin
P1 := new Integer’(23) ;P2 := new integer;P2.all := P1.all;-- P1 = P2 ?? -- P1.all=P2.all ??
type Ptr_Int is access Integer ;
P1, P2 : Ptr_Int; begin
P1 := new Integer’(23) ; P2 := P1;-- P1 = P2 ?? -- P1.all=P2.all ??
L’expression P1 = P2 vaut TRUE si P1 et P2 contie nnent la même adresse (ie pointent sur la même variable dynamique ou pointent tous les deux sur null )
L’expression P1.all = P2.all prend la valeur TRUE si P1 et P2 pointent sur des variables contenant la même valeur
P1 23
P2 23
P1
23
P2
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
102
Chap. 5 : Les pointeurs : utilisation
� Structures de données dynamiques
� Listes � à travers des exemples
� Arbres, graphes –cf. module suivant
� Dimensionnement dynamique de tableaux (sans bloc d eclare)
� En fin de chapitre
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
103
Chap. 5 : Les pointeurs - Structure de liste
� Gérer la liste des personnes s'inscrivant pour une course à pieds� On ne sait pas a priori combien de personnes vont participer à cette
course� Des nouveaux participants peuvent arriver à tout moment
� Des participants peuvent annuler à tout moment
� Pour chaque coureur� Nom� Numéro de dossard
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
104
Chap. 5 : Les pointeurs : structure de liste
� Structure de données � Déclarations des types
subtype Chaine3 is String(1..3);
type Un_Coureur;type Un_Ptr_Coureur is access Un_Coureur;
type Un_Coureur is recordNom : Chaine3 := (others => ' ');Dossard : Natural;Suivant : Un_Ptr_Coureur;
end record;
Déclaration de la liste : une seule variable quel que soit le nombre d’éléments
Deb_Liste : Un_Ptr_Coureur;
� Gestion de la liste : algorithmes classiques� Parcours de la liste (par exemple pour afficher tous les éléments)� Rechercher si un élément appartient à la liste� Insérer / Supprimer un élément� …
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
105
Chap. 5 : Les pointeurs : Affichage de la liste
� version itérative
procedure Afficher_Coureurs (L : in Un_Ptr_Coureur) isAux : Un_Ptr_Coureur := L;
beginPut_Line(" la liste des coureurs est : ");while Aux /= null loop
Put (" ") ;Put ( Aux.all.Nom );Put( Aux.all.Dossard) ;New_Line;Aux := Aux.all.Suivant;
end loop;end Afficher_Coureurs;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
106
Chap. 5 : Les pointeurs : Affichage de la liste
� version récursive
procedure Afficher_Coureurs (L : in Un_Ptr_Coureur) isbegin
if L /= null then-- affichage du 1er coureurPut (" ");Put (L.all.Nom);Put (L.all.Dossard,4);New_Line;-- affichage de la suiteAfficher_Coureurs (L.all.suiv);
end if;end Afficher_Coureurs;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
107
Chap. 5 : Les pointeurs : affichage d’une liste
� Que fait ce sous-programme ?
procedure Afficher_Coureurs (L : in Un_Ptr_Coureur) isbegin
if L /= null then-- affichage de la suiteAfficher_Coureurs (L.all.suiv);-- affichage du 1er coureurPut (" ");Put (L.all.Nom);Put (L.all.Dossard,4);New_Line;
end if;end Afficher_Coureurs;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
108
Chap. 5 : Les pointeurs - Recherche d’un élément dan s une liste
� Le coureur est identifié par son nom
function Chercher_Coureur ( Le_Nom : in chaine3 ; Dans : in Un_Ptr_Coureur ) return Boolean is
Aux : Un_Ptr_Coureur;Trouve : boolean :=false;
BeginAux := Dans;while Aux/=null and not Trouve loop
If Aux.all.nom = Le_Nom thenTrouve := True;
else -- on avance dans la listeAux := Aux.all.suiv;
end if;end loop;return Trouve;
end Ajouter_Coureur;
Remarque 1 : on pourrait retourner le pointeur sur l’élément recherché
Remarque 3 : version récursive ?
Remarque 2 : algo proche de celui de la recherche dans un tableau
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
109
Chap. 5 : Les pointeurs - Ajout d’un élément en débu t de liste
� Le nom et le num de dossard sont donnés
procedure Ajouter_Coureur ( L : ?? Un_Ptr_Coureur ; Le_Nom : in chaine3 ; Le_Num : in Natural) is
Aux : Un_Ptr_Coureur ;begin
-- réservation mémoireAux : = new Un_Coureur;-- actualisation des informations Aux.all.Nom := Le_Nom; Aux.all.Num := Le_Num;-- réalisation des chaînagesAux.all.suiv:= L;L:=Aux;
end Ajouter_Coureur; Mode de passage de L?
-- réservation mémoire-- actualisation des informations -- réalisation des chaînagesL := new Un_Coureur’(Le_Nom,Le_Num,L) ;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
110
Chap. 5 : Les pointeurs - Structure de liste
� Ajout d’un élément en début d’une liste
� Démarche générale
� 1- Faire la réservation mémoire
� 2- Actualiser les informations
� 3- Trouver l’endroit d’insertion
� Algo de recherche
� Est ce possible si on pointe sur l’élément qui suivra celui que l’on veut insérer ?
� � On a besoin d’avoir un pointeur sur l’élément qui précède
� 4- Réaliser les chaînages
� Attention aux cas particuliers
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
111
Chap. 5 : Les pointeurs – Suppression du 1 er coureur de la liste
procedure Sup_1er_Coureur ( L : ?? Un_Ptr_Coureur) isbegin
if L= null then-- il n’y a aucun coureur dans la liste
Raise Suppression_Impossible;else
L : = L.all.suiv ;-- liberer l’espace inutilisé � cf module suivant
end Sup_1er_Coureur ;
Mode de passage de L ?
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
112
Chap. 5 : Les pointeurs – Structure de liste
� Suppression d’’un coureur dont le nom est fourni
� Démarche
� 1- chercher le coureur à supprimer
� Algo de recherche
� On a besoin d’avoir un pointeur sur l’élément qui précède
� 2- Modifier les chaînages
� Attention au cas particuliers
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
113
Chap. 5 : Les pointeurs - Utilisations de pointeurs
� Structures de données dynamiques � Listes � vues à travers un exemple� Arbres, graphes � cf. module suivant
� Dimensionnement dynamique de tableaux
� Déclarer un tableau dont la dimension est fournie par l’utilisateur en début de programme
� 2 solutions � Bloc declare (cf. chapitre types tableaux non contraints)
� Avec pointeur
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
114
Chap. 5 : Les pointeurs - Dimensionnement dynamique de tableaux
beginput ("nombre de composantes ? ");get (Nbre_Comp) ;declareMon_Tab : Un_Tab (1..Nbre_Comp);
beginfor I in Mon_Tab’range loop
Mon_Tab(I) :=0.0;end loop;
end ;end Exemple ;
type Un_Ptr_Sur_Tab is access Un_Tab ;P_Mon_Tab : Un_Ptr_Sur_Tab;begin
put ("nombre de composantes ? ");get (Nbre_Comp) ;
P_Mon_Tab:=new Un_Tab (1..Nbre_Comp);
for I in P_Mon_Tab.all’range loopP_Mon_Tab.all (I) :=0.0;
end loop;
end Exemple;
procedure Exemple istype Un_Tab is array (Integer range <>) of Float ;
Nbre_Comp : Natural ;
G.AURIOL, C. MERCE, P. ESQUIROL
2
MIC
115
Chap. 5 : Les pointeurs - Dimensionnement dynamique de String
� Exemple
type Ref_String is access String ;
S : Ref_String ;
beginS := new String (1..8) ;S := new String’("bonjour!") ;S.all := "salut---" ;S := new string(1..20) ;
G.AURIOL, C. MERCE, P. ESQUIROL