Sunteți pe pagina 1din 10

PROGRAMAREA ORIENTATA PE OBIECTE Limbajul C++

Autor: Diana Stefanescu


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;}
};


#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <iostream.h>
#include Sir.h
#include complex.h

const int kSMALL_ENOUGH=
template <class Object>
15;


1
Unele rezolvate parial (a se urmri suportul complet de curs)
PROGRAMAREA ORIENTATA PE OBIECTE Limbajul C++

Autor: Diana Stefanescu
2
void selectionsort(Object d[],int left,int right)
{
for (int i=left;i<right;i++){
int min=i;
for(int j=i+1;j<=right;j++)
if(d[j]<d[min]) min=j ;
Object temp=d[min]; d[min]=d[i]; d[i]=temp;
}
}

template<class Object>
int partition(Object d[],int left,int right)
{
Object val=d[left]; int lm=left-1; int rm=right+1;
for(;;){
do rm--;
while(d[rm]>val);
do lm++;
while(d[lm]<val);
if(lm<rm){
Object tempr=d[rm]; d[rm]=d[lm]; d[lm]=tempr;
}
else return rm;
}
}

template<class Object>
void quicksort(Object d[],int left,int right)
{
if(left<(right-kSMALL_ENOUGH)){
int split_pt=partition(d,left,right);
quicksort(d,left,split_pt);
quicksort(d,split_pt+1,right);
}
else selectionsort(d,left,right);
}

const int kBIG=350;
int x1[kBIG];
double x2[kBIG*2];

int main()
{clrscr();
int i;
cout<<"Generare vector initial, de intregi:\n";
for(i=0;i<kBIG;i++){
x1[i]=rand()%15000; cout<<Object[i]<<'\t';
if(i!=0 && i%20==0) {cout<<endl;getch();}
}
getch();
quicksort(x1,0,kBIG-1); // ordonare vector de intregi
clrscr(); cout<<"\nVector ordonat:\n";
for(i=0;i<kBIG;i++){
cout<<x1[i]<<" ";
if(i!=0 && i%20==0)
{cout<<endl;getch();}
}
cout<<"\nApasa o tasta...\n";getch();
clrscr(); cout<<"Generare vector initial, de reali:\n";
for(i=0;i<kBIG*2;i++){
x2[i]=(rand()%30000)/7.0;
cout<<Object2[i]<<'\t';
if(i!=0 && i%20==0)
{cout<<endl;getch();}
}
getch();clrscr();
quicksort(x2,0,kBIG*2-1); // ordonare vector de reali
cout<<"\nVector ordonat:\n";
for(i=0;i<kBIG;i++){
cout<<x2[i]<<",";
if(i!=0 && i%20==0)
PROGRAMAREA ORIENTATA PE OBIECTE Limbajul C++

Autor: Diana Stefanescu
3
{cout<<endl;getch();}
}
cout<<endl;
//
persoana P[30];
//
quicksort(P,0,30); // ordonare vector de tip persoana
//
complex C[20];
//
quicksort(C,0,20); // ordonare vector de tip complex
//
return 1; }


Exerciiul 3: S se implementeaze tipul generic tablou mrginit.
template <class DType>
class Array{
public:
Array(int low_lim,int high_lim);
~Array();
int size()const;
int low()const;
int high()const;
DType& operator[](int ndx);
void printOn(ostream& os);
private:
void operator=(const Array &a);
Array(const Array &a);
DType *fdata;
int flow;
int fhigh;
int fsize;
};

template<class DType>
Array<DType>::Array(int low_lim,int high_lim) //constructor
{ assert(low_lim<high_lim); fsize=high_lim-low_lim;
fsize+=1; flow=low_lim; fhigh=high_lim; fdata=new DType[fsize];
}

template<class DType> //destructor
Array<DType>::~Array() { delete fdata;}

template<class DType>
int Array<DType>::size()const {return fsize;}

template<class DType>
void Array<DType>::printOn(ostream& os)
{ for (int i=0;i<fsize;i++){
int j=i+flow; os<<"["<<setw(4)<<j<<"]\t:";os<<fdata[i];os<<endl; }
}

template<class Dtype>
DType& Array<Dtype>::operator[](int ndx)
{
assert(ndx>=flow); assert(ndx<=fhigh);int j=ndx-flow;return fdata[j]; }

main()
{Array <int> a(3,7);
cout<<a.size()<<endl;
a[3]=17;a[4]=21;a[5]=a[3]+a[4];a[6]=-1;a[7]=123;
a.printOn(cout);
Array <double> b(2, 4);
b[2]=2.55;b[3]=-9.89;b[d]=89.345;
b.printOn(cout);

/* 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++

Autor: Diana Stefanescu
4
cout<<Introdu text . . . <<endl;
cin.get(c);
while(c != .){
if (isalpha(c)){
c=tolower(c); numara_litere[c]++;
}
cin.get(c) ;
}
cout<<endl<<Frecventa literelor este:<<endl; numara_litere.printOn(cout);
}


Exerciiul 4: Se implementeaz clasa generic stiv (Stack).
#include <iostream.h>
c

onst int MAXSIZE = 128;
template <class T>
class Stack
{
private:
T _array[MAXSIZE];
int _stackptr;
public:
Stack() : _stackptr(0) {}
T push(const T x)
{if(_stackptr < MAXSIZE) return _array[_stackptr++] = x;
else return (T)0; }
T pop()
{ if(_stackptr >0) return _array[--_stackptr];
else return (T)0; }
int empty() const
{ return (_stackptr == 0);}
};

main()
{ Stack<int> istack;
Stack<float> fstack;

cout << "Push:" << endl;
cout << istack.push(1) << endl;
cout << istack.push(2) << endl;cout << istack.push(3) << endl;

cout << "Pop:" << endl;
cout << istack.pop() << endl; cout << istack.pop() << endl;
cout << istack.pop() << endl;
}

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; }
};

template <class E>
class TBTree{
TBTreeNode<E> *root;
int count;
TBTreeNode<E> *insert1(TBTreeNode<E> *root,
TBTreeNode<E> *r, E data);
void inorder1(TBTreeNode<E> *root);
void preorder1(TBTreeNode<E> *root);
void postorder1(TBTreeNode<E> *root);
void delTree1(TBTreeNode<E> *root);
public:
TBTree() { root = NULL; count = 0;}
int getcount() {return count;}
void insert(E data);
int search(E data);
void remove(E data);
void inorder();
void preorder();
void postorder();
~TBTree();
};
template <class E>
TBTreeNode<E>* TBTree<E>::insert1(TBTreeNode<E> *root,TBTreeNode<E> *r, E data){
if(!r) {
r = new TBTreeNode<E>(data);
count++;
if(!root) return r;
if(data < root->d) root->left = r;
else root->right = r;
return r;
}
if (data == r->d) return 0;
if (data < r->d) return insert1(r, r->left, data);
else return insert1(r, r->right, data);
}
template <class E> void TBTree<E>::insert(E data) {
if(!root)
root = insert1(root, root, data);
else insert1(root, root, data);
}

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.

main(){
TBTree <Complex> c; //arb. binar cu noduri complecsi
for(i=0;i<n;i++){ Complex nrc(n-i-1); c.insert(nrc); }
cout << "Nr noduri: " << c.getcount()<< endl;
c.inorder();
TBTree <int> d;
for(i=0;i<n;i++){ Complex nrc(n-i-1); c.insert(nrc); }
cout << "Nr noduri: " << c.getcount()<< endl;
c.inorder();
}



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;
}
}

main(){
Map <int, String> x(-1,Implicit\n);
x[2] = Sirul 2\n; x[1] = Sirul 1\n; x[3] = Sirul 3\n;
cout << x[3]; cout << x[7]; cout << x[1]; cout << x[2]; }
/* Mesaje la executie:
Sirul 3
Default
Sirul 1
Sirul 2 */

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.

Clasa template MapIter este definit astfel:

template <class K, class V>
class MapIter {
friend class Map<
Map<K, V>* map;
K,V>;
MapNode<K,V>* node;
public:
MapIter(){map = 0; node = 0;}
MapIter(Map<K,V>* pmap, MapNode<K,V>* pnode){
map = pmap;
node = pnode; }
MapIter(Map<K,V>& mm){
map = &mm;
node = map->head;
}
operator void*() {return node;}
const K& key(){
if (node) return node->key;
else return map->def_k;
}
V& value(){
if (node) return node->value;
else return map->def_v;
}
MapIter& operator++(); // increment prefix
MapIter& operator--(); // decrement prefix
void operator++(int); // increment postfix
void operator--(int); // decrement postfix
};

//implementare operatori ++, --
template <class K, class V>
MapIter<K,V>& MapIter<K,V>::operator--(){
if(node) node = node->left;
return *this;
}

template <class K, class V>
void MapIter<K,V>::operator--(int){
if(node) node = node->left;
}

PROGRAMAREA ORIENTATA PE OBIECTE Limbajul C++

Autor: Diana Stefanescu
9
template <class K, class V>
MapIter<K,V>& MapIter<K,V>::operator++(){
if (node) node = node->right;
return *this;
}

template <class K, class V>
void MapIter<K,V>::operator++(int){
if(node) node = node->right;
}



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.

void f2(){
Map <String,int> tab("nil", 0);
tab["word1"] = 5;
tab["word3"] = 2;
tab["word3"] +=4;
tab["word2"] = 8;
MapIter<String,int> iter(tab);
for (; iter; ++iter)
cout << iter.key() << iter.value() << endl;


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.

void f3(){
Map<String,int> tab("nil", 0);
tab["word1"] = 5; tab["word3"] = 2;
tab["word3"] +=4; tab["word2"] = 8;
tab["word4"] = 9; tab["word5"] = 7;
MapIter<String,int> iter1(tab);
MapIter<String,int> iter2(tab);
for (; iter2; iter1++, iter2+=2) {
cout << iter1.key() << iter2.value() << endl;
cout << iter2.key() << iter2.value() << endl;
}
}
/* Mesaje la execuia funciei:
word1 5
word2 8
word3 6
word4 9
word5 7 */
PROGRAMAREA ORIENTATA PE OBIECTE Limbajul C++

Autor: Diana Stefanescu
10

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.

S-ar putea să vă placă și