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