1 REFERAT DE LABORATOR NR. 14 TEMA: Soluii template (clase i funcii template). Implementarea coleciilor de date cu ajutorul soluiiloe template. Tratarea excepiilor.
PROBLEME REZOLVATE 1
Exerciiul 1: Pornind de la exemplul implementat parial n curs (exerciiul 7.1.), s se implementeze i testeze o funcie template de comparare a dou numere ntregi, a dou numere reale, a dou obiecte de tip cerc i a dou obiecte de tip dreptunghi. Funcia va primi ca argumente referine ctre datele de comparat i o va returna pe cea mai mare dintre ele.
Exerciiul 2: S implementm o funcie generic de ordonare - prin procedeul QuickSort - care s poat ordona numere ntregi, numere reale, numele unor persoane sau numere complexe. OBS: Pentru a putea aplica operatorul > pentru datele de tip persoana sau complex, trebuie suprancrcat pentru aceste tipuri de date. Pentru tipul complex (drept criteriu de comparare se consider modulul) se poate porni de la implementarea din capitolul 3. class complex { double re,im; public: // . . . . . . . . . . double modul( ) const {return (pow(re)+pow(im)); int operator>(const complex&z1) {if (modul() > z1.modul()) return 1; else return 0; } };
Pentru tipul persoana (cu date membre de tip sir), se poate porni de la implementri anterioare., cu modificrile: class sir { int lung; //lungimea propriu-zisa, fara terminator char *sirul; //adresa inceput sir (sirul-pointer catre inceput sir) public: // . . . . . int operator > (const sir& s1) const {return strcmp(sirul, s1.sirul)>0;} };
class persoana { protected: ir numele,prenumele; char sexul; public: int operator > (const persoana& p1) {if (numele>p1.numele) return 1; else return 0;} };
/* frecventa literelor dintr-un sir de litere, terminat cu ., introdus de la tastatura */ Array<int>numara_litere(a, z); for (char c=a; c<=z; c++) numara_litere[c]=0; PROGRAMAREA ORIENTATA PE OBIECTE Limbajul C++
Exerciiul 4: Implementarea unei liste dublu nlnuite prin clase template. template <class E> class TListNode{ E elem; TListNode* prev; TListNode* next; public: friend class TList<E>; TListNode() { prev = NULL; next = NULL;} TListNode(E el){elem = el; prev = NULL; next = NULL;} TListNode* GetNext(){return next;} TListNode* GetPrev(){return prev;} virtual ~TListNode(){cout<< "Destructor baza nod \n";} };
template <class E> class TList{ TListNode<E>* first; TListNode<E>* last; int count; public: TList(){ first = 0; last = 0; count = 0;} TList(TList& r); ~TList(){}; PROGRAMAREA ORIENTATA PE OBIECTE Limbajul C++
Autor: Diana Stefanescu 5 int GetCount(){return count;} void AddHead(E); void AddTail(E E GetHead(); ); E GetTail(); E RemoveHead(); E RemoveTail(); void Display(); friend ostream& operator<<(ostream& stream, TList& list); };
//.............................. template <class E> void TList<E>::AddHead(E x){ TListNode<E>* elem = new TListNode<E>(x); if (count == 0){ first = elem; last = elem; } else{ first->prev = elem; elem->next = first; first = elem; } count++; }
template <class E> E TList<E>::RemoveHead(){ E v; if (count == 0){ cout << Eroare lista vida\n;return v; } else { v = first->elem; TListNode<E>* p = first; first = first->next; if (first) first->prev = 0; delete p; count--; if (count == 0)last = 0; return v; } }
Lista definit prin clasele template poate funciona ca stiv sau ca i coad, aa cum ilustreaz exemplul: void f(){ /* Functionare ca stiva a listei */ Tlist <int> x; x.AddHead(1); // push 1 x.AddHead(2); // push 2 x.AddHead(3); // push 3 cout << x.RemoveHead(); // pop, afiseaza 3 cout << x.RemoveHead(); // pop, afiseaza 2 cout << x.RemoveHead(); // pop, afiseaza 1 /* Functionarea ca o coada a listei */ Tlist <double> y; y.AddTail(1); // inserare 1 y.AddTail(2); // inserare 2 y.AddTail(3); // inserare 3 cout << y.RemoveHead(); // extragere afiseaza 1 cout << y.RemoveHead(); // extragere afiseaza 2 cout << y.RemoveHead(); // extragere afiseaza 3 cout << endl; }
Exerciiul 5: Implementarea unui arbore binar ordonat 2 ale crui noduri conin orice tip de informaie, tip care se precizeaz ca argument al clasei template. Arborele binar ordonat de elemente de un tip oarecare E se definete prin dou clase template, TBTreeNode i TBTree.
template <class E> class TBTreeNode{ E d; // informatia continuta in nod TBTreeNode *left, *right; // pointeri la fii
2 Implementarea coleciilor de date cu elemente ordonate folosind ierarhii de clase (clas de baz care s defineasc forma coleciei i clase derivate care s particularizeze tipul de date) este dificil, deoarece majoritatea operaiilor (inserare, tergere, cutare) necesit comparaii ale valorilor elementelor (informaiile din colecie), care nu sunt definite n clasa de baz. PROGRAMAREA ORIENTATA PE OBIECTE Limbajul C++
Autor: Diana Stefanescu 6 friend class TBTree<E>; public: TBTreeNode(E x) { d = x; left = right = NULL; } ~TBTreeNode() { left = right = NULL; } };
n programul de test, prin declaraii de forma: TBTree <int> i; TBTree <double> d, TBTree<Complex> c, se definesc obiecte pentru tipurile de date int, double,respectiv Complex, asupra crora se poate opera n mod obinuit, folosind funciile membre ale clasei template. n funcia main() se creeaz un arbore binar ordonat cu 10 noduri, informaia din fiecare nod fiind un numr complex, definit prin clasa Complex. Aceste informaii sunt apoi afiate n inordine.
Exerciiul 5: Implementarea unui vector asociativ. Vectorul asociativ, reprezentat ca o list dublu nlnuit de elemente de tip MapNode, este descris de clasa template Map, avnd aceleai argumente, tipurile de date class K i class V. Aceast clas definete lista dublu nlniut printr-un pointer la primul element al listei (head) i numrul de elemente (noduri) ale listei (size).
PROGRAMAREA ORIENTATA PE OBIECTE Limbajul C++
Autor: Diana Stefanescu 7 template <class K, class V> class MapNode{ friend class Map<K,V>; friend class MapIter<K,V>; K key; V value; MapNode *left; MapNode *right; public: MapNode(const K& k, const V& v):key(k), value(v){ left = NULL; right = NULL; } ~MapNode(); };
template <class K, class V> class Map{ friend class MapNode<K,V>; friend class MapIter<K,V>; MapNode<K,V>* head; MapNode<K,V>* current; /* pointerul current la un obiect de tipul MapNode, memoreaz poziia curent n lista nlnuit, adic ultima poziie accesat prin funcia operator de indexare */ V def_v; //memoreaza valoarea implicita a cheii key K def_k; //memoreaza valoarea implicita a valorii value int size; void init(){ size = 0; head = 0; current = 0;} public: Map() {init();} Map(const K& k, const V& v) :def_k(k),def_v(v) {init(); } /* La crearea unui obiect din clasa Map valorile implicite ale cheii i valorii se transmit ca argumente ale constructorului */ Map(const Map& r); ~Map(); void remove(const K& k); Map& operator=(const Map& m); V& operator[] (const K& k); // Operaia cea mai important a clasei int GetSize() const {return size;} };
Operaia cea mai important a clasei Map este operaia de indexare, pentru care s-asuprancrcat operatorul de indexare. Vectorul asociativ trebuie s se comporte ca un vector de date n care indexarea printr-un indice este nlocuit cu indexarea printr-o valoare a cheii. Ca urmare, suprancrcarea operatorului de indexare returneaz o referin la valoarea (value) corespunztoare cheii date, astfel nct valoarea dintr-un element (value) s poat fi folosit att n membrul drept al unei expresii (valoarea este citit), ct i n membrul stng al unei expresii (valoarea este scris).
Implementarea funciei operator de indexare este urmtoarea: template<class K, class V> V& Map<K, V>::operator[](const K& k){ if(head == 0){ current = head = new MapNode<K, V>(k, def_v); current->left = current->right = 0; return current->value; } MapNode<K,V>* p = head; for (;;){ if(p->key == k) { // cheie gasita current = p; return current->value; } if (k < p->key){ // inserare inainte de p current = new MapNode<K, V>(k, def_v); current->left = p->left; current->right = p; if (p == head) head = current; else p->left->right = current; return current->value; } MapNode<K, V>* s = p->right; PROGRAMAREA ORIENTATA PE OBIECTE Limbajul C++
Autor: Diana Stefanescu 8 if(s == 0) { // inserare dupa p, la sfarsit current = new MapNode<K,V>(k, def_v); current->left = p; current->right = 0; p->right = current; return current->value; } p = s; } }
Exerciiul 6: S se implementeze un iterator al vectorului asociativ descris de clasele Map i MapNode. Pentru implementarea unui iterator al vectorului asociativ descris de clasele Map i MapNode vom folosi o alt clas template, MapIter, ale crei funcii membre vor fi funcii de parcurgere n ordinea dorit a vectorului asociativ. De exemplu, se pot implementa funcii de parcurgere n ordine cresctoare, respectiv descresctoare a cheilor elementelor.
Exerciiul 7: Pornind de la exexciiul 6, s se creeze un vector asociativ cu cheie de tip String i valoare de tip ntreg. Folosind iteratorul implementat n exemplul 6, care acceseaz succesiv elementele listei nlnuite, s se parcurg iterativ lista i s se afieze cheia i valoarea elementelor listei.
Exerciiul 8: Dac s-ar fi dorit parcurgerea vectorului dup o alt regul (de exemplu, din dou n dou elemente a listei nlnuite n ordinea cresctoare a cheii), ar fi trebuit s fie suprancrcat funcia operator+=() a clasei MapIter astfel:
template <class K, class V> MapIter<K,V>& MapIter<K,V>::operator+=(int inc){ for (int i=0;i<inc;i++){ if (node) node = node->right; else break; } return *this; }
Exerciiul 8: Se modific funcia f2()din ex. 7 astfel nct vectorul asociativ tab s fie inspectat simultan prin intermediul a doi iteratori, iter1 i iter2, din care iteratorul iter1 parcurge lista din element n element n ordinea cresctoare a cheii, iar iteratorul iter2 parcurge lista din dou n dou elemente n ordinea cresctoare a cheii.
Dac s-ar fi dorit parcurgerea vectorului dup o alt regul (de exemplu, din dou n dou elemente a listei nlnuite n ordinea cresctoare a cheii), ar fi trebuit s fie suprancrcat funcia operator+=() a clasei MapIter astfel:
template <class K, class V> MapIter<K,V>& MapIter<K,V>::operator+=(int inc){ for (int i=0;i<inc;i++){ if (node) node = node->right; else break; } return *this; }
PROBLEME PROPUSE 1. Pentru structurile de date prezentate n capitolul 6 (liste, stive, cozi, arbori) modificai implementrile, conform soluiilor template. 2. S se definesc un vector de iruri de caractere (obiecte de clas String) folosind clasa template Tarray <String> i s se verifice funcionarea acestuia ca stiv i coad de iruri de caractere. 3. S se defineasc o clas Int care s se comporte exact ca tipul fundamental int, cu deosebirea c lanseaz excepii n situaiile de depire inferioar i superioar care apar n diferite operaii aritmetice. 4. S se implementeze o funcie de copiere de la un fiier surs ntr-un fiier destinaie, n care s se lanseze excepii pentru urmtoarele situaii: erori de deschidere sau nchidere fiiere, erori de citire din fiierul surs, erori de scriere n fiierul destinaie. Pentru fiecare tip de eroare s se defineasc o clas excepie, iar apelul funciei de copiere s fie executat ntr-un bloc try, urmat de rutinele de tratare a excepiilor corespunztoare. 5. S se defineasc o clas template TVector cu clase locale pentru excepiile Range i Size. 6. Pentru clasa template TBTree (definit n capitolul 7) care implementeaz o mulime printr-un un arbore binar ordonat, s se defineasc o clas local pentru definirea excepiei la cutarea unui element n mulime: dac elementul nu este gsit, funcia de cutare va lansa o excepie. Se va particulariza pentru un arbore binar sortat de iruri de caractere (obiecte de tipul String). 7. S se implementeze o funcie de nsumare a elementelor unui obiect de tip Vector care s lanseze o excepie dac se depeste capacitatea de reprezentare a numerelor ntregi.