Baze De Date Oracle. Limbajul Sql

  • Uploaded by: Cătălin
  • 0
  • 0
  • April 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Baze De Date Oracle. Limbajul Sql as PDF for free.

More details

  • Words: 34,389
  • Pages: 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

i =1

Ş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

se calculează astfel:

i = 1, k

! 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 n

m (m*lna)/n , a > 0 , pentru determinarea căreia există funcţiile standard EXP(x) a =e

ş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  . Procesul de căutare se opreşte când valoarea căutată  2 

determină astfel: i = 

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: = max(x1,x2); MAX1 MAX2 = max(MAX1,x3); MAX3 = max(MAX2,x4); ... = max(MAXn-2,xn); MAXn-1 --------------------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

S=a11+a12+...+a1n+a21+...+a2n+...+am1+...+amn=

n

∑ ∑ a(i, j) ,

dacă se însumează pe

i =1 j=1

linii (lexicografic) sau n

S=a11+a21+...+am1+a12+...+am2+...+a1n+...+amn=

m

∑ ∑ a(i, j) ,

dacă se însumează pe

j =1 i =1

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 dreptunghiulară, de dimensiuni mΗn.

   Fie matricea A=    

a 11 a 12 ... a1n   a 21 a 22 ... a 2n  . 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.

   Fie matricea A =    

a 11 a 12 ... a1n   a 21 a 22 ... a 2n  . Î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.

   Fie matricea A =    

a 11 a 12 . . . a 1n   a 21 a 22 . . . a 2n  . . . . . . . . . . . . . . . . .   a m1 a m 2 . . . a mn 

→ MAX1 → MAX 2 .......... → MAX m

. Elementele maxime de pe fiecare

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

end.

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

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

i =1

i =1

real. Deoarece min (xi ) = − max( − xi ) se construieste o functie (maxim) interna

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

Media aritmetica ponderata: x =

∑ x i ⋅ fi i =1

n

∑fi i =1

n

, dispersia: s = 2

∑ (x

i

− x )2 ⋅ f i

i =1

n

∑ fi

si

i =1

abaterea medie patrata: s = s . Semnificatia parametrilor formali este 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) . 2

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]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]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 x0) 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]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
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
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ă dezavantajul 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 factură String[10]

Data emiterii lună zi 1..12 1..31

Denumire beneficiar

Cod fiscal

Valoare facturată

TVA facturat

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ă î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 prelucră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.

Facturi.dat

CONSULTARE 1

2

Tabel.txt

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

Denumire produs

Cod depozit

Preţ unitar mediu

byte

String[30]

char

longint

Cantitate lunară 1 word

2 word



12 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ă î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ându-se la forma din figura 7.1. Indicator de stare (is)

Articol propriu-zis

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
110

Algoritmi de prelucrare a fişierelor organizate relativ

Marcă angajat Word

Nume şi prenume angajat String[20]

Profesie String[10]

Loc de muncă Byte

Salariu de bază 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 stare (is) 0..1

Nume şi prenume angajat String[20]

Profesie String[10]

Loc de muncă Byte

Salariu de bază 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
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'' 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'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
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
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
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
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, memorate 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 indicator 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 indicator 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ă valoarea FALSE, dacă articolul a fost şters sau valoarea TRUE, în caz contrar. Procedura şterge logic articolul curent din fişierul de date. Ştergerea se realizează 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 matricol

Nume şi prenume

Grupa

Număr discipline (n)

Word

String[25]

Word

1..20

Note obţinute: 1 2 … n 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

end.

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)

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ţieprogramare: 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. GhilicMicu (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 economicosociale; 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 dintro 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 TipCheie= string[7]; TipArt=RECORD nrm:TipCheie; marca:string[15]; an:word; tarif:real; stare:0..1; nrkm:longint end; TipFis=FILE OF TipArt;

UNIT Relativ; INTERFACE TYPE tipa=RECORD is:BYTE; nume:string[40]; adr:string[30]; nrc:byte; END; tipf=FILE of tipa;

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

M en iu principal

funcţia 1

A

funcţia 2

B

funcţia 3

C

funcţia 4

D

funcţia 5

E

funcţia 6

F

funcţia 7

G G

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 înmatriculare auto (cheia primară) nrm string[7]

Semnificaţie Codificare Tip

tipul auto, marca

anul de fabricaţie

tariful la 100 km

starea maşinii: închiriată sau nu

marca string[15]

an word

tarif real

stare 0..1

număr de km la bord nrkm longint

Fişierul clienti.dat, organizat relativ după cheia relativă codclient: Semnificaţie Codificare Tip

codul clientului (cheia relativă) codc word

indicatorul de stare a articolului is byte

numele şi prenumele clientului nume string[40]

număr de contracte încheiate nrc byte

adresa clientului adr string[30]

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

numărul contractului

codul clientului

Codificare Tip

nrc word

codc word

numărul auto al maşinii închiriate nrm string[7]

data încheierii contractului

număr de km parcurşi

data stingerii contractului

dataem data*

nrkm longint

scadenta data*

starea contractului: în derulare sau stins on 0..1

* a fost definit tipul data, de forma: an (word), luna (1..12), zi (1..31). Fişierul facturi.dat, organizat secvenţial: Semnificaţie

numărul facturii

numărul contractului

numele clientului

Codificare Tip

nrf word

nrc word

nume string[40]

numărul auto al maşinii închiriate nrm string[7]

număr de km parcurşi

valoarea facturii

nrkm longint

val real

starea facturii: achitată sau nu achitat 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

end; contr=record

an:word; luna:1..12; zi:1..31 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

nrc

FACTURI.DAT

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

Related Documents

Baze De Date Oracle
November 2019 15
Baze De Date
December 2019 17
Baze De Date
June 2020 12
Excel5-baze De Date
May 2020 9
Baze De Date Access
April 2020 4