Génie Logiciel I - Cours VII - La S.T.L. et les conteneurs

Transcription

Génie Logiciel I - Cours VII - La S.T.L. et les conteneurs
Génie Logiciel I
Cours VII - La S.T.L. et les conteneurs
Nicolas Kielbasiewicz
C.D.C.S.P./I.S.T.I.L./I.C.J.
Filière M.A.M. 2ème année - 08/09
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
1 / 37
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
2 / 37
Plan du cours
1
Généralités sur la S.T.L.
2
Les conteneurs séquentiels
3
Les conteneurs associatifs
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Généralités sur la S.T.L.
La S.T.L.
Definition (S.T.L.)
La S.T.L. ou Standard Template Library est la grande nouveauté de la
bibliothèque standard intégrée à la norme C++. Elle contient un ensemble de
patrons de classes permettant de manipuler simplement les éléments du C++.
Ex : les classes de flots, la classe string, la classe type info, la classe exception et
ses dérivées, . . .
La S.T.L. introduit de nouvelles notions :
les conteneurs;
les itérateurs;
les algorithmes;
les prédicats.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
3 / 37
Généralités sur la S.T.L.
Les conteneurs
Definition (Les conteneurs)
Les conteneurs sont des classes permettant de représenter les structures de
données les plus répandues : listes, vecteurs, ensembles, tableaux associatifs,
. . . Ce sont des patrons de classes paramétrés par le type de leurs éléments.
Chacune de ces classes dispose de fonctionnalités appropriées et en tant que
patrons, peuvent être instanciées pour n’importe quel paramètre, y compris un
paramètre de type classe défini par l’utilisateur.
Beaucoup de fonctionnalités sont communes à différents conteneurs.
Il existe deux types de conteneurs :
les conteneurs séquentiels : ce sont des conteneurs dont les éléments sont
ordonnés. On peut parcourir le conteneur suivant cet ordre et
insérer ou supprimer un élément en un endroit explicitement choisi;
les conteneurs associatifs : ce sont des conteneurs dont les éléments sont
identifiés par un clé et ordonnés suivant celle-ci. Pour insérer un
élément, il n’est en théorie plus utile de préciser un emplacement.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
4 / 37
Généralités sur la S.T.L.
Les itérateurs : rappels sur les pointeurs
Parcours ”classique” d’un tableau
double p t r [ 6 ] ;
f o r ( i n t j =0; j <6; j ++) {
c o u t << p t r [ j ] << e n d l ;
}
Parcours d’un tableau avec pointeur
double p t r [ 6 ] ;
double ∗ i=new double ( ) ;
i
f o r ( i=&p t r ; i !=& p t r +6; i ++) {
c o u t << ∗ i << e n d l ;
}
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
ptr[0]
ptr[1]
ptr[2]
ptr[3]
ptr[4]
ptr[5]
Filière M.A.M. 2ème année - 08/09
5 / 37
Généralités sur la S.T.L.
Les itérateurs
Definition (itérateur)
Un itérateur est un objet défini par la classe conteneur concernée. Il généralise la
notion de pointeur :
à un instant donné, un itérateur possède une valeur qui désigne un élément
donné du conteneur. On dit qu’ un itérateur pointe vers un élément du
conteneur;
un itérateur peut être incrémenté par l’opérateur ++, de manière à pointer
vers l’élément suivant du conteneur;
un itérateur peut être déréférencé, comme un pointeur, à l’aide de l’opérateur
*. Par exemple, si it est un itérateur sur une liste de points, *it désigne un
point de la liste;
deux itérateurs sur un même conteneur peuvent être comparés par égalité ou
inégalité.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
6 / 37
Généralités sur la S.T.L.
Les itérateurs
Il existe 3 principaux types d’itérateurs :
les itérateurs unidirectionnels : ce sont des itérateurs qui ne peuvent qu’être
incrémentés (++);
les itérateurs bidirectionnels : ce sont des itérateurs qui peuvent être incrémentés
(++) et décrémentés (–);
les itérateurs à accès direct : ce sont des itérateurs bidirectionnels pour lesquels
les expressions de la forme it+i ont un sens. Dans ce cas, on
surdéfinit souvent l’opérateur []. Les itérateurs à accès direct
peuvent être comparés par inégalité.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
7 / 37
Généralités sur la S.T.L.
Utilisation des itérateurs
Pour parcourir un conteneur avec un itérateur, on dispose de deux fonctions
begin() et end() retournant une valeur de type itérator pour un parcours direct, et
de deux fonctions rbegin() et rend() retournant une valeur de type reverse iterator
pour un parcours inverse (pour les itérateurs au moins bidirectionnels) :
Exemple
l i s t <p o i n t > l p ;
...
// i t é r a t e u r s u r l i s t e de p o i n t s
l i s t <p o i n t > : : i t e r a t o r i t ;
f o r ( i t =l p . b e g i n ( ) ; i t != l p . end ( ) ; i t ++) {
...
}
...
// i t é r a t e u r i n v e r s e s u r l i s t e de p o i n t s
l i s t <p o i n t > : : r e v e r s e i t e r a t o r r i t ;
f o r ( r i t =l p . r b e g i n ( ) ; r i t != l p . r e n d ( ) ; r i t ++) {
...
}
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
8 / 37
Généralités sur la S.T.L.
Les intervalles d’itérateurs
Comme nous l’avons précisé, tous les conteneurs sont ordonnés, de sorte que l’on
peut toujours les parcourir d’un début jusqu’à une fin.
Definition (intervalle d’itérateur)
On appelle intervalle d’itérateur d’un conteneur un couple de valeurs de deux
itérateurs it1 et it2 précisant les bornes. On le note [it1,it2).
Cela signifie qu’à partir de l’élément du conteneur pointé par it1, on peut
atteindre l’élément pointé par it2 à l’aide d’un certain nombre d’incrémentations.
L’intervalle d’itérateur [it1,it2) contiendra la séquence des éléments pointés durant
le parcours, de l’élément pointé par it1 inclus à l’élément pointé par it2 exclu.
Cette notion d’intervalle d’itérateur sera très utilisée dans les algorithmes.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
9 / 37
Généralités sur la S.T.L.
Les algorithmes
La notion d’algorithme est tout aussi originale que les deux précédentes. Elle se
fonde sur le principe suivant : Par le biais des itérateurs, beaucoup d’opérations
peuvent être appliquées à un conteneur quels que soient sa nature et le type de
ses éléments.
Par exemple, on peut trouver le premier élément ayant une valeur donnée aussi
bien dans une liste que dans un vecteur ou un ensemble.
Le seul besoin est que l’égalité entre deux éléments soit convenablement définie.
De même, on peut trier un conteneur de type quelconque, y compris un type classe
défini par l’utilisateur, à la condition que le conteneur en question dispose d’un
itérateur à accès direct et que la relation d’ordre < soit convenablement définie.
Definition (algorithme)
Un algorithme est un patron de fonction dont le paramètre est le type des
itérateurs fournis en arguments.
L’utilisation des algorithmes standards demandera d’include <algorithm>.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
10 / 37
Généralités sur la S.T.L.
Exemples d’algorithmes
Compter le nombre d’occurences d’une valeur dans un intervalle
d’itérateur : l’algorithme count
v e c t o r <i n t > v ;
i n t n=c o u n t ( v . b e g i n ( ) , v . end ( ) , 1 ) ;
l i s t <double> l ;
i n t m=c o u n t ( l . b e g i n ( ) , l . end ( ) , 2 . 0 ) ;
Copier une séquence de valeurs dans un autre (type de) conteneur :
l’algorithme copy
v e c t o r <double> v , w ;
l i s t <double> l ;
copy ( v . b e g i n ( ) , v . end ( ) , l . b e g i n ( ) ) ;
copy ( v . r b e g i n ( ) , v . r e n d ( ) , w . b e g i n ( ) ) ;
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
11 / 37
Généralités sur la S.T.L.
Fonctions unaires
Beaucoup d’algorithmes et quelques fonctions membres des classes conteneurs
permettent d’appliquer une fonction aux éléments d’une séquence. Cette fonction
est simplement passée en argument de l’algorithme :
Exemple : for each
main ( ) {
l i s t <f l o a t > l f ;
void a f f i c h e ( f l o a t ) ;
...
f o r e a c h ( l f . b e g i n ( ) , l f . end ( ) , a f f i c h e ) ;
c o u t << e n d l ;
...
}
v o i d a f f i c h e ( f l o a t x ) { c o u t << x << ” ”; }
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
12 / 37
Généralités sur la S.T.L.
Fonctions, prédicats et classes fonctions
Definition (Prédicat)
Un prédicat est une fonction dont la valeur de retour est de type bool.
Là encore, certains algorithmes et fonctions membres des classes conteneurs demandent
un prédicat en argument.
Exemple : find if
main ( ) {
l i s t <i n t > l ;
l i s t <i n t > : : i t e r a t o r i t ;
bool i m p a i r ( i n t ) ;
i t = f i n d i f ( l . b e g i n ( ) , l . end ( ) , i m p a i r ) ;
}
b o o l i m p a i r ( i n t i ) { r e t u r n i %2;}
Dans la plupart des cas, les fonctions passées en arguments sont des objets fonctions.
Pour utiliser les classes fonctions prédéfinies, on inclura <functional>.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
13 / 37
Généralités sur la S.T.L.
Conteneurs, algorithmes et relation d’ordre
par définition, les conteneurs séquentiels sont ordonnés. Par ailleurs, le
conteneur list dispose d’une fonction membre sort qui permet de les
réarranger selon un certain critère;
pour des raisons d’efficacité, les éléments d’un conteneur associatif sont
ordonnés;
il existe beaucoup d’algorithmes de tri qui réorganisent également les
éléments d’un conteneur suivant un certain ordre.
Tant que les éléments concernés sont d’un type standard (type de base ou string)
on peut se permettre d’appliquer ces méthodes de réordonnancement sans se
poser de questions.
Par contre, si les élements concernés sont de type classe, il faut s’assurer de la
surcharge de l’opérateur <, et pas n’importe comment. On peut également choisir
d’utiliser une relation autre que l’opérateur <, soit en choisissant un autre
opérateur, soit en fournissant une fonction de comparaison de deux éléments.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
14 / 37
Généralités sur la S.T.L.
Conteneurs, algorithmes et relation d’ordre
Quel que soit le choix de la relation d’ordre R, R doit être une relation d’ordre
faible strict, c’est-à-dire vérifie les propriétés suivantes :
1
la comparaison de deux éléments identiques retourne la valeur faux :
∀a !(aRa);
2
la relation d’ordre est transitive : si aRb et bRc, alors aRc;
3
si !(aRb) et !(bRc), alors !(aRc).
Pour des valeurs numériques, on peut donc utiliser les opérateurs < et >, mais
pas les opérateurs <= et >=, qui ne sont pas des relations d’ordre faible strict.
Il faudra faire bien attention à respecter ces propriétés lors de la définition de la
relation d’ordre sur un conteneur associatif, comme nous le verrons.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
15 / 37
Les conteneurs séquentiels
Généralités
Definition
Les conteneurs séquentiels sont des conteneurs ordonnés suivant un ordre imposé
explicitement par le programme lui-même.
Il existe 3 conteneurs séquentiels principaux :
list : ce conteneur correspond à la liste doublement chaı̂née;
vector : ce conteneur correspond à la généralisation des tableaux;
deque : ce conteneur est intermédiaire entre list et vector et n’existe que
pour des raisons d’efficacité.
En tant que conteneurs, les trois ont des fonctionnalités communes.
Ils ont aussi des fonctionnalités propres.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
16 / 37
Les conteneurs séquentiels
Fonctionnalités communes à list, vector et deque
Les fonctionnalités communes sont de 4 types :
1
la construction;
2
l’affectation globale;
3
la comparaison;
4
l’insertion / suppression d’éléments.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
17 / 37
Les conteneurs séquentiels
Construction
Les conteneurs list, vector et deque disposent de différents constructeurs :
construction d’un conteneur vide :
l i s t <i n t > l i ;
v e c t o r <f l o a t > v f ;
construction avec un nb donné d’éléments, initialisés par une valeur ou pas :
l i s t <i n t > l i ( 1 0 ) ;
point p (2 ,3);
deque<p o i n t > dd ( 5 , p ) ;
construction à partir d’une séquence :
l i s t <i n t > l i ( 5 ) ;
v e c t o r <i n t > v f ( l i . b e g i n ( ) ,
l i s t <i n t > l i r ( l i . r b e g i n ( ) ,
l i . end ( ) ) ;
l i . rend ( ) ) ;
construction par copie :
l i s t <i n t > l i ;
l i s t <i n t > l i 2 ( l i ) ;
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
18 / 37
Les conteneurs séquentiels
Modifications globales
affectation : elle n’est possible qu’entre conteneurs de même type;
l i s t <i n t > l i ( . . . ) , l i 2
l i s t <f l o a t > l f ( . . . ) ;
l i 2 = l i ; // c o r r e c t
l i 2 = l f ; // i n c o r r e c t
(...);
fonction membre assign : permet d’affecter à un conteneur existant les éléments d’une
séquence définie par un intervalle [deb,fin) ;
l i s t <i n t > l i ( . . . ) ;
v e c t o r <i n t > v i ( . . . ) ;
l i s t <f l o a t > l f ( . . . ) ;
v i . a s s i g n ( l i . b e g i n ( ) , l i . end ( ) ) ; // c o r r e c t
v i . a s s i g n ( 1 0 , 1 ) ; // c o r r e c t : 10 é l é m e n t s v a l a n t 1
v i . a s s i g n ( l f . r b e g i n ( ) , l f . r e n d ( ) ) ; // i n c o r r e c t
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
19 / 37
Les conteneurs séquentiels
Modifications globales
fonction membre clear : vide le conteneur de son contenu;
l i s t <i n t > l i ( . . . ) ;
l i . clear ();
fonction membre swap : permet d’échanger le contenu de deux conteneurs de
même type ;
l i s t <i n t > l i ( . . . ) ,
l i . swap ( l i 2 ) ;
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
li2 (...);
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
20 / 37
Les conteneurs séquentiels
Comparaison
l’opérateur == : retourne vrai si les deux conteneurs passés en arguments sont de
même type, de même taille et ont le même contenu. A surdéfinir si
besoin;
< : retourne faux si l’une des comparaisons lexicographiques entre
éléments de même rangs est fausse. Les deux conteneurs comparés
ne sont pas nécessairement de même taille ;
Exemple
i n t t1 [ ] = {2 , 5 , 2 , 4 , 8};
i n t t2 [ ] = {2 , 5 , 2 , 8};
v e c t o r <i n t > v1 ( t1 , t 1 +5);
v e c t o r <i n t > v2 ( t2 , t 2 +4);
v e c t o r <i n t > v3 ( t2 , t 2 +3);
v e c t o r <i n t > v4 ( v3 ) ;
v e c t o r <i n t > v5 ;
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
v2
v5
v5
v3
v3
v2
Génie Logiciel I
< v1 ;
< v4 ;
< v5 ;
< v2 ;
== v4 ;
== v3 ;
Filière M.A.M. 2ème année - 08/09
21 / 37
Les conteneurs séquentiels
Comparaison
l’opérateur == : retourne vrai si les deux conteneurs passés en arguments sont de
même type, de même taille et ont le même contenu. A surdéfinir si
besoin;
< : retourne faux si l’une des comparaisons lexicographiques entre
éléments de même rangs est fausse. Les deux conteneurs comparés
ne sont pas nécessairement de même taille ;
Exemple
i n t t1 [ ] = {2 , 5 , 2 , 4 , 8};
i n t t2 [ ] = {2 , 5 , 2 , 8};
v e c t o r <i n t > v1 ( t1 , t 1 +5);
v e c t o r <i n t > v2 ( t2 , t 2 +4);
v e c t o r <i n t > v3 ( t2 , t 2 +3);
v e c t o r <i n t > v4 ( v3 ) ;
v e c t o r <i n t > v5 ;
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
v2
v5
v5
v3
v3
v2
< v1 ; // f a l s e
< v4 ; // t r u e
< v5 ; // f a l s e
< v2 ; // t r u e
== v4 ; // t r u e
== v3 ; // f a l s e
Filière M.A.M. 2ème année - 08/09
22 / 37
Les conteneurs séquentiels
Insertion / suppression
fonction membre insert :
l i s t <double> l d ;
l i s t <double > : : i t e r a t o r i t ;
...
ld . insert ( il , 2 . 5 ) ;
ld . i n s e r t ( ld . begin ( ) , 6 . 7 ) ;
l d . i n s e r t ( l d . end ( ) , 3 . 2 ) ;
ld . i n s e r t ( i l ,10 , −1.0);
v e c t o r <double> vd ( . . . ) ;
l d . i n s e r t ( l d . end ( ) , vd . b e g i n ( ) , vd . end ( ) ) ;
fonction membre erase : supprime des éléments et retourne la valeur de l’élément
suivant le dernier supprimé :
l i s t <double> l d ;
l i s t <double > : : i t e r a t o r i t 1 , i t 2 ;
...
i t 1=l d . e r a s e ( i t 1 , i t 2 ) ;
i t 2=l d . e r a s e ( l d . b e g i n ( ) ) ;
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
23 / 37
Les conteneurs séquentiels
Le conteneur list
Alors que les conteneurs vector et deque disposent d’un itérateur à accès direct
(ce qui permet de les manipuler comme de simples tableaux), le conteneur list ne
dispose que d’un itérateur bidirectionnel. On peut donc parcourir un conteneur list
dans les deux sens, sans pour autant avoir la possibilité d’accéder à un élément
par un indice.
Le conteneur list est également le conteneur le plus efficace et rapide pour les
opérations d’insertion / suppression (coût en O(1) plutôt qu’en O(n) pour vector
et deque.
Nous allons voir maintenant quelles sont les fonctionnalités spécifiques au
conteneur list, les fonctionnalités communes vues précédemment étant bien
évidemment disponibles.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
24 / 37
Les conteneurs séquentiels
Le conteneur list
Le conteneur list ne dispose que d’un itérateur bidirectionnel. On ne peut donc pas accéder
directement à un élément de la liste. Il dispose néanmoins de deux fonctions membres sans
arguments back et front permettant d’accéder au dernier / premier élément.
Exemple
l i s t <i n t > l i ( . . . ) ;
i f ( l i . f r o n t ( ) == 9 9 )
l i . f r o n t ()=0;
Le conteneur list dispose également de deux fonctions membres remove et remove if permettant
de supprimer des éléments par valeur ou suivant un prédicat :
Exemple
b o o l p a i r e ( i n t n ) { r e t u r n n %2;}
i n t t [ ] = {1 , 3 , 1 , 6 , 4 , 1 , 5 , 2 , 1};
l i s t <i n t > l i ( t , t +9);
l i . remove ( 1 ) ; // l i c o n t i e n t 3 , 6 , 4 , 5 e t 2
l i . r e m o v e i f ( p a i r e ) ; // l i c o n t i e n t 3 e t 5
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
25 / 37
Les conteneurs séquentiels
Le conteneur list
Nous allons voir maintenant quelques opérations globales :
tri : le conteneur list dispose d’une fonction membre sort très efficace,
permettant de trier ses élements :
#i n c l u d e <f u n c t i o n a l >
...
i n t t [ ] = {1 , 6 , 3 , 9 , 11 , 18 , 5};
l i s t <i n t > l i ( t , t +7);
l i . s o r t ( ) ; // 1 , 3 , 5 , 6 , 9 , 1 1 , 1 8 ,
l i . s o r t ( g r e a t e r <i n t >); // 1 8 , 1 1 , 9 , 6 , 5 , 3 , 1
suppression des doublons : le conteneur list dispose d’une fonction membre unique très
efficace, permettant d’éliminer les doublons quand ils sont consécutifs :
i n t t [ ] = {1 , 6 , 6 , 4 , 6 , 5 , 5 , 4 , 2};
l i s t <i n t > l i ( t , t +9);
l i s t <i n t > l i 2 = l i ;
l i 1 . u n i q u e ( ) // 1 , 6 , 4 , 6 , 5 , 4 , 2
l i 2 . s o r t ( ) ; // 1 , 2 , 4 , 4 , 5 , 5 , 6 , 6 , 6
l i 2 . u n i q u e ( ) ; // 1 , 2 , 4 , 5 , 6
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
26 / 37
Les conteneurs séquentiels
Le conteneur list
Voici un exemple permettant d’illustrer les diverses fonctionnalités abordées (il y
en a d’autres, bien entendu) sur le conteneur list :
Le programme test
#i n c l u d e <i o s t r e a m >
#i n c l u d e < l i s t >
u s i n g namespace s t d ;
main ( ) {
v o i d a f f i c h e ( l i s t <char >);
char mot [ ] = { ” a n t i c o n s t i t u t i o n n e l l e m e n t ”} ;
l i s t <char> l c 1 ( mot , mot+s i z e o f ( mot ) −1);
l i s t <char> l c 2 ;
c o u t << ” l c 1 i n i t : ” << a f f i c h e ( l c 1 ) << e n d l ;
c o u t << ” l c 2 i n i t : ” << a f f i c h e ( l c 2 ) << e n d l ;
...
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
27 / 37
Les conteneurs séquentiels
Le conteneur list
Le programme test (suite)
...
l i s t <char > : : i t e r a t o r i t 1 , i t 2 ;
i t 2=l c 2 . b e g i n ( ) ;
f o r ( i t 1=l c 1 . b e g i n ( ) ; i t 1 != l c 1 . end ( ) ; i t 1 ++)
i f ( ∗ i l 1 != ’ t ’ ) l c 2 . p u s h b a c k ( ∗ i l 1 ) ; // e n l e v e r l e s
c o u t << ” l c 2 a p r e s : ” ; a f f i c h e ( l c 2 ) ;
l c 1 . remove ( ’ t ’ ) ;
c o u t << ” l c 1 remove : ” ; a f f i c h e ( l c 1 ) ;
i f ( l c 1 == l c 2 )
c o u t << ” l e s deux l i s t e s s o n t e g a l e s ” << e n d l ;
’t ’
lc1 . sort ();
c o u t << ” l c 1 s o r t : ” ; a f f i c h e ( l c 1 ) ;
lc1 . unique ( ) ;
c o u t << ” l c 1 u n i q u e : ” ; a f f i c h e ( l c 1 ) ;
}
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
28 / 37
Les conteneurs séquentiels
Le conteneur list
Fonction affiche et sortie écran
v o i d a f f i c h e ( l i s t <char> l c )
l i s t <char > : : i t e r a t o r i t ;
f o r ( i t =l c . b e g i n ( ) ; i t != l c . end ( ) ; i t ++)
c o u t << ( ∗ i t ) << ” ” ;
c o u t << e n d l ;
}
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
lc1 i n i t : a n t i c o n s t i t u t i o n n e l l e m e n t
lc2 i n i t :
lc2 apres : a n i c o n s i u i o n n e l l e m e n
l c 1 remove : a n i c o n s i u i o n n e l l e m e n
l e s deux l i s t e s s o n t e g a l e s
lc1 sort : a c e e e i i i l l m n n n n n o o s u
lc1 unique : a c e i l m n o s u
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
29 / 37
Les conteneurs associatifs
Généralités
Definition
Les conteneurs associatifs sont destinés à retrouver une information, non pas en fonction
de sa place dans le conteneur, mais en fonction de sa valeur, ou une partie de sa valeur
appelée clé. Pour des raisons d’efficacité, un conteneur associatif se trouve ordonné en
permanence, en se fondant sur une relation d’ordre définie à la construction.
Ex : dans un répertoire téléphonique, les numéros de téléphones sont ordonnés par une
clé que constitue le nom et le prénom de la personne.
À la différence des conteneurs séquentiels, chaque élément est ici composé de deux
parties : la clé et la valeur. Les deux conteneurs associatifs les plus importants sont :
map : conteneur associatif pur qui impose l’unicité des clés. On peut donc
utiliser à bon escient l’opérateur [];
multimap : à la différence de map, l’unicité de la clé n’est pas exigée. Dans
l’exemple du répertoire téléphonique, le conteneur multimap autorisera
les homonymes.
Les deux classes n’ont pas vraiment de fonctionnalités communes en raison de l’unicité
de la clé ou pas.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
30 / 37
Les conteneurs associatifs
Le conteneur map
Exemple
#i n c l u d e <i o s t r e a m >
#i n c l u d e <map>
u s i n g namespace s t d ;
main ( ) {
v o i d a f f i c h e ( map<char , i n t >);
map<char , i n t > m;
c o u t << ”map i n i t : ” ; a f f i c h e (m) ;
m[ ’ S ’ ] = 5 ;
m[ ’C ’ ] = 1 2 ;
c o u t << ”map SC : ” ; a f f i c h e (m) ;
c o u t << ”map ( S ) : ” << m[ ’ S ’ ] << e n d l ;
c o u t << ”map (X) : ” << m[ ’X ’ ] << e n d l ;
c o u t << ”map X : ” ; a f f i c h e (m) ;
m[ ’ S ’ ]=m[ ’ c ’ ] ;
c o u t << ”map f i n a l : ” ; a f f i c h e (m) ;
}
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
31 / 37
Les conteneurs associatifs
Le conteneur map
Exemple(suite)
v o i d a f f i c h e ( map<char , i n t > m) {
map<char , i n t > : : i t e r a t o r i t ;
f o r ( im=m. b e g i n ( ) ; i t !=m. end ( ) ; i t ++)
c o u t << ”( ” << im−> f i r s t << ” , ” << im−>s e c o n d << ”) ” ;
c o u t << e n d l ;
}
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
map i n i t :
map SC = (C , 1 2 ) ( S , 5 )
map ( S ) : 5
map (X) : 0
map X : (C , 1 2 ) ( S , 5 ) (X , 0 )
map f i n a l : (C , 1 2 ) ( S , 0 ) (X , 0 ) ( c , 0 )
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
32 / 37
Les conteneurs associatifs
Le conteneur map
Analysons cet exemple introductif :
la classe map dispose d’un itérateur iterator bidirectionnel;
les éléments d’un objet de type map sont d’un type particulier pair, dont la
classe comporte deux attributs, first et second, pour accéder respectivement
à la clé et à la valeur;
lorsqu’on utilise l’opérateur [], si la clé utilisée n’existe pas dans le conteneur,
elle est créée et la valeur associée sera 0;
le conteneur map est ordonné intrinsèquement. Ici c’est l’opérateur < par
défaut.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
33 / 37
Les conteneurs associatifs
Le conteneur map
Pour construire un conteneur map, on ne dispose que de 3 possibilités :
construire un conteneur vide;
construire un conteneur par copie;
construire un conteneur à partir d’une séquence;
La syntaxe est la même que celle vue pour les conteneurs séquentiels.
On peut spécifier la relation d’ordre utilisée à l’aide d’un prédicat. Rappelons que
par défaut, c’est l’opérateur < pour le type de la clé qui est utilisé. Si c’est un
type classe, on s’assurera de le surcharger.
map<char , long , g r e a t e r <char> > m1 ;
map<char , long , g r e a t e r <char> > m2(m1 ) ;
Dans le cas de la construction par copie, si m1 et m2 ne sont pas ordonnés par la
même relation, il y a erreur de compilation : La relation d’ordre fait partie du type
du conteneur.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
34 / 37
Les conteneurs associatifs
Le conteneur map
Comme pour tout conteneur, on peut accéder à un élément existant, soit pour en
connaı̂tre la valeur, soit pour la modifier. Néanmoins, dans le cas d’une map, c’est
un peu particulier. On a vu en effet qu’une tentative d’accès à une clé existante
amène à la création d’un nouvel élément.
Si l’on accède aux éléments par itérateur, ce comportement automatique n’existe
plus. En théorie, il n’est pas interdit de modifier la valeur de l’élément désigné par
un itérateur, mais le rôle exact d’une telle opération n’est pas spécifié par la norme.
...
// m o d i f p a r a p p e l à f c t membre m a k e p a i r de c l a s s e p a i r
∗ i t =m a k e p a i r ( ’R ’ , 4 ) ;
En effet, on peut modifier la valeur de la clé et l’ordre des éléments peut s’en
trouver modifié. Sur quoi pointe alors l’itérateur ?
Il est donc fortement déconseillé de modifier la valeur d’un élément d’une map par
le biais d’un itérateur.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
35 / 37
Les conteneurs associatifs
Le conteneur map
Quelques fonctions membres utiles :
find : permet de recherche un élément et retourne un itérateur. Si
l’élément est introuvable, elle retourne end() :
i f (m1 . f i n d ( ’R ’ )!=m1 . end ( ) ) c o u t << ”t r o u v é ”<<e n d l ;
insert : permet d’insérer un élément. Les syntaxes sont les mêmes que vues
précédemment;
erase : permet de supprimer un élément. Les syntaxes sont les mêmes que
vues précédemment. Il existe une nouvelle possibilité : donner la clé
en argument.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
36 / 37
Les conteneurs associatifs
Le conteneur map
Que se passe t-il quand on veut supprimer un élément en passant un itérateur en
argument ? Sur quoi va pointer l’itérateur ? La réponse dépend de la version du
compilateur. Toutefois, il existe une manière de contourner le problème :
Exemple
t e m p l a t e < c l a s s T> e r a s e Z e r o s ( map<i n t , T> m) {
typename map<i n t , T> : : i t e r a t o r i t ;
f o r ( i t =m. b e g i n ( ) ; i t !=m. end ( ) ; ) {
i f ( ( i t −>s e c o n d )==0.0){
m. e r a s e ( i t ++);
} else {
++i t ;
}
}
}
On peut voir le mot clé typename dans la syntaxe de déclaration de l’itérateur,
nécessaire dans ce cas. Il permet de signifier au compilateur que le type de l’itérateur
sera décidé à l’utilisation.
Nicolas Kielbasiewicz (C.D.C.S.P./I.S.T.I.L./I.C.J.)
Génie Logiciel I
Filière M.A.M. 2ème année - 08/09
37 / 37

Documents pareils

Le Traitement des données avec la STL (pdf - David Saint

Le Traitement des données avec la STL (pdf - David Saint Un « Foncteur » est un objet dont la classe définit l'opérateur « () ». Les foncteurs qui prennent : • un paramètre sont dites foncteurs «unaires», • deux paramètres sont dits foncteurs «binaires»....

Plus en détail

Les transparents du cours 3

Les transparents du cours 3 for (vector::iterator it=v.begin(); it! =v.end(); it++) if (*it == 0) { v.erase(it); it--; } // Efface tous les 0 du vecteur. Attention, erase() // déplace le pointeur vers l'élément suivant

Plus en détail