Standard Template Library
Transcript
Standard Template Library
STL - Standard Template Library C++ STL identifica la libreria dei template standard che contiene un insieme di algoritmi e di strutture di dati di uso comune nella programmazione C++ “Template” indica che la libreria è costituita da classi e funzioni parametrizzate (template di classi e funzioni) Fondamenti di Informatica II 26. Standard Template Library STL STL fa parte dello standard ANSI/ISO del C++ programmare tramite STL si indica con il termine programmazione generica Æ ossia significa disporre di strutture di dati e algoritmi che possono essere utilizzati in diversi contesti di elaborazione Corso di Laurea in Ingegneria Informatica A.A. 2008-2009 2° Semestre – Corso (A-M) Prof. Giovanni Pascoschi 2 La Standard Template Library Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Il contenitore vector vector è un contenitore sequenziale dal comportamento simile agli array, ma con capacità di espansione automatica e dotata di numerosi metodi per gestire i dati presenti nel contenitore, che facilitano il programmatore La Standard Template Library (STL) comprende tre tipologie di componenti: ¾Contenitori ¾Iteratori ¾Algoritmi l'aggiunta e la rimozione di elementi è rapida solo in coda ed e più lenta nelle altre posizioni (poichè gli elementi sono immagazzinati in aree di memoria contigue) I contenitori sono strutture dati come vettori, liste , pile, code e mappe, implementati con il meccanismo dei template, in grado di memorizzare oggetti di qualsiasi tipo occorre includere la libreria <vector>: #include <vector> Gli iteratori sono puntatori utilizzati per accedere e manipolare gli oggetti memorizzati nei contenitori in maniera semplificata la dichiarazione avviene ad esempio con: vector<int> v; // array di nome v e formato da numeri interi Gli algoritmi comprendono funzioni d’utilità per il conteggio, l’ordinamento, la ricerca, ed altre operazioni standard sui contenitori. oppure const int MAX = 100; vector<int> v(MAX); // si passa il parametro MAX al costruttore della classe vector 3 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni 4 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Il contenitore vector Esempio di contenitore vector Principali metodi size_type size( ); // restituisce il numero di elementi presenti nel vettore bool empty( ); // restituisce true se il vettore è vuoto void push_back(const T& x);// appende x alla fine del vettore void pop_back( ); // rimuove l’ultimo elemento del vettore void clear( ); // rimuove tutti gli elementi nel vettore T& at(size_type i); // restituisce un riferimento all’elemento in posizione i #include <vector> #include <iostream> using namespace std; int main( ) { vector<int> a; // crea un array di interi a tramite il contenitore vector for (int i = 1; i <= 5; i++) { a.push_back(i); // appende il valore i in fondo ad a } for (int i = 0; i < a.size( ); i++) { cout << a[i] << " "; } cout << endl; system("pause"); } Operatori I contenitori possono essere confrontati utilizzando gli operatori ==, !=, <=, >=, <, >, e possono essere assegnati utilizzando l’operatore =. L’operatore [ ] può essere usato nel vector per accedere ai singoli elementi (in alternativa ad at) N.B.: size_type Æ Unsigned integral type e corrisponde al tipo intero ritornato dall’operatore sizeof (esso esprime la dimensione o il numero di byte di ciascun elemento) 5 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni 12345 6 Iteratori vector<int>::iterator i; // definisce un iteratore i ad un vettore di interi i++ // avanza di un elemento i-// retrocede di un elemento *i // restituisce l’oggetto puntato da i vector<int>::const_iterator i; // definisce un iteratore i ad un vettore const di interi (i dati puntati dall’iteratore non possono essere cambiati) gli iteratori permettono di accedere a una determinata posizione all’interno del contenitore per poter agire su quel particolare elemento del contenitore sintassi: contenitore<T>::iterator nome; Metodi di vector che restituiscono o fanno uso di iteratori: iterator begin( ); // restituisce un iteratore al primo elemento del vettore iterator end( ); /* restituisce un iteratore che punta subito dopo l’ultimo elemento del vettore*/ iterator insert(iterator i, const T& x); /* inserisce x nella posizione precedente a quella puntata dall’iteratore i; restituisce un iteratore all’elemento inserito */ iterator erase(iterator i); /* cancella l’elemento nella posizione dell’iteratore; restituisce un iteratore all’elemento successivo a quello cancellato */ esempio: vector<int>::iterator i; tramite l’algebra dei puntatori è possibile accedere a tutti gli elementi del contenitore vector esistono due particolari metodi che permettono di individuare l’inizio e la fine del contenitore: ¾begin( ) Æ restituisce un iteratore che punta al primo elemento del contenitore ¾end ( ) Æ restituisce un iteratore che punta all’ultimo elemento del contenitore Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Iteratori per il contenitore vector gli iteratori sono una generalizzazione dei puntatori e possono essere applicati con le stesse modalità ai diversi contenitori 7 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni 8 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Scansione degli elementi di vector tramite iteratore Iteratori costanti void s2(const vector<int> &v) { vector<int>::const_iterator it = v.begin( ); #include <vector> #include <iostream> using namespace std; int main() { vector<int> a; for (int i = 1; i <= 5; i++) { a.push_back(i); } vector<int>::iterator it; for (it = a.begin( ); it != a.end( ); it++) { cout << *it << " "; } cout << endl; system("pause"); } while (it != v.end( )) { #include <vector> cout << *it << " "; #include <iostream> it++; using namespace std; } void s1(vector<int> &v) { cout << endl; vector<int>::iterator it = v.begin( ); while (it != v.end()) { cout << *it << " "; } int main( ) { vector<int> a; it++; for (int i = 1; i <= 5; i++) a.push_back(i); } s1(a); cout << endl; s2(a); } system("pause"); } 12345 9 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni 10 Vector di oggetti class Persona { public: string nome; int eta; Persona(string n, int v) { nome = n; eta = v; } }; double media(const vector<Persona> &v) { double n = 0; int d = 0; vector<Persona>::const_iterator it; it = v.begin( ); while (it != v.end( )) { int eta = (*it).eta; 11 Fondamenti di Informatica II – A.A. 2008-2009 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Il contenitore list n += eta; d++; it++; } return n/d; } int main( ) { vector<Persona> v; Persona e1(“antonio",21); Persona e2(“giovanni",25); Persona e3(“mario",28); v.push_back(e1); v.push_back(e2); v.push_back(e3); double m = media(v); cout << "media = " << m << endl; system("pause"); } a cura di Pascoschi Giovanni list è un contenitore sequenziale che permette inserimenti e cancellazioni rapidi, ma non permette l'accesso diretto agli elementi se si conosce il numero in sequenza (gli elementi non sono immagazzinati in aree di memoria contigue) il contenitore list implementa una struttura di dati organizzata come una lista linkata doppia (i dati nella lista sono di tipo omogeneo) occorre includere la libreria <list>: #include <list> la dichiarazione avviene ad esempio con: list<int> l; // lista di nome l e formato da numeri interi 12 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Il contenitore list Il contenitore list altri metodi del contenitore list Metodi principali del contenitore list size_type size( ); // restituisce il numero di elementi presenti nella lista bool empty( ); // restituisce true se la lista è vuota void sort( ); /*ordina gli elementi della lista in ordine crescente usando l’operatore < associato al tipo degli elementi */ void remove(const T& x); /*rimuove l’elemento x dalla lista usando l’operatore == associato al tipo degli elementi */ void push_back(const T& x); // appende x alla fine della lista 13 void push_front(const T& x); // inserisce x all’inizio della lista Iteratori void pop_back( ); // rimuove l’ultimo elemento della lista list<int>::iterator i; // definisce un iteratore i ad una lista di interi void pop_front( ); // rimuove il primo elemento della lista i++ // avanza di un elemento void clear( ); // rimuove tutti gli elementi nella lista i-- // retrocede di un elemento void reverse( ); // inverte la lista *i // restituisce l’oggetto puntato da i void merge( ); // effettua la fusione di due liste (già ordinate) Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni 14 Il contenitore list Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Esempio di contenitore list #include <list> Metodi di list che restituiscono o fanno uso di iteratori: #include <iostream> iterator begin( ); // restituisce un iteratore al primo elemento della lista using namespace std; iterator end( ); /* restituisce un iteratore che punta subito dopo l’ultimo elemento della lista*/ void eliminanumPari(list<int> &l) { void visualizza(const list<int> &l) { list<int>::const_iterator it; for(it = l.begin( ); it != l.end( ); it++) cout << *it << " "; cout << endl; list<int>::iterator it; iterator insert(iterator i, const T& x); /* inserisce x nella posizione precedente a quella puntata dall’iteratore i; restituisce un iteratore all’elemento inserito*/ it = l.begin(); while (it != l.end()) { } int main( ) { list<int> l; int val = *it; iterator erase(iterator i); /* cancella l’elemento nella posizione dell’iteratore; for (int i = 1; i <= 20; i++) if (val % 2 == 0) it = l.erase(it); restituisce un iteratore all’elemento successivo a quello cancellato*/ l.push_back(i); else it++; eliminanumPari(l); } visualizza(l); } system("pause"); } 1 3 5 7 9 11 13 15 17 19 15 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni 16 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Confronto tra vector e list Il contenitore map map è un array associativo, che permette di associare elementi (valori) a chiavi di vario tipo (simile agli array paralleli)Æ i valori sono mappati (indicizzati) tramite le chiavi di ricerca chiave1 valore1 vector è organizzato in memoria centrale come un insieme di elementi contigui Æ l‘accesso diretto al singolo elemento è piu’ veloce, ma fare nuovi inserimenti e cancellazioni è piu’ lento list non richiede memoria allocata in modo contiguo Æ non consente accesso diretto ma sequenziale, ma fare nuovi inserimenti e cancellazioni è molto piu’ efficiente Æ richiede piu’ memoria perchè devono essere gestiti due puntatori per ciascun dato chiave2 valore2 ... ... chiave n valore n il tipo delle chiavi puo’ essere diverso dal tipo dei valori Æ la struttura viene mantenuta ordinata in funzione dell’ordine crescente del valore delle chiavi in definitiva è piu’ conveniente usare vector quando non bisogna fare frequenti inserimenti/cancellazioni e si vuole accedere in maniera diretta a un elemento occorre includere la libreria <map: #include <map> è piu’ conveniente usare list quando non bisogna accedere in maniera diretta agli elementi ed occorre fare numerosi interventi di inserimento o eliminazioni la dichiarazione avviene ad esempio con: map<int, string> libro; //mappa dei libri a cui si accede tramite un intero (p.e. codice) libro[cod] = “Il milione”; 17 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni 18 Il contenitore map Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Il contenitore map Metodi principali size_type size( ) Iteratori // restituisce il numero di elementi nella mappa m bool empty( ) // restituisce true se la mappa m è vuota void insert(valType(“antonio", 22)) // inserisce nella mappa il valore 22 con chiave “antonio"; l’inserimento avviene soltanto se nella mappa non esiste già un’istanza con la stessa chiave iterator find(“antonio") // restituisce un iteratore all’istanza nella mappa la cui chiave è “antonio”; se l’istanza non è presente restituisce un iteratore uguale a end( ) int count(“antonio") // restituisce il numero di istanze nella mappa la cui chiave è “antonio"; il valore restituito può essere 0 o 1 map<string,int>::iterator i; // un iteratore ad una mappa <string,int> i++ // avanza di un elemento i-- // retrocede di un elemento (*i).first // restituisce la chiave dell’oggetto puntato da i (oppure->) (*i).second // restituisce il valore dell’oggetto puntato da i (oppure->) Metodi di map che restituiscono o fanno uso di iteratori: iterator begin( ); // restituisce un iteratore al primo elemento della mappa iterator end( ); // restituisce un iteratore che punta subito dopo l’ultimo elemento della mappa typedef map<string,int>::value_type valType; // definisce val come tipo associato a map iterator erase(iterator i); // cancella l’elemento nella posizione dell’iteratore; restituisce un iteratore all’elemento successivo a quello cancellato 19 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni 20 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Esempio di contenitore map Uso dell’operatore [ ] per inserire valori in una mappa #include <map> #include <iostream> using namespace std; } #include <map> #include <iostream> using namespace std; int main( ) { map<string,int> m; m[“Antonio"] = 21; m[“Mario"] = 24; m["Giovanni"] = 21"; map<string,string>::iterator it; for(it = m.begin( ); it != m.end( ); it++) cout << it->first << ": " << it->second << endl; system("pause"); } Antonio : 23 Antonio : 23 Mario: 24 Mario: 24 int main( ) { map<string,int> m; typedef map<string,int>::value_type val; // definisce val come tipo associato a map m.insert(val(“Antonio", 23)); m.insert(val(“Mario", 24)); m.insert(val("Giovanni", 21)); map<string,int>::iterator it; for(it = m.begin( ); it != m.end( ); it++) cout << it->first << ": " << it->second << endl; system("pause"); Giovanni: 21 Giovanni: 21 21 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni 22 Altri contenitori STL (coda/pila) Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Contenitore string std::queue #include <queue> "Container Adapter" (contenitore basato su altri contenitori) ottimizzato per il funzionamento in modo FIFO (First In, First Out) con push( ) = inserzione in testa e pop( ) = rimozione in coda. string è una classe della libreria STL che rappresenta un caso particolare di contenitore costituito da un array di caratteri std::stack #include <stack> "Container Adapter" (contenitore basato su altri contenitori) ottimizzato per il funzionamento in modo LIFO (Last In, First Out) con push( ) = inserzione e pop( ) = rimozione in testa. la dichiarazione avviene ad esempio con: string nome; // stringa con nome “nome” 23 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni occorre includere la libreria <string>: #include <string> definisce al suo interno l’overloading degli operatori: ¾ = assegnazione ¾ == confronto ¾ + concatenazione ¾ << output su stream ¾ >> per l’input da stream 24 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Il contenitore string Algoritmi STL Metodi principali string::substr(indice, numero) restituisce una stringa costituita dalla sottostringa a partire dalla posizione indice con numero di caratteri string::size( ) restituisce il numero di caratteri (escluso \0) Il vantaggio principale della libreria STL è la possibilità di utilizzare una vasta collezione di algoritmi (procedure standard applicate a strutture dati standard). Di seguito verranno analizzati solo alcuni degli algoritmi disponibili nella libreria standard C++, ai quali si può accedere attraverso gli header file <algorithm> e <numeric>. string::replace(indice,numero,stringa) sostituisce una stringa con un’altra a partire dalla posizione indice da numero di caratteri e stringa rimpiazzata string::c_str( ) converte un tipo string in un array di caratteri char* per rendere il codice compatibile con le librerie della gestione delle stringhe in C (p.e. nome.c_str( ) e poi bisogna usare le tipiche funzioni del C strcpy, etc) 25 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni 26 Algoritmi STL Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Algoritmi STL #include <algorithm> Algoritmi principali: iterator find(iterator first, iterator last, const T& value); Gli elementi nell’intervallo [first,last] sono confrontati con value usando l’operatore == associato al tipo T. Se si trova una corrispondenza, la ricerca finisce e restituisce un iteratore all’elemento. Se non trova alcuna corrispondenza viene restituito last. void replace(iterator first, iterator last, const T& oldVal, const T& newVal) Sostituisce tutte le istanze di oldVal con newVal nell’intervallo specificato dalla coppia di iteratori [first,last) void sort(iterator first, iterator last) Riordina gli elementi nell’intervallo [first,last] in ordine crescente usando l’operatore < associato al tipo degli elementi. 27 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni conta(iterator first1, iterator last1, val_cercato) conta gli elementi che sono uguali a val_cercato max_element( ) e min_element( ) esempio: vector<int> v; vector<int>::iterator i; ........ i=max_element(v.begin( ), v.end( )); cout<< “massimo: “<< *i << endl; i=min_element(v.begin( ), v.end( )); cout<<“minimo: “<< *i<<endl; ........ 28 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Esempio sull’uso dell’algoritmo find Funzioni virtuali (ulteriori chiarimenti) #include <list> triangolo_rett #include <algorithm> #include <iostream> base altezza using namespace std; int main( ) { Assegna Area Perimetro Stampa list<int> l; for (int i = 1; i <= 10; i++) l.push_back(i); int x; cout << "Numero da cercare: "; triangolo_isosc class triangolo_rett { public: double base, altezza; void Assegna(double, double); double Area( ); double Perimetro( ); void Stampa( ): triangolo_rett( ): base(0.0),altezza(0.0) { } }; cin >> x; list<int>::iterator it = find(l.begin( ), l.end( ), x); if (it != l.end( )) cout << "Numero trovato\n"; else cout << "Numero non trovato\n"; Perimetro system("pause"); } 29 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni 30 Funzioni virtuali (ulteriori chiarimenti) Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Funzioni virtuali (ulteriori chiarimenti) void triangolo_rett::Assegna(double b, double h) { base=b; altezza=h; } class triangolo_isosc:public triangolo_rett { public: double Perimetro( ); }; double triangolo_rett::Area( ) { return base*altezza/2; } void triangolo_isosc::Perimetro( ) { return base+2*sqrt(pow(altezza,2.0)+pow(base/2,2.0)); } double triangolo_rett::Perimetro( ) { return (base+altezza+sqrt(pow(base,2.0),pow(altezza,2.0))); } void triangolo_rett::Stampa( ) { cout << base << endl; cout << altezza << endl; cout<< Area( ) << endl; cout<< Perimetro( ) << endl; } 31 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni 32 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Funzioni virtuali (ulteriori chiarimenti) Funzioni virtuali (ulteriori chiarimenti) #include <iostream> #include <cmath> int main( ) { triangolo_rett TR; triangolo_isosc TI; TR.Assegna(2.0, 3.0); TI.Assegna(5.0, 4.0); TR.Stampa( ); TI.Stampa( ); //risultato errato perchè viene richiamato il metodo della classe base } 33 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni class triangolo_rett { public: double base, altezza; void Assegna(double, double); double Area( ); virtual double Perimetro( ); void Stampa( ): triangolo_rett( ): base(0.0),altezza(0.0) { } }; 34 Riepilogo della lezione Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Fine della lezione STL - Standard Template Library C++ Contenitori (vector, list, map, string) Iteratori Algoritmi (find, sort, ecc) Ulteriori chiarimenti sulle funzioni virtuali 35 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Domande? 36 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni Esercizi 1-2 Implementare la classe della pila con i metodi richiesti nelle lezioni precedenti utilizzando il contenitore vector Implementare la classe della pila con i metodi richiesti nelle lezioni precedenti utilizzando il contenitore list 37 Fondamenti di Informatica II – A.A. 2008-2009 a cura di Pascoschi Giovanni