Un tipo di dato derivato è ottenuto a partire da tipi di dato predefiniti attraverso gli operatori *, &, [] definendo enumerazioni definendo struct I tipi di dato derivati non sono tipi di dati nuovi, ma semplice composizione di tipi di dati esistenti 1 2001/02 1
Array Un array è un insieme di oggetti dello stesso tipo referenziati da un unico identificatore Gli oggetti dell array sono referenziati tramite l identificatore dell array e la loro posizione nell insieme (indicizzazione) int ia[10]; int i = ia[2]; ia[7] = i; // ia è un vettore di 10 interi // copia il terzo elemento di ia in i // copia i sull' ottavo elemento di ia La dimensione dell array può essere qualsiasi espressione costante non può essere variabile 2 Indicizzazione di un Array Le posizioni degli oggetti in un array si contano da 0 Il compilatore non effettua nessun controllo sulla correttezza dell indicizzazione char c[7]; c[7] = `Y ; // scrive Y nell ottavo elemento di c Indicizzazione errata implica un accesso ad aree di memoria non allocate all array Può provocare errori in esecuzione (segmentation fault) Può distruggere i dati del programma 3 2001/02 2
Inizializzazione di un Array L array è inizializzato dando la lista dei valori int ia[3] = {0, 1, 2}; Se il vettore è inizializzato si può non specificare la dimensione int ia[] = {0, 1, 2}; E possibile inizializzare parzialmente un array int ia[3] = {1}; // ia[0] = 1, gli altri elementi valgono 0 4 Array di char E possibile inizializzare un array di char con una stringa costante Una stringa è un array di char con il simbolo finale `\0 const char ca[] = {`C, `+, `+ }; // ca lungo 3 const char ca[] = C++ ; // ca lungo 4 const char ca[5] = prova ; // ERRORE 5 2001/02 3
Operazioni su Array Non è possibile inizializzare o assegnare un array ad un altro array int ia[] = {1, 2, 3}; int ia2[] = ia; Se si vuole copiare un array bisogna copiare un elemento per volta for(int i = 0; i<3; i++) ia2[i] = ia[i]; // ERRORE 6 Array Multidimensionali Si definisce un array multidimensionale specificando ogni dimensione tra parentesi quadre char a[3][4]; // matrice di 3 righe e 4 colonne Un array bidimensionale è un array di array a a[0] a[1] a[2] 7 2001/02 4
Inizializzazione di Array Multidimensionali Un array bidimensionale è un array di array ogni array inizializzato separatamente int ia[3][4] = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}}; int ia[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; E possibile inizializzare parzialmente un array multidimensionale int ia[3][4] = {0, 1, 2, 3}; int ia[3][4] = {{0}, {4}, {8}}; 8 Accesso a Array Multidimensionali Per accedere ad un elemento di un array multidimensionale bisogna specificare ogni indice in una parentesi quadra int i = ia[2][3]; i = ia[2, 3]; // ERRORE cosa fa in realtà l'istruzione errata? assegna ia[3] ad i ia[3] è un array 9 2001/02 5
Relazione tra Array e Puntatori Alla definizione di un array il compilatore alloca spazio per contenere tutti gli elementi dell array e definisce un puntatore inizializzato con l indirizzo del primo byte allocato char ac[5]; nome tipo indir. ac char* 10 Tipo di un Array Il tipo di un array è puntatore al tipo degli oggetti dell array Ogni operazione di indicizzazione è implementata attraverso l aritmetica dei puntatori ia[4] = 3; // implementata come *(ia + 4) = 3 m[1][2] = 0; /* implementata come *(*(m + 1) + 2) = 0 */ 11 2001/02 6
Tipo di un Array L identificatore dell array si comporta come un puntatore costante E sempre possibile assegnare un array ad un puntatore dello stesso tipo char buffer[256]; char *p = buffer; // p indirizza il primo elemento di buffer Non è possibile assegnare un puntatore ad un array buffer = p; // ERRORE 12 Differenze tra Array e Puntatori La definizione di un array implica allocazione di memoria per tutti gli oggetti dell array e per il puntatore che li indirizza La definizione di un puntatore implica allocazione di memoria per un indirizzo 13 2001/02 7
Il Contenitore vector La classe vector della libreria standard è una valida alternativa agli array stile C #include <vector> Differenze tra vector e array // include definizione classe vector È possibile definire vector di dimensione variabile è possibile modificare le dimensioni di un vector Non è possibile inizializzare esplicitamente oggetti vector È possibile assegnare un vector ad un altro vector Esistono operazioni su vector 14 Definizione di oggetti vector vector<t> a; /* Definisce un vettore di tipo T il cui identificatore è a e la cui dimensione è 0 */ vector<t> a(5); // equivale a T a[5]; // Definisce un vettore di tipo T di 5 elementi vector<t> a(5, 4); // equivale a T a[] = {4, 4, 4, 4, 4} /* Definisce un vettore di tipo T di 5 elementi inizializzati con 4 */ 15 2001/02 8
Accesso a elementi di vector L'accesso al vector può essere fatto tramite l'operatore [] Simile all'accesso agli array #include <vector> vector<int> vec(10); for(int i = 1; i <= 10; ++i) vec[i] = i; 16 Accesso a elementi di vector stile STL E' possibile accedere agli elementi del vector in maniera indipendente dalla rappresentazione della classe stessa tecnica per accedere ad ogni tipo di classe contenitore #include <vector> vector<int> vec(10); vector<int>::iterator it = vec.begin(); for(int i = 0; it!= vec.end(); ++i, ++it) *it = i; 17 2001/02 9
Iteratori L'iteratore è una classe che implementa l'astrazione del puntatore operazioni ammissibili =, *, ++, -- ogni contenitore ha la propria implementazione di iteratore, definita all'interno della classe Ogni contenitore fornisce metodi per recuperare indirizzi di suoi elementi tramite iteratori è possibile accedere e scorrere gli elementi di tutti i contenitori alla stessa maniera vector<t>::begin(); // primo elemento di vector vector<t>::end(); // elemento successivo all ultimo 18 Alcuni metodi della classe vector empty() // restituisce vero se il vettore è vuoto size() // restituisce # di elementi nel vettore capacity() // restituisce la grandezza del vettore resize(n) // la nuova dimensione del vettore è N push_back(x) // aggiunge x alla fine del vettore pop_back() // elimina l ultimo elemento del vettore per utilizzare i metodi della classe vector si usa l'operatore di selezione vector<int> v; v.metodo(); 19 2001/02 10
Ridimensionamento dinamico di vector un oggetto vector può essere allungato dinamicamente senza allocare esplicitamente la memoria #include <vector> #include <iostream> vector<string> testo; string parola; while(cin >> parola) testo.push_back(parola); cout << "Le parole lette sono:" << endl; for(vector<string>::iterator it = testo.begin(); it!= testo.end(); ++it) cout << *it << ' '; cout << endl; 20 Algoritmi su vector La libreria standard fornisce una serie di algoritmi generici per operare su qualsiasi tipo di contenitore algoritmi di ricerca ed ordinamento find(), find_if(), search(), binary_search(), count(), count_if() sort(), merge(), partition(), reverse(), rotate(), random_shuffle() algoritmi di creazione e cancellazione generate(), fill(), transform(), copy(), for_each(), remove(), unique() algoritmi relazionali e numerici equal(), min(), max() partial_sum(), inner_product(), accumulate(), adjacent_differences() 21 2001/02 11
Esempio uso vector #include <vector> #include <algorithm> #include <iostream> main() { int ia[10] = {51, 23, 7, 88, 41, 98, 12, 103, 37, 6}, x; vector<int> vec(ia, ia+10); sort(vec.begin(), vec.end()); reverse(vec.begin(), vec.end()); cin >> x; vector<int>::iterator trovato; trovato = find(vec.begin(), vec.end(), x); if(trovato!= vec.end()) cout << "valore trovato" << endl; else cout << "valore non presente" << endl; } 22 Stringhe Una stringa (stile C) è un array di caratteri indirizzato attraverso un puntatore Il tipo di una stringa è char* char *s = ciao mondo\n ; Una stringa è rappresentata in memoria da una sequenza di caratteri seguiti dal segnale di fine stringa (`\0 ) 23 2001/02 12
Esempio Stringhe Calcolare la lunghezza della stringa ciao mondo\n #include <iostream> char *st = ciao mondo\n ; int main() { int lung = 0; char *p = st; while( *p!= `\0 ) { lung = lung + 1; p = p+1; } cout << lunghezza di << st << = << lung; return 0; } 24 Operazioni sulle Stringhe La libreria standard del C fornisce funzioni per effettuare alcune operazioni su stringhe #include <cstring> int strlen(const char* s); // calcola lunghezza di s int strcmp(const char* s, const char* t); // controlla se s e t sono uguali int strcpy(const char* s, const char* t); // copia t su s 25 2001/02 13
Il Tipo string La libreria standard fornisce una nuova implementazione delle stringhe come classe Principali differenze Inizializzare una stringa con un'altra stringa Copia di stringhe Accesso ai singoli elementi della stringa Operazioni di confronto tra stringhe Operazioni di concatenazione e calcolo lunghezza Operazioni di manipolazione stringhe Controllo stringa vuota Conversione a stringa C-style 26 Esempio uso di string Calcolare la lunghezza della stringa ciao mondo\n #include <iostream> #include <string> string st = ciao mondo\n ; int main() { int lung = st.size(); cout << lunghezza di << st << = << lung; return 0; } 27 2001/02 14
Alcuni metodi della classe string bool empty() // restituisce vero se la stringa è vuota int size() // restituisce # di caratteri nella stringa string operator+(const string&) string operator+=(const string&) // concatena due stringhe const char* c_str() // converte la stringa in stile C 28 Enumerazioni Un enumerazione è un insieme di costanti simboliche intere Insieme di attributi da associare ad un oggetto enum stato { caldo, freddo }; // caldo = 0, freddo = 1; Gli enumeratori non sono singolarmente indirizzabili non si può applicare l operatore (&) ad un enumeratore Definizione di un enumerazione enum colore { giallo, rosso, verde = 1, bianco }; // giallo = 0, rosso = 1, verde = 1, bianco = 2 29 2001/02 15
Enumerazioni E possibile definire una variabile del tipo definito da un enumerazione colore vernice = giallo; //vernice può assumere solo i valori giallo, rosso, verde e bianco Non è possibile assegnare valori interi ad una variabile di tipo enumerazione E' possibile assegnare una variabile di tipo enumerazione ad una variabile int vernice = giallo; // giallo contiene il valore 0 vernice = 0; // ERRORE int i = vernice; // i = 0 30 Tipo bool Una variabile di tipo bool può assumere come valori solo i valori true e false bool trovato = false; 31 2001/02 16
Struct Uno struct è un insieme di oggetti, non necessariamente dello stesso tipo, memorizzati sequenzialmente ed identificati da un unico nome Gli elementi di uno struct sono referenziati attraverso l identificatore dello struct ed il loro specifico identificatore attraverso gli operatori di selezione (.) e (->) struct record { string nome, cognome, indirizzo; int eta; }; record dipendente; dipendente.nome = mario ; 32 Classi La classe è una generalizzazione dello struct Insieme di oggetti e funzioni (metodi) che operano su questi oggetti Ogni elemento di una classe ha un livello di visibilità Una funzione può accedere soltanto agli elementi di visibilità public di oggetti della classe Per ogni classe si definisce un interfaccia pubblica che consente di interagire con oggetti di quella classe l interfaccia pubblica è un insieme di metodi che hanno visibilità public La classe implementa il concetto di Abstract Data Type string e vector<t> sono classi 33 2001/02 17
Esempio di classe String class String { public: String(); String(const char *); String(const String&); ~String(); String& operator=(const String&); bool operator==(const String&); char& operator[](int); int size(); char* c_str(); private: int dim; char *arr; }; // String str; // String str("ciao"); // String str1 = str; 34 Typedef L operatore typedef consente di assegnare un identificatore ad un tipo di dato derivato Il typedef non crea un nuovo tipo di dato typedef char* stringa; Il tipo definito dal typedef può essere utilizzato come specificatore di tipo in una definizione o dichiarazione stringa c = ciao ; Il typedef è usato per diminuire la complessità notazionale delle definizioni 35 2001/02 18
Variabili Volatili Una variabile è dichiarata volatile se il suo valore può cambiare al di fuori del controllo del programma Variabili che leggono il time dal sistema Il compilatore deve evitare di applicare tecniche di ottimizzazione del codice a queste variabili volatile int time; volatile char* buffer; 36 2001/02 19