Sunteți pe pagina 1din 20

Algoritmi şi programe de prelucrare a fişierelor

6. 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 probleme 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 relativ 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 diverse moduri:
♦ Extinderea articolelor logice cu un indicator de stare (un octet), ajungându-se la forma din
figura 6.1.

Indicator Articol propriu-zis


de stare (is)

Fig. 6.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 -, 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:
- dacă nr<FileSize(f), se citeşte articolul respectiv din fişier şi adăugarea este permisă numai
dacă is=0;
- dacă nr>=FileSize(f), are loc extinderea fişierului cu preformarea articolelor cu numerele
relative cuprinse în domeniul FileSize(f)..nr-1. Noul articol se scrie pe poziţia nr.
Se remarcă faptul că scrierea în acces direct permite preformarea iniţială cu zero articole.
• Scrierea în acces secvenţial se face fără verificare de inexistenţă. Scrierea are loc în poziţia
dată de pointerul curent. Procedura face is=1. Utilizarea ei se recomandă numai la popularea densă.
• Citirea în acces direct presupune furnizarea numărului relativ (nr). Ea verifică dacă is=1.
• Citirea în acces secvenţial analizează articolele începând cu cel de la pointerul curent. Artico-
lele cu is=0 sunt ignorate, până la întâlnirea primului articol cu is=1 sau până se ajunge la sfârşit de
fişier.
• Ştergerea se realizează în acces direct. Ea presupune citirea articolului şi dacă ştergerea este
permisă (is=1), se modifică indicatorul de stare (is=0) şi se scrie articolul pe vechiul loc.
Algoritmi şi programe de prelucrare a fişierelor
• Rescrierea realizează scrierea unui articol în poziţia FilePos(f)-1, dacă vechiul articol din
această poziţie are is=1.
♦ Folosirea articolului zero ca tabelă de ocupare în fişier. Fiecărui articol din fişier îi cores-
punde câte un octet în primul articol: articolului cu numărul relativ i îi corespunde octetul a[i]. Primul
articol are structura a:ARRAY[1..max] OF BYTE, unde max este o constantă care indică numărul
maxim de articole pe care le poate avea fişierul pe durata existenţei sale. Dacă articolul i este prezent,
a[i]=1; dacă articolul i este inactiv (inexistent sau şters), a[i]=0.
Cu această structură, operaţiile de acces la articole se realizează în următoarele condiţii:
scrierea în fişier a articolului cu numărul relativ i este permisă numai dacă a[i]=0; citirea din fişier a
articolului cu numărul relativ i este permisă numai dacă a[i]=1.
Ştergerea articolului i presupune verificarea existenţei sale (a[i]=1) şi realizarea operaţiei
a[i]=0. Adăugarea unui articol i presupune verificarea inexistenţei lui (a[i]=0), înscrierea articolului şi
realizarea operaţiei a[i]=1.
Utilizarea acestei modalităţi necesită încărcarea iniţială în memoria principală a articolului cu
numărul relativ zero. În programele care realizează ştergeri sau/şi adăugări, înainte de închiderea
fişierului trebuie reînscris articolul zero. Pentru ca metoda să fie eficientă, articolul zero trebuie să aibă
lungime cel mult egală cu lungimea articolelor de date. Se pot concepe algoritmi prin care, pentru
tabela de ocupare în fişier, se alocă spaţiu mai mic, fiecărui articol corespunzându-i un bit, în loc de un
octet.

Exerciţiul 1: Să se realizeze un program multifuncţional pentru crearea şi întreţinerea unui fişier


referitor la angajaţii unei organizaţii economice, cu următoarea structură logică de articol:

Marcă Nume şi prenume Profesie Loc de Salariu


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

Marca angajatului indică numărul relativ al articolului corespunzător în fişier. De aceea, se


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

Indicator de Nume şi Profesie Loc de Salariu


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

Observaţii:
1. Programul oferă utilizatorului funcţiuni de Creare, Adăugare, Modificare şi Ştergere, realizate
în acces direct după cheia relativă. În meniul afişat pe ecran există şi funcţiunea de terminare a
programului.
2. Funcţiunile de Creare şi Adăugare sunt identice, cu deosebirea că pentru prima fişierul se
deschide ca nou (cu Rewrite), iar pentru cea de-a doua fişierul se deschide ca existent (cu
Reset).
3. La opţiunea de ştergere s-a inclus o confirmare suplimentară din partea utilizatorului, pentru
cazul în care cheia relativă introdusă de la tastatură există în fişier, dar nu aparţine angajatului
care se doreşte a fi şters.
4. Funcţiunea de modificare prevede posibilitatea modificării valorii oricărui câmp sau combinaţie
de câmpuri. Prin convenţie, tastarea doar 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
Algoritmi şi programe de prelucrare a fişierelor
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;
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
Algoritmi şi programe de prelucrare a fişierelor
write('Marca: ');
while not eof do
begin
readln(marca);
if marca<filesize(f) then
begin
seek(f,marca); read(f,x);
if is=0 then
begin
citire_campuri;
seek(f,marca);
write(f,x)
end
else writeln('Marca alocata altui angajat !')
end
else begin
preformare;
citire_campuri;
write(f,x)
end;
write('Marca (sau ^Z): ')
end;
end;
close(f);
end;
procedure stergere;
begin
reset(input); assign(f,'pers.dat'); reset(f);
checkeof:=true; clrscr;
with x do begin
write('Marca: ');
while not eof do
begin
readln(marca);
if marca<filesize(f) then
begin
seek(f,marca); read(f,x);
if is=1 then
begin
writeln(nume,' ',loc,' ',prof);
write('Confirmati stergerea ? (d/n): ');
readln(r);
if upcase(r)='D' then
begin
is:=0;
seek(f,marca);
write(f,x)
end
end
else writeln('Angajat inexistent in fisier !')
end
else writeln('Marca eronata !');
Algoritmi şi programe de prelucrare a fişierelor
write('Marca (sau ^Z): ')
end;
end;
close(f);
end;
procedure modif_campuri;
begin
with x do begin
write('Nume si prenume: ',nume,' '); readln(aux);
if aux<>'' then nume:=aux;
write('Profesie: ',prof,' '); readln(aux);
if length(aux)<>0 then prof:=aux;
write('Loc de munca: ',loc,' '); readln(aux);
if aux[0]<>#0 then val(aux,loc,err);
write('Salariu: ',sal,' '); readln(aux);
if aux[0]<>#0 then val(aux,sal,err);
seek(f,marca); write(f,x)
end
end;
procedure modificare;
begin
reset(input); assign(f,'pers.dat'); reset(f);
checkeof:=true; clrscr;
with x do begin
write('Marca: ');
while not eof do
begin
readln(marca);
if marca<filesize(f) then
begin
seek(f,marca); read(f,x);
if is=1 then modif_campuri
else writeln('Angajat inexistent in fisier !')
end
else writeln('Marca eronata !');
write('Marca (sau ^Z): ')
end;
end;
close(f);
end;

{***** Program 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
Algoritmi şi programe de prelucrare a fişierelor
end;
meniu
end
end.

Exerciţiul 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 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ă.

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

Exerciţiul 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 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
profesie). 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;
sw:=true; 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
Algoritmi şi programe de prelucrare a fişierelor
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;
if not vb then
begin
gotoxy(30,15);
writeln('Profesie inexistenta !',#7)
end;
readln; clrscr; write('Profesia (sau ^Z): ')
end
end;
close(f)
end.

Exerciţiul 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 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 modica
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;
Algoritmi şi programe de prelucrare a fişierelor
m:file of artm;
z:artf; x,y:artm;
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;
procedure listare_manevra;
begin
with x do begin
Algoritmi şi programe de prelucrare a fişierelor
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;
begin
creare_manevra;
sortare_manevra;
listare_manevra
end.

Exerciţiul 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 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);
while not eof(f) do
begin
read(f,x);
if is=1 then
begin
sal:=trunc(sal*(1+indice/100));

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