Sunteți pe pagina 1din 30

Funcții și clase generice 1

LUCRARE DE LABORATOR NR. 11

FUNCŢII ŞI CLASE GENERICE

I. Noţiuni teoretice

În C++, există posibilitatea de a crea familii de funcţii sau de clase cu


ajutorul şabloanelor (template).
Şabloanele nu au facut parte dintre specificatiile originale ale limbajului
C++, ci au fost adăugate în 1990, fiind definite de ANSI C++. Definiţia unui
şablon de clasă nu este nici clasă, nici obiect. Şablonul unei clase este o descriere
a modului în care compilatorul va genera o nouă clasă, pornind de la tipurile date
ca parametru. În C++, o clasă este inutilă dacă nu se declară o instanţă (obiect) a
clasei respective. La fel, un şablon este inutil dacă nu se declară o instanţă (clasă)
a şablonului respectiv.
Un alt aspect legat de folosirea şabloanelor este legat de faptul ca ele pot fi
folosite numai cu tipuri care acceptă operaţiile necesare şablonului.

O funcţie generică defineşte un set general de operaţii care vor fi aplicate


unor tipuri de date variate; tipul de date asupra căruia va opera, va fi transmis ca
parametru:

template <class Tip>


tip_rezultat nume_functie (lista_parametri) {
//corp functie
}

Definiţia unei funcţii template este foarte asemănătoare cu cea a unei


funcţii obişnuite, cu excepţia faptului că argumentele funcţiei sunt numite într-un
mod simbolic. Exemplu:

template <class Tip>


void interschimb(Tip &a, Tip &b)
{
Tip aux = a;
a = b;
b = aux;
}
2 Funcții și clase generice
În acest exemplu este definită o funcţie template interschimb(), ce
acţionează asupra oricărui tip de obiecte, atât timp cât aceste obiecte pot fi
atribuite unul altuia şi pot fi iniţializate. Tipul general al argumentelor este numit
Tip, şi este specificat în prima linie a funcţiei. Codul din exemplul precedent
efectuează următoarele operaţii:
 iniţial se creează o variabilă de tip Tip (aux) şi este iniţializată cu
argumentul a.
 apoi se interschimbă variabilele a şi b, prin intermediul variabilei locale
aux.

Clasele parametrizate (sau clasele template) se declară după următoarea


sintaxă:

template <class Tip>


class nume_clasa {
// definiţie clasă
};

II. Aplicaţii rezolvate

Aplicaţia 1
Să se realizeze un program ce conţine definirea unei funcții generice de
ordonare pentru tipul de date T și definirea unei funcții generice care determină
valoarea cea mai mare pentru tipul de date B, precum şi a unei clase
corespunzătoare tipului de date Medicament. În fişierul principal se vor instanţia
m obiecte de tip Medicament și n obiecte de tip numere întregi. Clasa
Medicament va avea ca atribute: denumirea, cantitatea și prețul.
Pentru ordonarea elementelor se va utiliza metoda de sortare prin selecție
indirectă.

Programul corespunzător problemei este:

#include<iostream>
#include<string.h>
#include<stdlib.h>
using namespace std;

template <class T>


void Ordonare(T *a, int n)

{ int i,j;
T aux ;
for(i=0;i<n-1;i++)
Funcții și clase generice 3
for(j=i+1;j<n;j++)
if (a[i]>a[j])
{aux=a[i];
a[i]=a[j];
a[j]=aux;
}
}

template <class B>


B maxim(B *b, int n)
{B max;
max=b[0];
for(int i=1;i<n;i++) if(max<b[i]) max=b[i];
return max;
}
class Medicament {
char denumire[20];
int cantitate;
float pret;
public:
Medicament () {
strcpy(denumire,"");
cantitate=0;
pret=0;

}
Medicament(char *n,int c,float p)
{strcpy(denumire,n);
cantitate=c;
pret=p;
}
char *get_denumire() {
return denumire;
}
int get_cantitate() {
return cantitate;
}

float get_pret() {
return pret;
}
void set_denumire (char *n) {
strcpy(denumire,n);
}
void set_cantitate(int c) {
cantitate=c;
4 Funcții și clase generice
}
void set_pret(float p) {
pret=p;
}

//supraincarcarea operatorilor
void operator+=(int c);
void operator+=(Medicament &);
// supraincarcarea op prefixat de incrementare
int operator++();
// supraincarcarea op postfixat de incrementare
int operator++(int a);
void operator= (Medicament &s);
//supraincarcarea op postfixat de decrementare
friend int operator --(Medicament &s, int c);
//supraincarcarea op prefixat de decrementare
friend int operator --(Medicament &s);
friend void operator-=(Medicament &s,int c);
friend int operator>(Medicament s,Medicament p);
float operator<(Medicament s);
//functie procedurala pentru a cauta obiectele din
clasa Medicament care au cantitatea maxima
friend void cautareMax(Medicament* s, int n);
ostream& afisare(ostream& s);
istream& citire(istream& s);

};

void Medicament::operator+=(int c)
{ cantitate=cantitate+c;
}

void Medicament::operator+=(Medicament &s)


{ cantitate=cantitate+s.get_cantitate();
}

int Medicament ::operator++( )


{ cantitate=cantitate+1;
return cantitate; }

int Medicament ::operator++(int c )


{ c=cantitate;
set_cantitate(cantitate+1);
return c; }

void Medicament::operator=(Medicament &s)


Funcții și clase generice 5
{ strcpy(denumire,s.get_denumire());
cantitate=s.get_cantitate();
pret=s.get_pret();
}
int operator -- (Medicament &s, int a)
{ a=s.get_cantitate();
s.set_cantitate(a-1);
return a;
}

int operator --(Medicament &s)


{ s.set_cantitate(s.get_cantitate()-1);
return s.get_cantitate();
}

void operator-=(Medicament &s,int c)


{
s.set_cantitate(s.get_cantitate()-c);
}

int operator>(Medicament s, Medicament p)


{
if (strcmp(s.denumire,p.denumire)>0) return 1;
else return 0;
}

float Medicament::operator<(Medicament s)
{int i;
if (pret<s.pret) return 1;
else return 0;
}
istream& Medicament::citire(istream& s)
{cout<<"Dati denumirea medicamentului: ";
s>>denumire;
cout<<"Dati cantitatea medicamentului: ";
s>>cantitate;
cout<<"Dati pretul medicamentului: ";
s>>pret;
return s;
}
ostream& Medicament::afisare(ostream& s)
{ s<<denumire<<" "<<" cantitate "<<cantitate<<"
bucati, pret "<<pret<<" lei "<<endl;
return s;
}
6 Funcții și clase generice
//supraincărcarea operatorului de extragere
istream& operator>>(istream& s, Medicament& m)
{ return m.citire(s);
}
//supraincărcarea operatorului de inserare
ostream& operator<<(ostream& s, Medicament& m)
{ return m.afisare(s);
}

int *i_vect,m;
Medicament* m_vect;

void cautareMax( Medicament* s, int n)


{Medicament k=maxim(m_vect,m);
for (int
i=0;i<n;i++)if(k.get_pret()==s[i].get_pret())
cout<<*(s+i);
}
int main ( )
{ int n;
cout<<"Dati nr de elemente din vectorul cu numere
intregi: ";
cin>>n;
i_vect=new int[n];
for(int i=0;i<n;i++)
{
cout<<"Dati un element din vector: ";
cin>>i_vect[i];
}

cout<<"Dati nr de medicamente: ";


cin>>m;
m_vect= new Medicament[m];
for (int i=0;i<m;i++) cin>>*(m_vect+i);

cout<<"\nVectorul introdus este:\n";


for (int i=0; i<n; i++)
cout<<i_vect[i]<<'\t';
cout<<'\n';

Ordonare (i_vect,n);
cout<<"\nVectorul sortat crescator:\n";
for (int i=0;i<n;i++)
cout<<i_vect[i]<<'\t';
cout<<'\n';
Funcții și clase generice 7
cout<<"\nCea mai mare valoare :
"<<maxim(i_vect,n);
cout<<"\n---------------------------------------
-------------";

cout<<"\nLista cu medicamentele introduse este:\n";


for (int i=0;i<m;i++)
cout<<*(m_vect+i);

Ordonare (m_vect,m);
cout<<"\nLista sortata alfabetic:\n";
for (int i=0;i<m;i++)
cout<<*(m_vect+i);
Medicament med1=maxim(m_vect,m);
cout<<"\nPretul cel mai mare este :
"<<med1.get_pret()<<endl;

cout<<"\nMedicamentele cu pretul cel mai mare


sunt: "<<endl;
cautareMax(m_vect,m);

cout<<"\nSupraincarcarea operatorilor din


clasa Medicament: "<<endl;
m_vect[0]+=2;
cout<<"\tCantitatea modificata cu op+=2: "<<endl;
cout<<*m_vect;

m_vect[0]+= m_vect[1];
cout<<"\tCantitatea modificata cu +=m_vect[1]:
"<<endl;
cout<<*m_vect;
cout<<"\tCantitatea modificata cu 1 op postfixat
de incrementare: "<<endl;
m_vect[0]++;
cout<<*m_vect;
cout<<"\tCantitatea modificata cu 1 op prefixat de
incrementare: "<<endl;
++m_vect[0];
cout<<*m_vect;

m_vect[0]-=2;
cout<<"\tCantitatea modificata cu op op-=2:
"<<endl;
cout<<*m_vect;
--m_vect[0];
8 Funcții și clase generice
cout<<"\tObiectul obtinut in urma utilizarii op
prefixat de decrementare: "<<endl;
cout<<*m_vect;
m_vect[0]--;
cout<<"\tObiectul obtinut in urma utilizarii op
postfixat de decrementare: "<<endl;
cout<<*m_vect;
}

Programul afișează:
Funcții și clase generice 9
Aplicaţia 2
Să se realizeze un program ce conţine definirea unei clase generice pentru
tipul de date multime. În funcţia principală se vor instanţia două obiecte de tip
multime: mulţime de numere reale şi mulţime de caractere.

Programul corespunzător problemei este:


#include <iostream>
#include <conio.h>
using namespace std;
template <class T>
class multime {
private:
unsigned n;
T* a;
public:
multime(){n=0;}
multime(unsigned m,T* b);
multime(const multime<T> & A);
~multime(){ delete [] a;}
multime<T> operator+(multime<T>);
multime<T> operator*(multime<T>);
multime<T> operator-(multime<T>);
multime<T> operator=(multime<T>);
void ordonare();
void afisare();
int vida();
unsigned cardinal(){return n;}
int apartine(T b);
};
template <class T>
multime<T>::multime(unsigned m,T* b)
{
n=m;
a=new T[n];
for (int i=0;i<n;i++) *(a+i)=*(b+i);
}
template <class T>
multime<T>::multime(const multime<T>& A)
{ n=A.n;
a=new T[n];
for (int i=0;i<n;i++) *(a+i)=A.a[i];
}
template <class T>
multime<T> multime<T>::operator+(multime<T> A)
{ T* b;
10 Funcții și clase generice
b=new T[n+A.n];
unsigned m=n;
for (int i=0;i<n;i++) *(b+i)=*(a+i);
for (int j=0;j<A.n;j++)
{ int cod=0, i=0;
while ((i<m) && (!cod))
if (A.a[j]==*(b+i)) cod=1;
else i++;
if (!cod) { *(b+m)=A.a[j];
m++;
}
}
multime<T> r(m,b);
delete [] b;
return r;
}
template <class T>
multime<T> multime<T>::operator*(multime<T> A)
{ T* b;
unsigned m=n>A.n?A.n:n;
b=new T[m];
m=0;
int cod,j;
for (int i=0;i<n;i++)
{ cod=0;j=0;
while ((j<A.n) && (!cod))
if (*(a+i)==A.a[j]) cod=1;
else j++;
if (cod) { *(b+m)=*(a+i);
m++;
}
}
multime<T> C(m,b);
delete [] b;
return C;
}
template <class T>
multime<T> multime<T>::operator-(multime<T> A)
{ T* b;
unsigned m=n;
b=new T[m];
m=0;
int cod,j;
for (int i=0;i<n;i++)
{ cod=1;j=0;
while ((j<A.n) && (cod))
Funcții și clase generice 11
if (*(a+i)==A.a[j]) cod=0;
else j++;
if (cod) { *(b+m)=*(a+i);
m++;
}
}
multime<T> C(m,b);
delete [] b;
return C;
}
template <class T>
multime<T> multime<T>::operator=(multime<T> A)
{ if (this!=&A)
{ delete [] a;
n=A.n;
a=new T[n];
for (int i=0;i<n;i++) a[i]=A.a[i];
}
return *this;
}
template <class T>
void multime<T>::afisare()
{
cout.precision(2);
cout<<"={";
for (int i=0;i<n-1;i++) cout<<*(a+i)<<" ,";
cout<<a[n-1]<<"}\n";
}
template <class T>
int multime<T>::vida()
{ return n==0;
}
template <class T>
void multime<T>::ordonare()
{ int cod;
T aux;
do{ cod=1;
for (int i=0;i<n-1;i++)
if (*(a+i)>*(a+i+1))
{ cod=0;
aux=*(a+i);
*(a+i)=*(a+i+1);
*(a+i+1)=aux;
}
}
while (!cod);
12 Funcții și clase generice
}
template <class T>
int multime<T>::apartine(T b)
{ int k=0;
int i=0;
while (i<n && !k)
{ if (*(a+i)==b) k=1;
i++;}
return k;
}
int main()
{ cout<<"\n Multimi de numere reale\n\n";
float x[]={10,4,6,2,13,11,8};
multime<float> A(7,x);
float y[]={3,5,4,11,7};
multime<float> B(5,y);
cout<<"Multimea A";
A.ordonare();
A.afisare();
cout<<"Multimea B";
B.ordonare();
B.afisare();
cout<<"Reuniunea ";
multime<float> R=A+B;
R.ordonare();
R.afisare();
cout<<"Intersectia ";
multime<float> I=A*B;
I.ordonare();
I.afisare();
cout<<"Diferenta A-B ";
multime<float> D1=A-B;
D1.ordonare();
D1.afisare();
cout<<"Diferenta B-A ";
multime<float> D2=B-A;
D2.ordonare();
D2.afisare();
cout<<"Diferenta simetrica ";
multime<float> D=D1+D2;
D.ordonare();
D.afisare();
cout<<"Dati valoarea cautata: ";
float v;cin>>v;
if (A.apartine(v))
cout<<"\nValoarea data apartine multimii A";
Funcții și clase generice 13
else cout<<"\nValoarea data nu apartine multimii A";
if (B.apartine(v))
cout<<"\nValoarea data apartine multimii B";
else cout<<"\nValoarea data nu apartine multimii B";
getch();
cout<<"\n\n Multimi de caractere\n\n";
char c1[]={'a','c','e','r','3','5','+'};
multime<char> A1(7,c1);
char c2[]={'b','c','5','6','-'};
multime<char> B1(5,c2);
cout<<"Multimea A";
A1.ordonare();
A1.afisare();
cout<<"Multimea B";
B1.ordonare();
B1.afisare();
cout<<"Reuniunea ";
multime<char> R1=A1+B1;
R1.ordonare();
R1.afisare();
cout<<"Intersectia ";
multime<char> I1=A1*B1;
I1.ordonare();
I1.afisare();
cout<<"Diferenta A-B ";
multime<char> D3=A1-B1;
D3.ordonare();
D3.afisare();
cout<<"Diferenta B-A ";
multime<char> D4=B1-A1;
D4.ordonare();
D4.afisare();
cout<<"Diferenta simetrica ";
multime<char> D5=D3+D4;
D5.ordonare();
D5.afisare();
cout<<"Dati caracterul cautat: ";
char c;cin>>c;
if (A1.apartine(c))
cout<<"\nCaracterul dat apartine multimii A";
else cout<<"\nCaracterul dat nu apartine multimii
A";
if (B1.apartine(c))
cout<<"\nCaracterul dat apartine multimii B";
else cout<<"\nCaracterul dat nu apartine multimii B";
return 0;
14 Funcții și clase generice
}

Programul afişează:
Multimi de numere reale
Multimea A= { 2, 4, 6, 8, 10, 11, 13 }
Multimea B= { 3, 4, 5, 7, 11 }
Reuniunea = { 2, 3, 4, 5, 6, 7, 8, 10, 11, 13 }
Intersectia = { 4, 11 }
Diferenta A-B = { 2, 6, 8, 10, 13 }
Diferenta B-A = { 3, 5, 7 }
Diferenta simetrica = { 2, 3, 5, 6, 7, 8, 10, 13 }
Dati valoarea cautata: 8
Valoarea data apartine multimii A
Valoarea data nu apartine multimii B
Multimi de caractere
Multimea A= { +, 3, 5, a, c, e, r }
Multimea B= { -, 5, 6, b, c }
Reuniunea = { +, -, 3, 5, 6, a, b, c, e, r }
Intersectia = { 5, c }
Diferenta A-B = { +, 3, a, e, r }
Diferenta B-A = { -, 6, b }
Diferenta simetrica = { +, -, 3, 6, a, b, e, r }
Dati valoarea cautata: b
Caracterul dat nu apartine multimii A
Caracterul dat apartine multimii B

Aplicaţia 3
Să se realizeze un proiect ce conţine definirea unei clase generice pentru
tipul de date listă dublu înlănţuită, precum şi a două clase corespunzătoare
tipurilor de date raţional şi dreptunghi. În fişierul principal se vor instanţia două
obiecte de tip listă dublu înlănţuită: lista de numere raţionale şi lista de
dreptunghiuri.
Programul corespunzător problemei este:
Fişierul rational.h
#include <stdio.h>
#include <iostream>
#include <cmath>
using namespace std;
class rational {
private:
long numarator,numitor;
public:
// constructori
rational(){numitor=1;numarator=0;}
Funcții și clase generice 15
rational(long a,long b);
rational(rational& r);
// operatori aritmetici binari
rational operator+(rational& r);
rational operator-(rational& r);
rational operator*(rational& r);
rational operator/(rational& r);
// operatori de atribuire
rational operator=(rational& r);
rational operator+=(rational& r);
rational operator-=(rational& r);
rational operator*=(rational& r);
rational operator/=(rational& r);
// operatori de egalitate
int operator==(rational& r);
int operator!=(rational& r);
// operatori de comparare
int operator<=(rational& r);
int operator<(rational& r);
int operator>(rational& r);
int operator>=(rational& r);
// operatori unari
rational& operator++(); //prefixat
rational operator++(int); //postfixat
rational& operator--(); //prefixat
rational operator--(int); //postfixat
rational& operator-();
rational& operator+();
int operator!();
// conversie
double real()
{ return double(numarator)/numitor;}
// functii de acces
long Numarator(){return numarator;}
long Numitor(){return numitor;}
// functii modificator
void modific_numarator(long a);
void modific_numitor(long b);
ostream& afisare(ostream& );
istream& citire(istream& );
int subunitar();
int supraunitar();
private:
void semn();
void simplifica();
long cmmdc();
16 Funcții și clase generice
};
Fişierul rational.cpp
#include "rational.h"
// constructori
rational::rational(long a,long b)
{ numarator=a;
numitor=b;
semn();
simplifica();
}
rational::rational(rational& r)
{ numarator=r.numarator;
numitor=r.numitor;
}
// operatorii aritmetici binari
rational rational::operator+(rational& r)
{ rational s;
s.numarator=numarator*r.numitor+r.numarator*numitor;
s.numitor=numitor*r.numitor;
s.simplifica();
return s;
}
rational rational::operator-(rational& r)
{ rational d;
d.numarator=numarator*r.numitor-r.numarator*numitor;
d.numitor=numitor*r.numitor;
d.simplifica();
return d;
}
rational rational::operator*(rational& r)
{ rational p;
p.numarator=numarator*r.numarator;
p.numitor=numitor*r.numitor;
p.simplifica();
return p;
}
rational rational::operator/(rational& r)
{ rational i;
i.numarator=numarator*r.numitor;
i.numitor=numitor*r.numarator;
i.simplifica();
return i;
}
// operatorii de atribuire
rational rational::operator=(rational& r)
{ if (this!=&r) { numarator=r.numarator;
Funcții și clase generice 17
numitor=r.numitor;}
return *this;
}
rational rational::operator+=(rational& r)
{ numarator=numarator*r.numitor+r.numarator*numitor;
numitor=numitor*r.numitor;
simplifica();
return *this;
}
rational rational::operator-=(rational& r)
{ numarator=numarator*r.numitor-r.numarator*numitor;
numitor=numitor*r.numitor;
simplifica();
return *this;
}
rational rational::operator*=(rational& r)
{ numarator=numarator*r.numarator;
numitor=numitor*r.numitor;
simplifica();
return *this;
}
rational rational::operator/=(rational& r)
{ numarator=numarator*r.numitor;
numitor=numitor*r.numarator;
semn();
simplifica();
return *this;
}
// operatorii de egalitate
int rational::operator==(rational& r)
{ return numarator*r.numitor==numitor*r.numarator;
}
int rational::operator!=(rational& r)
{ return numarator*r.numitor!=numitor*r.numarator;
}
// operatorii de comparare
int rational::operator<=(rational& r)
{ return numarator*r.numitor<=numitor*r.numarator;
}
int rational::operator<(rational& r)
{ return numarator*r.numitor<numitor*r.numarator;
}
int rational::operator>(rational& r)
{ return numarator*r.numitor>numitor*r.numarator;
}
int rational::operator>=(rational& r)
18 Funcții și clase generice
{ return numarator*r.numitor>=numitor*r.numarator;
}
//operatori unari
rational& rational::operator++() //prefixat
{ numarator+=numitor;
return *this;
}
rational rational::operator++(int) //postfixat
{ rational tmp=*this;
numarator+=numitor;
return tmp;
}
rational& rational::operator--() //prefixat
{ numarator-=numitor;
return *this;
}
rational rational::operator--(int) //postfixat
{ rational tmp=*this;
numarator+=numitor;
return tmp;
}
rational& rational::operator-()
{ numarator=-numarator;
return *this;
}

rational& rational::operator+()
{ return *this;
}
int rational::operator!()
{ return !numarator;
}
// functii modificator
void rational::modific_numarator(long a)
{ numarator=a;
simplifica();
}
void rational::modific_numitor(long b)
{ numitor=b;
semn();
simplifica();
}
ostream& rational::afisare(ostream& s)
{ s<<numarator<<"/"<<numitor;
return s;
}
Funcții și clase generice 19
istream& rational::citire(istream& s)
{ cout<<"\nNumaratorul=";
s>>numarator;
cout<<"Numitor=";
s>>numitor;
semn();
simplifica();
return s;
}
int rational::subunitar()
{ return abs(numarator)<abs(numitor)?1:0;
}
int rational::supraunitar()
{ return abs(numarator)>abs(numitor)?1:0;
}
void rational::semn()
{ if (numitor<0)
{ numitor=-numitor ;
numarator=-numarator;
}
}
void rational::simplifica()
{ long d; d=1;
if (numarator!=0) d=cmmdc();
if (d!=1)
{ numarator/=d;
numitor/=d;
}
}
long rational::cmmdc()
{ long x,y,r;
x=abs(numarator);
y=abs(numitor);
if (y>x) { r=x;
x=y;
y=r;
}
do { r=x%y;
x=y;
y=r;
}
while (r!=0);
return x;
}
Fişierul drept.h
#include <iostream>
20 Funcții și clase generice
#include <stdio.h>
#include <cmath>
using namespace std;
class dreptunghi {
private:
float lungime,latime;
public:
//constructori
dreptunghi(float l1=0, float l2=0);
dreptunghi(dreptunghi& );
//supraincarcarea operatorilor
dreptunghi operator=(dreptunghi& );
int operator==(dreptunghi& );
int operator!=(dreptunghi& );
istream& citire(istream& );
ostream& afisare(ostream& );
float diagonala();
float aria();
};
Fişierul drept.cpp
#include "drept.h"
dreptunghi::dreptunghi(float l1, float l2)
{ lungime=l1;
latime=l2;
}
dreptunghi::dreptunghi(dreptunghi& d)
{ lungime=d.lungime;
latime=d.latime;
}
dreptunghi dreptunghi::operator=(dreptunghi& d)
{ if (this!=&d)
{ lungime=d.lungime;
latime=d.latime;
}
return *this;
}
int dreptunghi::operator==(dreptunghi& d)
{ return lungime==d.lungime && latime==d.latime;
}
int dreptunghi::operator!=(dreptunghi& d)
{ return !(*this==d);
}
istream& dreptunghi::citire(istream& s)
{ cout<<"\nLungime="; s>>lungime;
cout<<"Latime="; s>>latime;
return s;
Funcții și clase generice 21
}
ostream& dreptunghi::afisare(ostream& s)
{ s.precision(2);
s<<"\n"<<"Lungime="<<lungime<<" Latime="<<latime;
return s;
}
float dreptunghi::diagonala()
{ float d;
d=sqrt(lungime*lungime+latime*latime);
return d;
}
float dreptunghi::aria()
{ float a;
a=lungime*latime;
return a;
}
Fişierul lista.cpp
#include <iostream>
using namespace std;
template <class T> class lista;
template <class T>
class Nod
{ private:
T c;
Nod<T>* s;
Nod<T>* d;

public:
Nod(T b,Nod<T>* s1=NULL,Nod<T>* d1=NULL);
~Nod(){}
Nod<T> operator=(Nod<T> &n);
friend class lista<T>;
};
template <class T>
Nod<T>::Nod(T b, Nod<T> * s1, Nod<T> * d1)
{ c=b;
s=s1;
d=d1;
}
template <class T>
Nod<T> Nod<T>::operator =(Nod<T> &n)
{ if (this!=&n)
{ c=n.c;
s=n.s;
d=n.d;
22 Funcții și clase generice
}
return *this;
}
template <class T>
class lista {
private:
Nod<T>* p;
Nod<T>* u;
public:
lista(){p=NULL;u=NULL;}
int vida(){return p==NULL;}
void adaug_u(T a);
void adaug_p(T a);
void adaug_d(T a, T b);
void adaug_i(T a, T b);
void stergere();
T prim(){return p->c; }
void afisare_sd();
void afisare_ds();
};
template <class T>
void lista<T>::adaug_u(T a)
{
Nod<T>* q;
if (vida())
{ q=new Nod<T>(a,NULL,NULL);
p=q;
}
else { q=new Nod<T>(a,u,NULL);
u->d=q;
}
u=q;
}
template <class T>
void lista<T>::adaug_d(T a,T b)
{
Nod<T>* q;
Nod<T>* r=p;
while (r->c!=b) r=r->d;
if (r==u) { q=new Nod<T>(a,u,NULL);
u->d=q;
u=q;}
else { q=new Nod<T>(a,r,r->d);
r->d->s=q;
r->d=q; }
}
Funcții și clase generice 23
template <class T>
void lista<T>::adaug_i(T a,T b)
{
Nod<T>* q;
Nod<T>* r=p;
while (r->c!=b) r=r->d;
if (r==p) { q=new Nod<T>(a,NULL,p);
p->s=q;
p=q;}
else { q=new Nod<T>(a,r->s,r);
r->s->d=q;
r->s=q; }
}
template <class T>
void lista<T>::adaug_p(T a)
{
Nod<T>* q;
if (vida()) { q=new Nod<T>(a,NULL,NULL);
u=q;}
else { q=new Nod<T>(a,NULL,p);
p->s=q;
}
p=q;
}
template <class T>
void lista<T>::stergere()
{
Nod<T>* tmp;
tmp=p;
tmp->d->s=NULL;
p=p->d;
if (p==NULL) u=NULL;
delete tmp;
}
template <class T>
void lista<T>::afisare_sd()
{ Nod<T>* q=p;
if (p==NULL) cout<<"\nLista este vida";
else while (q!=NULL)
{ cout<<q->c<<" ";
q=q->d;
}
}
template <class T>
void lista<T>::afisare_ds()
{ Nod<T>* q=u;
24 Funcții și clase generice
if (p==NULL) cout<<"\nLista este vida";
else while (q!=NULL)
{ cout<<q->c<<" ";
q=q->s;
}
}
Fişierul main.cpp
#include "rational.h"
#include "drept.h"
#include "lista.cpp"
ostream& operator<<(ostream& s, rational& r)
{ return r.afisare(s);
}
istream& operator>>(istream& s, rational& r)
{ return r.citire(s);
}
ostream& operator<<(ostream& s, dreptunghi& d)
{ return d.afisare(s);
}
istream& operator>>(istream& s, dreptunghi& d)
{ return d.citire(s);
}
int main()
{ lista<rational> A;
rational p,q;
char c1;
cout<<"\nLista numerelor rationale\n";
do{
printf("\n\n p : Adaugare prim ");
printf("\n u : Adaugare ultim ");
printf("\n d : Adaugare dupa ");
printf("\n i : Adaugare inainte ");
printf("\n s : Stergere primul nod ");
printf("\n a : Afisare stanga-dreapta");
printf("\n l : Afisare dreapta-stanga");
printf("\n b : Distrugere lista");
printf("\n e : Iesire");
printf("\n Selectati optiunea dorita: ");
cin>>c1;
switch (c1) {
case 'p' : {
printf(" Dati informatia care se adauga ");
cin>>p;
A.adaug_p(p);
break;}
case 'u' : {
Funcții și clase generice 25
printf(" Dati informatia care se adauga ");
cin>>p;
A.adaug_u(p);
break;}
case 'd' : {
printf(" Dati informatia care se adauga ");
cin>>p;
printf(" Dati informatia dupa care se adauga
");
cin>>q;
A.adaug_d(p,q);
break;}
case 'i' : {
printf(" Dati informatia care se adauga ");
cin>>p;
printf(" Dati informatia inainte de care se
adauga ");
cin>>q;
A.adaug_i(p,q);
break;}
case 's' : { A.stergere();
break;}
case 'a' : {
printf("\nAfisare stanga-dreapta ");
A.afisare_sd();
break; }
case 'l' : {
printf("\nAfisare dreapta-stanga ");
A.afisare_ds();
break; }
case 'b' : {
while (!A.vida()) A.stergere();
break;}
}
} while (c1!='e');
lista<dreptunghi> B;
dreptunghi c,d;
cout<<"\nLista dreptunghiurilor\n";
do{
printf("\n\n p : Adaugare prim ");
printf("\n u : Adaugare ultim ");
printf("\n d : Adaugare dupa ");
printf("\n i : Adaugare inainte ");
printf("\n s : Stergere primul nod ");
printf("\n a : Afisare stanga-dreapta");
printf("\n l : Afisare dreapta-stanga");
26 Funcții și clase generice
printf("\n b : Distrugere lista");
printf("\n e : Iesire");
printf("\n Selectati optiunea dorita: ");
cin>>c1;
switch (c1) {
case 'p' : {
printf(" Dati informatia care se adauga ");
cin>>c;
B.adaug_p(c);
break;}
case 'u' : {
printf(" Dati informatia care se adauga ");
cin>>c;
B.adaug_u(c);
break;}
case 'd' : {
printf(" Dati informatia care se adauga ");
cin>>c;
printf(" Dati informatia dupa care se adauga
");
cin>>d;
B.adaug_d(c,d);
break;}
case 'i' : {
printf(" Dati informatia care se adauga ");
cin>>c;
printf(" Dati informatia inainte de care se
adauga ");
cin>>d;
B.adaug_i(c,d);
break;}
case 's' : {
B.stergere();
break;}
case 'a' : {
printf("\nAfisare stanga-dreapta ");
B.afisare_sd();
break; }
case 'l' : {
printf("\nAfisare dreapta-stanga ");
B.afisare_ds();
break; }
case 'b' : {
while (!B.vida()) B.stergere();
break;}
}
Funcții și clase generice 27
} while (c1!='e');
return 0;
}
Programul afişează:
Lista numerelor rationale
p : Adaugare prim
u : Adaugare ultim
d : Adaugare dupa
i : Adaugare inainte
s : Stergere primul nod
a : Afisare stanga-dreapta
l : Afisare dreapta-stanga
b : Distrugere lista
e : Iesire
Selectati optiunea dorita: p
Dati informatia care se adauga
Numaratorul=8
Numitorul=-4
p : Adaugare prim
u : Adaugare ultim
d : Adaugare dupa
i : Adaugare inainte
s : Stergere primul nod
a : Afisare stanga-dreapta
l : Afisare dreapta-stanga
b : Distrugere lista
e : Iesire
Selectati optiunea dorita: d
Dati informatia care se adauga
Numaratorul=3
Numitorul=9
Dati informatia dupa care se adauga
Numaratorul=-2
Numitorul=1
p : Adaugare prim
u : Adaugare ultim
d : Adaugare dupa
i : Adaugare inainte
s : Stergere primul nod
a : Afisare stanga-dreapta
l : Afisare dreapta-stanga
b : Distrugere lista
e : Iesire
Selectati optiunea dorita: a
28 Funcții și clase generice
Afisare stanga-dreapta -2/1 1/3
p : Adaugare prim
u : Adaugare ultim
d : Adaugare dupa
i : Adaugare inainte
s : Stergere primul nod
a : Afisare stanga-dreapta
l : Afisare dreapta-stanga
b : Distrugere lista
e : Iesire
Selectati optiunea dorita: e
Lista dreptunghiurilor
p : Adaugare prim
u : Adaugare ultim
d : Adaugare dupa
i : Adaugare inainte
s : Stergere primul nod
a : Afisare stanga-dreapta
l : Afisare dreapta-stanga
b : Distrugere lista
e : Iesire
Selectati optiunea dorita: u
Dati informatia care se adauga
Lungime=20
Latime=10
p : Adaugare prim
u : Adaugare ultim
d : Adaugare dupa
i : Adaugare inainte
s : Stergere primul nod
a : Afisare stanga-dreapta
l : Afisare dreapta-stanga
b : Distrugere lista
e : Iesire
Selectati optiunea dorita: i
Dati informatia care se adauga
Lungime=40
Latime=25
Dati informatia inainte de care se adauga
Lungime=20
Latime=10
p : Adaugare prim
u : Adaugare ultim
Funcții și clase generice 29
d : Adaugare dupa
i : Adaugare inainte
s : Stergere primul nod
a : Afisare stanga-dreapta
l : Afisare dreapta-stanga
b : Distrugere lista
e : Iesire
Selectati optiunea dorita: l
Afisare dreapta-stanga
Lungime=20 Latime=10
Lungime=40 Latime=25
p : Adaugare prim
u : Adaugare ultim
d : Adaugare dupa
i : Adaugare inainte
s : Stergere primul nod
a : Afisare stanga-dreapta
l : Afisare dreapta-stanga
b : Distrugere lista
e : Iesire
Selectati optiunea dorita: e
Analiza programului:
În fişierul header „rational.h” este declarată clasa rational. Declaraţia
acestei clase cuprinde două date membre, declarate private, şi 37 funcţii membre,
declarate publice. Implementarea clasei rational este realizată în fişierul
„rational.cpp” şi constă din definirea a 33 de funcţii membre. În acest fişier este
inclus fişierul în care este definită clasa rational. Clasa definită în aceste două
fişiere a fost prezentată în lucrarea de laborator nr. 6.
În fişierul header „drept.h” este declarată clasa dreptunghi. Declaraţia
acestei clase cuprinde două date membre, declarate private, şi nouă funcţii
membre, declarate publice. Implementarea clasei dreptunghi este realizată în
fişierul „drept.cpp” şi constă din definirea funcţiilor membre. În acest fişier este
inclus fişierul în care este definită clasa dreptunghi. Clasa definită în aceste două
fişiere a fost prezentată în lucrarea de laborator nr. 3.
În fişierul lista.cpp sunt definite clasele generice Nod şi lista. În nodurile
listei dublu înlănţuite implementate în acest fişier se vor putea memora date de
un anumit tip specificat în aplicaţia unde se va utiliza. Pentru definirea celor
două clase generice s-a utilizat implementarea claselor corespunzătoare din
lucrarea de laborator nr. 12.
Instanţierea obiectelor de tip listă de numere raţionale şi listă de
dreptunghiuri este realizată în funcţia principală din fişierul „main.cpp”. În acest
fişier se vor include fişierele header „rational.h” şi „drept.h”, precum şi fişierul
„lista.cpp”. Pentru rularea aplicaţiei se realizează un proiect în care se vor
30 Funcții și clase generice
include cele patru fişiere cu extensia cpp: rational.cpp, drept.cpp, lista.cpp şi
main.cpp.

III. Aplicaţii propuse

1. Să se realizeze un program ce conţine definirea unei funcții generice de


definirea unei funcții generice care determină valoarea cea mai mică
pentru tipul de date T, precum şi a unei clase corespunzătoare tipului de
date Electrocasnic. În fişierul principal se vor instanţia n obiecte de tip
Electrocasnic și m obiecte de tip numere reale. Clasa Electrocasnic va
avea ca atribute: producător, denumire și preț.
2. Să se realizeze un proiect ce conţine definirea unei clase generice pentru
tipul de date listă simplu înlănţuită, precum şi a două clase
corespunzătoare tipurilor de date triunghi şi ţară. În fişierul principal se
vor instanţia două obiecte de tip listă simplu înlănţuită: lista de
triunghiuri şi lista de ţări.
3. Să se realizeze un proiect ce conţine definirea unei clase generice pentru
tipul de date coadă, precum şi a două clase corespunzătoare tipurilor de
date prisma şi vector. În fişierul principal se vor instanţia două obiecte
de tip coadă: lista de prisme şi lista de vectori.
4. Să se scrie un program care permite crearea unei agende electronice cu
numere de telefon, implementată ca o listă de liste.
5. Scrieţi şi testaţi o funcţie având ca parametri două liste L1 şi L2, funcţie
care verifică dacă lista L1 este inversa listei l2.
6. Scrieţi şi testaţi o funcţie având ca parametru o listă care verifică dacă
lista este sortată.
7. Scrieţi şi testaţi o funcţie iterativă care primeşte ca parametru o listă de
numere şi calculează suma elementelor sale.
8. Să se implementeze clasa generică arbore binar şi să se testeze această
clasă prin instanţierea a cel puţin două obiecte ce memorează în noduri
date de tipuri diferite.

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