POO_CH10 - dept
Transcription
POO_CH10 - dept
Les patrons (III) Exemples du code Les patrons <template> des classes Les templates génériques sans héritage : nécessité de définir des opérateurs spécifiques dans la classe /type définie par l’utilisateur qui sera « chargée » en substituant le type générique Exemple : liste générique avec une classe définie par l’utilisateur 13/01/2013 1 Code-source – utilisation // ExempleSTL.cpp // Liste, Vector, file(queue), pile(stack) #include #include #include #include #include #include #include <iostream> <algorithm> // copy, sort... <vector> <list> <string> <queue> <stack> using namespace std; void void void void LireVecteur(void); LireListe(void); LireQueue(void); LirePile(void); void main(void) { LireVecteur(); LireListe(); LireQueue(); LirePile(); } 13/01/2013 2 1 Utilisation de la classe “vector” void LireVecteur(void) { vector<int> v; // crée un vecteur d'entiers vide int input; while (cin >> input) { // tant que la saisie d'un entier réussit // fin de saisie : taper un non-entier v.push_back (input); // ajouter à la fin du vecteur } // trie // sort prend deux itérateurs en paramètres, et trie les éléments entre eux // depuis le 1er inclusivement jusqu'au dernier exclusivement sort(v.begin(), v.end()); // affiche le résultat du tri int size = v.size(); for (int i = 0; i < size; i++) cout << v[i] << endl; } 13/01/2013 3 Utilisation de la classe “list” void LireListe(void) { list<string> l; // crée une liste de chaînes vide string input; while (l.size() < 5) { // tant que pas saisi 5 chaînes cin >> input; // saisie d'une chaîne l.push_front(input); // ajouter en début de liste } // trie l.sort(); // affiche le résultat du tri list<string>::iterator i; for (i = l.begin(); i != l.end(); i++) cout << *i << endl; // inverse l'ordre des éléments l.reverse(); // affiche le résultat de l'inversion for (i = l.begin(); i != l.end(); i++) cout << *i << endl; } 13/01/2013 4 2 Utilisation de la classe “queue” void LireQueue(void) { // la queue fonctionne en FIFO (file) queue<int> q; // crée une queue d'entiers vide. int input; while (cin >> input) { // tant que la saisie d'un entier réussit // fin de saisie : taper un non-entier q.push(input); // ajouter en fin de queue } // pour parcourir la queue, il faut la vider int i; while (!q.empty()) { i = q.front(); // obtient le 1er élément de la queue cout << i << endl; q.pop(); // dépile le 1er élément de la queue } } 13/01/2013 5 Utilisation de la classe “stack” void LirePile(void) { // la pile fonctionne en LIFO stack<int> s; // crée une pile d'entiers vide int input; while (cin >> input) { // tant que la saisie d'un entier réussit // fin de saisie : taper un non-entier s.push(input); // ajouter en tête de pile } // pour parcourir la pile, il faut la vider int i; while (!s.empty()) { i = s.top(); // obtient le 1er élément de la pile cout << i << endl; s.pop(); // supprime le 1er élément de la pile } } 13/01/2013 6 3 Containeurs associatifs Les conteneurs associatifs : retrouver une information non-plus en fonction de sa place dans le conteneur mais en fonction de sa valeur ou d’une partie de sa valeur – « clé ». Map et Multimap – associent une clé et une valeur. Map : impose l’unicité de clés Multimap : possibilité d’avoir plusieurs éléments ayant la même clé. Ces éléments apparaissent consécutivement. 13/01/2013 7 Conteneur map(I) Conteneur map est ordonné par les clé. Accès : par [ ] Temps d’accès : O(logN) Existence de relation d’ordre stricte Déclaration: map<char, int> m;//conteneur vide m.size() vaut 0 //les clés sont char et les valeurs sont int m[’S’]=5;//création (S,5) – différence avec Vector Si on cherche à accéder à une valeur associée à une clé inexistante -> création d’un élément cout<< ’’valeur associée à X:’’<<m[’X’]; Résultat : …..0 13/01/2013 8 4 Conteneur map(II) Les éléments d’un conteneur map sont d’une classe particulière « pair » Fonctions définies : first, second La fonction first : correspond à la clé La fonction second : correspond à la valeur associée map<char, int>::iterator im; for(im=m.begin();im!=m.end();im++) cout<< im.first()<<’ ’<<im.second()<endl; /*afficher la clé et la valeur associée*/ 13/01/2013 9 Conteneur map(III) classe « pair » pair<int, float> p(1,1.05); pair<string,int>ps(’’toto’’, 2); Construction d’une map à partir d’une séquence : list<pair<char,long>> lir(…); … map<char,long> dict(lir.begin(),lir.end()); 13/01/2013 10 5 Conteneur map(III) Relation d’ordre: par défaut on utilise la relation d’ordre < soit pour les types prédéfinis soit surchargée pour les objets Une autre relation – fonction –template : map<char, long, greater<char> > mg; /*les clés seront ordonnées par ordre décroisant*/ map<char, long, less<char> > ml; //??? « Surcharger » l’ordre Class ordre_p{ public: bool operator ()(int n, int p){…} }; map <int, float, ordre_p> mmm; 13/01/2013 11 Conteneur map(IV) Accès aux éléments. Particularité : création des éléments si l’accès par une clé inexistante (cf. l’exemple) 1. Accès par l’opérateur [ ] map<char, int> m; m[’’A’’]=2; …=m[’’J’’]; // si la clé J n’existe pas on crée la valeur //0 2. Accès par itérateur *it.frist() *it.second() 3. Recherche Fonction – membre find(clé) – renvoie un itérateur sur l’élément ayant une clé donnée 13/01/2013 12 6 Conteneur map(V) map<char, int> m; map<char,int>::iterator im; m[’x’]=10; m[’c’]=100; im=m.find(’c’); cout<<*im.second()<<endl; //Résultat? 13/01/2013 13 Conteneur map(VI) Insertions. m.insert(element); //insère la paire element Temps en O(logN) m.insert(debut,fin);//insère les paires de la séquence Temps en O(log(M+N)) si l’intervalle n’est pas trié Exemple map<int, float> m1; map<int, float> m2 … m1.insert(make_pair(1, 3.14); m1.insert(m2.begin(), m2.end()); m.insert(position, pair) ;//insère à la position Résultat des fonctions d’insértion : pair (position, success) success est un boolean, position est un itérateur 13/01/2013 14 7 Conteneur map(VII) Suppression : erase 1. m.erase(position);// supprime l’élément à la position 2.m.erase(key);//supprime l’élément ayant la clé key 3. m.erase(it1,it2);//supprime la séquence entre // les itérateurs it1,it2 Les éléments « écrasés » ne sont plus accessibles après leur destruction 13/01/2013 15 Conteneur multimap(I) Propriétés : (1)une même clé apparaît plusieurs fois; (2)l’opérateur [ ] n’est plus applicable; (3)si il existe plusieurs clés équivalentes, la fonction find fournit un itérateur sur UN des éléments (pas forcément le premier). (4)la fonction erase(clé) supprimera toutes les occurrences au lieu d’un seul élément dans le cas du conteneur map. 13/01/2013 16 8 Conteneur multimap(II) Fonctions particulières lower_bound(clé) //fournit un itérateur sur le premier élément ayant une clé équivalente à la clé upper_bound(clé) //fournit un itérateur sur le dernier élément ayant une clé équivalente à la clé equal_range(clé) //fournit une paire fromée des valeurs des itérateurs lower_bound(clé) et upper_bound(clé) 13/01/2013 17 Exemples Simples des containeurs MAP et Multimap 1. Saisie d’une liste des mots et calcul des statistiques d’occurrence de chaque mot, du nombre des mots différents dans la liste, … (MAP) 2. Manipulations divers : insertions, recherches (multimap) 3. Calculs statistiques ( histogrammes des images) 13/01/2013 18 9 Exemples simples : map et multimap(I) #include <iostream> #include <string> #include <map> using namespace std; void Map(void); void Multimap(void); void main(void) { Map(); Multimap(); } void Map(void) { // Déclaration d'un objet map de clé une chaîne (string) et de valeur un entier (int) map<string, int> strCount; // Saisie d'une liste de mots jusqu'à "fin" et comptage string str; while (cin >> str && str != "fin") { strCount[str]++; } cout << "Nombre de mots differents : " << strCount.size() << endl; 13/01/2013 19 Exemples : map et multimap(II) // Parcours de l'objet map pour afficher les mots et leur occurrence map<string,int>::iterator iter; for (iter = strCount.begin(); iter != strCount.end(); iter++) { cout << "Mot \"" << iter->first << "\" apparu " << iter->second << " fois" << endl; } } 13/01/2013 20 10 Exemples : map et multimap(III) void Multimap(void) { // Déclaration d'un objet map de clé une chaîne (string) et de valeur un entier (int) multimap<string, int> resultats; // Insertion des résultats resultats.insert(pair<string, int>("Marie", 8)); resultats.insert(pair<string, int>("Marc", 16)); resultats.insert(pair<string, int>("Elise", 11)); resultats.insert(pair<string, int>("Marc", 2)); resultats.insert(pair<string, int>("Bruno", 15)); resultats.insert(pair<string, int>("Jacques", 10)); resultats.insert(pair<string, int>("Claire", 13)); cout << "Nombre de resultats : " resultats.insert(pair<string, int>("Bruno", 12)); resultats.insert(pair<string, int>("Jacques", 6)); resultats.insert(pair<string, int>("Claire", 15)); resultats.insert(pair<string, int>("Alain", 9)); resultats.insert(pair<string, int>("Pierre", 11)); << resultats.size() << endl; 13/01/2013 21 Exemples : map et multimap(III) pair< multimap<string, int>::iterator, multimap<string, int>::iterator > sequence;//préparation d’une séquence Resultats ?? d’éléments qui contiendront les résultats de recherche // equal_range("Bruno") retourne pair<iterator,iterator> representant la sequence des elements de cle "Bruno" sequence = resultats.equal_range("Bruno"); // Parcours des resultats de "Bruno" cout << "Resultats de \"Bruno\" :" << endl; multimap<string, int>::iterator iter; for (iter = sequence.first; iter != sequence.second; iter++) { cout << (*iter).first << " : " << (*iter).second << endl; } } 13/01/2013 22 11 Calcul de l’Histogramme (map) unsigned char image[N][M]; ... map<int, int> Histogramme; map<int,int>::iterator itmap;//Parcourir l'ensemble des donnees stockées dans une image NxM for (int i=0; i<N ; i++){ for (int j=0; j<M ; j++){ int donnee = (int) image[i][j]; itmap=Histogramme.find(donnee); if(itmap != Histogramme.end()) (*itmap).second++; else Histogramme.insert(pair<int,int>(donnee,1)); } } 13/01/2013 23 Exemples plus complexes. Dictionnaire (multimap)(I) //1. Rappel : classe Entree #ifndef ENTREE #define ENTREE_H #include <string> using namespace std; //utilisation des classes STL class Entree{ private: string *mot; string *genre; string *categorie_grammaticale; string *article; public: Entree(){mot=new string(); article=new string();categorie_grammaticale=new string(); genre=new string();} Entree(string& _mot, string& _genre, string& _cg, string& _article); //Entree(const Entree& cEntree); void affiche(); ~Entree(){delete mot; delete genre; delete categorie_grammaticale; delete article;} }; #endif 13/01/2013 24 12 Exemples plus complexes. Dictionnaire (multimap) Définition de la classe #include "Entree.h" using namespace std; //utilisation des classes STL typedef multimap<string, Entree*> Entrees; class Dico { private: Entrees* entrees; public: Dico(); Dico(const Entree& entree); ~Dico(); unsigned taille(); void affiche(); void ajoute(const Entree& entree); bool contient(const string& nom); vector<Entree>* liste(const string& nom); }; #endif 13/01/2013 25 Exemples plus complexes. Dictionnaire (multimap).Méthodes(I) #include <iostream> #include "Dico.h" using namespace std; // Constructeur par défaut Dico::Dico() { entrees = new Entrees; } // Constructeur avec une entrée Dico::Dico(const Entree& entree) { entrees = new Entrees; ajoute(entree); } // Destructeur Dico::~Dico() { for (Entrees::iterator it = entrees->begin(); it != entrees->end(); ++it) { delete it->second; } delete entrees; } … 13/01/2013 26 13 Méthodes (II) // Taille du dictionnaire unsigned Dico::taille(void) { return entrees->size(); } // Affichage du contenu du dictionnaire void Dico::affiche(void) { cout << entrees->size() << " entrees" << endl; cout << "---" << endl; Entree* entree; for (Entrees::iterator it = entrees->begin(); it != entrees->end(); ++it) { entree = it->second; entree->affiche(); cout << "---" << endl; } cout << "---" << endl; } 13/01/2013 27 Méthodes(III) // Ajout d'une entrée void Dico::ajoute(const Entree& entree) { Entree* nouvelle = new Entree(entree); entrees->insert( pair<string, Entree*>(*nouvelle->leMot(), nouvelle) ); } // Test de contenance d'un mot dans le dictionnaire bool Dico::contient(const string& nom) { Entrees::iterator it = entrees->find(nom); bool resultat = (it != entrees->end()); return resultat; } // Retourne la liste des définitions d'un mot donné vector<Entree>* Dico::liste(const string& nom) { vector<Entree>* liste_mots = new vector<Entree>; Entree* entree; Entrees::iterator it = entrees->find(nom); //it sur le début de la suite des clés égales while (it != entrees->end()) { entree = it->second; liste_mots->push_back(*entree); ++it; } return liste_mots; 13/01/2013 } 28 14 Fichier main.cpp #include <iostream> #include "Dico.h" using namespace std; void TestEntree(void); void TestDico(void); int main(){ TestDico(); return 0; } 13/01/2013 29 Procédure de test(I) void TestDico(void) { Dico dico1; cout << "Nombre d'elements dans dico1 avant ajouts : " << dico1.taille() << endl; cout << "Contenu de dico1 : " << endl; dico1.affiche(); cout << "----------------" << endl; Entree entree1("marteau", "nom", "masculin", "Outil de percussion compose d'une masse metallique et d'un manche"); Entree entree2("cle", "nom", "feminin", "Instrument qui permet d'ouvrir et de fermer une serrure"); Entree entree3("marteau", "nom", "masculin", "Piece de bois garnie de feutre qui frappe les cordes d'un piano"); Entree entree4("marteau", "nom", "masculin", "Osselet de l'oreille moyenne"); Entree entree5("cle", "nom", "feminin", "Signe place au commencement d'une portee pour indiquer l'intonation"); dico1.ajoute(entree1); dico1.ajoute(entree2); dico1.ajoute(entree3); dico1.ajoute(entree4); dico1.ajoute(entree5); cout << "Nombre d'elements dans dico1 apres les ajouts : " << dico1.taille() << endl; cout << "Contenu de dico1 : " << endl; dico1.affiche(); cout << "----------------" << endl; 13/01/2013 30 15 Procédure de test(II) if (dico1.contient("vis")) { cout << "Le dico contient le terme 'vis'" << endl; } else { cout << "Le dico ne contient pas le terme 'vis'" << endl; } cout << "----------------" << endl; if (dico1.contient("marteau")) { cout << "Le dico contient le terme 'marteau'" << endl; } else { cout << "Le dico ne contient pas le terme 'marteau'" << endl; } cout << "----------------" << endl; cout << "Liste du terme 'marteau' : " << endl; vector<Entree>* definitions = dico1.liste("marteau"); cout << "Nombre de definitions dans la liste : " << definitions->size() << endl; for (vector<Entree>::iterator it = definitions->begin(); it != definitions->end(); ++it) { it->affiche();//it fournit un pointeur sur l'objet Entree //et la méthode Entree->affiche est invoquée cout << "---" << endl; } delete definitions; } 13/01/2013 31 Nombre d'elements dans dico1 avant ajouts : 0 Contenu de dico1 : 0 entrees -------------------Nombre d'elements dans dico1 apres les ajouts : 5 Contenu de dico1 : 5 entrees --cle nom feminin Instrument qui permet d'ouvrir et de fermer une serrure --cle nom feminin Signe place au commencement d'une portee pour indiquer l'intonation --marteau nom masculin Outil de percussion compose d'une masse metallique et d'un manche --marteau nom masculin Piece de bois garnie de feutre qui frappe les cordes d'un piano --marteau nom masculin Osselet de l'oreille moyenne 13/01/2013 ----- 32 16 ---------------Le dico ne contient pas le terme 'vis' ---------------Formation du vecteur Le dico contient le terme 'marteau' « définitions » ---------------Liste du terme 'marteau' : Nombre de definitions dans la liste : 3 marteau nom masculin Outil de percussion compose d'une masse metallique et d'un manche --marteau nom masculin Piece de bois garnie de feutre qui frappe les cordes d'un piano --marteau nom masculin Osselet de l'oreille moyenne 13/01/2013 33 17