Sunteți pe pagina 1din 79

1

Manual de Informatic pentru licen 2012,



Specializarea Matematic-Informatic

Tematica general:

Partea 1.Algoritmi i specificri. Clase de algoritmi.

a. Cautari (secventiala si binara), sortari (selectie, bubblesort, quicksort), metodele
backtracking si divide et impera. (Sect. 1.1)
b. Algoritmi i specificri. Scrierea unui algoritm pornind de la o specificatie data. Se da
un algoritm; se cere rezultatul executiei lui. (Sect. 1.2)

Partea 2. Programare orientat pe obiecte

a. Concepte OOP n limbaje de programare (C++, Java, C#): Clase i obiecte, Membrii
unei clase i specificatorii de acces, Constructori i destructori, Clase derivate i
relaia de motenire, Suprascrierea metodelor, Polimorfism, Legare dinamica (Sect.
2.1)

Partea 3. Structuri de date

a. Cozi, Stive. Specificarea operaiilor caracteristice (fr implementri) (Sect. 3.1).
b. Identificarea structurilor i tipurilor de date potrivite pentru rezolvarea problemelor
(doar dintre cele de la punctul a.) (Sect. 3.2)

Partea 4. Baze de date

a. Baze de date relaionale. Primele trei forme normale ale unei relaii(Sect. 4.1)
b. Interogarea bazelor de date relaionale cu SQL (Select) (Sect. 4.2)

Partea 5. Sisteme de operare

a. Structura i funciile sistemelor de operare(Sect. 5.1)
b. Interpretoare ale fiierelor de comenzi, cu exemplificare sh (Unix) (Sect. 5.2)

2

Cuprins:

1. ALGORITMI I SPECIFICRI. CLASE DE ALGORITMI .................................... 4
1.1. CLASE DE ALGORITMI I METODE DE REZOLVARE ....................................................... 4
1.1.1. Cutri ............................................................................................................... 4
1.1.1.1. Cutare secvenial ........................................................................................ 4
1.1.1.2. Cutare binar ................................................................................................ 5
1.1.2. Sortri ................................................................................................................ 6
1.1.2.1. Sortare prin selecie........................................................................................ 7
1.1.2.2. Bubble sort ..................................................................................................... 7
1.2. ALGORITMI I SPECIFICRI .......................................................................................... 9
1.2.1. Scrierea unui algoritm pornind de la o specificaie dat .................................. 9
1.2.2. Ce face? ........................................................................................................... 11
2. PROGRAMAREA ORIENTAT PE OBIECTE ...................................................... 15
2.1. CONCEPTE OOP N LIMBAJE DE PROGRAMARE .......................................................... 15
2.1.1. Noiunea de clas ............................................................................................. 15
2.1.1.1. Realizarea proteciei datelor prin metoda programrii modulare ................ 15
2.1.1.2. Tipuri abstracte de date ................................................................................ 16
2.1.1.3. Declararea claselor ....................................................................................... 17
2.1.1.4. Membrii unei clase. Pointerul this ............................................................... 18
2.1.1.5. Constructorul................................................................................................ 19
2.1.1.6. Destructorul.................................................................................................. 22
2.1.2. Metoda programrii orientate obiect .............................................................. 23
2.1.2.1. Bazele teoretice ............................................................................................ 24
2.1.2.2. Declararea claselor derivate ......................................................................... 24
2.1.2.3. Funcii virtuale ............................................................................................. 25
3. STRUCTURI DE DATE ............................................................................................... 31
3.1. COZI, STIVE ............................................................................................................... 31
3.1.1. Stiva.................................................................................................................. 31
3.1.2. Coada ............................................................................................................... 32
3.2. IDENTIFICAREA STRUCTURILOR DE DATE POTRIVITE N APLICAII ............................. 35
4. BAZE DE DATE ............................................................................................................ 38
4.1. BAZE DE DATE RELAIONALE .................................................................................... 38
4.1.1. Modelul relaional ........................................................................................... 38
4.1.2. Primele trei forme normale ale unei relai ..................................................... 40
4.2. INTEROGAREA BD RELAIONALE CU SQL ................................................................ 49
5. SISTEME DE OPERARE ............................................................................................. 55
5.1. STRUCTURA I FUNCIILE SO .................................................................................... 55
5.1.1. Strile unui proces i principalele funcii ale SO ............................................ 55
5.1.2. Structura general a unui SO ............................................................................ 57
5.1.2.1. Structura unui SO ......................................................................................... 57
5.1.2.2. Partea de control .......................................................................................... 58
5.1.2.3. Partea de servicii .......................................................................................... 59
5.2. INTERPRETOARE ALE FIIERELOR DE COMENZI .......................................................... 63
3
5.2.1. Funcionarea unui interpretor de comenzi shell .............................................. 63
5.2.2. Programarea n shell ....................................................................................... 64
5.2.2.1. Scurt prezentare a limbajului sh ................................................................. 64
5.2.2.2. Variabile sh i mecanisme de substituie ..................................................... 66
5.2.2.3. Structura de control if din sh ........................................................................ 70
5.2.2.4. Structuri de control repetitive sh .................................................................. 71
5.2.2.5. Exemplul 1: o aplicaie de supraveghere ..................................................... 73
5.2.2.6. Exemplul 2: utilizri break i continue ........................................................ 75
5.2.2.7. Exemplul 3: reunirea fiierelor tipribile ntr-unul singur ........................... 75
6. BIBLIOGRAFIE GENERAL .................................................................................... 78

4

1. Algoritmi i specificri. Clase de algoritmi

1.1. Clase de algoritmi i metode de rezolvare

1.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 k
1
, k
2
, ...., k
n
cheile corespunztoare articolelor i cu a cheia pe care o cutm,
problema revine la a gsi (dac exist) poziia p cu proprietatea a = k
p
.
De obicei articolele sunt pstrate n ordinea cresctoare a cheilor, deci vom presupune c

k
1
< k
2
< .... < k
n
.

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,(k
i
, i=1,n);
Precondiia: neN, n>1 i k
1
< k
2
< .... < k
n
;
Rezultate p;
Postcondiia: (p=1 i a s k
1
) sau (p=n+1 i a > k
n
) sau (1<psn) i (k
p-1
< a s k
p
).

1.1.1.1. Cutare secvenial

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

Subalgoritmul CautSecv(a, n, K, p) este: {neN, n>1 i k
1
< k
2
< .... < k
n
}
{Se caut p astfel ca: (p=1 i a s k
1
) sau}
{ (p=n+1 i a>k
n
) sau (1<psn) i (k
p-1
< a s k
p
).
Fie p := 0; {Cazul "nc negasit"}
Dac a s k
1
atunci p := 1 altfel
Dac a > k
n
atunci p := n + 1 altfel
Pentru i := 2; n execut
Dac (p = 0) i (a s k
i
) atunci p := i sfdac
5
sfpentru
sfdac
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: {neN, n>1 i k
1
< k
2
< .... < k
n
}
{Se caut p astfel ca: p=1 i a s k
1
) sau }
{(p=n+1 i a>k
n
) sau (1<psn) i (k
p-1
< a s k
p
).
Fie p:=1;
Dac a>k
1
atunci
Cttimp psn i a>k
p
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.
Menionm, c acest tip de cutare se poate aplica i n cazul n care cheile nu sunt n
ordine cresctoare.

1.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: {neN, n>1 i k
1
< k
2
< .... < k
n
}
{Se caut p astfel ca: (p=1 i a s k
1
) sau}
{(p=n+1 i a>k
n
) sau (1<psn) i (k
p-1
< a s k
p
)}
Dac a s k
1
atunci p := 1 altfel
Dac a > k
n
atunci p := n+1 altfel
P := BinarySearch(a, n, K, 1, n)
6
sfdac
sfdac
sf-CautBin


Funcia BinarySearch(a, n, K, St, Dr) este:
Dac St > Dr - 1
atunci BinarySearch := Dr
altfel m := (St+Dr) Div 2;
Dac a s k
m

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 log
2
n comparri.
Deci complexitatea n cel mai ru caz este direct proporional cu log
2
n. 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 s k
m
atunci Dr := m altfel St := m sfdac
sfct
BinSeaNerec := Dr
sf-BinSeaNerec

1.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=(k
1
,k
2
,...,k
n
)}
Precondiia: k
i
eR, i=1,n
Rezultate K';
Postcondiia: K' este o permutare a lui K, dar ordonat cresctor.
Deci k
1
s k
2
s ... s k
n
.

7
1.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 k
1
s k
2
s .... s k
n
}
Pentru i := 1; n-1 execut
Fie ind := i;
Pentru j := i + 1; n execut
Dac k
j
< k
ind
atunci ind := j sfdac
sfpentru
Dac i < ind atunci t := k
i
; k
i
:= k
ind
; k
ind
:= 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(n
2
).

1.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 k
i-1
> k
i
atunci
t := k
i-1
;
k
i-1
:= k
i
;
k
i
:= 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(n
2
).
O variant optimizat a algoritmului "BubbleSort" este :
Subalgoritmul BubbleSort(n, K) este:
Fie s := 0
8
Repet
Fie kod := 0; {Ipoteza "este ordine"}
Pentru i := 2; n-s execut
Dac k
i-1
> k
i
atunci
t := k
i-1
;
k
i-1
:= k
i
;
k
i
:= t;
kod := 1 {N-a fost ordine!}
sfdac
sfpentru
s := s + 1
pncnd kod = 0 sfrep {Ordonare}
sf-BubbleSort

9

1.2. Algoritmi i specificri

1.2.1. Scrierea unui algoritm pornind de la o specificaie dat

Problema 1

Scriei o funcie care satisface urmtoarea specificaie:

Date nr;
Precondiia: nreN, nr1
Rezultate l
1
,l
2
,...,l
n
;
Postcondiia: neN
*
, n j i j i l l n i nr l
l
nr
j i i
i
s s = = s s =
(

, 1 , , 1 , n este
maximal

Problema 2

Scriei o funcie care satisface urmtoarea specificaie:

Date n,L=(l
1
,l
2
,...,l
n
);
Precondiia: l
i
eR, i=1,n
Rezultate R=(r
1
,r
2
,...,r
n
);
Postcondiia: R este o permutare a lui L, r
1
> r
2
> ... > r
n
.

Problema 3

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

La un concurs pe facultate particip mai multe grupe. Pentru fiecare grup se cunosc (se dau)
rezultatele (notele) studenilor la mai multe discipline. Ctig grupa cu cea mai mare medie
de concurs. Media de concurs este (se calculeaz ca) media aritmetic a notelor rmase dup
eliminarea rezultatelor unui student i a rezultatelor la o disciplin. Studentul i disciplina se
vor alege de ctre eful de grup astfel nct media de concurs s fie maxim.

10




Reformulare: Ce linie i ce coloan se pot tia dintr-o matrice
data,
astfel nct suma elementelor rmase s fie maxim?
O Ob bs s. .: :

Contraexemplu:
2 6 6 5 1 19 9 1 17 7
5 5 1 3 1 14 4 9 9
4 9 7 8 2 28 8 2 24 4
2 2 6 2 1 12 2 - -- -> > - -- -
1 11 1 2 20 0 1 14 4 1 16 6 m mi in n
l lc c
m ma ax x= =5 50 0! !
|
Suma max.= 50!
0 6 6 5
0 5 1 3
0 9 7 8
0 0 0 0
E Ex xe em mp pl lu u:
2 6 6 5
5 5 1 3
4 9 7 8
2 2 6 2
O O s so ol lu u i ie e (2,1):
Suma Max.= 51
0 6 6 5
0 0 0 0
0 9 7 8
0 2 6 2
Matricea A:
7 5 5 8
9 1 1 4
4 5 2 1
1 3 7 1
Suma Max.= 44
7 5 0 8
9 1 0 4
4 5 0 1
0 0 0 0
Suma max.= 43
7 0 5 8
9 0 1 4
0 0 0 0
1 0 7 1
17%
83%
Prin eliminarea studentului cu
medie minim i a disciplinei cu
medie minim nu se obine rezultatul
optim ntotdeauna!
int Pm(int* X, int n)
{
int m=1;
for (int i=2; i<=n; i++) if (X[i]<X[m]) m=i;
return m;
}
int Alb (Mat a, Mat b, int n)
{
int s,sij, sm=0,im=0,jm=0; int X[10],Y[10];
s=Sum(a,n); SumCol(a,n,X); SumLin(a,n,Y);
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++) {
sij=s-Y[i]-X[j]+a[i][j];
if (sij>sm) { sm=sij; im=i; jm=j; }
}
Mut(a,b,n);
Lin(b,n,im);Col(b,n,jm);
return sm;
}
int L_c (Mat a, Mat c, int n)
{
int im, jm, Sl[10], Sc[10];
Mut(a,c,n);
SumLin(c,n,Sl); Lin(c,n,Pm(Sl,n));
SumCol(c,n,Sc); Col(c,n,Pm(Sc,n));
return Sum(c,n);
}
void main ()
{ clrscr(); randomize();
Mat a,b,c; int n,Sa,Sb, Nt=10000, Ce=0;
for (int t=1; t<=Nt; t++) {
Gen(a,n);
Sa=Alb(a,b,n);
Sb=L_c(a,c,n);
if (Sa!=Sb) { Ce++;
g << endl <<" Matricea A:"<< endl; Tipf(a,n);
g << " Suma Max.= "<<Sa<<endl; Tipf(b,n);
g << " Suma max.= "<<Sb<<endl; Tipf(c,n);
}
}
if (!Ce) cout << " Ok dupa " << Nt << " teste." << endl;
else cout << " See ContraEx.Txt "<<Ce<<" din "<<Nt<<endl;
g.close();
getche();
}
void SumLin(Mat a, int n, int* Y)
{
for (int i=1; i<=n; i++) {
Y[i]=0;
for (int j=1; j<=n; j++) Y[i]+=a[i][j];
}}
void SumCol(Mat a, int n, int* X)
{
for (int j=1; j<=n; j++) {
X[j]=0;
for (int i=1; i<=n; i++) X[j]+=a[i][j];
}}
void Lin(Mat a, int n, int i)
{
for (int j=1; j<=n; j++)
a[i][j]=0;
}
void Col(Mat a, int n, int j)
{
for (int i=1; i<=n; i++)
a[i][j]=0;
}
void Mut(Mat a, Mat b, int n)
{
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++) b[i][j]=a[i][j];
}
int Sum(Mat a, int n)
{
int s=0;
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++) s+=a[i][j];
return s;
}
typedef int Mat[10][10];
void Gen(Mat a, int& n)
{
n=random(4)+4;
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
a[i][j]=random(9)+1;
}
ofstream g("ContraEx.Txt");
void Tipf(Mat a, int n)
{
for (int i=1; i<=n; i++) { g << endl;
for (int j=1; j<=n; j++)
g << setw(3)<<setfill('
')<<a[i][j];
} g << endl << endl;
}
S St tu ud di iu u: :

11
Problema 4

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 5

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.

1.2.2. Ce face?

Problema 6

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
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.

12
Problema 7

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);
Acc:= Ma=Mb
End;

Procedure P__(Var p:Integer);
Var v:Integer;
Begin
v:=0;
Repeat
13
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 8

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;
Begin
For i:=1 To Length(s) Do s[i]:=ModC(s[i]);
Modif:=s
End;

Var s:String;
Begin
ClrScr;
14
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!

15

2. Programarea orientat pe obiecte

2.1. Concepte OOP n limbaje de programare

2.1.1. Noiunea de clas

2.1.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
{
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
{
16
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.

2.1.1.2. Tipuri abstracte de date

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();
17
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.

2.1.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
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:
18
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.
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.

2.1.1.4. Membrii unei clase. Pointerul this

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

19
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.

2.1.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:

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:

20
#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:

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

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.

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
22
} //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).

2.1.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
23
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;
return 0;
}

2.1.2. Metoda programrii orientate obiect


24
2.1.2.1. Bazele teoretice

Prin folosirea tipurilor abstracte de date, se creeaz un tot unitar pentru gestionarea datelor i
a operaiilor referitoare la aceste date. Cu ajutorul tipului abstract clas se realizeaz i
protecia datelor, deci n general elementele protejate nu pot fi accesate dect de funciile
membru ale clasei respective. Aceast proprietate a obiectelor se numete ncapsulare
(encapsulation).
n viaa de zi cu zi ns ne ntlnim nu numai cu obiecte separate, dar i cu diferite legturi
ntre aceste obiecte, respectiv ntre clasele din care obiectele fac parte. Astfel se formeaz o
ierarhie de clase. Rezult a doua proprietate a obiectelor: motenirea (inheritance). Acest
lucru nseamn c se motenesc toate datele i funciile membru ale clasei de baz de ctre
clasa derivat, dar se pot aduga elemente noi (date membru i funcii membru) n clasa
derivat. n cazul n care o clas derivat are mai multe clase de baz se vorbete despre
motenire multipl.
O alt proprietate important a obiectelor care aparin clasei derivate este c funciile membru
motenite pot fi suprancrcate. Acest lucru nseamn c o operaie referitoare la obiectele
care aparin ierarhiei are un singur identificator, dar funciile care descriu aceast operaie pot
fi diferite. Deci, numele funciei i lista parametrilor formali este aceeai n clasa de baz i n
clasa derivat, dar descrierea funciilor difer ntre ele. Astfel, n clasa derivat funciile
membru pot fi specifice clasei respective, dei operaia se identific prin acelai nume.
Aceast proprietate se numete polimorfism.

2.1.2.2. Declararea claselor derivate

O clas derivat se declar n felul urmtor:

class nume_clas_derivat : lista_claselor_de_baz {
//date membru noi i funcii membru noi
};

unde lista_claselor_de_baz este de forma:
elem_1, elem_2, ..., elem_n
i elem_i pentru orice 1 i n poate fi
public clas_de_baz_i
sau
protected clas_de_baz_i
sau
private clas_de_baz_i

Cuvintele cheie public, protected i private se numesc i de aceast dat modificatori de
protecie. Ei pot s lipseasc, n acest caz modificatorul implicit fiind private. Accesul la
elementele din clasa derivat este prezentat n tabelul 1.

Accesul la Modificatorii de Accesul la
25
elementele din clasa
de baz
protecie referitoare
la clasa de baz
elementele din clasa
derivat
public public public
protected public protected
private public inaccesibil
public protected protected
protected protected protected
private protected inaccesibil
public private private
protected private private
private private inaccesibil

Tabelul 1: accesul la elementele din clasa derivat

Observm c elementele de tip private ale clasei de baz sunt inaccesibile n clasa derivat.
Elementele de tip protected i public devin de tip protected, respectiv private dac
modificatorul de protecie referitor la clasa de baz este protected respectiv private, i rmn
neschimbate dac modificatorul de protecie referitor la clasa de baz este public. Din acest
motiv n general datele membru se declar de tip protected i modificatorul de protecie
referitor la clasa de baz este public. Astfel datele membru pot fi accesate, dar rmn
protejate i n clasa derivat.

2.1.2.3. Funcii virtuale

Noiunea de polimorfism ne conduce n mod firesc la problematica determinrii
funciei membru care se va apela n cazul unui obiect concret. S considerm urmtorul
exemplu. Declarm clasa de baz baza, i o clas derivat din acest clas de baz, clasa
derivata. Clasa de baz are dou funcii membru: functia_1 i functia_2. n interiorul funciei
membru functia_2 se apeleaz functia_1. n clasa derivat se suprancarc funcia membru
functia_1, dar funcia membru functia_2 nu se suprancarc. n programul principal se declar
un obiect al clasei derivate i se apeleaz funcia membru functia_2 motenit de la clasa de
baz. n limbajul C++ acest exemplu se scrie n urmtoarea form.
Fiierul virtual1.cpp:

#include <iostream>

using namespace std;

class baza {
public:
void functia_1();
void functia_2();
};
26

class derivata : public baza {
public:
void functia_1();
};

void baza::functia_1()
{
cout << "S-a apelat functia membru functia_1"
<< " a clasei de baza" << endl;
}

void baza::functia_2()
{
cout << "S-a apelat functia membru functia_2"
<< " a clasei de baza" << endl;
functia_1();
}

void derivata::functia_1()
{
cout << "S-a apelat functia membru functia_1"
<< " a clasei derivate" << endl;
}

int main() {
derivata D;
D.functia_2();
}


Prin execuie se obine urmtorul rezultat:

S-a apelat functia membru functia_2 a clasei de baza
S-a apelat functia membru functia_1 a clasei de baza

ns acest lucru nu este rezultatul dorit, deoarece n cadrul funciei main s-a apelat funcia
membru functia_2 motenit de la clasa de baz, dar funcia membru functia_1 apelat de
functia_2 s-a determinat nc n faza de compilare. n consecin, dei funcia membru
functia_1 s-a suprancrcat n clasa derivat nu s-a apelat funcia suprancrcat ci funcia
membru a clasei de baz.
Acest neajuns se poate nltura cu ajutorul introducerii noiunii de funcie membru virtual.
Dac funcia membru este virtual, atunci la orice apelare a ei, determinarea funciei membru
corespunztoare a ierarhiei de clase nu se va face la compilare ci la execuie, n funcie de
natura obiectului pentru care s-a fcut apelarea. Aceast proprietate se numete legare
dinamic, iar dac determinarea funciei membru se face la compilare, atunci se vorbete de
legare static.
Am vzut c dac se execut programul virtual1.cpp se apeleaz funciile membru
functia_1 i functia_2 ale clasei de baz. ns funcia membru functia_1 fiind suprancrcat
n clasa derivat, ar fi de dorit ca funcia suprancrcat s fie apelat n loc de cea a clasei de
baz.
Acest lucru se poate realiza declarnd functia_1 ca funcie membru virtual. Astfel, pentru
orice apelare a funciei membru functia_1, determinarea acelui exemplar al funciei membru
27
din ierarhia de clase care se va executa, se va face la execuie i nu la compilare. Ca urmare,
funcia membru functia_1 se determin prin legare dinamic.
n limbajul C++ o funcie membru se declar virtual n cadrul declarrii clasei respective n
modul urmtor: antetul funciei membru se va ncepe cu cuvntul cheie virtual.
Dac o funcie membru se declar virtual n clasa de baz, atunci suprancrcrile ei se vor
considera virtuale n toate clasele derivate ale ierarhiei.
n cazul exemplului de mai sus declararea clasei de baz se modific n felul urmtor.

class baza {
public:
virtual void functia_1();
void functia_2();
};

Rezultatul obinut prin execuie se modific astfel:

S-a apelat functia membru functia_2 a clasei de baza
S-a apelat functia membru functia_1 a clasei derivate

Deci, ntr-adevr se apeleaz funcia membru functia_1 a clasei derivate.
Prezentm n continuare un alt exemplu n care apare necesitatea introducerii funciilor
membru virtuale. S se defineasc clasa fractie referitoare la numerele raionale, avnd ca
date membru numrtorul i numitorul fraciei. Clasa trebuie s aib un constructor, valoarea
implicit pentru numrtor fiind zero iar pentru numitor unu, precum i dou funcii membru:
produs pentru a calcula produsul a dou fracii i inmulteste pentru nmulirea obiectului
curent cu fracia dat ca i parametru. De asemenea, clasa fractie trebuie s aib i o funcie
membru pentru afiarea unui numr raional. Folosind clasa fractie ca i clas de baz se va
defini clasa derivat fractie_scrie, pentru care se va suprancrca funcia produs, astfel nct
concomitent cu efectuarea nmulirii s se afieze pe stdout operaia respectiv. Funcia
inmulteste nu se va suprancrca, dar operaia efectuat trebuie s se afieze pe dispozitivul
standard de ieire i n acest caz. Fiierul fvirt1.cpp:

#include <iostream>

using namespace std;

class fractie {
protected:
int numarator;
int numitor;
public:
fractie(int numarator1 = 0, int numitor1 = 1);
fractie produs(fractie& r); //calculeaza produsul a doua
//fractii, dar nu simplifica
fractie& inmulteste(fractie& r);
void afiseaza();
};

fractie::fractie(int numarator1, int numitor1)
{
numarator = numarator1;
numitor = numitor1;
}
28

fractie fractie::produs(fractie& r)
{
return fractie(numarator * r.numarator, numitor * r.numitor);
}

fractie& fractie::inmulteste(fractie& q)
{
*this = this->produs(q);
return *this;
}

void fractie::afiseaza()
{
if ( numitor )
cout << numarator << " / " << numitor;
else
cerr << "Fractie incorecta";
}

class fractie_scrie: public fractie{
public:
fractie_scrie( int numarator1 = 0, int numitor1 = 1 );
fractie produs( fractie& r);
};

inline fractie_scrie::fractie_scrie(int numarator1, int numitor1) :
fractie(numarator1, numitor1)
{
}

fractie fractie_scrie::produs(fractie& q)
{
fractie r = fractie(*this).produs(q);
cout << "(";
this->afiseaza();
cout << ") * (";
q.afiseaza();
cout << ") = ";
r.afiseaza();
cout << endl;
return r;
}

int main()
{
fractie p(3,4), q(5,2), r;
r = p.inmulteste(q);
p.afiseaza();
cout << endl;
r.afiseaza();
cout << endl;
fractie_scrie p1(3,4), q1(5,2);
fractie r1, r2;
r1 = p1.produs(q1);
r2 = p1.inmulteste(q1);
p1.afiseaza();
cout << endl;
r1.afiseaza();
cout << endl;
r2.afiseaza();
29
cout << endl;
return 0;
}

Prin execuie se obine:

15 / 8
15 / 8
(3 / 4) * (5 / 2) = 15 / 8
15 / 8
15 / 8
15 / 8

Observm c rezultatul nu este cel dorit, deoarece operaia de nmulire s-a afiat numai o
singur dat, i anume pentru expresia r1 = p1.produs(q1). n cazul expresiei r2 =
p1.inmulteste(q1) ns nu s-a afiat operaia de nmulire. Acest lucru se datoreaz
faptului c funcia membru inmulteste nu s-a suprancrcat n clasa derivat. Deci s-a apelat
funcia motenit de la clasa fractie. n interiorul funciei inmulteste s-a apelat funcia
membru produs, dar deoarece aceast funcie membru s-a determinat nc n faza de
compilare, rezult c s-a apelat funcia referitoare la clasa fractie i nu cea referitoare la clasa
derivat fractie_scrie. Deci, afiarea operaiei s-a efectuat numai o singur dat.
Soluia este, ca i n exemplul anterior, declararea unei funcii membru virtuale, i anume
funcia produs se va declara ca funcie virtual. Deci declararea clasei de baz se modific n
felul urmtor:

class fractie {
protected:
int numarator;
int numitor;
public:
fractie(int numarator1 = 0, int numitor1 = 1);
virtual fractie produs(fractie& r); //calculeaza produsul a doua
//fractii, dar nu simplifica
fractie& inmulteste(fractie& r);
void afiseaza();
};

Dup efectuarea acestei modificri prin executarea programului obinem:

15 / 8
15 / 8
(3 / 4) * (5 / 2) = 15 / 8
(3 / 4) * (5 / 2) = 15 / 8
15 / 8
15 / 8
15 / 8

Deci, se observ c afiarea operaiei s-a fcut de dou ori, pentru ambele expresii. Funciile
virtuale, ca i alte funcii membru de fapt, nu trebuie neaprat suprancrcate n clasele
derivate. Dac nu sunt suprancrcate atunci se motenete funcia membru de la un nivel
superior.
Determinarea funciilor membru virtuale corespunztoare se face pe baza unor tabele
construite i gestionate n mod automat. Obiectele claselor care au funcii membru virtuale
30
conin i un pointer ctre tabela construit. De aceea gestionarea funciilor membru virtuale
necesit mai mult memorie i un timp de execuie mai ndelungat.

31

3. Structuri de date

3.1. Cozi, stive

In cele ce urmeaz vom prezenta cteva dintre containerele des folosite in programare
i anume stivele i cozilei. Vom specifica tipurile abstracte de date corespunztoare, indicnd
i specificnd operaiile caracteristice. Pentru fiecare operaie din interfaa unui tip de date,
vom da specificarea operaiei n limbaj natural, indicnd datele i precondiiile operaiei
(pre), precum i rezultatele i postcondiiile operaiei (post).

3.1.1. Stiva

In limbajul uzual cuvntul stiv refer o grmad n care elementele constitutive
sunt aezate ordonat unele peste altele. Un element nou se adaug n stiv deasupra
elementului cel mai recent adugat n stiv. Din stiv se poate accesa i extrage doar
elementul cel mai recent introdus. Exemple de stive sunt multiple: stiv de farfurii, stiv de
lemne, etc. Tipul de date Stiv permite implementarea n aplicaii a acestor situaii din
lumea real.
Stiva este o list liniar n care adugrile, tergerile i accesul se fac la un singur
capt al stivei, numit vrf. ntr-o stiv nu este permis accesul la elemente pe baza poziiei.
Accesul ntr-o stiv este prespecificat (se poate accesa doar elementul cel mai recent
introdus n stiv din vrful stivei). Dintr-o stiv se poate terge elementul cel mai recent
introdus n stiv cel din vrful stivei. Ca urmare, stiva implementeaz principiul ultimul
sosit, primul servit LIFO (Last I n First Out).
Se poate considera i o capacitate iniial a stivei (numr maxim de elemente pe care le
poate include), caz n care dac numrul efectiv de elemente atinge capacitatea maxim,
spunem c avem o stiv plin. O stiv fr elemente o vom numi stiv vid. Dac se ncearc
extragerea unui element din stiva vid, vom spune c stiva are depire inferioar, iar n
cazul n care se ncearc adugarea unui element n stiva plin, vom spune c stiva are
depire superioar.
Vom da n continuare specificaia tipului abstract de date STIVA. Stiva vid o vom
nota cu |.

Tipul Abstract de Date STIVA

domeniu
S={s | s este o stiv cu elemente de tip TElement, s implementeaz principiul LIFO }

operaii (interfaa minimal)

creeaz(s)
descriere: creeaz o stiv vid
pre: adevrat
32
post: seS, | = s
adaug (s, e)
descriere: se adaug un element n vrful stivei
pre: seS, eeTelement, s nu e plin
post: seS, e a fost adugat n vrful stivei s (e va fi cel mai recent element
introdus n s)
terge (s, e)
descriere: se scoate un element din vrful stivei
pre: seS, | = s
post: seS, eeTElement, e este cel mai recent element introdus n s, s se
modific prin tergerea elementului din vrf
element (s, e)
descriere: se acceseaz elementul din vrful stivei
pre: seS, | = s
post: eeTElement, e este cel mai recent element introdus n s
vid(s)
descriere: funcie care verific dac stiva este vid
pre: seS
post: vid = adevrat n cazul n care s e stiva vid
fals n caz contrar
plin(s)
descriere: funcie care verific dac stiva este plin
pre: seS
post: plin = adevrat n cazul n care s e plin
fals n caz contrar
distruge(s)
descriere: distruge o stiv
pre: seS
post: stiva s a fost distrus

Avnd n vedere c nu este permis accesul la elementele din interiorul stivei, afiarea
coninutului stivei poate fi fcut doar dac privim stiva ca o list, adic: scoatem valorile din
stiv, afindu-le i punndu-le pe o stiv auxiliar, apoi repunndu-le pe stiva iniial. Ca
urmare, stiva nu este potrivit pentru aplicaiile care necesit traversarea ei, deoarece nu
avem acces direct la valorile interioare ale stivei.

3.1.2. Coada

n limbajul uzual cuvntul coad se refer la o niruire de oameni, maini, etc.,
aranjai n ordinea sosirii i care ateapt un eveniment sau serviciu. Noii sosii se
poziioneaz la sfritul cozii. Pe msur ce se face servirea, oamenii se mut cte o poziie
nainte, pn cnd ajung n fa i sunt servii, asigurndu-se astfel respectarea principiului
primul venit, primul servit. Exemple de cozi sunt multiple: coada de la benzinrii, coada
33
pentru cumprarea unui produs, etc. Tipul de date Coad permite implementarea n aplicaii
a acestor situaii din lumea real.
Coada este o list liniar n care adugrile se fac la un capt al cozii (numit spate),
iar accesul i tergerile se fac la cellat capt al cozii (numit fa). ntr-o coad nu este permis
accesul la elemente pe baza poziiei.
Accesul ntr-o coad este prespecificat (se poate accesa doar elementul cel mai
devreme introdus n coad elementul din fa). Dintr-o coad se poate terge elementul cel
mai devreme introdus n coad elementul din fa). Ca urmare, coada implementeaz
principiul primul sosit, primul servit FIFO (First I n First Out).
Se poate considera i o capacitate iniial a cozii (numr maxim de elemente pe care le
poate include), caz n care dac numrul efectiv de elemente atinge capacitatea maxim,
spunem c avem o coad plin. O coad fr elemente o vom numi coad vid. Dac se
ncearc extragerea unui element din coada vid, vom spune c avem o depire inferioar,
iar n cazul n care se ncearc adugarea unui element n coada plin, vom spune c avem
depire superioar.
Vom da n continuare specificaia tipului abstract de date COADA. Coada vid o vom
nota cu |.

Tipul Abstract de Date COADA

domeniu

C={c | c este o coad cu elemente de tip TElement, c implementeaz principiul FIFO }

operaii (interfaa minimal)

creeaz(c)
descriere: creeaz o coad vid
pre: adevrat
post: ceC, | = c
adaug (c, e)
descriere: se adaug un element la sfritul cozii
pre: ceC, eeTelement,c nu e plin
post: ceC, e a fost adugat la sfritul cozii c, e va fi cel mai recent element
introdus n c
terge (c, e)
descriere: se extrage primul element din coad
pre: ceC, | = c
post: ceC , eeTElement, e este cel mai devreme element introdus n c, c se
modific prin tergerea acestui elementul
element (c, e)
descriere: se acceseaz elementul cel mai devreme introdus n coad
pre: ceC, | = c
post: eeTElement, e este elementul introdus n c cel mai devreme
vid(c)
descriere: funcie care verific dac n coad nu sunt elemente (este vid)
34
pre: ceC
post: vid = adevrat n cazul n care c e coada vid
fals n caz contrar
plin(c)
descriere: funcie care verific dac n coad nu se mai pot aduga
elemente (este plin)
pre: ceC
post: plin = adevrat n cazul n care c e plin
fals n caz contrar
distruge(c)
descriere: distruge o coad
pre: ceC
post: coada c a fost distrus

Avnd n vedere c nu este permis accesul la elementele din interiorul cozii, afiarea
coninutului cozii poate fi fcut doar dac privim coada ca o list, adic: scoatem valorile
din coad, punndu-le ntr-o coad auxiliar, apoi repunndu-le n coada iniial i afindu-
le. Ca urmare, coada nu este potrivit pentru aplicaiile care necesit traversarea ei, deoarece
nu avem acces direct la valorile interioare cozii.

35

3.2. Identificarea structurilor de date potrivite n aplicaii

Pentru urmtoarele probleme, identificai cel mai potrivit tip abstract de date pentru
rezolvarea problemei (STIVA, COADA). Folosind doar operaiile din interfaa tipului
identificat (fcnd abstracie de implementarea sa propriu-zis), scriei o aplicaie pentru
rezolvarea problemei.

1. Evaluarea unei expresii aritmetice din forma polonez postfixat. Forma polonez
postfixat este o form de reprezentare a expresiilor aritmetice n care fiecare operator
aritmetic este scris dup operanzii si.

Fie EPost o expresie aritmetic corect n forma postfixat, coninnd operatorii binari:
+, -, *, /, iar ca operanzi cifrele de la 0 la 9 (ex: EPost=1 2 + 3 * 4 /). Se cere s se
determine valoarea expresiei (ex: valoarea este 2.25).

Indicaie: Se va folosi o STIV n care se vor aduga operanzii. n final, stiva va conine
valoarea expresiei.

Vom putea folosi urmtorii pai n rezolvare.

- Pentru fiecare EPost ee (n ordine de la stnga la dreapta)
i. Dac e este operand, atunci se adaug n stiv
ii. Dac e este operator, atunci se scot din stiv doi operanzi (
1
op i
2
op ), se
efectueaz operaia e ntre cei doi operanzi (
1 2
op e op v = ), dup care se
adaug v n stiv.
- n presupunerea noastr c expresia n forma postfixat este valid, n final, stiva va
conine o singur valoare, care se va extrage din stiv. Aceast valoare reprezint
valoarea expresiei.

2. Translatarea unei expresii aritmetice din forma polonez infixat n forma polonez
postfixat. Forma polonez infixat este forma uzual de reprezentare a expresiilor
aritmetice n care fiecare operator aritmetic binar este scris ntre operanzii si.

Fie E o expresie aritmetic corect n forma infixat, fr paranteze, coninnd
operatorii binari: +, -, *, /, iar ca operanzi cifrele de la 0 la 9 (ex: E=1 + 2 * 3). Se cere s
se determine forma postfixat EPost a expresiei (ex: EPost=1 2 3 * +).

Indicaie: Se va folosi o STIV n care se vor aduga operatorii i o COAD EPost care
va conine n final forma postfixat a expresiei.

Vom putea folosi urmtorii pai n rezolvare.

- Pentru fiecare E ee (n ordine de la stnga la dreapta)
i. Dac e este operand, atunci se adaug n coada EPost.
36
ii. Dac e este operator, atunci se scot din stiv operatorii avnd prioritatea de
evaluare mai mare sau egal dect a lui e i se adaug n coada Epost, dup
care se adaug e n stiv
- Se scot din stiv operatorii rmai i se adaug n coada EPost.
- In final, EPost va conine forma postfixat a expresiei.

3. Aceeai problem ca i cea anterioar, dar expresia n forma infixat conine paranteze
(ex: E= (1+2)*3).

Indicaie: Ideea/algoritmul de baza este aceeai ca i n cazul n care expresia nu ar
conine paranteze. Paranteza deschis ( se va aduga n stiv. Vor trebui identificai
paii care vor trebui efectuai la ntlnirea unei paranteze nchise ).

4. ntr-o bibliotec sunt mai multe teancuri de reviste. Bibliotecarul vrea s pun pe un raft
doar revistele cu anul de apariie > 1970. El va lua pe rnd revistele din vrful fiecrui
teanc i va pune revistele cu anul de apariie > 1970 pe raft, una lng cealalt,
completnd raftul de la stnga spre dreapta. Afiai revistele n ordinea n care
bibliotecarul le va pune pe raft.

Indicaie: Pentru a memora un teanc de reviste vom folosi o STIV, iar pentru
memorarea raftului nou creat vom folosi o COAD.

5. Se d un ir de paranteze. Se cere s se verifice dac parantezele se nchid corect. De
exemplu: (()()) se nchid corect, ())(() nu se nchid corect.

Indicaie: Se va folosi o STIVA.

6. Se d un text care conine litere, paranteze rotunde, paranteze drepte i acolade. Se cere s
se verifice dac n text parantezele se nchid corect. De exemplu n textul {a= (2 +
b[3])*5;} parantezele se nchid corect. n textul { a = (b[0) . 1]; } parantezele nu se nchid
corect.

Indicaie: Se va folosi o STIVA.


7. Un server HTTP primete cereri de la diveri clieni. S se simuleze procesul de rezolvare
a cererilor. Se vor afia cererile n ordinea n care serverul le rezolv.

Indicaie: Se va folosi o COADA.

8. S se simuleze urmtorul joc de cri. Doi juctori primesc iniial
2
n
cri de joc (fiecare
carte poate avea culoarea roie sau neagr). Juctorii pun alternativ cte o carte pe mas
(din vrful teancului lor de cri), pn se pune o carte roie (caz n care teancul de pe
mas va fi luat de ctre adversarul juctorului care a pus cartea roie i adugat sub
teancul su de cri). Pierde juctorul care nu mai are cri.

Indicaie: Teancurile celor doi juctori sunt COZI, iar teancul de pe mas este o
STIVA.
37

9. Fie un labir
n acest labirint. Robotul se poate deplasa n 4 direcii: N, S, E, V.
a). Testai dac R poate iei din labirint (poate ajunge la margine).
b). Determinai un drum pentru ieire (dac exist).

Indicaie:

Fie T mulimea poziiilor n care robotul poate ajunge pornind de la poziia iniial.
Notm cu S mulimea poziiilor n care robotul a ajuns pn la un moment dat i din care
s-ar putea deplasa. Un algoritm pentru determinarea mulimilor T i S ar putea fi:

T := {poziia iniial}
S := {poziia iniial}
Cttimp S =| execut
Fie p un element din S
S := S \ { p}
Pentru fiecare poziie q alturat poziiei p, q = 'X' i q eT
execut
S := S {q}
T := T {q}
Sfpentru
Sfct

- Pentru a rspunde la punctul a), algoritmul s-ar putea termina dac poziia q care
satisface condiiile este pe frontiera labirintului.
- Mulimea T poate fi memorat printr-o matrice asociat labirintului (ex: 0 pentru
poziiile neatinse nc, respectiv 1 pentru poziiile n care robotul a ajuns).
- Structura S poate fi o STIVA sau o COADA.

38

4. Baze de date

- Baze de date relaionale. Primele trei forme normale ale unei relaii
- Gestiunea bazelor de date relaionale cu SQL
- Interogarea bazelor de date cu operatori din algebra relaional
- Interogarea bazelor de date relaionale cu SQL

4.1. Baze de date relaionale

4.1.1. Modelul relaional

Modelul relaional de organizare a bazelor de date a fost introdus de E.F.Codd n 1970
i este cel mai studiat i mai mult folosit model de organizare a bazelor de date. In continuare
se va face o scurt prezentare a acestui model.
Fie A
1
, A
2
, ..., A
n
o mulime de atribute (coloane, constituani, nume de date, etc.) i
{?} )
i
Dom(A
i
D = domeniul valorilor posibile pentru atributul A
i
, unde prin ? s-a
notat valoarea de nedefinit (null). Valoarea de nedefinit se folosete pentru a verifica dac
unui atribut i s-a atribuit o valoare sau el nu are valoare (sau are valoarea nedefinit).
Aceast valoare nu are un anumit tip de dat, se pot compara cu aceast valoare atribute de
diferite tipuri (numerice, iruri de caractere, etc.).
Plecnd de la mulimile astfel introduse, se poate defini o relaie de gradul n sub
forma urmtoare:
, ...
2 1 n
D D D R _
i poate fi considerat ca o mulime de vectori cu cte n valori, cte o valoare pentru fiecare
din atributele A
i
. O astfel de relaie se poate memora printr-un tabel de forma:

R A
1
... A
i
.. A
n
r
1
a
11
... a
1j
... a
1n
... ... ... ... ... ...
r
i
a
i1
... a
ij
... a
in
... ... ... ... ... ...
r
m
a
m1
... a
mj
... a
mn

unde liniile din acest tabel formeaz elementele relaiei, sau tupluri, sau nregistrri, care
n general sunt distincte, i . ,..., 1 , ,..., 1 , m i n j D a
j ij
= = e Deoarece modul n care se
evideniaz elementele relaiei R de mai sus seamn cu un tabel, relaia se mai numete i
39
tabel. Pentru a pune n eviden numele relaiei (tabelului) i lista atributelor vom nota
aceast relaie cu:
| |
n
A A A R ,..., ,
2 1
.
Modelul relaional al unei baze de date const dintr-o colecie de relaii ce variaz n
timp (coninutul relaiilor se poate schimba prin operaii de adugare, tergere i actualizare).
O baz de date relaional const din trei pri:
1. Datele (relaii sau tabele, legturi ntre tabele) i descrierea acestora;
2. Reguli de integritate (pentru a memora numai valori corecte n relaii);
3. Operatori de gestiune a datelor.
Exemplul 1. STUDENTI [NUME, ANUL_NASTERII, ANUL_DE_STUDIU],
cu urmtoarele valori posibile:

NUME ANUL_NASTERII ANUL_DE_STUDIU
Pop Ioan 1979 4
Barbu Ana 1981 2
Dan Radu 1980 3
Exemplul 2. CARTE [AUTORI, TITLU, EDITURA, AN_APARITIE],
cu valorile:
AUTORI TITLU EDITURA AN_APARITIE
Date, C.J. An Introduction to Database
Systems
Addison-Wesley
Publishing Comp.
1995
Ghosh, S.P. Data Base Organization for
Data Management
Academic Press 1977
Helman, P. The Science of Database
Management
Irwin, SUA 1994
Ramakrishnan, R. Database Management
Systems
McGraw-Hill 1998
Pentru fiecare relaie se poate preciza un atribut sau o colecie de atribute, din cadrul
relaiei, numit cheie, cu rol de identificare a elementelor relaiei (cheia ia valori diferite
pentru nregistrri diferite din relaie, deci fiecare nregistrare se poate identifica prin
valoarea cheii). Dac se d cte o valoare pentru atributele din cheie, se poate determina linia
(una singur) n care apar aceste valori. Se presupune c nici o submulime de atribute din
cheie nu este cheie. Deoarece toate elementele relaiei sunt diferite, o cheie exist totdeauna
(n cel mai ru caz cheia este format din toate atributele relaiei). Pentru exemplul 1 se poate
alege NUME ca i cheie (atunci n baza de date nu pot exista doi studeni cu acelai nume),
iar pentru exemplul 2 se poate alege grupul de atribute {AUTORI, TITLU, EDITURA,
AN_APARITIE} ca i cheie.
Pentru anumite relaii pot fi alese mai multe chei. Una dintre chei (un atribut sau un
grup de atribute) se alege cheie principal (primar), iar celelalte se vor considera chei
secundare (chei candidat). Sistemele de gestiune a bazelor de date nu permit existena a
dou elemente distincte ntr-o relaie cu aceeai valoare pentru oricare cheie (principal sau
secundar), deci precizarea unei chei constituie o restricie pentru baza de date.
Exemplul 3. ORAR [ZI, ORA, SALA, PROFESOR, CLASA, DISCIPLINA],
40
cu orarul pe o sptmn. Se pot alege ca i chei urmtoarele mulimi de atribute:
{ZI, ORA, SALA}; {ZI, ORA, PROFESOR}; {ZI, ORA, CLASA}.

4.1.2. Primele trei forme normale ale unei relai

In general anumite date se pot reprezenta n mai multe moduri prin relaii (la modelul
relaional). Pentru ca aceste date s se poat prelucra ct mai simplu (la o operaie de
actualizare a datelor s nu fie necesare teste suplimentare) este necesar ca relaiile n care se
memoreaz datele s verifice anumite condiii (s aib un anumit nivel de normalizare).
Pn n prezent se cunosc mai multe forme normale pentru relaii, dintre care cinci
sunt mai cunoscute: 1NF, 2NF, 3NF, 4NF, 5NF. Aceste forme normale au fost definite de
ctre Codd (primele trei) i Fagin (formele 4NF i 5NF). Avem urmtoarele incluziuni pentru
relaii n diferite forme normale:


Dac o relaie nu este de o anumit form normal, atunci ea se poate descompune n
mai multe relaii de aceast form normal respectiv.
Definiie. Pentru descompunerea unei relaii se folosete operatorul de proiecie. Fie
| |
n
A A A R ,..., ,
2 1
o relaie i { }
p
i i i
A A A ,..., ,
2 1
= o o submulime de atribute,
{ }
n
A A A ,..., ,
2 1
c o . Prin proiecia relaiei R pe se nelege relaia:
| |
{ }
, ) ( ) ( ,..., , '
,..., ,
2 1
2 1
[ [
= =
p
i i i
p A A A
i i i
R R A A A R
o
,
unde:
( ) | | ( ) ' ,..., , ) ( ,..., ,
2 1
2 1
R a a a r r R a a a r
p
i i i n
e = = e =
[
o
o
,
i toate elementele din R' sunt distincte.
Definiie. Pentru compunerea relaiilor se folosete operatorul de join natural. Fie
| | | o, R , | | |, S dou relaii peste mulimile de atribute | o , , , = o . Prin joinul
natural al relaiilor R i S se nelege relaia:
( ) { }. ) ( ) ( , ) ( , ) ( ), ( ] , , [
[ [ [ [ [
= e e = -
| | o
| o s r si S s R r s r r S R
1NF
2NF
3NF
4NF
5NF
41
O relaie R se poate descompune n mai multe relaii noi
m
R R R ,..., ,
2
1
. Aceast
descompunere este bun dac
m
R R R R - - - = ...
2
1
, deci datele din R se pot regsi din datele
memorate n relaiile
m
R R R ,..., ,
2
1
i nu apar date noi prin aceste operaii de compunere.
Exemplu de descompunere care nu este bun: fie relaia:
ContracteStudiu[Student,CadruDidactic, Disciplina],
i dou noi relaii obinute prin proiecia acestei relaii: SC[Student,CadruDidactic] i
CD[CadruDidactic, Disciplina]. Presupunem c pentru relaia iniial avem urmtoarele
valori:

R Student CadruDidactic Disciplina
r
1
s1 c1 d1
r
2
s2 c2 d2
r
3
s1 c2 d3
Folosind definiia proieciei se obin urmtoarele valori pentru cele dou relaii obinute
din R i pentru joinul natural al acestor relaii:
SC Student CadruDidactic
r
1
s1 c1
r
2
s2 c2
r
3
s1 c2

CD CadruDidactic Disciplina
r
1
c1 d1
r
2
c2 d2
r
3
c2 d3

SC*CD Student CadruDidactic Disciplina

s1 c1 d1

s2 c2 d2

s2 c2 d3

s1 c2 d2

s1 c2 d3
Se observ c n relaia SC*CD se obin nregistrri suplimentare fa de relaia iniial, deci
descompunerea sugerat nu este bun.
Observaie. Prin atribut simplu vom nelege un atribut oarecare din relaie, iar prin
atribut compus vom nelege o mulime de atribute (cel puin dou) din relaie.
Este posibil ca n diverse aplicaii practice s apar atribute (simple sau compuse) ce
iau mai multe valori pentru un element din relaie. Aceste atribute formeaz un atribut
repetitiv.
Exemplul 4. Fie relaia:
STUDENT [NUME, ANULNASTERII, GRUPA, DISCIPLINA, NOTA],
42
cu atributul NUME ca i cheie. In acest exemplu perechea {DISCIPLINA, NOTA} este un
grup repetitiv. Putem avea urmtoarele valori n aceast relaie:
NUME ANULNASTERII GRUPA DISCIPLINA NOTA
Pop Ioan 1982 221 Baze de date
Sisteme de operare
Probabiliti
10
9
8
Murean Ana 1981 222 Baze de date
Sisteme de operare
Probabiliti
Proiect individual
8
7
10
9
Exemplul 5. Fie relaia:
CARTE [Cota, NumeAutori, Titlu, Editura, AnApariie, Limba, CuvinteCheie],
cu atributul Cota ca i cheie i atributele repetitive NumeAutori i CuvinteCheie. Atributul
COTA poate avea o semnificaie efectiv (s existe o cot asociat la fiecare carte) sau s fie
introdus pentru existena cheii (valorile, distincte, s fie generate automat).
Grupurile repetitive creaz foarte multe greuti n memorarea diverselor relaii i din
aceast cauz se ncearc evitarea lor, fr ns a pierde date. Dac R[A] este o relaie, unde
A este mulimea atributelor, iar formeaz un grup repetitiv (atribut simplu sau compus),
atunci R se poate descompune n dou relaii fr ca s fie atribut repetitiv. Dac C este o
cheie pentru relaia R, atunci cele dou relaii n care se descompune relaia R sunt:
| | ( )
[

=
o
o
C
R C R' i | | ( )
[

=
o
o
A
R A R ' ' .
Exemplul 6. Relaia STUDENT din exemplul 4 se descompune n urmtoarele dou
relaii:
DATE_GENERALE [NUME, ANULNASTERII, GRUPA],
REZULTATE [NUME, DISCIPLINA, NOTA].
Exemplul 7. Relaia CARTE din exemplul 5 se descompune n urmtoarele trei relaii
(n relaia CARTE exist dou grupuri repetitive):
CARTI [Cota, Titlu, Editura, AnApariie, Limba],
AUTORI [Cota, NumeAutori],
CUVINTE_CHEIE [Cota, CuvntCheie].
Observaie. Dac o carte nu are autori sau cuvinte cheie asociate, atunci ea va avea
cte o nregistrare n relaiile AUTORI sau CUVINTE_CHEIE n care al doilea atribut are
valoarea null. Dac se dorete eliminarea acestor nregistrri, atunci relaia CARTE nu se va
putea obine din cele trei relaii numai prin join natural (sunt necesari operatori de join
extern).
Definiie. O relaie este de prima form normal (1NF) dac ea nu conine grupuri
(de atribute) repetitive.
Sistemele de gestiune a bazelor de date relaionale permit descrierea numai a relaiilor
ce se afl n 1NF. Exist i sisteme de gestiune ce permit gestiunea relaiilor non-1NF
(exemplu Oracle, unde o coloan poate fi un obiect sau o colecie de date).
Urmtoarele dou forme normale ale unei relaii utilizeaz o noiune foarte important,
i anume dependena funcional dintre diverse submulimi de atribute. Stabilirea
dependenelor funcionale este o sarcin a administratorului bazei de date i depinde de
43
semnificaia (semantica) datelor ce se memoreaz n relaie. Operaiile de actualizare a
datelor din relaie (nserare, tergere, modificare) nu trebuie s modifice dependenele
funcionale (dac pentru relaie exist astfel de dependene).
Definiie. Fie | |
n
A A A R ,..., ,
2 1
o relaie i { }
n
A A A ,..., , ,
2 1
c | o dou submulimi de
atribute. Atributul (simplu sau compus) | este dependent funcional de atributul o (simplu
sau compus), notaie: | o , dac i numai dac fiecare valoare a lui o din R are asociat
o valoare precis i unic pentru | (aceast asociere este valabil tot timpul existenei
relaiei R). O valoare oarecare a lui o poate s apar n mai multe linii ale lui R i atunci
fiecare dintre aceste linii conine aceeai valoare pentru atributul | , deci ( ) ( )
[ [
=
o o
' r r
implic ( ) ( )
[ [
=
| |
' r r .
Valoarea o din implicaia (dependena) | o se numete determinant, iar | este
determinat.
- Dependena funcional se poate folosi ca o proprietate (restricie) pe care baza de date
trebuie s o ndeplineasc pe perioada existenei acesteia: se adaug elemente n relaie
numai dac dependena funcional este verificat.
Existena unei dependene funcionale ntr-o relaie nseamn c anumite asocieri de
valori se memoreaz de mai multe ori, deci apare o redundan. Pentru exemplificarea unor
probleme care apar vom lua relaia urmtoare, care memoreaz rezultatele la examene pentru
studeni:
Exemplul 8. EXAMEN [NumeStudent, Disciplina, Nota, CadruDidactic],
unde cheia este {NumeStudent, Disciplina}. Deoarece unei discipline i corespunde un singur
cadru didactic, iar unui cadru didactic pot s-i corespund mai multe discipline, putem cere ca
s fie ndeplinit restricia (dependena) {Disciplina} {CadruDidactic}.
Examen NumeStudent Disciplina Nota CadruDidactic
1

Alb Ana Matematic 10 Rus Teodor
2

Costin Constantin Istorie 9 Popa Horea
3

Alb Ana Istorie 8 Popa Horea
4

Enisei Elena Matematic 9 Rus Teodor
5

Frian Florin Matematic 10 Rus Teodor
Dac pstrm o astfel de dependen funcional, atunci pot apare urmtoarele probleme:
- Risip de spaiu: aceleai asocieri se memoreaz de mai multe ori. Legtura dintre
disciplina de Matematic i profesorul Rus Teodor este memorat de trei ori, iar dintre
disciplina Istorie i profesorul Popa Horea se memoreaz de dou ori.
- Anomalii la actualizare: schimbarea unei date ce apare ntr-o asociere implic efectuarea
acestei modificri n toate asocierile (fr a se ti cte astfel de asocieri exist), altfel baza
de date va conine erori (va fi inconsistent). Dac la prima nregistrare se schimb
valoarea atributului CadruDidactic i nu se face aceeai modificare i la nregistrrile 4 i
5, atunci modificarea va introduce o eroare n relaie.
- Anomalii la nserare: la adugarea unei nregistrri trebuie s se cunoasc valorile
atributelor, nu se pot folosi valori nedefinite pentru atributele implicate n dependenele
funcionale.
44
- Anomalii la tergere: la tergerea unor nregistrri se pot terge i asocieri (ntre valori)
ce nu se pot reface. De exemplu, dac se terg nregistrrile 2 i 3, atunci asocierea dintre
Disciplina i CadruDidactic se pierde.
Anomaliile de mai sus apar datorit existenei unei dependene funcionale ntre
mulimi de atribute. Pentru a elimina situaiile amintite trebuie ca aceste dependene
(asocieri) de valori s se pstreze ntr-o relaie separat. Pentru aceasta este necesar ca relaia
iniial s se descompun, fr ca prin descompunere s se piard date sau s se introduc
date noi prin compunerea de relaii (trebuie ca descompunerea "s fie bun"). O astfel de
descompunere se face n momentul proiectrii bazei de date, cnd se pot stabili dependenele
funcionale.
Observaii. Se pot demonstra uor urmtoarele proprieti simple pentru dependenele
funcionale:
1. Dac C este o cheie pentru | |
n
A A A R ,..., ,
2 1
, atunci { }
n
A A A C ,..., , ,
2 1
c | | .
2. Dac o | _ , atunci | o , numit dependena funcional trivial sau refelxivitatea.
| o
| |
o |
o o
H = H H = H
c
) ( ) ( ) ( ) (
2 1 2 1
r r r r
3. Dac | o , atunci | , cu o c .
|
| |
| o
o o
o

H = H H = H H = H
c
) ( ) ( ) ( ) ( ) ( ) (
2 1 2 1 2 1
r r r r r r
4. Dac | o i | , atunci o , care este proprietatea de tranzitivitate a
dependenei funcionale.
o

|
| |
| o
o o
H = H H = H H = H

) ( ) ( ) ( ) ( ) ( ) (
2 1 2 1 2 1
r r r r r r
5. Dac | o i A c , atunci | o , unde o o = .
) ( ) (
) ( ) (
) ( ) ( ) ( ) (
) ( ) (
2 1
2 1
2 1 2 1
2 1
r r
r r
r r r r
r r
| |

| | o o
o o
H = H
H = H
H = H H = H
H = H
Relativ la o relaie R[A] i o mulime F de dependene funcionale apar urmtoarele trei
probleme:
I. Determinarea nchiderii mulimii F de dependene funcionale. Pentru mulimea
F de dependene funcionale se cere determinarea mulimii F
+
, numit nchiderea mulimii
F, i care conine toate dependenele funcionale obinute logic din F. Mulimea F de
dependene funcionale implic logic o dependen funcional f dac pentru orice relaie n
care F este ndeplinit rezult c i f este ndeplinit.
Pentru determinarea nchiderii F
+
se pot aplica repetat urmtoarele trei reguli (axiomele
lui Armstrong):
1. Reflexivitatea: dac A c o i o | c , atunci | o .
2. Mrirea: dac | o i A c , atunci | o (unde s-a notat o o = ).
3. Tranzitivitatea: dac | o i | , atunci o .
Aceste reguli sunt complete (determin nchiderea) i logice (nu determin dependene
funcionale eronate).
Plecnd de la aceste reguli se poate demonstra c i urmtoarele reguli sunt adevrate:
4. Reuniunea: dac | o i o , atunci | o .
45
| o
| o| o
o| oo | o
o



=
tate tranzitivi
marire
marire

5. Descompunerea: dac | o , atunci | o i o .
| o
| |
| o

)
`


tate tranzitivi
ate reflexivit ) (

6. Pseudotranzitivitatea: dac | o i o | , atunci o o .
o o
o |
| o | o

)
`


tate tranzitivi

Exemplul 9. Fie A={A, B, C, D, E, F}, F={AB, AC, CDE, CDF, DE}.
In F
+
mai trebuie incluse, pe lng elementele din F, cel puin urmtoarele dependene:
AE (prin tranzitivitate),
CDEF (prin regula 4),
ADF (AC, ADCD din regula 2, CDF, i tranzitivitate),
ADE (analog ca mai sus),
ABC (prin regula 4).
II. Inchiderea unei mulimi de atribute sub o mulime de dependene funcionale.
Fie o submulime de atribute i F o mulime de dependene funcionale. Se pune problema
determinrii nchiderii lui (notat
+
) sub F i care conine mulimea atributelor
dependente funcional de atribute din . Pentru determinarea acestei nchideri se poate folosi
urmtorul algoritm:
inchidere := ;
while (inchidere se schimb) do
for fiecare dependen funcional | din F do
if c | inchidere then inchidere := inchidere .
Se poate demonstra c algoritmul este corect i determin
+
. Acest algoritm are o
complexitate foarte mare, proporional cu exponeniala lui |F| (|F| = numrul de elemente din
F).
Exemplul 10. Pentru { } D A, = o i F dat n exemplul precedent se obine:
AB
+
eo B ;
AC
+
eo C ;
CDE
+
eo E ;
CDF
+
eo F ;
deci { } { } F E D C B A D A , , , , , , = =
+ +
o .
III. Acoperire minimal de dependene funcionale.
Definiie. Dou mulimi de dependene funcionale F i G sunt echivalente (notaie
FG) dac F
+
=G
+
(deci nchiderile lor coincid).
46
Definiie. Fie F o mulime de dependene funcionale. Prin acoperirea minimal a
mulimii F se nelege o mulime de dependene funcionale, notat cu F
M
, care verific
urmtoarele condiii:
1. F
M
F;
2. Partea dreapt a fiecrei dependene funcionale din F
M
este format dintr-un singur
atribut;
3. Partea stng a fiecrei dependene funcionale din F
M
este redus ct mai mult posibil:
dac F e | o i o o c ' , atunci { } ( ) ( ) | o | o = '
'
F F
M
nu este echivalent
cu F
4. Nici o dependen funcional f din F
M
nu este redundant, deci (F
M
-f) nu este echivalent
cu F
M
.
Exemplul 11. Considerm relaia R [A, B, C, D, E, F] i mulimea de dependene
F={AB, BC, ABD, BEF}. Pentru a determina acoperirea minimal a mulimii F
vom analiza dependenele din F care nu se pot include n F
M
i dependenele noi care se obin
din cele deja determinate:
- BEF nu ndeplinete condiia 2, aceast dependen se nlocuiete cu BE i BF;
- AB, ABD implic prin pseudotranzitivitate dependena AD;
- Dependena anterioar (AD) implic faptul c ABD nu ndeplinete condiia 3;
- Dependena AC nu ndeplinete condiia 4 deoarece se obine din AB i BC.
Definiie. Un atribut A (simplu sau compus) se numete prim dac exist o cheie C i
AcC (C este o cheie compus, sau A este chiar o cheie a relaiei). Dac un atribut nu este
inclus n nici o cheie, atunci se numete neprim.
Definiie. Fie | |
n
A A A R ,..., ,
2 1
i { }
n
A A A ,..., , ,
2 1
c | o . Atributul | este complet
dependent funcional de o dac | este dependent funcional de o (deci | o ) i nu
este dependent funcional de nici o submulime de atribute din o ( | o o c , nu este
adevrat).
Observaie. Dac atributul | nu este complet dependent funcional de o , atunci
o este un atribut compus.
Definiie. O relaie este de a doua form norml (2NF) dac:
- este de prima form normal,
- orice atribut neprim (simplu sau compus) (deci care nu este inclus ntr-o cheie) este
complet dependent funcional de oricare cheie a relaiei.
Observaie. O relaie ce este de prima form normal (1NF) i nu este de a doua form
normal (2NF), atunci are o cheie compus. Dac o relaie nu este de a doua form normal,
atunci exist o dependen funcional | o cu o atribut (simplu sau compus) inclus ntr-
o cheie.
Pentru a preciza modul de descompunere pentru cazul general, fie | |
n
A A A R ,..., ,
2 1
o
relaie i { }
n
A A A A C ,..., ,
2 1
= c o cheie. Presupunem c exist A c | , = C | ( | este
un atribut necheie), | dependent funcional de C c o ( | este complet dependent
funcional de o submulime strict de atribute din cheie). Dependena | o se poate
elimina dac relaia R se descompune n urmtoarele dou relaii:
47
| | ( )
| |
[

=
| o
| o R R' i | | ( )
[

=
|
|
A
R A R ' ' .
Vom analiza relaia din exemplul 8:
EXAMEN [NumeStudent, Disciplina, Nota, CadruDidactic],
unde cheia este {NumeStudent, Disciplina} i exist dependena funcional (restricia)
{Disciplina} {CadruDidactic}. De aici deducem c atributul CadruDidactic nu este
complet dependent funcional de o cheie, deci relaia EXAMEN nu este de a doua form
normal. Eliminarea acestei dependene funcionale se poate face prin descompunerea relaiei
n urmtoarele relaii:
APRECIERI [NumeStudent, Disciplina, Nota];
STAT_FUNCTII [Disciplina, CadruDidactic].
Exemplul 12. Presupunem c pentru memorarea contractelor de studiu se folosete
relaia:
CONTRACTE[CNP, Nume, Prenume, CodDisciplina, DenumireDisciplina].
Cheia relaiei este {CNP,CodDisciplina}. In relaie mai exist dou dependene funcionale:
{CNP} {Nume, Prenume} i {CodDisciplina} {DenumireDisciplina}. Pentru eliminarea
acestor dependene se descompune relaia n urmtoarele:
STUDENTI [CNP, Nume, Prenume],
INDRUMATORI [CodDisciplina, DenumireDisciplina],
CONTRACTE [CNP, CodDisciplina].
Pentru a treia form normal este necesar noiunea de dependen tranzitiv.
Definiie. Un atribut Z este tranzitiv dependent de atributul X dac -Y nct XY,
YZ, iar YX nu are loc i Z nu este inclus n Y X .
Definiie. O relaie este de a treia form normal (3NF) dac este 2NF i orice
atribut neprim nu este tranzitiv dependent de oricare cheie a relaiei.
Dac C este o cheie i | un atribut tranzitiv dependent de cheie, atunci exist un
atribut o care verific: o C (dependen care este verificat totdeauna) i | o .
Deoarece relaia este 2NF, obinem c | este complet dependent de C, deci C . o . De aici
deducem c o relaie ce este 2NF i nu este 3NF are o dependen | o , iar o este atribut
neprim. Aceast dependen se poate elimina prin descompunerea relaiei R n mod
asemntor ca la eliminarea dependenelor de la 2NF.
Exemplul 13. Rezultatele obinute de absolveni la lucrarea de licen sunt trecute n
relaia:
LUCRARI_LICENTA [NumeAbsolvent, Nota, CadruDidIndr, Catedra].
Aici se memoreaz numele cadrului didactic ndrumtor i denumirea catedrei la care se afl
acesta. Deoarece se introduc date despre absolveni, cte o nregistrare pentru un absolvent,
putem s stabilim c NumeAbsolvent este cheia relaiei. Din semnificaia atributelor incluse n
relaie se observ urmtoarea dependen funcional:
{CadruDidIndr} {Catedra}.
Din existena acestei dependene funcionale se deduce c relaia nu este de 3NF.
Pentru a elimina dependena funcional, relaia se poate descompune n urmtoarele dou
relaii:
48
REZULTATE [NumeAbsolvent, Nota, CadruDidIndr]
INDRUMATORI [CadruDidIndr, Catedra].
Exemplul 14. Presupunem c adresele unui grup de persoane se memoreaz n urmtoarea
relaie:
ADRESE [CNP, Nume, Prenume, CodPostal, DenumireLocalitateDomiciliu, Strada, Nr].
Cheia relaiei este {CNP}. Deoarece la unele localiti codul potal se stabilete la nivel de
strad, sau chiar poiuni de strad, exist dependena funcional:
{CodPostal} {DenumireLocalitateDomiciliu}. Deoarece exist aceast dependen
funcional, deducem c relaia ADRESE nu este de a treia form normal, deci este necesar
descompunerea ei.
Exemplul 15. S considerm urmtoarea relaie care memoreaz o eventual planificare a
studenilor pentru examene:
PLANIFICARE_EX [Data, Ora, Cadru_did, Sala, Grupa],
cu urmtoarele restricii (cerine care trebuie respectate) care se transpun n definirea de chei
sau de dependene funcionale:
1. Un student d maximum un examen ntr-o zi, deci {Grupa, Data} este cheie.
2. Un cadru didactic are examen cu o singur grup la o anumit or, deci {Cadru_did, Data,
Ora} este cheie.
3. La un moment dat ntr-o sal este planificat cel mult un examen, deci {Sala, Data, Ora}
este cheie.
4. Intr-o zi cadrul didactic nu schimb sala, n sala respectiv pot fi planificate i alte
examene, dar la alte ore, deci exist urmtoarea dependen funcional:
{Cadru_did, Data} {Sala}
Toate atributele din aceast relaie apar n cel puin o cheie, deci nu exist atribute
neprime. Avnd n vedere definiia formelor normale precizate pn acuma, putem spune c
relaia este n 3NF. Pentru a elimina i dependenele funcionale de tipul celor pe care le
avem n exemplul de mai sus s-a introdus o nou form normal:
Definiie. O relaie este n 3NF Boyce-Codd, sau BCNF, dac orice determinant
(pentru o dependen funcional) este cheie, deci nu exist dependene funcionale | o
astfel nct o s nu fie cheie.
Pentru a elimina dependena funcional amintit mai sus trebuie s facem urmtoarea
descompunere pentru relaia PLANIFICARE_EX:
PLANIFICARE_EX [Data, Cadru_did, Ora, Student],
REPARTIZARE_SALI [Cadru_did, Data, Sala].
Dup aceast descompunere nu mai exist dependene funcionale, deci relaiile sunt de
tipul BCNF, dar a disprut cheia asociat restriciei precizate la punctul 3 de mai sus: {Sala,
Data, Ora}. Dac se mai dorete pstrat o astfel de restricie, atunci ea trebuie verificat
altfel (de exemplu, prin program).

49

4.2. Interogarea BD relaionale cu SQL

Comanda SELECT este folosit pentru interogarea bazelor de date (obinerea de
informaii). Aceast comand este cea mai complex din cadrul sistemelor ce conin comenzi
SQL. Comanda permite obinerea de date din mai multe surse de date. Ea are, printre altele,
funciile de selectie, proiectie, produs cartezian, join i reuniune din limbajul de interogare a
bazelor de date relaionale bazat pe algebra relaiilor. Sintaxa comenzii este dat n
continuare.
SELECT
| | | | | |
)
`

(
(
(

... cmp AS exp cmp AS exp


*
[PERCENT] n TOP
DISTINCT
ALL

FROM sursa1 [alias] [,sursa2 [alias]]...
[WHERE condiie]
[GROUP BY lista_cmpuri [HAVING condiie]]
[
(
(
(

LECT comanda_SE
EXCEPT
INTERSECT
[ALL] UNION


(
(

(
(

)
`

)
`

)
`

)
`

...
DESC
ASC
nrcmp
cmp
BY ORDER ,
DESC
ASC
nrcmp
cmp
BY ORDER
Aceast comand selecteaz date din sursele de date precizate n clauza FROM. Pentru
precizarea (calificarea) cmpurilor (dac este necesar, deci dac folosirea numai a numelui
cmpului produce ambiguitate, adic exist mai multe cmpuri cu acest nume n sursele de
date) se poate folosi numele tabelului sau un nume sinonim (alias local numai n comanda
SELECT) stabilit n FROM dup numele sursei de date. Dac se definete un "alias", atunci
calificarea se face numai cu el (nu se va mai face cu numele tabelului).
O construcie numit sursa poate fi:
1. un tabel sau view din baza de date
2. (instruciune_select)
3. expresie_join, sub forma:
o sursa1 [alias] operator_join sursa2 [alias] ON condiie_legatur
o (expresie_join)
O cond_elementara de legtur dintre dou surse de date (precizate prin expresie_tabel)
sunt de forma:
[alias_sursa1.]cmp1 operator [alias_sursa2.]cmp2
Condiiile de legtur sunt de forma:
o cond_elementara [AND cond_elementara] ...
- (condiie)
50

unde operator poate fi: =, <>, >, >=, <, <=.
Cei doi termeni ai comparatiei trebuie s aparin la tabele diferite.
O expresie join are ca rezultat un tabel i este de forma:
Sursa1
(
(
(
(
(

[OUTER] FULL
[OUTER] RIGHT
[OUTER] LEFT
INNER
JOIN Sursa2 ON conditie
Joinul condiional, din algebra relaional, notat prin Sursa1
c

Sursa2, este precizat


prin Sursa1 INNER JOIN sursa2 ON condiie, i determin acele nregistrri din produsul
cartezian al celor dou surse care ndeplinesc condiia din ON.
Joinul extern stnga, precizat prin Sursa1 LEFT [OUTER] JOIN sursa2 ON
condiie, determin o surs nou ce are ca atribute concatenarea atributelor din cele dou
surse, iar nregistrrile se obin astfel: se iau nregistrrile care se obin prin joinul condiional
Sursa1
c

Sursa2
,
la care se adaug nregistrrile din sursa1 care nu s-au folosit la acest join
condiional combinate cu valoarea null pentru toate atributele corespunztoare din Sursa2.
Joinul extern dreapta, precizat prin Sursa1 RIGHT [OUTER] JOIN sursa2 ON
condiie, determin o surs nou ce are ca atribute concatenarea atributelor din cele dou
surse, iar nregistrrile se obin astfel: se iau nregistrrile care se obin prin joinul condiional
Sursa1
c

Sursa2
,
la care se adaug nregistrrile din sursa2 care nu s-au folosit la acest join
condiional combinate cu valoarea null pentru toate atributele corespunztoare din Sursa1.
Joinul extern total, precizat prin Sursa1 FULL [OUTER] JOIN sursa2 ON condiie,
se obine prin reuniunea rezultatelor obinute de joinul extern stnga i joinul extern dreapta.
Alte tipuri de expresii join:
- Sursa1 JOIN Sursa2 USING (lista_coloane)
- Sursa1 NATURAL JOIN Sursa2
- Sursa1 CROSS JOIN Sursa2
Dac n clauza FROM apar mai multe surse de date (care se vor evalua la un tabel),
atunci ntre un astfel de tabel - pe care Il vom numi tabel principal, i celelalte tabele este
indicat s existe anumite legturi (stabilite prin condiii). Plecnd de la fiecare nregistrare a
tabelului principal se determin nregistrrile din celelalte tabele asociate prin astfel de
legturi (deci nregistrrile ce verific o condiie). Dac legtura (condiia) nu se stabilete,
atunci se consider c ea asociaz toate nregistrrile din celelalte tabele pentru fiecare
nregistrare a tabelului principal (se consider c valoarea condiiei este true atunci cnd ea
lipsete). Aceast condiie de legtur dintre sursele de date se precizeaz prin:
FROM sursa1[, sursa2] ... WHERE condiie_legtur
Folosind sursele de date din FROM i eventuala condiie de legtur (dac exist mai
multe surse de date) va rezulta un tabel_rezultat, cu coloanele obinute prin concatenarea
coloanelor din sursele de date, iar nregistrrile sunt determinate dup cum sunt explicate mai
sus.
In tabel_rezultat se pot pstra toate nregistrrile obinute din sursele de date, sau se
51
poate face o filtrare prin utilizarea unei condiii de filtrare. Aceasta condiie de filtrare va fi
trecut n clauza WHERE n continuarea condiiei de legtur. Cu o condiie de filtrare
condiia din WHERE este de forma:
WHERE condiie_filtrare
WHERE condiie_legtur AND condiie_filtrare
Condiia de filtrare din clauza WHERE poate fi construit dup urmtoarele reguli.
Condiiile elementare de filtrare pot fi de una din formele urmtoare:
- expresie operator_relational expresie
- expresie [NOT] BETWEEN valmin AND valmax
pentru a verifica dac valoarea unei expresii este cuprins ntre dou valori (valmin i
valmax) sau nu este cuprins ntre aceste valori (apare NOT)
- cmp (NOT) LIKE ablon
Dup LIKE apare un ablon (ca un ir de caractere) ce precizeaz o mulime de valori. In
funcie de sistemul de gestiune folosit, exist un caracter n ablon ce precizeaz locul unui
singur caracter necunoscut n cmp, sau un caracter n ablon ce precizeaz un ir neprecizat
de caractere n cmp.
- | |
| |
( )
)
`

e subselecti
... valoare valoare
IN NOT expresie
Se verific dac valoarea expresiei apare (sau nu - cu NOT) ntr-o list de valori sau ntr-o
subselecie. O subselecie este o surs de date generat cu comanda SELECT i care are
numai un singur cmp - cu valori de acelai tip cu valorile expresiei. Aceast condiie
corespunde testului de "apartenen" al unui element la o mulime.
- cmp operator_relational

SOME
ANY
ALL
(subselectie)
Valorile cmpului din stnga operatorului relaional i valorile singurului cmp din
subselecie trebuie s fie de acelai tip. Se obine valoarea adevrat pentru condiie dac
valoarea din partea stng este n relaia dat de operator pentru:
o toate valorile din subselectie (apare ALL),
o cel puin o valoare din subselectie (apare ANY sau SOME).
Condiii echivalente:
"expresie IN (subselecie)" echivalent cu "expresie = ANY (subselecie)"
"expresie NOT IN (subselecie)" echivalent cu "expresie <> ALL (subselecie)"
- [NOT] EXISTS (subselectie)
Cu EXISTS se obtine valoarea adevrat dac n subselecie exist cel puin o nregistrare, i
fals dac subselecia este vid. Prezena lui NOT inverseaz valorile de adevr.
- O condiie de filtrare poate fi:
o condiie elementar
52
o (condiie)
o not condiie
o condiie1 and condiie2
o condiie1 or condiie2
O condiie elementar poate avea una din valorile: true, false, null. Valoarea null se
obine dac unul din operazii utilizai are valoarea null. Valorile de adevr pentru operatorii
not, and, or sunt date n continuare:
true false null
not false true null

and true false null or true false null
true true false null true true true true
false false false false false true false null
null null false null null true null

Din aceast succesiune de valori se pot selecta toate cmpurile din toate tabelele (apare
"*" dup numele comenzii), sau se pot construi cmpuri ce au ca valoare rezultatul unor
expresii. Cmpurile cu aceeai denumire n tabele diferite se pot califica prin numele sau
alias-ul tabelelor surs. Numelecmpului sau expresiei din tabelul rezultat este stabilit
automat de sistem (n functie de expresia ce-l genereaz), sau se poate preciza prin clauza AS
ce urmeaz expresiei (sau cmpului). In acest fel putem construi valori pentru o nou
nregistrare ntr-un tabel_final.
Expresiile se precizeaz cu ajutorul operanzilor (cmpuri, rezultatul unor funcii) i a
operatorilor corespunztori tipurilor de operanzi.
In tabelul final se pot include toate sau numai o parte din nregistrri, dup cum e
precizat printr-un predicat ce apare n faa listei de coloane::
- ALL - toate nregistrrile
- DISTINCT - numai nregistrrile distinte
- TOP n - primele n nregistrri
- TOP n PERCENT - primele n% nregistrri
Inregistrrile din "tabelul final" se pot ordona cresctor (ASC) sau descresctor
(DESC) dup valorile unor cmpuri, precizate n clauza ORDER BY. Cmpurile se pot
preciza prin nume sau prin poziia lor (numrul cmpului) n lista de cmpuri din comanda
SELECT (precizarea prin poziie este obligatorie atunci cnd se dorete sortarea dup
valorile unei expresii). Ordinea cmpurilor din aceast clauz precizeaz prioritatea cheilor
de sortare.
Mai multe nregistrri consecutive din "tabelul final* pot fi grupate ntr-o singur
nregistrare, deci un grup de nregistrri se nlocuiete cu o singur nregistrare. Un astfel de
grup este precizat de valorile comune ale cmpurilor ce apar n clauza GROUP BY.
"Tabelul nou" se sorteaz (automat de ctre sistem) creasctor dup valorile cmpurilor din
53
GROUP BY. Inregistrrile consecutive din fiierul astfel sortat, ce au aceeai valoare pentru
toate cmpurile din GROUP BY, se nlocuiesc cu o singur nregistrare. Prezena unei astfel
de nregistrri poate fi condiionat de valoarea adevrat pentru o condiie ce se trece n
clauza HAVING.
Pentru grupul de nregistrri astfel precizat (deci pentru o mulime de valori) se pot
folosi urmtoarele funcii:
-
|
|
.
|

\
|
(

)
`

cmp
DISTINCT
ALL
AVG sau AVG([ALL]) expresie)
Pentru grupul de nregistrri se iau toate valorile (cu ALL, care este i valoarea implicit) sau
numai valorile distincte (apare DISTINCT) ale cmpului sau expresiei numerice precizate i
din aceste valori se determin valoarea medie.
-
|
|
|
.
|

\
|

)
`

cmp
DISTINCT
ALL
*
COUNT
Aceast funcie determin numrul de nregistrri din grup (apare '*'), numrul de valori ale
unui cmp (apare ALL, identic cu '*'), sau numrul de nregistrri distincte din grup (cu
DISTINCT).
-
|
|
.
|

\
|
(

)
`

cmp
DISTINCT
ALL
SUM sau SUM([ALL]) expresie)
Pentru nregistrrile din grup se face suma valorilor unui cmp sau ale unei expresii numerice
(deci numrul de termeni este dat de numrul de nregistrri din grup) sau suma valorilor
distincte ale cmpului.
-
|
|
.
|

\
|
(

)
`

)
`

cmp
DISTINCT
ALL
MIN
MAX
sau
)
`

MIN
MAX
([ALL]) expresie)
Pentru fiecare nregistrare din grup se determin valoarea unei expresii sau cmp i se afl
valoarea maxim sau minim dintre aceste valori.
Cele cinci funcii amintite mai sus (AVG, COUNT, SUM, MIN, MAX) pot apare att
n expresiile ce descriu cmpurile din fiierul rezultat, ct i n clauza HAVING. Deoarece
aceste funcii se aplic unui grup de nregistrri, n comada SELECT acest grup trebuie
generat de clauza GROUP BY. Dac aceast clauz lipsete, atunci ntregul "tabel final"
constituie un grup, deci tabelul rezultat va avea o singur nregistrare.
In general nu este indicat selectarea cmpurilor singure (fr rezultat al funcilor
amintite) dect numai dac au fost trecute n GROUP BY. Dac totui apar, i aceast
folosire nu produce eroare, atunci se ia o valoare oarecare, pentru o nregistrare din grup.
Dou tabele cu acelai numr de cmpuri (coloane) i cu acelai tip pentru valorile
cmpurilor aflate pe aceleai poziii se pot reuni ntr-un singur tabel obinut cu ajutorul
operatorului UNION. Din tabelul rezultat obinut se pot pstra toate nregistrrile (apare
ALL) sau numai cele distincte (nu apare ALL). Clauza ORDER BY poate apare numai
pentru ultima selecie. Nu se pot combina subselecii prin clauza UNION.
Intre dou rezultate obinute cu instruciuni SELECT se poate folosi operatorul
INTERSEC sau EXCEPT (sau MINUS).
54
Clauzele din instruciunea SELECT trebuie s fie n ordinea: lista_expresii FROM ...
WHERE ... HAVING ... ORDER BY ...
O comand se poate memora n baza de date ca o component numit view. Definirea
este:
CREATE VIEW nume_view AS comanda_SELECT

Bibliografie
[Da04] Date C. J., An Introduction to Database Systems, Addison-Wesley, 2004.
[[Mo08] Molima H.G., Ullman J., Widom J., Database Systems: The Complete Book,
Addison-Wesley + Prentice-Hall, 2008
(http://infolab.stanford.edu/~ullman/dscb.html)
Ra98] Ramakrishnan R,. Database Management Systems, WCB McGraw-Hill, 1998.
[Si02] Silberschatz A., Kortz H., Sudarshan S., Database System Concepts, McGraw-Hill,
2002.
[Ta03] mbulea L., Baze de date, Facultatea de Matematica i Informatic, Centrul de
Formare Continu i nvmnt la Distan, Cluj-Napoca, 2003.

55

5. Sisteme de operare

5.1. Structura i funciile SO

5.1.1. Strile unui proces i principalele funcii ale SO

Menirea unui SO, indiferent de tipul lui, este pe de o parte de a facilita accesul la sistem a
unuia sau mai multor utilizatori, iar pe de alt parte de a asigura o exploatare eficient a
echipamentului de calcul. Vom ncerca s artm mai n detaliu care sunt funciile posibile
ale unui sistem, independent de tipul acestuia. Desigur, dependent de tip va fi ponderea n
cadrul sistemului a uneia sau alteia dintre funcii. Printr-un proces vom nelege un calcul
care poate fi efectuat concurent cu alte calcule.

S-au proiectat i se proiecteaz nc multe tipuri de SO. Fiecare dintre acestea trebuie s aib
ca obiective fundamentale:
- optimizarea utilizrii resurselor;
- minimizarea efectului uman de programare i exploatare;
- automatizarea operaiilor manuale n toate etapele de pregtire i exploatare a SC;
- creterea eficienei utilizrii SC prin scderea preului de cost al prelucrrii datelor.

Sintetiznd strile proceselor sub diverse sisteme de operare, putem defini strile unui proces
ntr- un sistem de operare. Aceste stri sunt:
- HOLD proces pregtit pentru intrarea n sistem;
- READY procesul este n memorie i este gata de a fi servit de (un) procesor;
- RUN un procesor execut efectiv instruciuni (main) ale procesului;
- WAIT procesul ateapt terminarea unei operaii de intrare / ieire;
- SWAP imaginea procesului este evacuat temporar pe disc;
- FINISH procesul s-a terminat, trebuie livrate doar rezultatele.

HOLD este starea unui proces la un sistem serial n care procesului i sunt citite datele de
lansare din cadrul lotului din care face parte, se face o analiz preliminar a corectitudinii lor
i apoi procesul este depus ntr-o coad pe disc (numit HOLD) spre a fi preluat spre
prelucrare. De obicei, aceste sisteme au o component specializat pentru astfel de prelucrri
SPOOL-ing de intrare (Simultaneous Peripheral Operations OnLine).

FINISH este, de asemenea, stare a unui proces la un sistem serial. Procesul se execut i
rezultatele lui sunt plasate pe disc ntr-o coad FINISH. Dup terminare, acestea vor fi listate,
fie pe o imprimant local, fie pe una aflat la distan. Componenta din SO care face preia
din coada FINISH i listeaz se numete SPOOL-ing de ieire.

READY este starea n care un proces se afl n memoria intern dar nu este servit de
procesor. Este posibil ca el s fi fost servit parial, dar pe moment s fie suspendat n
defavoarea altui proces, urmnd s i se continue execuia mai trziu.
56

SWAP este starea n care un proces este evacuat temporar ntr-un spaiu rezervat pe disc
(SWAP) pentru a face temporar loc altui proces n memoria intern. Ulterior procesul va fi
rencrcat n memoria intern i i se va continua execuia.

WAIT este starea n care un proces a cerut executarea unei operaii de intrare / ieire. Ct
timp procesul ateapt s se termine operaia, ced altor procese procesorul.

RUN este starea principal, aceea n care procesorul execut efectiv instruciuni main ale
programului procesului. Intr-un sistem monoprocesor doar un singur proces se afl n starea
RUN. Dac sistemul are n procesoare, atunci maximum n procese se vor afla n starea RUN.

Aceste stri nu se vor ntlni la toate tipurile de sisteme de operare. De exemplu, la un sistem
monoutilizator (vezi 8.1)nu va fi starea SWAP, numai sistemele seriale au strile HOLD i
FINISH etc.

Principalele funcii ale SO sunt legate de aciunile acestuia pentru tranziia ntre diverse stri
ale procesului. In figura alturat sunt schematizate strile unui proces. In dreptul fiecrei
tranziii sunt trecute principalele aciuni efectuate de ctre SO. Caracteristicile fiecreia dintre
cele ase stri posibile (HOLD, READY, RUN, SWAP, WAIT, FIHISH) le-am prezentat n
seciunea precedent.

Figura 5.1 Strile unui proces i aciunile SO aferente

Aciunile SO sunt executate de ctre componenta nucleu a sistemului de operare. La nivelul
componentei user, o mare parte dintre aciunile SO sunt focalizate mai ales n sprijinul
utilizatorului pentru dezvoltarea de programe, adic de asistare a userului la trecerea
programului prin diverse faze.

57
5.1.2. Structura general a unui SO

In aceast seciune ncercm s oferim o imagine asupra structurii unui SO ipotetic. Un astfel
de sistem nu va fi regsit nicieri n practic, ns structura fiecrui SO real va fi apropiat de
a acestuia. Evident, n funcie de tipul de SO real, unele dintre prezentele componente vor fi
atrofiate sau vor lipsi cu desvrire, iar altele vor putea fi eventual mult mai dezvoltate dect
aici. Fr pretenia de "gen-proxim" i "diferen-specific", ncercm s definim principalele
noiuni, structuri i componente cu care opereaz orice SO.

S trecem acum la structura propriu-zis.

5.1.2.1. Structura unui SO

Schema general a unui SO este ilustrat n figura de mai jos.

Figura 5.2 Structura general a unui SO

Orice SO conine dou pri mari: partea de control i partea de servicii.

PARTEA DE CONTROL este n legtur direct cu operatorul uman i indirect cu
utilizatorul. SO execut n mod master componentele acestei pri. Principalul ei rol este de a
realiza legtura cu SC, deci cu echipamentul hard.

PARTEA DE SERVICIU lucreaz n mod slave, folosind facilitile prii de control. Este n
legtur direct cu utilizatorul i indirect cu operatorul uman. Sarcina de baz a ei este de a
ine legtura cu utilizatorul, facilitndu-i acestuia accesul la resursele SC i SO.

In continuare vom descrie succint rolul fiecrei componente.

58
5.1.2.2. Partea de control

INTRERUPERI. Un ansamblu de rutine, fiecare dintre ele fiind activat la apariia unui
anumit semnal fizic de ntrerupere. Corespunztor, SO efectueaz aciunile aferente
ntreruperii respective. Semnificaia conceptului de ntrerupere este descris n fiecare manual
de arhitectura calculatoarelor.

Funcionarea concret a componentei (sistemului) de ntreruperi depinde foarte mult de
particularitile SC, deci nu se preteaz prea bine la abordri cu caracter general. Pe de alt
parte, detalii despre aceste componente intereseaz n primul rnd pe programatorii i
inginerii de sistem, mai puin pe utilizatorii obinuii., crora ne adresm noi. Din aceste
motive vom schia numai mecanismul de funcionare a ntreruperilor.
Fiecare tip de ntrerupere are asociat o locaie fix de memorie. In aceast locaie se afl o
adres. Aceast adres indic locul din memorie la care se afl o secven de instruciuni,
numit handler, secven care deservete ntreruperea respectiv.

La apariia semnalului de ntrerupere, dup ce instruciunea main n curs s-a executat, se
execut, n aceast ordine, urmtoarele activiti:
- se salveaz ntr-o zon de memorie starea programului n curs de desfurare;
- se activeaz handlerul asociat ntreruperii respective;
- handlerul execut aciunile necesare servirii ntreruperii;
- se restaureaz starea programului care a fost ntrerupt.

GESTIUNE PROCESE. Creeaz procese i rezolv problemele privind cooperarea i
concurena acestora. La terminarea unui proces, acesta este ters din sistem. Asupra
conceptului de proces vom mai reveni.

DISPECER PROCESOARE. La sistemele multiprocesor, repartizeaz sarcinile de calcul
solicitate de procese, procesoarelor care sunt libere i care pot executa sarcinile cerute.

GESTIUNEA MEMORIEI. Aloc necesarul de memorie intern solicitat de procese i
asigur protecia memoriei interprocese. Componenta este parial realizat prin hard i parial
este realizat soft, de ctre o component a SO. Vom reveni i asupra problemelor legate de
gestiunea memoriei.

I/O LA NIVEL FIZIC. Asigur efectuarea operaiilor elementare de I/O cu toate tipurile de
periferice din sistem realiznd, acolo unde este posibil, desfurarea simultan a uneia sau
mai multor operaii I/O, cu activitatea procesorului central. Aceast component este, de
asemenea, puternic dependent hard, n special de multitudinea de echipamente periferice
conectate la sistem. Aa dup cum am vzut, exist nite rutine de interfa numite drivere,
care realizeaz compatibilizarea conveniilor de I/O ntre SC i echipamentele periferice.
Driverele printre altele, fac parte din aceast component. Vom reveni ntr-o seciune viitoare
cu detalii.

GESTIUNEA FISIERELOR. O colecie de module prin intermediul crora se asigur:
deschiderea, nchiderea i accesul utilizatorului la fiierele rezidente pe diferite suporturi de
informaii. Component de baz a SO, este cel mai des invocat de ctre utilizatori i de ctre
operator. Vom reveni i asupra ei ntr-un capitol special.

59
PLANIFICAREA LUCRARILOR SI ALOCAREA RESURSELOR. Resursele unui SC se
mpart n: resurse fizice (procesoare, memorie intern, periferice etc.) i resurse logice
(proceduri comune, tabele ale sistemului etc.). Fiecare proces solicit la un moment dat
anumite resurse. Prin aceast component a SO se asigur planificarea proceselor astfel, nct
ele s poat obine de fiecare dat resursele necesare, n mod individual sau partajate cu alte
procese. Elemente ale planificrii se rsfrng, dup cum vom vedea mai trziu, asupra
gestiunii proceselor, gestiunii memoriei, intrrilor si ieirilor etc. Atunci cnd vom discuta
despre procese, memorie i I/O la nivel fizic vom aborda i problematica planificrilor i a
alocrilor de resurse.

GESTIUNEA TEHNICA a SO. Tine evidena erorilor hard aprute la echipamentele SC. La
cerere, furnizeaz informaii statistice asupra gradului de utilizare a componentelor SC.

GESTIUNEA ECONOMICA a SO. Tine evidena utilizatorilor care folosesc sistemul,
lucrrile executate de ctre ace- tia i resursele consumate de aceste lucrri (timpi de rulare,
memorie intern ocupat, echipamente i supori folosii etc). Periodic (zilnic, lunar, anual)
editeaz liste cuprinznd lucrrile rulate i facturi de plat ctre beneficiari.

5.1.2.3. Partea de servicii

COMPILATOARELE sunt programe care traduc texte surs scrise n limbaje de nivel nalt
(C, C++, Java, FORTRAN, COBOL, Pascal, Ada etc.) n limbaj main. La aceast or exist
o mare varietate de tehnici de compilare, avnd ca nucleu teoria limbajelor formale. Exist de
asemenea sisteme automate de elaborare a diverselor componente ale compilatorului.
Rezultatul unei compilri este un modul obiect memorat ntr-un fiier obiect.

ASAMBLORUL este un program care traduce texte scrise n limbajul de asamblare propriu
SC ntr-un modul obiect. Din punct de vedere al SO problemele legate de asamblor sunt
incluse n problemele compilatoarelor.

LINK-EDITORUL sau EDITORUL DE LEGATURI. Grupeaz unul sau mai multe module
obiect, mpreun cu subprograme de serviciu din diverse biblioteci, ntr-un program
executabil. De cele mai multe ori aceast component ofer posibilitatea segmentrii
programelor mari, adic posibilitatea ca dou componente diferite a programului s poat
ocupa n execuie, la momente diferite de timp, aceeai zon de memorie. Rezultatul editrii
de legturi este un fiier executabil.

LOADER (PROGRAM DE INCARCARE) este un program al SO care are trei sarcini:
- citirea unui program executabil de pe un anumit suport;
- ncrcarea acestuia n memorie;
- lansarea lui n execuie.

Dac programul executabil este segmentat, atunci loaderul ncarc la nceput numai
segmentul rdcin al programului, dup care, la cerere, n timpul execuiei, ncarc de
fiecare dat segmentul solicitat n memorie.

INTERPRETOR este un program care execut pas cu pas instruciunile descrise ntr-un
anumit limbaj. Tehnica interpretrii este aplicat la diferite limbaje de programare, cum ar fi
60
Java, BASIC, LISP, PROLOG etc. Pentru SO, cea mai important categorie de interpretoare
sunt "interpretoarele de comenzi". Astfel, avem interpretoarele sh si bash sub sub Unix i
COMMAND.COM de pe platformele Microsoft.

MACROPROCESOR (PREPROCESOR) este un program cu ajutorul cruia se transform o
machet de program, pe baza unor parametri, ntr-un program surs compilabil. Spre
exemplu, fie macheta:
MACRO ADUNA &1, &2, &3
LOAD &1
ADD &2
STORE &3
ENDMACRO

Dac ntr-un program (dintr-un limbaj de asamblare) se scrie:
ADUNA A, B, C

atunci prin macroprocesoare se genereaz:
LOAD A
ADD B
STORE C

Practic, macroprocesarea este tehnica prin care se realizeaz o scriere mai compact a
programelor i o posibil parametrizare a acestora pentru realizarea comod a unor
implementri nrudite.

Astfel de macroprocesoare exist la toate SO moderne. Remarcm n mod deosebit
interpretorul de comenzi "shell" de sub Unix, descris n 2.2. Acesta dispune, printre altele, de
cele mai puternice faciliti de macroprocesare dintre toate interpretoarele de comenzi
cunoscute.

Unele limbaje au prevzute n standardele lor specificaii de macroprocesare. In acest sens
amintim preprocesorul "C" care trateaz n aceast manier liniile care ncep cu "#" i
construciile "typedef", precum i facilitile generice ale limbajului ADA .

EDITORUL DE TEXTE este un program interactiv destinat introducerii i corectrii textelor
surs sau a unor texte destinate tipririi. Orice SO interactiv dispune cel puin de cte un
astfel de editor de texte. Pn vom ajunge la capitolul dedicat editoarelor de texte, s
enumerm cteva editoare "celebre" unele prin vechimea lor, iar altele prin performanele lor:
- ed i vi sub Unix;
- Notepad i EDIT sub Windows;
- xedit i emacs de sub mediul X WINDOWS.

RUTINELE DE DEPANARE (DEPANATOARELE) asist execuia unui program utilizator
i-l ajut s depisteze n program cauzele erorilor aprute n timpul execuiei lui. Intreaga
execuie a programului utilizator se face sub controlul depanatorului. La prima apariie a unui
eveniment deosebit n execuie (depire de indici, adres inexistent, cod de operaie
necunoscut etc.) depanatorul primete controlul. De asemenea, el poate primi controlul n
locuri marcate n prealabil de ctre utilizator. Un astfel de loc poart numele de breakpoint.
La primirea controlului, depanatorul poate afia valorile unor variabile sau locaii de
memorie, poate reda, total sau parial istoria de calcul, poate modifica valorile unor variabile
61
sau locaii de memorie etc. Unele depanatoare mai performante permit execuia reversibil,
concept tratat teoretic dar mai puin aplicat practic. La aceast or sunt cunoscute dou tipuri
de depanatoare:
- depanatoare main;
- depanatoare simbolice.

Depanatoarele main opereaz cu elemente cum ar fi: adrese fizice, configuraii de bii,
locaii de memorie etc. Fiecare SO dispune de cte un astfel de instrument de depanare.

Depanatoarele simbolice opereaz cu elemente ale textelor surs ale programelor. Intlnim
aici termeni ca linie surs, nume de variabil, nume de procedur, stiv de apel a procedurilor
etc. Evident, depanatoarele simbolice sunt mult mai tentante pentru utilizator, i este bine c
este aa. De obicei, un astfel de depanator nsoete implementarea unui limbaj de programare
de nivel nalt. Primul i cel mai rspndit limbaj la care au fost ataate depanatoare simbolice
este limbajul Pascal. Amintim aici depanatorul Pascal de pe lng implementarea TURBO
Pascal, un depanator simbolic complet interactiv, cu o grafic destul de bun pentru
momentul implementrii lui i cu faciliti puternice. Firma BORLAND, un adevrat vrf de
lance n acest domeniu, a realizat printre altele produsul TURBO DEBUGER, care
recunoate n vederea depanrii toate limbajele pentru care s-au realizat medii TURBO:
Pascal, "C", limbajul de asamblare TASM, Basic, PROLOG etc. Produsul lucreaz att
simbolic, ct i la nivel main.

BIBLIOTECARUL este un program cu ajutorul cruia utilizatorul poate comanda pstrarea
programelor proprii n fiiere speciale de tip bibliotec, poate copia programe dintr-o
bibliotec n alta, terge, insereaz i modific programe n aceste biblioteci. Exemple de
programe biblioteci sunt LBR sub MS-DOS, ar (archive) sub Unix etc.

MEDIILE DE PROGRAMARE sunt componente complexe destinate n principal activitii
de dezvoltare de programe. O astfel de component nglobeaz, relativ la un limbaj, cel puin
urmtoarele subcomponente:
- editor de texte;
- compilator interactiv;
- compilator serial (clasic);
- editor de legturi sau un mecanism echivalent acestuia destinat creerii de programe
executabile;
- interpretor pentru execuia rezultatului compilrii;
- depanator, de regul simbolic;
- o component de legtur cu mediul exterior, de regul cu SO sub care se lucreaz.

De regul, filozofia de manevrare a mediului are un caracter unitar, este simpl i puternic.
Facilitile grafice ale acestor medii sunt destul de mult utilizate, fcnd deosebit de agreabil
lucrul cu ele.

SUPRAFETELE DE OPERARE au aprut tot la calculatoarele IBM-PC i a celor
compatibile cu ele. Ele au rolul principal de a "mbrca" sistemul de operare (Windows sau
Unix), pentru a-i face mai uoar operarea. Iniial au fost destinate utilizatorilor
neinformaticieni. La aceast or, nici profesionitii nu se mai pot "dezlipi" de o suprafa de
operare cu care s-a obinuit s lucreze. De regul, suprafeele de operare nlocuiesc limbajul
de control (de comand) al SO respectiv. Utilizatorul, n loc s tasteze o comand a SO
respectiv, poart un dialog cu suprafaa de operare, iar la finele dialogului suprafaa
62
genereaz sau execut comanda respectiv. Ponderea dialogului o deine suprafaa nsi,
utilizatorul rspunde de regul prin apsarea uneia sau maximum a dou taste, sau unul sau
dou "clicuri" cu un mouse. Suprafaa deine i un mecanism deosebit de puternic de HELP,
conducnd utilizatorul din aproape n aproape spre scopul dorit. Dei se adreseaz n primul
rnd neinformaticienilor, ele sunt din ce n ce mai mult folosite i de ctre specialiti.

O remarc special trebuie fcut pentru WINDOWS, care deine un mecanism propriu de
dezvoltare a unor aplicaii.

Din raiuni impuse de standarde, sub Unix se folosete aproape peste tot suprafaa
X-WINDOWS.

Din scurta prezentare a componentelor principale ale unui SO rezult caracterul modular al
SO i organizarea lui ierarhic. Modularitatea este termenul prin care se descrie partiionarea
unui program mare n module mai mici, cu sarcini bine precizate. Caracterul ierarhic este
reflectat n faptul c orice component acioneaz sub controlul componentelor interioare
acesteia, apelnd primitivele oferite de acestea. Aceste faciliti asigur o implementare mai
uoar a SO, o nelegere mai facil a SO de ctre diverse categorii de utilizatori, o ntreinere
i depanare mai uoar a sistemului i creeaz premisele simulrii lui pe alt sistem.

63

5.2. Interpretoare ale fiierelor de comenzi

5.2.1. Funcionarea unui interpretor de comenzi shell

Un interpretor de comenzi (shell) este un program special care furnizeaz o interfa ntre
nucleul sistemului de operare Unix (kernel-ul) i utilizator. Din aceast perspectiv, a
asigurrii legturii ntre utilizator i sistem, un shell poate fi privit diferit:

1. limbaj de comand care asigur interfaa dintre calculator i utilizator. In momentul n
care un utilizator i deschide o sesiune de lucru, n mod implicit, un shell se
instaleaz ca interpretor de comenzi. Shell-ul afieaz la ieirea standard (asociat de
obicei unui terminal) un prompter, invitnd astfel utilizatorul s introduc comenzi
sau s lanseze n execuie fiiere de comenzi, eventual parametrizate.

2. limbaj de programare, ce are ca element de baz (element primitiv) comanda Unix
(similar semantic cu instruciunea de atribuire din limbajele de programare). Ca i
element primitiv de dirijare a succesiunii elementelor de baz este valoarea codului
de retur al ultimei comenzi executate: valoarea 0 nseamn true, valoare nenul
nseamn false (corespondentul din limbajele de programare clasice este condiia).
Shell-urile dispun de conceptele de variabil, constant, expresie, structuri de control
i subprogram. Spre deosebire de alte limbaje de programare, expresiile cu care
lucreaz shell-urile sunt preponderent iruri de caractere. In ceea ce privete cerinele
sintactice, acestea au fost reduse la minim prin eliminarea parantezelor de delimitare a
parametrilor, a diferitelor caractere de separare i terminare, a declaraiilor de
variabile, etc.

un shell lansat n execuie la deschiderea unei sesiuni de lucru va rmne activ pn la
nchiderea respectivei sesiuni. Odat instalat, acesta lucreaz conform algoritmului urmtor:

CtTimp (nu s-a nchis sesiunea)
Afieaz prompter;
Citete linia de comand;
Dac ( linia se termin cu '&' ) atunci
Creaz un proces i-i d spre execuie comanda
Nu ateapt ca execuia s se termine
Altfel
Creaz un proces i-i d spre execuie comanda
Ateapt s se termine execuia comenzii
SfDac
SfCtTimp

Este important s remarcm, din algoritmul de mai sus, cele dou moduri n care o comand
poate fi executat:
- modul foreground - execuie la vedere. In acest gen de execuie sh lanseaz execuia
comenzii, ateapt terminarea ei dup care afieaz din nou prompterul pentru o nou
comand. Acesta este modul implicit de execuie al oricrei comenzi Unix.
64
- modul background - execuie n fundal, ascuns. In acest gen de execuie sh lanseaz
procesul care va executa comanda, dar nu mai ateapt terminarea ei ci afieaz
imediat prompterul, oferind utilizatorului posibilitatea de a lansa imediat o nou
comand. Comada care se dorete a fi lansat n background trebuie s se ncheie cu
caracterul special '&'.

Intr-o fereastr (sesiune) de lucru Unix se pot rula oricte comenzi n background i numai
una n foreground. Iat, spre exemplu, trei astfel de comenzi, dou lansate n background - o
copiere de fiier (comanda cp) i o compilare (comanda gcc) i una n foreground - editare
de fiier (comanda vi):
cp A B &
gcc x.c &
vi H

5.2.2. Programarea n shell

5.2.2.1. Scurt prezentare a limbajului sh

In cele ce urmeaz vom prezenta gramatica limbajului sh cel mai simplu shell de sub Unix.
Vom pune n eviden principalele categorii sintactice, semantica / funcionalitatea fiecrei
astfel de categorii se deduce uor din context.

Vom considera urmtoarele convenii, pe care le folosim doar n scrierea regulilor gramaticii:
- O categorie gramatical se poate defini prin una sau mai multe alternative de definire.
Alternativele se scriu cte una pe linie, ncepnd cu linia de dup numele categoriei
gramaticale, astfel:
categorieGramatical:
alternativa_1 de definire
- - - -
alternativa_n de definire
- [ ]? Semnific faptul c, construcia dintre paranteze va aprea cel mult odat.
- [ ]+ Semnific faptul c, construcia dintre paranteze va aprea cel puin odat.
- [ ]* Semnific faptul c, construcia dintre paranteze poate s apar de 0 sau mai multe
ori.

Folosind aceste convenii, sintaxa limbajului sh (n partea ei superioar, fr detalii) este
descris n fig. 2.2.

Semnificaia unora dintre elementele sintactice din fig. 2.2 este:
- cuvnt: secven de caractere diferite de caracterele albe (spaiu, tab)
- nume: secven ce ncepe cu liter i continu cu litere, cifre, _ (underscore)
- cifra: cele 10 cifre zecimale

O comanda sh poate avea oricare dintre cele 9 forme prezentate. Una dintre modalitile de
definire este cea de comandElementar, unde o astfel de comand elementar este un ir de
65
elemente, un element putnd fi definit n 10 moduri distincte. O legarePipe este fie o singur
comand, fie un ir de comenzi separate prin caracterul special '|'. In sfrit, listaCom este o
succesiune de legarePipe separate i eventual terminate cu simboluri speciale.

Se poate observa c, n conformitate cu gramatica de mai sus, sh accept i construcii fr
semantic! De exemplu, comand poate fi o comandElementar, care s conin un singur
element, format din >&-;. O astfel de linie este acceptat de sh, fiind corect din punct de
vedere sintactic, dei nu are sens din punct de vedere semantic.

Shell-ul sh are un numr de 13 cuvinte rezervate. Lista acestora este urmtoarea:
if then else elif fi
case in esac
for while until do done

Structurile alternative if i case sunt nchise de construciile fi, respectiv esac, obinute prin
oglindirea cuvintelor de start. In cazul ciclurilor repetitive, sfritul acestora este indicat prin
folosirea cuvntului rezervat done. Nu s-a folosit construcia similar corespunztoare lui do,
deoarece od este numele unui comenzi clasice Unix.

Incheiem acest subcapitol cu prezentarea sintaxei unor construcii rezervate, precum i a
unor caractere cu semnificaie special n shell-ul sh.
a) Construcii sintactice:
| legare pipe
&& legare andTrue
|| legare orFalse
; separator / terminator comand
;; delimitator case
(), {} grupri de comenzi
< << redirectri intrare
> >> redirectri ieire
&cifra, &- specific intrare sau ieire standard
b) Machete i specificri generice:
* nlocuiete orice ir de caractere
? nlocuiete orice caracter
[...] nlocuiete cu orice caracter din ...
Observaie: aceste machete i specificri generice nu trebuie confundate cu convenia
propus la nceputul subcapitolului pentru scrierea gramaticii limbajului sh


comand:
comandElementar
( listaCom )
{ listaCom }
if listaCom then listaCom [ elif listaCom then listaCom ]* [ else listaCom ]? fi
case cuvant in [ cuvant [ | cuvant ]* ) listaCom ;; ]+ esac
for nume do listaCom done
for nume in [ cuvant ]+ do listaCom done
while listaCom do listaCom done
until listaCom do listaCom done
66

comandElementar:
[ element ]+

listaCom:
legarePipe [ separator legarePipe ]* [ terminator ]?

legarePipe:
comanda [ | comanda ]*

element:
cuvnt
nume=cuvnt
>cuvnt
<cuvnt
>>cuvnt
<<cuvnt
>&cifra
<&cifra
<&-
>&-

separator:
&&
||
terminator

terminator:
;
&

5.2.2.2. Variabile sh i mecanisme de substituie

Shell-urile permit dou tipuri de substituii: substituia cu ieire standard i substituia cu
valoarea unei variabile shell.

O construcie avnd urmtoarea form:

`sir`

adic un ir de caractere cuprins ntre dou caractere accent grav sau apostrof invers (`)
reprezint un mecanism de substituie care acioneaz astfel: interpretorul de comenzi shell
implicit va interpreta irul dintre cele dou apostroafe inverse ca pe o comand Unix pe care
o va executa. Intreaga construcie, inclusiv apostroafele inverse, va fi nlocuit cu rezultatul
execuiei acestei comenzi.

De exemplu, dac directorul curent este /home/user1, urmtoarea comand lansat n
linia de comand:
67
$ echo Va aflati in directorul `pwd`!

va afia la ieirea standard:
$ Va aflati in directorul /home/user1!

Dac n schimb se lanseaz:
$ echo Va aflati in directorul pwd!

rezultatul execuiei va fi:
$ Va aflati in directorul pwd!

Variabilele shell sunt nume predefinite de shell-ul curent sau definite de ctre utilizator, ale
cror valori sunt iruri de caractere. Chiar dac ntr-un anumit context o variabil este
interpretat ca un numr, reprezentarea acesteia se face printr-un ir de cifre zecimale scrise
n cod ASCII.

Definirea unei variabile coincide cu atribuirea unei valori iniiale pentru ea i se face printr-o
construcie de urmtoarea form:

$ nume=cuvant

In urma evalurii, shell-ul creeaz o variabil denumit nume, avnd ca valoare irul de
caractere indicat prin cuvant. Trebuie precizat c nainte i dup semnul = nu trebuie s
apar spaiu! Dac se dorete ca n irul cuvant s apar i unul sau mai multe spaii, atunci
acestea trebuie scrise folosind mecanismul de evitare.

O variabil shell este local procesului n care a fost definit. Cu toate acestea exist
posibilitatea ca ea s fie motenit de ctre procesele fiu ale procesului curent, dac n
procesul care definete variabila apare o declaraie de forma:

$ export nume

unde nume indic variabila care se dorete a fi motenit de ctre procesele fiu.

Substituirea valorii unei variabile shell se poate specifica n mai multe moduri:
$nume
${nume}
${nume-cuvant}
${nume=cuvant}
${nume+cuvant}
${nume?cuvant}

Varianta aleas depinde de specificul situaiei. Ne vom opri numai la primele dou modaliti
prezentate, care dau ca rezultat valoarea variabilei sau irul vid dac variabila nu este definit.
A doua form de specificare se folosete n cazul n care prima modalitate nu permit
identificarea unic a numelui de variabil (de exemplu cnd acesta apare ntr-un ir de
caractere).
Prezentm n continuare cteva exemple simple de utilizare a acestor construcii. Considerm
c de la tastatur se introduc succesiv urmtoarele trei linii:
$ Fruct=Mar
68
$ aperitiv=tuica\ batrana
$ echo Dupa $aperitiv mananca $Fruct

In momentul execuiei comenzii echo, care cere afiarea unei linii, va avea loc i substituirea
variabilelor Fruct i aperitiv, cu valorile lor, rezultatul fiind:
Dupa tuica batrana mananca Mar

Dac n schimb se lanseaz comanda:
$ echo Salba de $Fructgaritare

rezultatul afiat va fi:
Salba de

deoarece shell-ul va caut s substituie valoarea variabilei Fructgaritar, care nu este
definit i drept urmare are ca valoare irul vid. Pentru a evita astfel de situaii se folosete a
doua form de specificare a unei substituii:
$ echo Salba de ${Fruct}garitare

Rezultatul execuiei comenzii este:
Salba de Margaritare

Orice proces creat de ctre shell motenete o serie de variabile standard, cu nume
predefinite. Totalitatea acestor variabile formeaz aa-numitul mediu Unix al procesului
(environment). In continuare vom prezenta cteva dintre aceste variabile:

HOME indic directorul gazd al utilizatorului, cel n care intr automat la deschiderea sesiunii
de lucru.

PATH indic cile de cutare ale fiierelor executabile. In momentul lansrii unei comenzi,
shell-ul caut n fiecare dintre cile specificate n PATH un fiier cu numele acesteia.
Separarea cilor n irul PATH se face prin simbolul : (dou puncte), iar cutarea se face de la
stnga spre dreapta. In momentul n care se gsete prima potrivire cutarea se oprete.
Trebuie precizat c operaia de cutare se face numai n cile definite n PATH, nu i n
directorul curent, exceptnd cazul n care acesta este adugat n PATH.

Utilizatorul poate s modifice dup dorin valoarea acestei variabilei. De exemplu, pentru a
aduga la cile deja existente directorul curent, directorul gazd i subdirectorul bin al
acestuia, se va lansa:
$ PATH=${PATH}:.:${HOME}:${HOME}/bin

LOGNAME conine numele sub care utilizatorul a deschis sesiunea de lucru (prin login, telnet,
ssh).

SHELL are ca valoare tipul de interpretor shell folosit.

TERM conine tipul de terminal folosit.

69
MAIL indic fiierul care conine pota electronic a utilizatorului. Dac variabila de mediu
MAILCHECK nu este setat, shell-ul curent va informa utilizatorul n momentul n care un
nou mesaj este depus n fiierul specificat.

MAILCHECK fixeaz intervalul de timp la care se va face controlul existenei mesajelor
primite prin pota electronic.

MAILPATH permite precizarea unei liste de nume de fiiere separate prin caracterul : (dou
puncte) pe care shell-ul curent le va monitoriza pentru a sesiza primirea unui nou mesaj.
Fiecare nume de fiier poate fi urmat de semnul % i de un mesaj ce va fi afiat n momentul
n care s-a primit un mesaj nou (mesajul implicit este You have mail).

IFS conine separatorii shell pentru cuvinte. In mod implicit acetia sunt: spaiul, caracterul
<TAB> i retur de car.

PS1 conine prompterul principal Unix. Acesta difer n funcie de distribuie (de exemplu,
pentru shell-ul Bourne, prompterul implicit pentru utilizatorii obinuii este "$", respectiv "#"
pentru superuser).

Aa cum am vzut, o comand Unix are forma:

$ comanda arg1 arg2 ... argn

Dac presupunem c numim prin comanda numele unui fiier de comenzi (script) care va fi
interpretat de ctre shell-ul implicit, atunci att numele comenzii, ct i primele 9 (nou)
argumente, pot fi utilizate n mod direct n interiorul scriptului n maniera parametrilor
formali, aa cum se vede mai jos:

$ comanda arg1 arg2 ... arg9 arg10 ... argn
^ ^ ^ ... ^
| | | ... |
$0 $1 $2 ... $9

Astfel, $0 desemneaz comanda, n timp ce $i desemneaz argi (al i-lea argument din
linia de comand) unde i poate lua valori ntre 1 i 9 inclusiv. In cazul n care sunt mai
puin de 9 argumente, cele absente au ca valoare irul vid. Dac n schimb, comanda este
lansat cu mai mult de 9 argumente, se vor reine toate, dar la un moment dat vor putea fi
referite doar primele 9 prin intermediul construciilor de forma $1 pn la $9, plus numele
comenzii reinut n $0. De asemenea, tot n contextul unui script, urmtoarele construcii au
semnificaie special:
- $# ntoarce numrul argumentelor comenzii (numrul n de mai sus);
- $* indic toate argumentele liniei de comand, privite ca un singur string:
"$1 $2 . . . $n";
- $@ indic toate argumentele liniei de comand, ca succesiune de stringuri:
"$1" "$2" . . . "$n";
- $- indic argumentul ce conine opiunile liniei de comand;
- $? ntoarce codul de terminare (retur) al comenzii precedente (0 nseamn succes);
- $! indic numrul (PID al) ultimului proces lansat n background;
70
- $$ indic numrul (PID al) procesului printe.

5.2.2.3. Structura de control if din sh

Sintaxa structurii este urmtoarea:

if listaCom then listaCom [ elif listaCom then listaCom
]*
[ else listaCom ]? fi

Se poate vedea din specificarea sintaxei c n cadrul unei instruciuni if pot s apar ori de
cte ori perechi elif ... then .... De asemenea, nainte de sfritul instruciunii,
poate aprea, cel mult o dat, construcia else ....

Inainte de a explica modul de execuie, dorim s atragem atenia asupra unor aspecte lexicale.
Unele shell-uri pretind ca fiecare (sau numai unele) dintre cuvintele rezervate if, then,
elif, else, fi s fie primele cuvinte din linie. De aceea recomandm ca n programe
liniile if s apar astfel:
if listaCom
then listaCom
elif listaCom
then listaCom
- - - - - - - - - - - -
elif listaCom
then listaCom
else listaCom
fi

Lista de comenzi care urmeaz dup if, ca i listele de comenzi care urmeaz dup elif au
un dublu rol: de execuie a comenzilor din list i de fixare a valorii de adevr a execuiei. O
execuie are valoarea TRUE dac codul de retur al ultimei execuii din lista de comenzi are
valoarea zero. Execuia are valoarea FALSE dac codul de retur are valoare nenul.

Listele de comenzi de dup then, ca i lista de comenzi de dup else au doar valori de
execuie.

Succesiunea de evenimente care au loc la ntlnirea unei comenzi if este urmtoarea:
- Se execut lista de comenzi ce urmeaz dup if. Dac execuia fixeaz valoarea
TRUE, (condiia if este adevrat), atunci se execut lista de comenzi de dup then
i execuia lui if se termin (se trece la instruciunea care urmeaz dup fi). In caz
contrar (lista de comenzi de dup if fixeaz FALSE) se trece la pasul urmtor:
- Dac exist (una sau mai multe) construcii elif, atunci se execut, pe rnd, listele
de comenzi care urmeaz dup elif, pn cnd una dintre ele fixeaz valoarea
TRUE. Apoi se execut lista de comenzi de dup then - ul corespunztor i
execuia lui if se termin. In caz contrar (fie nu exist elif, fie toate listele de
comenzi de dup elif - uri au fixat FALSE) se execut pasul urmtor:
71
- Dac exist else atunci se execut lista de comenzi de dup else i execuia lui if
se termin. In caz contrar (nu exist else):
- Execuia lui if se termin i se trece la execuia comenzii ce urmeaz dup fi.

In continuare vom prezenta, n dou variante, un fiier de comenzi care afieaz liniile -
ordonate alfabetic - ale unui fiier text. Numele fiierului va fi dat ca prim argument al liniei
de comand. O prim variant este::

if [ $# -eq 0 ]
then echo "Trebuie dat un nume de fisier"
else sort <$1 | more
fi

Varianta prezentat controleaz doar dac s-a dat un argument la linia de comand. O
verificare mai amnunit este realizat n a doua variant:


if [ $# -eq 0 ]
then echo "Trebuie dat un nume de fisier"
elif [ ! \( -r $1 \) ]
then echo "Fisierul $1 nu exista"
else sort <$1 | more
fi

5.2.2.4. Structuri de control repetitive sh

Shell conine patru structuri repetitive: for n dou variante, while i until:

for nume
do
listaCom
done
for nume in [ cuvant ]+
do
listaCom
done
while listaCom
do
listaCom
done
until listaCom
do
listaCom
done

Construcia for
Aceast construcie este cel mai des folosit pentru structurile repetitive shell. Ea are dou
forme, ambele folosind o variabil shell de control indicat prin nume.

In prima form, variabila nume ia toate valorile parametrilor din linia de comand: $1, $2,
..., $#, (de fapt valorile sunt luate din variabila $@). Pentru fiecare dintre acestea, execut
comenzile din corpul ciclului: listaCom.

In forma a doua, cuvntul sau lista de cuvinte care urmeaz dup in desemneaz cuvinte
simple separate prin spaii, sau specificri generice care se expandeaz la numele tuturor
72
fiierelor din directorul curent care se potrivesc, rezultnd n final o list de elemente.
Variabila nume ia pe rnd ca valori aceste elemente i pentru fiecare dintre ele execut
corpul ciclului: listaCom.

S dm cteva exemple. Mai nti sortri i afiri pentru mai multe fiiere:
for fiier
do
sort <$fiier | more
done

S presupunem c numele fiierului de mai sus este SORT. Atunci, comanda:
$ SORT A b C

va genera i executa comenzile:
sort <A | more
sort <b | more
sort <C | more

Acelai efect va fi obinut dac fiierul SORT va conine n interiorul lui numele fiierelor:

for fiier in A b C
do
sort <$fiier | more
done

iar lansarea se va face:
$ SORT

In sfrit, vor fi sortate, lansnd aceeai comand, toate fiierele din directorul curent al cror
nume se termin cu escu, dac fiierul de comenzi este:

for fiier in *escu
do
sort <$fiier | more
done

Exemplul de mai jos transmite un mail la toi utilizatorii conectai:

for x in `who | cut -f1 -d ' ' `
do
mail -s "Salutari celor conectati" ${x}@scs.ubbcluj.ro
<<MESAJ
Ne cerem scuze ca va deranjam. Am trimis acest mail doar
ca si un test pentru structura de control for din shell.
MESAJ
done

Construciile while i until
Aceste construcii sunt oarecum similare, ambele executnd mai nti listaCom de dup
cuvntul while sau until. In funcie de codul de retur obinut se execut listaCom din
corpul ciclului (dintre do i done) i apoi se reia secvena listaCom (de dup while sau
until), sau execuia ciclului se ncheie. Execuia ciclului while se termin cnd n urma
73
procesrii listei de comenzi, listaCom se primete codul de retur 0. Spre deosebire de
while, pentru ncheierea execuiei ciclului repetitiv until este necesar s se ntoarc un
numr nenul.

Iat spre exemplu n figura urmtoare programul de afiare sortat a unor fiiere cu numele
date prin argumentele din linia de comand, descris nti folosind while i apoi folosind
until:

while [ $# -gt 0 ]
do
if [ -s $1 ]
then sort <$1 | more
else echo "$1 nu exista"
fi
shift
done
until [ $# -eq 0 ]
do
if [ -s $1 ]
then sort <$1 | more
else echo "$1 nu exista"
fi
shift
done

Construciile true, false, break, continue
Aceste instruciuni sunt simple ns execuia lor are sens doar n contextul structurilor de
control ciclice.

Intruciunile break i continue se refer la prsirea, respectiv reiterarea ciclurilor
declarate prin construciile for, while sau until. Construciile sunt preluate din limbajul
C (unde se refer doar la ciclurile cele mai interioare) i extinse de ctre shell. Sintaxele lor
sunt urmtoarele:

break [ n ]
continue [ n ]

Comanda break cere prsirea corpului unui ciclu i continuarea execuiei cu comanda
care urmeaz ciclului (urmtoarea instruciune dup done). Dac parametrul n lipsete,
atunci este prsit ciclul cel mai interior care conine comanda break. Dac este prezent n i
break este coninut n cel puin n cicluri incluse unul n altul, atunci execuia continu cu
comanda aflat dup cel de-al n-lea ciclu (dup cel de-al n-lea cuvnt done).

Comanda continue reia execuia corpului unui ciclu. In absena lui n reitereaz ciclul cel
mai interior, altfel este reiterat cel de-al n-lea ciclu n care este inclus continue (naintea
celui de-al n-lea cuvnt do). Reiterarea nseamn pentru for c variabila shell de ciclare
primete urmtoarea valoare, iar pentru while i until reexecuia listaCom care
urmeaz dup while sau until.

5.2.2.5. Exemplul 1: o aplicaie de supraveghere

De multe ori n practic se pune problema supravegherii integritii unui anumit director de
pe un sistem Unix. Presupunem c operaia de supraveghere se va face dup cum urmeaz: la
un interval de timp t specificat n secunde (primul argument din linia de comand),
programul va face rezumatul detaliat al directorului supravegheat (al doilea argument din
linia de comand). Dac acest rezumat coincide cu cel efectuat n urm cu t secunde,
74
programul adoarme la loc pentru nc t secunde, dup care verific iari coincidena
rezumatelor, .a.m.d. La prima neconcordan programul de supraveghere furnizeaz un
mesaj semnalnd situaia i i ncheie execuia. Programul pe care l vom numi
supraveghere i care realizeaz secvena de aciuni descrise anterior, este prezentat n
figura de mai jos.
In legtur cu coninutul programului, facem cteva precizri:
- Variabilele t i DIRECTOR conin intervalul de timp ntre dou verificri, respectiv
numele directorului de supravegheat. Atribuirea unei valori iniiale pentru t se face
prin parametrul $1 dat n linia de comand (primul parametru). In absena acestui
parametru, t va primi implicit valoarea 60. Similar, DIRECTOR poate fi precizat prin
$2 (al doilea parametru din linia de comand), iar n absen va indica directorul
gazd.
- Variabila x reine penultimul rezumat al directorului, iar y reine ultimul rezumat.

#!/bin/sh
DIRECTOR=${2-${HOME}} # in absenta, directorul gazda
t=${1-60} # in absenta, valoarea 60
x=`ls -l $DIRECTOR` # vechiul rezumat
while true
do
sleep $t # asteptare t sec.
y=`ls -l $DIRECTOR` # noul rezumat
if [ "$x" != "$y" ] # sunt egale ?
then
echo "Directorul $DIRECTOR a fost modificat"
exit
else
echo "Nici o schimbare. Mai asteptam $t secunde"
fi
x=$y # se retine ultimul rezumat
Done

Un astfel de program poate fi folosit n diverse situaii. Un scenariu posibil este urmtorul: un
utilizator oarecare i-a deschis dou sesiuni de lucru la dou terminale, iar de la unul dintre
ele, avnd ca director curent directorul gazd $HOME, lanseaz comanda:
$ supraveghere 10

Dac de la cellalt terminal se face o modificare n acest director, de exemplu prin comanda
cat >A atunci, n maximum 10 secunde pe cellalt terminal apare mesajul care anun
modificarea.

Programul poate fi adaptat pentru situaii similare. Dac spre exemplu n locul comenzii
echo se folosete o comand trap adecvat, sau este apelat un alt program indicat de
utilizator, atunci supravegherea poate fi activat de la acelai terminal:
$ supraveghere >ieire &

In cazul n care n directorul curent apar modificri, va intra n lucru comanda trap sau
programul indicat de ctre utilizator.

75
5.2.2.6. Exemplul 2: utilizri break i continue

Pentru a ilustra modalitatea de folosire a comenzilor break i continue considerm
urmtoarea problem: s se gseasc n directorul curent un fiier text care s aib primul
cuvnt de pe o linie mai lung de 5 caractere. Programul care rezolv problema este
urmtorul:

for x in *
do
if [ `file $x | grep -c text` -ne 1 ]
then
echo $x nu e fisier text. Trecem la urmatorul fisier din
director
continue
fi
#in variabila cuv1 se retine primul cuvant de pe o linie
#(consideram ca delimitator este caracterul spatiu)
cat $x | cut -d" " -f1 | while read cuv1
do
#verificam daca linia nu e vida, respectiv lungimea
primului cuvant
if [ ! -z $cuv1 ] && [ `expr length $cuv1` -ge 5 ]
then
echo In $x s-a gasit cuv $cuv1 cu lungimea `expr
length $cuv1`
#se iese din ciclul while
break
fi
done
#se iese din ciclul for
break
done

Selectarea fiierului de tip text se face folosind combinaia a dou comenzi: file i grep.
La ntlnirea primului cuvnt care ndeplinete condiia cerut, se prsesc cele dou cicluri
(while inclus n for), folosind comanda break. Dac n schimb se comenteaz aceste
linii, se vor afia toate liniile care ncep cu un cuvnt de cel puin 5 caractere, din fiierele
text ale directorului din care a fost lansat programul.

5.2.2.7. Exemplul 3: reunirea fiierelor tipribile ntr-unul singur

Se cere un script sh care s fie apelat n modul urmtor:

$ pall director

76
i care s creeze n directorul /tmp un fiier text care s reuneasc toate fiierele tipribile
care sunt depistate n substructura de directoare care ncepe cu director. In fiierul text
rezultat fiecare dintre fiierele componente va fi precedat de un antet de identificare.

Cnd este util o astfel de aplicaie? De exemplu n momentul n care un utilizator care are n
structura de directoare proprii numeroase fiiere de tip text, scripturi shell, surse de programe,
etc. Pentru a evita tiprirea pe rnd a lor, utilizatorul poate opta pentru folosirea unui program
avnd funcionalitatea prezentat anterior.

Programul pall depisteaz, folosind filtrul egrep, toate fiierele ce pot fi tiprite, pe care
le reunete apoi n form tipribil. Sursa programului pall este:

#!/bin/sh
if [ $# -ne 1 ]
then echo "folosire: pall director" >&2
exit 1
fi
if [ ! \( -d $1 \) ]
then echo "$1 nu exista sau nu este director" >&2
exit 2
fi
rm /tmp/${LOGNAME}Afisari /tmp/${LOGNAME}DeListat >/dev/null
2>&1

TotalLinii=0
find $1 -type f -print | sort | while read FISIER
do
if file $FISIER |
egrep "exec|data|empty|reloc|cannot open" >/dev/null
2>&1
then
continue
else
NrLinii=`wc -l <"$FISIER"`
Linie=${TotalLinii}" Pana la "`file $FISIER`
echo $Linie >/dev/tty
echo $Linie >> /tmp/${LOGNAME}DeListat
echo $Linie >> /tmp/${LOGNAME}Afisari
pr -f $FISIER >> /tmp/${LOGNAME}Afisari
TotalLinii=`expr $TotalLinii + $NrLinii`
echo $TotalLinii >/tmp/${LOGNAME}TotalLinii
fi
done
if [ -f /tmp/${LOGNAME}TotalLinii ]
then
read TotalLinii </tmp/${LOGNAME}TotalLinii
rm /tmp/${LOGNAME}TotalLinii
fi
echo "Total general: $TotalLinii linii"
>>/tmp/${LOGNAME}DeListat
77
echo "Total general: $TotalLinii linii"
>>/tmp/${LOGNAME}Afisari
cat /tmp/${LOGNAME}Afisari >>/tmp/${LOGNAME}DeListat
rm /tmp/${LOGNAME}Afisari

Programul creeaz fiierul /tmp/${LOGNAME}DeListat n care apare mai nti un
cuprins ce conine numele fiierelor i lungimile acestora n numr de linii. Astfel, variabila
NrLinii conine, n fiecare moment numrul de linii al fiierului curent. In variabila
TotalLinii acest numr este cumulat de la nceputul procesului de concatenare a
fiierelor.

Pentru informaii suplimentare referitoare la fiierele considerate a fi tipribile, recomandm
consultarea fiierului /usr/share/magic (sub Linux), respectiv /etc/magic (Solaris),
acestea fiind fiierele folosite de ctre comanda file pentru stabilirea tipului.

78

6. Bibliografie general


1. ***: Linux man magyarul, http://people.inf.elte.hu/csa/MAN/HTML/index.htm
2. A.S. Tanenbaum, A.S. Woodhull, Opercis rendszerek, 2007, Panem
Kiad.
3. Alexandrescu, Programarea modern in C++. Programare generic si modele de
proiectare aplicate, Editura Teora, 2002.
4. Angster Erzsbet: Objektumorientlt tervezs s programozs Java, 4KR Bt, 2003.
5. Bartk Nagy Jnos, Laufer Judit, UNIX felhasznli ismeretek, Openinfo
6. Bjarne Stroustrup: A C++ programozsi nyelv, Kiskapu kiad, Budapest, 2001.
7. Bjarne Stroustrup: The C++ Programming Language Special Edition, AT&T, 2000.
8. Boian F.M. Frentiu M., Lazr I. Tambulea L. Informatica de baz. Presa Universitar
Clujeana, Cluj, 2005
9. Boian F.M., Ferdean C.M., Boian R.F., Drago R.C., Programare concurent pe
platforme Unix, Windows, Java, Ed. Albastr, Cluj-Napoca, 2002
10. Boian F.M., Vancea A., Bufnea D., Boian R.,F., Cobrzan C., Sterca A., Cojocar D.,
Sisteme de operare, RISOPRINT, 2006
11. Bradley L. Jones: C# mesteri szinten 21 nap alatt, Kiskapu kiad, Budapest, 2004.
12. Bradley L. Jones: SAMS Teach Yourself the C# Language in 21 Days, Pearson
Education,2004.
13. Cormen, T., Leiserson, C., Rivest, R., Introducere n algoritmi, Editura Computer
Libris Agora, Cluj, 2000
14. Date C.J., Au Introduction to database Systems, Addison-Wesley, 1995
15. Eckel B., Thinking in C++, vol I-II, http://www.mindview.net
16. Ellis M.A., Stroustrup B., The annotated C++ Reference Manual, Addison-Wesley,
1995
17. Frentiu M., Lazr I. Bazele programrii. Partea I-a: Proiectarea algoritmilor
18. Herbert Schildt: Java. The Complete Reference, Eighth Edition, McGraw-Hill, 2011.
19. Horowitz, E., Fundamentals of Data Structures in C++, Computer Science Press,
1995
20. J. D. Ullman, J. Widom: Adatbzisrendszerek - Alapvets, Panem kiado, 2008.
21. Kiad Kft, 1998, http://www.szabilinux.hu/ufi/main.htm
22. Niculescu,V., Czibula, G., Structuri fundamentale de date i algoritmi. O perspectiv
orientat obiect., Ed. Casa Crii de Stiin, Cluj-Napoca, 2011
23. Raffai Mria: UML 2 modellez nyelvi szabvny, Palatia nyomda s kiad, 2005.
24. Ramakrishnan R., Database Management Systems, WCB McGraw-Hill, 1998
25. Robert A. Maksimchuk, Eric J. Naiburg: UML fldi halandknak, Kiskapu kiad,
2006.
26. Robert A. Maksimchuk, Eric J. Naiburg: UML for Mere Mortals, Pearson Education,
2005.
27. Robert Sedgewick: Algorithms, Addison-Wesley, 1984
28. Simon Kroly: Kenyernk Java. A Java programozs alapjai, Presa Universitar
Clujean, 2010.
29. Tmbulea L., Baze de date, Facultatea de matematic i Informatic, Centrul de
Formare Continu i Invmnt la Distan, Cluj-Napoca, 2003
30. V. Varga: Adatbzisrendszerek (A relcis modelltl az XML adatokig), Editura
Presa Universitar Clujean, 2005, p. 260. ISBN 973-610-372-2
79