8 PDF

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

Sunteți pe pagina 1din 22

7.

Algoritmi de prelucrare a fişierelor organizate relativ

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


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

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


du-se la forma din figura 7.1.

Indicator de
Articol propriu-zis
stare (is)

Fig. 7.1. Structura articolului care include indicatorul de stare

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

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


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

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


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

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


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

Marcă Nume şi prenume Loc de Salariu


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

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


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

Indicator de Nume şi prenume Loc de Salariu


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

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

program actualizare_fisier_relativ;
uses crt;
type
art=record
is:0..1;
nume:string[20];
prof:string[10];
loc:byte;
sal:longint
end;
Algoritmi în programare. Aplicaţii

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

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

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


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

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


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

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

Procedura de scriere în acces direct

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

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

Procedura de scriere în acces secvenţial

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

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

Procedura de citire în acces direct

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

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

Procedura de citire în acces secvenţial

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

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

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

Procedura de ştergere în acces direct

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

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


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

Procedura de rescriere

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

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

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

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