Sunteți pe pagina 1din 27

Manual de Informatic pentru licen iulie 2013

i februarie 2014

Specializarea Matematic-Informatic

Tematica general:
Algoritmic i programare.

1. Cutari (secvenial i binar), sortri (selecie, bubblesort, quicksort).


2. Metodele backtracking i divide et impera.
3. Algoritmi i specificri. Scrierea unui algoritm pornind de la o specificaie dat. Se d
un algoritm; se cere rezultatul execuiei lui.
4. Concepte OOP n limbaje de programare (C++, Java, C#): Clase i obiecte. Membrii
unei clase i specificatorii de acces. Constructori i destructori.

1
Cuprins

ALGORITMIC I PROGRAMARE..................................................................................3

1. CUTRI I SORTRI..................................................................................................... 3
1.1. CUTRI............................................................................................................................ 3
1.1.1. Cutare secvenial................................................................................................ 3
1.1.2. Cutare binar........................................................................................................4
1.2. SORTRI.............................................................................................................................5
1.2.1. Sortare prin selecie................................................................................................6
1.2.2. Bubble sort..............................................................................................................6
1.2.3. Quicksort.................................................................................................................7
2. METODELE BACKTRACKING I DIVIDE ET IMPERA.......................................... 8
2.1. METODA BACKTRACKING.......................................................................................................8
2.2. METODA "DIVIDE ET IMPERA"..............................................................................................12
3. ALGORITMI I SPECIFICRI......................................................................................13
3.1. SCRIEREA UNUI ALGORITM PORNIND DE LA O SPECIFICAIE DAT................................................13
4. CONCEPTE OOP N LIMBAJE DE PROGRAMARE................................................ 17
4.1. NOIUNEA DE CLAS.......................................................................................................... 17
4.1.1. Realizarea proteciei datelor prin metoda programrii modulare.......................17
4.1.2. Tipuri abstracte de date........................................................................................18
4.1.3. Declararea claselor.............................................................................................. 19
4.1.4. Membrii unei clase. Pointerul this........................................................................21
4.1.5. Constructorul........................................................................................................ 21
4.1.6. Destructorul.......................................................................................................... 25
5. PROBLEME PROPUSE................................................................................................... 26

6. BIBLIOGRAFIE GENERAL........................................................................................ 27

2
Algoritmic i programare

1. Cutri i sortri
1.1. Cutri

Datele se afl n memoria intern, ntr-un ir de articole. Vom cuta un articol dup un
cmp al acestuia pe care l vom considera cheie de cutare. n urma procesului de cutare va
rezulta poziia elementului cutat (dac acesta exist).
Notnd cu k1, k2, ...., kn cheile corespunztoare articolelor i cu a cheia pe care o cutm,
problema revine la a gsi (dac exist) poziia p cu proprietatea a = kp.
De obicei articolele sunt pstrate n ordinea cresctoare a cheilor, deci vom presupune c

k1 < k2 < .... < kn .

Uneori este util s aflm nu numai dac exist un articol cu cheia dorit ci i s gsim n caz
contrar locul n care ar trebui inserat un nou articol avnd cheia specificat, astfel nct s se
pstreze ordinea existent.
Deci problema cutrii are urmtoarea specificare:

Date a,n,(ki, i=1,n);


Precondiia: nN, n 1 i k1 < k2 < .... < kn ;
Rezultate p;
Postcondiia: (p=1 i a k1) sau (p=n+1 i a > kn) sau (1<p n) i (kp-1 < a kp).

1.1.1. Cutare secvenial

O prim metod este cutarea secvenial, n care sunt examinate succesiv toate cheile.
Sunt deosebite trei cazuri: ak1, a>kn, respectiv k1 < a kn, cutarea avnd loc n al treilea caz.

Subalgoritmul CautSecv(a, n, K, p) este: {nN, n 1 i k1 < k2 < .... < kn}


{Se caut p astfel ca: (p=1 i a k1) sau}
{ (p=n+1 i a>kn) sau (1<p n) i (kp-1 < a kp).
Fie p := 0; {Cazul "nc negasit"}
Dac a k1 atunci p := 1 altfel
Dac a > kn atunci p := n + 1 altfel
Pentru i := 2; n execut
Dac (p = 0) i (a ki) atunci p := i sfdac
sfpentru
sfdac

3
sfdac
sf-CautSecv

Se observ c prin aceast metod se vor executa n cel mai nefavorabil caz n-1
comparri, ntruct contorul i va lua toate valorile de la 2 la n. Cele n chei mpart axa real n
n+1 intervale. Tot attea comparri se vor efectua n n-1 din cele n+1 intervale n care se poate
afla cheia cutat, deci complexitatea medie are acelai ordin de mrime ca i complexitatea n
cel mai ru caz.
Evident c n multe situaii acest algoritm face calcule inutile. Atunci cnd a fost deja
gsit cheia dorit este inutil a parcurge ciclul pentru celelalte valori ale lui i. Cu alte cuvinte
este posibil s nlocuim ciclul PENTRU cu un ciclu CTTIMP. Ajungem la un al doilea
algoritm, dat n continuare.

Subalgoritmul CautSucc(a, n, K, p) este: {nN, n 1 i k1 < k2 < .... < kn}


{Se caut p astfel ca: p=1 i a k1) sau }
{(p=n+1 i a>kn) sau (1<p n) i (kp-1 < a kp).
Fie p:=1;
Dac a>k1 atunci
Cttimp p n i a>kp execut p:=p+1 sfct
sfdac
sf-CautSucc

n cel mai ru caz i acest algoritm face acelai numr de operaii ca i subalgoritmul
Cautsecv. n medie numrul operaiilor este jumtate din numrul mediu de operaii efecuat de
subalgoritmul Cautsecv deci complexitatea este aceeai.

1.1.2. Cutare binar

O alt metod, numit cutare binar, care este mult mai eficient, utilizeaz tehnica
"divide et impera" privitor la date. Se determin n ce relaie se afl cheia articolului aflat n
mijlocul coleciei cu cheia de cutare. n urma acestei verificri cutarea se continu doar ntr-o
jumtate a coleciei. n acest mod, prin njumtiri succesive se micoreaz volumul coleciei
rmase pentru cutare. Cutarea binar se poate realiza practic prin apelul funciei
BinarySearch(a, n, K, 1, n), descris mai jos, folosit n subalgoritmul dat n continuare.

Subalgoritmul CautBin(a, n, K, p) este: {nN, n 1 i k1 < k2 < .... < kn}


{Se caut p astfel ca: (p=1 i a k1) sau}
{(p=n+1 i a>kn) sau (1<p n) i (kp-1 < a kp)}
Dac a k1 atunci p := 1 altfel
Dac a > kn atunci p := n+1 altfel
P := BinarySearch(a, n, K, 1, n)
sfdac
sfdac
sf-CautBin

4
Funcia BinarySearch(a, n, K, St, Dr) este:
Dac St Dr - 1
atunci BinarySearch := Dr
altfel m := (St+Dr) Div 2;
Dac a km
atunci BinarySearch := BinarySearch(a, n, K, St, m)
altfel BinarySearch := BinarySearch(a, n, K, m, Dr)
sfdac
sfdac
sf-BinarySearch

n funcia BinarySearch descris mai sus, variabilele St i Dr reprezint capetele


intervalului de cutare, iar m reprezint mijlocul acestui interval. Prin aceast metod, ntr-o
colecie avnd n elemente, rezultatul cutrii se poate furniza dup cel mult log2n comparri.
Deci complexitatea n cel mai ru caz este direct proporional cu log2n. Fr a insista asupra
demonstraiei, menionm c ordinul de mrime al complexitii medii este acelai.
Se observ c funcia BinarySearch se apeleaz recursiv. Se poate nltura uor
recursivitatea, aa cum se poate vedea n urmtoarea funcie:

Funcia BinSeaNerec(a, n, K, St, Dr) este:


Cttimp Dr St > 1 execut
m := (St+Dr) Div 2;
Dac a km atunci Dr := m altfel St := m sfdac
sfct
BinSeaNerec := Dr
sf-BinSeaNerec

1.2. Sortri

Prin sortare intern vom nelege o rearanjare a unei colecii aflate n memoria intern
astfel nct cheile articolelor s fie ordonate cresctor (eventual descresctor).
Din punct de vedere al complexitii algoritmilor problema revine la ordonarea cheilor.
Deci specificarea problemei de sortare intern este urmtoarea:

Date n,K; {K=(k1,k2,...,kn)}


Precondiia: kiR, i=1,n
Rezultate K';
Postcondiia: K' este o permutare a lui K, dar ordonat cresctor.
Deci k1 k2 ... kn.

5
1.2.1. Sortare prin selecie

O prim tehnic numit "Selecie" se bazeaz pe urmtoarea idee: se determin poziia


elementului cu cheie de valoare minim (respectiv maxim), dup care acesta se va interschimba
cu primul element. Acest procedeu se repet pentru subcolecia rmas, pn cnd mai rmne
doar elementul maxim.

Subalgoritmul Selectie(n, K) este: {Se face o permutare a celor}


{n componente ale vectorului K astfel}
{ca k1 k2 .... kn }
Pentru i := 1; n-1 execut
Fie ind := i;
Pentru j := i + 1; n execut
Dac kj < kind atunci ind := j sfdac
sfpentru
Dac i < ind atunci t := ki; ki := kind; kind := t sfdac
sfpentru
sf-Selectie

Se observ c numrul de comparri este:


(n-1)+(n-2)+...+2+1=n(n-1)/2
indiferent de natura datelor. Deci complexitatea medie, dar i n cel mai ru caz este O(n2).

1.2.2. Bubble sort

Metoda "BubbleSort", compar dou cte dou elemente consecutive iar n cazul n care
acestea nu se afl n relaia dorit, ele vor fi interschimbate. Procesul de comparare se va ncheia
n momentul n care toate perechile de elemente consecutive sunt n relaia de ordine dorit.

Subalgoritmul BubbleSort(n, K) este:


Repet
Fie kod := 0; {Ipoteza "este ordine"}
Pentru i := 2; n execut
Dac ki-1 > ki atunci
t := ki-1;
ki-1 := ki;
ki := t;
kod := 1 {N-a fost ordine!}
sfdac
sfpentru
pncnd kod = 0 sfrep {Ordonare}
sf-BubbleSort

Acest algoritm execut n cel mai nefavorabil caz (n-1)+(n-2)+ ... +2+1 = n(n-1)/2
comparri, deci complexitatea lui este O(n2).
O variant optimizat a algoritmului "BubbleSort" este :

6
Subalgoritmul BubbleSort(n, K) este:
Fie s := 0
Repet
Fie kod := 0; {Ipoteza "este ordine"}
Pentru i := 2; n-s execut
Dac ki-1 > ki atunci
t := ki-1;
ki-1 := ki;
ki := t;
kod := 1 {N-a fost ordine!}
sfdac
sfpentru
s := s + 1
pncnd kod = 0 sfrep {Ordonare}
sf-BubbleSort

1.2.3. Quicksort

O metod mai performant de ordonare, care va fi prezentat n continuare, se numete


"QuickSort" i se bazeaz pe tehnica "divide et impera" dup cum se poate observa n
continuare. Metoda este prezentat sub forma unei proceduri care realizeaz ordonarea unui
subir precizat prin limita inferioar i limita superioar a indicilor acestuia. Apelul procedurii
pentru ordonarea ntregului ir este : QuickSort(n, K, 1, n), unde n reprezint numrul de
articole ale coleciei date. Deci

Subalgoritmul SortareRapid(n, K) este:


Cheam QuickSort(n, K, 1, n)
sf-SortareRapid

Procedura QuickSort(n, K, St, Dr) va realiza ordonarea subirului kSt, kSt+1, ...,
kDr. Acest subir va fi rearanjat astfel nct kSt s ocupe poziia lui final (cnd irul este
ordonat). Dac i este aceast poziie, irul va fi rearanjat astfel nct urmtoarea condiie s fie
ndeplinit:

kj ki kl , pentru st j < i < l dr (*)

Odat realizat acest lucru, n continuare va trebui doar s ordonm subirul kSt,
kSt+1, ... ,ki-1 prin apelul recursiv al procedurii QuickSort(n, K, St, i-1) i apoi
subirul ki+1, ...,kDr prin apelul QuickSort(n, K, i+1, Dr). Desigur ordonarea acestor
dou subiruri (prin apelul recursiv al procedurii) mai este necesar doar dac acestea conin cel
puin dou elemente.
Procedura QuickSort este prezentat n continuare :

7
Subalgoritmul QuickSort (n, K, St, Dr) este:
Fie i := St; j := Dr; a := ki;
Repet
Cttimp kj a i (i < j) execut j := j - 1 sfct
ki := kj;
Cttimp ki a i (i < j) execut i := i + 1 sfct
kj := ki ;
pncnd i = j sfrep
Fie ki := a;
Dac St < i-1 atunci Cheam QuickSort(n, K, St, i - 1) sfdac
Dac i+1 < Dr atunci Cheam QuickSort(n, K, i + 1, Dr) sfdac
sf-QuickSort

Complexitatea algoritmului prezentat este O(n2) n cel mai nefavorabil caz, dar
complexitatea medie este de ordinul O(nlog2n).

2. Metodele backtracking i divide et impera

2.1. Metoda backtracking

Metoda backtracking (cutare cu revenire) este aplicabil in general unor probleme ce au


mai multe soluii.
Vom considera nti un exemplu, dup care vom indica civa algoritmi generali pentru
aceast metod.

Problema 1. (Generarea permutrilor) Fie n un numr natural. Determinai permutrile


numerelor 1, 2, ..., n.
O soluie pentru generarea permutrilor, n cazul particular n = 3, ar putea fi:

Subalgoritmul Permutri1 este:


Pentru i1 := 1; 3 execut
Pentru i2 := 1; 3 execut
Pentru i3 := 1; 3 execut
Fie posibil := (i1, i2, i3)
Dac componentele vectorului posibil sunt distincte
atunci
Tiprete posibil
sfdac
sfpentru
sfpentru
sfpentru
sf-Permutri1

8
x1 1 2 3

x2 1 2 3 1 2 3 1 2 3

x3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3

Figura 1.1. Reprezentare grafic a produsului cartezian {1, 2, 3}3

Observaii privind subalgoritmul Permutri1:


Pentru n oarecare nu putem descrie un algoritm care s conin n cicluri n textul
surs.
Numrul total de vectori verificai este 33, iar n general nn. Vectorii posibil
verificai sunt reprezentai grafic n Figura 1.1 - fiecare vector este un drum de la
rdcin (de sus) spre frunze (baza arborelui).
Algoritmul atribuie valori tuturor componentelor vectorului x, apoi verific dac
vectorul este o permutare.

O mbuntire a acestor algoritmi ar consta n a verifica anumite condiii din problem n


timp ce se construiesc vectorii, evitnd completarea inutil a unor componente.
De exemplu, dac prima component a vectorului construit (posibil) este 1, atunci este
inutil s atribuim celei de a doua componente valoarea 1, iar componentei a treia oricare din
valorile 1, 2 sau 3. Dac n este mare se evit completarea multor vectori ce au prefixul (1, ...). n
acest sens, (1, 3, ...) este un vector promitor (pentru a fi o permutare), n schimb vectorul (1, 1,
...) nu este. Vectorul (1, 3, ...) satisface anumite condiii de continuare (pentru a ajunge la
soluie) - are componente distincte. Nodurile haurate din Figura 1.1 constituie valori care nu
conduc la o soluie.
Vom descrie un algoritm general pentru metoda Bactracking dup care vom particulariza
acest algoritm pentru problemele enunate la nceputul seciunii. Pentru nceput vom face cteva
observaii i notaii privind metoda Backtracking aplicat unei probleme n care soluiile se
reprezint pe vectori, nu neaprat de lungime fix:
spaiul de cutare a soluiilor (spaiul soluiilor posibile): S = S1 x S2 x ... x Sn;
posibil este vectorul pe care se reprezint soluiile;
posibil[1..k] S1 x S2 x ... x Sk este un vector care poate conduce sau nu la o soluie; k
reprezint indice pentru vectorul posibil, respectiv nivel n arborele care red grafic procesul
de cutare (Figura 1.2).
posibil[1..k] este promitor dac satisface condiii care pot conduce la o soluie;
soluie(n, k, posibil) funcie care verific dac vectorul (promitor) posibil[1..k] este soluie
a problemei.

9
Start

x1 1 x1 n
... ...

x2 1 ... n 1 ... x2 ... n 1 ... n

x3 1 ... n 1 ... n 1 ... n 1 . . . x3 . . . n 1 ... n 1 ... n 1 ... n

... ... ... ... ...


xk-1 1 ... xk-1 xk-1+1 ... n
Cautare fara succes:
xk 1 ... xk xk+1 ... i ... n revenire pe nivelul k-1

...
xk+1 Cautare pe nivel Cautare cu succes:
pas in fata 1 n
...
xn
Figura 1.2. Spaiul soluiilor posibile pentru generarea permutrilor

Procesul de cutare poate fi urmrit n algoritmul care urmeaz:

Algoritmul Backtracking este: {varianta nefinisat}


Fie k := 1
@Iniializeaz cutarea pe nivelul k (= 1)
Cttimp k > 0 execut {posibil[1..k-1] este promitor}
@Caut (secvenial) pe nivelul k o valoare v, pentru a completa n
continuare vectorul posibil[1..k-1] astfel nct posibil[1..k] s
fie promitor
Dac cutarea este cu succes
atunci Fie posibil[k] := v {posibil[1..k] este promitor}
Dac soluie(n, k, posibil)
atunci {o soluie! (rmnem pe nivelul k)}
Tiparete posibil[1..k]
altfel {e doar un vector promitor}
@Initializeaza cautarea pe nivelul k+1
Fie k := k + 1 {pas n fa (pe nivelul k+1)}
sfdac
altfel {pas n spate (revenire pe nivelul k-1)}
k := k - 1
sfdac
sfct
sf-Backtracking

Pentru a finisa acest algoritm trebuie s precizm elementele nestandard prezente. Astfel,
avem nevoie de funcia boolean
condiii-continuare(k, posibil, v)
funcie care verific dac vectorul promitor posibil[1..k-1] completat cu valoarea v conduce la
un vector promitor.
Apoi, pentru a iniializa cutarea la nivelul j avem nevoie de a alege un element fictiv din
mulimea Sj, activitate realizat de funcia

10
init(j)
care returneaz acest element fictiv, care are rolul de a indica faptul c din mulimea S nc nu s-
a ales nici un element, deci dup el urmeaz primul element propriu din aceast mulime. Pentru
a cuta o valoare pe nivelul j, n ipoteza c valoarea curent nu e bun, avem nevoie de funcia
boolean
urmtor(j, v, nou)
care este True dac poate alege o valoare din Sj care urmeaz dup valoarea v, valoare notat
prin nou i False n cazul n care nu mai exist alte valori n Sj, deci nu mai poate fi fcut
alegerea. Cu aceste notaii algoritmul devine:

Algoritmul Backtracking este: {versiune final}


Fie k := 1;
posibil[1] := init(1);
Cttimp k > 0 execut {posibil[1..k-1] este promitor}
Fie Gsit := false; v := posibil[k] ;
Cttimp Urmtor(k, v,urm) i not Gsit execut
Fie v := urm;
Dac condiii-continuare(k, posibil, v) atunci
Gsit := true
sfdac
sfct
Dac Gsit
atunci Fie posibil[k] := v; {posibil[1..k] este promitor}
Dac soluie(n, k, posibil)
atunci {o soluie! (rmnem pe nivelul k)}
Tiparete posibil[1..k]
altfel {e doar un vector promitor}
Fie k := k + 1; {pas n fa (pe nivelul k+1)}
posibil[k] := init(k)
sfdac
altfel {pas n spate (revenire pe nivelul k-1)}
k := k - 1;
sfdac
sfct
sf-Backtracking
Procesul de cutare a unei valori pe nivelul k i funciile condiii-continuare i soluie sunt
dependente de problema care se rezolv. De exemplu, pentru generarea permutrilor funciile
menionate sunt:

Funcia init(k) este:


Init := 0
sf-init;

Funcia Urmtor(k, v, urm) este:


Dac v < n
atunci Urmtor := True; urm := v + 1
altfel Urmtor := False
sfdac
sf-urmator

Funcia conditii-continuare(k, posibil, v) este:


Kod := True; i := 1;
Cttimp kod i (i < k) execut
Dac posibil[i] = v atunci kod := False sfdac
i := i + 1;

11
sfct
conditii-continuare:=kod
sf-conditii

Funcia soluii(n, k, posibil) este:


Soluii := (k = n)
sf-solutii

n ncheiere, menionm c explorarea backtracking poate fi descris de asemenea recursiv. Dm


n acest scop urmtoru subalgoritm:

Subalgoritmul Backtracking(k, posibil) este:


{posibil[1..k] este promitor}
Dac soluie(n, k, posibil) atunci
{o soluie! terminare apel recursiv, astfel}
Tipareste posibil[1..k]
{rmnem pe acelai nivel}
altfel
Pentru fiecare v valoare posibil pentru posibil[k+1] execut
Dac condiii-continuare(k + 1, posibil, v) atunci
posibil[k + 1] := v
Backtracking(k + 1, posibil)
{pas in fa}
sfdac
sfpentru
sfdac
{terminare apel Backtracking(k, posibil)}
sf-Backtracking {deci, pas n spate (revenire)}

cu apelul iniial Cheam Backtracking(0, posibil).

2.2. Metoda "divide et impera"

Strategia "Divide et Impera" n programare presupune mparirea datelor ("divide and


conquer") i mpartirea problemei n subprobleme ("top-down").
Metoda se aplica problemelor care pot fi descompuse n subprobleme independente,
similar problemei iniiale, de dimensiuni mai mici i care pot fi rezolvabile foarte uor. Ea se
aplic atunci cnd rezolvarea problemei P pentru setul de date D se poate face prin rezolvarea
aceleiai probleme P pentru alte seturi de date d1, d2, ..., dk de volum mai mic dect D.

Observaii:
o mprirea se face pn cnd se obine o problem rezolvabil imediat.
o Subproblemele n care se descompune problema iniial trebuie s fie
independente. Dac subproblemele nu sunt independente, se aplic alte
metode de rezolvare.
o Tehnica admite i o implementare recursiv.

12
Metoda poate fi descris n felul urmtor:
mparte: Dac dimensiunea datelor este prea mare pentru a fi rezolvabil imediat,
mparte problema n una sau mai multe subprobleme independente (similare
problemei iniiale).
Stpnete: Folosete recursive aceeai metod pentru a rezolva subproblemele.
Combin: Combin soluiile subproblemelor pentru a obine soluia problemei
iniiale.

Subalgoritmul S pentru rezolvarea problemei P folosind metoda Divide et Impera are


urmtoarea structur:

Sublalgoritmul S(D) este:


Dac dim(D) a atunci
@problema se rezolva
altfel
@ Descompune D in d1, d2,..., dk
Cheama S(d1)
Cheama S(d2)
.
.
Cheama S(dk)
@ construieste rezultatul final prin utilizarea rezultatelor
partiale din apelurile de mai sus
sfdac
sf-NumeAlg

3. Algoritmi i specificri
Algoritmi i specificri. Scrierea unui algoritm pornind de la o specificaie dat. Se d un
algoritm; se cere rezultatul execuiei lui

3.1. Scrierea unui algoritm pornind de la o specificaie dat

Problema 1

Scriei o funcie care satisface urmtoarea specificaie:

Date nr;
Precondiia: nr, nr1
Rezultate l1,l2,...,ln;
nr
Postcondiia: n *, li = nr 1 i n, li l j i j ,1 i, j n , n este
li
maximal

13
Problema 2

Scriei o funcie care satisface urmtoarea specificaie:

Date n,L=(l1,l2,...,ln);
Precondiia: liR, i=1,n
Rezultate R=(r1,r2,...,rn);
Postcondiia: R este o permutare a lui L, r1 r2 ... rn.

Problema 3

Se cere s se scrie un algoritm/program pentru rezolvarea urmtoarei probleme.

Cnd merge la cumprturi, Ana i pregtete tot timpul o list de cumprturi:


denumire, cantitate, raion (alimente, mbrcminte, nclminte, consumabile), pre estimat.
Se cere s se afieze lista de cumprturi a Anei ordonat alfabetic dup raion, lista ordonat
descresctor dup cantitate, precum i lista Anei de la un anumit raion. Se cere s se calculeze
i un pre estimativ al cheltuielilor Anei.

Problema 4

Se cere s se scrie un algoritm/program pentru rezolvarea urmtoarei probleme.

S se scrie un program care citete un ir de numere ntregi nenule. Introducerea unui


ir se ncheie odat cu citirea valorii 0. n irul citit programul va elimina secvenele de
elemente consecutive strict pozitive de lungime mai mare dect 3 (dac exist), dupa care va
tipri irul obinut.

Problema 5

Ce face urmtorul program Pascal?


Program Ce_rezolva___;

Function Prim(p:Integer):Boolean;
Var d:Integer;
Begin
d:=2;
While (d<=Sqrt(p)) And (p Mod d>0) Do Inc(d);
Prim:= d> Sqrt(p)
End;

Function Desc(n:Integer; Var p1,p2:Integer):Boolean;


Begin
p1:=2;
While (p1<=n Div 2) And (Not Prim(p1) Or Not Prim(n-p1)) Do Inc(p1);
Desc:= p1<=n Div 2;
p2:=n-p1
End;

Var n,p1,p2:Integer;

Begin

14
Repeat
Write(' Dati n : '); Readln(n);
If n>0 Then
If Desc(n,p1,p2) Then Writeln(n:5,p1:7,p2:5)
Else Writeln(' Nu ex. desc.');
Until n=0;
End.

Problema 6

Pentru urmtorul program Pascal precizai:

a) ce face acest program;


b) ce realizeaz fiecare subprogram;
c) ce rezultate sunt tiprite pentru 12 1233 1132 2338 8533 10000 21500 0 ?
Program Fis_Sir_P__;
Uses Crt;
Type Sir=Array [1..100] Of Integer;
MultimeC = Set Of 0..9;

Procedure C__S__(Var X:Sir; Var n:Byte);


Var v:Integer; f:Text;
Begin
Assign(f,'Sir.In'); Reset(f); n:=0;
Writeln(' Sir.In : ');
Repeat
Read (f,v);
If v>0 Then Begin Inc(n); x[n]:=v; Write(v,',') End
Until v=0;
Close(f); Writeln
End;

Procedure T__S__(X:Sir; n:Byte);


Var i:Byte; f:Text;
Begin
Assign(f,'Sir.Out'); Rewrite(f);
Writeln(' Sir.Out : ');
For i:=1 To n Do Begin
Write(f,x[i],' ');
Write( x[i],' ')
End;
Writeln(f);
Close(f); Writeln
End;

Procedure Mc(a:Integer; Var M:MultimeC);


Begin
M:=[];
Repeat
M:=M+[a Mod 10];
a:=a Div 10
Until a=0;
End;

Function Acc(a,b:Integer):Boolean;
Var Ma, Mb:MultimeC;
Begin
Mc(a,Ma);
Mc(b,Mb);

15
Acc:= Ma=Mb
End;

Procedure P__(Var p:Integer);


Var v:Integer;
Begin
v:=0;
Repeat
v:=v*10+p Mod 10;
p:=p Div 10
Until p=0;
p:=v
End;

Procedure M__S__(Var X:Sir; n:Byte);


Var i:Byte; v:Integer;
Begin
For i:=1 To n-1 Do
If Acc(x[i],x[i+1]) Then P__(x[i])
End;

Var X:Sir;
n:Byte;
Begin
ClrScr;
C__S__(X,n);
M__S__(X,n);
T__S__(X,n);
Readln
End.

Raspuns c) 12 3321 1132 2338 8533 10000 21500

Problema 7

Precizai ce realizeaz urmtorul program, apoi scriei programul Pascal pentru funcia
invers.
Program Str_Lit_Urm;
Uses Crt;

Function UrmL(l:Char):Char;
Begin
Case l Of
'Z': UrmL:='A';
'z': UrmL:='a';
Else UrmL:=Succ(l)
End
End;

Function ModC(c:Char):Char;
Begin
If UpCase(c) In ['A'..'Z'] Then ModC:=UrmL(c)
Else ModC:=c
End;

Function Modif(s:String):String;
Var i:Byte;

16
Begin
For i:=1 To Length(s) Do s[i]:=ModC(s[i]);
Modif:=s
End;

Var s:String;
Begin
ClrScr;
Writeln(' Dati randurile de codif.:');
Repeat
Readln(s);
Writeln(Modif(s))
Until s=''
End.

Obs. Presupunnd c acest program realizeaz o codificare a unui text, scriei programul care
realizeaz decodificarea!

4. Concepte OOP n limbaje de programare

4.1. Noiunea de clas

4.1.1. Realizarea proteciei datelor prin metoda programrii modulare

Dezvoltarea programelor prin programare procedural nseamn folosirea unor funcii i


proceduri pentru scrierea programelor. n limbajul C lor le corespund funciile care
returneaz o valoare sau nu. ns n cazul aplicaiilor mai mari ar fi de dorit s putem realiza
i o protecie corespunztoare a datelor. Acest lucru ar nsemna c numai o parte a funciilor
s aib acces la datele problemei, acelea care se refer la datele respective. Programarea
modular ofer o posibilitate de realizare a proteciei datelor prin folosirea clasei de memorie
static. Dac ntr-un fiier se declar o dat aparinnd clasei de memorie static n afara
funciilor, atunci ea poate fi folosit ncepnd cu locul declarrii pn la sfritul modulului
respectiv, dar nu i n afara lui.
S considerm urmtorul exemplu simplu referitor la prelucrarea vectorilor de numere
ntregi. S se scrie un modul referitor la prelucrarea unui vector cu elemente ntregi, cu
funcii corespunztoare pentru iniializarea vectorului, eliberarea zonei de memorie ocupate i
ridicarea la ptrat, respectiv afiarea elementelor vectorului. O posibilitate de implementare a
modulului este prezentat n fiierul vector1.cpp:

#include <iostream>

using namespace std;

static int* e; //elementele vectorului


static int d; //dimensiunea vectorului

void init(int* e1, int d1) //initializare


{

17
d = d1;
e = new int[d];
for(int i = 0; i < d; i++)
e[i] = e1[i];
}

void distr() //eliberarea zonei de memorie ocupata


{
delete [] e;
}

void lapatrat() //ridicare la patrat


{
for(int i = 0; i < d; i++)
e[i] *= e[i];
}

void afiseaza() //afisare


{
for(int i = 0; i < d; i++)
cout << e[i] << ' ';
cout << endl;
}

Modulul se compileaz separat obinnd un program obiect. Un exemplu de program


principal este prezentat n fiierul vector2.cpp:

extern void init( int*, int); //extern poate fi omis


extern void distr();
extern void lapatrat();
extern void afiseaza();
//extern int* e;
int main() {
int x[5] = {1, 2, 3, 4, 5};
init(x, 5);
lapatrat();
afiseaza();
distr();
int y[] = {1, 2, 3, 4, 5, 6};
init(y, 6);
//e[1]=10; eroare, datele sunt protejate
lapatrat();
afiseaza();
distr();
return 0;
}

Observm c dei n programul principal se lucreaz cu doi vectori nu putem s-i folosim
mpreun, deci de exemplu modulul vector1.cpp nu poate fi extins astfel nct s realizeze i
adunarea a doi vectori. n vederea nlturrii acestui neajuns s-au introdus tipurile abstracte
de date.

4.1.2. Tipuri abstracte de date

18
Tipurile abstracte de date realizeaz o legtur mai strns ntre datele problemei i operaiile
(funciile) care se refer la aceste date. Declararea unui tip abstract de date este asemntoare
cu declararea unei structuri, care n afar de date mai cuprinde i declararea sau definirea
funciilor referitoare la acestea.
De exemplu n cazul vectorilor cu elemente numere ntregi putem declara tipul abstract:

struct vect {
int* e;
int d;
void init(int* e1, int d1);
void distr() { delete [] e; }
void lapatrat();
void afiseaza();
};

Funciile declarate sau definite n interiorul structurii vor fi numite funcii membru iar datele
date membru. Dac o funcie membru este definit n interiorul structurii (ca i funcia distr
din exemplul de mai sus), atunci ea se consider funcie inline. Dac o funcie membru se
definete n afara structurii, atunci numele funciei se va nlocui cu numele tipului abstract
urmat de operatorul de rezoluie (::) i numele funciei membru. Astfel funciile init, lapatrat
i afiseaza vor fi definite n modul urmtor:

void vect::init(int *e1, int d1)


{
d = d1;
e = new int[d];
for(int i = 0; i < d; i++)
e[i] = e1[i];
}

void vect::lapatrat()
{
for(int i = 0; i < d; i++)
e[i] *= e[i];
}
void vect::afiseaza()
{
for(int i = 0; i < d; i++)
cout << e[i] << ' ';
cout << endl;
}

Dei prin metoda de mai sus s-a realizat o legtur ntre datele problemei i funciile
referitoare la aceste date, ele nu sunt protejate, deci pot fi accesate de orice funcie utilizator,
nu numai de funciile membru. Acest neajuns se poate nltura cu ajutorul claselor.

4.1.3. Declararea claselor

Un tip abstract de date clas se declar ca i o structur, dar cuvntul cheie struct se
nlocuiete cu class. Ca i n cazul structurilor referirea la tipul de dat clas se face cu
numele dup cuvntul cheie class (numele clasei). Protecia datelor se realizeaz cu

19
modificatorii de protecie: private, protected i public. Dup modificatorul de protecie se
pune caracterul :. Modificatorul private i protected reprezint date protejate, iar public date
neprotejate. Domeniul de valabilitate a modificatorilor de protecie este pn la urmtorul
modificator din interiorul clasei, modificatorul implicit fiind private. Menionm c i n
cazul structurilor putem s folosim modificatori de protecie, dar n acest caz modificatorul
implicit este public.
De exemplu clasa vector se poate declara n modul urmtor:

class vector {
int* e; //elementele vectorului
int d; //dimensiunea vectorului
public:
vector(int* e1, int d1);
~vector() { delete [] e; }
void lapatrat();
void afiseaza();
};

Se observ c datele membru e i d au fost declarate ca date de tip private (protejate), iar
funciile membru au fost declarate publice (neprotejate). Bineneles, o parte din datele
membru pot fi declarate publice, i unele funcii membru pot fi declarate protejate, dac
natura problemei cere acest lucru. n general, datele membru protejate pot fi accesate numai
de funciile membru ale clasei respective i eventual de alte funcii numite funcii prietene
(sau funcii friend).
O alt observaie important referitoare la exemplul de mai sus este c iniializarea datelor
membru i eliberarea zonei de memorie ocupat s-a fcut prin funcii membru specifice.
Datele declarate cu ajutorul tipului de dat clas se numesc obiectele clasei, sau simplu
obiecte. Ele se declar n mod obinuit n forma:

nume_clas list_de_obiecte;

De exemplu, un obiect de tip vector se declar n modul urmtor:

vector v;

Iniializarea obiectelor se face cu o funcie membru specific numit constructor. n cazul


distrugerii unui obiect se apeleaz automat o alt funcie membru specific numit destructor.
n cazul exemplului de mai sus

vector(int* e1, int d1);

este un constructor, iar

~vector() { delete [] e; }

este un destructor.
Tipurile abstracte de date de tip struct pot fi i ele considerate clase cu toate elementele
neprotejate. Constructorul de mai sus este declarat n interiorul clasei, dar nu este definit, iar
destructorul este definit n interiorul clasei. Rezult c destructorul este o funcie inline.

20
Definirea funciilor membru care sunt declarate, dar nu sunt definite n interiorul clasei se
face ca i n cazul tipurilor abstracte de date de tip struct, folosind operatorul de rezoluie.

4.1.4. Membrii unei clase. Pointerul this

Referirea la datele respectiv funciile membru ale claselor se face cu ajutorul operatorilor .
sau -> ca i n cazul referirii la elementele unei structuri. De exemplu, dac se declar:

vector v;
vector* p;

atunci afiarea vectorului v respectiv a vectorului referit de pointerul p se face prin:


v.afiseaza();
p->afiseaza();

n interiorul funciilor membru ns referirea la datele respectiv funciile membru ale clasei se
face simplu prin numele acestora fr a fi nevoie de operatorul punct ( . ) sau sgeat ( -> ).
De fapt compilatorul genereaz automat un pointer special, pointerul this, la fiecare apel de
funcie membru, i folosete acest pointer pentru identificarea datelor i funciilor membru.
Pointerul this va fi declarat automat ca pointer ctre obiectul curent. n cazul exemplului de
mai sus pointerul this este adresa vectorului v respectiv adresa referit de pointerul p.
Dac n interiorul corpului funciei membru afiseaza se utilizeaz de exemplu data membru d,
atunci ea este interpretat de ctre compilator ca i this->d.
Pointerul this poate fi folosit i n mod explicit de ctre programator, dac natura problemei
necesit acest lucru.

4.1.5. Constructorul

Iniializarea obiectelor se face cu o funcie membru specific numit constructor. Numele


constructorului trebuie s coincid cu numele clasei. O clas poate s aib mai muli
constructori. n acest caz aceste funcii membru au numele comun, ceea ce se poate face
datorit posibilitii de suprancrcare a funciilor. Bineneles, n acest caz numrul i/sau
tipul parametrilor formali trebuie s fie diferit, altfel compilatorul nu poate s aleag
constructorul corespunztor.
Constructorul nu returneaz o valoare. n acest caz nu este permis nici folosirea cuvntului
cheie void.
Prezentm n continuare un exemplu de tip clasa cu mai muli constructori, avnd ca date
membru numele i prenumele unei persoane, i cu o funcie membru pentru afiarea numelui
complet.
Fiierul persoana.h:

21
class persoana {
char* nume;
char* prenume;
public:
persoana(); //constructor implicit
persoana(char* n, char* p); //constructor
persoana(const persoana& p1); //constructor de copiere
~persoana(); //destructor
void afiseaza();
};

Fiierul persoana.cpp:

#include <iostream>
#include <cstring>
#include "persoana.h"

using namespace std;

persoana::persoana()
{
nume = new char[1];
*nume = 0;
prenume = new char[1];
*prenume = 0;
cout << "Apelarea constructorului implicit." << endl;
}

persoana::persoana(char* n, char* p)
{
nume = new char[strlen(n)+1];
prenume = new char[strlen(p)+1];
strcpy(nume, n);
strcpy(prenume, p);
cout << "Apelare constructor (nume, prenume).\n";
}

persoana::persoana(const persoana& p1)


{
nume = new char[strlen(p1.nume)+1];
strcpy(nume, p1.nume);
prenume = new char[strlen(p1.prenume)+1];
strcpy(prenume, p1.prenume);
cout << "Apelarea constructorului de copiere." << endl;
}

persoana::~persoana()
{
delete[] nume;
delete[] prenume;
}

void persoana::afiseaza()
{
cout << prenume << ' ' << nume << endl;
}

Fiierul persoanaTest.cpp:

22
#include "persoana.h"

int main() {
persoana A; //se apeleaza constructorul implicit
A.afiseaza();
persoana B("Stroustrup", "Bjarne");
B.afiseaza();
persoana *C = new persoana("Kernighan","Brian");
C->afiseaza();
delete C;
persoana D(B); //echivalent cu persoana D = B;
//se apeleaza constructorul de copire
D.afiseaza();
return 0;
}

Observm prezena a doi constructori specifici: constructorul implicit i constructorul de


copiere. Dac o clas are constructor fr parametri atunci el se va numi constructor implicit.
Constructorul de copiere se folosete la iniializarea obiectelor folosind un obiect de acelai
tip (n exemplul de mai sus o persoan cu numele i prenumele identic). Constructorul de
copiere se declar n general n forma:

nume_clas(const nume_clas& obiect);

Cuvntul cheie const exprim faptul c argumentul constructorului de copiere nu se modific.


O clas poate s conin ca date membru obiecte ale unei alte clase. Declarnd clasa sub
forma:

class nume_clasa {
nume_clasa_1 ob_1;
nume_clasa_2 ob_2;
...
nume_clasa_n ob_n;
...
};

antetul constructorului clasei nume_clasa va fi de forma:

nume_clasa(lista_de_argumente):
ob_1(l_arg_1), ob_2(l_arg_2), ..., ob_n(l_arg_n)

unde lista_de_argumente respectiv l_arg_i reprezint lista parametrilor formali ai


constructorului clasei nume_clasa respectiv ai obiectului ob_i.

Din lista ob_1(l_arg_1), ob_2(l_arg_2), ..., ob_n(l_arg_n) pot s lipseasc


obiectele care nu au constructori definii de programator, sau obiectul care se iniializeaz cu
un constructor implicit, sau cu toi parametrii implicii.

Dac clasa conine date membru de tip obiect atunci se vor apela mai nti constructorii
datelor membru, iar dup aceea corpul de instruciuni al constructorului clasei respective.

23
Fiierul pereche.cpp:

#include <iostream>
#include "persoana.h"

using namespace std;

class pereche {
persoana sot;
persoana sotie;
public:
pereche() //definitia constructorului implicit
{ //se vor apela constructorii impliciti
} //pentru obiectele sot si sotie
pereche(persoana& sotul, persoana& sotia);
pereche(char* nume_sot, char* prenume_sot,
char* nume_sotie, char* prenume_sotie):
sot(nume_sot, prenume_sot),
sotie(nume_sotie, prenume_sotie)
{
}
void afiseaza();
};

inline pereche::pereche(persoana& sotul, persoana& sotia):


sot(sotul), sotie(sotia)
{
}

void pereche::afiseaza()
{
cout << "Sot: ";
sot.afiseaza();
cout << "Sotie: ";
sotie.afiseaza();
}

int main() {
persoana A("Pop", "Ion");
persoana B("Popa", "Ioana");
pereche AB(A, B);
AB.afiseaza();
pereche CD("C","C","D","D");
CD.afiseaza();
pereche EF;
EF.afiseaza();
return 0;
}

Observm c n cazul celui de al doilea constructor, parametrii formali sot i sotie au fost
declarai ca i referine la tipul persoana. Dac ar fi fost declarai ca parametri formali de tip
persoana, atunci n cazul declaraiei:

pereche AB(A, B);

constructorul de copiere s-ar fi apelat de patru ori. n astfel de situaii se creeaz mai nti
obiecte temporale folosind constructorul de copiere (dou apeluri n cazul de fa), dup care
se execut constructorii datelor membru de tip obiect (nc dou apeluri).

24
4.1.6. Destructorul

Destructorul este funcia membru care se apeleaz n cazul distrugerii obiectului. Destructorul
obiectelor globale se apeleaz automat la sfritul funciei main ca parte a funciei exit. Deci,
nu este indicat folosirea funciei exit ntr-un destructor, pentru c acest lucru duce la un ciclu
infinit. Destructorul obiectelor locale se execut automat la terminarea blocului n care s-au
definit. n cazul obiectelor alocate dinamic, de obicei destructorul se apeleaz indirect prin
operatorul delete (obiectul trebuie s fi fost creat cu operatorul new). Exist i un mod
explicit de apelare a destructorului, n acest caz numele destructorului trebuie precedat de
numele clasei i operatorul de rezoluie.
Numele destructorului ncepe cu caracterul ~ dup care urmeaz numele clasei. Ca i n cazul
constructorului, destructorul nu returneaz o valoare i nu este permis nici folosirea
cuvntului cheie void. Apelarea destructorului n diferite situaii este ilustrat de urmtorul
exemplu. Fiierul destruct.cpp:

#include <iostream>
#include <cstring>

using namespace std;

class scrie { //scrie pe stdout ce face.


char* nume;
public:
scrie(char* n);
~scrie();
};

scrie::scrie(char* n)
{
nume = new char[strlen(n)+1];
strcpy(nume, n);
cout << "Am creat obiectul: " << nume << '\n';
}

scrie::~scrie()
{
cout << "Am distrus obiectul: " << nume << '\n';
delete nume;
}

void functie()
{
cout << "Apelare functie" << '\n';
scrie local("Local");
}

scrie global("Global");

int main() {
scrie* dinamic = new scrie("Dinamic");
functie();
cout << "Se continua programul principal" << '\n';
delete dinamic;

25
return 0;
}

5. Probleme propuse
1. Scriei un program ntr-unul din limbajele de programare C++, Java, C# care:
a. Definete o clas Student avnd:
un atribut nume de tip ir de caractere;
un atribut note coninnd un ir de note (numere ntregi),
constructori, accesori i o metod care calculeaz media notelor studentului.
b. Definete o funcie care primind un obiect de tip Student returneaz adevrat dac
toate notele elevului sunt >4.
c. Scriei specificaiile metodelor definite n clasa Student precum i a funciei de la
punctul b.

2. Scriei un program ntr-unul din limbajele de programare C++, Java, C# care:


a. Definete o clas Student avnd:
un atribut nume de tip ir de caractere;
un atribut note coninnd un ir de note (numere ntregi),
constructori, accesori i o metod care calculeaz media notelor studentului.
b. Definete un subprogram care primind un obiect de tip Student tiparete numele
studentului i notele acestuia n ordine descresctoare.
c. Scriei specificaiile metodelor definite n clasa Student precum i a
subprogramului de la punctul b.

26
6. Bibliografie general

1. Alexandrescu, Programarea modern in C++. Programare generic si modele de


proiectare aplicate, Editura Teora, 2002.
2. Angster Erzsbet: Objektumorientlt tervezs s programozs Java, 4KR Bt,
2003.
3. Bjarne Stroustrup: A C++ programozsi nyelv, Kiskapu kiad, Budapest, 2001.
4. Bjarne Stroustrup: The C++ Programming Language Special Edition, AT&T, 2000.
5. Boian F.M. Frentiu M., Lazr I. Tambulea L. Informatica de baz. Presa
Universitar Clujeana, Cluj, 2005
6. Bradley L. Jones: C# mesteri szinten 21 nap alatt, Kiskapu kiad, Budapest, 2004.
7. Bradley L. Jones: SAMS Teach Yourself the C# Language in 21 Days, Pearson
Education,2004.
8. Cormen, T., Leiserson, C., Rivest, R., Introducere n algoritmi, Editura Computer
Libris Agora, Cluj, 2000
9. Eckel B., Thinking in C++, vol I-II, http://www.mindview.net
10. Ellis M.A., Stroustrup B., The annotated C++ Reference Manual, Addison-Wesley,
1995
11. Frentiu M., Lazr I. Bazele programrii. Partea I-a: Proiectarea algoritmilor
12. Herbert Schildt: Java. The Complete Reference, Eighth Edition, McGraw-Hill, 2011.
13. Robert Sedgewick: Algorithms, Addison-Wesley, 1984
14. Simon Kroly, Kenyernk Java. A Java programozs alapjai, Presa Universitar
Clujean, 2010.

27

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