Sunteți pe pagina 1din 175

Cuprins

1. Exerciţii comentate .............................................................................................. 3

2. Subprograme interne ........................................................................................... 27

3. Subprograme externe ......................................................................................... 47

4. Subprograme recursive ....................................................................................... 71

5. Masive memorate în fişiere ................................................................................ 77

6. Algoritmi de prelucrare a fişierelor organizate secvenţial ....................... 89

7. Algoritmi de prelucrare a fişierelor organizate relativ .............................. 109

8. Algoritmi de prelucrare a fişierelor organizate indexat ............................ 131

9. Aplicaţie informatică cu prelucrare de fişiere ............................................. 149

Bibliografie ................................................................................................................. 175


1. Exerciţii comentate

1.1. Suma elementelor unui vector de dimensiune n.


n
Fie X=(x1,x2,...,xn). Suma elementelor este S = x1 + x2 + … + xn = ∑x .
i =1
i

Ştiind că adunarea numerelor reale este asociativă şi că elementul neutru pentru


adunare este 0, algoritmul poate fi descris astfel:
S0 = 0;
------------------
S1 = S0 + x1 = 0 + x1 = x1;
S2 = S1 + x2 = x1 + x2;
...
Sn = Sn-1 + xn = x1 + ... + xn-1 + xn;
------------------
S = Sn.
Deoarece sumele parţiale S0, S1,...,Sn nu interesează şi, în plus, se ocupă inutil
memorie internă, însumarea se va realiza în aceeaşi locaţie de memorie, cu adresa
simbolică S, în care se vor depune sumele parţiale (se va cumula câte un nou
element).
S = 0;
------------------
S = S + x1 = 0 + x1 = x1;
S = S + x2 = x1 + x2;
...
S = S + xn = x1 + ... + xn-1 + xn;
Algoritmul recursiv poate fi descris cu ajutorul a două formule:
! formula de start: S = 0;
! formula recursivă: S = S + x(i), i=1,n.
Elementele vectorului sunt reale şi se introduc de la tastatură.

Program suma_elemente_vector;
Var
x:array[1..100] of real;
n,i:byte;
s:real;
Begin
write('Dimensiunea vectorului: ');
readln(n);
write('Elementele vectorului: ');
for i:=1 to n do read(x[i]);
s:=0;
for i:=1 to n do s:=s+x[i];
writeln('Suma = ',s:10:2)
End.

3
Algoritmi în programare. Aplicaţii

1.2. Suma elementelor de rang impar ale unui vector de dimensiune n.

Fie X=(x1,x2,...,xn). Suma elementelor de rang impar este S=x1+x3+x5+...


Există mai multe variante de rezolvare.

⊄ Varianta 1. Se parcurge vectorul cu indicele pornind de la valoarea iniţială


1 şi crescând cu pasul 2. Datorită particularităţilor instrucţiunii FOR privind pasul, se
utilizează structura WHILE-DO.

Program suma_elemente_rang_impar_1;
Var
x:array[1..100] of real; n,i:byte; s:real;
Begin
write('Dimensiunea vectorului: '); readln(n);
writeln('Elementele vectorului: ');
for i:=1 to n do readln(x[i]);
s:=0; i:=1;
while i<=n do
Begin
s:=s+x[i];
i:=i+2;
End;
writeln('Suma = ',s:10:2)
End.

⊄ Varianta 2. Se parcurge integral vectorul şi se selectează elementele de


rang impar, testând indicele fie prin verificarea restului împărţirii lui i la 2 (i mod 2),
fie prin funcţia standard ODD.

Program suma_elemente_rang_impar_2;
Var
x:array[1..100] of real; n,i:byte; s:real;
Begin
write('Dimensiunea vectorului: '); readln(n);
writeln('Elementele vectorului: ');
for i:=1 to n do readln(x[i]);
s:=0;
for i:=1 to n do if odd(i) then s:=s+x[i];
writeln('Suma = ',s:10:2)
End.

⊄ Varianta 3. Variabila de ciclare ia valori între 1 şi cel mai apropiat întreg


faţă de n/2, iar elementele vectorului se selectează utilizând indicele 2*i-1.

Program suma_elemente_rang_impar_3;
Var
x:array[1..100] of real; n,i:byte; s:real;

4
Exerciţii comentate

Begin
write('Dimensiunea vectorului: '); readln(n);
writeln('Elementele vectorului: ');
for i:=1 to n do readln(x[i]);
s:=0;
for i:=1 to round(n/2) do s:=s+x[2*i-1];
writeln('Suma = ',s:10:2)
End.

1.3. Media geometrică a elementelor pozitive dintr-un vector de dimensiune n.

Fie X=(x1,x2,...,xn). Media geometrică a elementelor pozitive este


, xi>0. Ştiind că înmulţirea în numere reale este asociativă şi are
MEDG = k xi Π
i = 1, k

elementul neutru 1, produsul P = Πx


i = 1, k
i se calculează astfel:

! formula de start: P = 1;
! formula recursivă: P = P Η x(i); i=1,k; x(i)>0.
Pentru economie de memorie internă, produsul se calculează direct în
variabila MEDG. Media geometrică se poate determina numai dacă numărul
elementelor pozitive (k) este mai mare decât 2.
Deoarece în limbajul Pascal nu există operatori (sau funcţii) pentru radicali
şi ridicări la putere (mai mari de ordinul doi) se utilizează formula
m (m*lna)/n
n
a =e , a > 0 , pentru determinarea căreia există funcţiile standard EXP(x)
şi LN(x).

Program media_geometrica;
Var
x:array[1..100] of real;
n,i,k:byte; medg:real;
Begin
write('Dimensiunea vectorului: '); readln(n);
writeln('Elementele vectorului: ');
for i:=1 to n do
begin write('X(',i,') = '); readln(x[i]); end;
medg:=1; k:=0;
for i:=1 to n do
if x[i] > 0 then
begin medg:=medg * x[i]; k:=k+1 end;
if k > 1 then
begin
medg:=Exp(Ln(medg)/k);
writeln('Media geometrica = ',medg:10:2)
end
else writeln('Nu se poate calcula !');
End.

5
Algoritmi în programare. Aplicaţii

1.4. Determinarea poziţiei primei apariţii a unei valori date într-un vector
neordonat, de dimensiune n.

Vectorul se parcurge secvenţial de la primul element, într-o structură


DO-WHILE, până când se regăseşte valoarea căutată, sau până la ultimul element,
caz în care valoarea căutată nu se află în vector, afişându-se un mesaj corespunzător.

Program cautare_prima_aparitie;
Var
x:array[1..100] of real; n,i:byte; a:real;
Begin
write('Dimensiunea vectorului: '); readln(n);
writeln('Elementele vectorului: ');
for i:=1 to n do
begin
write('X(',i,') = '); readln(x[i]);
end;
Write('Valoarea cautata: '); readln(a);
i:=1;
while (i<=n) and (x(i)<>a) do i:=i+1;
if i<=n then writeln('Pozitia = ',i)
else writeln('Valoare neregasita !');
End.

1.5. Determinarea poziţiei ultimei apariţii a unei valori date într-un vector
neordonat, de dimensiune n.

Vectorul se parcurge secvenţial într-o structură DO-FOR, de la primul la


ultimul element, reţinând în aceeaşi variabilă (POZ) valoarea curentă a indicelui, în
cazul identităţii elementului cu valoarea căutată. Dacă variabila POZ are valoarea 0
la sfârşitul ciclării, valoarea căutată nu a fost regăsită printre elementele vectorului şi
se afişează un mesaj corespunzător.

Program cautare_ultima_aparitie;
Var x:array[1..100] of real; n,i,poz:byte; a:real;
Begin
write('Dimensiunea vectorului: '); readln(n);
writeln('Elementele vectorului: ');
for i:=1 to n do begin
write('X(',i,') = ');
readln(x[i])
end;
write('Valoarea cautata: '); readln(a);
poz:=0;
for i:=1 to n do if x[i] = a then poz:=i;
if poz <> 0 then writeln('Pozitia = ',poz)
else writeln('Valoare neregasita!')
End.

6
Exerciţii comentate

1.6. Determinarea poziţiei tuturor apariţiilor unei valori date într-un vector
neordonat, de dimensiune n.

Vectorul se parcurge secvenţial într-o structură DO-FOR, de la primul la


ultimul element, reţinând valoarea curentă a indicelui în cazul identităţii elementului
cu valoarea căutată, într-un vector (POZ) de poziţii (vectorul POZ se construieşte).
Dacă la sfârşitul ciclării vectorul POZ este vid (indicele k al acestuia este 0), valoarea
căutată nu a fost regăsită şi se afişează un mesaj corespunzător.

Program cautare_toate_aparitiile;
Var
x:array[1..100] of real; poz:array[1..100] of byte;
n,i,k:byte; a:real;
Begin
write('Dimensiunea vectorului: '); readln(n);
writeln('Elementele vectorului: ');
for i:=1 to n do
begin
write('X(',i,') = '); readln(x[i]);
end;
write('Valoarea cautata: '); readln(a);
k:=0;
for i:=1 to n do
if x[i] = a then
begin
k:=k+1;
poz[k]:=i
end;
if k > 0 then
begin
write('Pozitiile = ');
for i:=1 to k do write(poz[i],', ')
end
else writeln('Valoare neregasita!');
End.

1.7. Căutarea unei valori date într-un şir de numere, ordonat crescător, de
dimensiune n.

Pornind de la ipoteza că şirul este ordonat, căutarea valorii se realizează pe


subşiruri, în funcţie de elementul central al subşirului curent. Rangul elementelor
unui subşir poate lua valori în intervalul [ls,ld] φ [1,n], unde ls este limita stângă şi ld
este limita dreaptă. Dacă valoarea căutată nu coincide cu elementul central al
subşirului, procesul de căutare continuă pe subşirul din stânga (dreapta) elementului
central, după cum valoarea este mai mică (mai mare) decât acesta, modificându-se
corespunzător ld (ls) pentru noul subşir.

7
Algoritmi în programare. Aplicaţii

Modificarea limitei dreapta (stânga) se realizează prin incrementarea


(decrementarea) cu o unitate. Rangul elementului central al subşirului curent se
1s + 1d 
determină astfel: i =  . Procesul de căutare se opreşte când valoarea căutată
 2 
coincide cu elementul central al subşirului curent, sau când ls > ld, caz în care
valoarea dată nu se regăseşte în şirul iniţial.

Program cautare_in_vector_ordonat;
Var
x:array[1..100] of real;
n,i,s,d:byte;
a:real;
vb:boolean;
Begin
write('Dimensiunea vectorului: '); readln(n);
writeln('Elementele vectorului: ');
for i:=1 to n do
begin
write('X(',i,') = ');
readln(x[i])
end;
write('Valoarea cautata: '); readln(a);
s:=1; d:=n; vb:=false;
repeat
i:=(s+d) div 2;
if x[i] = a then vb:=true
else if x[i] < a then s:=i+1
else d:=i-1;
until (d < s) or vb;
if vb then writeln('Pozitia = ',i)
else writeln('Valoare neregasita!');
End.

1.8. Determinarea elementului maxim dintr-un vector de dimensiune n şi a


poziţiei primei (ultimei) sale apariţii.

Fie vectorul X=(x1,x2,...,xn). Maximul din vectorul X este MAX = max(xi),


i=1,n. Deoarece, la un moment dat, comparaţia se realizează numai pentru două
valori, algoritmul poate fi descris astfel:
MAX1 = max(x1,x2);
MAX2 = max(MAX1,x3);
MAX3 = max(MAX2,x4);
...
MAXn-1 = max(MAXn-2,xn);
---------------------
MAX = MAXn-1.

8
Exerciţii comentate

Maximele parţiale MAX1,MAX2,...,MAXn-1 nu interesează şi de aceea se va utiliza o


singură variabilă (MAX) pentru reţinerea elementului maxim din vector. De
asemenea, pentru a putea exprima iterativ procesul, variabila MAX va fi iniţializată
cu x(1). Algoritmul recursiv poate fi descris astfel:
! formula de start: MAX = x(1);
! formula recursivă: MAX = max(MAX,x(i)), i=2,n.
Pentru a reţine poziţia valorii maxime din vector se utilizează variabila POZ,
iniţializată cu 1 (corespunzator poziţiei elementului cu care se iniţializează variabila
MAX). În procesul iterativ, variabila POZ se modifică dacă un element x(i) este fie
strict mai mare decât MAX (pentru reţinerea poziţiei primei apariţii), fie mai mare
sau egal decât MAX (pentru reţinerea poziţiei ultimei apariţii).

Program determinare_maxim;
Var
x:array[1..100] of real; n,i,poz:byte; max:real;
Begin
write('Dimensiunea vectorului: '); readln(n);
writeln('Elementele vectorului: ');
for i:=1 to n do
begin
write('X(',i,') = ');
readln(x[i])
end;
max:=x[1]; poz:=1;
for i:=2 to n do
if x[i] > max then begin max:=x[i]; poz:=i end;
writeln('Maximul = ',max:10:2,' pe pozitia ',poz)
End.

1.9. Determinarea elementului maxim dintr-un vector şi a apariţiilor sale.

Elementul maxim se determină după algoritmul utilizat la exerciţiul 1.8.


Deoarece valoarea maximă poate apărea în vector de mai multe ori (cel puţin o dată
şi cel mult de n ori - în cazul şirului constant), se va construi un vector de poziţii
(POZ). Există mai multe variante de rezolvare.

⊄ Varianta 1. Vectorul POZ se construieşte după ce s-a determinat valoarea


maximă, caz în care problema se rezolvă ca în exerciţiul 1.6.

Program determinare_pozitii_maxim_1;
Var
x:array[1..100] of real;
poz:array[1..100] of byte;
n,i,k:byte; max:real;
Begin
write('Dimensiunea vectorului: '); readln(n);
writeln('Elementele vectorului: ');

9
Algoritmi în programare. Aplicaţii

for i:=1 to n do
begin
write('X(',i,') = ');
readln(x[i])
end;
max:=x[1];
for i:=2 to n do if x[i] > max then max:=x[i];
k:=0;
for i:=1 to n do
if x[i] = max then
begin
k:=k+1;
poz[k]:=i
end;
write('Maximul = ',max:10:2,' pe pozitiile ');
for i:=1 to k do write(poz[i],' ')
End.

⊄ Varianta 2. Vectorul POZ se construieşte simultan cu determinarea


elementului maxim. Astfel, în urma comparaţiei între variabila MAX şi elementul
x(i) apar două cazuri:
- dacă x(i) = MAX, se construieşte un nou element în vectorul de poziţii
(indicele vectorului POZ se incrementează cu 1);
- dacă x(i) > MAX, înseamnă că s-a găsit o nouă valoare maximă şi indicele
vectorului POZ se iniţializează cu 1.
Pentru ambele cazuri, în vectorul POZ se reţine valoarea curentă a indicelui de
parcurgere a vectorului de date.

Program determinare_pozitii_maxim_2;
Var
x:array[1..100] of real; poz:array[1..100] of byte;
n,i,k:byte; max:real;
Begin
write('Dimensiunea vectorului: '); readln(n);
writeln('Elementele vectorului: ');
for i:=1 to n do
begin
write('X(',i,') = ');
readln(x[i])
end;
max:=x[1]; k:=0;
for i:=1 to n do
if x[i] >= max then
begin
if x[i] > max then begin max:=x[i]; k:=1 end
else k:=k+1;
poz[k]:=i
end;

10
Exerciţii comentate

write('Maximul = ',max:10:2,' pe pozitiile ');


for i:=1 to k do
write(poz[i],' ')
End.

1.10. Sortarea unui vector de dimensiune n.

Prin sortare se înţelege aranjarea elementelor unei mulţimi, în ordine


crescătoare (descrescătoare) a valorilor. Există mai multe variante de sortare,
exemplificate în continuare pe ordonarea crescătoare a elementelor unui vector.
⊄ Sortarea prin interschimbare. Se compară două câte două elemente
consecutive ale vectorului, interschimbându-le în cazul neîndeplinirii criteriului de
ordonare. După o parcurgere integrală a vectorului procesul se reia începând cu
primul element. Astfel, elementele cu valoare mică sunt "împinse" către începutul
vectorului. De aceea, metoda se mai numeşte "metoda bulelor". Procesul se opreşte
când la o parcurgere a vectorului nu s-a produs nici o interschimbare, situaţie indicată
de valoarea de adevăr a unei variabile-semafor (booleană), controlată de
programator.

Program sortare_prin_interschimbare;
Var
x:array[1..100] of real; n,i:byte; aux:real; vb:boolean;
Begin
write('Dimensiunea vectorului: '); readln(n);
writeln('Elementele vectorului: ');
for i:=1 to n do
begin
write('X(',i,') = '); readln(x[i])
end;
repeat
vb:=false;
for i:=1 to n-1 do
if x[i] > x[i+1] then
begin
aux:=x[i];
x[i]:=x[i+1];
x[i+1]:=aux;
vb:=true
end
until not vb;
writeln(' Vectorul ordonat este:');
for i:=1 to n do writeln('X(',i,') = ',x[i]:10:2)
End.

⊄ Sortarea prin selecţie. Metoda presupune determinarea elementului minim


din vector şi aducerea lui pe prima poziţie, după care se determină minimul din
vectorul rămas şi aducerea lui pe a doua poziţie etc. Minimul se poate determina

11
Algoritmi în programare. Aplicaţii

comparând un element al vectorului cu toate care îl succed, interschimbându-le în


cazul neîndeplinirii criteriului de ordonare. Această metodă poate avea la rândul ei
mai multe variante.

Program sortare_prin_selectie;
Var
x:array[1..100] of real; n,i,j:byte; aux:real;
Begin
write('Dimensiunea vectorului: '); readln(n);
writeln('Elementele vectorului: ');
for i:=1 to n do
begin
write('X(',i,') = ');
readln(x[i])
end;
for i:=1 to n-1 do
for j:=i+1 to n do
if x[i] > x[j] then
begin
aux:=x[i]; x[i]:=x[j]; x[j]:=aux
end;
writeln(' Vectorul ordonat este:');
for i:=1 to n do writeln('X(',i,') = ',x[i]:10:2)
End.

⊄ Sortarea prin inserţie. Pornind de la ipoteza că la pasul i elementele


predecesoare lui x(i) sunt ordonate, se determină poziţia (POZ) în care valoarea lui
x(i) se încadrează conform criteriului de ordonare. Elementul x(i) va fi inserat în acea
poziţie, după ce toate elementele vectorului, începând cu poziţia POZ şi până la
sfârşit, glisează cu o poziţie la dreapta. Se reduce astfel numărul de interschimbări,
deoarece, în cazul în care un element x(i) este mai mare decât precedentul, acesta se
consideră ordonat.

Program sortare_prin_insertie;
Var
x:array[1..100] of real; n,i,j,k,poz:byte; aux:real;
Begin
write('Dimensiunea vectorului: '); readln(n);
writeln('Elementele vectorului: ');
for i:=1 to n do
begin
write('X(',i,') = ');
readln(x[i])
end;
for i:=2 to n do
if x[i] < x[i-1] then
begin
poz:=0; j:=1;

12
Exerciţii comentate

repeat if x[i]<x[j] then poz:=j else j:=j+1


until (j>n) or (poz<>0);
aux:=x[i];
for k:=i downto poz+1 do x[k]:=x[k-1];
x[poz]:=aux
end;
writeln(' Vectorul ordonat este:');
for i:=1 to n do writeln('X(',i,') = ',x[i]:10:2)
End.

1.11. Interclasarea a doi vectori de dimensiuni variabile.

Prin interclasare se înţelege procesul de obţinere din două sau mai multe
mulţimi ordonate o nouă mulţime, ordonată după acelaşi criteriu. Există mai multe
variante de interclasare, exemplificate în continuare pe doi vectori, sortaţi crescător.

⊄ Varianta 1 presupune compararea a două elemente, câte unul din fiecare


vector iniţial, cu scrierea celui mai mic dintre ele în vectorul rezultant şi trecerea la
următorul element al vectorului iniţial din care s-a preluat. Procesul de comparare se
încheie când s-a epuizat unul din vectorii iniţiali. În continuare, elementele
netransferate ale celuilalt vector iniţial se copiază în vectorul rezultant.

Program interclasare_vectori_metoda_1;
Var
x:array[1..100] of real;
y:array[1..150] of real;
z:array[1..250] of real;
m,n,i,j,k,l:byte;
Begin
write('Dimensiunea vectorului 1: '); readln(m);
writeln('Elementele vectorului 1: ');
for i:=1 to m do
begin write('X(',i,') = '); readln(x[i]) end;
write('Dimensiunea vectorului 2: '); readln(n);
writeln('Elementele vectorului 2: ');
for i:=1 to n do
begin write('Y(',i,') = '); readln(y[i]) end;
k:=0; i:=1; j:=1;
while (i <= m) and (j <= n) do
begin
k:=k+1;
if x[i] < y[j] then
begin z[k]:=x[i]; i:=i+1 end
else
begin z[k]:=y[j]; j:=j+1 end
end;
if i>m then
for l:=j to n do

13
Algoritmi în programare. Aplicaţii

begin
k:=k+1; z[k]:=y[l]
end
else
for l:=i to m do
begin
k:=k+1; z[k]:=x[l]
end;
writeln(' Vectorul interclasat este:');
for i:=1 to m+n do
writeln('Z(',i,') = ',z[i]:10:2)
End.

⊄ Varianta 2 presupune obţinerea vectorului rezultant într-un proces unic de


comparare. Pentru a continua procesul în cazul în care se epuizează unul din vectorii
iniţiali, ultimul element al acestuia va primi o valoare mai mare decât oricare din
valorile regăsite în vectorii iniţiali. Această valoare poartă denumirea de high-value
(HV) şi depinde de natura şi reprezentarea internă a vectorilor. Comparările
ulterioare cu HV vor forţa copierea în vectorul rezultant numai a elementelor
vectorului care nu s-a epuizat. Procesul se încheie când ambii vectori iniţiali au fost
parcurşi integral, deci elementele finale au valoarea HV.

Program interclasare_vectori_metoda_2;
Var
x:array[1..101] of real;
y:array[1..151] of real;
z:array[1..250] of real;
m,n,i,j,k:byte;
Const
hv=1E10;
Begin
write('Dimensiunea vectorului 1: '); readln(m);
writeln('Elementele vectorului 1: ');
for i:=1 to m do begin
write('X(',i,') = '); readln(x[i])
end;
write('Dimensiunea vectorului 2: '); readln(n);
writeln('Elementele vectorului 2: ');
for i:=1 to n do begin
write('Y(',i,') = '); readln(y[i])
end;
k:=0; i:=1; j:=1;
while (x[i]<>hv) or (y[j]<>hv) do
begin
k:=k+1;
if x[i] < y[j] then begin
z[k]:=x[i];
i:=i+1;

14
Exerciţii comentate

if i>m then x[i]:=hv


end
else begin
z[k]:=y[j]; j:=j+1; if j>n then y[j]:=hv
end
end;
writeln(' Vectorul interclasat este:');
for i:=1 to m+n do writeln('Z(',i,') = ',z[i]:10:2)
End.
Observaţie: Pentru a nu altera valoarea elementului final al fiecărui vector iniţial se
va rezerva o poziţie suplimentară la declararea masivelor.

1.12. Suma elementelor unei matrice dreptunghiulare de dimensiuni mΗn.


 a 11 a12 ... a 1n 
 
Fie matricea A =  a 21 a 22 ... a 2n  . Suma elementelor este:
 .......................
 
 
 a m1 a m 2 ... a mn 
m n
S=a11+a12+...+a1n+a21+...+a2n+...+am1+...+amn= ∑ ∑ a(i, j) ,
i =1 j=1
dacă se însumează pe

linii (lexicografic) sau


n m
S=a11+a21+...+am1+a12+...+am2+...+a1n+...+amn= ∑ ∑ a(i, j) ,
j =1 i =1
dacă se însumează pe

coloane (invers lexicografic). Matricea A poate fi privită ca un vector de dimensiune


m⋅n dacă este liniarizată (lexicografic sau invers lexicografic). Pornind de la
ipotezele formulate la determinarea sumei elementelor unui vector, algoritmul
(parcurgând matricea lexicografic), poate fi descris astfel:

S=0
-------------------------
j=1 S = S + a11 = a11
j=2 S = S + a12 = a11 + a12
i=1 ...
j=n S = S + a1n = a11 +...+ a1n
-------------------------
j=1 S = S + a21 = a11 +...+ a21
i=2 ...
j=n S = S + a2n = a11 +...+ a2n
…………………….
j=1 S = S + am1 = a11 +...+ am1
i=m ...
j=n S = S + amn = a11 +...+ amn
-------------------------

15
Algoritmi în programare. Aplicaţii

Algoritmul recursiv poate fi descris astfel:


! formula de start: S = 0;
! formula recursivă: S = S + a(i,j); i=1,m; j=1,n
Parcurgând matricea invers lexicografic algoritmul este similar, cu deosebirea că
indicele liniilor (i) va lua toate valorile din intervalul [1,m] pentru o valoare dată a
indicelui de coloane (j). Elementele matricei se introduc de la tastatură, element cu
element, cu ajutorul a două structuri DO-FOR imbricate.

Program suma_elemente_matrice;
Var a:array[1..10,1..20] of real; m,n,i,j:byte; s:real;
Begin
write('Numarul de linii: '); readln(m);
write('Numarul de coloane: '); readln(n);
writeln('Elementele matricei: ');
for i:=1 to m do
for j:=1 to n do
begin
write('A(',i,',',j,') = ');
readln(a[i,j]);
end;
s:=0;
for i:=1 to m do
for j:=1 to n do
s:=s+a[i,j];
writeln(' Suma: ',s:15:3)
End.

1.13. Determinarea elementelor maxim şi minim dintr-o matrice dreptun-


ghiulară, de dimensiuni mΗn.
 a 11 a 12 ... a1n 
 
 a 21 a 22 ... a 2n 
Fie matricea A=  . Liniarizând matricea lexicografic se obţine un
.......................
 
 
 a m1 a m 2 ... a mn 
vector de dimensiune mΗn: A=(a11,a12,...,a1n,a21,...,a2n,...,am1,...,amn). Elementele
maxim şi minim se determină astfel: MAX=max(a11,a12,...,a1n,a21,...,a2n,...,am1,...,amn)
şi MIN= min(a11,a12,...,a1n,a21,...,a2n,...,am1,...,amn). Algoritmul recursiv poate fi descris
astfel:
! formulele de start: MAX = a(1,1); MIN = a(1,1);
! formulele recursive: MAX = max{MAX, a(i,j)}; i=1,m; j=1,n;
MIN = min{MIN, a(i,j)}; i=1,m; j=1,n.
Dacă matricea se consideră liniarizată invers lexicografic algoritmul este similar, cu
deosebirea că ordinea de variaţie a indicilor este inversă. Maximul şi minimul se vor
determina concomitent, pornind de la ipoteza că un element oarecare a(i,j) se poate
afla:

16
Exerciţii comentate

- în intervalul (MAX, +4) şi este noua valoare maximă;


- în intervalul (-4, MIN) şi este noua valoare minimă;
- în intervalul [MIN, MAX], caz în care nu afectează nici una din valorile căutate.

Program minim_maxim_din_matrice;
Var
a:array[1..10,1..20] of real;
m,n,i,j:byte;
min,max:real;
Begin
write('Numarul de linii: ');
readln(m);
write('Numarul de coloane: ');
readln(n);
writeln('Elementele matricei: ');
for i:=1 to m do
begin
write('Linia ',i,': ');
for j:=1 to n do
read(a[i,j])
end;
max:=a[1,1];
min:=max;
for i:=1 to m do
for j:=1 to n do
if a[i,j] > max then max:=a[i,j]
else if a[i,j] < min then min:=a[i,j];
writeln(' Minim = ',min:15:3);
writeln(' Maxim = ',max:15:3)
End.

1.14. Determinarea sumei elementelor de pe fiecare coloană a unei matrice


dreptunghiulare precum şi a valorii maxime dintre aceste sume.
 a 11 a 12 ... a1n 
 
 a 21 a 22 ... a 2n 
Fie matricea A =  . Însumând elementele de pe fiecare coloană a
.......................
 
 
 a m1 a m 2 ... a mn 
8 8 8
S = (S1, S2, ..., Sn)
unei matrice se obţine un vector (S) de sume, de dimensiune n. Fiecare element al
acestui vector se determină după algoritmul descris la exerciţiul 1, asfel:
! formula de start: S(j) = 0;
! formula recursivă: S(j) = S(j) + a(i,j); i=1,m.
Determinarea sumei maxime se poate realiza n în etape distincte, prin construirea
vectorului S urmată de determinarea maximului dintr-un vector sau o în aceeaşi

17
Algoritmi în programare. Aplicaţii

structură repetitivă astfel: se determină suma elementelor de pe o coloană a matricei,


după care, dacă este prima coloană se aplică formula de start MAX=S(1), altfel,
formula recursivă MAX=max{MAX,S(j)}, j=2,n.

Program sume_pe_coloane;
Var
a:array[1..10,1..20] of real; s:array[1..20] of real;
m,n,i,j:byte; max:real;
Begin
write('Numarul de linii: '); readln(m);
write('Numarul de coloane: '); readln(n);
writeln('Elementele matricei: ');
for i:=1 to m do
for j:=1 to n do
begin write('A(',i,',',j,') = '); readln(a[i,j]) end;
for j:=1 to n do
begin s[j]:=0;
for i:=1 to m do s[j]:=s[j]+a[i,j];
if j = 1 then max:=s[j]
else if s[j] > max then max:=s[j]
end;
writeln('Sumele pe coloane sunt:');
for j:=1 to n do writeln(' Coloana ',j,' = ',s[j]:15:3);
writeln(' Maximul = ',max:15:3)
End.

1.15. Determinarea elementului maxim de pe fiecare linie şi a elementului


maxim dintr-o matrice dreptunghiulară de dimensiuni mΗn.
 a 11 a 12 . . . a 1n  → MAX1
 
 a 21 a 22 . . . a 2n  → MAX 2
Fie matricea A =  . Elementele maxime de pe fiecare
. . . . . . . . . . . . . . . . . ..........
 
  → MAX m
 a m1 a m 2 . . . a mn 
linie vor forma un vector de dimensiune m: MAX = (MAX1,MAX2,...,MAXm). Un
element al vectorului MAX se determină astfel:
! formula de start: MAX(i) = a(i,1);
! formula recursivă: MAX(i) = max{MAX(i),a(i,j)}, j=2,n.
Maximul din matrice (MAXM) se poate determina n în etape distincte, prin
determinarea elementului maxim al vectorului MAX după ce acesta a fost construit:
MAXM=max{MAX(i)}, i=1,m sau o în aceeaşi structură repetitivă, comparând
elementul MAX(i) recent determinat, cu variabila MAXM.

Program maxime_pe_linii;
Var
a:array[1..10,1..20] of real; max:array[1..10] of real;
m,n,i,j:byte; maxm:real;

18
Exerciţii comentate

Begin
write('Numarul de linii: '); readln(m);
write('Numarul de coloane: '); readln(n);
writeln('Elementele matricei: ');
for i:=1 to m do
for j:=1 to n do
begin
write('A(',i,',',j,') = '); readln(a[i,j]);
end;
for i:=1 to m do
begin
max[i]:=a[i,1];
for j:=2 to n do
if max[i] < a[i,j] then
max[i]:=a[i,j];
if (i=1) or (maxm < max[i]) then
maxm:=max[i]; {formula de start sau recursiva}
end;
writeln(' Maximele pe linii sunt:');
for i:=1 to m do writeln('Linia ',i,' = ',max[i]:10:2);
writeln('Maximul din matrice = ',maxm:10:2)
End.

1.16. Numărarea liniilor unei matrice dreptunghiulare de dimensiuni mΗn ale


căror elemente sunt în ordine strict descrescătoare.

Matricea AmΗn va fi parcursă lexicografic. Pentru fiecare linie se verifică,


într-o structură repetitivă WHILE-DO, dacă oricare două elemente succesive satisfac
criteriul cerut. La prima neconcordanţă se iese forţat din ciclare. Numărătorul de linii
care au proprietatea cerută (NR) se incrementează cu 1 numai dacă s-a parcurs
întreaga linie (j>n-1). Altfel, linia nu satisface cerinţa şi procesul se reia pentru
următoarea linie a matricei. În final, dacă variabila NR are valoare nenulă va fi
afişată pe ecran, altfel se afişează un mesaj corespunzător.

Program numarare_linii;
Var
a:array[1..10,1..20] of real; m,n,i,j,nr:byte;
Begin
write('Numarul de linii: '); readln(m);
write('Numarul de coloane: '); readln(n);
writeln('Elementele matricei: ');
for i:=1 to m do
for j:=1 to n do
begin
write('A(',i,',',j,') = ');
readln(a[i,j])
end;
nr:=0;

19
Algoritmi în programare. Aplicaţii

for i:=1 to m do
begin
j:=1;
while (j<=n-1) and (a[i,j]>a[i,j+1]) do j:=j+1;
if j > n-1 then nr:=nr+1;
end;
if nr > 0 then
writeln('Nr. de linii: ',nr)
else
writeln('Nu exista linii cu elemente descrescatoare !');
End.

1.17. Determinarea poziţiei primei apariţii a unei valori date într-o matrice
dreptunghiulară, de dimensiuni mΗn.

Matricea va fi parcursă în ordinea lexicografic. În momentul în care se


găseşte valoarea căutată se afişează poziţia (linia şi coloana elementului respectiv) şi
se abandonează parcurgerea matricei. Ieşirea "forţată" din structurile repetitive se
realizează cu ajutorul unei variabile booleene (VB), care ia valoarea TRUE dacă
valoarea dată a fost regăsită printre elementele matricei sau FALSE în caz contrar.
Testarea suplimentară a variabilei VB, alături de condiţia de sfârşit de linii (i>m) şi
sfârşit de coloane (j>n), transformă structurile repetitive cu numărător (gândite pentru
parcurgerea matricei) în două structuri WHILE-DO imbricate. În final, dacă VB este
falsă, înseamnă că valoarea nu a fost regăsită şi se afişează un mesaj corespunzător.

Program pozitia_primei_aparitii;
Var
a:array[1..10,1..20] of real;
m,n,i,j:byte; x:real; vb:boolean;
Begin
Write('Numarul de linii: '); Readln(m);
Write('Numarul de coloane: '); Readln(n);
Writeln('Elementele matricei: ');
For i:=1 to m do
For j:=1 to n do
begin
write('A(',i,',',j,') = ');
readln(a[i,j])
end;
Write('Valoarea cautata: '); readln(x);
vb:=false; i:=1;
While (i<=m) and not vb do
begin
j:=1;
while (j<=n) and not vb do
if a[i,j] = x then
begin
vb:=true;

20
Exerciţii comentate

writeln('Valoarea apare pe linia ',i,' coloana ',j)


end
else j:=j+1;
i:=i+1
end;
If not vb then writeln('NU exista valoarea cautata!')
End.

1.18. Înmulţirea a două matrice dreptunghiulare cu elemente reale de dimen-


siuni mΗn, respectiv nΗp.

Fie matricele A={a(i,k)}, i=1,m, k=1,n şi B={b(k,j)}, k=1,n, j=1,p. Matricea


rezultat este C=AΗB={c(i,j)}, i=1,m, j=1,p. ∨inând cont că înmulţirea de matrice nu
este comutativă şi că elementul neutru pentru adunarea în numere reale este 0,
algoritmul pentru determinarea unui element c(i,j) poate fi descris astfel:
! formula de start: c(i,j) = 0;
! formula recursivă: c(i,j) = c(i,j) + a(i,k)Ηb(k,j); k=1,n.
Se obţine o construcţie compusă din trei structuri repetitive cu numărător, imbricate.

Program inmultire_matrice;
Var
a:array[1..10,1..20] of real;
b:array[1..20,1..30] of real;
c:array[1..10,1..30] of real;
m,n,p,i,j,k:byte; x:real;
vb:boolean;
Begin
Write('Nr. de linii ale matricei deinmultit: '); Readln(m);
Write('Nr. de coloane ale matricei deinmultit: '); Readln(n);
Write('Nr. de coloane ale matricei inmultitor: '); Readln(p);
Writeln('Elementele matricei deinmultit: ');
For i:=1 to m do
For j:=1 to n do
begin
write('A(',i,',',j,') = '); readln(a[i,j])
end;
Writeln('Elementele matricei inmultitor: ');
For i:=1 to n do
For j:=1 to p do
begin
write('B(',i,',',j,') = ') readln(b[i,j])
end;
For i:=1 to m do
For j:=1 to p do
begin
c[i,j]:=0;
for k:=1 to n do c[i,j]:=c[i,j]+a[i,k]*b[k,j]
end;

21
Algoritmi în programare. Aplicaţii

Writeln('Matricea rezultat este:');


For i:=1 to m do
begin
for j:=1 to p do write(c[i,j]:7:2,' ');
writeln
end
End.

Observaţie: Matricele A şi B se introduc câte un element pe un rând al ecranului, iar


matricea C se va afişa câte o linie pe un rând al ecranului.

1.19. Rezolvarea ecuaţiei ax2 + bx + c = 0, a,b,c 0 R.

Având în vedere că de la tastatură se poate introduce orice triplet (a,b,c) de


valori reale, rezolvarea ecuaţiei date necesită următoarea discuţie, după valorile
coeficienţilor:
a. (0,0,0) - ecuaţia este nedeterminată;
b. (0,0,c 0) - ecuaţia este imposibilă;
c. (0,b 0,c0R) - ecuaţia este degenerată şi se determină soluţia ecuaţiei de
gradul I;
d. (a 0,b0R,c0R) - ecuaţia este determinată, de gradul al II-lea, iar discuţia
se va face după semnul discriminantului d=b2-4ac, astfel:
d.1. dacă d>0, ecuaţia are două soluţii reale distincte;
d.2. dacă d=0, ecuaţia are soluţie dublă;
d.3. dacă d<0, ecuaţia are soluţii imaginare.
Soluţiile vor fi determinate şi afişate pe ecran.

Program ecuatie;
Var a,b,c,x,x1,x2,r,im,d:real;
Begin
Write('Coeficientii ecuatiei: '); Readln(a,b,c);
If a<>0 then
begin
d:=b*b-4*a*c;
if d>=0 then
begin
if d>0 then
begin
x1:=(-b+sqrt(d))/2/a; x2:=(-b-sqrt(d))/2/a;
writeln('X1=',x1:6:2,' X2=',x2:6:2)
end
else
begin
x:=-b/2/a; writeln('X1 = X2 = ',x:6:2)
end;
end
else

22
Exerciţii comentate

begin
r:=-b/2/a; im:=abs(sqrt(-d)/2/a);
write('X1=',r:6:2,'+',im:6:2,'i; X2=',
r:6:2,' -',im:6:2,'i')
end;
end
else if b<>0 then
begin
x:=-c/b;
writeln('Ecuatie de gradul I: X=',x:6:2)
end
else if c<>0 then writeln('Ecuatie imposibila !')
else writeln('Ecuatie nedeterminata !')
End.

1.20. Determinarea c.m.m.d.c. dintre două numere naturale nenule.

Pentru determinarea c.m.m.d.c. dintre două numere (A şi B) se aplică


algoritmul lui Euclid, care constă în următoarele etape:
a. primul deîmpărţit (D) este A, iar primul împărţitor (I) este B;
b. se împarte D la I şi se obţine un cât (C) şi un rest (R), conform teoremei
împărţirii: D=IΗC+R;
c. dacă R=0, atunci c.m.m.d.c. este ultimul împărţitor (I) şi procesul se opreşte.
d. dacă R=1, atunci numerele sunt prime între ele şi procesul se opreşte;
e. dacă R∃2, noul deîmpărţit este vechiul împărţitor, noul împărţitor este restul, iar
procesul se reia de la pasul b.
În program, câtul împărţirii nu se calculează, având în vedere existenţa în Pascal a
operatorului MOD, care returnează restul împărţirii întregi a două numere naturale.

Program cmmdc_al_doua_numere;
Var
a,b,d,i,r:word;
Begin
write('Numerele: '); readln(a,b);
d:=a; i:=b;
repeat
r:=d mod i;
if r=0 then writeln('C.m.m.d.c. = ',i)
else if r=1 then writeln('Numere prime intre ele !')
else begin d:=i; i:=r end
until r < 2
End.

1.21. Determinarea c.m.m.d.c. dintr-un şir de numere naturale nenule.

Fie şirul X=(x1,x2,...,xn). Pentru determinarea c.m.m.d.c. al şirului X se


foloseşte proprietatea acestuia de asociativitate, astfel:

23
Algoritmi în programare. Aplicaţii

CMMDC1 = cmmdc(x1, x2);


CMMDC2 = cmmdc(CMMDC1, x3);
...
CMMDCn-1= cmmdc(CMMDCn-2, xn);
-----------------------------
CMMDC = CMMDCn-1,
unde c.m.m.d.c. pentru două numere se determină conform exerciţiului 1.20. Pentru
că cei mai mari divizori comuni parţiali CMMDC1, CMMDC2,..., CMMDCn-1 sunt de
fapt împărţitorii curenţi, nu se folosesc variabile suplimentare. Procesul se opreşte fie
când şirul de numere a fost epuizat, caz în care c.m.m.d.c. a fost determinat, fie când
în urma unei împărţiri restul este 1, caz în care numerele sunt prime între ele.

Program cmmdc_al_unui_sir_de_numere;
Var
x:array[1..20] of word; k,n,d,i,r:word;
Begin
write('Dimensiunea sirului: '); readln(n);
write('Numerele: ');
for i:=1 to n do read(x[i]);
d:=x[1]; r:=0; k:=2;
while (r<>1) and (k<=n) do
begin
i:=x[k];
repeat
r:=d mod i; d:=i; i:=r
until r < 2;
k:=k+1
end;
if r<>1 then writeln('C.m.m.d.c. = ',d)
else writeln('Numere prime intre ele !')
End.

1.22. Fie o matrice Amxn care reprezintă notele obţinute de m studenţi la n


discipline. Să se determine:
a) studenţii integralişti (care au toate notele ≥ 5);
b) studenţii bursieri (integraliştii cu media ≥ 8,50);
c) disciplinele la care s-au înregistrat cei mai mulţi restanţieri;
d) media pe fiecare disciplină (se iau în calcul doar notele de promovare).

program note;
uses crt;
var a:array[1..15,1..20] of 0..10;
med:array[1..20] of real;
dsp:array[1..20] of 1..20;
stb:array[1..15] of real;
sti:array[1..15] of 1..15;
m,n,i,j,k,maxr,nr:byte;

24
Exerciţii comentate

vb:boolean;
begin
clrscr;
write('Nr. de studenti:');readln(m);
write('Nr. de discipline:');readln(n);
for i:=1 to m do
for j:=1 to n do begin
write('Nota studentului ',i,' la disciplina ',
j,' :');
readln(a[i,j])
end;
k:=0;
for i:=1 to m do begin
j:=1;
while (j<=n) and (a[i,j]>=5) do inc(j);
if j>n then
begin
k:=k+1;
sti[k]:=i
end
end;
if k=0 then writeln('Nu exista studenti integralisti!')
else begin
writeln('Studentii integralisti sunt:');
for i:=1 to k do write(sti[i]:4)
end;
writeln('STUDENTII BURSIERI');
writeln;
if k=0 then writeln('Nu exista bursieri!')
else
begin
vb:=false;
for i:=1 to k do begin
stb[i]:=0;
for j:=1 to n do
stb[i]:=stb[i]+a[sti[i],j];
stb[i]:=stb[i]/n;
if stb[i]>=8.5 then
begin
vb:=true;
writeln('Studentul ',sti[i],
' este bursier cu media',stb[i]:6:2);
readln
end
end;
if not vb then writeln('Nu exista bursieri!');
readln
end;
writeln;
writeln('DISCIPLINELE CU CEI MAI MULTI RESTANTIERI');

25
Algoritmi în programare. Aplicaţii

writeln;
for j:=1 to n do begin
k:=0;
for i:=1 to m do if a[i,j]<5 then inc(k);
if j=1 then begin
maxr:=k;
nr:=1;
dsp[nr]:=j
end
else if k>maxr then begin
maxr:=k;
nr:=1;
dsp[nr]:=j
end
else if k=maxr then begin
nr:=nr+1;
dsp[nr]:=j
end
end;
writeln('Disciplinele sunt:');
for i:=1 to nr do write(dsp[i]:4);
readln;
writeln;
writeln('MEDIA PE FIECARE DISCIPLINA');
writeln;
for j:=1 to n do begin
med[j]:=0;
k:=0;
for i:=1 to m do
if a[i,j]>=5 then
begin
inc(k);
med[j]:=med[j]+a[i,j]
end;
if k>0 then med[j]:=med[j]/k
end;
for j:=1 to n do
if med[j]<>0 then
writeln('La disciplina ',j,
' - media a fost',med[j]:6:2)
else
writeln('La disciplina ',j,
' nu a promovat nici-un student');
readln
end.

26
2. Subprograme interne

2.1. Fie o matrice de dimensiuni mxn, reprezentând consumurile de energie


pentru fabricarea a m produse într-o perioada de n zile. Sa se scrie programul
Pascal care afiseaza pe monitor produsele care au înregistrat consumuri
constante pe întreaga perioada. Determinarea produselor care îndeplinesc
conditia ceruta se va realiza într-un subprogram.
Subprogramul este de tip procedura si are ca parametri de intrare: numarul
de produse (m), numarul de zile (n) si matricea consumurilor (a), iar ca parametri
de iesire: vectorul cu pozitiile produselor care îndeplinesc conditia ceruta (v) si
numarul acestora (p≥0). Matricea consumurilor este parcursa în subprogram
lexicografic.

program consumuri;
type matrice=array[1..15,1..20] of real;
vector=array[1..15] of byte;
var a:matrice; r:vector; m,n,i,j,k:byte;
procedure consumuri_constante(m,n:byte; a:matrice;
var p:byte; var v:vector);
var i,j:byte; x:real;
begin
p:=0;
for i:=1 to m do
begin
x:=a[i,1]; j:=2;
while (j<=n) and (a[i,j]=x) do inc(j);
if j>n then begin inc(p); v[p]:=i end
end
end;
{program principal}
begin
write(’Nr. de produse:’); readln(m);
write(’Nr. de zile: ’); readln(n);
for i:=1 to m do
for j:=1 to n do
begin
write(’consum [’,i,’,’,j,’]= ’);
readln(a[i,j])
end;
consumuri_constante(m,n,a,k,r);
if k<>0 then begin
write(’Produsele cu consumuri constante:’);
for i:=1 to k do write(r[i]:3)
end
else
writeln(’Nu exista produse cu consumuri constante!’)
end.

27
Algoritmi în programare. Aplicatii

2.2. Fie o matrice de dimensiuni mxn, reprezentând vânzarile valorice a m


produse într-o perioada de n zile. Sa se scrie programul Pascal care afiseaza
pe monitor zilele în care nu s-au înregistrat vânzari. Determinarea zilelor care
îndeplinesc conditia ceruta se va realiza într-un subprogram.
Subprogramul este de tip procedura si are ca parametri de intrare: numarul
de produse (m), numarul de zile (n) si matricea vânzarilor (a), iar ca parametri de
iesire: vectorul cu zilele care îndeplinesc conditia ceruta (v) si numarul acestora
(p≥0). Matricea vânzarilor este parcursa în subprogram invers lexicografic.

program vanzari;
uses crt;
type matrice=array[1..15,1..20] of real;
vector=array[1..20] of byte;
var a:matrice; r:vector; m,n,i,j,k:byte;
procedure zile_fara_vanzari(m,n:byte; a:matrice;
var p:byte; var v:vector);
var i,j:byte;
begin
p:=0;
for j:=1 to n do
begin
i:=1;
while (i<=m) and (a[i,j]=0) do inc(i);
if i>m then begin
inc(p);
v[p]:=j
end
end
end;
{program principal}
begin
clrscr;
write(’Nr. de produse:’); readln(m);
write(’Nr. de zile: ’); readln(n);
for i:=1 to m do
for j:=1 to n do begin
write(’vanzari [’,i,’,’,j,’]=’);
readln(a[i,j])
end;
zile_fara_vanzari(m,n,a,k,r);
if k<>0 then begin
write(’Zilele fara vanzari sunt:’);
for i:=1 to k do write(r[i]:3)
end
else
writeln(’Nu exista zile fara vanzari!’);
readln
end.

28
Subprograme interne

2.3. Fie o matrice de dimensiuni mxn, reprezentând notele obtinute de m


studenti la n discipline. Sa se scrie programul Pascal care afiseaza pe monitor
mediile studentilor integralisti. Determinarea studentilor care îndeplinesc
conditia ceruta se va realiza într-un subprogram.
Subprogramul este de tip procedura si are ca parametri de intrare: numarul
de studenti (m), numarul de discipline (n) si matricea notelor (a), iar ca parametri
de iesire: vectorul cu pozitiile studentilor integralisti (s), vectorul cu mediile
acestora (v) si numarul de studenti care îndeplinesc conditia ceruta (p≥0). Matricea
notelor este parcursa lexicografic în subprogram. Un student integralist are note de
trecere la toate disciplinele.

program note_discipline;
uses crt;
type
matrice=array[1..15,1..20] of 0..10;
vector=array[1..15] of byte;
vector1=array[1..15] of real;
var a:matrice;
r:vector1;
s:vector;
m,n,i,j,k:byte;
procedure medii_integralisti(m,n:byte; a:matrice;
var p:byte; var v:vector1; var s:vector);
var i,j:byte; ss:real;
begin
p:=0;
for i:=1 to m do
begin
j:=1;
ss:=0;
while (j<=n) and (a[i,j]>4) do begin
ss:=ss+a[i,j];
inc(j)
end;
if j>n then
begin
inc(p);
v[p]:=ss/n;
s[p]:=i
end
end
end;
{program principal}
begin
clrscr;
write(’Nr. de studenti: ’); readln(m);
write(’Nr. de discipline:’); readln(n);
for i:=1 to m do

29
Algoritmi în programare. Aplicatii

begin
writeln(’Studentul ’,i);
for j:=1 to n do begin
write(’nota la disciplina ’,j,’= ’);
readln(a[i,j])
end;
end;
medii_integralisti(m,n,a,k,r,s);
if k<>0 then
begin
writeln(’Mediile studentilor integralisti sunt:’);
for i:=1 to k do
writeln(’studentul’,s[i]:2,’ cu media’,r[i]:6:2)
end
else writeln(’Nu exista studenti integralisti!’);
readln
end.

2.4. Fie o matrice de dimensiuni mxn reprezentând profiturile nete obtinute de


m societati comerciale într-o perioada de n ani. Sa se scrie programul Pascal
care afiseaza pe monitor societatile care au înregistrat profitul net maxim în
perioada analizata. Determinarea societatilor care îndeplinesc conditia ceruta
se va realiza într-un subprogram.
Subprogramul este de tip procedura si are ca parametri de intrare: numarul
de societati(m), numarul de ani (n) si matricea profiturilor nete (a), iar ca parametri
de iesire: profitul net maxim (max), vectorul cu pozitiile societatilor care au
înregistrat profitul maxim (s) si numarul de societati care au îndeplinit conditia
(p≥1). Matricea profiturilor este parcursa lexicografic în subprogram. Profitul
maxim se calculeaza din profiturile cumulate pe n ani de fiecare societate în parte.
Maximul si pozitiile aparitiei lui se determina în etape distincte.

program profituri_nete;
uses crt;
type
matrice=array[1..15,1..20] of real;
vector=array[1..15] of byte;
vector1=array[1..15] of real;
var
a:matrice;
r:vector1;
s:vector;
m,n,i,j,k:byte;
c:real;
procedure profit_maxim(m,n:byte; a:matrice; var p:byte;
var max:real; var s:vector);
var
i,j:byte;
x:vector1;

30
Subprograme interne

begin
for i:=1 to m do
begin
x[i]:=0;
for j:=1 to n do x[i]:=x[i]+a[i,j];
if i=1 then max:=x[i]
else if x[i]>max then max:=x[i];
end;
p:=0;
for i:=1 to m do
if x[i]=max then begin inc(p); s[p]:=i end
end;
{program principal}
begin
clrscr;
write(’Nr. de societati:’); readln(m);
write(’Nr. de ani: ’); readln(n);
for i:=1 to m do begin
writeln(’Societatea ’,i);
for j:=1 to n do begin
write(’profitul net in anul ’,j,’= ’);
readln(a[i,j])
end
end;
profit_maxim(m,n,a,k,c,s);
writeln(’Profitul net maxim este ’,c:8:2);
write(’Societatile care l-au inregistrat: ’);
for i:=1 to k do write(s[i]:4)
end.

2.5. Sa se elaboreze un program Pascal care sa includa un subprogram pentru


determinarea liniilor unei matrice dreptunghiulare care au elem entele în
progresie aritmetica.
Subprogramul este de tip procedura si are ca parametri de intrare: matricea
de elemente reale (a), numarul de linii (m) si numarul de coloane (n), iar ca
parametri de iesire: un vector de elemente logice (v) în care vi este true daca linia
i este progresie aritmetica si false în caz contrar si un indicator de eroare (er )
care returneaza true daca numarul de coloane este mai mic decât 3 (numarul
minim de termeni necesari) . Matricea este parcursa lexicografic în subprogram.
Citirea si afisarea datelor de intrare/iesire se realizeaza în programul principal.

program determinare_linii_in_progresie;
uses crt;
type
matrice=array[1..10,1..15] of real;
vector=array[1..10] of boolean;
var a:matrice;
v:vector;

31
Algoritmi în programare. Aplicatii

vb:boolean;
i,j,k,m,n:byte;
procedure linii_pa(m,n:byte; a:matrice; var v:vector;
var er:boolean);
var i,j:byte;
begin
if n<3 then er:=true
else
begin
er:=false;
for i:=1 to m do begin
v[i]:=false;
j:=2;
while (j<=n-1)and(a[i,j]=(a[i,j-1]+a[i,j+1])/2) do
inc(j);
if j>n-1 then v[i]:=true
end {for}
end {else}
end;
{programul principal}
begin
clrscr;
write('Nr. de linii: '); readln(m);
write('Nr. de coloane:'); readln(n);
for i:=1 to m do
for j:=1 to n do
begin
write('el[',i,',',j,']=');
readln(a[i,j])
end;
linii_pa(m,n,a,v,vb);
if vb then
writeln('Matricea are mai putin de 3 coloane!')
else begin
k:=0;
for i:=1 to m do
if v[i] then
begin
writeln('Linia ',i);
inc(k)
end;
if k<>0 then
writeln('Au elementele in progresie aritmetica')
else
writeln('Nu exista linii cu elemente in progresie!')
end {else};
readln
end.

32
Subprograme interne

2.6. Sa se elaboreze un program Pascal care sa includa un subprogram pentru


determinarea coloanelor unei matrice dreptunghice care au elementele în
progresie geometrica.
Subprogramul este de tip procedura si are ca parametri de intrare: matricea
de elemente reale (a), numarul de linii (m) si numarul de coloane (n), iar ca
parametri de iesire: un vector de elemente logice (v) în care vj este true daca
coloana j este progresie geometrica si false în caz contrar si un indicator de
eroare (er) care returneaza true daca numarul de linii este mai mic decât 3
(numarul minim de termeni necesari). Matricea este parcursa invers lexicografic în
subprogram. Citirea si afisarea datelor de ni trare/iesire se realizeaza în programul
principal.

program determinare_coloane_in_progresie;
uses crt;
type
matrice=array[1..10,1..15] of real;
vector=array[1..15] of boolean;
var
a:matrice; v:vector;
vb:boolean;
i,j,k,m,n:byte;
procedure coloane_pg(m,n:byte; a:matrice; var v:vector;
var er:boolean);
var
i,j:byte;
q:real;
begin
if m<3 then er:=true
else
begin
er:=false;
for j:=1 to n do
begin
v[j]:=false; i:=3;
while i<=m do
begin
if a[1,j]<>0 then
begin
q:=a[2,j]/a[1,j];
if a[i,j]=a[i-1,j]*q then inc(i)
else i:=m+3
end
else i:=m+5;
if i=m+1 then v[j]:=true
end {while}
end {for}
end {else}
end;

33
Algoritmi în programare. Aplicatii

{programul principal}
begin
clrscr;
write('Nr. de linii: '); readln(m);
write('Nr. de coloane:'); readln(n);
for i:=1 to m do
for j:=1 to n do begin
write('el[',i,',',j,']=');
readln(a[i,j])
end;
coloane_pg(m,n,a,v,vb);
if vb then
writeln('Matricea are mai putin de 3 linii!')
else
begin
k:=0;
for j:=1 to m do
if v[j]=true then
begin
writeln('coloana ',j);
inc(k)
end;
if k<>0 then
writeln('Au elementele in progresie geometrica.')
else
writeln('Nu exista linii cu elemente in progresie!')
end {else}
end.

2.7. Sa se elaboreze un program Pascal care sa includa un subprogram pentru


crearea unui vector cu elementele strict pozitive din triunghiul inferior
diagonalei principale (inclusiv diagonala) dintr-o matrice patrata.
Subprogramul este de tip procedura si are ca parametri de intrare: matricea
de elemente reale (a), numarul de linii/coloane (n), iar ca parametri de iesire:
vectorul cu elementele strict pozitive (v) si numarul de elemente gasite în
triunghiul inferior (0≤k≤n(n+1)/2). Citirea si afisarea datelor de intrare/iesire se
realizeaza în programul principal.

program triunghi_inferior_diagonala_principala;
uses crt;
type matrice=array[1..15,1..15] of real;
vector=array[1..120] of real;
var a:matrice;
v:vector;
i,j,m,n:byte;
procedure creare_vector(n:byte; a:matrice; var v:vector;
var k:byte);
var i,j:byte;

34
Subprograme interne

begin
k:=0;
for i:=1 to n do
for j:=1 to i do
if a[i,j]>0 then begin inc(k); v[k]:=a[i,j] end
end;
{programul principal}
begin
clrscr; write('Dimensiunea matricei:'); readln(n);
for i:=1 to n do
for j:=1 to n do begin
write('el[',i,',',j,']='); readln(a[i,j])
end;
creare_vector(n,a,v,m);
if m>0 then begin
writeln('Elementele vectorului sunt:');
for i:=1 to m do write(v[i]:6:2)
end
else writeln('Nu exista elemente > 0!')
end.

2.8. Sa se elaboreze un program Pascal care sa includa un subprogram pentru


crearea unui vector cu elementele de valoare para din triunghiul superior
diagonalei secundare (inclusiv diagonala) dintr-o matrice patrata.
Subprogramul este de tip procedura si are ca parametri de intrare: matricea
de elemente naturale (a), numarul de linii/coloane (n), iar ca parametri de iesire:
vectorul cu elementele de valoare para (v) si numarul de elemente gasite în
triunghiul superior (0≤k≤n(n+1)/2). Citirea si afisarea datelor de intrare/iesire se
realizeaza în programul principal. Paritatea se defineste numai pe numere naturale
si se poate verifica în program fie prin restul împartirii la 2 (operatorul MOD), fie
prin functia ODD.

program triunghi_superior_diagonala_secundara;
uses crt;
type matrice=array[1..15,1..15] of word;
vector=array[1..120] of word;
var a:matrice; v:vector; i,j,m,n:byte;
procedure creare_vector(n:byte; a:matrice; var v:vector;
var k:byte);
var i,j:byte;
begin
k:=0;
for i:=1 to n do
for j:=1 to n-i+1 do
if a[i,j] mod 2=0 then begin
inc(k); v[k]:=a[i,j]
end
end;

35
Algoritmi în programare. Aplicatii

{programul principal}
begin
clrscr; write('Dimensiunea matricei:'); readln(n);
for i:=1 to n do
for j:=1 to n do begin
write('el[',i,',',j,']=');
readln(a[i,j])
end;
creare_vector(n,a,v,m);
if m>0 then begin
writeln('Elementele vectorului sunt:');
for i:=1 to m do write(v[i]:4)
end
else writeln('Nu exista elemente pare inferior!')
end.

2.9. Sa se elaboreze un program Pascal care sa includa un subprogram pentru


determinarea mediei aritmetice a elementelor strict pozitive pentru fiecare
linie a unei matrice dreptunghiulare.
Subprogramul este de tip procedura si are ca parametri de intrare: matricea
de elemente reale (a), numarul de linii (m) si numarul de coloane (n), iar ca
parametru de iesire: vectorul cu media pe fiecare linie a matricei (v). Daca nu
exista cel putin doua elemente strict pozitive, media nu se poate calcula si vi=0.
Citirea si afisarea datelor de intrare/iesire se realizeaz a în programul principal.
program medii_aritmetice_pe_linii;
uses crt;
type matrice=array[1..10,1..15] of real;
vector=array[1..10] of real;
var a:matrice; v:vector; i,j,m,n:byte;
procedure medie_linii(m,n:byte; a:matrice; var v:vector);
var i,j,k:byte;
begin
for i:=1 to m do
begin
k:=0; v[i]:=0;
for j:=1 to n do
if a[i,j]>0 then begin
inc(k);
v[i]:=v[i]+a[i,j]
end;
if k>1 then v[i]:=v[i]/k else v[i]:=0
end
end;
{programul principal}
begin
clrscr; write('Nr. de linii: '); readln(m);
write('Nr. de coloane:'); readln(n);
for i:=1 to m do

36
Subprograme interne

for j:=1 to n do begin


write('el[',i,',',j,']='); readln(a[i,j])
end;
medie_linii(m,n,a,v);
for i:=1 to m do
if v[i]<>0 then
writeln('Media pe linia ',i,' este ', v[i]:6:2)
else writeln('Nu exista medie pe linia ',i)
end.

2.10. Sa se elaboreze un program Pascal care sa includa un subprogram


pentru determinarea produsului vectorial dintre fiecare dou a linii ale unei
matrice dreptunghiulare.
Subprogramul este de tip procedura si are ca parametri de intrare: matricea
de elemente reale (a), numarul de linii (m) si numarul de coloane (n), iar ca
parametru de iesire: matricea rezultat (b), cu m(m-1)/2 linii si n coloane. Citirea si
afisarea datelor de intrare/iesire se realizeaza în programul principal.
program produs_vectorial;
uses crt;
type matrice=array[1..10,1..20] of real;
matrice_rez=array[1..45,1..20] of real;
var a:matrice; b:matrice_rez; i,j,m,n:byte;
procedure pv_linii(m,n:byte; a:matrice; var b:matrice_rez);
var i,j,l,k:byte;
begin
k:=0;
for i:=1 to m-1 do
for j:=i+1 to m do begin
inc(k);
for l:=1 to n do b[k,l]:=a[i,l]*a[j,l]
end
end;
{programul principal}
begin
clrscr; write('Nr. de linii: '); readln(m);
write('Nr. de coloane:'); readln(n);
for i:=1 to m do
for j:=1 to n do begin
write('el[',i,',',j,']='); readln(a[i,j])
end;
pv_linii(m,n,a,b);
writeln('Matricea rezultat este:');
for i:=1 to m*(m-1)div 2 do begin
for j:=1 to n do write(b[i,j]:6:2);
writeln
end
end.

37
Algoritmi în programare. Aplicatii

2.11. Sa se realizeze un program Pascal pentru sortarea unui vector prin


tehnica quicksort.
Fie secventa (x(p),x(p+1),...,x(u)), unde p ia valoarea initiala 1, iar u este
dimensiunea vectorului. Se pozitioneaza x(p) astfel încât toate elementele din fata
lui sa fie mai mici, iar toate de dupa el sa fie mai mari, prin interschimbari repetate.
Fie aceasta pozitie i. Procedeul se reia pentru secventele (x(p),...x(i-1)), respectiv
(x(i+1),...,x(u)). Pozitionarea lui x(p) se realizeaza astfel:
a. se compara x(p) cu x(u), x(u-1),... pâna la primul u1, cu x(u1)<x(p); x(u1)
si x(p) se interschimba, iar p1=p+1;
b. se compara x(u1) cu x(p1), x(p1+1),... pâna la primul p2, cu x(p2)>x(u1);
x(u1) si x(p2) se interschimba.
c. pentru p=p2 si u=u1 se repeta pasii a) si b) pâna când p≥u.
Procedura quick realizeaza sortarea propriu-zisa a vectorului initial. Ea
apeleaza procedura poz care va împarti vectorul init ial în doi subvectori, apoi este
autoapelata procedura quick (recursivitate) pentru sortarea celor doi subvectori.

program quick_sort;
uses crt;
var x:array[1..100] of real; n,i:byte;
procedure poz(p,u:byte; var k:byte);
{ procedura returneaza pozitia finala pe care o va
ocupa elementul x[k] in vectorul sortat.}
var
i,j:byte;
l,di,dj:shortint; {di, dj = pasii de incrementare pentru
i si j, indicand sensul parcurgerii}
v:real;
begin
i:=p; j:=u; di:=0; dj:=-1;
while i<j do
if x[i]>x[j] then
begin
v:=x[i]; x[i]:=x[j]; x[j]:=v;
l:=di; di:=-dj; dj:=-l;
i:=i+di; j:=j+dj
end
else begin i:=i+di; j:=j+dj end;
k:=i
end;
procedure quick(p,u:byte);
var i:byte;
begin
if p<u then
begin
poz(p,u,i); quick(p,i-1); quick(i+1,u)
end
end;

38
Subprograme interne

{programul principal}
begin
clrscr; write('Dimensiunea vectorului:'); readln(n);
write('Elementele vectorului:');
for i:=1 to n do begin
write('x[', i , ']= ');
readln(x[i])
end;
quick(1,n);
for i:=1 to n do write(x[i]:6:2,' ')
end.

2.12. Sa se realizeze programul Pascal pentru sortarea unui vector prin


tehnica de interclasare.
Pasii algoritmului sunt:
a) se împarte vectorul în doua secvente, astfel ([ ] semnifica parte întreaga) :
S1= {v(1),v(2),...,v([n/2])} si S2= {v([n/2]+1), ..., v(n)};
b) se apeleaza recursiv procedura de sortare pentru vectorii S1 si S2;
c) se interclaseaza vectorii S1 si S2, obtinându-se vectorul sortat.
Subprogramul interc realizeaza interclasarea a doi vectori. Elementele primului
vector au indicii cuprinsi între l si m, iar elementele celui de-al doilea vector au
indicii cuprinsi între m+1 si r. Procedura inters realizeaza sortarea propriu-zisa
a elementelor vectorului initial recurgând la tehnica „DIVIDE ET IMPERA”.
Vectorul este divizat în doi subvectori care se sorteaza prin dublul autoapel al
procedurii inters (recursivitate), iar rezultatele divizarii se interclaseaza apelând
procedura interc .

program inter_sort;
uses crt;
var v, par:array[1..1000] of real; n,i:word;
procedure interc(l,m,r:word);
var i,j,k:word;
begin
if l<r then begin
i:=l; j:=m+1; k:=1;
while(i<=m) and (j<=r) do
begin
if v[i]<v[j] then begin
par[k]:=v[i]; i:=i+1; k:=k+1
end
else begin
par[k]:=v[j]; j:=j+1; k:=k+1
end
end;
if i<=m then
for j:=i to m do
begin par[k]:=v[j]; k:=k+1 end

39
Algoritmi în programare. Aplicatii

else
for i:=j to r do begin par[k]:=v[i]; k:=k+1 end
end;
for i:=0 to r-l do v[l+i]:=par[i+1]
end;
procedure inters(l,r:word);
var i:word;
begin
if l<r then begin
i:=(l+r)div 2; inters(l,i);inters(i+1,r);interc(l,i,r)
end
end;
{programul principal}
begin
clrscr;
write('Dimensiunea vectorului:'); readln(n);
write('Elementele vectorului:');
for i:=1 to n do begin
write('v[', i , ']= '); readln(v[i])
end;
inters(1,n);
for i:=1 to n do write(v[i]:8:2,' ')
end.

2.13. Sa se elaboreze un program Pascal care sa includa un subprogram care


verifica daca o matrice patrata este simetrica sau nu.
Subprogramul este de tip functie si are ca parametri de intrare dimensiunea
matricei (m) si matricea de elemente reale (a). Rezultatul este de tip logic. Citirea si
afisarea datelor de intrare/iesire se realizeaza în programul principal.

program verificare_matrice_simetrica;
type
matrice=array[1..10,1..10] of real;
var
a:matrice;
m,i,j:byte; {i si j sunt variabile globale}
function simetrica(m:byte; a:matrice):boolean;
var
i,j:byte; {i si j sunt variabile locale}
begin
simetrica:=true;
for i:=1 to m do
for j:=1 to i-1 do
if a[i,j] <> a[j,i] then simetrica:=false
end;
{program principal}
begin
write('Nr. de linii: '); readln(m);
write('Nr. de coloane: '); readln(n);

40
Subprograme interne

for i:=1 to m do
for j:=1 to n do
begin
write('(',i,',',j,')=' );
readln(a[i,j])
end;
if simetrica(m,n,a) then
writeln('Matricea este simetrica !')
else writeln('Matricea nu este simetrica !')
end.

2.14. Sa se elaboreze un program Pascal care sa includa un subprogram care


determina urma unei matrice patrate.
Subprogramul este de tip functie si are ca parametri de intrare dimensiunea
matricei (m) si matricea de elemente reale (a). Rezultatul este de tip real. Urma
matricei se calculeaza ca suma elementelor de pe diagonala principala. Citirea si
afisarea datelor de intrare/iesire se realizeaza în programul principal.

program urma_matricei;
type matrice=array[1..10,1..10] of real;
var a:matrice; m,i,j:byte;
function urma(m:byte; a:matrice):real;
var i:byte; s:real;
begin
s:=0;
for i:=1 to m do s:=s+a[i,i];
urma:=s
end;
{program principal}
begin
write('Dimensiunea matricei: '); readln(m);
for i:=1 to m do
for j:=1 to m do begin
write('(',i,',',j,')=' ); readln(a[i,j])
end;
writeln('Urma matricei = ',urma(m,a):10:2)
end.

2.15. Sa se elaboreze un program Pascal care sa includa un subprogram care


determina amplitudinea unui sir de numere (memorate într-un vector de
elemente reale).
Amplitudinea unui sir de numere se determina ca diferenta (în valoare
absoluta) dintre maximul si minimul din sirul respectiv. Subprogramul de
determinare a amplitudinii este de tip functie si are ca parametri de intrare
dimensiunea vectorului (n) si vectorul de elemente reale (v). Rezultatul este de tip
n n
real. Deoarece min (xi ) = − max( − xi ) se construieste o functie (maxim) interna
i =1 i =1

41
Algoritmi în programare. Aplicatii

subprogramului amplit care determina maximul dintr-un vector si care este


apelata de doua ori. Citirea si afisarea datelor de intrare/iesire se realizeaza în
programul principal.

program amplitudine;
uses crt;
type vector=array[1..100] of real;
var v:vector; n,i:byte;
function amplit(n:byte; v:vector):real;
var max,min:real; i:byte;
function maxim(m:byte; x:vector):real;
var r:real; i:byte;
begin
r:=x[1];
for i:=2 to m do if x[i]>r then r:=x[i];
maxim:=r
end;
begin
max:=maxim(v,n);
for i:=1 to n do v[i]:=-v[i];
min:=-maxim(v,n);
amplit:=abs(max-min)
end;
{programul principal}
begin
clrscr; write('Nr. de elemente:'); readln(n);
for i:=1 to n do
begin write('v[',i,']='); readln(v[i]) end;
writeln('Amplitudinea vectorului =',amplit(v,n):8:2);
readln
end.

2.16. Sa se elaboreze un program Pascal care sa includa un subprogram


pentru determinarea celui mai mare divizor comun dintre elementele unei
matrice dreptunghiulare.
Subprogramul cmmdc este de tip functie si are ca parametri de intrare
dimensiunile matricei (m si n) si matricea de elemente naturale (a). Rezultatul este
de tip întreg. Pentru obtinerea c.m.m.d.c. din matrice se determina c.m.m.d.c. de pe
fiecare linie si apoi c.m.m.d.c. din rezultatele partiale. Determinarea c.m.m.d.c.
dintr-un sir de numere se realizeaza prin functia cmmdc_vect, interna
subprogramului cmmdc . Citirea si afisarea datelor de intrare/iesire se realizeaza în
programul principal.

program cmmdc_mat;
uses crt;
type
matrice=array[1..10,1..15] of word;

42
Subprograme interne

vector=array[1..15] of word;
var a:matrice;
m,n,i,j:byte;
c:word;
function cmmdc(m,n:byte; a:matrice):word;
var x,y:vector;
i,j:byte;
function cmmdc_vect(n:byte; v:vector):word;
var i:byte;
deim,imp,rest:word;
begin
deim:=v[1]; rest:=0; i:=2;
while (i<=n) and (rest<>1) do
begin
imp:=v[i];
repeat
rest:=deim mod imp;
deim:=imp;
imp:=rest
until rest<2;
inc(i)
end;
if rest<>1 then cmmdc_vect:=deim
else cmmdc_vect:=1
end;
begin
for i:=1 to m do
begin
for j:=1 to n do x[j]:=a[i,j]; {salvare linie i}
y[i]:=cmmdc_vect(n,x) {cmmdc de pe linia i}
end;
cmmdc:=cmmdc_vect(m,y)
end;
{programul principal}
begin
clrscr;
write('Nr. de linii:'); readln(m);
write('Nr. de coloane:'); readln(n);
for i:=1 to m do
for j:=1 to n do
begin
write('a[',i,',',j,']=');
readln(a[i,j])
end;
c:=cmmdc(m,n,a);
if c<>1 then writeln('CMMDC din matrice =',c:4)
else writeln('Numere prime intre ele!');
readln
end.

43
Algoritmi în programare. Aplicatii

2.17. Sa se elaboreze un program Pascal care sa contina subprograme pentru


determinarea permutarilor (P n), aranjamentelor (Ank) si combinarilor (C nk).
Se construiesc trei subprograme de tip functie. Functia permutari
calculeaza Pn=n!, functia aranjamente calculeaza An k=Pn/Pn- k si functia
combinari calculeaza Cn k=An k/P k. Parametrii de intrare si rezultatele sunt de tip
întreg si nu se fac validari. Citirea si afisarea datelor de intrare/iesire se realizeaza
în programul principal.

program p_a_c;
var
n,k:byte;
function permutari(n:byte):real;
var
i:byte;
r:real;
begin
r:=1;
for i:=2 to n do r:=r*i;
permutari:=r
end;
function aranjamente(n,k:byte):longint;
begin
aranjamente:=trunc(permutari(n)/permutari(n-k))
end;
function combinari(n,k:byte):longint;
begin
combinari:=trunc(aranjamente(n,k)/permutari(k))
end;
{programul principal}
begin
write('n = '); readln(n);
write('k (0<k≤n) = '); readln(k);
writeln('Permutari de',n,' = ',permutari(n):10:0);
writeln('Aranjamente de ',n,' luate cate ',k,' = ',
aranjamente(n,k));
writeln('Combinari de ',n,' luate cate ',k,' = ',
combinari(n,k))
end.

2.18. Sa se elaboreze un program Pascal care sa includa un subprogram


pentru interclasarea a doua siruri de caractere neordonate.
Subprogramul interclasare este de tip functie si are ca parametri de
intrare cele doua siruri de caractere (s1 si s2). Rezultatul este de tip STRING (de
lungime maxima). Pentru ordonarea sirurilor se utilizeaza o procedura de sortare
sortare_sir, interna functiei interclasare . Citirea si afisarea datelor de
intrare/iesire se realizeaza în programul principal.

44
Subprograme interne

program siruri;
uses crt;
var s1,s2,s:string;
function interclasare(var s1,s2:string):string;
var
rez:string;
i,j,k,l:byte;
procedure sortare_sir(var s:string);
var
i,j:byte; c:char;
begin
for i:=1 to length(s)-1 do
for j:=i+1 to length(s) do
if s[i]>s[j] then begin
c:=s[i];
s[i]:=s[j];
s[j]:=c
end
end;
begin
sortare_sir(s1);
sortare_sir(s2);
i:=1; j:=1; k:=0;
while (i<=length(s1)) and (j<=length(s2)) do
if s1[i]<s2[j] then begin
inc(k);
rez[k]:=s1[i];
inc(i)
end
else begin
inc(k);
rez[k]:=s2[j];
inc(j)
end;
if i>length(s1) then
for l:=j to length(s2) do
begin
inc(k);
rez[k]:=s2[l]
end
else
for l:=i to length(s1) do
begin
inc(k);
rez[k]:=s1[l]
end;
{memorare lungime efectiva}
rez[0]:=chr(length(s1)+length(s2));
interclasare:=rez
end;

45
Algoritmi în programare. Aplicatii

{programul principal}
begin
clrscr;
writeln('Primul sir (maxim 126 de caractere):');
readln(s1);
write('Al doilea sir (maxim 126 de caractere):');
readln(s2);
writeln('Sirul rezultat este:');
writeln(interclasare(s1,s2))
readln
end.

46
3. Subprograme externe

3.1. Sa se realizeze o unitate Pascal care sa contina subprograme pentru


realizarea operatiilor de reuniune, intersectie, diferenta si produs cartezian
dintre doua multimi.
a) Reuniunea dintre doua multimi A si B se defineste astfel:
A∪B={xx∈A sau x∈B}
Cunoscuta si sub numele de „interclasare cu selectie”, operatia de reuniune
presupune parcurgerea secventiala a multimilor initiale si trecerea în multimea
rezultat a elementelor care se regasesc în cele doua multimi, fiecare luat o singura
data.
b) Intersectia dintre doua multimi A si B se defineste astfel:
A∩B={xx∈A si x∈B}
Se obtine o multime cu elementele comune multimilor initiale. Daca intersectia
este vida, atunci cardinalul multimii rezultat este 0.
c) Diferenta dintre doua multimi A si B se defineste astfel:
A\B={xx∈A si x∉B}.
d) Produsul cartezian dintre doua multimi A si B se defineste astfel:
AxB={(x,y) x∈A si y∈B}.
Pentru rezolvarea problemei propuse, unitatea contine subprograme
corespunzatoare operatiilor prezentat e anterior. Se utilizeaza doua proceduri
interne pentru sortarea elementelor unui vector, respectiv pentru compactarea
elementelor unui vector (prin compactare se asigura unicitatea valorilor
elementelor din multimile initiale, eliminându-se dublurile).
Semnificatia parametrilor formali este urmatoarea:
• m, n = numarul de elemente ale multimilor initiale;
• a, b = multimile initiale (vectori);
• c = multimea rezultat (vector);
• card = numarul de elemente ale multimii rezultat.
unit multimi;
INTERFACE
type multime=array[1..50] of integer;
produs=array[1..100] of record
x,y:integer
end;
procedure reuniune(m,n:byte; var a,b,c:multime;
var card:byte);
procedure intersectie(m,n:byte; var a,b,c:multime;
var card:byte);
procedure diferenta(m,n:byte; var a,b,c:multime;
var card:byte);
procedure produs_cartezian(m,n:byte; var a,b:multime;
var c:produs);

47
Algoritmi în programare. Aplicatii

IMPLEMENTATION
procedure sortare(n:byte; var v:multime);
var i:byte; aux:integer; vb:boolean;
begin
repeat
vb:=false;
for i:=1 to n-1 do
if v[i]>v[i+1] then begin
aux:=v[i];
v[i]:=v[i+1];
v[i+1]:=aux;
vb:=true
end
until not vb
end;
procedure compactare(var n:byte; var v:multime);
var i,j,k:byte;
begin
sortare(n,v);
k:=0; i:=1;
while i<=n-k do
if v[i]=v[i+1] then begin
k:=k+1;
for j:=i to n-k+1 do v[j]:=v[j+1]
end
else inc(i);
n:=n-k
end;
procedure reuniune;
const hv=maxint;
var i,j,k,l:byte;
begin
k:=0; i:=1; j:=1;
while (a[i]<>hv) or (b[j]<>hv) do
if a[i]<b[j] then begin
inc(k);
c[k]:=a[i];
inc(i);
if i>m then a[i]:=hv
end
else if a[i]>b[j] then begin
inc(k);
c[k]:=b[j];
inc(j);
if j>n then b[j]:=hv
end
else begin inc(i); if i>m then a[i]:=hv end;
card:=k
end;

48
Subprograme externe

procedure intersectie;
var i,j,k:byte;
begin
k:=0; i:=1; j:=1;
while (i<=m) and (j<=n) do
if a[i]=b[j] then begin
inc(k);
c[k]:=a[i];
i:=i+1
end
else if a[i]>b[j] then inc(j) else inc(i);
card:=k
end;
procedure diferenta;
var i,j,k:byte;
begin
k:=0;
for i:=1 to m do
begin
j:=1;
while (a[i]<>b[j]) and (j<=n) do inc(j);
if j>n then begin inc(k);
c[k]:=a[i]
end
end;
card:=k
end;
procedure produs_cartezian;
var i,j,k:byte;
begin
k:=0;
for i:=1 to m do
for j:=1 to n do
begin
inc(k);
c[k].x:=a[i];
c[k].y:=b[j]
end
end;
BEGIN
END.

3.2. Sa se realizeze o unitate Pascal care sa contina subprograme


pentru calcularea medie i aritmetice ponderat e , dispersie i si abaterii
medii patrate pentru un sir de observatii statistice.
Pentru rezolvarea problemelor statistice trebuie avut e în vedere, pe lânga
observatiile propriu-zise, si frecventele de aparitie a acestora în cadrul sirului

49
Algoritmi în programare. Aplicatii

initial. În cadrul unitatii au fost dezvoltate doua subprograme frecvente_1 si


frecvente_2, care reprezinta variante ale aceleiasi probleme.
Prima varianta determina vectorul valorilor caracteristicii observate (unice),
precum si vectorul de frecvente, prin parcurgerea secventiala a sirului initial de
observatii statistice. Pentru fiecare observatie initiala se verifica existenta în
vectorul de valori unice: daca exista, atunci se incrementeaza frecventa
corespunzatoare valorii respective, în caz contrar observatia are o valoare noua si
se adauga sirului de valori unice.
A doua varianta presupune sortarea sirului initial de observatii statistice si
obtinerea vectorului valorilor caracteristicii observate (unice) si a vectorului de
frecvente folosind algoritmul controlului dupa caracteristica.
Observatie: Cele doua variante sunt utile în cazul problemelor statistice care
necesita cunoasterea frecventelor de aparitie a valorilor caracteristicii observate (de
exemplu valoarea modala a unei serii de observatii statistice, valorile quartilelor,
decilelor etc.).
Formulele utilizate pentru determinarea indicatorilor statistici sunt:
n n

∑ x i ⋅ fi ∑ (x i − x )2 ⋅ f i
Media aritmetica ponderata: x = i =1
n
, dispersia: s =
2 i =1
n
si
∑fi
i =1
∑ fi
i =1

abaterea medie patrata: s = s . Semnificatia parametrilor formali este


2

urmatoarea:
• n = numarul de observatii statistice (parametru de intrare) ;
• x = sirul initial de observatii statistice (parametru de intrare) ;
• y = multimea valorilor unice ale caracteristicii (parametru de iesire);
• f = vectorul de frecvente asociat multimii y (parametru de iesire);
• k = numarul de valori unice identificate în x - cardinalul multimii y
(parametru de iesire) .

unit statist;
INTERFACE
type vector=array[1..50] of real;
vector1=array[1..50] of byte;
procedure frecvente_1(n:byte; var x,y:vector; var f:vector1;
var k:byte);
procedure frecvente_2(n:byte; var x,y:vector; var f:vector1;
var k:byte);
function media(n:byte; var x:vector):real;
function dispersia(n:byte; var x:vector):real;
function abaterea_medie_patratica(n:byte; var x:vector):real;
IMPLEMENTATION
var
y:vector; f:vector1;
dim:byte;

50
Subprograme externe

procedure sortare(n:byte; var v:vector);


var i:byte; aux:real; vb:boolean;
begin
repeat
vb:=false;
for i:=1 to n-1 do
if v[i]>v[i+1] then begin
aux:=v[i]; v[i]:=v[i+1]; v[i+1]:=aux;
vb:=true end
until not vb
end;
procedure frecvente_1;
var i,j:byte;
begin
y[1]:=x[1]; f[1]:=1; k:=1;
for i:=2 to n do
begin
j:=1;
while (x[i]<>y[j]) and (j<=k) do inc(j);
if j<=k then inc(f[j])
else begin inc(k);y[k]:=x[i]; f[k]:=1 end
end
end;
procedure frecvente_2;
var i:byte;
begin
sortare(n,x); k:=0; i:=1;
while i<=n do
begin
k:=k+1; y[k]:=x[i]; f[k]:=0;
while (x[i]=y[k]) and (i<=n) do
begin inc(f[k]); inc(i) end
end
end;
function media;
var s:real; dim,i:byte;
begin
frecvente_1(n,x,y,f,dim);
if dim=n then
begin
s:=0;
for i:=1 to n do s:=s+x[i];
media:=s/n {medie aritmetica simpla}
end
else begin
s:=0;
for i:=1 to dim do s:=s+y[i]*f[i];
media:=s/n {medie aritmetica ponderata}
end
end;

51
Algoritmi în programare. Aplicatii

function dispersia;
var
m:real; dim,i:byte; s:real;
begin
m:=media(n,x,y,f);
frecvente_2(n,x,y,f,dim);
s:=0;
for i:=1 to dim do s:=s+sqr(y[i]-m)*f[i];
dispersia:=s/n
end;
function abaterea_medie_patratica;
begin
abaterea_medie_patratica:=sqrt(dispersia(n,x,y,f))
end;
end.

3.3. Sa se construiasca o unitate Pascal care sa contina subprograme pentru


lucrul cu masive de date, pentru rezolvarea urmatoarelor operatii:
determinarea valorii unui polinom într-un punct dat;
determinarea numarului de elemente pare de pe fiecare linie a unei
matrice;
însumarea elementelor strict negative ale unui masiv tridimensional;
inserarea valorii 0 între oricare doua elemente ale unui vector dat;
determinarea liniilor cu elementele în ordine strict crescatoare dintr-o
matrice dreptunghiulara;
cautarea unei valori date într-un vector neordonat;
determinarea valorii maxime din fiecare plan al unui masiv
tridimensional;
numararea aparitiilor într-un text a tuturor literelor alfabetului englez;
cautarea unei valori date într-un vector ordonat;
determinarea transpusei unei matrice dreptunghiulare;
compactarea unui vector prin eliminarea elementelor maxim si minim;
ridicarea unei matrice patrate la o putere data;
transformarea literelor mici dintr-un sir în litere mari;
determinarea maximului de pe fiecare coloana dintr-o matrice
dreptunghiulara;
determinarea mediei geometrice a elementelor unui vector;
determinarea mediei aritmetice a elementelor strict negative dintr-un
vector;
determinarea produsului vectorial dintre diagonalele principala si
secundara ale unei matrice patrate;
determinarea produsului scalar dintre diagonalele principala si
secundara ale unei matrice patrate;
determinarea produsului elementelor strict pozitive dintr-un vector;
determinarea mediei aritmetice a elementelor nenule dintr-un vector;
determinarea mediei armonice a tuturor elementelor unui vector;

52
Subprograme externe

determinarea produsului a doua matrice dreptunghiulare;


adunarea a doua matrice cu elemente logice;
înmultirea a doua matrice cu elemente logice;
sortarea crescatoare a elementelor unui vector prin metoda bulelor
(prin interschimbare);
sortarea crescatoare a elementelor unui vector prin metoda selectiei
(minime succesive);
interclasarea a doi vectori;
înmultirea unui vector cu o matrice.
Unitatea masive va contine, pe lânga subprogramele de rezolvare a cerintelor
problemei, patru subprograme pentru citirea si afisarea unui vector, respectiv
citirea si afisarea unei matrice.

unit masive;
INTERFACE
uses crt;
type {tipuri publice}
masiv3d=array[1..10,1..10,1..10] of real;
matrice=array[1..20,1..20] of real;
matrice1=array[1..20,1..20] of word;
matrice2=array[1..20,1..20] of boolean;
vector=array[1..100] of real;
vector1=array[1..20] of byte;
vector2=array['A'..'Z'] of byte;
{determinarea valorii unui polinom intr-un punct dat}
function polinom(grad:byte; x:real; var coef:vector):real;
{determinarea numarului de elemente pare de pe fiecare linie
a unei matrice}
procedure el_pare(m,n:byte; a:matrice1; var rez:vector1);
{insumarea elementelor strict negative ale unui masiv
tridimensional}
function suma_tridim(m,n,p:byte; var t:masiv3d):real;
{inserarea valorii 0 intre oricare doua elemente ale unui
vector}
procedure inserare_0(var n:byte; var v:vector);
{determinarea liniilor cu elementele in ordine strict
crescatoare dintr-o matrice dreptunghiulara – 2 variante}
procedure linii_cresc1(m,n:byte; a:matrice;
var nr:byte; var v:vector1);
procedure linii_cresc2(m,n:byte; a:matrice; var v:vector1);
{cautarea unei valori intr-un vector neordonat – 2 variante}
function cautare1(n:byte; v:vector; x:real):boolean;
function cautare2(n:byte; v:vector; x:real):byte;
{determinarea valorii maxime din fiecare plan al unui masiv
tridimensional}
procedure maxim_plan3d(m,n,p:byte; var t:masiv3d;
var v:vector);

53
Algoritmi în programare. Aplicatii

{numararea aparitiilor intr-un text a tuturor literelor


alfabetului englez}
procedure litere(s:string; var v:vector2);

{cautarea unei valori date intr-un vector ordonat}


function cautare_binara(n:byte; v:vector; x:real):byte;
{determinarea transpusei unei matrice dreptunghice}
procedure transpusa(var m,n:byte; a:matrice; var at:matrice);
{compactarea unui vector prin eliminarea elementelor maxim si
minim}
procedure compactare(var n:byte; var v:vector);
{ridicarea unei matrice patrate la o putere data}
procedure matrice_la_putere(n,p:byte; a:matrice;
var ap:matrice);
{transformarea literelor mici dintr-un sir in litere mari}
procedure transformare_litere(var s:string);
{determinarea maximului de pe fiecare coloana dintr-o matrice
dreptunghiulara}
procedure maxim_coloane(m,n:byte; a:matrice; var v:vector);
{determinarea mediei geometrice a elementelor unui vector}
procedure medie_geom(n:byte; v:vector; var mg:real;
var er:boolean);
{determinarea mediei aritmetice a elementelor strict negative
dintr-un vector}
function medie_aritm_negative(n:byte; v:vector):real;
{determinarea produsului vectorial dintre diagonalele
principala si secundara ale unei matrice patrate}
procedure produs_vectorial_diagonale(n:byte; a:matrice;
var pv:vector);
{determinarea produsului scalar dintre diagonalele principala
si secundara ale unei matrice patrate}
function produs_scalar_diagonale(n:byte; a:matrice):real;
{determinarea produsului elementelor strict pozitive dintr-un
vector}
function produs_elem_pozitive(n:byte; v:vector):real;
{determinarea mediei aritmetice a elementelor nenule dintr-un
vector}
function ma_nenule(n:byte; v:vector):real;
{determinarea mediei armonice a elementelor unui vector}
procedure medie_armonica(n:byte; v:vector; var mh:real;
var er:boolean);
{determinarea produsului a doua matrice dreptunghiulare}
procedure produs_matrice(m,n,p:byte; a,b:matrice;
var c:matrice);
{adunarea a doua matrice cu elemente booleene}
procedure suma_matrice_logice(m,n:byte; a,b:matrice2;
var c:matrice2);
{inmultirea a doua matrice cu elemente booleene}
procedure produs_matrice_logice(m,n,p:byte; a,b:matrice2;
var c:matrice2);

54
Subprograme externe

{sortarea crescatoare a elementelor unui vector prin metoda


bulelor (prin interschimbare)}
procedure sortare1(n:byte; var v:vector);
{sortarea crescatoare a elementelor unui vector prin metoda
selectiei (minime succesive)}
procedure sortare2(n:byte; var v:vector);
{interclasarea a doi vectori}
procedure interclasare(n,m:byte; a,b:vector; var c:vector);
{inmultirea unui vector cu o matrice}
procedure vector_x_matrice(m,n:byte; v:vector; a:matrice;
var x:vector);
{proceduri auxiliare de citire/afisare vectori si matrice}
procedure citire_vector(var n:byte; var v:vector);
procedure afisare_vector(n:byte; v:vector);
procedure citire_matrice(var m,n:byte; var a:matrice);
procedure afisare_matrice(m,n:byte; a:matrice);

IMPLEMENTATION
var {variabile globale unitatii, nepublice}
i,j,k:byte;
function polinom;
var
val,temp:real;
begin
temp:=1; val:=coef[1];
for i:=2 to grad+1 do
begin
temp:=temp*x;
val:=val+coef[i]*temp
end;
polinom:=val
end;
procedure el_pare;
{matricea trebuie sa aiba elemente naturale}
begin
for i:=1 to m do begin
rez[i]:=0;
for j:=1 to n do
if (a[i,j] mod 2)=0 then inc(rez[i])
end
end;
function suma_tridim;
{daca rezultatul este 0 inseamna ca masivul nu contine
elemente strict negative}
var s:real;
begin
s:=0;
for i:=1 to m do
for j:=1 to n do
for k:=1 to p do

55
Algoritmi în programare. Aplicatii

if t[i,j,k]<0 then s:=s+t[i,j,k];


suma_tridim:=s
end;
procedure inserare_0; {vector rezultat are 2n-1 elemente}
begin
k:=n; i:=2;
while i<=2*n-1 do begin
inc(k);
for j:=k downto i+1 do v[j]:=v[j-1];
v[i]:=0; inc(i,2)
end;
n:=k
end;
procedure linii_cresc1;
{vectorul rezultat v este compact si contine nr>=0 elemente}
begin
nr:=0;
for i:=1 to m do begin
j:=1;
while (j<=n-1) and (a[i,j]<a[i,j+1]) do inc(j);
if j>n-1 then begin nr:=nr+1; v[nr]:=i end
end
end;
procedure linii_cresc2;
{vectorul rezultat are elem. binare: v(i)=1 daca linia i a
matricei are elem. crescatoare si v(i)=0 in caz contrar}
begin
for i:=1 to m do begin
j:=1;
while (j<=n-1) and (a[i,j]<a[i,j+1]) do inc(j);
if j>n-1 then v[i]:=1 else v[i]:=0
end
end;
function cautare1;
{se verifica doar existenta unei valori date intr-un vector}
begin
i:=1;
while (i<=n) and (v[i]<>x) do inc(i);
if i>n then cautare1:=false else cautare1:=true
end;
function cautare2;
{se verifica existenta valorii si se determina
pozitia primei aparitii}
begin
cautare2:=0; {valoarea cautata nu exista in vector}
i:=1;
while i<=n do
if v[i]=x then begin
cautare2:=i;{valoarea cautata exista in vector}
i:=n+1 {fortarea iesirii din bucla while}

56
Subprograme externe

end
else inc(i)
end;
procedure maxim_plan3d;
{masivul tridimensional este tratat ca un vector
de matrice, de maxim 10 componente}
begin
for i:=1 to m do
begin
v[i]:=t[i,1,1];
for j:=1 to n do
for k:=1 to p do
if t[i,j,k]>v[i] then v[i]:=t[i,j,k]
end
end;
procedure litere;
{nu se fac deosebiri intre litere mari si mici}
var i:char;
begin
for i:='A' to 'Z' do v[i]:=0;
for j:=1 to length(s) do inc(v[upcase(s[j])])
end;
function cautare_binara;
{vectorul are elementele obligatoriu sortate}
var cb,prim,ultim:byte;
begin
prim:=1; ultim:=n; cb:=0;
repeat
i:=(prim+ultim) div 2;
if v[i]=x then cb:=i
else if x<v[i] then ultim:=i-1
else prim:=i+1
until (cb<>0) or (prim>ultim);
cautare_binara:=cb
end;
procedure transpusa;
{transpusa se construieste invers lexicografic}
begin
for i:=1 to m do
for j:=1 to n do
at[j,i]:=a[i,j]
end;
procedure compactare;
{dupa compactare vectorul v are n>=0 componente}
var min,max:real;
begin
min:=v[1]; max:=v[1]; {se determina min si max}
for i:=2 to n do
if v[i]<min then min:=v[i]
else if v[i]>max then max:=v[i];

57
Algoritmi în programare. Aplicatii

k:=0; i:=1;
while i<=n-k do {se elimina elem. egale cu min sau max}
begin
if (v[i]=min) or (v[i]=max) then
begin
for j:=i to n-k-1 do v[j]:=v[j+1];
inc(k);
end
else inc(i)
end;
n:=n-k {nr. de componente dupa compactare}
end;
procedure matrice_la_putere;
{puterea este p>=0}
var b:matrice;
l:byte;
begin
for i:=1 to n do {initializare matrice unitate}
for j:=1 to n do
if i=j then ap[i,j]:=1 else ap[i,j]:=0;
for k:=1 to p do {ridicare la puterea p}
begin
for i:=1 to n do
for j:=1 to n do
begin
b[i,j]:=0;
for l:=1 to n do b[i,j]:=b[i,j]+ap[i,l]*a[l,j]
end;
for i:=1 to n do
for j:=1 to n do
ap[i,j]:=b[i,j]
end
end;
procedure transformare_litere;
begin
for i:=1 to length(s) do s[i]:=upcase(s[i])
end;
procedure maxim_coloane;
begin
for j:=1 to n do {vectorul poate avea max. 20 de elem.}
begin
v[j]:=a[1,j];
for i:=2 to m do if a[i,j]>v[j] then v[j]:=a[i,j]
end
end;
procedure medie_geom;
begin
er:=false; mg:=1;
for i:=1 to n do mg:=mg*v[i];
if mg>=0 then mg:=exp(ln(mg)/n)

58
Subprograme externe

else if (n mod 2)=1 then mg:=-exp(ln(-mg)/n)


else er:=true {media nu se poate calcula}
end;
function medie_aritm_negative;
var ma:real;
begin
ma:=0; k:=0;
for i:=1 to n do
if v[i]<0 then begin ma:=ma+v[i]; inc(k) end;
if k>1 then medie_aritm_negative:=ma/k
else medie_aritm_negative:=0 {media nu se poate calcula}
end;
procedure produs_vectorial_diagonale;
begin for i:=1 to n do pv[i]:=a[i,i]*a[i,n-i+1]
end;
function produs_scalar_diagonale;
var ps:real;
begin
ps:=0;
for i:=1 to n do ps:=ps+a[i,i]*a[i,n-i+1];
produs_scalar_diagonale:=ps
end;
function produs_elem_pozitive;
var p:real; k:boolean;
begin
p:=1; k:=false; {k este variabila semafor}
for i:=1 to n do
if v[i]>0 then begin
p:=p*v[i];
k:=true {exista elemente pozitive}
end;
if k then produs_elem_pozitive:=p
else produs_elem_pozitive:=0 {nu exista elemente pozitive}
end;
function ma_nenule;
var ma:real;
begin
ma:=0; k:=0; {k este variabila semafor, dar si contor}
for i:=1 to n do
if v[i]<>0 then begin ma:=ma+v[i]; inc(k) end;
if k>1 then ma_nenule:=ma/k
else ma_nenule:=0 {nu exista elemente diferite de 0}
end;
procedure medie_armonica;
{daca er=true, atunci media armonica nu se poate calcula}
begin
mh:=0; er:=false; i:=1;
while (i<=n) and (v[i]<>0) do begin
mh:=mh+1/v[i]; inc(i)
end;

59
Algoritmi în programare. Aplicatii

if i>n then if mh<>0 then mh:=n/mh else er:=true


else er:=true
end;
procedure produs_matrice;
begin
for i:=1 to m do
for j:=1 to p do
begin
c[i,j]:=0;
for k:=1 to n do c[i,j]:=c[i,j]+a[i,k]*b[k,j]
end
end;
procedure suma_matrice_logice;
{adunarea a 2 valori logice este SAU logic}
begin
for i:=1 to m do
for j:=1 to n do c[i,j]:=a[i,j] or b[i,j]
end;
procedure produs_matrice_logice;
{inmultirea a 2 valori logice este SI logic}
begin
for i:=1 to m do
for j:=1 to p do
begin
c[i,j]:=false;
for k:=1 to n do c[i,j]:=c[i,j]or(a[i,k]and b[k,j])
end
end;
procedure sortare1; {metoda bulelor}
var vb:boolean;
aux:real;
begin
repeat
vb:=false;
for i:=1 to n-1 do
if v[i]>v[i+1] then begin
aux:=v[i]; v[i]:=v[i+1]; v[i+1]:=aux; vb:=true
end
until not vb
end;
procedure sortare2; {metoda selectiei}
var aux:real;
begin
for i:=1 to n-1 do
for j:=i+1 to n do
if v[i]>v[j] then begin
aux:=v[i]; v[i]:=v[j]; v[j]:=aux
end
end;
procedure interclasare; {card(a) + card(b) = maxim 100}

60
Subprograme externe

var l:byte;
begin
k:=0; i:=1; j:=1;
while (i<=m) and (j<=n) do begin
inc(k);
if a[i]<b[j] then begin c[k]:=a[i]; inc(i) end
else begin c[k]:=b[j]; inc(j) end
end;
if i>m then for l:=j to n do begin
inc(k); c[k]:=b[l]
end
else for l:=i to m do begin
inc(k); c[k]:=a[l]
end
end;
procedure vector_x_matrice;
begin
for j:=1 to n do begin
x[j]:=0;
for i:=1 to m do x[j]:=x[j]+v[i]*a[i,j]
end
end;
procedure citire_vector; {cate un element pe rand}
begin
write('Nr. de elemente:'); readln(n);
for i:=1 to n do begin
write('el[',i,']='); readln(v[i])
end
end;
procedure afisare_vector; {pe acelasi rand al monitorului}
begin
for i:=1 to n do write(v[i]:6:2)
end;

procedure citire_matrice; {cate un element pe rand}


begin
write('Nr. de linii: '); readln(m);
write('Nr. de coloane:'); readln(n);
for i:=1 to m do
for j:=1 to n do begin
write('el[',i,',',j,']=');
readln(a[i,j])
end;
end;
procedure afisare_matrice; {sub forma matriceala}
begin
for i:=1 to m do begin
for j:=1 to n do write(a[i,j]:6:2);
writeln
end

61
Algoritmi în programare. Aplicatii

end;
BEGIN
END.
3.4. Sa se realizeze programul Pascal care apeleaza subprograme din unitatea
conceputa la exercitiul 3.3.
Programul principal care apeleaza unitatea masive este conceput
multifunctional (modularizat), astfel încât utilizatorul sa poata opta pentru una din
functiuni, având posibilitatea reluarii prin citirea de la tastatura a optiunii dorite.

program apelator_masive;
uses masive,crt;
var a,b,c:matrice;
x,y,z:vector;
a1:matrice1;
v1:vector1;
v2:vector2;
t:masiv3D;
s:string;
cc:char;
i,j,k,l,m,n,opt:byte;
p:real;
vb:boolean;
procedure meniu;
begin
clrscr;
textcolor(yellow+blink);
gotoxy(25,1); write(' « APLICATIE CU SUBPROGRAME »');
textcolor(white);
gotoxy(1,5); write(' 1 ? Valoare polinom intr- un punct dat');
gotoxy(1,6); write(' 2 ? Elemente pare pe linie matrice');
gotoxy(1,7); write(' 3 ? Suma elemente negative masiv 3D');
gotoxy(1,8); write(' 4 ? Inserare 0 intre elemente vector');
gotoxy(1,9); write(' 5 ? Linii cu elemente crescatoare var1');
gotoxy(1,10); write(' 6 ? Linii cu elemente crescatoare var2');
gotoxy(1,11); write(' 7 ? Cautare in vector oarecare var1');
gotoxy(1,12); write(' 8 ? Cautare in vector oarecare var2');
gotoxy(1,13); write(' 9 ? Maxim din fiecare plan masiv 3D');
gotoxy(1,14); write('10 ? Aparitii litere in text');
gotoxy(1,15); write('11 ? Cautare in vector ordonat');
gotoxy(1,16); write('12 ? Transpusa unei matrice');
gotoxy(1,17); write('13 ? Compactare vector eliminand max/min');
gotoxy(1,18); write('14 ? Matrice la o putere data');
gotoxy(41,5); write(' |15 ? Transformare litere mici in mari');
gotoxy(41,6); write(' |16 ? Maxim pe fiecare coloana matrice');
gotoxy(41,7); write(' |17 ? Medie geometrica elemente vector');
gotoxy(41,8); write(' |18 ? Medie aritmetica elemente < 0');
gotoxy(41,9); write(' |19 ? Produs vectorial intre diagonale');
gotoxy(41,10); write('|20 ? Produs scalar intre diagonale');
gotoxy(41,11); write('|21 ? Produs elemente > 0 din vector');
gotoxy(41,12); write('|22 ? Medie aritmetica elemente nenule');
gotoxy(41,13); write('|23 ? Medie armonica elemente vector');
gotoxy(41,14); write('|24 ? Inmultirea a doua matrice');
gotoxy(41,15); write('|25 ? Sortare vector prin interschimbare');

62
Subprograme externe

gotoxy(41,16); write('|26 ? Sortare vecto r prin selectie');


gotoxy(41,17); write('|27 ? Interclasarea a doi vectori');
gotoxy(41,18); write('|28 ? Inmultire vector cu matrice');
textcolor(magenta+blink);
gotoxy(27,20); write('Pentru iesire tastati 0');
textcolor(yellow+blink);
gotoxy(30,22); clreol; write('Alegeti optiunea: ');
textcolor(white); readln(opt)
end;
{programul principal}
begin
meniu;
while opt<>0 do begin
case opt of
1: begin
clrscr; write('Gradul polinomului:'); readln(n);
writeln('Coeficientii polinomului:');
for i:=1 to n+1 do
begin
write('coeficientul lui x la puterea ',i-1,' = ');
readln(x[i])
end;
write('Punctul pentru care se va calcula valoarea:');
readln(p);
writeln('Valoarea polinomului in punctul',p:3:0,
' este ',polinom(n,p,x):6:2);
readln
end;
2: begin
clrscr;
write('Nr. de linii:'); readln(m);
write('Nr. de coloane:'); readln(n);
for i:=1 to m do
for j:=1 to n do begin
write('el[',i,',',j,']='); readln(a1[i,j])
end;
el_pare(m,n,a1,v1);
for i:=1 to m do
writeln('Pe linia',i:2,' se afla',v1[i]:2,
' elemente pare');
readln
end;
3: begin
clrscr;
write('Nr. de plane 3D:'); readln(l);
write('Nr. linii pe plan:'); readln(m);
write('Nr. coloane pe plan:'); readln(n);
for i:=1 to l do
for j:=1 to m do
for k:=1 to n do begin
write('el[',i,',',j,',',k,']=');
readln(t[i,j,k])
end;
p:=suma_tridim(l,m,n,t);
if p<>0 then

63
Algoritmi în programare. Aplicatii

writeln('Suma elementelor < 0 din masiv este:',p:6:2)


else writeln(' Nu exista elemente negative!');
readln
end;
4: begin
clrscr;
citire_vector(n,x);
inserare_0(n,x);
afisare_vector(n,x);
readln
end;
5: begin
clrscr;
citire_matrice(m,n,a);
linii_cresc1(m,n,a,k,v1);
if k>0 then begin
write('Liniile cu elemente in ordine crescatoare:');
for i:=1 to k do write(v1[i]:2)
end
else
writeln( 'Nu exista linii cu elem. in ordine crescatoare!');
readln
end;
6: begin
clrscr; vb:=false;
citire_matrice(m,n,a);
linii_cresc2(m,n,a,v1);
for i:=1 to m do
if v1[i]=1 then begin
writel n('linia',i:2,) ; vb:=true
end;
if not vb then writeln('Nu exista linii!');
readln
end;
7: begin
clrscr;
citire_vector(n,x);
write('Valoarea de cautat:'); readln(p);
if cautare1(n,x,p) then writeln('Valoare existenta!')
else write('Valoare inexistenta!');
readln
end;
8: begin
clrscr;
citire_vector(n,x);
write('Valoarea de cautat:'); readln(p);
l:=cautare2(n,x,p);
if l<>0 then
writeln('Prima aparitie este pe pozitia',l:3)
else write('Valoarea nu exista in vector!');
readln
end;
9: begin
clrscr;
write('Nr. de plane 3D:'); readln(l);

64
Subprograme externe

write('Nr. linii pe plan:'); readln(m);


write('Nr. coloane pe plan:'); readln(n);
for i:=1 to l do
for j:=1 to m do
for k:=1 to n do begin
write('el[',i,',',j,',',k,' ]=');
readln(t[i,j,k])
end;
maxim_plan3d(l,m,n,t,x);
write('Elementele maxime din fiecare plan sunt:');
afisare_vector(l,x);
readln
end;
10: begin
clrscr;
writeln('Textul de prelucrat:'); readln(s);
litere(s,v2);
writeln('Frecventele de aparitie a literelor sunt:');
for cc:='A' to 'Z' do write(cc:2);
writeln;
for cc:='A' to 'Z' do write(v2[cc]:2);
readln
end;
11: begin
clrscr;
citire_vector(n,x);
write('Valoarea de cautat:'); readln(p);
l:=cautare_binara(n,x,p);
if l=0 then
write('Valoare inexistenta sau vector nesortat!')
else write('Valoarea apare pe pozitia',l:3);
readln
end;
12: begin
clrscr;
citire_matrice(m,n,a);
transpusa(m,n,a,b);
write ln('Matricea transpusa este:');
afisare_matrice(n,m,b);
readln
end;
13: begin
clrscr;
citire_vector(n,x);
compactare(n,x);
if n=0 then
writeln('Vectorul rezultat are cardinalul = 0')
else begin
writeln('Vectorul compactat este:');
afisare_vector(n,x)
end;
readln
end;
14: begin
clrscr;

65
Algoritmi în programare. Aplicatii

citire_matrice(n,n,a);
write('Puterea la care se va ridica matricea:');
readln(l);
matrice_la_putere(n,l,a,b);
writeln('Matricea rezultat este:');
afisare_matrice(n,n,b);
readln
end;
15: begin
clrscr;
writeln('Textul de prelucrat:'); readln(s);
transformare_litere(s);
writeln('Textul transformat in litere mari este:');
writeln(s);
readln
end;
16: begin
clrscr;
citire_matrice(m,n,a);
maxim_coloane(m,n,a,x);
writeln('Elementele maxime pe fiecare coloana sunt:');
afisare_vector(n,x);
readln
end;
17: begin
clrscr;
citire_vector(n,x);
medie_geom(n,x,p,vb);
if vb then
writeln('Media geometrica nu se poate calcula!')
else writeln('Media geometrica este',p:6:2);
readln
end;
18: begin
clrscr;
citir e_vector(n,x);
p:=medie_aritm_negative(n,x);
if p<0 then writeln('Media aritmetica este',p:6:2)
else writeln('Nu exista elemente negative in vector!');
readln
end;
19: begin
clrscr;
citire_matrice(n,n,a);
produs_vectorial_diagonale(n,a,x);
writeln('Rezultatul este:');
afisare_vector(n,x);
readln
end;
20: begin
clrscr;
citire_matrice(n,n,a);
writeln('Produsul scalar este',
produs_scalar_diagonale(n,a):6:2);
readln

66
Subprograme externe

end;
21: begin
clrscr;
citire_vector(n,x);
p:=produs_elem_pozitive(n,x);
if p>0 then writeln('Produsul este',p:6:2)
else writeln('Nu exista elemente pozitive!');
readln
end;
22: begin
clrscr;
citire_vector(n,x);
p:=ma_nenule(n,x);
if p<>0 then writeln('Media aritmetica este',p:6:2)
else writeln('Nu exista elemente nenule in vector!');
readln
end;
23: begin
clrscr;
citire_vector(n,x);
medie_armonica(n,x,p,vb);
if vb then
writeln('Media armonica nu se poate calcula!')
else writeln('Media armonica este',p:6:2);
readln
end;
24: begin
clrscr;
citire_matrice(m,n,a);
citire_matrice(k,l,b);
if n<>k then writeln('Dimensiuni incompatibile!')
else begin
produs_matrice(m,n,l,a,b,c);
writeln('Matricea rezultat este:');
afisare_matrice(m,l,c)
end;
readln
end;
25: begin
clrscr;
citire_vector(n,x);
sortare1(n,x);
writeln('Vectorul sortat prin interschimbare este:');
afisare_vector(n,x);
readln
end;
26: begin
clrscr;
citire_vector(n,x);
sortare2(n,x);
writeln('Vectorul sortat prin selectie este:');
afisare_vector(n,x);
readln
end;
27: begin

67
Algoritmi în programare. Aplicatii

clrscr;
writeln('ATENTIE! Vectorii trebuie sa fie sortati !!!');
writeln('Primul vector');
citire_vector(n,x);
writeln('Al doilea vector');
citire_vector(m,y);
interclasare(n,m,x,y,z);
writeln('Vectorul rezultat al interclasarii este:');
afisare_vector(n+m,z);
readln
end;
28: begin
clrscr;
citire_vector(n,x);
citire_matrice(m,k,a);
if n<>m then writeln('Dimensiuni incompatibile!')
else begin
vector_x_matrice(m,k,x,a,y);
writeln('Rezultatul inmultirii este:');
afisare_vector(k,y)
end;
readln
end
else begin
gotoxy(48,22);clreol;
textcolor(red+blink);
write('OPTIUNE ERONATA!',#7);
readln;
textcolor(white)
end
end;
meniu
end
end.

Dupa lansarea în executie a programului apelator, ec ranul principal va arata ca în


figura urmatoare, utilizatorul având posibilitatea de a alege o optiune de la 1 la 28,
iar pentru iesirea din aplicatie, optiunea 0.

68
Subprograme externe

Programul apelator_masive nu include apelul subprogramelor care


lucreaza cu masive de elemente logice: suma_matrice_logice si
produs_matrice_logice. Pentru includerea acestora este nevoie de proceduri
speciale de citire/afisare, având în vedere particularitatile tipului Pascal
BOOLEAN, care nu poate fi citit din fisiere (si, implicit, de la tastatura), iar la
scriere se comporta diferit, în functie de tipul fisierului: binar sau TEXT (cazul
monitorului).
Pentru citirea datelor de tip logic de la tastatura este nevoie de stabilirea
unei conventii (de exemplu introducerea valorii 0 pentru fals si 1 pentru adevarat),
initializarea datelor booleene urmând a fi realizata prin atribuire. Afisarea datelor
logice poate fi realizata fie prin valorile de adevar 0 si 1 (caz în care trebuie
refacuta conventia de la citire), fie direct, tinând cont ca datele de tip BOOLEAN
se pot scrie în fisiere TEXT, prin conversia la sirurile de caractere TRUE si
FALSE.

program citire_afisare_matrice_booleana;
var
a:array[1..10,1..20] of boolean;
i,j,m,n,x:byte;
begin
write('Nr. de linii: ');
readln(m);
write('Nr. de coloane: ');
readln(n);

{citirea matricei booleene}


writeln('Elementele matricei (0-fals si 1-adevarat) ');
for i:=1 to m do
for j:=1 to n do
begin
write('el(',i,',',j,')= ');

69
Algoritmi în programare. Aplicatii

readln(x); {nu se fac validari}


{construirea matricei booleene}
if x=0 then a[i,j]:=false
else a[i,j]:=true
end;

{afisarea matricei booleene, cu valori 0 si 1}


for i:=1 to m do
begin
for j:=1 to n do
begin
if a[i,j]= false then x:=0 else x:=1;
write(x:2)
end;
writeln
end;

{afisarea matricei booleene, cu valori FALSE si TRUE}


for i:=1 to m do
begin
for j:=1 to n do write(a[i,j]:6);
writeln
end
end.

70
4. Subprograme recursive

4.1. Sa se construiasca o unitate Pascal care sa contina subprograme recursive


pentru realizarea urmatoarelor operatii:
suma elementelor unui vector;
produsul elementelor unui vector;
factorialul unui numar natural;
generarea unu i termen din sirul lui Fibonacci;
minimul dintr-un vector;
maximul dintr-un vector;
produsul scalar dintre doi vectori;
sortarea unui vector;
valoarea unui polinom într-un punct dat;
ridicarea unei matrice la o putere data.
Parametrii de intrare de tip vector si matrice sunt transmisi prin adresa
deoarece, prin recursivitate, duplicarea repetata a masivelor în stiva poate genera
depasirea acesteia.
Tipul functiei factorial a fost ales REAL deoarece domeniul de valori pentru
cel mai mare tip întreg (LONGINT) este valabil numai pâna la 12!.
Pentru exemplificarea maximului dintr-un vector s-a ales varianta procedurii
recursive, subprogramul de tip functie fiind similar celui de determinare a
minimului.
Functia pol care determina valoarea unui polinom într-un punct dat apeleaza un
subprogram intern recursiv (functia put ) pentru ridicarea unui numar la o putere.
Procedura putere este functionala si pentru ridicarea unei matrice la puterea 0,
returnând matricea unitate.
Procedura sort realizeaza sortarea unui vector prin metoda bulelor.

unit recursiv;
INTERFACE
type
{tipuri publice}
vector=array[1..100] of real;
matrice=array[1..20,1..20] of real;
{suma elementelor unui vector}
function suma(n:byte; var v:vector):real;
{produsul elementelor unui vector}
function produs(n:byte; var v:vector):real;
{factorialul unui numar natural}
function factorial(n:byte):real;
{generarea unui termen din sirul lui Fibonacci}
function fibonacci(n:byte):longint;

{minimul dintr-un vector}


function min(n:byte; var v:vector):real;

71
Algoritmi în programare. Aplicatii

{maximul dintr-un vector}


procedure maxim(n:byte; var v:vector; var max:real);
{produsul scalar dintre doi vectori}
function ps(n:byte; var v,w:vector):real;
{sortarea unui vector}
procedure sort(n:byte; var v:vector);
{valoarea unui polinom intr-un punct dat}
function pol(n:byte; var v:vector; x:real):real;
{ridicarea unei matrice la o putere data}
procedure putere(n,p:byte; var a,b:matrice);
IMPLEMENTATION
Var
i,j,k:byte; {variabile globale unitatii}
function suma;
begin
if n=0 then suma:=0
else suma:=suma(n-1,v)+v[n]
end;
function produs;
begin
if n=0 then produs:=1
else produs:=produs(n-1,v)*v[n]
end;
function factorial;
begin
if n<2 then factorial:=1
else factorial:=factorial(n-1)*n
end;
function fibonacci;
begin
if n<3 then fibonacci:=1
else fibonacci:=fibonacci(n-2)+fibonacci(n-1)
end;
function min;
begin
if n=1 then min:=v[n]
else if v[n]<min(n-1,v) then min:=v[n]
else min:=min(n-1,v)
end;
procedure maxim;
begin
if n=1 then max:=v[n]
else
begin
maxim(n-1,v,max); {apel recursiv}
if v[n]>max then max:=v[n]
end
end;
function ps;
begin

72
Subprograme recursive

if n=0 then ps:=0


else ps:=ps(n-1,v,w)+v[n]*w[n]
end;
procedure sort;
var vb:boolean;
aux:real;
begin
vb:=false;
for i:=1 to n-1 do
if v[i]>v[i+1] then begin
aux:=v[i];
v[i]:=v[i+1];
v[i+1]:=aux;
vb:=true
end;
if vb then sort(n,v) {apel recursiv}
end;
function pol;
function put(y:real; n:byte):real;
begin
if n=0 then put:=1
else put:=put(y,n-1)*y
end;
begin
if n=0 then pol:=v[1]
else pol:=pol(n-1,v,x)+v[n]*put(x,n)
end;
procedure putere;
var c:matrice;
begin
if p=0 then
for i:=1 to n do
for j:=1 to n do
if i=j then b[i,j]:=1 else b[i,j]:=0
else begin
putere(n,p-1,a,b);
for i:=1 to n do
for j:=1 to n do
begin
c[i,j]:=0;
for k:=1 to n do c[i,j]:=c[i,j]+b[i,k]*a[k,j]
end;
for i:=1 to n do
for j:=1 to n do b[i,j]:=c[i,j]
end
end;
BEGIN
END.

73
Algoritmi în programare. Aplicatii

4.2. Sa se realizeze programul Pascal care apeleaza subprograme din unitatea


conceputa la exercitiul 4.1.
Programul principal care apeleaza unitatea recursiv este conceput
multifunctional (modularizat), astfel încât utilizatorul sa poata opta pentru una din
functiuni, având posibilitatea reluarii prin citirea de la tastatura a optiunii dorite. De
asemenea, programul principal apeleaza unitatea masive (construita la exercitiul
3.3), din care foloseste subprogramele citire_vector , afisare_vector,
citire_matrice si afisare_matrice .

program apelator_recursiv;
uses recursiv,masive,crt;
var
a,b:matrice;
x,y:vector;
i,j,m,n,opt:byte;
p:real;
procedure meniu;
begin
clrscr;
textcolor(yellow+blink);
gotoxy(20,1); write('« APLICATIE CU SUBPROGRAME RECURSIVE »');
textcolor(white);
gotoxy(1,5); write(' 1 ? Suma elementelor unui vector');
gotoxy(1,6); write(' 2 ? Produsul elementelor unui vector');
gotoxy(1,7); write(' 3 ? Factorialul unui numar natural');
gotoxy(1,8); write(' 4 ? Generarea unui termen Fibonacci');
gotoxy(1,9); write(' 5 ? Minimul dintr-un vector');
gotoxy(1,10); write(' 6 ? Maximul dintr-un vector');
gotoxy(1,11); write(' 7 ? Produsul scalar dintre doi vectori');
gotoxy(1,12); write(' 8 ? Sortarea unui vector');
gotoxy(1,13); write(' 9 ? Valorea unui polinom intr -un punct');
gotoxy(1,14); write('10 ? Ridicarea unei matrice la o putere');
textcolor(magenta+blink);
gotoxy(27,20);
write('Pentru iesire tastati 0');
textcolor(yellow+blink);
gotoxy(30,22);
clreol;
write('Alegeti optiunea: ');
textcolor(white);
readln(opt)
end;
{programul principal}
begin
meniu;
while opt<>0 do begin
case opt of
1: begin
clrscr;
citire_vector(n,x);
writeln('Suma elementelor este', suma(n,x):8:2);
readln
end;

74
Subprograme recursive

2: begin
clrscr;
citire_vector(n,x);
writeln('Produsul elementelor este', produs(n,x):8:2);
readln
end;
3: begin
clrscr;
write('Numarul:'); readln(n);
writeln(n,'!=',fact orial(n):8);
readln
end;
4: begin
clrscr;
write('Termenul Fibonacci de generat:'); readln(n);
writeln('Al ',n,'-lea termen este',fibonacci(n):6);
readln
end;
5: begin
clrscr;
citire_vector(n,x);
writeln('Minimul din vector este', min(n,x):8:2);
readln
end;
6: begin
clrscr;
citire_vector(n,x);
maxim(n,x,p);
writeln('Maximul din vector este', p:8:2);
readln
end;
7: begin
clrscr;
citire_vector(n,x); {citire vector 1}
citire_vector(m,y); {citire vector 2}
if n<>m then writeln('Dimensiuni incompatibile!')
else writeln('Produsul scalar este', ps(n,x,y):8:2);
readln
end;
8: begin
clrscr;
citire_vector(n,x);
sort(n,x);
writeln('Vectorul sortat este:');
afisare_vector(n,x);
readln
end;
9: begin
clrscr;
write('Gradul polinomului:'); readln(n);
writeln('Coeficientii polinomului:');
for i:=1 to n+1 do begin
write('coeficientul lui x la puterea ',i-1,' = ');
readln(x[i])
end;

75
Algoritmi în programare. Aplicatii

write('Punctul pentru care se va calcula valoarea:');


readln(p);
write ln('Valoarea polinomului in punctul',p:3:0,
' este ',pol(n,x,p):6:2);
readln
end;
10: begin
clrscr;
citire_matrice(n,n,a);
write('Puterea:'); readln(m);
putere(n,m,a,b);
afisare_matrice(n,n,b);
readln
end
else begin
gotoxy(48,22);clreol;
textcolor(red+blink);
write('OPTIUNE ERONATA!',#7);
readln;
textcolor(white)
end
end {case-of};
meniu
end {while}
end.

Dupa lansarea în executie a programului apelator, ecranul principal va


arata ca în figura urmatoare.

76
5. Masive memorate în fişiere

Una din aplicaţiile des întâlnite în lucrul cu fişiere este memorarea masivelor
de date de dimensiuni mari, care fac imposibilă aducerea integrală a lor în memoria
internă. Problema principală a prelucrării masivelor (vectori, matrice etc.) memorate
în fişiere binare o constituie determinarea poziţiei unui anumit element din masiv în
cadrul fişierului. Indiferent de numărul de dimensiuni ale masivului şi de modalităţile
de memorare a elementelor sale în cadrul fişierului, legătura între elementul de masiv
care se referă şi numărul relativ al articolului care îl conţine se realizează pe baza
funcţiei rang, similară celei implementate pentru datele de tip ARRAY.
În cazul masivelor memorate în fişiere, prelucrarea acestora depinde de
unele caracteristici particulare: numărul de dimensiuni ale masivului; ordinea de
memorare în fişier (lexicografică sau invers lexicografică); modul de memorare (dens
sau nedens); ordinea de parcurgere a masivului.

5.1. Prelucrarea vectorilor

De regulă, vectorii se memorează dens. Numărul relativ al articolului


depinde de rangul elementului în cadrul vectorului, astfel:
• nr_relativ=rang(xi)=i, pentru i=1..n, dacă articolul cu numărul relativ 0 nu
este utilizat, caz în care dimensiunea vectorului este n=FileSize(f)-1, sau memorează
numărul efectiv de componente ale vectorului (n<FileSize(f));
• nr_relativ=rang(xi)-1=i-1, pentru i=1..n, dacă vectorul se memorează
începând cu primul articol (caz în care dimensiunea vectorului este n=FileSize(f)).
Pentru exemplificarea prelucrării vectorilor de mari dimensiuni memoraţi în
fişiere s-a construit unitatea Pascal Unit_vec, care conţine următoarele proceduri de
prelucrare a vectorilor memoraţi dens, începând de la poziţia 0:
• Creare_vector realizează crearea în acces secvenţial a unui fişier binar
ale cărui articole, de tip REAL, memorează elementele vectorului.
• Listare_vector afişează pe ecran conţinutul fişierului (vectorului),
printr-o parcurgere secvenţială. Procedura poate fi folosită de către utilizator, în
special pentru verificarea corectitudinii rezultatelor.
• Sortare_vector realizează sortarea fişierului prin metoda selecţiei, prin
interschimbarea fizică a elementelor vectorului (articolelor), utilizând accesul direct.
• Min_max_vector determină elementul minim, respectiv maxim din
vector, printr-o singură parcurgere secvenţială a fişierului.
• Interclasare realizează interclasarea a doi vectori de dimensiuni
diferite, memoraţi în câte un fişier binar. Procedura asigură sortarea lor înainte de
interclasarea propriu-zisă. Rezultatul va fi memorat într-un fişier binar, similar
vectorilor iniţiali.
• Produs_vectorial determină produsul vectorial dintre doi vectori,
memoraţi consecutiv în acelaşi fişier. Rezultatul va fi memorat împreună cu vectorii
iniţiali, ca extindere a fişierului de intrare, a cărui dimensiune la ieşire va fi 3n.

77
Algoritmi în programare. Aplicaţii

unit unit_vec;
INTERFACE
uses crt;
type tipfis=file of real;
procedure creare_vector(var f:tipfis; var nume:string);
procedure listare_vector(var f:tipfis; var nume:string);
procedure sortare_vector(var f:tipfis; var nume:string);
procedure min_max_vector(var f:tipfis; var nume:string;
var min,max:real);
procedure interclasare(var f,g,h:tipfis;
var nume1,nume2,nume3: string);
procedure produs_vectorial(var f:tipfis; var nume:string);
IMPLEMENTATION
var n,i,j:word; x,y,z,hv:real;
procedure creare_vector;
begin
clrscr; assign(f,nume); rewrite(f);
write('Dimensiune vector: '); readln(n);
for i:=1 to n do
begin
write('x(',i:2,') = '); readln(x); write(f,x)
end;
close(f)
end;
procedure listare_vector;
begin
clrscr; assign(f,nume); reset(f);
for i:=1 to filesize(f) do
begin read(f,x); writeln('x(',i:2,') = ',x:10:2) end;
close(f)
end;
procedure sortare_vector;
begin
clrscr; assign(f,nume); reset(f); n:=filesize(f);
for i:=1 to n-1 do
begin
seek(f,i-1); read(f,x);
for j:=i+1 to n do
begin
seek(f,j-1); read(f,y);
if x>y then
begin
seek(f,i-1); write(f,y);
seek(f,j-1); write(f,x);
x:=y
end
end
end;
close(f)
end;

78
Masive memorate în fişiere

procedure min_max_vector;
begin
assign(f,nume); reset(f);
read(f,max);
min:=max;
for i:=2 to filesize(f) do
begin
read(f,x);
if x>max then max:=x
else if x<min then min:=x
end;
close(f)
end;
procedure interclasare;
begin
hv:=1000000;
sortare_vector(f,nume1);
sortare_vector(g,nume2);
reset(f); reset(g);
assign(h,nume3);
rewrite(h);
read(f,x);
read(g,y);
while (x<>hv) or (y<>hv) do
if x<y then
begin
write(h,x);
if eof(f) then x:=hv else read(f,x)
end
else
begin
write(h,y);
if eof(g) then y:=hv else read(g,y)
end;
close(f); close(g); close(h)
end;
procedure produs_vectorial;
begin
assign(f,nume); reset(f);
n:=filesize(f) div 2;
for i:=1 to n do
begin
seek(f,i-1); read(f,x);
seek(f,n+i-1); read(f,y);
z:=x*y;
seek(f,2*n+i-1); write(f,z)
end;
close(f);
end;
end.

79
Algoritmi în programare. Aplicaţii

5.2. Prelucrarea matricelor

O matrice poate fi memorată într-un fişier binar nedens (similar memorării în


memoria principală) sau dens, în ordine lexicografică sau invers lexicografică.
Numărul relativ al elementului aij se determină pe baza funcţiei rang, astfel:
• rang(aij)=(i-1)⋅nr_coloane+j, în cazul memorării lexicografice, unde
nr_coloane este fie numărul coloanelor efective (populare densă), fie numărul
coloanelor rezervate (populare nedensă);
• rang(aij)=(j-1)⋅nr_linii+i, în cazul memorării invers lexicografice, unde
nr_linii este fie numărul liniilor efective (populare densă), fie numărul liniilor
rezervate (populare nedensă).
Fie m şi n numărul liniilor, respectiv coloanelor efective şi mr şi nr numărul
liniilor, respectiv coloanelor rezervate (mr şi nr corespund elementelor din declaraţia
ARRAY). Pentru ca fişierul să conţină informaţii complete despre matrice trebuie să
memoreze pe lângă elementele ei şi alte informaţii cu privire la dimensiuni:
ƒ m (sau n), în cazul memorării dense. Când se memorează m, n se
determină după relaţia FileSize(f) DIV m; când se memorează n, m se determină
după relaţia FileSize(f) DIV n. Funcţia rang depinde de m sau n, după cum matricea
este memorată invers lexicografic sau lexicografic;
ƒ n şi nr, în cazul memorării nedense în ordine lexicografică; m se
determină după relaţia FileSize(f) DIV nr, iar mr nu are relevanţă (el putea fi
memorat în locul lui nr, acesta determinându-se după relaţia FileSize(f) DIV mr).
Funcţia rang depinde de nr;
ƒ m şi mr, în cazul memorării nedense în ordine invers lexicografică; n se
determină după relaţia FileSize(f) DIV mr, iar nr nu are relevanţă (el putea fi
memorat în locul lui mr, acesta determinându-se după relaţia FileSize(f) DIV nr).
Funcţia rang depinde de mr.
Funcţia rang se calculează şi se utilizează numai dacă problema de rezolvat
implică parcurgerea matricei în altă ordine decât cea în care este memorată în fişier
(consultarea acestuia se realizează în acces direct).

1. Pentru exemplificarea prelucrării matricelor dreptunghiulare, memorate dens şi


lexicografic s-a construit unitatea Unit_mat. Se presupune că matricea are
dimensiunea maximă 100x100. Unitatea conţine următoarele proceduri:
• Creare_matrice realizează crearea în acces secvenţial a unui fişier binar,
care va conţine în primul articol numărul de linii, iar în celelalte elementele matricei.
• Listare_matrice afişează pe ecran o matrice dreptunghiulară, sub
formă tabelară, prin parcurgerea secvenţială a fişierului care o memorează.
• Maxime_pe_coloane determină elementul maxim de pe fiecare coloană a
unei matrice dreptunghiulare, memorată într-un fişier binar. Elementele matricei sunt
accesate direct, pe baza funcţiei rang. Rezultatul se depune într-un vector, memorat
în memoria principală.
• Determinare_linii selectează liniile cu elemente constante ale unei
matrice dreptunghiulare, memorată într-un fişier binar. Primul element al fiecărei

80
Masive memorate în fişiere

linii este accesat direct pe baza funcţiei rang, celelalte elemente fiind accesate
secvenţial. Rezultatul se depune într-un vector, memorat în memoria principală.
• Transpusa determină transpusa unei matrice dreptunghiulare, memorată
într-un fişier binar. Rezultatul este depus într-un alt fişier binar, cu structură similară
fişierului iniţial. Fişierul de intrare este parcurs în acces direct, iar cel de ieşire este
creat în acces secvenţial.
• Adunare_matrice determină suma a două matrice dreptunghiulare,
memorate în câte un fişier binar. Rezultatul este memorat similar, într-un alt fişier
binar. Fişierele de intrare, precum şi cel de ieşire, sunt parcurse secvenţial.
• Produs_matrice realizează înmulţirea a două matrice dreptunghiulare,
memorate în câte un fişier binar. Rezultatul este memorat similar, într-un alt fişier
binar. Fişierele de intrare sunt parcurse în acces direct, iar cel de ieşire este creat în
acces secvenţial.
• Coloane_progr_aritm determină coloanele cu elemente în progresie
aritmetică ale unei matrice dreptunghiulare, memorată într-un fişier binar. Fişierul de
intrare se parcurge în acces direct, iar rezultatul de depune într-un vector, memorat în
memoria principală. Pentru ca problema să aibă sens, matricea trebuie să aibă minim
trei linii.

unit unit_mat;
INTERFACE
uses crt;
type art=record
case boolean of
false:(dim:word);
true:(a:real)
end;
tipfis=file of art;
vector=array[1..100] of real;
procedure creare_matrice(var f:tipfis; var nume:string);
procedure listare_matrice(var f:tipfis; var nume:string);
procedure maxime_pe_coloane(var f:tipfis; var nume:string;
var nrc:word; var max:vector);
procedure determinare_linii(var f:tipfis; var nume:string;
var k:word; var v:vector);
procedure coloane_progr_aritm(var f:tipfis; var nume:string;
var k:word; var v:vector);
procedure transpusa(var f,g:tipfis; var nume1,nume2:string);
procedure adunare_matrice(var f,g,h:tipfis; var nume1,nume2,
nume3 :string);
procedure produs_matrice(var f,g,h:tipfis; var nume1,nume2,
nume3 :string);
IMPLEMENTATION
var
m,n,p,i,j,k:word;
x,y,z:art; vb:boolean;
r:real;

81
Algoritmi în programare. Aplicaţii

procedure creare_matrice;
begin
clrscr; assign(f,nume); rewrite(f);
write('Nr. linii: '); readln(m);
write('Nr. coloane: '); readln(n);
x.dim:=m; write(f,x);
for i:=1 to m do
for j:=1 to n do
begin
write('a(',i,',',j,') = '); readln(x.a);
write(f,x)
end;
close(f)
end;
procedure listare_matrice;
begin
clrscr; assign(f,nume); reset(f);
read(f,x); m:=x.dim;
n:=(filesize(f)-1) div m;
for i:=1 to m do
begin
for j:=1 to n do
begin
read(f,x); write(x.a:5:2,' ')
end;
writeln
end;
close(f)
end;
procedure maxime_pe_coloane;
begin
assign(f,nume); reset(f);
read(f,x); m:=x.dim; nrc:=(filesize(f)-1) div m;
for j:=1 to nrc do
begin
seek(f,j); read(f,x);
max[j]:=x.a;
for i:=2 to m do
begin
seek(f,(i-1)*nrc+j); read(f,x);
if x.a>max[j] then max[j]:=x.a
end
end
end;
procedure determinare_linii;
begin
assign(f,nume); reset(f);
read(f,x); m:=x.dim; n:=(filesize(f)-1) div m;
k:=0;
for i:=1 to m do

82
Masive memorate în fişiere

begin
j:=1; vb:=false; seek(f,(i-1)*n+1); read(f,x);
while (j<=n-1) and not vb do
begin
read(f,y);
if x.a<>y.a then vb:=true else inc(j)
end;
if j=n then begin inc(k); v[k]:=i end
end
end;
procedure transpusa;
Begin
assign(f,nume1); assign(g,nume2);
reset(f); rewrite(g);
read(f,x); m:=x.dim; n:=(Filesize(f)-1) div m;
x.dim:=n; Write(g,x);
for i:=1 to n do
for j:=1 to m do
begin
seek(f,(j-1)*n+i);
read(f,x);
write(g,x)
end;
close(f); close(g)
end;
procedure adunare_matrice;
begin
assign(f,nume1); assign(g,nume2); assign(h,nume3);
reset(f); reset(g); rewrite(h);
read(f,x);
m:=x.dim; n:=(Filesize(f)-1) div m;
seek(g,1); write (h,x);
for i:=1 to m do
for j:=1 to n do
begin
read(f,x); read(g,y);
z.a:=x.a+y.a;
write(h,z)
end;
close(f); close(g); close(h)
end;
procedure produs_matrice;
begin
assign(f,nume1); assign(g,nume2); assign(h,nume3);
reset(f); reset(g); rewrite(h);
read(f,x); m:=x.dim; read(g,y); n:=y.dim;
p:=(Filesize(g)-1) div n; write(h,x);
for i:=1 to m do
for j:=1 to p do
begin

83
Algoritmi în programare. Aplicaţii

z.a:=0;
for k:=1 to n do
begin
seek(f,(i-1)*n+k); Read(f,x);
seek(g,(k-1)*p+j); read(g,y);
z.a:=z.a+x.a*y.a
end;
write(h,z)
end;
close(f); close(g); close(h)
end;
procedure coloane_progr_aritm;
begin
assign(f,nume); reset(f);
read(f,x); m:=x.dim; n:=(Filesize(f)-1) div m;
k:=0;
for j:=1 to n do
begin
vb:=false;
for i:=1 to m-2 do
begin
seek(f,i*n+j); read(f,x);
seek(f,(i-1)*n+j); read(f,y);
seek(f,(i+1)*n+j); read(f,z);
if 2*x.a<>(y.a+z.a) then vb:=true
end;
if not vb then
begin
k:=k+1;
v[k]:=j
end
end;
close(f)
end
end.

2. Pentru exemplificarea prelucrării matricelor pătrate, memorate dens şi lexicografic


s-a construit unitatea Unit_m2, care include o serie de proceduri şi funcţii specifice.
Numărul de linii şi de coloane ale matricei nu este memorat în fişier, ci va fi calculat
pe baza dimensiunii fişierului (presupus n2). Numărul relativ al elementului în fişier
este dat de rangul elementului a(i,j) minus 1, deoarece matricea se memorează în
fişier începând de la poziţia 0.
• Procedurile Creare_mat_real şi Creare_mat_intreg realizează crearea
în acces secvenţial a unui fişier binar, care va conţine matricea cu elemente reale,
respectiv întregi.
• Procedurile Listare_mat_real şi Listare_mat_intreg afişează pe
ecran o matrice pătrată cu elemente reale, respectiv întregi, sub formă tabelară, prin
parcurgerea secvenţială a fişierului care o memorează.

84
Masive memorate în fişiere

• Funcţia Medie_a determină media aritmetică a elementelor din triunghiul de


deasupra diagonalei principale, inclusiv diagonala, dintr-o matrice pătrată cu
elemente reale. Media se calculează numai dacă există cel puţin două elemente.
• Funcţia Medie_g determină media geometrică a elementelor strict pozitive de
pe diagonala secundară a unei matrice pătrate cu elemente reale. Media se calculează
numai dacă există cel puţin două elemente, fişierul fiind parcurs în acces direct.
• Funcţia Urma calculează urma unei matrice pătrate cu elemente reale (suma
elementelor de pe diagonala principală). Fişierul este parcurs în acces direct.
• Funcţia Numar determină numărul de elemente divizibile cu 3 din triunghiul
de sub diagonala secundară dintr-o matrice pătrată cu elemente naturale.

unit unit_m2;
INTERFACE
uses crt;
type tipfis=file of real; tipfisi=file of word;
vector=array[1..100] of real;
procedure creare_mat_real(var f:tipfis; var nume:string);
procedure creare_mat_intreg(var f:tipfisi; var nume:string);
procedure listare_mat_real(var f:tipfis; var nume:string);
procedure listare_mat_intreg(var f:tipfisi; var nume:string);
function medie_a(var f:tipfis; var nume:string):real;
function medie_g(var f:tipfis; var nume:string):real;
function urma(var f:tipfis; var nume:string):real;
function numar(var f:tipfisi; var nume:string):word;
IMPLEMENTATION
var n,i,j,k,x:word; a,med,tr:real;
procedure creare_mat_real;
begin
clrscr; assign(f,nume); rewrite(f);
write('Nr.linii/coloane: '); readln(n);
for i:=1 to n do
for j:=1 to n do
begin
write('a(',i,',',j,')='); readln(a); write(f,a)
end;
close(f)
end;
procedure creare_mat_intreg;
begin
clrscr; assign(f,nume); rewrite(f);
write('Nr.linii/coloane: '); readln(n);
for i:=1 to n do
for j:=1 to n do
begin
write('a(',i,',',j,')='); readln(x); write(f,x)
end;
close(f)
end;

85
Algoritmi în programare. Aplicaţii

procedure listare_mat_real;
begin
clrscr; assign(f,nume); reset(f);
n:=trunc(sqrt(filesize(f)));
for i:=1 to n do begin
for j:=1 to n do
begin read(f,a); write(a:5:2,' ') end;
writeln
end;
close(f)
end;
procedure listare_mat_intreg;
begin
clrscr; assign(f,nume); reset(f);
n:=trunc(sqrt(filesize(f)));
for i:=1 to n do begin
for j:=1 to n do
begin read(f,x); write(x,' ') end;
writeln
end;
close(f)
end;
function medie_a;
begin
assign (f,nume); reset (f); n:=trunc(sqrt(filesize(f)));
med:=0; k:=0;
for i:=1 to n do
for j:=i to n do
begin
seek (f,(i-1)*n+j-1); read (f,a);
med:=med+a; k:=k+1
end;
if k>=2 then medie_a:=med/k;
close (f)
end;
function medie_g;
begin
assign(f,nume); reset(f); n:=trunc(sqrt(filesize(f)));
med:=1; k:=0;
for i:=1 to n do
begin
seek(f,i*(n-1)); read(f,a);
if a>0 then begin
med:=med*a;
k:=k+1
end
end;
if k>=2 then medie_g:=exp(ln(med)/k);
close (f)
end;

86
Masive memorate în fişiere

function urma;
begin
assign (f,nume); reset (f);
n:=trunc(sqrt(filesize(f)));
tr:=0;
for i:=1 to n do
for j:=1 to n do
begin
seek (f,(j-1)*n+j-1);
read (f,a);
tr:=tr+a
end;
urma:=tr;
close (f)
end;
function numar;
begin
assign (f,nume); reset (f);
n:=trunc(sqrt(filesize(f)));
k:=0;
for j:=2 to n do
for i:=n-j+2 to n do
begin
seek (f,(i-1)*n+j-1);
read (f,x);
if (x mod 3)=0 then inc(k)
end;
numar:=k;
close (f)
end
end.

5.3. Matrice memorate nedens

Să se determine elementul maxim de pe fiecare coloană a unei matrice de


dimensiuni m⋅n (n<=1000), memorată nedens într-un fişier binar, în ordine
lexicografică. Primul articol conţine numărul de coloane efective. Numărul rezervat
de coloane este 1000. Pot fi elaborate variante în care se încarcă în memoria internă o
întreagă linie a matricei. Din această categorie de rezolvări sunt prezentate două
variante: cu parcurgerea integrală de n ori a fişierului şi cu o singură parcurgere.

• Varianta 1 - fişierul se parcurge integral de n ori.


type
vector=array[1..1000] of real;
var
matrice:file of vector;
max,linie:vector;
m,n,i,j:longint;

87
Algoritmi în programare. Aplicaţii

begin
assign(matrice,'matrice.dat'); reset(matrice);
read(matrice,linie); {citirea numarului de coloane}
n:=trunc(linie[1]);
m:=filesize(matrice)-1;
for j:=1 to n do
begin
seek(matrice,1); {pozitionare pe prima linie}
read(matrice,linie);
max[j]:=linie[j];
for i:=2 to m do
begin
read(matrice,linie);
if linie[j] > max[j] then max[j]:=linie[j]
end
end;
writeln('Maximele pe fiecare coloana sunt:');
for j:=1 to n do
writeln('Coloana ',j,' = ',max[j]:10:2);
close(matrice)
end.

• Varianta 2 - fişierul se parcurge o singură dată.


type
vector=array[1..1000] of real;
var
matrice:file of vector;
max,linie:vector;
m,n,i,j:longint;
begin
assign(matrice,'matrice.dat'); reset(matrice);
read(matrice,linie); {citirea numarului de coloane}
n:=trunc(linie[1]);
m:=filesize(matrice)-1;
read(matrice,linie);
{initializare maxime cu primul element de pe coloana j}
for j:=1 to n do max[j]:=linie[j];
for i:=2 to m do
begin
read(matrice,linie);
for j:=1 to n do
if linie[j] > max[j] then max[j]:=linie[j]
end;
writeln('Maximele pe fiecare coloana sunt:');
for j:=1 to n do
writeln('Coloana ',j,' = ',max[j]:10:2);
close(matrice)
end.

88
6. Algoritmi de prelucrare a fişierelor organizate secvenţial

Din punct de vedere al operaţiilor de gestiune solicitate de diverse aplicaţii,


fişierele binare se pot grupa în fişiere care nu sunt actualizate (ţinute la zi) şi fişiere
care sunt actualizate. De obicei, fişierele din prima grupă se regăsesc în aplicaţii
matematice sau ca fişiere temporare şi de tranzacţii în aplicaţii de gestiune
economică. Fişierele din cea de-a doua grupă sunt, de obicei, fişiere permanente
(principale) în aplicaţii de gestiune economică şi au particularităţi de proiectare,
referitoare, în special, la asigurarea ştergerii şi adăugării de articole.
Asupra fişierelor binare care nu necesită actualizare se realizează, de obicei,
operaţiile de creare (populare) şi consultare. Dintre operaţiile de actualizare pot fi
realizate, fără mari complicaţii, modificarea şi adăugarea densă de articole.

♦ Popularea fişierelor se realizează prin preluarea datelor fie din alte fişiere,
fie de la tastatură (popularea interactivă). În ultimul caz, cel mai des întâlnit în
practică, fişierul conducător corespunde mulţimii datelor introduse de la tastatură.
Articolele sunt preluate câmp cu câmp, neexistând posibilitatea citirii unei variabile de
tip articol şi, în plus, introducerea unei date este adesea însoţită de proceduri de
validare specifice, cu reintroducerea ei în cazul unei erori.
Sfârşitul introducerii datelor de la tastatură (şi implicit a procesului de
populare a fişierului) poate fi:
- De tip chestionar, prin consultarea utilizatorului, privind continuarea sau nu
a introducerii articolelor. Pentru un volum mare de date, varianta prezintă dezavan-
tajul măririi timpului de prelucrare.
- Convenţional, prin introducerea pentru primul câmp din articol a unei valori
prestabilite, cu semnificaţie de sfârşit de prelucrare.
- Standard, prin tastarea caracterului CTRL/Z, cu rol de sfârşit de fişier
TEXT, caz în care variabilei standard CheckEof (definită în unitatea standard CRT)
trebuie să i se atribuie în program valoarea TRUE.
O altă problemă a populării fişierelor binare o reprezintă aşezarea articolelor
pe suportul extern. Din acest punct de vedere se întâlnesc două modalităţi:
• Populare densă, prin care articolele se scriu unul după altul, în ordinea în
care au fost furnizate, fără a se lăsa locuri libere (acces secvenţial). Pentru fişierele
care nu necesită actualizare acesta este tipul recomandat.
• Populare aleatoare, prin care articolele sunt scrise pe poziţiile al căror
număr relativ este furnizat explicit de programator (acces direct). Scrierea unui articol
se realizează după poziţionarea pe numărul relativ dorit, cu procedura
Seek(f,nr_relativ). La populare, nr_relativ nu este limitat decât de spaţiul existent pe
suportul extern.
Metoda are dezavantajul că necesită evidenţa "articolelor vide". În cazul
fişierelor care nu necesită actualizare, popularea aleatoare se recomandă numai dacă,
după creare, fişierul este dens.

89
Algoritmi în programare. Aplicaţii

Exerciţiul 6.1. Să se realizeze programul pentru crearea unui fişier secvenţial care
memorează datele referitoare la facturile emise de către o societate comercială,
într-un anumit an. Structura articolului este următoarea:

Număr Data emiterii Denumire Valoare TVA


Cod fiscal
factură lună zi beneficiar facturată facturat
String[10] 1..12 1..31 String[20] Longint Real Real

Datele se introduc de la tastatură, câmp cu câmp, fără validare. Sfârşitul


introducerii este standard (se tastează <CTRL/Z> în câmpul nr_fact). Programul
de creare a fişierului Facturi.dat este Creare.

Program Creare;
Uses crt;
Type
data = record
luna:1..12;
zi:1..31
end;
art_fact = record
nr_fact:string[10];
data_emit:data;
den_benef:string[20];
cod_fiscal:longint;
valoare,tva:real
end;
Var
f:file of art_fact; factura:art_fact;
Begin
Assign(f,'facturi.dat'); Rewrite(f);
checkeof:=true; clrscr;
With factura do begin
Gotoxy(15,10); Write('Nr. factura: '); Gotoxy(40,10);
While not eof do
begin
Readln(nr_fact);
Gotoxy(15,11); Writeln('Data emiterii');
Gotoxy(22,12); Writeln('luna:');
Gotoxy(40,12); Readln(data_emit.luna);
Gotoxy(22,13); Writeln('ziua:');
Gotoxy(40,13); Readln(data_emit.zi);
Gotoxy(15,14); Writeln('Denumire benef.:');
Gotoxy(40,14); Readln(den_benef);
Gotoxy(15,15); Writeln('Cod fiscal:');
Gotoxy(40,15); Readln(cod_fiscal);
Gotoxy(15,16); Writeln('Valoare facturata:');
Gotoxy(40,16); Readln(valoare);
Gotoxy(15,17); Writeln('TVA facturat:');

90
Algoritmi de prelucrare a fişierelor organizate secvenţial

Gotoxy(40,17); Readln(tva);
Write(f,factura);
clrscr; Gotoxy(15,9); Write('Nr. factura: ');
Gotoxy(40,9)
End {while};
Close(f)
End {with}
End.

♦ Consultarea fişierelor are mai multe variante, în funcţie de scopul prelu-


crării. După modul de regăsire a articolelor în cadrul fişierului, consultarea poate fi
secvenţială, directă sau mixtă.
• Consultarea secvenţială presupune regăsirea articolelor în ordinea în care
sunt memorate pe suportul extern. După numărul articolelor prelucrate, consultarea
secvenţială poate fi: integrală, când se prelucrează toate articolele fişierului; cu
selecţie, când se prelucrează numai acele articole care au una sau mai multe
caracteristici comune. După numărul de caracteristici, selecţia poate fi simplă, dublă,
multiplă. Pentru consultarea secvenţială se poate utiliza oricare din tipurile de
algoritmi de prelucrare cu fişier conducător1.

Exemplu: Obţinerea unei situaţii cu mai multe grade de total.


Pentru aceasta se stabilesc câmpuri, numite caracteristici de grupare sau
caracteristici de control, asociate gradelor de total. O caracteristică de control este un
câmp al articolului din fişierul de date, care are aceeaşi valoare pentru mai multe
înregistrări. Astfel, articolele care au valoare comună pentru o caracteristică de
grupare se pot ordona pe submulţimi, formând o grupă de control. Fişierul poate
constitui, în ansamblul său, caracteristica de grupare de cel mai înalt nivel, pentru care
se poate calcula totalul general. Numărul maxim de grade de total este superior cu unu
numărului de caracteristici de control stabilite. Între caracteristicile de grupare se
stabileşte o relaţie de ordine ierarhică. Pentru prelucrarea fişierului, cu utilizare
minimă de memorie, articolele trebuie sortate după caracteristicile de control. Acest
tip de prelucrare intră în categoria consultărilor secvenţiale integrale. Prelucrarea unui
fişier sortat după criteriile enunţate presupune existenţa unor operaţii standard,
executate la schimbarea valorii fiecărei caracteristici de control stabilite:
• operaţii iniţiale ale unei grupe de control prin care se iniţializează variabila
de total specifică grupei; se salvează valoarea caracteristicii primului articol din grupă;
alte operaţii iniţiale specifice grupei;
• operaţii finale ale unei grupe de control prin care se afişează totalul calculat
pentru caracteristica ce se schimbă; se cumulează totalul grupei curente la totalul
grupei ierarhic superioară; alte operaţii finale specifice grupei;
• condiţia de prelucrare a unei grupe de control conţine, pe lângă condiţia
specifică, toate celelalte condiţii din amonte.

1
Figurile 15.2 - 15.6, capitolul Algoritmi de prelucrare a fişierelor binare din lucrarea
Algoritmi în programare, B. Ghilic-Micu (coord.), Ed. ASE, Bucureşti 2002, pag. 235-238

91
Algoritmi în programare. Aplicaţii

Raportul final este listat la imprimantă, fie direct, ca fişier de ieşire, fie creat
pe suport magnetic, ca fişier TEXT, în vederea imprimării ulterioare. Structura unei
pagini a raportului şi controlul trecerii la o nouă pagină trebuie asigurate de
programator.
În continuare se prezintă structura de principiu2 a unui program de obţinere a
unui raport final, cu control după două caracteristici şi trei grade de total, unde
camp_1 şi camp_2 sunt caracteristicile de control (câmpuri din articol), v1 şi v2 sunt
variabile de lucru pentru salvarea caracteristicilor, iar totg, tot1 şi tot2 sunt
variabile pentru calculul gradelor de total. Analog, se poate extinde pentru oricâte
caracteristici şi grade de total.

procedure inceput;
begin
(* citire nume fisiere externe *)
assign(f,nume_fisier);reset(f); assign(g,lista); rewrite(g);
sf:=false; totg:=0;
(* scriere in lista a antetului si capului de tabel *)
read(f,x);
end;
procedure inceput_1;
begin
tot1:=0; v1:=x.camp_1
end;
procedure inceput_2;
begin
tot2:=0; v2:=x.camp_2
end;
procedure sfarsit_1;
begin
writeln('total 1 = ',tot1); totg:=totg+tot1
end;
procedure sfarsit_2;
begin
writeln('total 2 = ',tot2); tot1:=tot1+tot2
end;
procedure sfarsit;
begin
writeln('total general = ',totg);
close(f); close(g)
end;
procedure prel_art_x;
begin
(* prelucrarea articolului x *)
if eof(f) then sf:=true else read(f,x)
end;

2
În exemple, comentariile incluse între perechile de caractere (* şi *) sugerează existenţa
unei secvenţe de program, iar cele incluse între caracterele { } sunt comentarii propriu-zise.

92
Algoritmi de prelucrare a fişierelor organizate secvenţial

procedure prel_2;
begin
inceput_2;
while (v1=x.camp_1) and (v2=x.camp_2) and not sf
do prel_art_x;
sfarsit_2
end;
procedure prel_1;
begin
inceput_1;
while (v1=x.camp_1) and not sf do prel_2;
sfarsit_1
end;
{programul principal}
begin
inceput;
while not sf do prel_1;
sfarsit
end.

Exerciţiul 6.2. Să se realizeze programul pentru obţinerea unei liste cu valoarea


lunară facturată şi TVA-ul aferent, pentru fiecare beneficiar către care au fost
emise facturi, utilizând informaţiile memorate în fişierul creat prin programul
prezentat în exerciţiul 6.1. Numărul şi denumirile beneficiarilor sunt necunoscute la
momentul proiectării. Schema de sistem este prezentată în figura 6.1.
Programul Consultare este structurat pe trei module:
• modulul Creare_manevra (1) copiază într-un fişier intermediar (fişier de
manevră) informaţiile utile obţinerii situaţiei de ieşire, în vederea sortării lor;
• modulul Sortare_manevra (2) realizeză sortarea fişierului de manevră
prin metoda selecţiei, după valoarea câmpului den_benef;
• modulul Listare (3) realizează obţinerea situaţiei finale într-un fişier
magnetic de tip TEXT.

CONSULTARE
Facturi.dat Tabel.txt
1 2 3

Manevra.tmp

Fig. 6.1. Schema de sistem a programului de consultare

93
Algoritmi în programare. Aplicaţii

Program Consultare;
Uses crt;
Type data = record
luna:1..12;
zi:1..31
end;
art_fact = record
nr_fact:string[10];
data_emit:data;
den_benef:string[20];
cod_fiscal:longint;
valoare,tva:real
end;
art_man = record
data_emit:data;
den_benef:string[20];
valoare,tva:real
end;
Var f:file of art_fact;
factura:art_fact;
manevra:file of art_man;
aux:art_man;
lista:text;
Procedure Creare_manevra;
Begin
Assign(f,'facturi.dat'); Reset(f);
Assign(manevra,'manevra.tmp'); Rewrite(manevra);
While not eof(f) do
begin
Read(f,factura);
aux.data_emit:=factura.data_emit;
aux.den_benef:=factura.den_benef;
aux.valoare:=factura.valoare;
aux.tva:=factura.tva;
Write(manevra,aux)
end;
Close(f);
Close(manevra)
End;
Procedure Sortare_manevra;
Var
art1,art2:art_man;
i,j:word;
Begin
Assign(manevra,'manevra.tmp'); Reset(manevra);
For i:=1 to filesize(manevra)-1 do
Begin
Seek(manevra,i-1); Read(manevra,art1);
For j:=i+1 to filesize(manevra) do
Begin

94
Algoritmi de prelucrare a fişierelor organizate secvenţial

Seek(manevra,j-1); Read(manevra,art2);
If art1.den_benef > art2.den_benef then
Begin
Seek(manevra,i-1); Write(manevra,art2);
Seek(manevra,j-1); Write(manevra,art1);
art1:=art2
End
End
End;
Close(manevra)
End;
Procedure Listare;
Var
sf:boolean; i:1..12;
c:string[20];
tot_val,tot_tva:array[1..12] of real;
Const
luni:array[1..12] of string[3]=
('Ian','Feb','Mar','Apr','Mai','Iun','Iul','Aug','Sep','Oct',
'Nov','Dec');
Begin
Assign(manevra,'manevra.tmp'); Reset(manevra);
Assign(lista,'tabel.txt'); Rewrite(lista);
sf:=false;
Writeln(lista,
'Tabel cu valorile facturate lunar, pe beneficiari');
Writeln(lista);
Writeln(lista,’Valoare TVA’);
With aux do begin
Read(manevra,aux);
While not sf do
begin
c:=den_benef;
for i:=1 to 12 do begin
tot_val[i]:=0;
tot_tva[i]:=0
end;
While (c=den_benef) and not sf do
begin
tot_val[data_emit.luna]:=
tot_val[data_emit.luna]+valoare;
tot_tva[data_emit.luna]:=
tot_tva[data_emit.luna]+tva;
{$I-} Read(manevra,aux); {$I+}
If IOresult <> 0 then sf:=true
end;
Writeln(lista,c);
for i:=1 to 12 do Writeln(lista,
' ':5,luni[i],':',tot_val[i]:12:0,tot_tva[i]:10:0)
end;

95
Algoritmi în programare. Aplicaţii

Close(manevra);
Erase(manevra);
Close(lista)
end
End;
{programul principal}
Begin
Creare_manevra;
Sortare_manevra;
Listare
End.

• Consultarea în acces direct presupune regăsirea articolului după numărul


relativ, prin secvenţa Seek(f,nr_relativ); Read(f,art). Numărul relativ este furnizat de
utilizator şi trebuie să aparţină domeniului 0..FileSize(f)-1. Se remarcă faptul că dacă
nr_relativ depăşeşte dimensiunea fişierului, procedura Seek nu generează eroare, dar
citirea va determina întreruperea execuţiei programului. Pentru evitarea acestei situaţii
se va include în program validarea apartenenţei numărului relativ la intervalul
acceptat. Algoritmul de consultare în acces direct a unui fişier are un alt fişier
conducător (de exemplu, tastatura).

Exemplu:
begin
(* citire nume fisier extern *)
checkeof:=true;
assign(f,nume_fisier);
reset(f);
write('nr. relativ: ');
while not eof do
begin
readln(r); {citire numar relativ}
seek(f,r);
{$i-} read(f,art); {$i+} {citire articol in acces direct}
if ioresult = 0 then (* prelucrare articol *)
else writeln('Articol inexistent !');
write('Nr. relativ (sau ctrl-z): ')
end;
close(f)
end.

• Consultarea în acces mixt utilizează o combinaţie între accesul direct şi cel


secvenţial, în vederea prelucrării unui grup de articole, memorate contiguu în fişier şi
selectabile printr-o condiţie. Pentru fişierele binare, metoda poate fi aplicată dacă se
doreşte selectarea articolelor dintre două limite ale numerelor relative: limita
inferioară (li) şi limita superioară (ls). Algoritmul trebuie să verifice relaţia
0≤li≤ls<FileSize(f), după care parcurgerea fişierului poate fi realizată prin orice tip de
structură repetitivă.

96
Algoritmi de prelucrare a fişierelor organizate secvenţial

Exemplu:
begin
(* citire nume fisier extern *)
assign(f,nume_fisier);
reset(f);
write('limita inferioara: ');
readln(li); { citirea nr. relativ al primului articol }
write('limita superioara: ');
readln(ls); { citirea nr. relativ al ultimului articol }
if (0<=li) and (li<=ls) and (ls<filesize(f)) then
begin
seek(f,li);
for i:=li to ls do
begin
read(f,art);
(* prelucrare articol *)
end
end
else
writeln('>> Nu este indeplinita conditia de limite');
close(f)
end.

♦ Adăugarea de articole se realizează, în general, cu tranzacţii de la


tastatură, similar operaţiei de populare. Pentru o corectă exploatare ulterioară,
adăugarea trebuie să fie densă. Acest lucru poate fi realizat astfel:
• Adăugare la sfârşit (extindere), după ultimul articol scris. Operaţia se
realizează similar populării în acces secvenţial, după poziţionarea pe marcatorul de
sfârşit de fişier, cu procedura Seek(f,FileSize(f)).

Exemplu:
begin
(* citire nume fisier extern *)
assign(f,nume_fisier); reset(f);
{pozitionare dupa ultimul articol scris}
seek(f,filesize(f));
checkeof:=true;
write('camp 1: ');
while not eof do
begin
readln(art.camp_1);
(* preluare de la tastatura a celorlalte
campuri din articol *)
write(f,art);
write('camp 1 (sau ctrl-z): ')
end;
close(f)
end.

97
Algoritmi în programare. Aplicaţii

• Inserarea unor articole. Se aplică în cazul în care articolele sunt scrise în


fişier în ordinea crescătoare (descrescătoare) a valorilor unui anumit câmp. În acest
caz, noul articol va fi inserat între două articole, astfel:
- se caută (cu un algoritm secvenţial, binar etc.) poziţia k în care trebuie
inserat noul articol;
- se copiază, glisând cu o poziţie spre dreapta, toate articolele de la sfârşitul
fişierului până la articolul cu numărul relativ k;
- se scrie în acces direct noul articol, în poziţia k.

Exemplu:
{articolele sunt in ordinea crescatoare a valorii campului 1}
begin
(* citire nume fisier extern *)
assign(f,nume_fisier);
reset(f);
checkeof:=true;
write('camp 1: ');
while not eof do {se pot adauga mai multe articole}
begin
{introducerea campului dupa care sunt sortate articolele}
readln(art_nou.camp_1);
(* preluare de la tastatura a celorlalte
campuri din articolul de adaugat *)
{cautarea pozitiei in care se va insera articolul}
seek(f,0); { pozitionare pe inceput de fisier }
sf:=false;
read(f,art_existent);
while not sf and (art_existent.camp_1<art_nou.camp_1) do
begin
{$I+} read(f,art_existent); {$I-}
if ioresult <> 0 then sf:=true
end;
if not sf then begin
k:=filepos(f)-1;{articolul se va insera in pozitia k }
for i:=filesize(f)-1 downto k do
begin
seek(f,i);
read(f,art_existent);
write(f,art_existent)
end
end
else k:=filesize(f); {articolul se adauga la sfarsit}
seek(f,k);
write(f,art_nou);
write('camp 1: ')
end;
close(f)
end.

98
Algoritmi de prelucrare a fişierelor organizate secvenţial

♦ Modificarea valorii unor câmpuri din articol se realizează în mai multe


etape:
- se citeşte articolul care se modifică (Seek şi Read);
- se modifică (în zona articol din memoria principală) câmpurile cu valorile dorite,
introduse, în general, de la tastatură;
- se repoziţionează pe articolul respectiv cu Seek(f,FilePos(f)-1);
- se scrie articolul modificat, cu procedura Write.
O problemă importantă rămâne selectarea câmpurilor care se modifică, pentru
fiecare articol în parte. O variantă simplă este afişarea vechii valori, urmată de
introducerea noii valori, în variabile independente de tip STRING. În cazul în care
şirul introdus este vid (s-a tastat numai <ENTER>), respectivul câmp, prin convenţie,
nu se modifică. Altfel, câmpului respectiv i se va atribui valoarea citită în variabila
independentă, eventual prin conversie cu procedura VAL, pentru câmpurile numerice.

Exemplu:
(* cautare articol de modificat *)
read(f,art);
write('Codul: ',art.cod,' '); {afisare vechea valoare}
readln(cods); {citire noua valoare; cods este de tip string}
if length(cods)<>0 then
val(cods,art.cod,err); {conversie din ASCII in binar}
write('Denumire: ',art.den,' '); {afisare vechea valoare}
readln (dens); {citire noua valoare}
if length(dens) <> 0 then
art.den:=dens; {atribuire noua valoare}
(* introducerea celorlalte campuri din articol *)
seek(f,filepos(f)-1); {repozitionare pe articol}
write(f,art) {rescriere articol modificat }

O altă variantă se poate realiza prin folosirea unei machete de ecran în care se
afişează valorile actuale ale fiecărui câmp de modificat, se poziţionează succesiv
cursorul la începutul fiecărui câmp, cu două răspunsuri posibile ale utilizatorului:
<ENTER>, caz în care se menţine actuala valoare, respectiv o tastă diferită de
<ENTER>, reprezentând primul caracter al noii valori.

Exerciţiul 6.3. Să se realizeze programul pentru crearea unui fişier secvenţial


Produse.dat, care memorează datele referitoare la produsele fabricate de către o
întreprindere, într-un an. Structura articolului este următoarea:

Cod Denumire Cod Preţ unitar Cantitate lunară


produs produs depozit mediu 1 2 … 12
byte String[30] char longint word word word

Datele se introduc de la tastatură, câmp cu câmp, asigurându-se


următoarele validări:

99
Algoritmi în programare. Aplicaţii

- codul produsului să fie numeric;


- denumirea produsului să fie alfabetică (formată numai din litere mari,
litere mici şi spaţii);
- codul depozitului să fie o literă ;
- preţul unitar să fie numeric şi mai mare sau egal cu 100;
- cantităţile lunare să fie numerice.
În cazul în care o dată nu îndeplineşte condiţiile impuse, se semnalează
eroarea şi se reia introducerea. Sfârşitul introducerii este standard (se tastează
<CTRL/Z> în câmpul cod).

program creare_fisier_secvential;
uses crt;
type
produs=record
cod:byte;
den:string[30];
dep:char;
pu:longint;
cant:array[1..12] of word
end;
var
art:produs;
f:file of produs;
er:boolean;
i,l:byte;
s:string[100];
const
alfabet=['A'..'Z','a'..'z',' '];
procedure eroare;
begin
er:=true; gotoxy(10,25);
write(s,' tastati <ENTER>',#7);
repeat until readkey=#13;
gotoxy(10,25); clreol;
end;
procedure cit_cod;
begin
repeat
er:=false; gotoxy(38,5);
{$i-}; readln(art.cod); {$i+};
if ioresult <> 0 then
begin
s:='Valoare nenumerica !';
eroare; gotoxy(38,5);
clreol
end
until not er
end;

100
Algoritmi de prelucrare a fişierelor organizate secvenţial

procedure cit_den;
begin
repeat
er:=false; gotoxy(38,6); clreol;
readln(art.den); l:=length(art.den);
for i:=1 to l do
if not (art.den[i] in alfabet) then er:=true;
if er then
begin
s:='Caractere nealfabetice !';
eroare
end
until not er
end;
procedure cit_dep;
begin
repeat
er:=false; gotoxy(38,7); clreol;
readln(art.dep);
if not (upcase(art.dep)in ['A'..'Z']) then
begin
s:='Cod depozit eronat !';
eroare
end
until not er
end;
procedure cit_pret;
begin
repeat
er:=false; gotoxy(38,8); clreol;
{$i-} readln(art.pu); {$i+}
if ioresult<>0 then
begin
s:='Caractere nenumerice !';
eroare
end
else if art.pu < 100 then
begin
s:='Pret < 100 !';
eroare
end
until not er
end;
procedure cit_cant;
begin
repeat
er:=false; gotoxy(38,i+8); clreol;
{$i-} readln(art.cant[i]); {$i+}
if ioresult<>0 then
begin

101
Algoritmi în programare. Aplicaţii

s:='Caractere nenumerice !';


eroare
end
until not er
end;
procedure inceput;
begin
textbackground(magenta); textcolor(yellow); clrscr;
assign(f,'produse.dat'); rewrite(f); checkeof:=true;
gotoxy(20,5); write('Cod (sau ^Z): ');
gotoxy(20,6); write('Denumire : ');
gotoxy(20,7); write('Cod depozit: ');
gotoxy(20,8); write('Pret mediu : ');
for i:=1 to 12 do
begin
gotoxy(20,i+8);
write('Cant. luna ',i:2,' : ')
end;
gotoxy(38,5)
end;
procedure prelucrare;
begin
cit_cod; cit_den; cit_dep; cit_pret;
for i:=1 to 12 do cit_cant;
write(f,art);
for i:=5 to 20 do begin gotoxy(38,i); clreol end;
gotoxy(38,5)
end;
procedure sfarsit;
begin close(f)
end;
{programul principal}
begin
inceput;
while not eof do prelucrare;
sfarsit
end.

Exerciţiul 6.4. Să se realizeze programul pentru afişarea pe monitor a denumirii şi


a producţiei valorice anuale pentru produsele existente în fişierul Produse.dat,
ale căror coduri se introduc de la tastatură. Sfârşitul introducerii de la tastatură se
marchează standard (^Z în câmpul cod).
Observaţii: Deoarece codul produselor are valori unice, căutarea se realizeză până
când se regăseşte un articol al cărui cod produs este egal cu valoarea introdusă de
la tastatură, caz în care se calculează valoarea anuală şi se afişează, sau până la
sfârşitul fişierului, caz în care produsul căutat nu există în fişier şi se afişează un
mesaj corespunzător. Pentru fiecare nou cod, căutarea se realizează de la începutul
fişierului.

102
Algoritmi de prelucrare a fişierelor organizate secvenţial

program consultare_dupa_camp_cu_valoare_unica;
uses crt;
type
produs=record
cod:byte;
den:string[30];
dep:char;
pu:longint;
cant:array[1..12] of word
end;
var
art:produs;
f:file of produs;
vb:boolean;
cod_t,i:byte;
v:real;
begin
assign(f,'produse.dat'); reset(f);
clrscr; checkeof:=true; gotoxy(27,5);
write('Codul produsului: ');
while not eof do
begin
gotoxy(50,5); readln(cod_t);
seek(f,0);
vb:=false;
while not vb and not eof(f) do
begin
read(f,art);
if art.cod = cod_t then
begin
v:=0;
for i:=1 to 12 do v:=v+art.cant[i];
v:=v*art.pu;
gotoxy(27,12);
writeln('Denumire',' ':10,'Valoare');
gotoxy(25,15);
writeln(art.den,' ':5,v:10:0,' lei');
readln; vb:=true
end
end;
if not vb then
begin
gotoxy(30,15);
writeln('Cod produs eronat !',#7)
end;
clrscr; gotoxy(27,5);
write('Codul produsului (sau ^Z): ')
end;
close(f)
end.

103
Algoritmi în programare. Aplicaţii

Exerciţiul 6.5. Să se realizeze programul pentru afişarea pe monitor a denumirii şi


a producţiei valorice anuale pentru produsele existente în fişierul Produse.dat,
aflate în depozitele ale căror coduri se introduc de la tastatură. Sfârşitul introducerii
de la tastatură se marchează standard (^Z în câmpul dep).
Observaţii: Deoarece într-un depozit se află mai multe produse (câmpul dep are
valori duplicate), căutarea se realizeză de la începutul până la sfârşitul fişierului
pentru fiecare nou cod de depozit introdus. În cazul în care nici un produs nu are
codul depozitului egal cu valoarea introdusă de la tastatură, se afişează un mesaj
corespunzător şi procesul se reia. Existenţa sau inexistenţa a cel puţin unui produs
în depozitul căutat este marcată cu o variabilă semafor, care este şi contor (k).

program consultare_dupa_camp_cu_valoare_duplicata;
uses crt;
type
produs=record
cod:byte;
den:string[30];
dep:char;
pu:longint;
cant:array[1..12] of word
end;
var
art:produs;
f:file of produs;
sir:string[30];
dep_t:char;
i,k:byte;
v:real;
begin
assign(f,'produse.dat'); reset(f);
clrscr; checkeof:=true;
gotoxy(27,5);
write('Codul depozitului: ');
while not eof do
begin
gotoxy(50,5); readln(dep_t);
seek(f,0);
k:=0;
while not eof(f) do
begin
fillchar(sir,31,' ');
read(f,art);
if art.dep=dep_t then
begin
inc(k); v:=0;
for i:=1 to 12 do v:=v+art.cant[i];
v:=v*art.pu;
gotoxy(10,12);

104
Algoritmi de prelucrare a fişierelor organizate secvenţial

writeln('Cod',' ':10,'Denumire',
' ':25,'Valoare');
gotoxy(10,14+k);
sir:=art.den; sir[0]:=#30;
writeln(art.cod:3,' ':10,sir,' ',
v:10:0,' lei')
end
end;
if k=0 then
begin
gotoxy(30,15);
writeln('Cod depozit eronat !',#7)
end;
readln; clrscr; gotoxy(27,5);
write('Codul depozitului (sau ^Z): ')
end;
close(f)
end.

Exerciţiul 6.6. Să se realizeze programul pentru afişarea pe monitor a producţiei


valorice anuale pentru fiecare depozit şi pe întreprindere, utilizând fişierul
Produse.dat.
Observaţii: Problema se rezolvă cu ajutorul algoritmului de consultare secvenţială
cu control după o caracteristică. Pentru obţinerea situaţiei cerute se creează un
fişier de manevră, care va conţine date privind codul depozitului şi stocul valoric
anual pentru toate produsele existente în fişierul de date. Fişierul de manevră se
sortează după câmpul depm, apoi este consultat secvenţial şi integral după această
caracteristică, obţinându-se două grade de total: unul pentru depozit şi unul pentru
întreprindere.

program consultare_cu_control_dupa_caracteristica;
uses crt;
type
artf=record
cod:byte;
den:string[30];
dep:char;
pu:longint;
cant:array[1..12] of word
end;
artm=record
depm:char;
v:real
end;
var
z:artf; x,y:artm; f:file of artf; m:file of artm;
i,j:byte; totgen,totdep:real;
vb,sf:boolean; c:char;

105
Algoritmi în programare. Aplicaţii

procedure copiere;
begin
assign(f,'produse.dat'); reset(f);
assign(m,'manevra.tmp'); rewrite(m);
with z,x do
begin
while not eof(f) do
begin
read(f,z);
v:=0;
for i:=1 to 12 do v:=v+cant[i];
v:=v*pu;
depm:=dep;
write(m,x)
end
end;
close(f)
end;
procedure sortare;
begin
repeat
vb:=false;
for i:=1 to filesize(m)-1 do
begin
seek(m,i-1); read(m,x,y);
if x.depm>y.depm then
begin
seek(m,i-1);
write(m,y,x);
vb:=true
end
end
until not vb
end;
procedure afisare;
begin
seek(m,0); sf:=false; totgen:=0; i:=0; clrscr;
gotoxy(5,3); writeln('Stocul valoric pe depozite');
gotoxy(9,6); writeln('Depozit Stoc');
read(m,x);
while not sf do
begin
totdep:=0;
c:=x.depm;
while (x.depm=c) and not sf do
begin
totdep:=totdep+x.v;
if eof(m) then sf:=true
else read(m,x)
end;

106
Algoritmi de prelucrare a fişierelor organizate secvenţial

inc(i);
gotoxy(12,7+i);
writeln(c,' ':5,totdep:10:0,' lei');
totgen:=totgen+totdep
end;
gotoxy(9,9+i);
writeln('Total = ',totgen:10:0,' lei');
close(m)
end;
{programul principal}
begin
copiere;
sortare;
afisare
end.

Exerciţiul 6.7. Să se realizeze programul pentru crearea unui tabel cu următoarele


informaţii, despre toate produsele existente în fişierul Produse.dat: cod produs,
denumire produs, preţ unitar mediu, stoc anual cantitativ şi stoc anual valoric.
Observaţii: Tabelul va fi memorat într-un fişier de tip TEXT, pentru listări
multiple şi pentru alte consideraţii (de exemplu: evitarea reluării programului în
cazul defectării imprimantei, procesarea tabelului cu un editor de texte etc.).

program afisare_integrala;
uses crt;
type
art=record
cod:byte;
den:string[30];
dep:char;
pu:longint;
cant:array[1..12] of word
end;
var
z:art;
f:file of art;
l:text;
linie:string[76];
d:string[30];
cant_tot:longint;
valoare:real;
i:byte;
begin
clrscr;
assign(f,'produse.dat'); reset(f);
assign(l,'lista.txt'); rewrite(l);
with z do begin
fillchar(linie,77,'='); linie[0]:=#76;
writeln(l,' ':25,'TABEL CU STOCURILE DE PRODUSE');

107
Algoritmi în programare. Aplicaţii

writeln(l); writeln(l); writeln(l,' ',linie);


write(l,' ║ Cod ║',' ':12,'Denumire',' ':12,'║ Pret ║');
writeln(l,' Cantitate ║ Valoare ║');
writeln(l,' ',Linie);
while not eof(f) do
begin
read(f,z);
cant_tot:=0;
for i:=1 to 12 do cant_tot:=cant_tot+cant[i];
valoare:=cant_tot*pu;
fillchar(d,31,' '); d:=den; d[0]:=#30;
write(l,' ║ ',cod:3,' ║ ',d,' ║ ',pu:8,' ║ ');
writeln(l,cant_tot:9,' ║ ',valoare:10:0,' ║');
writeln(l,' ',linie)
end
end;
close(f); close(l)
end.

108
7. Algoritmi de prelucrare a fişierelor organizate relativ

Prelucrarea fişierelor binare care necesită actualizare trebuie să asigure


posibilitatea ştergerii articolelor şi să elimine riscul de suprascriere a articolelor
adăugate. Pentru aceasta, trebuie proiectate structuri particulare de articole şi
concepute operaţii de gestiune specifice. Organizarea fişierelor care asigură
identificarea articolelor prin numărul lor relativ se numeşte organizare relativă.
Fără a epuiza multitudinea soluţiilor de rezolvare a problemelor de gestiune a
fişierelor care necesită actualizare, în continuare se prezintă câteva dintre ele. În orice
situaţie, limitările de regăsire prin acces secvenţial sau relativ a articolelor în fişier
reduc aria folosirii limbajului în problemele de gestiune. Marele inconvenient îl
constituie lipsa accesului după cheie, cel care corespunde cel mai bine gestiunii în
sistemele reale.
Pentru a simula organizarea relativă în Pascal se poate utiliza o codificare
externă a cheilor relative (numerelor relative) ale articolelor, prin utilizarea unui
nomenclator de articole, care să conţină numărul relativ al fiecăruia dintre ele.
Nomenclatorul este elaborat extern (automat sau neautomat). Orice operaţie de
regăsire în acces direct presupune introducerea din exterior a numărului relativ. La
crearea iniţială, fiecare articol este înscris la numărul său relativ predefinit. Asigurarea
ştergerii şi adăugării controlate poate fi făcută în mai multe moduri.

♦ Extinderea articolelor logice cu un indicator de stare (un octet), ajungân-


du-se la forma din figura 7.1.

Indicator de
Articol propriu-zis
stare (is)

Fig. 7.1. Structura articolului care include indicatorul de stare

Indicatorul de stare (notat is) va avea o valoare din două posibile (de exemplu
0 pentru articol inactiv - inexistent sau şters - şi 1 pentru articol prezent). Cu această
structură, operaţiile de acces la articole se realizează în următoarele condiţii: scrierea
în fişier este permisă numai pentru articolele cu is=0; citirea din fişier este permisă
numai pentru articolele cu is=1.
• Preformarea presupune deschiderea fişierului ca nou şi crearea unui număr
de articole (la limită, zero) cu is=0. Includerea operaţiei de preformare conduce la
dispariţia distincţiei dintre populare şi adăugare. Datorită faptului că fişierul se
deschide ca existent, orice operaţie de scriere a unui nou articol se tratează ca
adăugare. Într-un sistem de programe, deschiderea cu Rewrite a unui fişier se
realizează o singură dată, în procedura de preformare.
• Scrierea în acces direct presupune furnizarea numărului relativ (nr) al
articolului. În funcţie de valoarea lui nr se disting următoarele situaţii:

109
Algoritmi în programare. Aplicaţii

- dacă nr<FileSize(f), se citeşte articolul respectiv din fişier şi adăugarea este


permisă numai dacă is=0;
- dacă nr≥FileSize(f), are loc extinderea fişierului cu preformarea articolelor
cu numerele relative cuprinse în domeniul FileSize(f)..nr-1. Noul articol se scrie pe
poziţia nr.
Se remarcă faptul că scrierea în acces direct permite preformarea iniţială cu
zero articole.
• Scrierea în acces secvenţial se face fără verificare de inexistenţă. Scrierea
are loc în poziţia dată de pointerul curent. Procedura face is=1. Utilizarea ei se
recomandă numai la popularea densă.
• Citirea în acces direct presupune furnizarea numărului relativ (nr). Ea
verifică dacă is=1.
• Citirea în acces secvenţial analizează articolele începând cu cel de la
pointerul curent. Articolele cu is=0 sunt ignorate, până la întâlnirea primului articol cu
is=1 sau până se ajunge la sfârşit de fişier.
• Ştergerea se realizează în acces direct. Ea presupune citirea articolului şi
dacă ştergerea este permisă (is=1), se modifică indicatorul de stare (is=0) şi se scrie
articolul pe vechiul loc.
• Rescrierea realizează scrierea unui articol în poziţia FilePos(f)-1, dacă
vechiul articol din această poziţie are is=1.

♦ Folosirea articolului zero ca tabelă de ocupare în fişier. Fiecărui articol


din fişier îi corespunde câte un octet în primul articol: articolului cu numărul relativ i
îi corespunde octetul a[i]. Primul articol are structura a:ARRAY[1..max] OF BYTE,
unde max este o constantă care indică numărul maxim de articole pe care le poate
avea fişierul pe durata existenţei sale. Dacă articolul i este prezent, a[i]=1; dacă
articolul i este inactiv (inexistent sau şters), a[i]=0. Cu această structură, operaţiile de
acces la articole se realizează în următoarele condiţii: scrierea în fişier a articolului cu
numărul relativ i este permisă numai dacă a[i]=0; citirea din fişier a articolului cu
numărul relativ i este permisă numai dacă a[i]=1.
Ştergerea articolului i presupune verificarea existenţei sale (a[i]=1) şi realiza-
rea operaţiei a[i]=0. Adăugarea unui articol i presupune verificarea inexistenţei lui
(a[i]=0), înscrierea articolului şi realizarea operaţiei a[i]=1.
Utilizarea acestei modalităţi necesită încărcarea iniţială în memoria principală
a articolului cu numărul relativ zero. În programele care realizează ştergeri sau/şi
adăugări, înainte de închiderea fişierului trebuie reînscris articolul zero. Pentru ca
metoda să fie eficientă, articolul zero trebuie să aibă lungime cel mult egală cu
lungimea articolelor de date. Se pot concepe algoritmi prin care, pentru tabela de
ocupare în fişier, se alocă spaţiu mai mic, fiecărui articol corespunzându-i un bit, în
loc de un octet.

Exerciţiul 7.1. Să se realizeze un program multifuncţional pentru crearea şi


întreţinerea unui fişier referitor la angajaţii unei organizaţii economice, cu
următoarea structură logică de articol:

110
Algoritmi de prelucrare a fişierelor organizate relativ

Marcă Nume şi prenume Loc de Salariu


Profesie
angajat angajat muncă de bază
Word String[20] String[10] Byte Longint

Marca angajatului indică numărul relativ al articolului corespunzător în


fişier. De aceea, se poate opta pentru metoda de organizare relativă, cheia relativă
fiind marca angajatului şi se va utiliza codificarea externă prin numere relative.
Deoarece cheia relativă nu face parte din articolul memorat în fişier,
structura fizică va fi următoarea:

Indicator de Nume şi prenume Loc de Salariu


Profesie
stare (is) angajat muncă de bază
0..1 String[20] String[10] Byte Longint

Observaţii:
1. Programul oferă utilizatorului funcţiuni de Creare, Adăugare, Modificare şi
Ştergere, realizate în acces direct după cheia relativă. În meniul afişat pe ecran
există şi funcţiunea de terminare a programului.
2. Funcţiunile de Creare şi Adăugare sunt identice, cu deosebirea că pentru prima
fişierul se deschide ca nou (cu Rewrite), iar pentru cea de-a doua fişierul se
deschide ca existent (cu Reset).
3. La opţiunea de ştergere s-a inclus o confirmare suplimentară din partea
utilizatorului, pentru cazul în care cheia relativă introdusă de la tastatură există
în fişier, dar nu aparţine angajatului care se doreşte a fi şters.
4. Funcţiunea de modificare prevede posibilitatea modificării valorii oricărui
câmp sau combinaţie de câmpuri. Prin convenţie, tastarea doar a lui <ENTER>
semnifică nemodificarea câmpului respectiv.
5. Fiecare funcţiune a programului prevede posibilitatea reluării ei în interior, fără
a mai ieşi în meniul principal. Terminarea unei funcţiuni se realizează prin
tastarea caracterului CTRL/Z în câmpul marca (sfârşit standard al tastaturii).
De aceea, la revenirea în meniul principal şi la apelul unei noi funcţiuni,
tastatura (fişier TEXT standard de intrare) trebuie deschisă cu procedura
Reset(Input).

program actualizare_fisier_relativ;
uses crt;
type
art=record
is:0..1;
nume:string[20];
prof:string[10];
loc:byte;
sal:longint
end;

111
Algoritmi în programare. Aplicaţii

var
f:file of art; x:art; opt,r:char;
marca,i,err:word; aux:string[20];
procedure meniu;
begin
reset(input); clrscr;
gotoxy(30,7); write('Functiunile programului');
gotoxy(36,9); write('1. Creare');
gotoxy(36,10); write('2. Adaugare');
gotoxy(36,11); write('3. Modificare');
gotoxy(36,12); write('4. Stergere');
gotoxy(36,13); write('5. Terminare');
gotoxy(30,16); write('Functia aleasa:');
gotoxy(46,16); readln(opt)
end;
procedure citire_campuri;
begin
write('Nume si prenume: '); readln(x.nume);
write('Profesie: '); readln(x.prof);
write('Loc de munca: '); readln(x.loc);
write('Salariu: '); readln(x.sal);
x.is:=1
end;
procedure preformare;
begin
seek(f,filesize(f));
x.is:=0;
for i:=filesize(f) to marca-1 do write(f,x)
end;
procedure creare;
begin
reset(input); assign(f,'pers.dat');
if opt='1' then rewrite(f) else reset(f);
checkeof:=true; clrscr;
with x do begin
write('Marca: ');
while not eof do
begin
readln(marca);
if marca<filesize(f) then
begin
seek(f,marca); read(f,x);
if is=0 then
begin
citire_campuri;
seek(f,marca);
write(f,x)
end
else writeln('Marca alocata !')
end

112
Algoritmi de prelucrare a fişierelor organizate relativ

else begin
preformare;
citire_campuri;
write(f,x)
end;
write('Marca (sau ^Z): ')
end
end;
close(f)
end;
procedure stergere;
begin
reset(input); assign(f,'pers.dat'); reset(f);
checkeof:=true; clrscr;
with x do begin
write('Marca: ');
while not eof do
begin
readln(marca);
if marca<filesize(f) then
begin
seek(f,marca); read(f,x);
if is=1 then
begin
writeln(nume,' ',loc,' ',prof);
write('Confirmati stergerea ? (d/n): ');
readln(r);
if upcase(r)='D' then
begin
is:=0;
seek(f,marca);
write(f,x)
end
end
else writeln('Angajat inexistent in fisier !')
end
else writeln('Marca eronata !');
write('Marca (sau ^Z): ')
end
end;
close(f)
end;
procedure modif_campuri;
begin
with x do begin
write('Nume si prenume: ',nume,' '); readln(aux);
if aux<>'' then nume:=aux;
write('Profesie: ',prof,' '); readln(aux);
if length(aux)<>0 then prof:=aux;
write('Loc de munca: ',loc,' '); readln(aux);

113
Algoritmi în programare. Aplicaţii

if aux[0]<>#0 then val(aux,loc,err);


write('Salariu: ',sal,' '); readln(aux);
if aux[0]<>#0 then val(aux,sal,err);
seek(f,marca); write(f,x)
end
end;
procedure modificare;
begin
reset(input); assign(f,'pers.dat'); reset(f);
checkeof:=true; clrscr;
with x do begin
write('Marca: ');
while not eof do
begin
readln(marca);
if marca<filesize(f) then
begin
seek(f,marca); read(f,x);
if is=1 then modif_campuri
else writeln('Angajat inexistent in fisier !')
end
else writeln('Marca eronata !');
write('Marca (sau ^Z): ')
end
end;
close(f)
end;
{programul principal}
begin
meniu;
while opt<>'5' do
begin
case opt of
'1','2': creare;
'3': modificare;
'4': stergere
else begin gotoxy(25,23);
write('Functie inexistenta !',#7) end
end;
meniu
end
end.

Exerciţiul 7.2. Să se realizeze programul pentru afişarea pe monitor a informaţiilor


existente despre acei angajaţi ale căror mărci se introduc de la tastatură. Se va
utiliza fişierul creat la exerciţiul 7.1.
Observaţie: Sfârşitul introducerii de la tastatură va fi marcat standard (CTRL/Z în
câmpul marca). Programul codifică un algoritm de consultare în acces direct după
cheia relativă.

114
Algoritmi de prelucrare a fişierelor organizate relativ

program vizualizare_angajat;
uses crt;
type
art=record
is:0..1;
nume:string[20];
prof:string[10];
loc:byte;
sal:longint
end;
var
f:file of art;
x:art;
marca:word;
vb:boolean;
begin
assign(f,'pers.dat'); reset(f);
checkeof:=true; clrscr;
with x do begin
gotoxy(30,10); write('Marca: ');
while not eof do
begin
readln(marca);
if marca<filesize(f) then
begin
seek(f,marca);
read(f,x);
if is=1 then
begin
gotoxy(25,15);
writeln(nume,' ',prof,' ',loc,' ',sal)
end
else
begin
gotoxy(30,12);
writeln('Angajat inexistent!',#7)
end
end
else
begin
gotoxy(30,12);
writeln('Marca eronata !',#7)
end;
readln; clrscr; gotoxy(30,10);
write('Marca(sau ^Z): ')
end
end;
close(f)
end.

115
Algoritmi în programare. Aplicaţii

Exerciţiul 7.3. Să se realizeze programul pentru afişarea pe monitor a informaţiilor


existente (marcă, nume şi prenume, loc de muncă şi salariu) pentru acei angajaţi a
căror profesie este identică cu o valoare introdusă de la tastatură. Se va utiliza
fişierul creat la exerciţiul 7.1.
Observaţie: Programul prevede posibilitatea reluării procesului pentru o nouă
profesie, fie pentru că se doreşte un nou tabel, fie pentru că profesia introdusă a
fost eronată (nu există nici un angajat cu profesia cerută). Sfârşitul introducerii de
la tastatură va fi marcat standard (CTRL/Z în câmpul prof). Programul codifică un
algoritm de consultare în acces secvenţial cu selecţie dublă: după indicatorul de
stare şi după profesie. Pentru fiecare profesie, fişierul va fi consultat de la primul la
ultimul articol.

program vizualizare_profesie;
uses crt;
type art=record
is:0..1;
nume:string[20]; prof:string[10];
loc:byte; sal:longint
end;
var
f:file of art; x:art; prof_t:string[10]; aux:string[20];
vb,sw:boolean; i:byte;
begin
assign(f,'pers.dat'); reset(f);
checkeof:=true; clrscr; i:=0;
with x do begin
write('Profesia: ');
while not eof do
begin
readln(prof_t);
seek(f,0); sw:=true; i:=0; vb:=false;
while not eof(f) do
begin
read(f,x);
if (is=1) and (prof=prof_t) then
begin
if sw then begin {prima scriere in tabel}
gotoxy(20,10);
writeln('Marca Nume si prenume Loc Salariu');
sw:=false
end;
inc(i); gotoxy(20,12+i); fillchar(aux,21,' ');
aux:=nume; aux[0]:=#20;
writeln((filepos(f)-1):5,' ',aux,' ',loc:3,
' ',sal:7);
vb:=true
end
end;

116
Algoritmi de prelucrare a fişierelor organizate relativ

if not vb then
begin
gotoxy(30,15);
writeln('Profesie inexistenta !',#7)
end;
readln; clrscr;
write('Profesia (sau ^Z): ')
end {while}
end {with};
close(f)
end.

Exerciţiul 7.4. Să se realizeze programul pentru afişarea informaţiilor existente


despre toţi angajaţii, în ordine alfabetică a numelui şi grupaţi pe profesii. Se va
utiliza fişierul creat la exerciţiul 7.1.
Observaţii:
1. Pentru a obţine lista dorită, fişierul de date trebuie sortat după două chei. Cheia
principală este profesia, iar cheia secundară este numele şi prenumele.
2. Pentru a nu afecta organizarea relativă, sortarea se va realiza într-un fişier de
manevră, organizat secvenţial, cu memorare densă. Structura articolului asociat
manevrei este structura logică a fişierului de date. Valorile câmpului marca
sunt date de poziţia curentă a articolului în fişierul iniţial. La sfârşitul
programului, fişierul de manevră va fi şters din director.
3. Pentru a obţine lista pe mediu magnetic (pentru imprimări ulterioare), în
program se va modifica afişarea pe ecran cu scrierea într-un fişier TEXT
magnetic.

program sortare_dupa_doua_campuri;
uses crt;
type
artf=record
is:0..1;
nume:string[20];
prof:string[10];
loc:byte;
sal:longint
end;
artm=record
marca:word;
nume:string[20];
prof:string[10];
loc:byte;
sal:longint
end;
var
f:file of artf;
m:file of artm;
z:artf; x,y:artm;

117
Algoritmi în programare. Aplicaţii

n,i,j:word;
aux1:string[10];
aux2:string[20];
procedure creare_manevra;
begin
assign(f,'pers.dat');
reset(f);
assign(m,'manevra.tmp');
rewrite(m);
while not eof(f) do
begin
read(f,z);
if z.is=1 then
begin
x.marca:=filepos(f)-1;
x.nume:=z.nume;
x.prof:=z.prof;
x.loc:=z.loc;
x.sal:=z.sal;
write(m,x)
end
end;
close(f)
end;
procedure sortare_manevra;
begin
n:=filesize(m);
for i:=1 to n-1 do
begin
seek(m,i-1); read(m,x);
for j:=i+1 to n do
begin
seek(m,j-1); read(m,y);
if x.prof>y.prof then
begin
seek(m,i-1); write(m,y);
seek(m,j-1); write(m,x);
x:=y
end
else if x.prof=y.prof then
if x.nume>y.nume then
begin
seek(m,i-1); write(m,y);
seek(m,j-1); write(m,x);
x:=y
end
end
end
end;

118
Algoritmi de prelucrare a fişierelor organizate relativ

procedure listare_manevra;
begin
with x do begin
seek(m,0); i:=0;
clrscr; gotoxy(25,2);
writeln('Tabel cu angajatii pe profesii');
gotoxy(17,4);
writeln(' PROFESIE MARCA NUME SI PRENUME LOC',
' SALARIU');
while not eof(m) do
begin
read(m,x);
fillchar(aux1,11,#32); aux1:=prof; aux1[0]:=#10;
fillchar(aux2,21,#32); aux2:=nume; aux2[0]:=#20;
gotoxy(17,6+i); inc(i);
writeln(aux1,' ',marca:4,' ',aux2,
' ',loc:3,' ',sal:7)
end
end;
close(m); erase(m)
end;
{programul principal}
begin
creare_manevra;
sortare_manevra;
listare_manevra
end.

Exerciţiul 7.5. Să se realizeze programul pentru indexarea salariului tuturor


angajaţilor existenţi în fişier, cu un procent introdus de la tastatură. Se va utiliza
fişierul creat la exerciţiul 7.1.
Observaţie: Programul codifică un algoritm de modificare în acces secvenţial.

program modificare_secventiala;
uses crt;
type
art=record
is:0..1;
nume:string[20];
prof:string[10];
loc:byte;
sal:longint
end;
var
f:file of art; x:art; indice:real;
begin
assign(f,'pers.dat'); reset(f);
with x do begin
write('Indicele de crestere (%): '); readln(indice);

119
Algoritmi în programare. Aplicaţii

while not eof(f) do


begin
read(f,x);
if is=1 then
begin
sal:=trunc(sal*(1+indice/100));
seek(f,filepos(f)-1);
write(f,x)
end
end
end;
close(f)
end.

Programele din exerciţiile 7.1-7.5, care codifică algoritmi de prelucrare a


fişierelor organizate relativ, includ explicit gestionarea indicatorului de stare în
toate cazurile, fapt ce constituie un efort suplimentar din partea programatorului. În
continuare, se prezintă o unitate Pascal (relativ), în care sunt incluse o serie de
proceduri (primitive), care gestionează prelucrarea fişierelor organizate relativ,
degrevând astfel programatorul de prelucrări suplimentare. Primitivele pot fi
folosite în orice program al utilizatorului, schimbându-se doar tipul fişier şi tipul
articol. Unitatea cuprinde primitive pentru următoarele operaţii de gestiune:
preformare, scriere în acces direct, scriere în acces secvenţial, citire în acces direct,
citire în acces secvenţial, ştergere în acces direct şi rescriere.
În afara procedurii Preformare, care este o operaţie la nivel de fişier, toate
celelalte sunt operaţii de acces la articole şi presupun fişierul deschis corespunzător
(cu Reset). În unitate sunt făcute publice două tipuri: tipf, pentru tipul fişierului şi
tipa, pentru tipul articolului. Programele apelatoare lucrează numai cu câmpurile
articolului propriu-zis, gestiunea indicatorului de stare făcându-se integral în unitate.
Unitatea ar putea fi perfecţionată, astfel încât programele apelatoare să
descrie numai articolul propriu-zis, procedurile ataşând fizic octetul de stare. În felul
acesta, programele apelatoare lucrează cu un tip de articol (logic) şi procedurile
asigură conversia la/de la un alt tip de articol (fizic). Articolul fizic diferă de cel logic
prin indicatorul is.

Procedura de preformare

OpenNew(VAR f:tipf;VAR nume:STRING; n:WORD; VAR ivk:BOOLEAN)

F este fişierul, nume este identificatorul său extern, iar n este numărul relativ
al ultimului articol preformat. Ivk este indicator de eroare şi are valorile: FALSE, dacă
fişierul se poate deschide ca nou (nu există în directorul precizat, implicit sau explicit,
prin identificatorul extern) sau TRUE, dacă fişierul nu se poate deschide ca nou
(există în directorul precizat prin identificatorul extern).
Procedura deschide ca nou un fişier inexistent şi scrie articolele cu numerele
relative cuprinse în domeniul 0..n, făcând, pentru ele, is=0.

120
Algoritmi de prelucrare a fişierelor organizate relativ

Procedura de scriere în acces direct

WriteD(VAR f:tipf; VAR z:tipa; nr:WORD; VAR ivk:BOOLEAN)

F este fişierul, z este articolul care se scrie în poziţia relativă nr. Ivk este
indicator de eroare şi are valorile: FALSE, dacă articolul s-a putut scrie sau TRUE,
dacă articolul nu s-a putut scrie (este prezent în fişier). Procedura verifică inexistenţa
articolului şi realizează înscrierea lui în fişier.
Dacă nr<FileSize(f), se citeşte articolul din poziţia nr, într-o zonă z1 şi dacă
z1.is=0, se scrie articolul z în poziţia nr şi se face ivk:=FALSE, iar dacă z1.is=1 se
face ivk:=TRUE. Citirea se face în zona z1, pentru a nu se distruge articolul care este
constituit în z, pentru adăugare. Dacă nr≥FileSize(f), se preformează articolele cu
numerele relative cuprinse în intervalul FileSize(f)..nr-1, se scrie articolul z în poziţia
nr şi se face ivk:=FALSE.

Procedura de scriere în acces secvenţial

WriteS(VAR f:tipf; VAR z:tipa)

F este fişierul, iar z este zona din care se preia articolul care se scrie. Scrierea
se face fără nici o verificare. De aceea, procedura se foloseşte numai la popularea
iniţială a fişierului sau la adăugarea compactă de articole la sfârşitul lui. Pentru
articolul scris se face z.is=1. După scriere, pointerul indică următorul articol din fişier.

Procedura de citire în acces direct

ReadD(VAR f:tipf; VAR z:tipa; nr:WORD; VAR ivk:BOOLEAN)

F este fişierul, z este zona în care se transferă articolul şi nr este numărul său
relativ. Ivk este indicator de eroare şi are valorile: FALSE, dacă articolul s-a citit (este
prezent în fişier) sau TRUE, dacă articolul nu s-a citit logic (este absent din fişier).
Procedura verifică existenţa articolului şi realizează citirea lui din fişier.
Dacă nr<FileSize(f), se citeşte articolul şi dacă z.is=1, se face ivk:=FALSE,
iar dacă z.is=0, se face ivk:=TRUE. Dacă nr≥Filesize(f), se face ivk:=TRUE.

Procedura de citire în acces secvenţial

ReadS(VAR f:tipf; VAR z:tipa; VAR sf:BOOLEAN)

F este fişierul, iar z este zona în care se citeşte primul articol prezent în fişier,
începând de la pointerul curent. Sf este un indicator de semnalare a atingerii sfârşitului
de fişier şi are valorile: FALSE, dacă articolul s-a citit (şi nu este sfârşit de fişier) sau
TRUE, dacă s-a ajuns la sfârşit de fişier. Procedura citeşte secvenţial, începând de la
pointerul curent până la primul articol care are z.is=1 sau până se ajunge la sfârşit de

121
Algoritmi în programare. Aplicaţii

fişier. După citirea articolului, pointerul indică următorul articol fizic din fişier
(prezent sau nu logic).

Procedura de ştergere în acces direct

DeleteD(VAR f:tipf; nr:WORD; VAR ivk:BOOLEAN)

F este fişierul şi nr este numărul relativ al articolului care urmează să se


şteargă. Ivk este indicator de eroare şi are valorile: FALSE, dacă articolul s-a şters
(este prezent în fişier) sau TRUE, dacă articolul nu s-a şters (este absent din fişier).
Procedura realizează verificări asemănătoare procedurii ReadD. Când articolul este
prezent, se face z.is:=0 şi se rescrie în poziţia nr.

Procedura de rescriere

RewriteS(VAR f:tipf; VAR z:tipa; VAR ivk:BOOLEAN)

F este fişierul, iar z este articolul care se scrie în poziţia FilePos(f)-1. Ivk este
indicator de eroare şi are valorile: FALSE, dacă articolul se poate rescrie (articolul din
poziţia FilePos(f)-1 este prezent în fişier) sau TRUE, dacă articolul nu se poate rescrie
(articolul din poziţia FilePos(f)-1 este absent).
Procedura presupune execuţia anterioară a unei citiri (cu ReadD sau ReadS).
Ea rescrie un articol în poziţia anterioară pointerului curent, dacă acesta are câmpul
is=1 şi dacă FilePos(f)-1<FileSize(f).

unit relativ;
INTERFACE
type
tipa=record
is:byte;
np:string[20];
prof:string[10];
loc:byte;
sal:longint
end;
tipf=file of tipa;
procedure opennew(var f:tipf; var nume:string; n:word;
var ivk:boolean);
procedure writed(var f:tipf; var z:tipa; nr:word;
var ivk: boolean);
procedure writes(var f:tipf; var z:tipa);
procedure readd(var f:tipf; var z:tipa; nr:word;
var ivk:boolean);
procedure reads(var f:tipf; var z:tipa; var sf:boolean);
procedure deleted(var f:tipf; nr:word; var ivk:boolean);
procedure rewrites(var f:tipf; var z:tipa; var ivk:boolean);

122
Algoritmi de prelucrare a fişierelor organizate relativ

IMPLEMENTATION
procedure opennew;
var
i:word; z1:tipa;
begin
ivk:=false;
assign(f,nume);
{$i-} reset(f); {$i+}
if ioresult <>0 then
begin
rewrite(f);
z1.is:=0;
for i:= 0 to n do write(f,z1);
close(f)
end
else ivk:=true
end;
procedure writed;
var
z1:tipa;
i:word;
begin
ivk:=false;
if nr < filesize(f) then
begin
seek(f,nr);
read(f,z1);
if z1.is=0 then
begin
z.is:=1;
seek (f,nr);
write (f,z)
end
else
ivk:=true
end
else
begin
seek(f,filesize(f));
z1.is:=0;
for i:=filesize(f) to nr-1 do write(f,z1);
z.is:=1;
write(f,z)
end
end;
procedure writes;
begin
z.is:=1;
write(f,z)
end;

123
Algoritmi în programare. Aplicaţii

procedure readd;
begin
ivk:=false;
if nr < filesize(f) then
begin
seek(f,nr);
read(f,z);
if z.is=0 then ivk:=true
end
else
ivk:=true
end;
procedure reads;
begin
sf:=false;
repeat
{$i-} read(f,z); {$i+}
if ioresult <>0 then sf:=true
until (z.is=1) or sf
end;
procedure deleted;
var
z1: tipa;
begin
ivk:=false;
if nr < filesize(f) then
begin
seek(f,nr);
read(f,z1);
if z1.is=0
then ivk:=true
else
begin
z1.is:=0;
seek(f,nr);
write(f,z1)
end
end
else ivk:=true
end;
procedure rewrites;
var
z1:tipa;
begin
ivk:=false;
if (filepos(f)-1) < filesize(f) then
begin
seek(f,filepos(f)-1);
read(f,z1);
if z1.is=0

124
Algoritmi de prelucrare a fişierelor organizate relativ

then ivk:=true
else
begin
seek(f,filepos(f)-1);
z.is:=1;
write(f,z)
end
end
else ivk:=true
end
end.

Exerciţiul 7.6. Să se realizeze programul pentru afişarea informaţiilor existente în


fişier despre acei angajaţi ale căror coduri se introduc de la tastatură. Se va utiliza
fişierul creat la exerciţiul 7.1.
Observaţii:
1. Sfârşitul introducerii va fi marcat standard (CTRL/Z în câmpul marca).
2. Se va utiliza primitiva de citire în acces direct din unitatea relativ.

program vizualizare_persoana;
uses crt,relativ;
var
f:tipf;
x:tipa;
marca:word;
ivk:boolean;
begin
assign(f,'pers.dat'); reset(f);
checkeof:=true; clrscr;
with x do begin
gotoxy(30,10); write('Marca: ');
while not eof do
begin
readln(marca);
readD(f,x,marca,ivk);
if not ivk then begin
gotoxy(25,15);
writeln(np,' ',prof,' ',loc,' ',sal)
end
else begin
gotoxy(30,12);
writeln('Angajat inexistent!')
end;
readln; clrscr; gotoxy(30,10);
write('Marca(sau ^Z): ')
end
end;
close(f)
end.

125
Algoritmi în programare. Aplicaţii

Exerciţiul 7.7. Să se realizeze programul pentru afişarea informaţiilor existente în


fişier despre angajaţii dintr-un anumit loc de muncă, al cărui cod se introduce de la
tastatură. Se va utiliza fişierul creat la exerciţiul 7.1.
Observaţii:
1. Se va asigura posibilitatea reluării introducerii de coduri pentru mai multe locuri
de muncă. Sfârşitul introducerii va fi marcat standard (CTRL/Z în câmpul loc de
muncă).
2. Se va utiliza primitiva de citire în acces secvenţial din unitatea relativ.
3. Algoritmul codificat în program este bazat pe varianta schemei logice de
prelucrare cu fişier conducător cu o citire iniţială şi o citire curentă, la sfârşitul
modulului Prelucrare.

program vizualizare_loc_de_munca;
uses crt,relativ;
var
f:tipf; x:tipa; loc_t,i:byte; aux:string[20];
vb,sw,sf:boolean;
begin
assign(f,'pers.dat'); reset(f);
checkeof:=true; clrscr;
with x do begin
write('Loc de munca: ');
while not eof do {repetitiva dupa sfarsit de tastatura}
begin
readln(loc_t);
seek(f,0);
sw:=true; i:=0;
vb:=false;
sf:=false;
readS(f,x,sf);
while not sf do {repetitiva dupa sfarsit fisier magnetic}
begin
if (is=1) and (loc=loc_t) then begin
if sw then begin {prima scriere in tabel}
gotoxy(20,10);
writeln('Marca Nume si prenume Loc Salariu');
sw:=false
end;
{scriere rand curent in tabel}
inc(i); gotoxy(20,12+i);
fillchar(aux,21,' ');
aux:=np; aux[0]:=#20;
writeln((filepos(f)-1):5,' ',aux,' ',loc:3,
' ',sal:7);
vb:=true
end;
readS(f,x,sf)
end;

126
Algoritmi de prelucrare a fişierelor organizate relativ

if not vb then
begin
gotoxy(30,15);
writeln('Loc de munca eronat !',#7)
end {while dupa sf};
readln; clrscr; write('Loc de munca (sau ^Z): ')
end {dupa eof}
end {with};
close(f)
end.

Exerciţiul 7.8. Să se realizeze programul multifuncţional pentru realizarea operaţiilor


de creare, adăugare, modificare şi ştergere, pentru un fişier cu articole având structura
similară celui de la exerciţiul 7.1.
Observaţii: Operaţiile sunt similare exerciţiului 7.1, cu deosebirea că sunt utilizate
primitive din unitatea relativ: preformare (deschidere fişier nou), citire în acces
direct, scriere în acces direct, ştergere în acces direct, rescriere.

program actualizare_fisier_relativ;
uses crt,relativ;
var
f:tipf;
x:tipa;
opt,r:char;
ivk:boolean;
marca,i,err:word;
aux:string[20];
const
numefis:string='pers.dat';
procedure meniu;
begin
reset(input);
clrscr;
gotoxy(30,7); write('Functiile programului');
gotoxy(36,9); write('1. Creare');
gotoxy(36,10); write('2. Adaugare');
gotoxy(36,11); write('3. Modificare');
gotoxy(36,12); write('4. Stergere');
gotoxy(36,13); write('5. Terminare');
gotoxy(30,16); write('Functia aleasa:');
gotoxy(46,16);
readln(opt)
end;
procedure citire_campuri;
begin
write('Nume si prenume: ');
readln(x.np);
write('Profesie: ');
readln(x.prof);

127
Algoritmi în programare. Aplicaţii

write('Loc de munca: ');


readln(x.loc);
write('Salariu: ');
readln(x.sal)
end;
procedure creare;
begin
reset(input);
if opt='1' then openNew(f,numefis,2500,ivk)
else
begin
assign(f,'pers.dat');
reset(f)
end;
checkeof:=true;
clrscr;
with x do begin
write('Marca: ');
while not eof do
begin
readln(marca);
readD(f,x,marca,ivk);
if ivk then
begin
citire_campuri;
writeD(f,x,marca,ivk)
end
else writeln('Marca alocata altui angajat !');
write('Marca (sau ^Z): ')
end {while}
end {with};
close(f);
end;
procedure stergere;
begin
reset(input);
assign(f,'pers.dat');
reset(f);
checkeof:=true;
clrscr;
with x do begin
write('Marca: ');
while not eof do
begin
readln(marca);
readD(f,x,marca,ivk);
if not ivk then
begin
writeln(np,' ',loc,' ',prof);
write('Confirmati stergerea ? (d/n): ');

128
Algoritmi de prelucrare a fişierelor organizate relativ

readln(r);
if upcase(r)='D' then deleteD(f,marca,ivk)
end
else
writeln('Angajat inexistent in fisier !');
write('Marca (sau ^Z): ')
end {while}
end {with};
close(f);
end;
procedure modif_campuri;
begin
with x do begin
write('Nume si prenume: ',np,' ');
readln(aux);
if aux<>'' then np:=aux;
write('Profesie: ',prof,' ');
readln(aux);
if length(aux)<>0 then prof:=aux;
write('Loc de munca: ',loc,' ');
readln(aux);
if aux[0]<>#0 then val(aux,loc,err);
write('Salariu: ',sal,' ');
readln(aux);
if aux[0]<>#0 then val(aux,sal,err);
rewrites(f,x,ivk)
end
end;
procedure modificare;
begin
reset(input);
assign(f,'pers.dat');
reset(f);
checkeof:=true;
clrscr;
with x do begin
write('Marca: ');
while not eof do
begin
readln(marca);
readd(f,x,marca,ivk);
if not ivk then modif_campuri
else writeln('Angajat inexistent in fisier !');
write('Marca (sau ^Z): ')
end {while}
end {with};
close(f);
end;

129
Algoritmi în programare. Aplicaţii

{programul principal}
begin
meniu;
while opt<>'5' do
begin
case opt of
'1','2': creare;
'3' : modificare;
'4' : stergere
else
begin
gotoxy(25,23);
write('Functie inexistenta !',#7)
end
end;
meniu
end
end.

130
8. Algoritmi de prelucrare a fişierelor organizate indexat

Majoritatea aplicaţiilor de gestiune economică utilizează fişiere de date în


care articolele trebuie regăsite după valorile unui câmp de identificare, numit cheie.
Problema corespondenţei între chei şi numerele relative ale articolelor din fişierul de
date se poate rezolva prin intermediul unui fişier binar suplimentar, cu rol de tabelă de
indexuri. O astfel de organizare se numeşte indexată. Articolele fişierului tabelă de
indexuri au structura din figura 8.1.

Indicator de
Cheie Număr relativ (nr)
stare (is)
Fig. 8.1. Structura articolului din tabela de indexuri

Indicatorul de stare (is) are rol identic cu cel prezentat în capitolul referitor la
fişierele organizate relativ (capitolul 7). Cheie este un câmp în care se memorează
valoarea cheii articolului existent logic în fişierul de date, al cărui număr relativ
corespunzător este memorat în câmpul nr. Articolele tabelei de indexuri sunt, în orice
moment, sortate crescător după valorile câmpului cheie. Articolele din fişierul de date
sunt memorate aleator şi conţin câmpurile de date ale utilizatorului (pot conţine,
redundant, pentru o eventuală refacere după incidente, şi valorile cheii). O parte dintre
acestea nu-şi regăsesc corespondent în tabela de indexuri, fiind considerate şterse.
Orice operaţie de acces la articolele fişierului de date se realizează numai prin
intermediul tabelei, gestionată automat de procedurile unui unităţi specializate şi care
este netransparentă utilizatorului.

8.1. Operaţii de acces la nivel de fişier şi articol

Operaţiile de acces la nivel de fişier sunt: deschiderea şi închiderea fişierului


de date. La rândul ei, deschiderea poate fi: pentru creare (ca fişier nou) sau pentru
consultare şi întreţinere (ca fişier vechi). Procedurile realizează, pe lângă operaţiile
asupra fişierului de date şi gestionarea automată a tabelei de indexuri: formarea
numelui său extern, asignarea numelui fizic la numele logic, deschiderea ca fişier nou
sau vechi, închiderea. Operaţiile de gestiune care se pot realiza cu fişierele de date
astfel organizate sunt:
• Crearea în acces secvenţial presupune furnizarea articolelor sortate strict
crescător după valorile câmpului ales drept cheie. Articolele sunt scrise cu ajutorul
procedurii de scriere în acces secvenţial. Eroarea de cheie invalidă poate apărea la
tentativa de scriere a unui articol a cărui cheie este mai mică sau egală decât ultima
înscrisă în fişierul de date.
• Crearea în acces direct se realizează cu procedura de scriere în acces
direct, articolele fiind furnizate în orice ordine. Eroarea de cheie invalidă apare la

131
Algoritmi în programare. Aplicaţii

tentativa de scriere a unui articol a cărui cheie este egală cu una din cele prezente în
fişier.
• Consultarea în acces secvenţial presupune regăsirea articolelor în ordinea
strict crescătoare a valorilor cheii. Ea se realizează cu ajutorul procedurii de citire în
acces secvenţial, care detectează şi sfârşitul fişierului de date.
• Consultarea în acces mixt permite selectarea unui grup de articole, memo-
rate logic contiguu în fişier, selecţie realizată pe baza valorilor cheii primului şi
ultimului articol din grupul dorit. Accesul mixt presupune poziţionarea pe primul
articol prin citirea în acces direct (sau poziţionare şi citire în acces secvenţial), urmată
de exploatarea în acces secvenţial, până la găsirea cheii ultimului articol dorit, sau
până la sfârşitul fişierului.
• Adăugarea de articole se realizează utilizând procedura de scriere în acces
direct. Articolele pot fi furnizate în orice ordine a valorilor cheii. Eroarea de cheie
invalidă apare la tentativa de scriere a unui articol a cărui cheie este egală cu una deja
existentă.
• Modificarea unor câmpuri din articol se realizează în următoarele etape:
- citirea articolului de modificat (în acces secvenţial sau direct);
- modificarea, în zona articol corespunzătoare, a câmpurilor dorite, cu excep-
ţia câmpului cheie;
- rescrierea articolului, cu procedura de rescriere.
Eroarea de cheie invalidă apare în cazul tentativei de rescriere a unui articol a
cărui cheie este diferită de cea a articolului citit anterior.
• Ştergerea în acces secvenţial elimină articolul curent din fişierul de date. În
general, articolul trebuie mai întâi identificat printr-o citire (în acces secvenţial sau
direct) sau prin poziţionare. Procedura returnează eroare în cazul tentativei de ştergere
după ultimul articol existent.
• Ştergerea în acces direct elimină articolul a cărui cheie este precizată.
Operaţia nu trebuie precedată de citirea articolului şi returnează eroare în cazul
furnizării unei chei inexistente în fişier. În aplicaţii este preferabilă ştergerea în acces
secvenţial, deoarece permite (datorită citirii care o precede), vizualizarea articolului şi
luarea unei decizii în condiţii de siguranţă.
Unitatea indexate cuprinde o serie de proceduri (primitive), cu rol de
instrucţiuni de intrare/ieşire la nivel de fişier şi articol, necesare realizării algoritmilor
de prelucrare specifici operaţiilor de gestiune a fişierelor, când se utilizează
corespondenţa internă între valorile unui anumit câmp din articole - numit cheie - şi
numerele relative ale acestora. Tabela de corespondenţă între chei şi numerele relative
este memorată într-un fişier cu tip, a cărui gestiune este transferată integral
procedurilor aparţinând unităţii, astfel încât programele utilizatorului vor lucra
exclusiv cu fişierul de date. Totuşi, utilizatorul trebuie să ţină cont de existenţa tabelei
de indexuri în vederea asigurării spaţiului necesar pe disc şi manipulării concomitente
a celor două fişiere (salvare, restaurare, ştergere etc.).
În unitate sunt făcute publice următoarele tipuri: TipFis, pentru tipul
fişierului de date; TipArt, pentru tipul articolului din fişierul de date; TipCheie,
pentru tipul cheii.

132
Algoritmi de prelucrare a fişierelor organizate indexat

Procedura de deschidere a unui fişier nou

OpenNew(VAR f:TipFis; VAR nume:STRING; VAR ivk:BOOLEAN)

F este fişierul de date şi nume este identificatorul său extern. Ivk este indi-
cator de eroare, care returnează valoarea FALSE, dacă fişierul nu există sau valoarea
TRUE, dacă fişierul există deja pe disc. Procedura deschide, pentru creare, fişierul de
date (ca fişier nou). Concomitent, se deschide şi tabela de indexuri, al cărei nume
extern este identic cu al fişierului de date, dar cu extensia .IDX.
Observaţie: la deschiderea tabelei de indexuri ca fişier nou nu se verifică
existenţa acestuia în suport. Fişierul va fi şters şi recreat.

Procedura de deschidere a unui fişier existent

OpenOld(VAR f:TipFis; VAR nume:STRING; VAR ivk:BOOLEAN)

F este fişierul de date şi nume este identificatorul său extern. Ivk este indi-
cator de eroare, care returnează valoarea FALSE, dacă ambele fişiere (de date şi de
indexuri) există sau valoarea TRUE, dacă unul din ele nu există. Procedura deschide,
pentru consultare sau actualizare, ambele fişiere.

Procedura de închidere a fişierului de date

CloseFile(VAR f:TipFis)

F este fişierul de date. Procedura închide fişierul de date, precum şi tabela de


indexuri.

Procedura de citire în acces secvenţial

ReadSeqRec(VAR f:TipFis; VAR z:TipArt; VAR sf:BOOLEAN)

F este fişierul şi z este zona în care se citeşte articolul prezent în fişier. Sf este
un indicator de semnalare a atingerii sfârşitului fişierului de date şi are valorile:
FALSE, dacă articolul s-a citit (şi nu este sfârşit de fişier) sau TRUE, dacă s-a ajuns la
sfârşit de fişier.
Procedura returnează articolul curent din fişierul de date (articolul următor
ultimului accesat printr-o operaţie de intrare/ieşire). Citirea unui articol din fişierul de
date se realizează prin intermediul tabelei de indexuri. De fapt se citeşte un articol din
tabelă de la poziţia indicată de pointerul curent şi apoi se citeşte articolul cu numărul
relativ y.nr din fişierul de date (y este zona articol a tabelei de indexuri).
Dacă pointerul indică marcatorul de sfârşit al tabelei, parametrul sf va returna
valoarea TRUE. Execuţia repetată a acestei proceduri are ca efect furnizarea
articolelor din fişierul de date în ordinea strict crescătoare a valorilor cheii.

133
Algoritmi în programare. Aplicaţii

Procedura de citire în acces direct

ReadKeyRec(VAR f:TipFis; VAR z:TipArt; Key:TipCheie;


VAR ivk:BOOLEAN)

F este fişierul de date şi z este zona articol ataşată lui. Key precizează
valoarea cheii articolului care se citeşte. Ivk este indicator de eroare, care returnează
valoarea FALSE, dacă articolul a fost regăsit sau valoarea TRUE, dacă articolul este
absent. Procedura caută, prin procedura Start, cheia cu valoarea key şi dacă o
găseşte, citeşte în z articolul cu numărul relativ y.nr şi face ivk=FALSE; dacă nu o
găseşte, face ivk:=TRUE.

Procedura de scriere în acces secvenţial

WriteSeqRec(VAR f:TipFis; VAR z:TipArt; VAR ivk:BOOLEAN)

F este fişierul de date şi z este zona articol ataşată lui. Ivk este indicator de
eroare, care returnează valoarea FALSE, dacă articolul a fost scris, sau valoarea
TRUE, în caz contrar. Procedura adaugă un articol în fişierul de date, concomitent cu
extinderea tabelei de indexuri cu o nouă înregistrare, a cărei cheie este mai mare decât
cele existente. În cazul în care cheia este mai mică sau egală cu a ultimului articol din
tabelă, se returnează eroare (ivk=TRUE) şi articolul nu se scrie.

Procedura de scriere în acces direct

WriteKeyRec(VAR f:TipFis; VAR z:TipArt; Key:TipCheie;


VAR ivk:BOOLEAN)

F este fişierul de date şi z este zona articol ataşată lui. Key precizează
valoarea cheii articolului care se scrie. Ivk este indicator de eroare, care returnează
valoarea FALSE, dacă articolul a fost scris sau valoarea TRUE, în caz contrar.
Procedura adaugă un articol la sfârşitul fişierului de date. Cheia acestuia poate
avea orice valoare, inexistentă în tabela de indexuri. Iniţial, tabela se extinde cu un
nou articol şi apoi se reordonează (pentru a satisface cerinţele citirii secvenţiale). În
cazul în care cheia furnizată de apelator se regăseşte în tabelă, articolul nu se scrie şi
se returnează eroare de cheie invalidă (ivk=TRUE). Căutarea se face cu procedura
Start.

Procedura de rescriere

RewriteRec(VAR f:Tip VAR z:TipArt; VAR ivk:BOOLEAN)

F este fişierul de date şi z este zona articol ataşată lui. Ivk este indicator de
eroare, care returnează valoarea FALSE, dacă articolul a fost rescris sau valoarea
TRUE, în caz contrar.

134
Algoritmi de prelucrare a fişierelor organizate indexat

Procedura transferă datele din z în fişierul de date, în aceeaşi poziţie din care
s-a citit anterior (printr-o operaţie de citire în acces secvenţial sau direct). Tabela de
indexuri nu se modifică. Procedura verifică dacă valoarea cheii s-a modificat faţă de
momentul citirii sale precedente, caz în care se semnalează eroare de cheie invalidă
(ivk=TRUE).

Procedura de ştergere în acces secvenţial

DeleteSeqRec(VAR f:TipFis; VAR ivk:BOOLEAN)

F este fişierul de date, iar ivk este indicator de eroare, care returnează valoa-
rea FALSE, dacă articolul a fost şters sau valoarea TRUE, în caz contrar.
Procedura şterge logic articolul curent din fişierul de date. Ştergerea se reali-
zează fizic în tabela de indexuri. Iniţial se face y.is=0 şi apoi se elimină articolul din
tabelă, prin procedura de sortare. Eroarea de cheie invalidă (ivk=TRUE) este
semnalată în cazul în care pointerul curent al tabelei de indexuri indică marcatorul de
sfârşit de fişier.

Procedura de ştergere în acces direct

DeleteKeyRec(VAR f:TipFis; Key:TipCheie; VAR ivk:BOOLEAN)

F este fişierul de date şi key precizează valoarea cheii articolului care se


şterge. Ivk este indicator de eroare, care returnează valoarea FALSE, dacă articolul a
fost şters sau valoarea TRUE, în caz contrar.
Procedura şterge logic din fişierul de date articolul a cărui cheie este furnizată
ca parametru. Ştergerea se realizează fizic în tabela de indexuri, analog ştergerii în
acces secvenţial. Eroarea de cheie invalidă (ivk=TRUE) este semnalată în cazul în
care articolul respectiv nu se regăseşte în tabelă. Căutarea se face cu procedura
Start.

Procedura de poziţionare

Start(VAR f:TipFis; key:TipCheie; VAR ivk:BOOLEAN)

F este fişierul de date şi key precizează valoarea cheii articolului pe care se


face poziţionarea. Ivk este indicator de eroare, care returnează valoarea FALSE, dacă
articolul există în fişier sau valoarea TRUE, în caz contrar.
Procedura caută binar cheia cu valoarea key în tabela de indexuri şi dacă o
găseşte, face ivk=FALSE, iar dacă nu o găseşte, face ivk:=TRUE.

Observaţie: Unitatea Indexate include o procedură de sortare (Sort) care nu


este publică. Ea sortează tabela de indexuri şi elimină articolul care are y.is=0.

135
Algoritmi în programare. Aplicaţii

unit indexate;
INTERFACE
type
tipcheie= word;
tipart=record
nrm:tipcheie;
nume:string[25];
grupa:word;
nrd:1..20;
nota:array[1..20] of 0..10
end;
tipfis=file of tipart;
procedure opennew(var f:tipfis; var nume_fis:string;
var ivk:boolean);
procedure openold(var f:tipfis; var nume_fis:string;
var ivk:boolean);
procedure closefile(var f:tipfis);
procedure readseqrec(var f:tipfis; var z:tipart;
var sf:boolean);
procedure readkeyrec(var f:tipfis; var z:tipart;
key:tipcheie; var ivk:boolean);
procedure writeseqrec(var f:tipfis; var z:tipart;
var ivk:boolean);
procedure writekeyrec(var f:tipfis; var z:tipart;
key:tipcheie; var ivk:boolean);
procedure rewriterec(var f:tipfis; var z:tipart;
var ivk:boolean);
procedure deleteseqrec(var f:tipfis; var ivk:boolean);
procedure deletekeyrec(var f:tipfis; key:tipcheie;
var ivk:boolean);
procedure start(var f:tipfis; key:tipcheie; var ivk:boolean);
IMPLEMENTATION
type
tipindex=record
is:0..1;
cheie:tipcheie;
nr:word
end;
tabela=file of tipindex;
var
g:tabela;
y:tipindex;
procedure sort(var g:tabela);
var
h:tabela; a,b:tipindex; i,j:word;
begin
assign(h,'temp.dat'); rewrite(h); seek(g,0);
for i:=1 to filesize(g) do
begin
read(g,a);

136
Algoritmi de prelucrare a fişierelor organizate indexat

if a.is = 1 then write(h,a)


end;
close(g); seek(h,0);
for i:=1 to filesize(h)-1 do
begin
seek(h,i-1); read(h,a);
for j:=i+1 to filesize(h) do
begin
seek(h,j-1); read(h,b);
if a.cheie > b.cheie then
begin
seek(h,i-1); write(h,b);
seek(h,j-1); write(h,a);
a:=b
end
end
end;
rewrite(g); seek(h,0);
for i:=1 to filesize(h) do
begin
read(h,a);
write(g,a)
end;
close(h); erase(h)
end;
procedure opennew;
begin
assign(f,nume_fis); {$i-} reset(f) {$i+} ;
if ioresult <> 0 then
begin
ivk:=false; rewrite(f);
assign(g,copy(nume_fis,1,
length(nume_fis)-4)+'.idx');
rewrite(g)
end
else ivk:=true
end;
procedure openold;
begin
assign(f,nume_fis); {$i-} reset(f) {$i+} ;
if ioresult = 0 then
begin
ivk:=false;
assign(g,copy(nume_fis,1,
length(nume_fis)-4)+'.idx');
{$i-} reset(g) {$i+};
if ioresult <> 0 then ivk:=true
end
else ivk:=true
end;

137
Algoritmi în programare. Aplicaţii

procedure closefile;
begin
close(f);
close(g)
end;
procedure readseqrec;
begin
sf:=false;
{$i-} read(g,y) {$i+};
if ioresult <> 0 then sf:=true;
if not sf then
begin
seek(g,filepos(g)-1);
read(g,y);
seek(f,y.nr);
read(f,z)
end
end;
procedure readkeyrec;
begin
start(f,key,ivk);
if not ivk then
begin
seek(g,filepos(g)-1);
read(g,y);
seek(f,y.nr);
read(f,z)
end
end;
procedure writeseqrec;
begin
ivk:=false;
if filepos(g) > 0 then
begin
seek(g,filesize(g)-1);
read(g,y);
if y.cheie >= z.nrm then ivk:=true
end;
if not ivk then
begin
y.is:=1;
y.cheie:=z.nrm;
y.nr:=filesize(f);
write(g,y);
seek(f,filesize(f));
write(f,z)
end
end;

138
Algoritmi de prelucrare a fişierelor organizate indexat

procedure writekeyrec;
begin
start(f,key,ivk);
if ivk then
begin
y.is:=1; y.cheie:=z.nrm; y.nr:=filesize(f);
seek(g,filesize(g)); write(g,y);
seek(f,filesize(f)); write(f,z);
sort(g); ivk:=false
end
else ivk:=true
end;
procedure rewriterec;
begin
start(f,z.nrm,ivk);
if not ivk then
begin
seek(f,filepos(f)-1); write(f,z)
end
end;
procedure deleteseqrec;
begin
if filepos(g) <= filesize(g) then
begin
ivk:=false; seek(g,filepos(g)-1);
y.is:=0; write(g,y); sort(g)
end
else ivk:=true
end;
procedure deletekeyrec;
begin
start(f,key,ivk);
if not ivk then deleteseqrec(f,ivk)
end;
procedure start;
var
i,ld,ls:word; vb:boolean;
begin
ivk:=false; vb:=false; ls:=1; ld:=filesize(g);
while not vb and (ld>=ls) do
begin
i:=(ls+ld) div 2;
seek(g,i-1); read(g,y);
if y.cheie = key then
vb:=true
else if y.cheie < key then ls:=i+1 else ld:=i-1
end;
if not vb then ivk:=true
end;
end.

139
Algoritmi în programare. Aplicaţii

8.2. Exerciţii de prelucrare a fişierelor indexate

Exerciţiul 8.1. Să se realizeze un program pentru crearea în acces direct a unui


fişier indexat referitor la situaţia şcolară a studenţilor unei facultăţi, cu articole
având următoarea structură:

Număr Nume şi Număr Note obţinute:


Grupa
matricol prenume discipline (n) 1 2 … n
Word String[25] Word 1..20 0..10 0..10 0..10

Cheia este câmpul număr matricol. Datele se introduc de la tastatură, asigurându-se


următoarele validări:
- câmpul număr matricol: să fie numeric;
- câmpul nume şi prenume: să fie alfabetic (să fie compus numai din litere
mari, litere mici şi spaţiu);
- câmpul grupa: să fie numeric;
- câmpul număr discipline: să fie numeric;
- câmpurile note obţinute: să fie numerice.
În cazul în care valoarea introdusă nu corespunde cerinţelor impuse, se
semnalează eroare şi se reia introducerea. Sfârşitul introducerii datelor se va marca
standard (CTRL/Z în câmpul număr matricol).
Observaţie: Fişierul va fi deschis ca nou, cu primitiva OpenNew. În cazul în care
există în director un fişier cu acelaşi specificator, se semnalează eroare şi se reia
introducerea numelui de fişier. Dacă nu există, se va crea eticheta fişierului de date
cu specificatorul furnizat de către utilizator şi, concomitent, se va crea eticheta
fişierului de indexuri.
Scrierea în fişierul indexat se va realiza cu primitiva de scriere în acces
direct (WriteKeyRec). Pentru a nu citi inutil, de la tastatură, câmpurile din articol,
în cazul în care valoarea cheii există deja în tabela de indexuri (eroarea fiind
semnalată doar la sfârşitul introducerii articolului), s-a optat pentru următoarea
variantă:
- se citeşte de la tastatură valoarea cheii (numărul matricol);
- se verifică existenţa în fişier a vreunui articol cu aceeaşi valoare a cheii, cu
ajutorul primitivei de poziţionare (Start);
- dacă există un astfel de articol, se semnalează eroare şi se reia introducerea
valorii pentru cheie;
- dacă nu există articolul, se citesc de la tastatură celelalte câmpuri şi se scrie
articolul în fişier.

program creare_fisier_indexat;
uses crt,indexate;
var
art:tipart; f:tipfis; er,ivk,ivk1:boolean;
i,l:byte; s:string[100]; nume_fis:string;

140
Algoritmi de prelucrare a fişierelor organizate indexat

const
alfabet=['a'..'z','a'..'z',' '];
procedure eroare;
begin
er:=true; gotoxy(10,25);
write(s,' Tastati <enter>',#7);
repeat until readkey=#13;
gotoxy(10,25); clreol
end;
procedure citire_nrm;
begin
repeat
er:=false; gotoxy(38,5);
{$i-}; readln(art.nrm); {$i+};
if ioresult <> 0 then
begin
s:='Valoare nenumerica !';
eroare; gotoxy(38,5);
clreol
end
until not er
end;
procedure citire_nume;
begin
repeat
er:=false; gotoxy(38,6); clreol;
readln(art.nume);
l:=length(art.nume);
for i:=1 to l do
if not (art.nume[i] in alfabet) then er:=true;
if er then
begin
s:='Caractere nealfabetice !';
eroare
end
until not er
end;
procedure citire_grupa;
begin
repeat
er:=false;
gotoxy(38,7); clreol;
{$i-}; readln(art.grupa); {$i+};
if ioresult <> 0 then
begin
s:='Valoare nenumerica !';
eroare; clreol
end
until not er
end;

141
Algoritmi în programare. Aplicaţii

procedure citire_nrd;
begin
repeat
er:=false; gotoxy(38,8); clreol;
{$i-} readln(art.nrd); {$i+}
if ioresult<>0 then
begin
s:='Caractere nenumerice !';
eroare
end
until not er
end;
procedure citire_note;
begin
for i:=1 to art.nrd do
begin
gotoxy(20,i+8);
write('Nota ',i:2,' : ');
repeat
er:=false; gotoxy(38,i+8); clreol;
{$i-} readln(art.nota[i]); {$i+}
if ioresult<>0 then
begin
s:='Caractere nenumerice !';
eroare
end
until not er
end
end;
procedure inceput;
begin
textbackground(blue); textcolor(yellow); clrscr;
repeat
write('Numele fisierului: ');
readln(nume_fis);
opennew(f,nume_fis,ivk)
until not ivk;
clrscr; checkeof:=true;
gotoxy(20,5); write('Nr. matricol: ');
gotoxy(20,6); write('Nume si prenume: ');
gotoxy(20,7); write('Grupa: ');
gotoxy(20,8); write('Nr. discipline: ');
gotoxy(38,5)
end;
procedure prelucrare;
begin
citire_nrm;
start(f,art.nrm,ivk);
if ivk then
begin

142
Algoritmi de prelucrare a fişierelor organizate indexat

citire_nume; citire_grupa;
citire_nrd; citire_note;
writekeyrec(f,art,art.nrm,ivk1)
end;
if not ivk or ivk1 then
begin
s:='Articol existent !';
eroare
end;
for i:=5 to 8 do begin gotoxy(38,i); clreol end;
for i:=9 to 24 do begin gotoxy(20,i); clreol end;
gotoxy(38,5);
end;
procedure sfarsit;
begin
closefile(f);
end;
{programul principal}
begin
inceput;
while not eof do prelucrare;
sfarsit
end.

Exerciţiul 8.2. Să se realizeze programul pentru afişarea informaţiilor (nume şi


prenume, grupa şi notele obţinute) existente în fişierul indexat creat la exerciţiul
8.1, pentru studenţii ale căror numere matricol se citesc de la tastatură.
Observaţii: Fişierul se va deschide pentru consultare, ca fişier existent, cu
primitiva OpenOld. În cazul în care nu există un fişier cu specificatorul furnizat de
către utilizator, se reia introducerea specificatorului până când este citit unul valid.
Citirea articolului se va realiza în acces direct după cheia furnizată, cu ajutorul
primitivei ReadKeyRec.

program consultare_acces_direct;
uses crt,indexate;
var
x:tipart; f:tipfis; nrm,i:word;
ivk:boolean; nume_fis:string;
begin
clrscr;
repeat
write('Numele fisierului: ');
readln(nume_fis);
openold(f,nume_fis,ivk)
until not ivk;
clrscr; checkeof:=true;
with x do begin
gotoxy(10,5);

143
Algoritmi în programare. Aplicaţii

write('Numar matricol:');
while not eof do
begin
gotoxy(35,5); readln(nrm);
readkeyrec(f,x,nrm,ivk);
if not ivk then
begin
gotoxy(15,8); write(nume);
gotoxy(10,11); write('Grupa ',grupa);
gotoxy(10,13); write('Note obtinute:');
for i:=1 to nrd do
begin
gotoxy(10,14+i);
write('Nota ',i:2,': ',nota[i]:2)
end
end
else begin
gotoxy(10,10); write('Articol inexistent !',#7)
end;
readln; clrscr; gotoxy(10,5);
write('Numar matricol:')
end
end {with};
closefile(f)
end.

Exerciţiul 8.3. Să se realizeze programul pentru afişarea unor informaţii (număr


curent, număr matricol, nume şi prenume) pentru studenţii din grupele ale căror
valori se citesc de la tastatură. Fişierul indexat este cel creat la exerciţiul 8.1.
Observaţii: Programul codifică un algoritm de consultare secvenţială cu selecţie
simplă (după câmpul grupa), similar schemei generale de prelucrare cu o citire
iniţială şi o citire curentă, la sfârşitul modulului prelucrare.
Pentru fiecare nouă grupă introdusă de la tastatură, fişierul se parcurge de
la primul la ultimul articol. De aceea, de fiecare dată, fişierul de date se va deschide
(pentru consultare, cu primitiva OpenOld) înainte de prima citire şi se va închide
(cu primitiva CloseFile) după ultima citire. În cazul în care nu există un fişier cu
specificatorul furnizat de către utilizator se va semnala eroare de sistem şi se va
întrerupe execuţia programului. Citirea articolului se va realiza în acces secvenţial,
cu ajutorul primitivei ReadSeqRec.

program consultare_grupa;
uses crt,indexate;
var
x:tipart;
f:tipfis;
gr,i:word;
sf,vb,ivk:boolean;
nume_fis:string;

144
Algoritmi de prelucrare a fişierelor organizate indexat

begin
clrscr;
write('Numele fisierului: ');
readln(nume_fis);
clrscr; checkeof:=true;
with x do begin
gotoxy(10,1);
write('Grupa (sau ^Z):');
while not eof do
begin
openold(f,nume_fis,ivk);
gotoxy(27,1); readln(gr);
sf:=false; vb:=false; i:=0;
readseqrec(f,x,sf);
while not sf do
begin
if grupa=gr then
begin
inc(i); gotoxy(10,2+i);
write(i:2,'. ',nrm:4,' ',nume);
vb:=true
end;
readseqrec(f,x,sf)
end;
if not vb then begin
gotoxy(25,10);
write('Numar grupa eronat !',#7)
end;
readln; clrscr;
closefile(f);
gotoxy(10,1); write('Grupa (sau ^Z): ')
end
end {with}
end.

Exerciţiul 8.4. Să se realizeze programul pentru actualizarea fişierului referitor la


studenţi, creat la exerciţiul 8.1.
Observaţii:
1. Programul oferă utilizatorului funcţiuni de Adaugare, Modificare şi
Stergere, realizate în acces direct după cheie. În meniul afişat pe ecran există şi
funcţia de terminare a programului.
2. Funcţia de Adaugare este similară creării, cu deosebirea că verificarea
existenţei sau nonexistenţei articolului în fişier se realizează cu primitiva de citire
în acces direct ReadKeyRec.
3. Opţiunea de Stergere prevede citirea în acces direct a articolului,
afişarea acestuia pe monitor, confirmarea ştergerii şi, în caz afirmativ, ştergerea în
acces secvenţial cu primitiva DeleteSeqRec.

145
Algoritmi în programare. Aplicaţii

4. Opţiunea de Modificare prevede posibilitatea modificării valorii oricărui


câmp sau combinaţie de câmpuri. Prin convenţie, tastarea doar a lui <ENTER>
semnifică nemodificarea câmpului respectiv. Modificarea se realizează în următorii
paşi: citirea articolului în acces direct, modificarea câmpurilor dorite şi rescrierea
articolului cu primitiva RewriteRec.
5. Fiecare funcţiune a programului prevede posibilitatea reluării ei în interior,
fără a mai ieşi în meniul principal. Terminarea unei funcţiuni se realizează prin
tastarea caracterului CTRL/Z în câmpul număr matricol (sfârşit standard al
tastaturii). De aceea, la revenirea în meniul principal şi la apelul unei noi funcţiuni,
tastatura (fişier TEXT standard de intrare) trebuie deschisă cu procedura
Reset(Input).

program actualizare_fisier_indexat;
uses crt,indexate;
var
f:tipfis;
x:tipart;
t:text;
opt,r:char;
ivk:boolean;
nrm,i,err:word;
aux:string[25];
numefis:string;
procedure meniu;
begin
clrscr; reset(input);
gotoxy(30,8); write('Functiunile programului');
gotoxy(36,10); write('1. Adaugare');
gotoxy(36,11); write('2. Modificare');
gotoxy(36,12); write('3. Stergere');
gotoxy(36,13); write('4. Terminare');
gotoxy(30,16); write('Functia aleasa:');
gotoxy(46,16); readln(opt)
end;
procedure citire_campuri;
begin
write('Nume si prenume: ');
readln(x.nume);
write('Grupa: ');
readln(x.grupa);
write('Nr. discipline: ');
readln(x.nrd);
for i:=1 to x.nrd do
begin
write('Nota ',i,': ');
readln(x.nota[i])
end
end;

146
Algoritmi de prelucrare a fişierelor organizate indexat

procedure adaugare;
begin
reset(input); checkeof:=true; clrscr;
with x do begin
write('Nr. matricol: ');
while not eof do
begin
readln(nrm);
readkeyrec(f,x,nrm,ivk);
if ivk then
begin
citire_campuri;
writekeyrec(f,x,nrm,ivk)
end
else writeln('Numarul matricol exista in fisier !');
write('Nr. matricol (sau ^Z): ')
end
end
end;
procedure stergere;
begin
reset(input);
checkeof:=true; clrscr;
with x do begin
write('Nr. matricol: ');
while not eof do
begin
readln(nrm);
readkeyrec(f,x,nrm,ivk);
if not ivk then
begin
writeln(nume,' ',grupa);
write('Confirmati stergerea ? (d/n): ');
readln(r);
if upcase(r)='D' then deleteseqrec(f,ivk)
end
else writeln('Student inexistent in fisier !');
write('Nr. matricol (sau ^Z): ')
end
end
end;
procedure modif_campuri;
begin
with x do begin
write('Nume si prenume: ',nume,' '); readln(aux);
if aux<>'' then nume:=aux;
write('Grupa: ',grupa,' '); readln(aux);
if length(aux)<>0 then val(aux,grupa,err);
write('Nr. discipline: ',nrd,' '); readln(aux);
if aux[0]<>#0 then val(aux,nrd,err);

147
Algoritmi în programare. Aplicaţii

for i:=1 to nrd do


begin
write('Nota ',i,': ',nota[i],' ');
readln(aux);
if aux<>'' then val(aux,nota[i],err)
end;
rewriterec(f,x,ivk)
end
end;
procedure modificare;
begin
checkeof:=true; clrscr; reset(input);
with x do
begin
write('Nr. matricol: ');
while not eof do
begin
readln(nrm); readkeyrec(f,x,nrm,ivk);
if not ivk then modif_campuri
else writeln('Student inexistent in fisier !');
write('Nr. matricol (sau ^Z): ')
end
end;
end;
{programul principal}
begin
clrscr; assign(t,'con');
repeat
write('Numele fisierului: ');
readln(numefis);
openold(f,numefis,ivk)
until not ivk;
meniu;
while opt<>'4' do
begin
case opt of
'1': adaugare;
'2': modificare;
'3': stergere
else
begin
gotoxy(25,23);
write('Functie inexistenta !',#7)
end
end;
meniu
end
end.

148
9. Aplicaţie informatică cu prelucrare de fişiere

Capitolul prezintă un model de aplicaţie care simulează activitatea


informaţională la nivelul unei organizaţii economico-sociale de dimensiuni medii.
Din perspectivă sistemică, orice organizaţie poate fi privită ca o componentă a unui
sistem superior cum ar fi sistemul de subramură, sistemul de ramură etc.
La rândul său, privită cel puţin din perspectiva funcţiunilor manageriale ale
întreprinderii, orice organizaţie constituie un sistem format din subsisteme
corespunzătoare departamentelor aprovizionare, desfacere, financiar, contabilitate,
resurse umane, marketing etc. În direcţia eficientizării activităţii fiecărui subsistem
al organizaţiei socio-economice, conducerea are la dispoziţie cel mai performant
instrument existent astăzi pe piaţă – instrumentul informatic. În acest context,
rezolvarea unei probleme cu ajutorul calculatorului electronic este o activitate
complexă, care presupune o abordare sistematică, bazată pe o succesiune de
operaţii, pentru realizarea cărora se folosesc tehnici şi instrumente specifice.
În practica proiectării aplicaţiilor informatice se utilizează o serie de
concepte de bază:
Proiect informatic – denumire generică referitoare la realizarea sistemelor
informatice, a aplicaţiilor informatice sau a unor probleme independente.
Sistem informatic – ansamblu structurat de elemente intercorelate funcţional,
pentru automatizarea procesului de culegere şi prelucrare a datelor, în vederea
obţinerii informaţiilor pentru fundamentarea deciziilor. În general, sistemele
informatice reprezintă componente ale sistemelor informaţionale din organizaţiile
socio-economice.
Aplicaţie informatică – denumire generică pentru problemele de informatică
de dimensiuni relativ reduse, care vizează un domeniu de activitate strict delimitat.
Metodologie – în sens informatic, defineşte succesiunea etapelor de parcurs
pentru conceperea şi realizarea proiectelor informatice. O metodologie poate
cuprinde mai multe metode.
Metodă (tehnică) – o mulţime de paşi, aplicaţi într-o succesiune logică asupra
unei mulţimi de date de intrare, care conduce la obţinerea rezultatelor.
Aplicaţiile informatice acoperă o gamă largă de probleme1, ale căror
extreme pot fi caracterizate astfel:
a) existenţa unui volum relativ redus de date de intrare şi ieşire, dublată de
calcule laborioase (aplicaţii tehnico-inginereşti, care conduc la aplicaţii bazate pe
aproximări succesive, exprimate matematic prin ecuaţii algebrice şi transcendente,
sisteme de ecuaţii liniare, ecuaţii diferenţiale, integrale, adică într-o formulare
globală, aplicaţii bazate pe metode de calcul numeric).
b) existenţa unui volum mare de date de intrare şi ieşire, asociate uzual
unor calcule cu complexitate redusă (evidenţa materialelor, evidenţa personalului şi

1
Capitolul 4 – Etapele rezolvării problemelor cu calculatorul, în lucrarea Algoritmi în
programare, B. Ghilic-Micu (coord.), Ed. ASE, Bucureşti 2002, pg. 65

149
Algoritmi în programare. Aplicaţii

calculul salariilor, evidenţa mijloacelor fixe, urmărirea realizării producţiei, a


contractelor de aprovizionare/desfacere etc., adică, în general, aplicaţii de gestiune
economică). Între aceste extreme există o diversitate de aplicaţii, dintre care unele
presupun atât volume mari de date cât şi modele economico-matematice bazate pe
calcule laborioase: gestiunea stocurilor, programarea producţiei, probleme de
transport, croire, alocare a resurselor etc.
Realizarea proiectelor informatice este un proces complex, structurat în
mai multe etape, cu obiective specifice. Modul de realizare a acestor etape,
resursele implicate şi durata lor totală depind de varianta de soluţie aleasă, pe de o
parte, şi de nivelul de abordare (aplicaţie, sistem informatic, problemă), pe de altă
parte. În funcţie de complexitatea problemelor abordate în vederea rezolvării cu
calculatorul, din perspectiva programelor care vor fi elaborate, soluţiile proprii pot
conduce la una din situaţiile: sisteme de programe realizate la nivelul unor aplicaţii
informatice, abordate independent sau ca parte a unor sisteme informatice; unul sau
mai multe programe, în cazul unor probleme de dimensiuni reduse.

9.1. Etapele de realizare a proiectelor informatice

Realizarea proiectelor informatice presupune parcurgerea următoarelor


etape: formularea cerinţelor, analiza, concepţia2 şi finalizarea3. Pentru realizarea
unui proiect informatic se recomandă constituirea unei echipe de analiză-
concepţie-programare. Numărul membrilor echipei va fi stabilit în funcţie de
dimensiunea şi complexitatea proiectului, precum şi de resursele disponibile. În
acest sens, există mai multe modele de organizare a activităţii de analiză-concepţie-
programare: organizare democratică (deschisă), echipa programatorului şef (CPT –
Chief Programmer’s Team), echipa chirurgicală etc.
Organizarea democratică este cel mai simplu model de conducere a
proiectelor, în care: întreaga echipă are ca scop unic reuşita proiectului şi nu
scopuri individuale, înlăturarea erorilor şi nu ascunderea lor; definirea soluţiei de
realizare a proiectului se face în colectiv; realizarea sarcinilor se distribuie între
membrii echipei iar rolul conducător poate fi jucat de orice membru al echipei, prin
rotaţie.
Echipa programatorului şef (CPT) presupune existenţa unui număr de
programatori dintre care unul este conducător, iar procesul de realizare a
proiectelor trebuie structurat precis, pe sarcini care se vor distribui membrilor
echipei. Programatorul şef este conducătorul tehnic al întregii echipe, realizând şi
legătura cu beneficiarii produsului. De asemenea, programatorul şef trebuie să fie
un bun manager şi un bun analist-programator. Avantajul principal al acestui model
de organizare este că activitatea poate fi riguros planificată şi urmărită, atât sub
aspectul sarcinilor de executat, cât şi al resurselor şi termenelor stabilite.
2
În literatura de specialitate, etapa de concepţie se regăseşte sub numele de proiectare şi
conţine două subetape: proiectarea de ansamblu (logică) şi proiectarea de detaliu (fizică).
3
Finalizarea, conform metodologiilor existente, cuprinde fazele de testare de ansamblu,
implementare şi evaluare a produsului informatic.

150
Aplicaţie informatică cu prelucrare de fişiere

Modelul echipei chirurgicale presupune o specializare mai accentuată a


membrilor echipei de analiză-concepţie-programare. Astfel, va exista un manager
care va fi ajutat de un administrator şi un secretar, iar ceilalţi membri ai echipei vor
fi repartizaţi pe diverse sarcini: formalizarea matematică, proiectarea algoritmilor,
stabilirea instrumentelor de programare, elaborarea documentaţiei, determinarea
necesarului de hardware şi software, codificarea şi implementarea, testarea şi
depanarea programelor, crearea interfaţelor om-calculator etc.
Indiferent de modelul ales pentru organizarea activităţii echipei de analiză-
concepţie-programare, acesta trebuie să asigure controlul proiectului în sensul
atingerii obiectivelor privind calitatea produselor software, utilizarea eficientă a
resurselor alocate, încadrarea în costurile alocate şi respectarea termenelor stabilite.
Principalele etape de realizare a proiectelor informatice sunt:

1. Formularea cerinţelor pentru proiect. Realizarea unui proiect


presupune, încă de la început, formularea clară, completă şi corectă a problemei, ca
o cerinţă importantă pentru desfăşurarea cu bune rezultate a activităţii de concepţie
şi finalizare a proiectelor. Cerinţele sunt formulate de beneficiarul proiectului.
După formularea cerinţelor se va stabili echipa de analiză-concepţie-programare,
pentru fiecare membru al echipei atribuindu-se responsabilităţi în procesul de
realizare a proiectului informatic, pornind de la un model de organizare.

2. Analiza. În această fază, plecând de la formularea cerinţelor


informaţionale exprimate concret în date de ieşire, echipa de analiză-proiectare va
identifica transformările şi prelucrările necesare pentru obţinerea acestora. În
funcţie de natura aplicaţiei, se vor stabili formulele matematice şi metodele
numerice corespunzătoare. Aparatul matematic folosit va fi argumentat teoretic în
documentaţia care trebuie să însoţească proiectul informatic în forma finală. Pe
baza exprimării matematice a prelucrărilor şi transformărilor identificate în proiect
se vor stabili datele de intrare4 necesare. De asemenea, se vor pune în evidenţă
condiţiile iniţiale şi restricţiile referitoare la soluţie. La finalul fazei, membrii
echipei vor angaja discuţii în urma cărora se poate reveni pentru eventuale corectări
şi detalieri, înainte de trecerea la faza următoare.

3. Concepţia proiectului (proiectarea aplicaţiei). Pe baza datelor de


intrare/ieşire şi prelucrărilor stabilite în cadrul analizei se proiectează formatele5 de
intrare, formatele de ieşire, codurile şi algoritmii, se definesc colecţiile de date şi

4
Determinarea datelor de intrare pornind de la transformările necesare pentru obţinerea
datelor de ieşire se realizează utilizând tehnica analizei concordanţei ieşiri-intrări (intrările
sunt condiţionate de ieşiri).
5
În acest context, prin format se înţelege modul în care vor fi reprezentate extern (pe ecran
sau pe hârtie) câmpurile pentru citirea datelor de intrare şi cele pentru afişarea rezultatelor.
De asemenea, formatele de intrare/ieşire sunt parte integrantă din interfaţa aplicaţiei
informatice cu utilizatorul, în proiectarea căreia trebuie să fie luate în calcul şi elemente de
estetică şi “ergonomie vizuală” (sarcina responsabilului cu proiectarea interfeţei).

151
Algoritmi în programare. Aplicaţii

se stabilesc modulele proiectului care urmează să fie programate (structurarea


proiectului).
Formatele de intrare se vor constitui în ferestre individualizate de preluare
a datelor şi vor conţine câmpuri “dedicate”. Formatele de ieşire trebuie să fie
sugestive, să evidenţieze rezultatele (datele de ieşire) şi să ofere, eventual,
posibilităţi de imprimare. Formatele de intrare/ieşire trebuie să fie descrise şi în
documentaţia proiectului.
Proiectarea codurilor reprezintă o activitate cu implicaţii importante asupra
funcţionării produselor informatice. Codul reprezintă o combinaţie de simboluri
elementare (sau semnale), împreună cu o serie de reguli de combinare a lor,
atribuită univoc unei entităţi reale, pentru a o identifica fără nici un dubiu. Între cod
şi entitatea reală există o relaţie de asociere biunivocă. Simplificând, codurile pot fi
văzute ca “porecle unice” atribuite unor entităţi din cadrul proiectelor informatice.
Cel mai cunoscut exemplu este codul numeric personal, format din 13 caractere:
unul pentru sex, şase pentru data naşterii (an, lună, zi), cinci din registrul de
evidenţă a populaţiei şi o cifră de control. Codificarea este activitatea de stabilire a
codurilor.
Datele care stau la baza obţinerii rezultatelor (informaţiilor de ieşire) vor fi
grupate în colecţii, care vor concretiza sistemul de fişiere sau baza de date. Pot fi
identificate următoarele tipuri de colecţii de date: de bază, pentru tranzacţii,
intermediare, colecţii de date statistice, colecţii de date istorice.
Se identifică funcţiile de prelucrare, care vor fi grupate în entităţi numite
module. Pentru aceasta pot fi utilizate tehnicile de proiectare top-down şi
modularizată6. Etapa se finalizează cu elaborarea schemei de sistem, care ilustrează
modulele de prelucrare, colecţiile de date folosite şi legăturile dintre module şi
colecţii.
Proiectarea algoritmilor este o etapă complexă, care presupune analiza
riguroasă a problemei şi a formalizării ei matematice. Tehnicile top-down şi
modularizată pot fi adoptate şi în proiectarea algoritmilor. Etapa trebuie încheiată,
obligatoriu, cu testarea algoritmilor. Odată cu elaborarea algoritmilor se stabilesc
resursele de calcul necesare: echipamentele periferice, limbajele de programare
care vor fi utilizate, seturile de date care vor fi folosite la testare, necesarul de
memorie internă etc. Necesarul de resurse va trebui să fie trecut în formă explicită
în documentaţie, astfel încât să se poată realiza o exploatare ulterioară corectă a
produsului program.
Codificarea algoritmilor poate fi realizată după elaborarea algoritmilor sau
în paralel, când se lucrează în echipă. Scrierea programelor trebuie să se facă
respectând algoritmii (eventual se pot face modificări şi detalieri ale acestora)
urmărindu-se, în acelaşi timp, optimizarea utilizării resurselor calculatorului (timp
unitate centrală, memorie internă şi periferice) şi realizarea interfeţelor deja
conturate în etapele anterioare.

6
Paragraful 3.8 – Proiectarea algoritmilor, în lucrarea Algoritmi în programare, B. Ghilic-
Micu (coord.), Ed. ASE, Bucureşti 2002, pg. 60

152
Aplicaţie informatică cu prelucrare de fişiere

În documentaţia proiectului vor apărea în formă explicită detaliile legate de


limbajul de programare ales, de versiunea acestuia, de sistemul de operare sub care
poate rula produsul informatic.

4. Finalizarea proiectului. Odată realizat, proiectul este testat în ansamblu


pe baza unor seturi de date de control prestabilite. Produsele program se consideră
corecte dacă rezultatele obţinute sunt cele scontate (pentru datele de test,
programatorii trebuie să determine apriori rezultatele – valorile şi forma lor de
prezentare). Programele se testează atât independent, cât şi în corelaţie cu cele care
se execută în amonte sau în aval.
Implementarea aplicaţiei informatice presupune asigurarea exploatării sale
în condiţii reale la beneficiar, furnizorul livrând produsul “la cheie” (programe în
formă executabilă, care pot fi exploatate conform manualului de utilizare/
exploatare).

5. Evaluarea proiectelor. La baza elaborării proiectelor informatice stă


conceptul de eficienţă economică, respectiv compararea efectelor obţinute cu
cheltuielile necesare pentru funcţionarea sistemului/aplicaţiei în cauză. În acest
sens s-au formulat mai multe teorii şi concepte care privesc evaluarea eficienţei
proiectelor informatice, şi care se pot clasifica în trei grupe:
1. teorii şi metode bazate pe utilitatea proiectelor – eficienţa lor nu poate fi
pusă în discuţie cât timp acestea nu servesc cerinţelor informaţionale ale
utilizatorului final;
2. teorii şi concepte bazate pe valoarea informaţiilor furnizate prin proiectele
informatice realizate – eficienţa lor rezultă din impactul pe care îl au sistemele/
aplicaţiile respective asupra activităţii de conducere a organizaţiilor economico-
sociale;
3. teorii şi concepte pentru care eficienţa economică se poate evalua prin
contribuţia produselor informatice realizate la sporirea eficienţei activităţilor cu
caracter tehnic, de producţie, economic sau social, numărul indicatorilor utilizaţi
fiind limitat: coeficientul de satisfacere a cerinţelor informaţionale, coeficientul
timpului de răspuns, coeficientul timpului de recuperare, coeficientul economiei de
personal, coeficientul eficienţei economice, coeficientul tehnico-economic.

6. Exploatarea şi mentenanţa. După punerea la punct, produsele intră în


utilizare, fiind urmărite în vederea depistării unor erori care nu au putut fi sesizate
anterior. Această fază asigură menţinerea în funcţiune şi dezvoltarea produselor
informatice, proces care poate să continue pe tot parcursul utilizării lor şi care
poate conduce la dezvoltarea de noi versiuni, bazate pe informaţii despre
comportarea produsului la utilizatorul final.

7. Documentarea. Deşi nu este o etapă distinctă în procesul de realizare a


proiectelor informatice (documentarea se asigură în cadrul fiecărei etape parcurse),
pentru a-i sublinia importanţa şi pentru a crea reflexul întocmirii ei, o punctăm

153
Algoritmi în programare. Aplicaţii

metodologic şi separat. Documentarea corectă a proiectului informatic face posibilă


exploatarea, dezvoltarea şi adaptarea produselor, mai ales dacă fac parte dintr-un
sistem informatic, precum şi comercializarea lor către diverşi utilizatori.
Documentaţia proiectului (manuale de prezentare şi utilizare/exploatare), cuprinde:
descrierea problemei (rezultatele, datele de intrare, procesul de prelucrare,
formalizarea matematică şi modelul matematic, precizia algoritmilor etc.);
descrierea resurselor necesare şi a restricţiilor de utilizare;
schema de sistem a proiectului (organigrama modulelor);
schema tehnologică a proiectului (modul de punere în funcţiune a
modulelor);
reprezentarea algoritmilor pentru fiecare modul (schemă logică, pseudocod
etc.);
modul de apel al procedurilor/funcţiilor şi structura datelor/parametrilor
care se transferă între apelator şi apelat;
instrucţiuni de utilizare (procedura de punere în lucru, lista şi forma
întrebărilor şi răspunsurilor în conversaţia cu utilizatorii etc.);
exemple de utilizare.
Documentaţia proiectului poate fi tehnoredactată folosind instrumente
informatice specifice: editoare de texte; editoare grafice; editoare de ecuaţii etc.
Trebuie menţionată, în special pentru dezvoltările ulterioare, utilitatea
autodocumentării proiectelor, realizată sub forma unor comentarii intercalate în
programe.

Evoluţia rapidă în domeniul tehnologiei informaţiei a condus la elaborarea


de noi metodologii pentru realizarea proiectelor informatice. În cazul unui proiect
real, de mari dimensiuni (sistem informatic/produs program) este bine ca echipa de
analiză-concepţie-programare să utilizeze o metodologie de proiectare (consacrată
sau proprie). Există o multitudine de metodologii de analiză-proiectare, începând
cu cele structurate şi continuând cu metodologiile orientate obiect.
În abordarea structurată, cele mai reprezentative metodologii sunt:
SSADM (Structured Systems Analysis and Design Method – elaborată în Marea
Britanie la începutul anilor ’80), MERISE (Franţa), Yourdon&Constantine,
Jackson, SA/SD (Structured Analysis/Structured Design), HIPO (Hierarchycal
Input Proces Output) etc.
Metodologiile de analiză şi proiectare a sistemelor informatice au cunoscut
o îmbunătăţire remarcabilă datorită dezvoltării programării orientate obiect.
Analiza şi proiectarea orientate obiect reprezintă un nou mod de abordare a
problemelor, bazat pe concepte din lumea reală. Modelele orientate obiect
constituie reprezentări abstracte ale sistemelor reale.
Dintre cele mai cunoscute metodologii de analiză-proiectare orientate
obiect fac parte: OOSE (Object Oriented Software Engineering – Ivar Jacobson),
OMT (Object Modelling Technique), OOSA (Object Oriented System Analysis -
Shlaer&Mellor), OOA (Object Oriented Analysis - Coad&Yourdon) etc.

154
Aplicaţie informatică cu prelucrare de fişiere

Pentru analiza şi proiectarea aplicaţiilor informatice există o serie de


instrumente software (medii integrate de dezvoltare software), care asistă echipa de
analiză-proiectare pe tot parcursul elaborării proiectelor. Astfel de instrumente sunt
produsele CASE (Computer Aided Software Engineering), care oferă posibilităţi
grafice şi de editare, generarea de cod în diferite limbaje de programare,
autodocumentarea proiectelor, conexiuni Internet etc.

Proiectele reale nu pot fi realizate fără un suport adecvat de baze de date


sau sisteme de fişiere, deoarece presupun memorarea stării iniţiale a sistemului şi
actualizarea lui în timp. Pentru exemplificare am ales o problemă a cărei rezolvare
utilizează un sistem de fişiere binare şi text, simulând metodele de organizare
relativă şi indexată.

Formularea cerinţelor pentru proiect


Să se realizeze un proiect de aplicaţie informatică utilizând limbajul Pascal
pentru gestiunea activităţii de închiriere a autoturismelor pentru o societate
comercială din domeniu. Aplicaţia va evidenţia aspectele legate de parcul auto, de
gestiunea clienţilor, contractelor de închiriere şi a facturilor emise. De asemenea,
principalele funcţiuni ale aplicaţiei se vor regăsi în următoarele operaţii, dintre care
unele situaţii se vor obţine la cerere: înregistrări/achiziţii auto; închirieri auto;
reeşalonarea tarifelor auto; radieri auto; emiterea automată a facturilor; plata
facturilor emise şi scadente; prezentarea ofertei auto pe tipuri de autoturisme;
calculul venitului societăţii pe fiecare maşină.

Analiza
Echipa de analiză-concepţie-programare a identificat, pe baza cerinţelor
formulate în proiect, datele de ieşire şi principalele prelucrări necesare pentru
obţinerea acestor date.
Datele de ieşire:
a) facturile emise ca urmare a scadenţei contractelor de închiriere auto;
b) oferta integrală a societăţii (prezentată pe tipuri de autoturisme);
c) venitul înregistrat pe fiecare maşină din parcul auto.
Prelucrări:
a) compararea datei curente din sistem cu data scadenţei contractelor
neonorate, calculul valorii facturii emise luând în calcul numărul de
kilometri parcurşi de client de la momentul închirierii auto; de asemenea,
la calculul valorii facturate se va ţine cont de fidelitatea clientului;
b) ordonarea alfabetică a datelor despre autoturismele din parcul auto în
funcţie de tipul acestora (problemă cu control după caracteristică);
c) calculul valorii închirierilor auto pentru fiecare maşină din parcul auto.
De asemenea, au fost stabilite condiţiile iniţiale şi restricţiile referitoare la
soluţie:
- o maşină nu poate fi închiriată dacă apare într-un contract neonorat;

155
Algoritmi în programare. Aplicaţii

- unicitatea numerelor de înmatriculare auto;


- o maşină poate fi radiată dacă nu face obiectul unui contract de
închiriere neonorat;
- valoarea facturată este calculată cu o precizie de două zecimale;
- oferta auto a societăţii va fi afişată pe ecran şi va fi memorată într-un
fişier text.
Pe baza prelucrărilor, pentru obţinerea datelor de ieşire, au fost definite
următoarele date de intrare: informaţiile despre o maşină (număr auto, marca, anul
fabricaţiei, tariful la 100 km, starea, numărul de km la bord). Alte date de intrare,
care participă la obţinerea datelor de ieşire vor fi construite (introduse) interactiv şi
constau din informaţiile despre clienţi (cod, nume, adresa, număr de contracte
încheiate), contracte şi facturi.

Concepţia proiectului (proiectarea aplicaţiei)


Plecând de la analiza proiectului, în această etapă au fost definite formatele
de intrare/ieşire, s-au proiectat codurile, colecţiile de date şi modulele aplicaţiei,
precum şi algoritmii care vor fi programaţi. De asemenea, au fost elaborate schema
de sistem a proiectului şi schema tehnologică de punere în funcţiune a modulelor.
Formatele de intrare au fost proiectate pornindu-se de la datele de intrare
identificate. Pentru crearea fişierelor cu date despre parcul auto, clienţi, contracte şi
facturi, a fost realizat un program independent (creare), care realizează crearea
fără articole a fişierelor.
Pentru toate situaţiile formulate în problemă au fost proiectate formate de
ieşire care oferă posibilitatea obţinerii rezultatelor în fişiere text şi/sau pe ecran.
Fişierele rezultate vor avea nume sugestive, în funcţie de cerinţele solicitate de
utilizator, şi pot fi vizualizate în orice editor de texte. Conţinuturile fişierelor de
ieşire vor fi prezentate în documentaţia proiectului.
Corespunzător situaţiilor prezentate, au fost proiectate opt module
specializate, apelate din modulul principal al proiectului. Pe baza modulelor
proiectate, au fost definitivate schema de sistem a proiectului şi schema
tehnologică de punere în lucru a modulelor.
Activitatea de codificare vizează caracteristicile maşinilor din parcul auto,
informaţiile despre clienţi, atributele contractelor de închiriere şi informaţiile dintr-
o factură. Codificarea va ajuta şi la definirea colecţiilor de date.
Colecţiile de date externe alese sunt fişiere binare, câte unul pentru maşini,
clienţi, contracte şi facturi. Structura logică a articolelor din fiecare fişier este
descrisă în manualul de prezentare:
Algoritmii s-au realizat folosind metoda proiectării structurate, iar pentru
implementarea acestora s-a utilizat limbajul Pascal. În cadrul algoritmilor nu au
fost proiectate secvenţe de validare7. Descrierea detaliată a algoritmilor poate fi
studiată în documentaţia proiectului. De asemenea, primitivele folosite în lucrul cu

7
Pentru validare a se vedea capitolul 11 – Validarea datelor, din lucrarea Algoritmi în
programare, B. Ghilic-Micu (coord.), Ed. ASE, Bucureşti 2002, pg. 183

156
Aplicaţie informatică cu prelucrare de fişiere

fişiere relative (clienti.dat) şi fişiere indexate (auto.dat) sunt prezentate


detaliat în capitolele 7 şi 8 ale acestei lucrări).
Diferenţele faţă de unităţile relativ.tpu şi indexate.tpu constau în
structura articolelor (tabelul 9.1).

Tabelul 9.1. Diferenţe faţă de unităţile din capitolele 7 şi 8


UNIT Indexate;
INTERFACE
TYPE UNIT Relativ;
TipCheie= string[7]; INTERFACE
TipArt=RECORD TYPE
nrm:TipCheie; tipa=RECORD
is:BYTE;
marca:string[15]; nume:string[40];
an:word; adr:string[30];
tarif:real; nrc:byte;
stare:0..1; END;
nrkm:longint tipf=FILE of tipa;
end;
TipFis=FILE OF TipArt;

Finalizarea proiectului
Pentru această fază, proiectul a fost testat în ansamblu, verificându-se
astfel funcţionalitatea acestuia. Testarea s-a realizat utilizând date de test. După
testare, proiectul informatic este livrat beneficiarului, unde va fi implementat şi
pregătit pentru exploatare.

Exploatarea şi mentenanţa
Aplicaţia va fi exploatată la beneficiar, urmărindu-se comportamentul
acesteia pe parcursul utilizării.

Documentarea
Documentaţia proiectului cuprinde manualele de prezentare şi de
utilizare/exploatare. Pentru tehnoredactarea acestora a fost folosit editorul de texte
Microsoft Word 2002, editorul de ecuaţii Microsoft Equation 3.0 şi editorul grafic
Microsoft Word Picture 2002.

157
Algoritmi în programare. Aplicaţii

9.2. Dosarul de prezentare a aplicaţiei

Aplicaţia realizată permite gestiunea activităţii de închiriere a


autoturismelor pentru o societate comercială din domeniu. Aplicaţia evidenţiază
aspectele legate de parcul auto, de gestiunea clienţilor, contractelor de închiriere şi
a facturilor emise. Principalele funcţiuni ale aplicaţiei sunt următoarele:
A. înregistrări/achiziţii auto;
B. închirieri auto;
C. actualizarea tarifelor auto;
D. radieri auto;
E. emiterea automată a facturilor;
F. plata facturilor emise şi scadente;
G. prezentarea ofertei auto pe tipuri de autoturisme;
H. calculul venitului societăţii pe fiecare maşină.
Aplicaţia simulare este scrisă în Limbajul Pascal, versiunea 6.0, fiind
structurată în opt module, câte unul pentru fiecare funcţiune. Punerea în execuţie a
modulelor aplicaţiei se realizează conform schemei de sistem (figura 9.1).

funcţia 1 A

funcţia 2 B

funcţia 3 C

M en iu
principal funcţia 4 D

funcţia 5 E

funcţia 6 F

G
funcţia 7

funcţia 8 H
Fig. 9.1. Schema de sistem a proiectului

158
Aplicaţie informatică cu prelucrare de fişiere

Prelucrările aplicaţiei folosesc patru colecţiile de date externe (fişiere


binare), câte unul pentru maşini, clienţi, contracte şi facturi. Structura logică a
articolelor din fiecare fişier este:
Fişierul auto.dat, organizat indexat după cheia primară nrauto:

numărul de număr de
tipul auto, anul de tariful la starea maşinii:
Semnificaţie înmatriculare auto km la
marca fabricaţie 100 km închiriată sau nu
(cheia primară) bord
Codificare nrm marca an tarif stare nrkm
Tip string[7] string[15] word real 0..1 longint

Fişierul clienti.dat, organizat relativ după cheia relativă codclient:

codul clientului indicatorul de numele şi număr de


adresa
Semnificaţie (cheia stare a prenumele contracte
clientului
relativă) articolului clientului încheiate
Codificare codc is nume adr nrc
Tip word byte string[40] string[30] byte

Fişierul contr.dat, organizat secvenţial:

numărul starea
data număr data
numărul codul auto al contractului:
Semnificaţie încheierii de km stingerii
contractului clientului maşinii în derulare
contractului parcurşi contractului
închiriate sau stins
Codificare nrc codc nrm dataem nrkm scadenta on
Tip word word string[7] data* longint data* 0..1
* a fost definit tipul data, de forma: an (word), luna (1..12), zi (1..31).

Fişierul facturi.dat, organizat secvenţial:

numărul starea
număr
numărul numărul numele auto al valoarea facturii:
Semnificaţie de km
facturii contractului clientului maşinii facturii achitată sau
parcurşi
închiriate nu
Codificare nrf nrc nume nrm nrkm val achitat
Tip word word string[40] string[7] longint real 0..1

Pentru memorarea datelor din fişierele aplicaţiei au fost definite, ca


structuri de date interne, următoarele tipuri de articole:

TipCheie= string[7];
TipArt=record
nrm:TipCheie;
marca:string[15];
an:word;
tarif:real;
stare:0..1;
nrkm:longint
end;

159
Algoritmi în programare. Aplicaţii

tipa=record
is:BYTE;
nume:string[40];
adr:string[30];
nrc:byte;
end;
data=record
an:word;
luna:1..12;
zi:1..31
end;
contr=record
nrc:word;
codc:word;
nrm:tipcheie;
dataem:data;
nrkm:longint;
scadenta:data;
on:0..1
end;
facturi=record
nrf:word;
nrc:word;
nume:string[40];
nrm:tipcheie;
nrkm:longint;
val:real;
achitat:0..1
end;

Simultan cu crearea fişierului indexat (de date) auto.dat se creează


automat şi fişierul secvenţial auto.idx care va conţine tabela de indexuri
asociată. Structura articolului tabelei de indexuri este prezentată în capitolul 8.
Pentru fiecare modul au fost proiectate seturi de date de test, modulele
fiind testate atât individual, cât şi în inter-funcţionalitatea lor. Structura sistemului
de fişiere a fost proiectată astfel încât să simuleze funcţionarea unei baze de date
relaţionale (figura 9.2).
Pentru funcţiunea G a aplicaţiei se creează un fişier temporar de manevră
pe baza căruia se obţine oferta de maşini grupate după câmpul marca. Structura
logică a articolelor din fişierul de manevră este următoarea:

manevra=record
nrauto:string[7];
marca:string[15];
tarif:real;
nrkm:longint
end;

160
Aplicaţie informatică cu prelucrare de fişiere

OFERTA.TXT
MANEVRA.TMP

codc

AUTO.DAT CLIENTI.DAT

nume
MENIU PRINCIPAL
nrm

CONTR.DAT FACTURI.DAT
nrc

Fig. 9.2. Relaţiile dintre fişierele aplicaţiei

Descrierea algoritmilor pe funcţiuni

1. Modulul functia1 (funcţiunea A) este o operaţie de adăugare în acces


direct în fişierul indexat auto.dat. Se folosesc primitivele openold, start,
writekeyrec şi closefis din unitatea indexate. Dacă valoarea cheii primare
(nrm) introdusă de la tastatură este validă se realizează preluarea câmpurilor din
structura articolului, se setează starea pe valoarea 0 (neînchiriat) şi se scrie articolul
în fişier. Fişierul conducător este tastatura, iar în caz de cheie invalidă se
semnalează eroare.
2. Modulul functia2 (funcţiunea B) constă în mai multe operaţii:
- introducerea de la tastatură a tipului de maşină pe care doreşte să o închirieze
clientul (marca);
- căutare în acces secvenţial în fişierul indexat auto.dat utilizând primitiva
readseqrec din unitatea indexate; căutarea se face cu selecţie după două
criterii (marca şi starea);
- afişarea ofertei disponibile pentru marca căutată;
- alegerea maşinii care va face obiectul unui nou contract de închiriere (prin
introducerea de la tastatură a cheii primare corespunzătoare maşinii din oferta
afişată la pasul anterior);
- introducerea datelor despre client cu validarea cheii relative (codc) din
fişierul clienti.dat (se foloseşte primitiva writed din unitatea relativ);
- în cazul în care clientul există se realizează operaţia de modificare a
numărului de contracte de închiriere (sporul de fidelitate);

161
Algoritmi în programare. Aplicaţii

- adăugare în acces secvenţial în fişierul contr.dat după ce sunt completate


celelalte câmpuri ale articolului şi starea contractului ia valoarea 0 (contract în
derulare).
3. Modulul functia3 (funcţiunea C) realizează reeşalonarea tarifelor prin
creşterea acestora cu 10% şi constă în operaţia de modificare în acces secvenţial a
articolelor din fişierul auto.dat, utilizând primitivele readseqrec şi
rewriterec din unitatea indexate.
4. Modulul functia4 (funcţiunea D) realizează ştergerea în acces direct a
articolelor din fişierul indexat auto.idx pentru cheile primare citite de la
tastatură. Radierea unei maşini se poate face doar dacă nu există contracte
neonorate pentru maşina respectivă. Această verificare se face comparând data
curentă din sistem (citită cu procedura getdate din unitatea DOS a mediului
Pascal) cu data de scadenţă a contractelor neonorate, folosindu-se o funcţie special
construită dme.
5. Modulul functia5 (funcţiunea E) realizează adăugarea în acces
secvenţial la sfârşitul fişierului facturi.dat. O factură este emisă automat dacă
în fişierul de contracte se găseşte o înregistrare care are ca dată de scadenţă data
curentă din sistem. În momentul emiterii facturii are loc calculul valorii acesteia pe
baza numărului de kilometri parcurşi de la momentul încheierii contractului de
închiriere. În cazul în care clientul este fidel (numărul de contracte încheiate este de
cel puţin cinci), aplicaţia permite acordarea unui discount de 10%. De asemenea,
odată cu emiterea facturii se modifică în acces direct şi starea maşinii din fişierul
auto.dat.
6. Modulul functia6 (funcţiunea F) cuprinde două operaţii de
modificare: modificarea stării facturii după achitare şi modificarea stării
contractului aferent (stingerea acestuia).
7. Modulul functia7 (funcţiunea G) constituie un model de problemă cu
control după caracteristică (marca). Astfel, pe baza fişierului indexat auto.dat
se creează un fişier temporar (manevra.tmp) care este şters fizic la ieşirea din
această funcţiune. Fişierul temporar este ordonat după caracteristica de grupare
marca, obţinându-se apoi pe ecran şi în lista oferta.txt oferta de maşini.
8. Modulul functia6 (funcţiunea H) este o operaţie de consultare în
acces secvenţial a fişierului facturi.dat, după o validare prealabilă a cheii
primare nrm (introdusă de la tastatură) în fişierul indexat auto.dat. În cazul când
cheia există se realizează totalul facturilor achitate în urma stingerii contractelor de
închiriere care au avut ca obiect maşina cu numărul auto corespunzător cheii.

Instalarea produsului informatic

La instalarea produsului, beneficiarul va lansa în execuţie programul


creare.exe, care realizează crearea fişierelor aplicaţiei fără articole. Utilizatorul
va trebui să furnizeze de la tastatură numele asociate fişierelor fizice pe disc.

162
Aplicaţie informatică cu prelucrare de fişiere

Urmează punerea în execuţie a aplicaţiei simulare, în urma căreia va fi


afişat meniul principal al aplicaţiei.

Utilizatorul poate alege una din cele opt opţiuni, iar pentru fiecare opţiune
se deschide un ecran special în care sunt preluate datele de intrare şi sunt afişate
rezultatele.
Dacă este aleasă opţiunea 2 şi clientul care urmează să închirieze maşina
este nou (nu există în fişierul clienti.dat), ecranul aplicaţiei va arăta astfel:

Dacă este aleasă opţiunea 5 şi există facturi scadente la momentul apelării


opţiunii, se emite automat o factură de următoarea formă:

163
Algoritmi în programare. Aplicaţii

Pentru opţiunea 7 rezultatul este afişat pe ecran, dar va fi salvat şi într-un


fişier text numit oferta.txt.

164
Aplicaţie informatică cu prelucrare de fişiere

DOSAR DE PREZENTARE

Anexa A: fişierul sursă creare.pas

program creare;
uses crt, relativ, indexate;
type data=record
an:word;
luna:1..12;
zi:1..31
end;
contr=record
nrc:word;
codc:word;
nrm:tipcheie;
dataem:data;
nrkm:longint;
scadenta:data;
on:0..1
end;
facturi=record
nrf:word;
nrc:word;
nume:string[40];
nrm:tipcheie;
nrkm:longint;
val:real;
achitat:0..1
end;
var f:tipfis; g:tipf;
h1:file of contr; h2:file of facturi;
numef,numeg,numeh1,numeh2:string;
ivk:boolean;
begin
clrscr;
write('Numele fisierului de masini:');
readln(numef);
opennew(f,numef,ivk);
write('Numele fisierului de clienti:');
readln(numeg);
open(g,numeg,0,ivk);
write('Numele fisierului de contracte:');
readln(numeh1);
assign(h1,numeh1); rewrite(h1);
write('Numele fisierului de facturi:');
readln(numeh2);
assign(h2,numeh2); rewrite(h2);
end.

165
Algoritmi în programare. Aplicaţii

DOSAR DE PREZENTARE

Anexa B: fişierul sursă simulare.pas

program simulare;
uses dos,crt,relativ,indexate;
type data=record
an:word;
luna:word;
zi:word
end;
contr=record
nrc:word;
codc:word;
nrm:tipcheie;
dataem:data;
nrkm:longint;
scadenta:data;
on:0..1
end;
facturi=record
nrf:word;
nrc:word;
nume:string[40];
nrm:tipcheie;
nrkm:longint;
val:real;
achitat:0..1
end;
manevra=record
nrauto:string[7];
marca:string[15];
tarif:real;
nrkm:longint
end;
const numef:string='auto.dat';
numeg:string='clienti.dat';
numeh1:string='contr.dat';
numeh2:string='facturi.dat';
var f:tipfis; g:tipf; h1:file of contr; h2:file of facturi;
m:file of manevra; l:text;
a:tipart; b:tipa; c:contr; d:facturi; t,z:manevra;
ivk,sf,vb:boolean; opt:0..8; i:byte;
datas:data; codc,sapt:word; nrm_t:tipcheie;
c1,marca_t:string[15]; r:char; n:longint; tot:real;
procedure meniu;
begin
reset(input); clrscr;
gotoxy(30,7); write('Aplicatie multifunctionala RENT A CAR');
gotoxy(26,9); write('1. Achizitie auto');
gotoxy(26,10); write('2. Inchiriere auto');
gotoxy(26,11); write('3. Cresterea pretului carburantului cu 10%');
gotoxy(26,12); write('4. Radiere auto');
gotoxy(26,13); write('5. Emitere automata factura');

166
Aplicaţie informatică cu prelucrare de fişiere

gotoxy(26,14); write('6. Plata factura');


gotoxy(26,15); write('7. Oferta auto pe tipuri de masini');
gotoxy(26,16); write('8. Valoarea inchirierilor pe masina');
gotoxy(20,18); write('Functia aleasa (sau 0):');
gotoxy(46,18); readln(opt);
end;
procedure functia1;
begin
clrscr; checkeof:=true; openold(f,numef,ivk);
if ivk then writeln('Fisier inexistent!')
else begin
gotoxy(20,2);
write('Nr. de inmatriculare (exp: B92BGM) sau ^Z:');
while not eof do
begin
gotoxy(20,42);
readln(nrm_t);
for i:=1 to length(nrm_t) do nrm_t[i]:=upcase(nrm_t[i]);
start(f,nrm_t,ivk);
if not ivk then begin
gotoxy(26,18);
writeln('Nr. deja existent!');
gotoxy(26,18); readln;
clreol
end
else begin
writeln;
a.nrm:=nrm_t;
write('Marca :'); readln(a.marca);
for i:=1 to length(a.marca) do
a.marca[i]:=upcase(a.marca[i]);
write('Anul fabricatiei :'); readln(a.an);
write('Tarif la 100 km :'); readln(a.tarif);
write('Nr. km la bord :'); readln(a.nrkm);
a.stare:=0;
writekeyrec(f,a,nrm_t,ivk)
end;
writeln;
write('Nr. de inmatriculare (exp: B92BGM) sau ^Z:')
end
end;
closefile(f)
end;
procedure functia2;
begin
clrscr; checkeof:=true;
assign(h1,numeh1); reset(h1); seek(h1,filesize(h1));
assign(g,numeg); reset(g);
write('Marca sau ^Z:');
while not eof do
begin
openold(f,numef,ivk);
readln(marca_t);
for i:=1 to length(marca_t) do
marca_t[i]:=upcase(marca_t[i]);

167
Algoritmi în programare. Aplicaţii

sf:=false; vb:=false; i:=0;


readseqrec(f,a,sf);
while not sf do
begin
if (a.marca=marca_t) and (a.stare=0) then
begin
inc(i);
gotoxy(10,2+i);
write(a.nrm,' ',a.marca,
' ',a.nrkm:5,' km la bord');
vb:=true
end;
readseqrec(f,a,sf)
end;
readln;
if not vb then begin
gotoxy(26,18);
writeln('Marca de masina inexistenta sau alocata!');
gotoxy(26,18); readln;
clrscr
end
else
begin
writeln;
write('Nr. de inmatriculare din oferta:');
readln(nrm_t);
for i:=1 to length(nrm_t) do nrm_t[i]:=upcase(nrm_t[i]);
readkeyrec(f,a,nrm_t,ivk);
if ivk then writeln('Nr. de inmatriculare introdus gresit!')
else begin
a.stare:=1;
rewriterec(f,a,ivk);
closefile(f);
c.nrm:=a.nrm;
c.nrc:=filesize(h1)+1;
c.nrkm:=a.nrkm;
getdate(c.dataem.an,c.dataem.luna,c.dataem.zi,sapt);
write('Codul clientului:');
readln(codc);
readd(g,b,codc,ivk);
if ivk then begin
writeln('Client nou!');
write('Nume:'); readln(b.nume);
write('Adresa:'); readln(b.adr);
b.nrc:=1;
writed(g,b,codc,ivk)
end
else begin
b.nrc:=b.nrc+1;
writed(g,b,codc,ivk)
end;
writeln('Data scadentei contractului:');
write('Anul:'); readln(c.scadenta.an);
write('Luna:'); readln(c.scadenta.luna);
write('Ziua:'); readln(c.scadenta.zi);

168
Aplicaţie informatică cu prelucrare de fişiere

c.on:=0;
write(h1,c); clrscr
end
end;
write('Marca sau ^Z:')
end;
close(h1); close(g)
end;
procedure functia3;
begin
openold(f,numef,ivk);
clrscr; writeln('Tarifele la inchirieri auto vor creste cu 10%');
sf:=false;
readseqrec(f,a,sf);
while not sf do
begin
a.tarif:=a.tarif*1.1;
rewriterec(f,a,ivk);
readseqrec(f,a,sf)
end;
gotoxy(20,20); write('Sfarsit de operatie. Apasati ENTER'); readln;
closefile(f)
end;
function dme(var d1,d2:data):boolean;
begin
if d1.an>=d2.an then
if (d1.an=d2.an) and (d1.luna>=d2.luna) then
if (d1.an=d2.an) and (d1.luna=d2.luna) and (d1.zi>=d2.zi)
then dme:=true
else dme:=false
end;
procedure functia4;
begin
clrscr; checkeof:=true;
openold(f,numef,ivk);
write('Nr. de inmatriculare al masinii de radiat sau ^Z:');
while not eof do
begin
readln(nrm_t);
for i:=1 to length(nrm_t) do nrm_t[i]:=upcase(nrm_t[i]);
readkeyrec(f,a,nrm_t,ivk);
if ivk then begin
gotoxy(26,18);
writeln('Masina neinmatriculata sau radiata!');
gotoxy(26,18); readln; clrscr
end
else begin
if a.stare=1 then writeln('Pentru masina cu numarul ',
nrm_t,' exista contracte neonorate!')
else begin
writeln;
writeln('Nr. de inmatriculare: ',a.nrm);
writeln('Marca: ',a.marca);
writeln('Anul fabricatiei: ',a.an);
writeln('Tarif la 100 km: ',a.tarif:6:0,' USD');

169
Algoritmi în programare. Aplicaţii

writeln;
write('Confirmati radierea (d/n)?');
readln(r);
if upcase(r)='D' then deletekeyrec(f,nrm_t,ivk)
end
end;
write('Nr. inmatriculare al masinii de radiat sau ^Z:')
end;
closefile(f)
end;
procedure functia5;
begin
clrscr;
assign(h2,numeh2); reset(h2); seek(h2,filesize(h2));
assign(h1,numeh1); reset(h1);
assign(g,numeg); reset(g);
openold(f,numef,ivk);
getdate(datas.an,datas.luna,datas.zi,sapt);
while not eof(h1) do
begin
vb:=false;
read(h1,c);
if (dme(datas,c.scadenta)) and (c.on=0) then
begin
vb:=true;
d.nrf:=filesize(h2)+1;
d.nrc:=c.nrc;
readd(g,b,c.codc,ivk);
d.nume:=b.nume;
d.nrm:=c.nrm;
writeln('Factura aferenta contractului nr. ',d.nrc,
' pentru masina ',d.nrm);
repeat
write('Nr. de km: '); readln(n);
if n<c.nrkm then writeln('Km mai putini decat la '
'inchiriere!')
until n>=c.nrkm;
d.nrkm:=n;
readkeyrec(f,a,c.nrm,ivk);
d.val:=(d.nrkm-c.nrkm)*a.tarif/100;
if b.nrc>=5 then d.val:=0.9*d.val;
d.achitat:=0;
write(h2,d);
readkeyrec(f,a,d.nrm,ivk);
a.stare:=0;
rewriterec(f,a,ivk);
clrscr;
gotoxy(20,2); write('FACTURA FISCALA nr. ',d.nrf:5);
gotoxy(15,4); write('S.C. RENT A CAR S.R.L. BUCURESTI');
gotoxy(12,7); write('Contravaloarea contractului nr. ',
d.nrc:6);
gotoxy(12,8); write('Numele clientului: ',d.nume);
gotoxy(12,9); write('Nr. masinii inchiriate: ',d.nrm);
gotoxy(12,11); write('Valoare factura: ',d.val:10:2,
' USD');

170
Aplicaţie informatică cu prelucrare de fişiere

gotoxy(20,15); write('Emitent');
gotoxy(50,15); write('Beneficiar');
readln;
clrscr
end
end;
if not vb then writeln('Nu sunt contracte scadente astazi!');
readln;
closefile(f);
close(g);
close(h1);
close(h2)
end;
procedure functia6;
begin
clrscr;
assign(h2,numeh2); reset(h2);
assign(h1,numeh1); reset(h1);
openold(f,numef,ivk);
while not eof(h2) do
begin
read(h2,d);
vb:=false;
if d.achitat=0 then begin
vb:=true;
writeln('Nr. factura: ',d.nrf);
writeln('Nr. contract: ',d.nrc);
writeln('Nr. auto: ',d.nrm);
writeln('Valoare: ',d.val:10:2,' USD');
writeln;
write('Platiti factura (d/n)?');
readln(r);
if upcase(r)='D' then begin
d.achitat:=1;
seek(h2,filepos(h2)-1);
write(h2,d);
reset(h1);
while not eof(h1) do begin
read(h1,c);
if c.nrc=d.nrc then begin
c.on:=1;
seek(h1,filepos(h1)-1);
write(h1,c)
end
end
end
end
end;
if not vb then writeln('Nu exista facturi de platit!');
readln;
closefile(f);
close(h1);
close(h2)
end;

171
Algoritmi în programare. Aplicaţii

procedure functia7;
begin
openold(f,numef,ivk);
assign(m,'manevra.tmp');
rewrite(m);
readseqrec(f,a,sf);
while not sf do
begin
if a.stare=0 then
begin
t.nrauto:=a.nrm;
t.marca:=a.marca;
t.tarif:=a.tarif;
t.nrkm:=a.nrkm;
write(m,t)
end;
readseqrec(f,a,sf)
end;
closefile(f);
{sortarea dupa marca}
repeat
vb:=false;
for i:=1 to filesize(m)-1 do
begin
seek(m,i-1);
read(m,t,z);
if t.marca>z.marca then begin
seek(m,i-1);
write(m,z,t);
vb:=true
end
end
until not vb;
{obtinerea ofertei}
assign(l,'oferta.txt');
rewrite(l);
clrscr;
seek(m,0);
writeln(l,' Oferta de masini');
writeln(l,'_____________________________________');
writeln(l,'| Nr. auto | Tarif | Nr. km la bord |');
writeln(l,'_____________________________________');
writeln(' Oferta de masini');
writeln('_____________________________________');
writeln('| Nr. auto | Tarif | Nr. km la bord |');
writeln('_____________________________________');
sf:=false;
fillchar(t.nrauto,8,' ');
read(m,t);
while not sf do
begin
c1:=t.marca;
writeln(l,c1);
writeln(c1);
while (not sf) and (t.marca=c1) do

172
Aplicaţie informatică cu prelucrare de fişiere

begin
t.nrauto[0]:=#7;
writeln(l,'|',t.nrauto,' |',t.tarif:7:2,'|',
t.nrkm:16,'|');
writeln('|',t.nrauto,' |',t.tarif:7:2,'|',
t.nrkm:16,'|');
fillchar(t.nrauto,8,' ');
{$I-} read(m,t) {$I+};
if ioresult<>0 then sf:=true
end;
writeln(l,'_____________________________________');
writeln('_____________________________________')
end;
close(m);
erase(m);
close(l);
readln
end;
procedure functia8;
begin
clrscr;
checkeof:=true;
openold(f,numef,ivk);
assign(h2,numeh2);
reset(h2);
write('Nr. de inmatriculare al masinii sau ^Z:');
while not eof do
begin
readln(nrm_t);
for i:=1 to length(nrm_t) do nrm_t[i]:=upcase(nrm_t[i]);
start(f,nrm_t,ivk);
if ivk then begin
gotoxy(26,18);
writeln('Masina neinmatriculata sau radiata!');
gotoxy(26,18);
readln; clrscr
end
else begin
seek(h2,0);
tot:=0;
while not eof(h2) do
begin
read(h2,d);
if (d.nrm=nrm_t) and (d.achitat=1) then
tot:=tot+d.val
end;
writeln('Masina ',nrm_t:7,' a inregistrat o valoare a'+
' inchirierilor de ',tot:7:2,' USD');
readln
end;
write('Nr. de inmatriculare sau ^Z:')
end;
closefile(f);
close(h2)
end;

173
Algoritmi în programare. Aplicaţii

{programul principal}
begin
meniu;
while opt<>0 do begin
case opt of
1: functia1;
2: functia2;
3: functia3;
4: functia4;
5: functia5;
6: functia6;
7: functia7;
8: functia8
end;
meniu
end
end.

9.3. Dosarul de utilizare/exploatare a aplicaţiei

Pentru exploatarea corectă a produsului informatic proiectat, beneficiarul


trebuie să asigure un minim de resurse hardware şi software, care constă în:
- calculator IBM-PC sau compatibil;
- microprocesor 80386, frecvenţa de 166 MHz;
- memorie RAM 16 Mb;
- monitor VGA;
- sistem de operare MS-DOS, versiunea 6.2;
- limbajul de programare Pascal, versiunea 6.0;
- un editor de texte.

Etape în utilizarea produsului simulare:

1. Lansarea în execuţie a aplicaţiei creare.exe, pentru crearea, fără


articole, a fişierelor referitoare la parcul auto (auto.dat şi auto.idx), la clienţi
(clienti.dat), la contracte (contr.dat) şi la facturi (facturi.dat).
2. Lansarea în execuţie a aplicaţiei simulare.exe, care execută următorii
paşi:
2.1. afişează meniul principal;
2.2. execută funcţiunile din meniul principal dacă pasul 1 s-a
realizat corect (în soluţia adoptată, numele fişierelor sunt stabilite în aplicaţia
simulare în secţiunea const).
3. Utilizatorul va solicita execuţia uneia din opţiunile meniului.
4. După execuţia fiecărei opţiuni, simulare revine în meniul principal.
5. Terminarea execuţiei se poate realiza prin alegerea opţiunii 0 din meniu.

174
BIBLIOGRAFIE

Ghilic-Micu B., Roşca Gh. Ion, Apostol C., Stoica M., Cocianu C.,
Algoritmi în programare, Ed. ASE, Bucureşti, 2002, ISBN 973-594-168-6

Roşca Gh.I., Ghilic-Micu B., Stoica M., Algoritmi şi programe de


prelucrare a fişierelor, Ed. ASE, Bucureşti, 2001, ISBN 973-9462-36-7

Roşca Gh.I., Ghilic-Micu B., Apostol C., Stoica M., Cocianu C., Uscatu
C., Bazele elaborării programelor. Exerciţii rezolvate şi propuse, Ed.
ASE, Bucureşti, 1999, ISBN 973-98468-5-5

Walter Savitch, Turbo Pascal: An Introduction to the Art and Science of


Programming, 4th Edition, Benjamin & Cummings, ISBN 0-8053-0418-5

Stephen O'Brien, Turbo Pascal 6: The Complete Reference, Osborne &


McGraw-Hill, ISBN 0-07-881703-X

Jeremy G. Soybel, Building Turbo Pascal Libraries, Data Entry Tools,


Tab Books, ISBN 0-8306-7734-8

Keith Weiskamp, Turbo Pascal Self-Teaching Guide, John Wiley & Sons
Inc., ISBN 0-471-54492-2

175