Structures de données IFT-2000

Slides:



Advertisements
Présentations similaires
Piles, files et listes: notions théoriques
Advertisements

La classe String Attention ce n’est pas un type de base. Il s'agit d'une classe défini dans l’API Java (Dans le package java.lang) String s="aaa"; // s.
Cours n° 8 Conception et Programmation à Objets
1 UMLV 1. Introduction 2. Hachage ouvert 3. Hachage fermé 4. Implémentation des fonctions Méthodes de hachage.
Approfondissement du langage
C.
Chap. 1 Structures séquentielles : listes linéaires
8. Les tableaux P. Costamagna – ISEN N1.
Chapitre IV. Structures linéaires (piles, files, listes chaînées)
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées
Structures de données linéaires
Les méthodes en java Une méthode est un regroupement d’instructions ayant pour but de faire un traitement bien précis. Une méthode pour être utilisée.
Algorithmique et Programmation
Leçon 6 : Structures de données dynamiques IUP 2 Génie Informatique Méthode et Outils pour la Programmation Françoise Greffier.
II. Chaînage, SDD séquentielles
Programme de baccalauréat en informatique Algorithmique et programmation IFT-1001 Thierry EUDE Hatem Mahbouli Laboratoire #12 Département dinformatique.
IFT-2000: Structures de Données Listes chaînées Dominic Genest, 2009.
Les tris.
Structures de données IFT-2000
Complément Le diagramme des classes
Leçon 2 : Surcharge des opérateurs IUP 2 Génie Informatique Méthode et Outils pour la Programmation Françoise Greffier Université de Franche-Comté.
Structures de données IFT Abder Alikacem La classe vector Édition Septembre 2009 Département dinformatique et de génie logiciel.
Abder Alikacem Semaine 13 La récursivité
Code des opérateurs Appartenance à une liste ( appartient_l ) –Prototype: Bool appartient_l(type_el x, liste L) –Pré-conditions: aucunes. –Post-conditions:
IFT-2000: Structures de données Plan de cours Théorie du contrat Types abstraits Dominic Genest, 2009.
IFT-2000: Structures de données
IFT-10541A : Hiver 2003 Semaine 5 : Piles et files.
IFT-10541A : Hiver 2003 Semaine 1 : Type de données abstrait.
Structures de données IFT-2000
Structures de données IFT Abder Alikacem La classe string Département dinformatique et de génie logiciel Édition Septembre 2009 Département dinformatique.
Structures de données IFT Abder Alikacem Espace de nommage Département d’informatique et de génie logiciel Édition Septembre 2009.
Structures de données IFT-2000 Abder Alikacem Espace de nommage Département dinformatique et de génie logiciel Édition Septembre 2009 Département dinformatique.
Structures de données IFT-2000 Abder Alikacem Introduction au cours Semaine 1 Département dinformatique et de génie logiciel Édition Septembre 2009.
Structures de données IFT-2000
Structures de données IFT-2000
Structures de données IFT-2000 Abder Alikacem Standard Template library Édition Septembre 2009 Département dinformatique et de génie logiciel.
Structures de données IFT Abder Alikacem Gestion des exceptions Département dinformatique et de génie logiciel Édition Septembre 2009.
Structures de données IFT-10541
Programme de baccalauréat en informatique Programmation Orientée Objets IFT Thierry EUDE Module 7 : Classes et fonctions paramétrables Département.
IFT Structures de données
Présentation Structures de Données et TDA
COURS DE PROGRAMMATION ORIENTEE OBJET :
Leçon 1 : notion dobjet IUP Génie Informatique Besançon Méthode et Outils pour la Programmation Françoise Greffier Université de Franche-Comté.
IFT-2000: Structures de données Piles et files Dominic Genest, 2009.

Structures de données IFT-2000
IFT Structures de données Abder Alikacem Département dinformatique et de génie logiciel.
Structures de données IFT-10541
Structures de données IFT-2000 Abder Alikacem La récursivité Semaine 5 Département dinformatique et de génie logiciel Édition Septembre 2009.
Structures de données IFT Abder Alikacem Linéarisation des matrices Département dinformatique et de génie logiciel Édition septembre 2009.
Structures de données IFT-2000 Abder Alikacem Semaine 11 Gestion des arbres binaires de tri et de recherche. Les arbres cousus. Les arbres n-aires Département.
Structures de données IFT-2000 Abder Alikacem Retour sur les listes ordonnées Département dinformatique et de génie logiciel Édition Septembre 2009.
Structures de données IFT-2000 Abder Alikacem La récursivité Département d’informatique et de génie logiciel Édition Septembre 2009.
Structures de données IFT-2000
Structures de données IFT-2000
Structures de données IFT-2000
Structures de données IFT-2000 Abder Alikacem Introduction Semaine 1 Département d’informatique et de génie logiciel Édition Septembre 2009.
Structures de données IFT Abder Alikacem Semaine 2 Tests sur les pointeurs Département d’informatique et de génie logiciel Édition Janvier 2009.
Structures de données IFT-10541
Le langage C Structures de données
LES PILES ET FILES.
1 Structures des données. 2  Le tableau permettait de désigner sous un seul nom un ensemble de valeurs de même type, chacune d'entre elles étant repérée.
Tutorat en bio-informatique
Tutorat en bio-informatique Le 14 novembre Au programme… Les objets –Propriétés (attributs) –Constructeurs –Méthodes.
Liste Une liste est une séquence d’éléments. Concept important: Chaque élément possède une position dans la liste. Notation: De quelles opérations a-t-on.
8PRO107 Éléments de programmation Les tableaux. Étude de cas 1 Description du problème : Lire une liste d’entiers et l’afficher d’abord dans le même ordre.
Structures de données IFT-2000 Abder Alikacem Pointeurs, références et gestion dynamique de la mémoire. QQ éléments techniques du C++. Semaine 2..suite.
Structures de données IFT-2000 Abder Alikacem Laboratoire #1 Département d’informatique et de génie logiciel Édition Septembre 2009.
Transcription de la présentation:

Structures de données IFT-2000 Abder Alikacem Types de données abstraits (2) Semaine 1 Édition Septembre 2009 Département d’informatique et de génie logiciel

Plan Exemple d’un TDA: une liste ordonnée Utilités Spécifications Implantation Structures de données génériques Gestion des exceptions

Introduction L’objectif de cette partie du cours est de commencer à décrire des représentations des structures de base utilisées en informatique telles les listes. Ces derniers seront vus en termes de types abstraits. Un autre objectif recherché est de donner des exemples de séparations des représentations logiques à travers les TDA des implémentations physiques. Enfin, un dernier objectif est de décrire les outils du langage C++ qu’on aurait besoin pour implanter les structures de données dans notre cours.

Les listes Les listes sont des structures informatiques qui permettent de garder en mémoire des données en respectant un certain ordre: on peut ajouter, enlever ou consulter un élément en début ou en fin de liste, vider une liste ou savoir si elle contient un ou plusieurs éléments. La structure de liste particulièrement souple et dont les éléments sont accessibles à tout moment. Toute suite d’informations inscrites les unes après les autres est une liste. Exemple : liste d’étudiants, liste d’inventaire, liste des absents, …

Les listes Une liste est définie comme étant une suite ordonnée d’éléments. L’ordre signifie que chaque élément possède une position dans la liste. Une liste: structure récursive ( a (b ( c (d)))) a b c Une liste peut être vu comme une structure récursive : liste = élément + liste OU liste = vide

Un exemple de liste: une liste ordonnée Liste ordonnée d’éléments (int) L = <8,1,5,4,6> L1 = 8, L2 = 1, L3 = 5, L4 = 4, L5 = 6 <8,1,5,4,6>  <8,1,4,6,5> Utilité?

Un exemple de liste: une liste ordonnée Liste ordonnée d’éléments (int) L = <8,1,5,4,6> L1 = 8, L2 = 1, L3 = 5, L4 = 4, L5 = 6 <8,1,5,4,6>  <8,1,4,6,5> Utilité? liste de réquisitions Réq.#3 Réq.#2 Réq.#1 Réq.#1: 2000 chemises 1000 pantalons 1500 cravates ...

Un exemple de liste: une liste ordonnée Liste ordonnée d’éléments (int) L = <8,1,5,4,6> L1 = 8, L2 = 1, L3 = 5, L4 = 4, L5 = 6 <8,1,5,4,6>  <8,1,4,6,5> Utilité? liste de réquisitions file d’attente 3 2 1

Un exemple de liste: une liste ordonnée Liste ordonnée d’éléments (int) L = <8,1,5,4,6> L1 = 8, L2 = 1, L3 = 5, L4 = 4, L5 = 6 <8,1,5,4,6>  <8,1,4,6,5> Utilité? liste de réquisitions file d’attente Parcours d’un graphe 1 8 5 4 6

Un exemple de liste: une liste ordonnée Liste ordonnée d’éléments (int) L = <8,1,5,4,6> L1 = 8, L2 = 1, L3 = 5, L4 = 4, L5 = 6 <8,1,5,4,6>  <8,1,4,6,5> Utilité? liste de réquisitions file d’attente Parcours d’un graphe 1 8 x 5 4 x 6

Un exemple de liste: une liste ordonnée Liste ordonnée d’éléments (int) L = <8,1,5,4,6> L1 = 8, L2 = 1, L3 = 5, L4 = 4, L5 = 6 <8,1,5,4,6>  <8,1,4,6,5> Utilité? liste de réquisitions file d’attente Parcours d’un graphe 1 8 5 4 6

Opérateurs sur les listes Manipulations (opérateurs): L L = ? (i.e., L = 0?) x  L? Li x = L? L  L +i x L  -i L L  L - x L = L’? L  L’? L  L’? lister L L = <8,1,5,4,6>

Opérateur: nombre d’éléments? Manipulations (opérateurs): L L = ? (i.e., L = 0?) x  L? Li x = L? L  L +i x L  -i L L  L - x L = L’? L  L’? L  L’? lister L L = <8,1,5,4,6> L = 5

Opérateur: liste vide? L = <8,1,5,4,6> Non! Manipulations (opérateurs): L L = ? (i.e., L = 0?) x  L? Li x = L? L  L +i x L  -i L L  L - x L = L’? L  L’? L  L’? lister L L = <8,1,5,4,6> Non!

Opérateur: appartenance Manipulations (opérateurs): L L = ? (i.e., L = 0?) x  L? Li x = L? L  L +i x L  -i L L  L - x L = L’? L  L’? L  L’? lister L L = <8,1,5,4,6> 4  L? Oui! 9  L? Non!

Opérateur: accès L = <8,1,5,4,6> Manipulations (opérateurs): L L = ? (i.e., L = 0?) x  L? Li x = L? L  L +i x L  -i L L  L - x L = L’? L  L’? L  L’? lister L L = <8,1,5,4,6> L1 = 8, L2 = 1, L3 = 5, L4 = 4, L5 = 6

Opérateur: rang (indice) Manipulations (opérateurs): L L = ? (i.e., L = 0?) x  L? Li x = L? L  L +i x L  -i L L  L - x L = L’? L  L’? L  L’? lister L L = <8,1,5,4,6,1> 81, 12, 53, 44, 65, 90

Opérateur: ajout L = <8,1,5,4,6> L  L +1 9: <9,8,1,5,4,6> Manipulations (opérateurs): L L = ? (i.e., L = 0?) x  L? Li x = L? L  L +i x L  -i L L  L - x L = L’? L  L’? L  L’? lister L L = <8,1,5,4,6> L  L +1 9: <9,8,1,5,4,6> L  L +2 9: <8,9,1,5,4,6> L  L +3 9: <8,1,9,5,4,6> L  L +4 9: <8,1,5,9,4,6> L  L +5 9: <8,1,5,4,9,6> L  L +6 9: <8,1,5,4,6,9> L  L +7 9: <>

Opérateur: retrait du rang Manipulations (opérateurs): L L = ? (i.e., L = 0?) x  L? Li x = L? L  L +i x L  -i L L  L - x L = L’? L  L’? L  L’? lister L L = <8,1,5,4,6> L  -1 L: <1,5,4,6> L  -2 L: <8,5,4,6> L  -3 L: <8,1,4,6> L  -4 L: <8,1,5,6> L  -5 L: <8,1,5,4> L  -6 L: <8,1,5,4,6>

Opérateur: retrait d’élément Manipulations (opérateurs): L L = ? (i.e., L = 0?) x  L? Li x = L? L  L +i x L  -i L L  L - x L = L’? L  L’? L  L’? lister L L = <8,1,5,4,6,1> L  L - 8: <1,5,4,6,1> L  L - 1: <8,5,4,6,1> L  L - 5: <8,1,4,6,1> L  L - 4: <8,1,5,6,1> L  L - 6: <8,1,5,4,1> L  L - 9: <8,1,5,4,6,1>

Opérateur: test d’égalité Manipulations (opérateurs): L L = ? (i.e., L = 0?) x  L? Li x = L? L  L +i x L  -i L L  L - x L = L’? L  L’? L  L’? lister L L  = <8,1,5,4,6> L’ = <8,1,4,6,5> Non!

Opérateur: inclusion stricte Manipulations (opérateurs): L L = ? (i.e., L = 0?) x  L? Li x = L? L  L +i x L  -i L L  L - x L = L’? L  L’? L  L’? lister L L  = <8,4,5> L’ = <8,1,4,6,5> Oui! L  = <8,1,4,6,5> L’ = <8,1,4,6,5> Non!

Opérateur: inclusion L = <8,4,5> L’ = <8,1,4,6,5> Manipulations (opérateurs): L L = ? (i.e., L = 0?) x  L? Li x = L? L  L +i x L  -i L L  L - x L = L’? L  L’? L  L’? lister L L  = <8,4,5> L’ = <8,1,4,6,5> Oui! L  = <8,1,4,6,5> L’ = <8,1,4,6,5> Oui!

Opérateur: listage L = <8,1,5,4,6> Manipulations (opérateurs): L = ? (i.e., L = 0?) x  L? Li x = L? L  L +i x L  -i L L  L - x L = L’? L  L’? L  L’? lister L L = <8,1,5,4,6> 8,1,5,4,6

Opérateur: sous-liste Autres opérateurs?

Opérateur: sous-liste Autres opérateurs? sous-liste de L, de i, pour une longueur de n: L[i,n] L = <8,1,5,4,6> L[2,3] = <1,5,4>

Opérateur: concaténation Autres opérateurs? sous-liste de L, de i, pour une longueur de n: L[i,n] concaténation de listes: L + L’ L = <8,1,5,4,6> L[2,3] = <1,5,4> L = <8,1,5,4,6> L’ = <1,9> L + L’ = <8,1,5,4,6,1,9>

Spécifications « langage C » L  L +i x prototype de la fonction implantant l’opérateur: Liste ajouterListe(Liste l, TypeEl x, int i, int *err); préconditions  conditions devant être vraies au départ pour assurer le bon fonctionnement de l ’opérateur l ne doit pas être pleine et i  [1,|L|+1] postconditions  conditions étant vraies (observables) après l’application (correcte) de l’opérateur l contient x et *err = OK si les préconditions sont respectées l est inchangée sinon et *err contient: PAM si L est pleine, PERR si i  [1,|L|+1] valeur retournée en output de l’application de l ’opérateur: l mise à jour ou l inchangée en cas d'erreurs

Spécifications « C++ » prototype de la méthode implantant l’opérateur: L  L +i x prototype de la méthode implantant l’opérateur: void ajouter(TypeEl x, int i) throw(range_error, length_error); préconditions  conditions devant être vraies au départ pour assurer le bon fonctionnement de l ’opérateur La liste ne doit pas être pleine et i  [1,|L|+1] postconditions  conditions étant vraies (observables) après l’application (correcte) de l’opérateur La liste contient x si les préconditions sont respectées La liste est inchangée sinon et : Exceptions  les exceptions lancées par la méthode lors d’un problème si L est pleine, si i  [1,|L|+1] valeur retournée en output de l’application de l ’opérateur: aucune

Spécifications version dOxygen L  L +i x prototype de la méthode implantant l’opérateur: void ajouter(TypeEl x, int i) throw(range_error, length_error); /** * \brief Ajouter un nouvel élément dans la liste * * \pre il y a assez de mémoire pour ajouter l'élément x * \pre la position d'ajout, pos, est comprise entre 1 et |L|+1 * \post la liste comprend un élément de plus * \post la liste est inchangée sinon * \exception range_error si la position est erronée * \exception length_error si pas assez de mémoire */

Spécifications du type liste: -i L -i L prototype: Liste enleverListe (Liste l, int i, int *err); préconditions: i  [1,|L|] postconditions: l est inchangée si i  [1,|L|] avec *err = PERR l contient un élément de moins, l’élément Li avec *err=OK, sinon valeur(s) retournée(s): l mise à jour ou inchangée en cas d'erreurs

Spécifications du type liste: -i L -i L prototype: void enlever(int i) throw(range_error); préconditions: i  [1,|L|] postconditions: La liste contient un élément de moins, l’élément Li si la précondition n’est pas satisfaite La liste est inchangée si i  [1,|L|] sinon Exception: si la position est erronée valeur retournée: aucune

Spécifications du type liste: -i dOxygen L -i L prototype: void enlever(int i) throw(range_error); /** * \brief Enlever l’élément en position i dans la liste * * \pre i est compris entre 1 et |L| * \post la liste comprend un élément de moins * \post la liste est inchangée sinon * \exception range_error si la position est erronée */

Spécifications du type liste: - L  L - x prototype: Liste enleverElListe (Liste l, TypeEl x, int *err); préconditions: Aucune postconditions: l contient un élément x de moins (le premier rencontré), l inchangée si x  L et *err = OK valeur retournée: l inchangée si x n’appartenait pas à l l mise à jour sinon

Spécifications du type liste: - L  L - x prototype: void enleverEl (TypeEl x); préconditions: Aucune postconditions: La liste contient un élément x de moins (le premier rencontré), inchangée si x  L Exception aucune valeur retournée:

Spécifications du type liste: - dOxygen L  L - x prototype: void enleverEl (TypeEl x); /** * \brief EnleverEl dans la liste la première occurrence de x * * \post la liste comprend un élément de moins * \post la liste est inchangée si x  à la liste */

Spécification du type liste: Li prototype: TypeEl elementListe(Liste l, int i, int *err); préconditions: i  [1,|L|] postconditions: l est inchangée avec *Err = OK l est inchangée et *Err = PERR si i [1,|L|] valeur(s) retournée(s): Une copie de Li si la précondition est respectée Une valeur quelconque sinon

Spécification du type liste: Li prototype: TypeEl elementPos(int i) throw(range_error); préconditions: i  [1,|L|] postconditions: La liste est inchangée si i [1,|L|] La liste est inchangée sinon Exception : Si la position est erronée valeur(s) retournée(s): Une copie de Li si la précondition est respectée Une valeur quelconque sinon

Spécification du type liste: Li dOxygen Li prototype: TypeEl elementPos(int i) throw(range_error);; /** * \brief retourner l’élément en position i dans la liste * * \pre i est compris entre 1 et |L| * \post la liste est inchangée * \post l’élément en position i est retournée, une valeur quelconque sinon * \exception range_error si la position i est erronée */

Implantation du type liste ordonnée Implantation par tableau statique

Implantation du type liste ordonnée Implantation par tableau La liste peut être implantée à l'aide d'un tableau. Dans ce cas, il faut prévoir une taille maximum pour le tableau. L'opération d'impression des éléments d'une liste et de recherche d'un élément se font en temps linéaire. La recherche du k-ième élément se fait O(1) i.e. en un temps constant. Cependant les insertions et les suppressions d'éléments sont plus coûteuses. Par exemple, l'insertion à la position 0 nécessite le déplacement de tous les éléments de la liste pour libérer la position 0. Par conséquent la création d'une liste à l'aide de n insertions successives à partir de la position 0 nécessite un temps en O(n2) (pourquoi?).

Implantation du type liste ordonnée En langage C Implantation par tableau /******************************************************************** ModeleImplantationListe.h i.e. modèle d’implantation du type Liste ordonnée Version 1.0 Janvier 2007 (c) IFT-10541 Structures de données ********************************************************************/ #ifndef _LISTEC__H #define _LISTEC__H #define MAX_LISTE 100 typedef enum {FAUX, VRAI} Bool; /*le type booléen*/ typedef int TypeEl; /* le type de base de la liste */ typedef struct { TypeEl tab[MAX_LISTE]; /* représentation physique de la liste */ int cpt; /* la cardinalité de la liste */ } Liste; /* le type liste ordonnée */ #endif

Création de listes En langage C { Liste l; déclaration: Liste L1, L2; initialisation: L1 = initListe(&err); L2 = initListe(&err); Liste initListe(int * err) { Liste l; /*A: L’espace mémoire est suffisant.*/ l.cpt = 0; *err = OK; return l; }

Destruction de listes En langage C { … return l; } destruction: detruireListe(L1, &err); detruireListe(L2, &err); Liste detruireListe(Liste l, int * err) { … return l; }

Interface d’un type abstrait (invariable) En langage C Interface du type Liste /******************************************************************** Liste.h i.e. interface du type Liste ordonnée Version 1.0 Janvier 2007 (c) IFT-10541 Structures de données ********************************************************************/ #include "ModeleImplantationListe.h" #define OK 0 /* tout est correct */ #define LNI 1 /* liste non initialisée */ #define PAM 2 /* pas assez de mémoire*/ #define PERR 3 /* position erronée */ Liste initListe(int *err); /***************************************************************** prototype : Liste initListe(int *err) précondition : … etc..

Implémentation En langage C /******************************************************************** Liste.c Version 1.0 Janvier 2007 (c) IFT-10541 Structures de données ********************************************************************/ #include "Liste.h" Liste ajouterListe (Liste l, TypeEl x, int pos, int *err) { /* objectif: ajouter l'élément x à la liste l en position pos méthode: décaler vers la droite tous les éléments à partir de la fin de la liste, jusqu'à ce que pos soit atteint besoins: La liste l, l'élément x, l'indice d'insertion pos et MAX_LISTE, la taille maximale de la liste connu: MAX_LISTE entrée: l, x, pos sortie: La liste l mise à jour (si *err = OK), la liste l inchangée sinon. résultat: *err=OK si les pré sont respectées, PAM si pas assez de place, PERR si la position est erronée hypothèse: Pos est compris entre 1 et la taille de la liste + 1 (|L| + 1) inclusivement, il y a assez de place pour ajouter x. */ …

Implémentation En langage C Liste ajouterListe (Liste l, TypeEl x, int pos, int *err) { … if (l.cpt >= MAX_LISTE) { /* La liste est pleine. */ *err = PAM; return l; } /*A: La liste n'est pas pleine */ if ((pos < 1) || (pos > (l.cpt + 1))) /* Les paramètre fournis sont invalides. */ *err = PERR; /*A: pos >= 1 et pos <= taille de la liste + 1 */ *err = OK; //etc... En langage C

Implantation du type liste ordonnée En langage C++……

D’abord, quelques différences entre C++ et C en ce qui concerne le cours malloc(sizeof(float)*25) free(x) realloc(x,sizeof(float)*25); typedef struct { // […] } MaStruct; void fonction(MaStruct *m,float x); Aucun équivalent pour « private: », il faut user de discipline. float f(float a, int x, int *err) { if(x<a) { *err=PROBLEME; return 0.0f; } // […] } int x; for(x=0;x<2;x++) new float[25] delete x ou delete[] x Pas d’équivalent pour « realloc » struct MaStruct { void fonction(float x); }; Possibilité de rendre des membres privés à l’aide de « private: » float f(float a, int x) { if(x<a) throw PROBLEME; // […] } for(int x=0;x<2;x++)

D’abord, quelques différences entre C++ et C en ce qui concerne le cours typedef struct { float x[100]; int n; } Nombres; CodeErreur initNombres(Nombres *n); CodeErreur ajoutNombres(Nombres *n , float nouv_nbr); // etc. struct Nombres { Nombres(); void ajout(float nouv_nbr); // etc. private: float x[100]; int n; };

D’abord, quelques différences entre C++ et C en ce qui concerne le cours typedef enum { OK, Erreur } CodeErr; typedef struct { int matricule,nb_cours,age; char nom[50]; } Etudiant; Etudiant etudiants[40000]; int n; } Universite; CodeErr initUniversite(Universite *u); CodeErr ajoutUniversite(Universite *u, Etudiant et); int trouve_age(const Universite *u, int matricule); void detruitUniversite(Universite *u); struct Etudiant { public: int matricule,nb_cours,age; char nom[50]; }; struct Universite Universite(); void ajout(Etudiant et); int trouve_age(int matricule) const; ~Universite(); private: Etudiant etudiants[40000]; int nb_etudiants;

D’abord, quelques différences entre C++ et C en ce qui concerne le cours Universite::Universite() { n=0; } void Universite::ajout(Etudiant et) if(n==40000) throw runtime_error(‘’L’université est pleine!’’); etudiants[n++]=et; int Universite::trouve_age(int matricule) const for(int i=0;i<n;i++) if(etudiants[i].matricule==matricule) return etudiants[i].age; return -1; // Convention pour matricule introuvable. Universite::~Universite() CodeErr initUniversite(Universite *u) { u->n=0; return OK; } CodeErr ajoutUniversite(Universite *u, Etudiant et) if(u->n==40000) return Erreur; u->etudiants[u->n++] = et; int trouve_age(const Universite *u, int matricule) int i; for(i=0;i<u->n;i++) if(u->etudiants[i].matricule==matricule) return u->etudiants[i].age; return -1; // Convention pour matricule introuvable. void detruitUniversite(Universite *u) C++ C

Encapsulation. struct (C) vs classe (C++) //Fichier ModeleImplantationListe.h #ifndef _LISTEC__H #define _LISTEC__H #define MAX_LISTE 100 typedef enum {FAUX, VRAI} Bool; typedef struct { int tab[MAX_LISTE]; int cpt; } Liste; #endif //Fichier Liste.h #include "ModeleImplantationListe.h" #include "CodesErreur.h" Liste initListe(int * err); /* */ int tailleListe(Liste l, int *err); Bool estVideListe(Liste l, int *err); Liste ajouterListe(Liste l, int x, int pos, int *err); // etc.. Version de base // Fichier Liste.h #include <iostream> using namespace std; #ifndef _LISTEC__H #define _LISTEC__H #define MAX_LISTE 100 class Liste { private: int tab[MAX_LISTE]; int cpt; public: Liste(); //constructeur ~Liste(); //destructeur void ajouter (int x, int pos); int taille() const ; bool estVide() const; //etc… }; #endif

Implantation du type liste ordonnée Note 1 Remarquez que le mot clé const est utilisé à la fin des déclarations de fonction membres de la classe Liste en mode lecture seule, à savoir taille () et estVide(). Afin de mieux protéger un programme, il y a tout intérêt à déclarer comme constantes les fonctions qui ne sont pas censées modifier l’état des objets auxquels elles sont liés. On bénéficiera ainsi d’une aide supplémentaire du compilateur qui empêchera tout ajout de code modifiant l’état de l’objet dans la fonction.

Implantation de la classe Liste en C++ //Liste.cpp #include "Liste.h" Liste::Liste() { cpt = 0; } bool Liste::estVide() const return taille()==0; Liste:: ~Liste() cpt=0; //Note.. int Liste::taille() const return cpt; #include "Liste.h "   void Liste::ajouter (int x, int pos) { if(cpt==MAX_LISTE) return; if (pos < 1 || pos > taille() +1) return; pos--; for (i = (cpt - 1); i >= pos; i--) tab[i+1] = tab[i]; } tab[pos] = x; cpt++;

Utilisation de la classe Liste //Main.cpp #include "Liste.h" int main() { Liste l; //appel automatique du constructeur l.ajouter(1,1); l.ajouter(2,2); l.ajouter(3,3); if(l.estVide()) cout << "liste vide" << endl; else cout << "liste non vide" << endl; cout << l.taille() << endl; l.~Liste(); //destruction de la liste, inutile… // etc.. return 0; }

Définition de la classe Liste en C++ (version 2) #ifndef _LISTEC__H #define _LISTEC__H #include <iostream> using namespace std; #define MAX_LISTE 5 // Le type Liste class Liste{ public: Liste(); //constructeur ~Liste(); //destructeur Liste(const Liste &); //constructeur de copie Liste& operator = (const Liste&); // surcharge de l’opérateur = void ajouter(int x, int pos); bool estVide() const; int taille() const; friend ostream& operator << (ostream&, const Liste& p); Liste& operator = (const Liste&); private: int tab[MAX_LISTE]; int cpt; }; #endif Constructeur de copie Surcharge op. =

Définition de la classe Liste en C++ (version 2) Constructeur de copie Le constructeur par copie est une méthode implicite dans toute classe. Cette méthode est appelée automatiquement dans les opérations suivantes : Création et initialisation d ’une nouvelle instance X I2=I1; X I2(I1); passage d ’un argument par valeur retour d ’une fonction return (I); // une copie de I est retournée

Définition de la classe Liste en C++ (version 2) Constructeur de copie class Liste { public : Liste (const Liste&); // constructeur par copie ... }; Par défaut, cette méthode implicite réalise une copie des valeurs qui correspondent à la section private de la classe. Si l ’implantation d ’un objet est dynamique le constructeur par copie, réalisera par défaut une copie de pointeur. ==> Surcharger cet opérateur afin qu’il crée un vrai clone de l ’instance qui le déclenche.

Implémentation (version 2) #include "Liste.h" int main() { //on crée une instance d'une liste Liste l; l.ajouter(1,1); //ajout de 1 en pos =1 //... //copie de l'appel du constructeur de copie Liste l1(l); //Affichage de la copie cout << l1 << endl; return 0; } Constructeur de copie Liste :: Liste (const Liste& l) { cpt = l.cpt; for (int i=0; i<cpt;i+=1) tab[i]=l.tab[i]; } ostream& operator << (ostream& f, const Liste& l){ for (int i=0; i<l.cpt;i++) f << l.tab[i]<<" "; return f;

Définition de la classe Liste en C++ (version 2) Surcharge de l’opérateur = L ’opérateur d ’affectation est une méthode implicite dans toute classe. Par défaut, il réalise une copie des valeurs qui correspondent à la section private de la classe. Liste l1; ... l1.tab 2 5 8 3 Liste l2; l2=l1; Problème : Toute modification du tableau des entiers dans la liste l1 se répercute dans la liste l2 (et inversement) l2.tab

Définition de la classe Liste en C++ (version 2) Surcharge de l’opérateur = Pour réaliser une vraie copie de pile par affectation, il faut surcharger l ’opérateur implicite. Liste l1; ... l1.tab 2 5 8 3 Liste l2; l2=l1; l2.tab 2 5 8 3

Définition de la classe Liste en C++ (version 2) Surcharge de l’opérateur = class Liste { public: Liste operator = (const Liste&); // opérateur d ’affectation l1 = l2 <=> l1.operator = (l2); Le comportement habituel de l’opérateur = autorise à enchaîner les affectations : l1=l2=l3; => la fonction retourne une référence et l ’argument est une référence.

Implémentation (version 2) #include "Liste.h" int main() { //on crée une instance d'une liste Liste l; l.ajouter(1,1); //ajout de 1 en pos =1 //... Liste l1; l1 = l; // appel de l’op. = surchargé //Affichage de la copie cout << l1 << endl; return 0; } Surcharge de l’op. = Liste& operator = (const Liste&){ cpt = l.cpt; for (int i=0; i<cpt;i+=1) tab[i]=l.tab[i]; return (*this); //retourner : une référence sur // ’objet courant }

Forme canonique de Coplien Remarque On dit qu'une classe est sous forme canonique de Coplien si elle contient les éléments suivants : template <typename T> class Liste { public: Liste(const int = MAX_LISTE) throw(bad_alloc); // constructeur Liste(const Liste&) throw(bad_alloc); // constructeur de copie ~Liste(); // destructeur Liste<T>& operator = (const Liste<T>&) throw (bad_alloc); //surcharge de = //… On fera de sorte que toutes les classes que nous Implanterons auront ces méthodes au minimum.

Définition de la classe Liste en C++ (version 3.1) #include <iostream> using namespace std; #pragma warning( disable : 4290 ) #define MAX_LISTE 5 // Le type Liste class Liste{ public: Liste(); //constructeur ~Liste(); //destructeur Liste(const Liste&); //constructeur de copie void ajouter(int x, int pos) throw(int); // lancement d’un int bool estVide() const; int taille() const; friend ostream& operator << (ostream&, const Liste& p); Liste& operator = (const Liste&); private: int tab[MAX_LISTE]; int cpt; }; Gestion des exceptions Usage d’un int

Implémentation (version 3.1) int main() { Liste l; try //on essaie un ajout{ l.ajouter(1,1); l.ajouter(2,2); l.ajouter(4,8); // erreur.. //… } catch(int& code) { cerr << "ERREUR: " << code << endl; return 0; } .... void Liste::ajouter (int x, int pos) throw(int) { if (cpt==MAX_LISTE) throw 1; if (pos < 1 || pos > this->taille() +1) throw 2 ; //… }

Définition de la classe Liste en C++ (version 3.2) #include <iostream> using namespace std; #include <stdexcept> #pragma warning( disable : 4290 ) #define MAX_LISTE 5 // Le type Liste class Liste{ public: Liste(); //constructeur ~Liste(); //destructeur Liste(const Liste&); //constructeur de copie void ajouter(int x, int pos) throw(out_of_range, length_error); bool estVide() const; int taille() const; friend ostream& operator << (ostream&, const Liste& p); Liste& operator = (const Liste&); private: int tab[MAX_LISTE]; int cpt; }; Gestion des exceptions Usage d’une classe de la librairie stdexcept

Implémentation (version 3.2) int main() { Liste l; try //on essaie un ajout{ l.ajouter(1,1); l.ajouter(2,2); l.ajouter(4,8); // erreur.. //… } catch(exception& e) cerr << "ERREUR: " << e.what() << endl; return 0; } .... void Liste::ajouter (int x, int pos) throw(out_of_range, length_error); { if (cpt==MAX_LISTE) throw length_error("Ajouter:La liste est pleine"); if (pos < 1 || pos > this->taille() +1) throw out_of_range("Ajouter:Position d'ajout erronée"); //… }

Définition de la classe Liste en C++ (version 3.3) #include <iostream> using namespace std; #pragma warning( disable : 4290 ) #define MAX_LISTE 5 // Le type Liste class Liste{ public: Liste(); //constructeur ~Liste(); //destructeur Liste(const Liste&); //constructeur de copie void ajouter(int x, int pos) throw(Erreur); bool estVide() const; int taille() const; friend ostream& operator << (ostream&, const Liste& p); Liste& operator = (const Liste&); private: int tab[MAX_LISTE]; int cpt; }; Gestion des exceptions Usage d’une classe Erreur

Définition de la classe Liste en C++ (version 3.3) Suite.. class Erreur: public exception{ public: Erreur(int numero=0,std::string phrase="", int niveau=0) throw() :m_numero(numero),m_phrase(phrase),m_niveau(niveau){} virtual const char* what() const throw(){ return m_phrase.c_str();} int getNiveau() const throw(){ return m_niveau;} int getNumero() const throw(){ return m_numero;} virtual ~Erreur() throw(){} private: int m_numero; //Numéro de l'erreur string m_phrase; //Description de l'erreur int m_niveau; //Niveau de l'erreur };

Implémentation (version 3.3) int main() { Liste l; try //on essaie un ajout{ l.ajouter(1,1); l.ajouter(2,2); l.ajouter(4,8); // erreur.. //… } catch(const Erreur& e) cerr<< "ERREUR: "<< e.what()<<endl; cerr<<"Niveau: "<<e.getNiveau()<<endl; cerr <<"Numero: "<<e.getNumero()<<endl; return 0; } .... void Liste::ajouter (int x, int pos) throw(out_of_range, length_error); { if (cpt==MAX_LISTE) throw Erreur(1, «Ajouter:La liste est pleine", 2); if (pos < 1 || pos > this->taille() +1) throw Erreur(2, « Ajouter: Position d'ajout erronée",2); //… }

Gestion des exceptions Note 2 Il faut savoir que vous n'êtes pas le seul à lancer des exceptions. Certaines fonctions standards lancent elles aussi des exceptions. Toutes les exceptions lancées par les fonctions standards dérivent de la classe exception, ce qui permet avec un code générique de rattraper toutes les erreurs qui pourraient potentiellement arriver. Exemple: catch(const std::exception& e) { std::cerr << "ERREUR: " << e.what() << std::endl; } Ceci est possible grâce au polymorphisme. On attrape un objet de type std::exception, mais grâce aux fonctions virtuelles et à la référence (les deux ingrédients), c'est la fonction what() de la classe fille qui sera appelée, ce qui est justement ce que l'on souhaite. :)

Gestion des exceptions Note 3 La bibliothèque standard peut lancer 5 types d'exceptions différents résumés dans le tableau suivant : Nom de la classe Description bad_alloc Lancée s'il se produit une erreur lors d'un new. bad_cast Lancée s'il se produit une erreur lors d'un dynamic_cast. (On verra plus tard ce que c'est) bad_exception Lancée si aucun catch ne correspond à un objet lancé. bad_typeid Lancée s'il se produit une erreur lors d'un typeid.(On verra plus tard ce que c'est) ios_base::failure Lancée s'il se produit une erreur avec un flux.

Gestion des exceptions #include <stdexcept> Le fichier stdexcept contient 9 classes d'exceptions séparées en 2 catégories, les exceptions "logiques" (logic errors) et les exceptions "d'exécution" (runtime errors). Toutes les exceptions présentées dérivent de la classe std::exception et possèdent un constructeur prenant en argument une chaîne de caractère permettant de décrire le problème.

Gestion des exceptions #include <stdexcept> suite.. Nom de la classe Catégorie Description domain_error logique Lancée s'il se produit une erreur de domaine mathématique. invalid_argument logique Lancée si un des arguments d'une fonction est invalide. length_error logique Lancée si un objet aura une taille invalide. Par exemple si la classe Pile vue précédemment a une taille dépassant la taille de la mémoire. out_of_range logique Lancée si il y a une erreur avec un indice. Par exemple si on essaye d'accéder à une case inexistante d'un tableau. logic_error logique Lancée lors de n'importe quel autre problème de logique du programme. range_error exécution Lancée lors d'une erreur de domaine à l'exécution. overflow_error exécution Lancée si il y a une erreur d'overflow. underflow_error exécution Lancée si il y a une erreur d'underflow. runtime_error exécution Lancée pour tout autre type d'erreur non-prévue survenant à l'exécution. Sinon, vous ne savez pas quoi choisir, prenez simplement runtime_error.

Programmation générique Introduction La classe Liste de tout à l’heure se présentait comme suit : class Liste{ public: … private: int tab[MAX_LISTE]; }; Si l’on veut une liste de double? + c’est exactement le même code sauf qu’il faut remplacer le type de la données pouvant être stockée dans un tableau + duplication de code !!

Définition de la classe Liste en C++ (version 4) #include <iostream> using namespace std; #pragma warning( disable : 4290 ) template <typename T> class Liste{ public: Liste(); //constructeur ~Liste(); //destructeur Liste(const Liste&); //constructeur de copie void ajouter(T x, int pos)throw(out_of_range, length_error); bool estVide() const; int taille() const; friend ostream & operator << (ostream & f, const Liste & l){ for (int i=0; i<l.cpt;i++) f << l.tab[i]<<" "; return f; } private: static const int MAX_LISTE = 5; //Remplace le #define MAX_LISTE T tab[MAX_LISTE]; int cpt; }; #include "Liste.inl" Liste générique

Définition de la classe Liste en C++ (version 4) #define MAX_LISTE 5 template <typename T> class Liste{ public: Liste(); //constructeur ~Liste(); //destructeur void ajouter(T x, int pos)throw(out_of_range, length_error); //… private: T tab[MAX_LISTE]; int cpt; }; Paramètre générique Formel

Définition de la classe Liste en C++ (version 4) template <typename T, in max = 100> class Liste{ public: Liste(); //constructeur ~Liste(); //destructeur void ajouter(T x, int pos)throw(out_of_range, length_error); //… private: T tab[max]; int cpt; }; Paramètres génériques Formels

Implémentation (version 4) Liste.inl #include "Liste.h" template <typename T> Liste<T>::Liste() { cpt = 0; } bool Liste<T>::estVide() const return taille()==0; template <typename T> void Liste<T>::ajouter (T x, int pos) throw(out_of_range, length_error) { … this->tab[pos] = x; this->cpt++; }

Utilisation de la classe Liste générique int main() { Liste<int> l; // ou Liste<int, 100> try{ l.ajouter(1,1); //ajout de 1 en pos =1 l.ajouter(2,2); //ajout de 2 en pos =2 l.ajouter(3,3); //ajout de 3 en pos =3 l.ajouter(4,8); //erreur, position erronée l.ajouter(4,1); //ajout de 4 en pos =1 l.ajouter(5,3); //ajout de 5 en pos =3 l.ajouter(6,6); //erreur, liste pleine } catch(exception &e){ cerr << "ERREUR: " << e.what() << endl; return 0; … Paramètre générique effectif

Limitations d’une implantation par tableau private : int cpt; T tab[max]; // implantation dans un tableau }; // statique il faut prévoir le pire cas si grandes fluctuations  gaspille d’espace limitation majeure en ajout d’éléments besoins variables? allocation dynamique (de mémoire) Utilité des pointeurs et objets pointées Cours de la semaine prochaine