Sunteți pe pagina 1din 221

Cuprins

1. Tipuri dinamice de date. Lucrul cu adrese ...................................................... 3


2. Structura de list n limbajul Pascal ................................................................ 15
3. Grafuri. Implementri n limbajul Pascal ........................................................ 28
4. Structuri arborescente ...................................................................................... 48
5. Algoritmi recursivi. Metodele divide et impera i backtracking ............ 73
6. Reprezentarea vizual a datelor ....................................................................... 92
7. Tehnici speciale n Pascal .................................................................................... 123
8. Prelucrarea etichetelor de fiier i a altor informaii externe
memorate n discuri .................................................................................................. 143
9. Unele aspecte tehnice referitoare la prelucrarea fiierelor .................... 162
10. Obiecte n Pascal ................................................................................................. 174
Anexa 1 Unitatea DOS .......................................................................................... 208
Anexa 2 Unitatea CRT .......................................................................................... 215
Anexa 3 Erori de execuie ................................................................................... 217
Bibliografie ................................................................................................................. 221










Datele de tip static au caracteristici care limiteaz rezolvarea unor clase de
probleme. n primul rnd, spaiul de memorie aferent unor astfel de date se definete
i se rezerv la dimensiune maxim, prestabilit, ca spaiu propriu care nu poate fi
disponibilizat i nici mprit cu alte date, chiar dac, n momentul diverselor execuii
ale programului, nu este n ntregime utilizat (rezervare static sau la momentul
compilrii). n al doilea rnd, componentele structurilor statice ocup locuri
prestabilite n spaiul rezervat, determinate de relaia de ordonare specific fiecrei
structuri. n al treilea rnd, limbajul definete operaiile admise cu valorile
componentelor, potrivit tipului de baz al structurii, astfel nct numrul maxim i
ordinea componentelor structurii nu pot fi modificate. n aceste condiii, structurile
statice sunt dificil de utilizat n rezolvarea problemelor care prelucreaz mulimi de
date pentru care numrul i ordinea componentelor se modific frecvent n timpul
execuiei programului. Pentru astfel de situaii, limbajul PASCAL ofer posibilitatea
utilizrii datelor de tip dinamic, crora li se pot aloca i elibera zone de memorie pe
parcursul execuiei programului.


1.1 Lucrul cu adrese n Pascal


Adresarea memoriei se realizeaz prin registre ale unitii centrale, care au
capacitatea de un cuvnt. La adresarea n modul real, pentru formarea unei adrese fizice
din spaiul de 1Mo este necesar folosirea a dou registre: de segment (segment), care
conine adresa de nceput a segmentului, numit i adresa de baz; de deplasare (offset),
care precizeaz distana la care se afl octetul adresat fa de nceputul segmentului.
Astfel, orice adres din memorie poate fi specificat n formatul segment:offset sau, n
ali termeni, baz:deplasare. ntruct deplasarea de 16 bii nu poate accesa o locaie de
memorie din afara domeniului 0..2
16
-1, rezult c dimensiunea maxim a unui segment
este de 64 Ko, restricie valabil pentru orice produs utilizat sub MS-DOS. Memoria
este mprit n paragrafe de cte 16 octei, iar fiecare segment ncepe la grani de
paragraf, adic de la o adres divizibil cu 16. ntr-un spaiu de 1Mo sunt 2
16
paragrafe,
ceea ce nseamn c adresa de nceput a unui segment, corespunznd unui numr de
TIPURI DINAMICE DE DATE
LUCRUL CU ADRESE
3
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
paragraf, poate fi reprezentat ca o valoare pe 16 bii. n calculul adresei fizice pe
20 bii, se aplic urmtoarea relaie: segment*16+offset, unde segment i offset
desemneaz coninutul registrelor de segment (un numr de paragraf), respectiv de
deplasare. Adresele din segmentul curent se numesc apropiate (near), iar cele din afara
acestuia sunt ndeprtate (far). Accesul la o adres apropiat presupune doar
schimbarea coninutului registrului de deplasare, n timp ce pentru o adres ndeprtat
trebuie schimbat att valoarea registrului de segment, ct i a celui de deplasare.
n unitatea System sunt definite funciile Seg(Var x):WORD, Ofs(VAR
x):WORD care furnizeaz adresa de segment i deplasarea variabilei, procedurii sau
funciei x. n Pascal exist tipul de date pointer, memorat pe dou cuvinte, n care
cuvntul superior (high) conine partea de segment, iar cuvntul inferior (low) pe cea de
deplasare asociate unei adrese. Pentru a se putea exemplifica modul de lucru cu
adrese, se precizeaz faptul c: tipul pointer se definete prin construcia de forma
^tip; adresarea indirect a unei variabilei se definete prin construcia identificator^;
referirea adresei unei variabile se definete prin construcia @identificator.
Programatorul trebuie s fac distincie ntre adresa i coninutul unei
variabile, precum i ntre adresarea direct i cea indirect. n exemplul de mai jos,
liniile surs numerotate de la 1 la 8 se genereaz urmtoarele tipuri de adresare: 1, 2,
4:adresare direct pentru ambii operanzi i lucru cu coninut; 3: adresare direct
pentru pa i a, lucru cu coninut pentru pa i cu adresa a; 5: adresare direct pentru c
i indirect pentru pa, lucru cu coninut; 6, 7, 8: adresare indirect i lucru cu
coninut. De remarcat c pa este de tip pointer, pa^ este de tip REAL iar @a este
adresa a (are configuraie de pointer).
n sintaxa @identificator, identificator se refer la o variabil, procedur sau
funcie. Efectul referirii @identificator este similar celui obinut prin funcia Addr
definit n unitatea System astfel: Addr(VAR x):pointer, unde x este variabil,
funcie sau procedur. Folosirea referirii identificator^ presupune existena unei
adrese valide n variabila identificator.

Exemplu:
1.1.
VAR a,b,c:REAL; {Se rezerv cte 6 octei pentru fiecare variabil}
pa,pb:^REAL; {Se rezerv cte 4 octei pentru fiecare variabil}
BEGIN
a:=20; {Se atribuie valoarea 20 variabilei de adresa a} 1
b:=a; {Se atribuie variabilei de adresa b, coninutul variabilei
de adresa a} 2
pa:=@a; {Se atribuie variabilei de adresa pa, adresa a} 3

pb:=pa; {Se atribuie variabilei de adresa pb, coninutul variabilei de
adresa pa} 4
c:=pa^; {Se atribuie variabilei c, coninutul variabilei a crei adres
este memorat n pa; aceasta este adresare indirect prin pa.
Lui c i se atribuie coninutul lui a (20)} 5
4
Tipuri dinamice de date. Lucrul cu adrese
WriteLn( 'Valoarea ',pb^:10:2,');
{Se scrie continutul variabilei a carei adresa este n pb } 6
WriteLn( 'Adresa fizica a lui A : ,seg(pb^),':',ofs(pb^));
{Se scrie adresa a, sub forma segment:deplasare} 7
WriteLn( 'Adresa fizica a lui PB:',seg(pb),':',ofs(pb));
{Se scrie adresa pb, sub forma segment:deplasare} 8



1.2 Structura memoriei la execuia unui program


Dup ncrcarea programului executabil, memoria aferent lui se structureaz
n urmtoarele regiuni (segmente): segmentul prefix program, regiunea de cod,
segmentul de date, stiva i zona heap (figura 1.1). Pentru adresarea acestora, unitatea
central de prelucrare folosete registre specializate (tabelul 1.1), la unele dintre ele
existnd acces direct (vezi tipul Registers din unitatea DOS, anexa 1) sau indirect din
programe Pascal.

Tabelul 1.1 Registre de segment /deplasare i funcii standard asociate
Tipul segmentului Registrul de
segment
Registrul de
deplasare
Seg:Ofs
Segment de cod CS (CSeg) IP CS:IP
Segment de date DS (DSeg) SI DS:SI
Segment de stiv SS (SSeg) SP (SPtr) SS:SP (SSeg:SPtr)
Observaie: Cseg, DSeg, SSeg, SPtr sunt funcii de tip WORD, nu au parametri i
sunt definite n unitatea System.

Segmentul prefix al programului (PSP) este o zon de 256 de octei constituit
de MS-DOS la ncrcarea n memorie a fiierului de tip .EXE. El conine informaii
necesare sistemului de operare pentru a transfera controlul ctre program, respectiv
pentru a returna controlul ctre sistemul de operare la ncheierea execuiei acestuia.
Adresa de segment este memorat n variabila public PrefixSeg, de tip WORD,
definit n unitatea System.
Regiunea de cod este constituit din mai multe segmente de cod: unul
corespunznd programului principal, respectiv cte unul pentru fiecare unitate referit n
program. Primul segment de cod este cel asociat programului principal, urmat de cele
ale unitilor, n ordinea invers specificrilor din clauza USES. Ultimul segment de
cod, introdus implicit n orice program executabil, corespunde unitii System, care
conine biblioteca de subprograme standard referite la momentul execuiei (Run-time
library). n absena clauzei USES, zona de cod va conine dou segmente: cel al
programului principal i cel al unitii System. Codul poate fi mprit ntr-un numr
oarecare de segmente, singura limitare fiind dat de memoria disponibil. Registrul CS
5
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
conine adresa de start a instruciunilor programului, iar registrul IP (registru pointer al
instruciunilor) precizeaz adresa urmtoarei instruciuni de executat. Programele Pascal
nu au acces la registrul IP, dar valoarea curent a registrului CS poate fi obinut cu
funcia CSeg. Adresa de nceput a zonei de cod este CSeg:0000. Coninutul registrului
CS se poate modifica pe parcursul execuiei, depinznd de faptul c instruciunile
executate sunt din programul principal sau din una dintre uniti.

Segment cod program principal

(Limita superioar a memoriei RAM convenionale)
HeapPtr
HeapOrg
SSeg:SPtr
SSeg:0000
DSeg:0000
CSeg:0000
PrefixSeg:0000
Heap
Stiva
Date
Cod
Zona neutilizat n heap
Zona neutilizat n stiva
Variabile globale
Constante cu tip
Unitatea System
Uniti specificate n
clauza USES
Exemplu:
USES Crt,A,B,C;
Segment cod Crt
Segment cod A
Segment cod B
Segment cod C
Program Segment Prefix (PSP)
Variabile dinamice curent alocate n heap
Date nregistrate n stiva
Coninut
fiier
.EXE

Fig. 1.1 Harta memoriei la execuia unui program Pascal

Segmentul de date este unic i conine constantele cu tip urmate de variabilele
globale. Atunci cnd necesarul de memorie pentru datele interne depete 64Ko,
trebuie s se recurg la folosirea unor tehnici adecvate (memorarea datelor n heap sau
pe medii externe, folosirea compactrii etc.). Registrul DS conine adresa de nceput a
segmentului de date i nu se modific pe parcursului execuiei. SI reprezint registrul
index al sursei, folosit pentru a puncta (a indexa) o dat n cadrul segmentului de date.
Pentru instruciunile asupra irurilor de caractere, registrul SI puncteaz pe operandul
surs, n timp ce un alt registru, index al destinaiei (DI), puncteaz operandul
destinaie. Funcia DSeg returneaz valoarea curent a registrului DS. Registrele SI i
DI pot fi accesate indirect, printr-un apel la o ntrerupere. Adresa de nceput a
segmentului de date este DSeg:0000.
6
Tipuri dinamice de date. Lucrul cu adrese
Segmentul de stiv, ca i cel de date, poate avea maximum 64Ko, reducn-
du-se la unul singur. Stiva este folosit n lucrul cu subprograme pentru memorarea
parametrilor formali, variabilelor locale i adreselor de revenire. Registrul SS conine
adresa de nceput a stivei i nu se modific pe parcursul execuiei. Registrul pointer al
stivei (SP) precizeaz deplasarea curent n cadrul stivei. Funcia SSeg returneaz
valoarea registrului SS, iar SPtr returneaz valoarea curent a registrului SP. n cadrul
stivei, alocarea spaiului se face ncepnd de la adrese mai mari spre adrese mai mici.
Adresa curent este definit de SS:SP sau, conform celor precizate anterior, de
SSeg:SPtr.
Zona variabilelor dinamice poate corespunde ntregii memorii convenionale
a calculatorului, rmas disponibil dup ncrcarea programului. n heap se memoreaz
variabilele dinamice, buffer-ele pentru structuri de reacoperire i pentru lucrul n modul
grafic. Adresa de nceput a zonei heap este dat de variabila public HeapOrg, iar
adresa curent este dat de variabila HeapPtr, ambele de tip pointer, definite n unitatea
System. Alocarea variabilelor ncepe de la adrese mai mici ctre adrese mai mari,
spaiul maxim ce poate fi alocat unei variabile neputnd depi 64Ko (strict riguros,
65520 octei), ca urmare a limitrilor impuse mecanismului de adresare a memoriei.
Dup modul lor de funcionare, stiva i heap-ul pot fi asimilate cu dou stive aezate
spate n spate.
Programatorul poate controla repartizarea memoriei disponibile ntre stiv i
heap n faza de execuie cu directiva de compilare {$M}, care are urmtoarea form
sintactic:
{$M StackSize,HeapMin,HeapMax}
StackSize trebuie s fie un ntreg din domeniul 1024 (1Ko) la 65520 (64 Ko),
prin care se specific mrimea segmentului de stiv. HeapMin i HeapMax specific
dimensiunea minim, respectiv maxim a heap-ului, teoretic cu valori ntre 0 i 640 Ko.
Riguros, HeapMin poate avea valori de la 0 la 655360, iar HeapMax trebuie s fie n
domeniul de la HeapMin la 655360. Valorile implicite pentru aceti parametri de
alocare sunt {$M 16384,0,655360}.
Rezult c dimensiunea implicit a stivei este de 16 Ko, iar zona de heap se
extinde, teoretic, n tot spaiul rmas liber n memoria convenional. Practic, din
dimensiunea de 640 Ko trebuie sczut, pe lng spaiul ocupat de programul nsui, cel
corespunztor componentelor sistemului de operare rezidente n memorie pe parcursul
execuiei.

1.3 Tipuri dinamice de date


n Pascal se opereaz cu dou tipuri de date dinamice - referin i pointer -
primele fiind "cu tip" iar celelalte "fr tip".
Tipul referin are sintaxa: tip_referin=^tip_de_baz;. Simbolul ^ are
semnificaia de "indirect". Datorit asocierii cu un tip de baz, variabilele tip_referin
se mai numesc i variabile cu referin legat. La compilare, pentru astfel de variabile,
se vor rezerva n segmentul de date dou cuvinte i la referirea lor se vor genera
7
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
instruciuni cod main conform tipului de baz, dar cu adresare indirect. nainte de
referire, n variabilele de tip_referin trebuie s se ncarce adresele variabilelor de tipul
tip_de_baz. Declararea unui tip referin permite referirea anterior declarrii tipului de
baz. Astfel, urmtoarea secven de declarri este corect: TYPE pointer_a=^vector;
vector=ARRAY[1..20] OF REAL;
Construcia sintactic a referirii unei variabile dinamice depinde de
caracteristicile tipului su de baz: este de forma identificator^ n cazul tipurilor
nestructurate sau celor structurate care permit referirea global (STRING, RECORD i
SET); conine prefixul identificator^, urmat de elementele specifice modului de
referire a componentelor, n cazul tipurilor structurate care permit referirea pe
componente (ARRAY, STRING i RECORD). Aceste posibiliti de referire sunt
ilustrate n programul Alocare_dinamic_1.
Tipul pointer este desemnat prin cuvntul rezervat pointer. Variabilele de tip
pointer pot fi denumite variabile cu referin liber, deoarece pot fi folosite la
memorarea adreselor pentru variabile de orice tip. Tehnica de lucru cu astfel de variabile
este asemntoare celei prezentate la tipul referin. Utilizarea efectiv presupune i n
acest caz o asociere explicit cu un anumit tip de baz, dar soluia folosit este diferit.
La tipul referin, asocierea se face prin declarare, iar n cazul tipului pointer asocierea
se realizeaz la utilizare, prin diverse tehnici. O posibilitate este asigurat de referina
typecasting (transfer de tip), care are forma general: tip(variabil), unde tip este un tip
standard sau declarat anterior de utilizator iar variabil poate fi cu/fr tip sau o
referin prin pointer, de forma variabil_pointer^.
Din punct de vedere fizic, variabilele de tip referin_legat i pointer
memoreaz adrese sub forma segment:offset. De aceea, n limbajul curent de
specialitate, ambele tipuri se definesc prin termenul pointer. Urmtorul exemplu
evalueaz expresia e:=a+b, folosind adresarea indirect pentru toate variabilele (a i e
prin referin_cu_tip iar b prin pointer):

VAR
a,b,e:REAL;
pa,pe:^REAL;
pb:POINTER;
BEGIN
pa:=addr(a); pb:=@b; pe:=@e;
Write(A=); ReadLn(pa^);
Write(B=); ReadLn(REAL(pb^));
pe^:=pa^+REAL(pb^);
WriteLn(E= ,pe^:8:2))
END.

Variabilele pointer (referin sau pointer) pot fi puse n relaie cu operatorii = i
< >. Dou variabile vor fi egale dac au componentele segment, respectiv offset egale.
De remarcat faptul c dou variabile de tip pointer care indic aceeai adres pot fi
neegale, deoarece le difer componentele. Variabilele pointer pot fi folosite n atribuiri.
Att n relaii ct i n atribuiri sunt definite urmtoarele clase de compatibilitate: tipul
referin este compatibil cu orice alt tip dinamic; dou variabile de tip referin sunt
compatibile dac sunt de acelai tip.
Observaie: pa i pb nu sunt de acelai tip dac sunt declarate astfel: pa:^real; pb:^real.
8
Tipuri dinamice de date. Lucrul cu adrese
Ele sunt de acelai tip dac sunt declarate astfel: pa,pb:^real.
Este definit o constant simbolic (nil) cu semnificaie de valoare nul a
tipului dinamic (valoarea nil nu puncteaz o zon de memorie).



1.4 Utilizarea zonei heap


Noiunea de dinamic este strns legat de utilizarea zonei de memorie heap
(dei tipul dinamic poate fi asociat variabilelor memorate n orice component a
memoriei principale). n unitatea System sunt definite urmtoarele variabile de tip
pointer, care pot fi folosite n gestionarea zonei heap: HeapOrg, HeapPtr, HeapEnd,
HeapError, FreeList.
HeapOrg puncteaz pe adresa de nceput a zonei heap, iar HeapEnd d adresa
de sfrit a heap-ului. HeapPtr conine urmtoarea adresa disponibil din heap. Ea este
variabila prin care se gestioneaz fiecare nou alocare, punctnd pe prima adres
disponibil din heap. Toate procedurile de alocare (New, GetMem, Mark) lucreaz cu
aceast variabil. HeapError corespunde adresei rutinei de tratare a erorilor de alocare
pentru variabile dinamice. FreeList servete la gestiunea blocurilor devenite libere n
interiorul heap-ului, punctnd pe primul bloc liber n heap, care puncteaz pe al doilea
.a.m.d. Ultimul bloc liber puncteaz pe vrful heap-ului, adic pe locaia dat de
HeapPtr, asigurndu-se astfel posibilitatea realocrii acestor spaii. Dac n interiorul
heap-ului nu exist blocuri libere, atunci FreeList va fi egal cu HeapPtr.
De asemenea, n unitatea System sunt definite o serie de proceduri i funcii
care pot fi utilizate n lucrul cu variabilele dinamice. Procedurile GetMem(p,n),
FreeMem(p,n), respectiv New(p) i Dispose(p) se folosesc pentru a aloca/elibera un
bloc a crui adres este dat de variabila pointer sau referin, p.
Deoarece zona heap este limitat, iar alocarea i eliberarea dinamic
determin alternana unor zone libere cu cele ocupate, este necesar cunoaterea
spaiului disponibil i a spaiului contiguu maxim disponibil. n acest scop pot fi
folosite funciile (fr argumente, cu rezultat de tip LONGINT) MemAvail (pentru
spaiul total disponibil) i MaxAvail (pentru spaiul contiguu maxim disponibil).
Iniial, rezultatul furnizat de MemAvail corespunde dimensiunii totale a heap-ului, care
poate fi obinut i prin aplicarea formulei (Seg(HeapEnd^)-Seg(HeapOrg^))*16,
ntruct adresele de nceput i de sfrit ale heap-ului sunt exprimate ca numere de
paragraf. De asemenea, aceast dimensiune coincide iniial cu cea furnizat de funcia
MaxAvail, care precizeaz cel mai lung bloc de locaii de memorie contigue disponibile
n heap. Se poate determina dac spaiul disponibil este contiguu, pe baza expresiei
relaionale MemAvail = MaxAvail. Dimensiunea n octei ocupat de o variabil
poate fi obinut cu funcia SizeOf(VAR x):WORD, unde x este identificator de
variabil. Se poate stabili dac spaiul disponibil este acoperitor pentru o variabil de
un anumit tip, scriind o relaie de forma MaxAvail >= SizeOf (tip).
Alocarea i eliberarea zonelor pentru variabile referin_legat se face cu
9
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
procedurile New, respectiv Dispose, definite n unitatea System astfel: New(VAR
p:pointer), Dispose(VAR p:pointer). Procedura New rezerv n heap o zon de
memorie de lungime egal cu cea indicat de tipul de baz i ncarc n variabila p
adresa acestei zone.

Exemplu:
1.2.
VAR
px:^INTEGER; {La compilare se rezerva 4 octeti in segmentul de date}

BEGIN

New(px); {La executie se rezerva 2 octeti si se incarca adresa zonei rezervate in
px}
px^:=21; {Se memoreaza valoarea 21 in zona de tip INTEGER din heap}
Dispose(px); {Se elibereaza spatiul rezervat in heap}

De remarcat c exist dou niveluri de rezervare: static (corespunztoare lui
px) i dinamic (datorat procedurii New(px), care rezerv variabil n heap, n
conformitate cu tipul de baz). Din punct de vedere fizic, operaia realizeaz memorarea
n variabila p a valorii HeapPtr i avansarea acesteia din urm cu lungimea specific
tipului de baz. Dac nu exist o zon contigu disponibil de lungime mai mare sau
egal cu cea necesar, se genereaz eroare de execuie. Procedura Dispose elibereaz
zona alocat variabilei. Urmtorea alocare se poate face pe spaiul eliberat, dac este
acoperitor ca lungime. Fizic, se reface n HeapPtr valoarea de dinaintea alocrii prin
New.
n programul Alocare_dinamic_1 se ilustreaz prin exemple simple alocarea i
eliberarea spaiului din heap, precum i referirile globale i pe componente pentru
variabile dinamice ale cror tipuri de baz sunt nestructurate sau structurate. La execuia
programului, pe lng afiarea mesajelor care ilustreaz corectitudinea folosirii tehnicii
de lucru cu variabile dinamice, se remarc revenirea n final, dup eliberarea tuturor
zonelor alocate, la dimensiunea iniial a heap-ului.
Prin posibilitatea de generare a unor succesiuni de valori de acelai tip, de la
simpla alocare dinamic de spaiu pentru o singur valoare a unei variabile se poate
trece la realizarea unor structuri dinamice de date. Acest lucru este posibil pe baza
nlnuirii succesiunilor de valori, ca urmare a includerii la fiecare element al structurii a
dou pri: o parte de informaii, corespunznd valorii propriu-zise a elementului; o
parte de legtur, care va conine adresa urmtorului element.
Fr a se urmri, n acest context, abordarea problematicii implementrii
structurilor de date complexe (liste, stive, cozi, arbori binari etc.), n programul
Alocare_dinamic_2 se prezint realizarea unei liste nlnuite pentru memorarea n
heap a unui vector. Aplicaia are n vedere memorarea n heap a unui vector de mari
dimensiuni, cu elemente de tip ntreg. Pentru fiecare element se construiete o structur
de tip RECORD, n forma asociat tipului element. Pentru simplificare, se cere
utilizatorului s precizeze numrul total de valori i valoarea de start, elementele fiind
generate automat, ca numere ntregi consecutive. Dup construire se reia traversarea
10
Tipuri dinamice de date. Lucrul cu adrese
listei, cu afiarea pe monitor a elementelor vectorului.
Prin procedura New(leg) se va aloca o zon de memorie de dimensiunea unei
date de tipul element, iar n variabila de tip leg se va memora adresa de nceput a acestei
zone. Zona de memorie a crei adres este coninut n variabila de tip leg va fi referit
prin indirectare, folosind o construcie sintactic format din - sau ncepnd cu -
variabila de tip leg^.

PROGRAM Alocare_dinamica_1;
USES Crt;
TYPE
pv=^v;
v=ARRAY[1..100] OF INTEGER;
ps=^s;
s=STRING[120];
pm=^m;
m=SET OF CHAR;
pc=^CHAR;
pa=^a;
a=RECORD
nume:STRING[15];
nota:ARRAY[1..5] OF 1..10;
end;
VAR
legv:pv; legs:ps; legm:pm; legc:pc; lega:pa;
BEGIN
ClrScr;
WriteLn('Adresa de inceput heap: ',
Seg(HeapOrg^),':',Ofs(HeapOrg^));
Writeln('Adresa de sfirsit heap: ',
Seg(HeapEnd^),':',Ofs(HeapEnd^));
WriteLn('Valoare pointer heap: ',
Seg(HeapPtr^),':',Ofs(HeapPtr^));
WriteLn('Dimensiune totala heap: ',MemAvail);
{Rezultat echivalent: (Seg(HeapEnd^)-Seg(HeapOrg^))*16 }
WriteLn('Bloc maxim in heap: ',MaxAvail);
New(legv);
WriteLn('Memorie alocata in heap: ',SizeOf(legv^));
WriteLn('Memorie libera in heap: ',MemAvail);
legv^[1]:=1;
WriteLn('v[1]=',legv^[1]);
Dispose(legv);
WriteLn('Memorie libera in heap: ',MemAvail);
New(legs); legs^:='PASCAL';
WriteLn('Al treilea caracter din sir este ',legs^[3]);
New(legm); legm^:=['a'..'c'];
IF 'c' IN legm^ THEN Writeln('Litera "c" apartine multimii');
New(legc); legc^:=#65; Writeln('Caracter atribuit: ',legc^);
New(lega); lega^.nume:='POPESCU ION'; lega^.nota[2]:=10;
WriteLn('Studentul ',lega^.nume,' are nota ',lega^.nota[2], '
la disciplina a doua');
Dispose(lega); Dispose(legs); Dispose(legc); Dispose(legm);
WriteLn('Memorie libera in heap: ',MemAvail);
END.
Din analiza programului Alocare_dinamic_2 se pot desprinde cteva din
cerinele impuse programatorului n construirea i prelucrarea structurilor dinamice.
Astfel, pentru a face posibil traversarea ulterioar, se memoreaz n variabila de tip
referin inceput adresa primului element. La construirea unui nou element, inclusiv a
primului, cmpul de legtur urm (de tip referin) este iniializat cu valoarea nil; la
11
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
traversarea ulterioar, regsirea unei valori nil corespunde identificrii ultimului
element din list. Pentru toate elementele, ncepnd cu al doilea, construirea presupune
revenirea la elementul anterior, a crui informaie de legtur trebuie s puncteze pe
elementul nou construit. Aceast balansare este asigurat prin jocul variabilelor de tip
referin curent, respectiv urmtor.

PROGRAM Alocare_dinamica_2;
leg=^element;
element=RECORD
v:INTEGER;
urm:leg;
END;
VAR
inceput,curent,urmator: leg;
n,vi,i:INTEGER;
BEGIN
Write('Nr. de elemente si valoare de inceput: ');
ReadLn(n,vi);
New(inceput);
inceput^.v:=vi;
inceput^.urm:=nil;
WriteLn('S-a creat elementul 1 = ',inceput^.v);
curent:=inceput;
FOR i:=2 TO n DO
BEGIN
New(urmator);
urmator^.v:=curent^.v+1;
urmator^.urm:=nil;
WriteLn('S-a creat elementul ',i,' = ',urmator^.v);
curent^.urm:=urmator;
curent:=urmator
END;
i:=1;
curent:=inceput;
WHILE curent^.urm <> nil DO
BEGIN
WriteLn('v[',i,']: ',curent^.v);
curent:=curent^.urm;
Inc(i)
END;
Writeln('v[',i,']: ',curent^.v)
END.

Alocarea i eliberarea zonelor pentru variabile de tip pointer se realizeaz cu
procedurile GetMem, respectiv FreeMem, definite n unitatea System astfel:
GetMem(VAR p:pointer; l:WORD), FreeMem(VAR p:pointer; l:WORD). Efectul
acestora este asemntor procedurilor New i Dispose, cu precizarea c este necesar
specificarea lungimii, care nu poate fi dedus implicit, neexistnd un tip de baz. Un
exemplu simplu de folosire a variabilelor pointer din heap este ilustrat n programul
Alocare_dinamic_3.

PROGRAM Alocare_dinamica_3;
12
Tipuri dinamice de date. Lucrul cu adrese
VAR
p: POINTER;
BEGIN
GetMem(p,6);
REAL(p^):=5.25;
WriteLn(REAL(p^):4:2);
FreeMem(p,6)
END.

Relund exemplul propus prin programul Alocare_dinamic_2, trecerea la
folosirea variabilelor pointer presupune unele adaptri, ilustrate n programul
Alocare_dinamic_4. Din program se constat c aplicarea tehnicii de typecasting
permite att referirea global, ct i pe componente, ilustrat n acest caz pentru
cmpurile unui articol. Spaiul alocat la un apel al procedurii GetMem corespunde
dimensiunii articolului (6 octei).

PROGRAM Alocare_dinamica_4;
TYPE
element=RECORD
v:INTEGER; urm:POINTER;
END;
VAR
inceput,curent,urmator: POINTER;
n,vi,i : INTEGER;
BEGIN
Write('Nr. de elemente si valoare de inceput: ');
ReadLn(n,vi);
GetMem(inceput,6);
element(inceput^).v:=vi;
element(inceput^).urm:=nil;
WriteLn('S-a creat elementul 1 = ',element(inceput^).v);
curent:=inceput;
FOR i:=2 TO n DO
BEGIN
GetMem(urmator,6);
element(urmator^).v:=element(curent^).v+1;
element(urmator^).urm:=nil;
WriteLn('S-a creat elementul ',i,' =
'element(urmator^).v);
element(curent^).urm:=urmator;
curent:=urmator
END;
i:=1;
curent:=inceput;
WHILE element(curent^).urm <> nil DO
BEGIN
WriteLn('v[',i,']: ',element(curent^).v);
curent:=element(curent^).urm;
Inc(i)
END;
Writeln('v[',i,']: ',element(curent^).v)
END.

Ca alternative ale procedurilor New, GetMem, respectiv Dispose,
FreeMem, pot fi folosite procedurile Mark i Release, definite n unitatea System
astfel: Mark(VAR p:pointer), Release(VAR p:pointer). Procedura Mark
memoreaz n variabila p valoarea din HeapPtr, iar procedura Release depune n
13
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
variabila HeapPtr coninutul variabilei p. Folosirea n pereche a procedurilor Mark
i Release ofer posibilitatea ca, dup diverse alocri, s se restabileasc valoarea
variabilei HeapPtr cu valoarea memorat prin Mark. Apelul Release(HeapOrg)
aduce HeapPtr pe nceputul zonei heap (elibereaz zona).
n exemplul urmtor, se memoreaz n y adresa de la un moment dat a lui
HeapPtr (fie ea a), se modific HeapPtr prin rezervarea a 12 octei (pentru x2, x3),
se reface coninutul lui HeapPtr cu adresa a, ceea ce nseamn c x3^ se rezerv la
aceast adres (n locul variabilei x2^).

VAR
x1,x2,x3.x4:^REAL;
y:POINTER;
BEGIN
New(x1); x1^:12;
Mark(y); {Memorarea valorii HeapPtr in Y}
New(x2); x2^:=10;
New(x3); x3^:=34;
Release(y); {Reincarcarea valorii din Y in Heapptr}
New(x4); x4:=46; {Se va memora peste valoare 10 din x2}

14









Unul din principalele atribute ale datelor este structura sau modul de
organizare care le caracterizeaz. Structurile rezult prin gruparea ntr-un anumit
mod a coleciilor de date primitive. Exemple de structuri de date sunt: tablourile,
mulimile, nregistrrile. n continuare vor fi prezentate noi tipuri de organizri, i
anume: listele simplu i dublu nlnuite i cazurile particulare cunoscute sub numele
de stive i cozi.


2.1 Noiuni introductive


Un tip de structur de date poate fi gndit logic, fcnd abstracie de modul
particular n care datele sunt reprezentate n memoria calculatorului. El se reprezint
particularizat prin diverse implementri din limbajele de programare.
Specificarea unui anume tip de organizare pentru datele procesate de un
program presupune definirea mulimii de valori permise pe care o variabil sau
parametru aparinnd acestui tip de date le poate avea, precum i a mulimii de
operaii care pot fi efectuate cu astfel de date. Eficiena unei scheme de prelucrare a
datelor este determinat n mare msur de tipurile particulare de date utilizate.
Limbajul de programare Pascal ofer suficient flexibilitate pentru
reprezentarea unor tipuri complexe de date, dar controlul corectitudinii modului n
care sunt utilizate revine programatorului. Structurile de date Pascal pentru
reprezentarea coleciilor de date pot fi clasificate n structuri statice i dinamice.
Structurile statice cuprind: array, set i file pentru reprezentarea datelor de acelai tip
(omogene) i record, pentru reprezentarea datelor eterogene. Structurile dinamice se
construiesc pe baza tipurilor de date Pascal referin legat i referin liber
(desemnat prin tipul predefinit pointer).
Definirea unei date reprezentat printr-o structur static presupune alocarea
unui spaiu de memorie de dimensiune invariabil pe durata evoluiei programului, n
timp ce dimensiunea unei date reprezentat prin intermediul unei structuri dinamice
poate fi modificat pe durata execuiei.
STRUCTURA DE LIST
N LIMBAJUL PASCAL
15
Programarea calculatoarelor - Tehnica programrii n limbajul Pascal
Pentru anumite clase de probleme, structurile statice de date nu numai c nu
sunt suficiente, dar se dovedesc chiar imposibil de folosit, datorit limitrilor la care
sunt supuse. n primul rnd, spaiul de memorie aferent unor astfel de date se
definete i se rezerv n momentul compilrii programului (rezervare static), la o
dimensiune maxim (cuprinztoare). Acest spaiu nu poate fi disponibilizat i nici
mprit cu alte date, chiar dac nu este n ntregime utilizat n anumite momente ale
execuiei programului. n al doilea rnd, componentele structurilor statice ocup
locuri prestabilite n spaiul rezervat, determinate de relaia de ordonare specific
fiecrei structuri. n al treilea rnd, limbajul definete operaiile admise cu valorile
componentelor, potrivit tipului de baz al structurii, astfel nct numrul maxim i
ordinea componentelor structurii nu pot fi modificate.
n aceste condiii, structurile statice sunt dificil de utilizat n rezolvarea
problemelor care prelucreaz mulimi de date pentru care numrul i ordinea
componentelor se modific frecvent n timpul execuiei programului. Pentru astfel de
situaii, exist posibilitatea utilizrii datelor de tip dinamic, crora li se pot aloca i
elibera zone de memorie pe parcursul execuiei programului.



2.2 Structura de list


Organizarea de tip list corespunde unei structurri lineare a datelor, la
nivelul fiecrei componente dispunndu-se de informaie suficient pentru
identificarea urmtoarei componente a coleciei. Datele dintr-o colecie astfel
structurat sunt referite de obicei prin termenii de noduri, celule, componente etc.
Reprezentarea unei liste n limbajul Pascal poate fi realizat prin intermediul
structurii de date array, ordinea componentelor fiind dat de ordinea pe domeniul
valorilor corespunztoare indexrii i, n consecin, urmtoarea component este
implicit specificat. Memorarea unei mulimi de date {d
1
, d
2
,, d
n
} prin intermediul
unei structuri statice poate fi realizat n limbajul Pascal utiliznd un masiv
unidimensional.
Definirea tipului de date Pascal pentru memorarea ca list a datelor {d
1
,
d
2
,, d
n
} este:
const max=500;
type lst=array[1..max] of tip_informatie;
unde nmax i tip_informatie este numele tipului de date Pascal utilizat pentru
memorarea fiecrei date din mulimea {d
1
, d
2
,, d
n
}. Dac lista este variabila de
tip lst utilizat pentru memorarea coleciei {d
1
, d
2
,, d
n
}, atunci data d
i
este
memorat n componenta lista[i], n i 1 .
16
Structura de list n limbajul Pascal
Dezavantajele majore n utilizarea reprezentrii statice rezid n volumul de
calcule necesare efecturii operaiilor de inserie/eliminare de noduri i n necesitatea
pstrrii unei zone de memorie alocat, indiferent de lungimea efectiv a listei.
Aceste dezavantaje sunt eliminate prin opiunea de utilizare a structurilor dinamice.
Componentele unei liste dinamice sunt eterogene, fiecare nod coninnd o parte de
informaie i cmpuri de legtur care permit identificarea celulelor vecine.
Cmpurile de legtur sunt reprezentate de date de tip referin (adres). n cazul
listelor cu un singur cmp de legtur (simplu nlnuite), valoarea cmpului indic
adresa nodului urmtor, n timp ce, n cazul listelor cu dubl legtur (dublu
nlnuite), valorile memorate n cmpurile de legtur sunt adresele componentelor
care preced i, respectiv, urmeaz celulei. n ambele situaii, cmpul de legtur
pentru indicarea celulei urmtoare corespunztor ultimei componente a listei are
valoarea nil n cazul listelor deschise (lineare) i respectiv indic adresa primei
componente din list n cazul listelor nchise (circulare).
Se presupune c mulimea de date {d
1
, d
2
,, d
n
} este memorat ca list
linear. Convenional, structura rezultat poate fi reprezentat grafic fie prin a) (list
simplu nlnuit), fie prin b) (list dublu nlnuit), unde simbolul
desemneaz valoarea nil a cmpului de legtur (figura 2.1). n cazul n care
pentru memorarea datelor {d
1
, d
2
,, d
n
} se dorete utilizarea unei structuri de list
circular, reprezentarea grafic este dat n figura 2.2.


d
n
d
n-1
d
1
d
2
C

Fig. 2.1 Liste lineare
d
1
d
2
d
n-1
d
n

C
b)
a)


Declarrile tipurilor de date Pascal pentru definirea structurilor de liste
dinamice simplu i, respectiv, dublu nlnuite sunt:
a) List simplu nlnuit

type lista=^nod;
nod=record
inf:tip_informatie;
leg: lista;
end;
b) List dublu nlnuit

type lista=^nod;
nod=record
inf:tip_informatie;
st,dr: lista;
end;
unde tip_informatie este numele tipului de date Pascal utilizat pentru memorarea
fiecrei date din mulimea{d
1
, d
2
,, d
n
}.
17
Programarea calculatoarelor - Tehnica programrii n limbajul Pascal

d
n
d
n-1
d
1
d
2

a) ultim


Fig. 2.2 Liste circulare
d
1
d
2
d
n-1
d
n

ultim
b)




2.3 Operaii primitive asupra listelor


Accesul la informaia stocat ntr-o variabil de tip list revine efectund una
sau mai multe dintre operaiile primitive: regsirea nodului (dac exist) care
corespunde unei chei date (condiie impus asupra valorii cmpului de informaie),
inserarea unei noi componente n list, eliminarea componentei (componentelor) cu
proprietatea c valorile cmpurilor de informaie satisfac o anumit cerin i
nlocuirea cmpului de informaie corespunztor unei componente printr-o informaie
dat.
Accesarea componentelor unei liste reprezentat printr-o structur static
poate fi realizat att secvenial, ct i direct, utiliznd valorile indicelui considerat
pentru indexare, n timp ce accesarea componentelor unei liste dinamice se
realizeaz, de regul, numai secvenial, ncepnd cu prima component i continund
cu urmtoarele, pe baza valorilor cmpurilor de legtur. Convenional, numim cap
al listei dinamice pointerul a crui valoare este adresa primei componente a listei.

1. Parcurgerea integral a datelor memorate ntr-o list. Se presupune c
declarrile de tip pentru definirea structurilor de liste menionate anterior sunt
globale, relativ la procedurile descrise n continuare.

18
Structura de list n limbajul Pascal
a) Lista reprezentat prin structur static (masiv unidimensional)

procedure parcurgere1(var l:lst; n:word);
var i:word;
begin
for i:=1 to n do
prelucrare(l[i]);
end;

b) Lista reprezentat prin structur dinamic simplu nlnuit

procedure parcurgere2( var cap:lista);
var p:lista;
begin
p:=cap;
while(p<>nil) do
begin
prelucrare(p^.inf);
p:=p^.leg;
end;
end;

c) Lista reprezentat prin structur dinamic dublu nlnuit

procedure parcurgere3( var cap:lista);
var p:lista;
begin
p:=cap;
while(p<>nil) do
begin
prelucrare(p^.inf);
p:=p^.dr;
end;
end;

2. Regsirea unei date d ntr-o colecie memorat ntr-o list
n continuare se presupune c funcia egal(a,b:tip_informatie):boolean
returneaz valoarea true dac a i b coincid, altfel returneaz false. Funciile Pascal
exista1, exista2 i exista3 calculeaz valoarea true, dac data d se afl n colecia
memorat n lista dat ca argument, altfel calculeaz valoarea false.

a) Lista reprezentat prin structur static (masiv unidimensional)

function exista1(l:lst; n:word; d:tip_informatie):boolean;
var i:word;
c:boolean;
begin
c:=false;
i:=1;
while(i<=n)and(not c) do
if egal(d,l[i]) then c:=true
else i:=i+1;
exista1:=c;
end;
b) Lista reprezentat prin structur dinamic simplu nlnuit

function exista2(cap:lista;d:tip_informatie):boolean;
var p:lista;
19
Programarea calculatoarelor - Tehnica programrii n limbajul Pascal
c:boolean;
begin
p:=cap;
c:=false;
while(p<>nil)and(not c) do
if egal(d,p^.inf) then c:=true
else p:=p^.leg;
exista2:=c;
end;

c) Lista reprezentat prin structur dinamic dublu nlnuit

function exista3(cap:lista;d:tip_informatie):boolean;
var p:lista;
c:boolean;
begin
p:=cap;
c:=false;
while(p<>nil)and(not c) do
if egal(d,p^.inf) then c:=true
else p:=p^.dr;
exista3:=c;
end;

3. Inserarea unei date, d, ntr-o list
Includerea unei noi componente ntr-o list poate fi realizat, n funcie de
cerinele problemei particulare, la nceputul listei, dup ultima component din list,
naintea/dup o component cu proprietatea c valoarea cmpului de infor-
maie ndeplinete o anumit condiie. Presupunem c funcia condiie
((a,b:tip_informatie):boolean calculeaz valoarea true dac a i b verific condiia
formulat pentru inserare, altfel calculeaz valoarea false. De asemenea, procedura
atribuie(var destinatie:tip_informatie; sursa:tip_informatie) realizeaz copierea datei
sursa n destinatie.
Deoarece prin inserarea unei componente se poate ajunge la depirea
spaiului disponibil de memorie, este necesar verificarea prealabil a posibilitii
realizrii operaiei (dac se poate aloca spaiu de memorie pentru componenta de
inserat). n cazul listelor reprezentate prin structuri statice, aceast verificare va fi
realizat prin compararea lungimii efective n a listei cu dimensiunea declarat max.
n cazul listelor dinamice, este utilizat funcia Pascal predefinit MaxAvail, care
calculeaz lungimea maxim a zonelor nealocate contigue din memoria Heap.
Valoarea returnat pentru parametrul test este true, dac inserarea a fost posibil,
altfel este false.
De exemplu, inserarea la nceputul listei decurge astfel:

a) Lista reprezentat prin structur static (masiv unidimensional)

procedure inserare_la_inceput1(var l:lst; var n:word;
d:tip_informatie;var test:boolean);
20
Structura de list n limbajul Pascal
var i:word;
begin
test:=true;
if n=max then test:=false
else
begin
for i:=n downto 1 do atribuie(l[i+1],l[i]);
atribuie(l[1],d);
n:=n+1;
end;
end;

b) Lista reprezentat prin structur dinamic simplu nlnuit

procedure inserare_la_inceput2(var
cap:lista;d:tip_informatie;var test:boolean);
var p:lista;
begin
test:=true;
if MaxAvail<sizeof(nod) then test:=false
else
begin
new(p);
atribuie(p^.inf,d);
p^.leg:=cap;
cap:=p;
end;
end;

c) Lista reprezentat prin structur dinamic dublu nlnuit

procedure inserare_la_inceput3(var
cap:lista;d:tip_informatie;var test:boolean);
var p:lista;
begin
test:=true;
if MaxAvail<sizeof(nod) then test:=false
else
begin
new(p);
atribuie(p^.inf,d);
p^.dr:=cap;p^.st:=nil;
cap:=p;
end;
end;

Procedurile de inserare la nceputul listei pot fi folosite i pentru crearea unei
liste n care s fie memorat o colecie de date {d
1
, d
2
,, d
n
}. Procedura copiaza(var
d:tip_informatie; var i:word) realizeaz copierea n d a datei d
i
din colecia
considerat. Utiliznd procedurile de inserare deja descrise, operaia de creare a unei
liste poate fi realizat astfel:

a) Lista reprezentat prin structur static (masiv unidimensional)

procedure creeaza1(var l:lst; n:word; var test:boolean);
var i,j:word;
21
Programarea calculatoarelor - Tehnica programrii n limbajul Pascal
d:tip_informatie;
begin
test:=true;
if n>max then test:=false
else
begin
i:=1;
while(i<=n) do
begin
copiaza(d,i);
inserare_la_inceput1(l,i,d,test)
end;
end;
end;

b) Lista reprezentat prin structur dinamic simplu nlnuit

procedure creeaza2(var cap:lista;n:word;var test:boolean);
var i:word;
begin
i:=0; cap:=nil;
test:=true;
while(i<n)and(test) do
begin
i:=i+1;copiaza(d,i);
inserare_la_inceput2(cap,d,test);
end;
end;

4. Eliminarea (tergerea) unei date, d, dintr-o list
Modificarea coninutului unei liste prin eliminarea uneia sau mai multor
componente poate fi descris secvenial, astfel nct este suficient s dispunem de o
procedur care realizeaz eliminarea unei singure componente.
Criteriile de eliminare pot fi formulate diferit, cele mai uzuale fiind: prima
component, ultima component, prima component care ndeplinete o anumit
condiie, respectiv componenta ce precede/urmeaz prima component care
ndeplinete o condiie dat.
n aceste cazuri este necesar verificarea existenei n lista considerat a
componentei ce trebuie eliminat. Verificarea asigur i testarea faptului c lista
prelucrat este vid sau nu. Analog operaiilor de inserare, n cadrul procedurilor
urmtoare, parametrul test returneaz valoarea true, dac eliminarea este efectiv,
altfel returneaz false.
De exemplu, eliminarea primei componente dintr-o list are loc astfel:

a) Lista reprezentat prin structur static (masiv unidimensional)

procedure elimina_prima1(var l:lst; var n:word; var
d:tip_informatie;var test:boolean);
var i:word;
begin
test:=true;
if n=0 then test:=false
else
begin
atribuie(d,l[1]);
22
Structura de list n limbajul Pascal
for i:=1 to n-1 do atribuie(l[i],l[i+1]);
n:=n-1;
end;
end;

b) Lista reprezentat prin structur dinamic simplu nlnuit

procedure elimina_prima2(var cap:lista;var d:tip_informatie;var
test:boolean);
var p:lista;
begin
test:=true;
if cap=nil then test:=false
else
begin
p:=cap;
cap:=cap^.leg;
atribuie(d,p^.inf);
dispose(p);
end;
end;

c) Lista reprezentat prin structur dinamic dublu nlnuit

procedure elimina_prima3(var cap:lista;var d:tip_informatie;var
test:boolean);
var p:lista;
begin
test:=true;
if cap=nil then test:=false
else
begin
p:=cap;
cap:=cap^.dr;
cap^.st:=nil;
atribuie(d,p^.inf);
dispose(p);
end;
end;
2.4 Liste circulare


n anumite cazuri, este preferabil renunarea la structura de tip linear a
listelor i utilizarea unei legturi de la ultima component ctre capul listei, rezultnd
ceea ce se numete list circular (figura 2.2).
Avantajul utilizrii acestui tip de structur este posibilitatea de accesare
dintr-un element al listei a oricrui alt element. n continuare sunt prezentate module
pentru realizarea unor operaii de baz n lucrul cu liste circulare.

type
tip_informatie=string;
clista=^nod;
nod=record
inf:tip_informatie;
leg:clista;
end;

23
Programarea calculatoarelor - Tehnica programrii n limbajul Pascal
procedure atribuie(var d:tip_informatie;s:tip_informatie);
begin
d:=s;
end;

procedure inserare_la_inceput(var
ultim:clista;d:tip_informatie;var test:boolean);
var
p:clista;
cap:clista;
begin
test:=true;
if MaxAvail<sizeof(nod) then test:=false
else
begin
new(p);
atribuie(p^.inf,d);
if ultim=nil then
begin
ultim:=p;
ultim^.leg:=ultim;
end
else
begin
cap:=ultim^.leg;
p^.leg:=cap;
ultim^.leg:=p;
end;
end;
end;

procedure inserare_la_sfarsit(var
ultim:clista;d:tip_informatie;var test:boolean);
var
p:clista;
cap:clista;
begin
test:=true;
if MaxAvail<sizeof(nod) then test:=false
else
begin
new(p);
atribuie(p^.inf,d);
if ultim=nil then
begin
ultim:=p;
ultim^.leg:=ultim;
end
else
begin
cap:=ultim^.leg;
p^.leg:=cap;
ultim^.leg:=p;
ultim:=p;
end;
end;
end;

procedure elimina_la_inceput(var ultim:clista;var
d:tip_informatie;var test:boolean);
var
cap:clista;
24
Structura de list n limbajul Pascal
begin
test:=true;
if ultim=nil then test:=false
else
begin
cap:=ultim^.leg;
atribuie(d,cap^.inf);
if cap=ultim then
begin
dispose(ultim);
ultim:=nil;
end
else
begin
ultim^.leg:=cap^.leg;
dispose(cap);
end;
end;
end;

procedure elimina_la_sfarsit(var ultim:clista;var
d:tip_informatie;var test:boolean);
var
p:clista;
cap:clista;
begin
test:=true;
if ultim=nil then test:=false
else
begin
cap:=ultim^.leg;
atribuie(d,ultim^.inf);
if cap=ultim then
begin
dispose(ultim);
ultim:=nil;
end
else
begin
p:=cap;
while(p^.leg<>ultim) do p:=p^.leg;
p^.leg:=cap;
dispose(ultim);
ultim:=p
end;
end;
end;
procedure afisare(ultim:clista);
var p,cap:clista;
begin
if ultim=nil then writeln('Lista vida')
else
begin
cap:=ultim^.leg;
p:=cap;
repeat
write(p^.inf,' ');
p:=p^.leg;
until p=cap;
writeln;
end;
end;
25
Programarea calculatoarelor - Tehnica programrii n limbajul Pascal



2.5 Stive i cozi


Accesul la informaia memorat ntr-o list linear pentru efectuarea
operaiilor de inserare i eliminare este permis la oricare dintre componentele
coleciei. Aa dup cum a rezultat n 2.3, identificarea poziiei n care trebuie
efectuat inserarea/eliminarea presupune iniierea unei secvene de operaii de
cutare, ceea ce determin creterea timpului de lucru. Pe de alt parte, o mulime de
aplicaii pot fi modelate utiliznd liste lineare n care introducerea i, respectiv,
eliminarea informaiilor sunt permise numai la capete. Astfel au fost definite tipurile
de list stiv i coad, care impun un tip de organizare a aplicrii operaiilor de
inserare i eliminare.
Stiva
Se numete stiv o list organizat astfel nct operaiile de inserare i
eliminare sunt permise numai la prima component. Acest mod de organizare
corespunde unei gestiuni LIFO (Last In First Out) a informaiei stocate.
Modelul corespunde unei stive de cri. Adugarea unei noi cri n stiv se
face deasupra primei cri, iar extragerea este posibil numai pentru prima carte.
Operaiile de inserare i eliminare ntr-o stiv pot fi descrise prin intermediul
procedurilor inserare_la_inceput1, inserare_la_inceput2, elimina_prima1,
elimina_prima2. Operaiile elementare pentru gestiunea informaiei memorate ntr-o
stiv sunt:
- push(S,d,test) inserarea informaiei d n stiva S;
- pop(d,S,test) preluarea cu eliminare a informaiei memorate n prima
celul a stivei S;
- top(d,S,test) preluarea fr eliminare a informaiei deinute de prima
component a stivei S.
Parametrul test returneaz true dac operaia este posibil, altfel false.

Coada
Se numete coad o list organizat astfel nct operaia de inserare este
permis la ultima component, iar operaia de eliminare este permis numai la prima
component. Acest mod de organizare corespunde unei gestiuni FIFO (First In First
Out) a informaiei stocate.
Modelul corespunde unei cozi de ateptare la un magazin. O nou persoan
se aaz la coad dup ultimul cumprtor, iar persoana care i achit nota de plat
(primul cumprtor) prsete coada.
Implementarea unei liste coad poate fi efectuat att printr-o structur
static (masiv unidimensional), ct i printr-o structur dinamic de tip list. n
scopul eficientizrii operaiilor de inserare/extragere, n cazul implementrii cozilor
prin structuri dinamice lineare, este necesar utilizarea a dou informaii: adresa
26
Structura de list n limbajul Pascal
primei componente i adresa ultimei componente. Aceste informaii pot fi meninute
explicit prin utilizarea a doi pointeri sau prin utilizarea unui pointer i a unei structuri
de list circular.
1. Operaiile de inserare i eliminare pentru list coad reprezentat static
sunt descrise de procedurile inserare_la_sfarsit1 i eliminare_la_inceput prezentate
n cadrul seciunii 2.3.
2. Reprezentarea unei liste coad printr-o structur dinamic circular
utilizeaz o singur variabil adres, ultim, pentru referirea ultimei componente a
listei. Operaiile de inserare i eliminare sunt descrise de procedurile inserare_coada
i eliminare_coada.

procedure inserare_coada(var ultim:lista; d:tip_informatie; var
test:boolean);
var p:lista;
begin
test:=true;
if MaxAvail<sizeof(nod) then test:=false
else
begin
new(p);
atribuie(p^.inf,d);
if ultim=nil then
begin
ultim:=p;
ultim^.leg:=ultim;
end
else
begin
p^.leg:=ultim^.leg;
ultim^.leg:=p;
ultim:=p;
end;
end;
end;
procedure elimina_coada(var ultim:lista; var d:tip_informatie;
var test:boolean);
var prim:lista;
begin
test:=true;
if ultim=nil then test:=false
else
begin
prim:=ultim^.leg;
atribuie(d,prim^.inf);
if ultim^.leg=ultim then
begin
dispose(ultim);
ultim:=nil;
end
else
begin
ultim^.leg:=prim^.leg;
dispose(prim);
end;
end;
end;

27








Grafurile sunt structuri de date cu aplicaii n multe domenii ale prelucrrii
automate a datelor, algoritmii pentru reprezentarea i prelucrarea grafurilor fiind
considerai fundamentali n acest domeniu.
n cadrul seciunii 3.1 sunt prezentate principalele caracteristici ale
grafurilor, precum i modalitile uzuale de reprezentare a structurii de graf. n
continuare sunt descrise tehnicile de parcurgere a grafurilor n lime i n adncime.
Verificarea conexitii i calculul drumurilor n grafuri sunt tratate n seciunea 3.3



3.1 Definiii, caracteristici i reprezentri ale grafurilor


Definiia 3.1.1. Un graf (sau un graf neorientat) este o structur G=(V,E),
unde V este o mulime nevid, iar E este o submulime (posibil vid) a mulimii
perechilor neordonate cu componente distincte din V.
Obiectele mulimii V se numesc vrfuri, iar obiectele mulimii E se numesc
muchii. Dac eE, uv v) (u, e = = , se spune c muchia e are ca extremiti u,v sau
c muchia e este determinat de vrfurile u i v. Dac e=uvE se spune c vrfurile
u, v sunt incidente cu muchia e.

Definiia 3.1.2. Fie G = (V,E) graf. Vrfurile u, v sunt adiacente n G dac
uvE.

Definiia 3.1.3. Graful G = (V,E) este finit, dac V este o mulime finit.

n cadrul acestui capitol vor fi considerate n exclusivitate grafurile finite,
chiar dac acest lucru nu va fi precizat n mod explicit.

Definiia 3.1.4. Fie G
i
=(V
i
,E
i
), i=1,2 grafuri. G
2
este un subgraf al grafului
G
1
dac
1 2
V V i
1 2
E E . Dac G
2
este un subgraf al lui G
1
, G
2
este un graf
parial al lui G
1
dac V
2
=V
1
.
GRAFURI. IMPLEMENTRI
N LIMBAJUL PASCAL
28
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Definiia 3.1.5. Un digraf este o structur D = (V,E), unde V este o mulime
nevid de obiecte numite convenional vrfuri, iar E este o mulime (posibil vid) de
perechi ordonate cu componente elemente distincte din V. Convenional, elementele
mulimii E sunt numite arce sau muchii ordonate.
Terminologia utilizat relativ la digrafuri este similar celei corespunztoare
grafurilor.

Definiia 3.1.6. Se numete graf ponderat o structur (V,E,W), unde G =
= (V,E) este graf, W funcie, ( ) , 0 E : W . Funcia W este numit pondere i ea
asociaz fiecrei muchii a grafului un cost/ctig al parcurgerii ei.

Definiia 3.1.7. Fie G=(V,E) un graf, u,vV.
Secvena de vrfuri : u
0
, u
1
,..,u
n
este un u-v drum dac u
0
=u, u
n
=v, u
i
u
i+1
E
pentru toi i, n i 0 .

Moduri de reprezentare a grafurilor

Cea mai simpl reprezentare a unui graf este cea intuitiv, grafic; fiecare
vrf este figurat printr-un punct, iar muchiile sunt reprezentate prin segmentele de
dreapt, orientate (n cazul digrafurilor) sau nu i etichetate (n cazul grafurilor
ponderate) sau nu, avnd ca extremiti punctele corespunztoare vrfurilor care le
determin.

Exemple:
3.1. Fie G = (V, E) graf, cu V = {1, 2, 3, 4, 5}, E = {(1,2),(1,3),(2,5),(3,5)}.
O posibil reprezentare grafic este:











1


2 4




3
5
29
Grafuri. Implementri n limbajul Pascal
3.2. Fie D = (V, E) digraf, cu V = {1, 2, 3, 4, 5}, E = {(1,2),(1,3),
(2,5),(3,5),(1,5)}. Digraful poate fi reprezentat grafic astfel:














3.3. Fie G = (V, E, W) graf ponderat, cu V = {1, 2, 3, 4}, E =
{(1,2),(1,3),(2,4),(3,4)}, W((1,2))=5, W((1,3))=1, W((2,4))=2, W((1,4))=7. O
posibil reprezentare grafic este:
Dei acest mod de reprezentare este foarte comod i sugestiv, n special n
cazul grafurilor cu numr mic de vrfuri, pentru prelucrri cu ajutorul calculatorului
sunt necesare reprezentri prin intermediul structurilor de date.
O modalitate de reprezentare este cea prin matrice de adiacen. Dac
G=(V,E) este graf sau digraf cu n V = , atunci matricea de adiacen AM
nxn
({0,1})
are componentele:
( )


=
altfel
j i
dac
ij
, 0
E v , v , 1
a ,
1


2 4




3
5

1


5 1


2 3
7
2


4
30
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
unde v
i
, v
j
reprezint cel de-al i-lea, respectiv cel de-al j-lea nod din V. Se observ c,
n cazul unui graf neorientat, matricea de adiacen este simetric -
ji ij
a a , n , 1 j , i = = (perechile de vrfuri ce caracterizeaz muchiile sunt
neordonate, deci dac uvE, atunci i vuE), n timp ce, n cazul unui digraf, este
posibil ca ( ) , E v , v
j i
( ) E v , v
j i
, deci a
ij
a
ji
.

Exemplu:
3.4. Graful din exemplul 3.1 i digraful din exemplul 3.2 sunt reprezentate
prin matricele de adiacen:
|
|
|
|
|
|
.
|

\
|
=
0 0 1 1 0
0 0 0 0 0
1 0 0 0 1
1 0 0 0 1
0 0 1 1 0
A pentru 3.1,
|
|
|
|
|
|
.
|

\
|
=
0 0 0 0 0
0 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 1 1 0
A pentru 3.2

n cazul grafurilor ponderate, reprezentarea matriceal este asemntoare
celei prezentate anterior. Matricea ponderilor unui graf ponderat G = (V, E, W),
n V = , W M
nxn
((0, )) are componentele:
( ) ( )


=
altfel ,
E v , v dac , ) v , v ( W
w
j i j i
j , i
,
unde v
i
, v
j
reprezint cel de-al i-lea, respectiv cel de-al j-lea nod din V, =0
dac ponderea are semnificaia de ctig, respectiv = n cazul n care se dorete
reprezentarea costurilor ca ponderi ale grafului.

Exemplu:
3.5. Presupunnd c ponderile reprezint costuri, matricea de reprezentare a
grafului din exemplul 3.3. este:
|
|
|
|
|
.
|

\
|


=
2 7
1
2 5
7 1 5
W .

Reinnd numai informaia util, i anume existena unei muchii ntre dou
vrfuri i eventual valoarea ponderii ei, se obine reprezentarea tabelar, mai
economic din punctul de vedere al spaiului de memorare. n cazul n care exist
vrfuri izolate n graf (ce nu sunt incidente cu nici o muchie), atunci este necesar
pstrarea acestora ntr-un vector suplimentar. Mulimea muchiilor se memoreaz
31
Grafuri. Implementri n limbajul Pascal
ntr-o matrice cu E linii i 2 coloane dac graful nu este ponderat, respectiv cu
3 coloane, dac graful este ponderat. n primele dou coloane se scriu perechile de
vrfuri ce determin muchiile, n cazul grafurilor ponderate cea de-a treia coloan
conine valoarea ponderii muchiei respective.

Exemple:
3.6. Graful din exemplul 3.1 poate fi reprezentat astfel: deoarece 4 este vrf
izolat, vectorul suplimentar este VS = (4), pentru reprezentarea muchiilor fiind
utilizat matricea
|
|
|
|
|
.
|

\
|
=
5 3
5 2
3 1
2 1
A

3.7. Digraful din exemplul 3.2 poate fi reprezentat astfel: deoarece 4 este
vrf izolat, vectorul suplimentar este VS = ( 4), arcele fiind reprezentate prin
|
|
|
|
|
|
.
|

\
|
=
5 3
5 2
5 1
3 1
2 1
A

O alt reprezentare este prin intermediul listelor. Reprezentarea permite
utilizarea economic a spaiului de memorare i, n anumite cazuri, implementri mai
eficiente pentru anumite clase de algoritmi. Vrfurile grafului se memoreaz ntr-o
list, fiecare celul a listei avnd o legtur ctre lista vecinilor acelui vrf (vrfurile
din graf adiacente cu vrful corespunztor acelei celule i indicat ca informaie util).
n situaia n care graful nu este ponderat, el se reprezint printr-o list de
liste, i anume: nodurile grafului se trec ntr-o list L_nod, fiecare celul avnd
structura
informaie legtur vecini legtur nod urmtor
unde:
cmpul informaie conine identificatorul nodului;
legtur vecini reprezint pointer ctre capul listei vecinilor;
legtur nod urmtor conine adresa urmtoarei celule din lista
L_nod.

Un graf ponderat poate fi reprezentat n mod similar, cu diferena c fiecare
celul din lista vecinilor conine i ponderea muchiei respective (muchia care are ca
extremiti vrful referit prin identificatorul de nod din lista vecinilor i respectiv
vrful indicat de informaia acelei celule din L_nod ce conine adresa primului
element al listei vecinilor).
32
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
3.2 Modaliti de parcurgere a grafurilor


Parcurgerea unui graf reprezint o modalitate de vizitare a tuturor vrfurilor
grafului, fiecare vrf fiind vizitat o singur dat. n acest paragraf sunt prezentate
dou modaliti de parcurgere a grafurilor neorientate.
Ambele metode de parcurgere presupun selectarea unui vrf iniial v
0
. Prin
aplicarea acestor metode sunt identificate numai vrfurile grafului cu proprietatea c
exist cel puin un drum de la vrful iniial ctre acel vrf. Grafurile cu proprietatea
c oricare dou vrfuri sunt conectate printr-un drum se numesc conexe i sunt
prezentate n 3.3. Dac graful este conex, atunci prin aplicarea metodelor de
parcurgere vor fi identificate toate vrfurile grafului.


3.2.1 Metoda de parcurgere BF (Breadth First)

Ideea traversrii BF este de parcurgere n lime a grafului, n sensul c
vrfurile grafului sunt prelucrate n ordinea cresctoare a distanelor la vrful
iniial. Prin distan se nelege numrul de muchii din drumul identificat la acel
moment de la vrful iniial ctre acel vrf. La momentul iniial, vrful curent este v
0
.
Deoarece vrful curent la fiecare moment trebuie s fie unul aflat la distan minim
de v
0
, se poate proceda n modul urmtor: iniial lui v
0
i se asociaz valoarea 0 i
fiecrui vrf diferit de v
0
i se asociaz valoarea 1. Dac valoarea asociat vrfului
curent este m, atunci fiecruia dintre vecinii acestuia de valoare 1 i se asociaz
valoarea m+1. Se observ c dac dup ce toate vrfurile de valoare m au fost
considerate i nici unui vrf nu i-a fost recalculat valoarea, atunci toate vrfurile
conectate cu v
0
au fost gsite, deci calculul se ncheie.

Exemple:
3.8 Fie graful:













i v
0
=1.
1


2 3


4 6


5 7
33
Grafuri. Implementri n limbajul Pascal
Valorile calculate prin aplicarea metodei prezentate sunt:

vrf
m
1 2 3 4 5 6 7
0 0 -1 -1 -1 -1 -1 -1
1 0 1 1 -1 1 -1 1
2 0 1 1 2 1 2 1
0 1 1 2 1 2 1
Ordinea de vizitare a vrfurilor: 1,2,3,5,7,4,6.

3.9. Fie graful:












i v
0
=1.
Se observ c vrfurile 8, 9 i 10 nu sunt conectate cu vrful iniial.
Valorile rezultate prin aplicarea metodei sunt:

vrf
m
1 2 3 4 5

6

7 8

9

10
0 0 -1 -1 -1 -1 -1 -1 -1 -1 -1
1 0 1 1 -1 1 -1 1 -1 -1 -1
2 0 1 1 2 1 2 1 -1 -1 -1
0 1 1 2 1 2 1 -1 -1 -1
Ordinea de vizitare a vrfurilor este 1,2,3,5,7,4,6.

Se observ c valorile lui m calculate n final reprezint numrul de muchii
corespunztor celui mai scurt drum care conecteaz vrful iniial cu vrful respectiv,
pentru vrfurile neconectate cu v
0
valoarea lui m rezultat la terminarea calculului
este 1.
O implementare diferit, dar urmnd aceeai idee, rezult prin utilizarea
urmtoarelor structuri de date:
A matricea de adiacen a grafului;
o structur de tip coad, C, n care sunt introduse vrfurile ce urmeaz a fi
vizitate i procesate (n sensul cercetrii vecinilor lor);
1 8

2 3


4 6 9 10


7
5
34
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Un vector c cu n componente, unde:
dac i a fost introdus n coad

=
, 0
, 1
c
i

altfel
i n este numrul vrfurilor grafului.
Componentele vectorului c vor fi iniializate cu valoarea 0.
Descrierea metodei este:
se iniializeaz coada C cu vrful v
0
;
ct timp coada este nevid, se extrage un vrf i din coad, se viziteaz, apoi
se introduc n coad numai vecinii acestuia care nu au fost deja introdui (adic toate
vrfurile k avnd proprietatea c c[k]=0 i a[i,k]=1). Vrfurile i ce au fost introduse
n coad sunt marcate: i introdus n coad, c[i]=1.
n continuare este prezentat un program Pascal pentru parcurgerea n lime a
unui graf. Vrfurile grafului sunt numerotate de la 1 pn la n, parcurgerea ncepnd
cu vrful numerotat cu 1. Graful este reprezentat prin matricea de adiacen.
Structura de coad este implementat ca o list simplu nlnuit, procedurile push i
pop realiznd introducerea, respectiv extragerea unui element din coad.

uses crt;
type
ptcoada=^coada;
coada=record
inf:byte;
leg:ptcoada;
end;


var
prim,ultim:ptcoada;
c:array[1..20] of byte;
a:array[1..20,1..20] of byte;
i,j,k,n:byte;

procedure push(var p,u:ptcoada;i:byte);
var a:ptcoada;
begin
new(a); a^.inf:=i; a^.leg:=nil;
if p=nil then
begin
p:=a; u:=a;
end
else begin
u^.leg:=a;u:=a;
end;
end;

procedure pop(var p,u:ptcoada;var i:byte);
var a:ptcoada;
begin
if p<>nil then
begin
i:=p^.inf; a:=p; p:=p^.leg;
dispose(a);
if p=nil then u:=nil;
end;
35
Grafuri. Implementri n limbajul Pascal
end;

begin {program principal}
clrscr;
write('Numarul de varfuri:');
readln(n);
writeln('Matricea de adiacenta');
for i:=1 to n do
for j:=1 to n do
begin
write('a[',i,',',j,']=');
readln(a[i,j]);
end;
for i:=2 to n do c[i]:=0;
readln;
clrscr;
writeln('Incepem parcurgerea de la nodul 1');
c[1]:=1;
prim:=nil;ultim:=nil;
push(prim,ultim,1);
while prim<>nil do
begin
pop(prim,ultim,i);
write(i,' ');
for k:=1 to n do
if (a[i,k]=1)and(c[k]=0) then
begin
c[k]:=1;
push(prim,ultim,k);
end;
end;
readln;
end.


3.2.2 Metoda de parcurgere DF (Depth First)

Ideea metodei DF revine la parcurgerea n adncime a grafurilor, n sensul
c, la fiecare moment, dac M este mulimea vrfurilor vizitate de procedur, pentru
vizitarea vecinilor este considerat unul din vrfurile din M cu proprietatea c
lungimea drumului calculat pn la vrful iniial v
0
este maxim.
Implementarea metodei poate fi realizat n mai multe moduri, pentru
meninerea mulimii vrfurilor grafului disponibilizate pn la momentul curent fiind
utilizat o structur de date de tip stiv, S.
La momentul iniial se introduce n stiv v
0
. La fiecare pas, se preia cu
tergere ca vrf curent vrful stivei S i se introduc n stiv vecinii nc nevizitai ai
vrfului curent. Un vrf se marcheaz ca vizitat n momentul introducerii lui n S.
Calculul continu pn cnd este efectuat un acces de preluare din stiv i se constat
c S este vid. Pentru gestiunea vrfurilor vizitate, se utilizeaz un vector c cu
n componente, unde n reprezint numrul vrfurilor grafului i, la fiecare moment,
componentele sunt:

36
Programarea calculatoarelor Tehnica programrii n limbajul Pascal

=
altfel 0
vizitat fost a dac 1
,
i ,
c
i


Componentele vectorului c vor fi iniializate cu valoarea 0.

Exemple:
3.10. Pentru graful:












i v
0
= 1, ordinea n care sunt vizitate vrfurile este: 1, 2, 3, 4, 6, 7, 5.

3.11. Pentru graful












i v
0
= 1, ordinea n care sunt vizitate vrfurile este: 1, 2, 3, 4, 6, 7, 5. Vrfurile 8, 9 i
10 nu sunt vizitate de procedur, pentru c nu sunt conectate de vrful iniial selectat.
O variant de implementare a metodei DF rezult prin gestionarea stivei S
dup cum urmeaz. Iniial vrful v
0
este unicul component al lui S . La fiecare etap
se preia, fr tergere, ca vrf curent vrful stivei. Se introduce n stiv unul dintre
vecinii vrfului curent nc nevizitat. Vizitarea unui vrf revine la introducerea lui n
S. Dac vrful curent nu are vecini nc nevizitai, atunci este eliminat din stiv i
1


2 3


4 6


5 7
1 8

2 3


4 6 9 10


7
5
37
Grafuri. Implementri n limbajul Pascal
este efectuat un nou acces de preluare a noului vrf al stivei ca vrf curent. Calculul
se ncheie n momentul n care este efectuat un acces de preluare a vrfului stivei ca
vrf curent i se constat c S este vid. Evident, nici n cazul acestei variante nu vor
fi vizitate vrfurile care nu sunt conectate cu vrful ales iniial.



3.3 Drumuri n grafuri. Conexitate


3.3.1 Drumuri; definiii

Una dintre cele mai importante proprieti ale grafurilor o constituie
posibilitatea de accesare, prin intermediul unei secvene de muchii (arce), dintr-un
vrf dat a oricrui alt vrf al grafului, proprietate cunoscut sub numele de conexitate
sau conexiune. Aa dup cum a rezultat n 3.2., dac G=(V,E) este un graf conex,
atunci pentru orice vrf iniial v
0
considerat, metodele BF i DF permit vizitarea
tuturor vrfurilor din V.

Definiia 3.3.1. Fie G=(V,E) un graf, u,vV. Secvena de vrfuri
: u
0
, u
1
,..,u
n
este un u-v drum dac u
0
=u, u
n
=v, u
i
u
i+1
E pentru toi i, n i 0 .
Lungimea drumului, notat l(),este egal cu n. Convenional, se numete trivial, un
drum cu l()=0.
Definiia 3.3.2. Fie : u
0
, u
1
,..,u
n
un drum n graful G=(V,E). este un drum
nchis dac u
0
=u
n
; n caz contrar, este deschis. Drumul este elementar dac
oricare dou vrfuri din sunt distincte, cu excepia, eventual, a extremitilor.
Drumul este proces dac, pentru orice 1 n j i 0 , u
i
u
i+1
u
j
u
j+1
.
Evident, orice drum elementar este un proces.

Definiia 3.3.3. Fie : u
0
, u
1
,..,u
n
un drum n graful G = (V,E).

: v
0
, v
1
,..,v
m

este un subdrum al lui dac

este un drum i pentru orice j, m j 0 , exist i,


n i 0 , astfel nct u
i
= v
j
.
Evident, orice drum cu lungime cel puin 1 conine cel puin un drum
elementar cu aceleai extremiti.
ntr-adevr, dac : u
0
, u
1
,..,u
n
nu este elementar, atunci exist
n j i 0 < i i 0 sau j n, astfel nct u
i
= u
j
.

Atunci drumul
38
Programarea calculatoarelor Tehnica programrii n limbajul Pascal


=
=

+
+
n j , 0 i dac , u ... u u ... u u
0 j dac , u ... u u
0 i dac , u ... u u
:
n 1 j i 1 0
i 1 0
n 1 j j
'

este, de asemenea, un u
0
-u
n
drum. Aplicnd n continuare eliminarea duplicatelor
vrfurilor n modul descris, rezult n final un u
0
-u
n
drum elementar.


3.3.2 Matricea existenei drumurilor; algoritmul Roy-Warshall

Fie G=(V,E) un graf, n V = . Dac A este matricea de adiacen asociat
grafului, atunci, pentru orice p1,
) p (
ij
a este numrul v
i
-v
j
drumurilor distincte de
lungime p din graful G, unde ( )
) p (
ij
p
a A = .
Definiia 3.3.4. Fie M
n
({0,1)} mulimea matricelor de dimensiuni nxn,
componentele fiind elemente din mulimea {0,1}. Pe M
n
({0,1)}se definesc operaiile
binare, notate i , astfel: pentru orice A=(a
ij
), B=(b
ij
) din M
n
({0,1)},
AB=(c
ij
), AB=(d
ij
), unde
n j , i 1 ,
c
ij
=max{a
ij
, b
ij
}
d
ij
=max{min{a
ik
, b
kj
}, n k 1 }.
Dac A=(a
ij
) M
n
({0,1)}, se noteaz ( ) { } 1 k ; a A
) k (
ij
k
= secvena de
matrice definit prin:
( )
2 k , A A A , A A
) 1 k ( k 1
= =

.
Dac A este matricea de adiacen a unui graf G=(V,E), atunci pentru fiecare
k, 1 n k 1 ,

=
altfel , 0
k lungime de j la i la de drum exist dac , 1
a
) k (
ij

) 1 n ( ) 2 ( ) 1 (
A A A M

= se numete matricea existenei drumurilor
n graful G. Semnificaia componentelor matricei M este:


=
altfel , 1
G n drum v v exist nu dac , 0
m , n j , i 1
j i
ij

39
Grafuri. Implementri n limbajul Pascal
Exemplu:
3.12. Pentru graful:













|
|
|
|
|
.
|

\
|
=
|
|
|
|
|
.
|

\
|
=
|
|
|
|
|
.
|

\
|
=
|
|
|
|
|
.
|

\
|
=
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 0 1
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 0
1 1 0 1
0 1 0 1
1 0 0 1
0 0 0 1
1 1 1 0
3 2
M , A , A , A

Calculul matricei existenei drumurilor permite verificarea faptului c un
graf dat este conex: graful este conex dac i numai dac toate componentele
matricei M sunt egale cu 1.

Algoritmul Roy-Warshall calculeaz matricea existenei drumurilor ntr-un
graf G cu n vrfuri.

procedure Roy_Warshall (a,n,m);
i,j,k:integer;
do-for i=1,n,1
do-for j=1,n,1
m
ij
=a
ij
;
do-for j=1,n,1
do-for i=1,n,1
if m
ij
=1 then
do-for k=1,n,1
if m
ik
<m
kj
then
m
ik
=m
kj
;
endif;
enddo;
endif;
enddo;
enddo;
end;
2


1

3



4
40
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Datele de intrare sunt: n, numrul de noduri i A, matricea de adiacen
corespunztoare grafului. Matricea M calculat de algoritm constituie ieirea i este
matricea existenei drumurilor n graful G.


3.3.3 Componente conexe ale unui graf

Definiia 3.3.5. Fie G=(V,E) graf netrivial. Vrfurile u,v V sunt conectate
dac exist un u-v drum n G.

Definiia 3.3.6. Dac G este un graf, atunci o component conex a lui G este
un subgraf conex al lui G, maximal n raport cu proprietatea de conexitate.
Evident, un graf este conex dac i numai dac numrul componentelor sale
conexe este 1. Mulimile vrfurilor corespunztoare oricror dou componente
conexe distincte sunt disjuncte. Mulimile vrfurilor corespunztoare componentelor
conexe ale unui graf formeaz o partiie a mulimii vrfurilor grafului.
Multe aplicaii modelate n termeni de grafuri impun determinarea
componentelor conexe corespunztoare unui graf dat. Problema poate fi rezolvat n
modul urmtor: se selecteaz un vrf al grafului, se determin componenta conex
care-l conine; dac exist vrfuri care nu aparin componentei conexe determinate,
se alege unul dintre acele vrfuri cruia i se determin componenta conex care-l
conine; n continuare, se repet procedeul pn cnd au fost gsite toate
componentele conexe ale grafului.
Pentru G=(V,E), n V = , n 1 i v
0
V, paii algoritmului pentru
determinarea componentei conexe care conine un vrf v
0
dat sunt:

Pasul 1: V
0
={v
0
}; E
0
=; i=0;
Pasul 2: repet Pas 3 pn cnd V
i
=V
i-1
i E
i
=E
i-1

Pasul 3: i=i+1;
{ }
{ }; e cu incident u , V u , E e / e E E
; E uv , V u , V v / v V V
1 i 1 i i
1 i 1 i i


=
=


Ieirea este G
1
=(V
i
,E
i
), componenta conex din care face parte v
0
.

Exemplu:
3.13. Pentru graful






1 2 7 3





4 5 8 6
41
Grafuri. Implementri n limbajul Pascal
Aplicarea algoritmului descris, pentru v
0
=1, determin urmtoarea evoluie:

i V
i
E
i
i=0 {1}
i=1 {1,2,4} {(1,2),(1,4)}
i=2 {1,2,4,7,5} {(1,2),(1,4),(2,7),(4,5),(4,7)}
i=3 {1,2,4,7,5,8} {(1,2),(1,4),(2,7),(4,5),(4,7),(5,8),(7,8)}
i=4 {1,2,4,7,5,8} {(1,2),(1,4),(2,7),(4,5),(4,7),(5,8),(7,8)}


3.3.4 Drumuri de cost minim

Definiia 3.3.7. Fie G=(V, E, w) un graf ponderat. Costul drumului
: u
1
, u
2
,..,u
n
, notat L(), este definit prin:
( ) ( )

=
+
=
1 n
1 i
1 i i
u , u w L .
Pentru orice u i v vrfuri conectate n G, u v, w-distana ntre u i v, notat
D(u,v), este definit prin:
( ) ( ) { }
uv
D , L min v , u D = , unde D
uv
desemneaz mulimea tuturor u-v
drumurilor elementare din G. Dac
uv
D este astfel nct D(u,v)=L(), drumul
se numete de cost minim.
Cu toate c este utilizat termenul de w-distan, n general D nu este o
distan n sensul matematic al cuvntului.
n particular, dac funcia pondere asociaz valoarea 1 fiecrei muchii a
grafului, atunci, pentru fiecare pereche de vrfuri distincte ale grafului, costul D(u,v)
este lungimea celui mai scurt drum ntre cele dou vrfuri. n acest caz, D este o
distan pe mulimea vrfurilor.
Dat fiind interesul pentru determinarea w-distanelor i a drumurilor de cost
minim n cadrul aplicaiilor modelate pe grafuri, n continuare vor fi prezentai
algoritmi pentru rezolvarea acestor probleme.

Algoritmul Dijkstra

Algoritmul a fost propus de E. W. Dijkstra pentru determinarea w-distanelor
D(u
0
,v) i a cte unui u
0
-v drum de cost minim pentru fiecare vrf vu
0
ntr-un graf
ponderat, unde u
0
este prestabilit.
Fie (V,E,w) graf conex ponderat, u
0
V, SV, u
0
S. Se noteaz S \ V S = i
( ) ( ) { } S x ; x , u D min S , u D
0 0
= . Fie vS astfel nct D(u
0
,v)=D(u
0
, S ), : u
0
,
u
1
,,u
p
v este un u
0
-v drum de cost minim. Evident, 0ip u
i
S i

: u
0
, u
1
,,u
p
,
un u
0
- u
p
drum de cost minim. De asemenea,
( ) ( ) { } E uv , S v , S u ); uv ( w u , u D min S , u D
0 0
+ = .
42
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Dac xS, yS astfel nct ( ) ( ) ) xy ( w x , u D S , u D
0 0
+ = , rezult
( ) ( ) ) xy ( w x , u D y , u D
0 0
+ = . Pentru determinarea unui drum u
0
-v, cel mai ieftin,
algoritmul consider o etichetare dinamic a vrfurilor grafului. Eticheta vrfului v
este (L(v),u), unde L(v) este lungimea celui mai ieftin drum u
0
-v determinat pn la
momentul respectiv i u este predecesorul lui v pe un astfel de drum.

Pentru (V,E,w) graf conex ponderat, n V = i u
0
V, calculul implicat de
algoritmul Dijkstra poate fi descris astfel:
Pasul 1: i=0; S
0
={u
0
}; L(u
0
)=0, L(v)=pentru toi vV, vu
0
. Dac n=1
atunci stop
Pasul 2: Pentru toi v
i
S , dac L(v)>L(u
i
)+w(u
i
v), atunci L(v)=L(u
i
)+w(u
i
v)
i eticheteaz v cu (L(v),u
i
).
Pasul 3: Se determin d=min{L(v), v
i
S } i se alege u
i+1

i
S astfel nct
L(u
i+1
)=d.
Pasul 4: S
i+1
=S
i
{u
i+1
}
Pasul 5: i=i+1. Dac i=n-1, atunci stop. Altfel, reia Pasul 2.

Evident, dac (V,E,w) este graf ponderat neconex, atunci, pentru u
0
V,
algoritmul lui Dijkstra permite determinarea w-distanelor D(u
0
,v) i a cte unui u
0
-v
drum de cost minim pentru toate vrfurile v din componenta conex creia i aparine
u
0
.

Exemplu:

3.14. Fie graful ponderat














1


5 1
9
2 3


2 16
5
5
4
43
Grafuri. Implementri n limbajul Pascal
Considernd u
0
=1, etapele n aplicarea algoritmului Dijkstra sunt:
P1: i=0; S
0
={1}; L(1)=0, L(i)=pentru toi 5 , 2 i = .
P2:
0
S ={2,3,4,5}, u
0
=1
L(2)= >L(1)+5=5 L(2)=5, eticheteaz 2 cu 1
L(3)= >L(1)+1=1 L(3)=1, eticheteaz 3 cu 1
L(4)= >L(1)+9=9 L(4)=9, eticheteaz 4 cu 1
L(5)= , w(1,5)= , deci L(5) nu se modific
P3: selecteaz u
1
=3, L(3)=1, cea mai mic dintre w-distanele calculate la P2
P4: S
1
={1,3}
P5: i=i+1=1 4, reia P2

P2:
1
S ={2,4,5}, u
1
=3
Nu se modific nici o etichet i nici o w-distan (w(3,i)=, pentru
toi i din
1
S )
P3: selecteaz u
2
=2, L(2)=5, cea mai mic dintre w-distanele calculate la P2
P4: S
2
={1,3,2}
P5: i=i+1=2 4, reia P2

P2:
2
S ={4,5}, u
2
=2
L(4)= 9>L(2)+2=7 L(4)=7, eticheteaz 4 cu 2
L(5)= >L(2)+16=21, eticheteaz 5 cu 2
P3: selecteaz u
3
=4, L(4)=7, cea mai mic dintre w-distanele calculate la P2
P4: S
3
={1,3,2,4}
P5: i=i+1=3 4, reia P2

P2:
3
S ={5}, u
3
=4
L(5)= 21>L(4)+5=12, eticheteaz 5 cu 4
P3: selecteaz u
4
=5, L(5)=12, cea mai mic dintre w-distanele calculate la
P2
P4: S
3
={1,3,2,4,5}
P5: i=i+1=4, stop.
Algoritmul calculeaz urmtoarele rezultate:

Vrful v pn la care se
calculeaz w-distana
1 2 3 4 5
D(1,v), eticheta lui v 0, 1 5, 1 1, 1 7, 2 12, 4

Drumurile de cost minim de la vrful 1 la fiecare dintre vrfurile grafului se
stabilesc pe baza sistemului de etichete astfel: drumul de la 1 la un vrf v este dat de:
v
1
, eticheta lui v, v
2
eticheta lui v
1
.a.m.d., pn se ajunge la eticheta 1.

44
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Astfel, v
0
-drumurile de cost minim sunt:
pn la 2: 2,1;
pn la 3: 3,1;
pn la 4: 4,2,1;
pn la 5: 5,4,2,1.

Programul Pascal pentru algoritmul Dijkstra, graful ponderat fiind
reprezentat sub form tabelar, este prezentat n continuare.
Variabilele folosite n program au urmtoarele semnificaii:
- v: numrul de vrfuri ale grafului;
- m: numrul de muchii din graf;
- s: mulimea S
i
la momentul curent;
- t: mulimea
i
S la momentul curent;
- l: vectorul componentelor L din etichetele ataate vrfurilor;
- dr: vectorul componentelor de tip vrf din etichetele ataate vrfurilor.

uses crt;
var a:array[1..200,1..3] of integer;
s,dr,t,l:array[1..20] of integer;
i,j,k,p,v1,u,c,d:integer;
m,v:integer;
begin
clrscr;
readln(v);
readln(m);
for i:=1 to m do
for j:=1 to 3 do
begin
write('a[',i,',',j,']=');
readln(a[i,j]);
end;
i:=1;s[1]:=1;v1:=1;
for j:=2 to v do
begin
t[j-1]:=j; l[j]:=maxint;
end;
l[1]:=0;
for k:=1 to v-1 do
begin
for j:=1 to v-i do
begin
u:=1;
while((t[j]<>a[u,1])or(v1<>a[u,2]))and
((t[j]<>a[u,2])or(v1<>a[u,1]))and(u<=m)
do inc(u);
if(u<=m) and (l[t[j]]>l[v1]+a[u,3]) then
begin
l[t[j]]:=l[v1]+a[u,3];
dr[t[j]]:=v1;
end;
end;
d:=l[t[1]];v1:=t[1];
for j:=2 to v-i do
if l[t[j]]<d then begin
d:=l[t[j]];
45
Grafuri. Implementri n limbajul Pascal
v1:=t[j];
end;
inc(i);
s[i]:=v1;
u:=1;
while(u<=v-i+1)and(t[u]<>v1) do inc(u);
for j:=u to v-i do t[j]:=t[j+1];
end;
clrscr;
for i:=1 to v do
writeln(i,'--->',l[i]);
writeln('Drumurile minime de la fiecare varf la 1:');
for j:=2 to v do
begin
k:=j;write(k,' ');
while k<>1 do
begin
write(dr[k],' '); k:=dr[k];
end;
writeln;
end;
readln;
end.

n anumite cazuri se dorete determinarea numai a w-distanelor D(v
0
,v),
pentru toi vV. n acest caz, algoritmul Roy-Floyd permite o rezolvare a acestei
probleme mai simplu de implementat dect algoritmul Dijkstra.

Algoritmul Roy-Floyd

Pentru (V,E,w) graf ponderat, n V = i W matricea ponderilor, sistemul de
w-distane D(v
0
,v), vV, poate fi calculat pe baza urmtoarei proceduri (similar
algoritmului Roy-Warshall):

procedure Roy_Floyd (w,n,d);
i,j,k:integer;
do-for i=1,n,1
do-for j=1,n,1
d
ij
=w
ij
;
do-for j=1,n,1
do-for i=1,n,1
if d
ij
then
do-for k=1,n,1
if d
ik
>d
ij
+ d
jk
then
d
ik
=d
ij
+ d
jk
;
endif;
enddo;
endif;
enddo;
enddo;
46
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
end;

Matricea D calculat de algoritm este a w-distanelor D(u,v) n graful
ponderat conex (V,E,w); pentru orice n j , i 1

=
altfel ,
conectate sunt v , v ), v , v ( D
d
j i j i
ij

ntr-adevr, procedura calculeaz dinamic w-distana ntre oricare dou
vrfuri i i k, astfel: dac exist un i-k drum ce trece prin j ( n j 1 ), cu costul
corespunztor (d
ij
+ d
jk
)

inferior costului curent (d
ik
), atunci noul drum de la i la k via
j este de cost mai mic dect cel al drumului vechi, deci w-distana ntre i i k trebuie
reactualizat la d
ij
+ d
jk
.

Algoritmul Yen

Pentru calculul tuturor w-distanelor ntr-un graf ponderat, algoritmul propus
de Yen rezolv problema ntr-o manier mai eficient dect algoritmul Roy-Floyd,
din punctul de vedere al volumului operaiilor. Fie (V,E,w) un graf ponderat, W
matricea ponderilor. Pentru determinarea w-distanelor de la vrful v
k
fixat la
celelalte vrfuri ale grafului, algoritmul Yen iniiaz urmtoarele operaii:

Pasul 1: D = W
Pasul 2: i = 1; (k) = 0, b(k) = 0; (j)=0, pentru toi n j 1 , j k
Pasul 3: Calculeaz min{d
kj
; n j 1 , (j)=1}; determin j
0
astfel nct
(j
0
) = 1 i
0
kj
d = min{d
kj
; n j 1 , (j) = 1}
B(j
0
) =
0
kj
d , (j
0
) = 0
d[k,j] = min{d[k,j],d[k,j0]+d[j0,j]}, pentru toi j, n j 1
i=i+1
Pasul 4: Dac i<n, reia Pasul 3, altfel stop.

La terminarea algoritmului, componentele vectorului B sunt egale cu
w-distana de la vrful v
k
la orice alt vrf al grafului: B(j)=D(v
k
,v
j
), n j 1 .
ntr-adevr, componentele egale cu 1 ale vectorului indic, la fiecare reluare a
pasului 3, vrfurile grafului pentru care nu s-a calculat nc w-distana la vrful v
k
.
Dup fiecare efectuare a etapei 3, dac j
0
a fost selectat, atunci B(j
0
)=D(v
k
,
0
j
v ).

47







n clasa grafurilor conexe, structurile cele mai simple, dar care apar cel mai
frecvent n aplicaii, sunt cele arborescente (arbori). n acest capitol sunt prezentate
principalele caracteristici ale arborilor, algoritmi pentru calculul arborelui parial de
cost minim, arbori direcionai, arbori cu rdcin i arbori binari. Pe lng operaiile
primitive asupra arborilor cutarea unei informaii, inserarea unui nod, extragerea
unui nod i metode de parcurgere, sunt prezentate dou clase importante de arbori
binari, i anume arbori de sortare i arbori de structur.



4.1 Grafuri de tip arbore


4.1.1 Definiii i caracterizri ale grafurilor de tip arbore

Definiia 4.1.1. Graful G este arbore dac G este aciclic i conex.
Definiia 4.1.2. Fie G=(V,E) graf arbore. Subgraful H=(V1,E1) al lui G este
un subarbore al lui G dac H este graf arbore.

Exemple:
4.1. Graful










este arbore, deoarece pentru orice pereche de vrfuri i,j, 1i,j 6, ij, exist un i-j
drum i graful nu conine cicluri.

1 3


4 2

5

STRUCTURI ARBORESCENTE
48
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
4.2. Graful










nu este arbore deoarece este conex, dar drumul :1,4,3,2,1 este un ciclu.

4.3. Graful










nu este arbore deoarece are dou componente conexe {1,2,3,4,5,6}, {7,8}.

Proprietatea unui graf de a fi arbore poate fi verificat prin algoritmi care
testeaz calitile de conexitate i aciclicitate. Verificarea proprietii unui graf de a fi
arbore poate fi realizat i pe baza urmtoarelor proprieti:
Proprietatea 1.: Un graf G=(V,E), cu m E , n V = = este de tip arbore dac
i numai dac G este aciclic i n=m+1. Cu alte cuvinte, problema revine la
verificarea aciclicitii grafului i a relaiei existente ntre numrul vrfurilor i
numrul muchiilor grafului.
Proprietatea 2: Un graf G=(V,E), cu m E , n V = = este de tip arbore dac
i numai dac G este conex i n=m+1.
Fie G=(V,E) un graf. Urmtoarele afirmaii sunt echivalente:
1. G este graf arbore;
2. G este graf conex minimal (oriare ar fi eE, prin eliminarea muchiei
e graful rezultat nu este conex);
1 3


4 2

5
6

1 3 7


4 2

5

6 8
49
Structuri arborescente
3. G este graf aciclic maximal (prin adugarea unei noi muchii n graf
rezult cel puin un ciclu).
Definiia 4.1.3. Un graf orientat D=(V,E), cu proprietatea c pentru
, E v , u E v , u , atunci vuE se numete graf asimetric. Digraful D este
simetric dac , E v , u uvE, dac i numai dac vuE.

Definiia 4.1.4. Fie D=(V,E) digraf netrivial. Graful G=(V,E), unde
E={uv/ uvE sau vuE} se numete suport al digrafului D.

Definiia 4.1.5. Un arbore direcionat este un graf orientat asimetric cu
proprietatea c graful suport corespunztor lui este graf arbore. Arborele direcionat
T=(V,E) este cu rdcin dac exist rV astfel nct, pentru orice uV, u r, exist
r-u drum n T. Vrful r se numete rdcina arborelui direcionat T.

Definiia 4.1.6. Dac T=(V,E) este arbore direcionat, atunci T1=(V1,E1)
este subarbore al lui T dac V1V, E1E i T1 este arbore direcionat.

Deoarece graful suport al unui arbore direcionat este aciclic, rezult c
pentru orice uV, u r, r-u drumul n T este unic. De asemenea, un arbore
direcionat are cel mult o rdcin. n consecin, pentru orice uV, u r, distana de
la rdcin la vrful u este egal cu numrul de muchii ale r-u drumului n T.

Exemple:
4.4. Arborele direcionat













este cu rdcin (vrful r este rdcina arborelui).

u
w x


t r y



v z
50
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
4.5. Arborele direcionat












nu are rdcin.

4.6. Arborele






este un subarbore cu rdcin x al arborelui din exemplul 4.5


4.1.2 Arbori orientai; reprezentri i parcurgeri

Definiia 4.1.7. Un arbore orientat este un arbore direcionat cu rdcin.
Deoarece un arbore orientat este un caz particular de digraf, pentru
reprezentarea unui arbore orientat poate fi utilizat oricare din modalitile prezentate
n 3.1. n plus, exist i posibilitatea obinerii unor reprezentri mai eficiente pentru
acest tip de graf.
Una dintre modaliti este reprezentarea FIU-FRATE, care const n
numerotarea convenional a vrfurilor grafului i reinerea, pentru fiecare vrf i al
arborelui, a urmtoarelor informaii:
- FIU(i), care reprezint numrul ataat primului descendent al vrfului i;
- FRATE(i), care reprezint numrul ataat vrfului descendent al tatlui
vrfului i i care urmeaz imediat lui i;
- INF(i), care reprezint informaia ataat vrfului i (de obicei valoarea i).
Pentru reprezentarea arborelui se rein rdcina i numrul nodurilor.
Absena fiului, respectiv a fratelui unui vrf, este marcat printr-o valoare
diferit de numerele ataate vrfurilor (de obicei valoarea 0).
u v


x


y


z w
y w

x

v
51
Structuri arborescente
Exemplu:
4.7. Arborele orientat














este reprezentat astfel:
N=15 (numrul nodurilor arborelui)
R=1 (rdcina), FIU=(2,5,7,9,0,10,0,0,13,0,0,0,0,0,0)


fiul lui 1 este 2 vrful 9 are fiul 13
FRATE=(0,3,4,0,6,0,8,0,0,11,12,0,14,15,0)


vrful 1 nu are frate vrful 14 are fratele 15

Utiliznd structurile de date dinamice pentru arbori orientai, se obine o
reprezentare descris n continuare. Presupunnd c fiecare vrf al arborelui are cel
mult n descendeni, fiecrui vrf i este ataat structura:

vector de legturi ctre descendenii vrfului identificatorul vrfului
legtur ctre fiul 1

legtur ctre fiul n

Dac un vrf are p<n descendeni, atunci primele p legturi sunt ctre
descendeni, iar ultimile n-p legturi sunt nil. Pentru n10, descrierea structurii de
date n limbajul Pascal este:
type ptnod=^nod;
nod=record
inf:integer;
leg:array[1..10] of ptnod;
end;
1


2 3 4




5 6 7 8 9



10 11 12 13 14 15
52
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
O parcurgere revine la aplicarea sistematic a unei reguli de vizitare a
vrfurilor grafului. Cele mai uzuale reguli de parcurgere a arborilor orientai sunt
prezentate n continuare.

A. Parcurgerea n A-preordine

Iniial vrful curent este rdcina arborelui. Se viziteaz vrful curent i sunt
identificai descendenii lui. Se aplic aceeai regul de vizitare pentru arborii care au
ca rdcini descendenii vrfului curent, arborii fiind vizitai n ordinea dat de
numerele ataate vrfurilor rdcin corespunztoare.

Exemplu:
4.8. Pentru arborele orientat din exemplul 4.7, prin aplicarea parcurgerii n
A-preordine, rezult: 1,2,5,6,10,11,12,3,7,8,4,9,13,14,15.

Pentru un arbore reprezentat FIU-FRATE, implementarea parcurgerii n
A-preordine se bazeaz pe urmtoarea procedur recursiv, avnd ca parametru de
intrare rdcina arborelui curent (vrful curent n momentul apelului).

procedure A_preordine (R);
if R0 then
vizit (R);
A_preordine(FIU[R]);
A_preordine(FRATE[R]);
endif;
end;

B. Parcurgerea A-postordine

Regula de vizitare a vrfurilor n parcurgerea n A-postordine difer de cea n
A-preordine numai prin faptul c rdcina fiecrui arbore este vizitat dup ce au fost
vizitate toate celelalte vrfuri ale arborelui.

Exemplu:
4.9. Pentru arborele orientat din exemplul 4.7, ordinea de vizitare a vrfurilor
este: 5,10,11,12,6,2,7,8,3,13,14,15,9,4,1.

Pentru arbori reprezentai prin structuri de date arborescente, implementarea
parcurgerii n A-postordine poate fi obinut pe baza urmtoarei proceduri recursive.
Unicul parametru (de intrare) reprezint rdcina arborelui curent n momentul
apelului.

procedure A_postordine (R);
if Rnil then
do-for i=1,n,1
A_postordine(R^.leg[i]);
53
Structuri arborescente
enddo;
vizit (R);
endif;
end;

Procedurile A-preordine i A-postordine sunt variante de parcurgeri n
adncime, fiind prioritare vrfurile aflate la distan maxim fa de rdcina
arborelui iniial.

C. Parcurgerea pe niveluri

Definiia 4.1.8. Un vrf v al unui arbore orientat cu rdcin r se afl pe
nivelul i al arborelui, dac distana de la vrf la rdcin (lungimea r-v drumului) este
egal cu i. Rdcina arborelui este de nivel 0.
Parcurgerea unui arbore orientat pe niveluri const n vizitarea vrfurilor sale
n ordinea cresctoare a distanelor fa de rdcin.

Exemplu:
4.10. Pentru arborele din exemplul 4.7, prin aplicarea parcurgerii pe niveluri,
rezult: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15.

Implementarea parcurgerii pe niveluri se bazeaz pe utilizarea unei structuri
de coad C. La momentul iniial, rdcina arborelui este unicul element din C. Atta
timp ct coada este nevid, se extrage (cu tergere) un vrf din C, este vizitat i sunt
introdui n coad descendenii si. Calculul se ncheie n momentul n care, la
tentativa de extragere a unui vrf din C, se constat C=.
Parcurgerea pe niveluri este realizat de urmtoarea procedur care are ca
parametri de intrare reprezentarea FIU-FRATE a grafului. Procedurile push i pop
realizeaz operaiile de acces introducere-extragere n C.

procedure parcurgere_pe_niveluri(R,FIU,FRATE,n)
C:ptcoada;
C=nil;push(C,R);
while Cnil do
pop(C,v);
VIZIT(v);
v=FIU[v];
while v0 do
push(C,v);
v=FRATE[v];
endwhile;
endwhile;
end;

54
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Exemplu
4.11. Pentru arborele de la exemplul 4.7, evoluia algoritmului este:

C
t

t=1 1
t=2 2 3 4
t=3 3 4 5 6
t=4 4 5 6 7 8
t=5 5 6 7 8 9
t=6 6 7 8 9
t=7 7 8 9 10 11 12
t=8 8 9 10 11 12
t=9 9 10 11 12
t=10 10 11 12 13 14 15
t=11 11 12 13 14 15
t=12 12 13 14 15
t=13 13 14 15
t=14 14 15
t=15 15
t=16

deci vrfurile sunt vizitate n ordinea: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15.

Metoda BF pentru parcurgerea grafurilor este o generalizare a tehnicii de
parcurgere pe niveluri a arborilor orientai. O alternativ de implementare a
parcurgerii pe niveluri poate fi descris prin intermediul procedurilor recursive frai
i parc. Coada C este o variabil global i este iniializat cu rdcina arborelui.
Parcurgerea este obinut prin apelul parc(C).

procedure frai(v);
if v0 then
push(C,v);frai(FRATE[v];
endif;
end;

procedure parc;
if Cnil then
pop(C,v);VIZIT(v);
frai(FIU[v]); parc;
endif;
end;
55
Structuri arborescente
4.1.3 Arbori pariali; algoritmul Kruskal

Definiia 4.1.9. Fie G graf. Subgraful parial H este un arbore parial al lui G
dac H este graf arbore.
Definiia 4.1.10. Fie (V,E,w) un graf ponderat conex. Dac T=(V,E
0
) este un
arbore parial al grafului G=(V,E), ponderea arborelui T este definit prin:
W(T)=

0
E e
) e ( w .
Definiia 4.1.11. Fie T(G) mulimea arborilor pariali corespunztori grafului
G. T
0
T(G) este arbore parial minim pentru G dac W(T
0
)=min{W(T); TT(G)}.
Dac G este graf finit, atunci T(G) este mulime finit, deci orice graf finit
ponderat i conex are cel puin un arbore parial minim.
Pentru calculul unui arbore parial minim sunt cunoscui mai muli algoritmi.
n continuare este prezentat algoritmul Kruskal pentru determinarea unui arbore
parial minim al unui graf ponderat conex G=(V,E,w).

Pasul 1: i=1; E
0
=
Pasul 2: Determin mulimea
R={e/eE \ E
i-1
astfel nct graful (V,E
i-1
{e}) este aciclic}
Dac R=, atunci stop;
altfel, selecteaz e
i
R cu w(e
i
)=min{w(e), eR};
E
i
=E
i-1
{e
i
}
Pasul 3: i=i+1 i reia pasul 2.

Structura (V,E
i-1
) calculat de procedur este arbore parial minim al grafului
conex ponderat G.

Ideea algoritmului Kruskal revine la alegerea i includerea n mulimea de
muchii curente a unei muchii de cost minim nc neselectate i astfel nct s nu
formeze un ciclu cu muchiile selectate la etapele precedente. Algoritmul se ncheie
atunci cnd nici o alegere nu mai este posibil. Aplicarea metodei la grafuri neconexe
calculeaz o mulime de arbori pariali minimi, cte un arbore pentru fiecare
component conex.
Pentru implementarea algoritmului Kruskal, graful conex ponderat este
reprezentat sub form tabelar, muchiile fiind ordonate cresctor dup ponderi.
Muchiile selectate de algoritm pot fi meninute, de asemenea, ntr-o structur
tabelar, sau doar marcate ca fiind incluse n mulimea muchiilor arborelui parial
minim a crui construcie este dorit. n varianta prezentat n continuare muchiile
selectate sunt afiate.
Pentru verificarea condiiei ca muchia selectat s nu formeze nici un ciclu
cu muchiile selectate la etapele precedente, este utilizat un vector, TATA. Pentru
fiecare vrf i (vrfurile grafului fiind numerotate de la 1 la n, unde n este numrul
nodurilor grafului), componenta TATA [i] este predecesorul su n arborele care
conine vrful i construit pn la momentul curent, dac i nu este rdcina acelui
56
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
arbore, respectiv TATA[i] este egal cu numrul de vrfuri ale arborelui de
rdcin i, n caz contrar. Componentele vectorului TATA sunt iniializate cu
valoarea -1. Calculul care realizeaz adugarea unei noi muchii poate fi descris
astfel:
- este determinat o muchie de cost minim, e=v1v2, care nu a fost selectat
anterior;
- se verific proprietatea de aciclicitate a grafului care rezult prin eventuala
adugare a muchiei selectate astfel: dac vrfurile v1 i v2 nu aparin
aceluiai arbore, atunci proprietatea de aciclicitate este ndeplinit i
muchia e este adugat la structura curent. Determinarea valorii k
reprezentnd rdcina arborelui care conine vrful dat v rezult prin
parcurgerea vectorului TATA:
k=v;
while TATA[k] >0 do k=TATA[k]
endwhile;
- adugarea muchiei e selectate este realizat prin reunirea arborilor cu
rdcini r1 i r2, din care fac parte v1 i respectiv v2, astfel: dac
TATA[r1]<TATA[r2] (arborele de rdcin r1 conine mai multe vrfuri
dect arborele de rdcin r2), atunci arborele rezultat prin reunirea celor
doi arbori are ca rdcin vrful r1, iar vrful r2 devine fiu al lui r1
(TATA[r2]=r1 i TATA[r1] =TATA[r2]+TATA[r1] (numrul muchiilor
arborelui cu rdcin r1 este crescut cu numrul muchiilor arborelui cu
rdcin r2). n caz contrar se procedeaz analog, rdcina arborelui
rezultat prin reunire fiind r2, iar r1 devenind fiu al rdcinii.
Calculul se ncheie dup ce a fost adugat cea de-a (n-1)-a muchie.



4.2 Arbori binari


4.2.1 Reprezentare; parcurgeri

Definiia 4.2.1. Un arbore binar este un arbore orientat cu proprietatea c
pentru orice vrf v, od(v)2. n cazul od(v)=2, cei doi descendeni sunt desemnai ca
descendent stng (fiu stnga) respectiv descendent drept (fiu dreapta). Pentru
vrfurile cu od(v)=1, unicul descendent este specificat fie ca fiu stnga, fie ca fiu
dreapta.
Definiia 4.2.2. Se numete nod terminal orice vrf v al arborelui cu od(v)=0.
Nodul v este neterminal dac od(v)>0.
Reprezentarea unui arbore binar este realizat prin reinerea, pentru fiecare
nod, a legturilor ctre descendenii lui. Absena unui descendent este reprezentat
prin nil.
57
Structuri arborescente

identificator
nod
legtur fiu
stnga
legtur fiu
dreapta

Structura de date Pascal este:
type arb=^nod;
nod=record;
inf:integer;
fius,fiud:arb;
end;

Definiia 4.2.3. Fie T=(V,E) un arbore binar cu rdcina R. Subarborele
stng al lui T este ST=(V\{R},E\{RS}), unde S este fiul stnga al rdcinii.
Subarborele drept al lui T este DT=(V\{R},E\{RD}), unde D este fiul dreapta al
rdcinii.
n plus fa de metodele deja prezentate pentru parcurgerea arborilor generali
i care sunt aplicabile i n acest caz particular, parcurgerile n preordine(RSD),
inordine(SRD) i respectiv postordine(SDR) sunt special considerate pentru arbori
binari i au multiple aplicaii. Regula de vizitare revine la parcurgerea subarborelui
stng, a subarborelui drept corespunztori vrfului curent. La momentul iniial, vrful
curent este rdcina arborelui. Diferena ntre cele trei tipuri de parcurgere este dat
de momentul n care este vizitat fiecare vrf al arborelui. n parcurgerea RSD
(rdcin-subarbore stng-subarbore drept), fiecare vrf al arborelui este vizitat n
momentul n care devine vrf curent; n parcurgerea SRD (subarbore stng-rdcin-
subarbore drept), vizitarea vrfului este efectuat dup ce a fost parcurs subarborele
stng; n parcurgerea SDR (subarbore stng-subarbore drept-rdcin) vizitarea
fiecrui vrf este efectuat dup ce au fost parcuri subarborii afereni lui.
Procedura preordine realizeaz parcurgerea n preordine, metodele SRD i
SDR fiind propuse cititorului ca exerciii. Procedura preordine este recursiv i are
ca parametru de intrare vrful curent n momentul apelului.

procedure preordine(r:arb);
begin
if r<>nil then
begin
write(r^.inf);
preordine(r^.fius);
preordine(r^.fiud);
end;
end;


58
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
4.2.2 Arbori binari de sortare

Definiia 4.2.4. Un arbore de sortare este un arbore binar cu proprietile:
fiecrui nod i al arborelui i este ataat o informaie INF(i) dintr-o
mulime ordonat de valori;
pentru fiecare nod i, INF(i) este mai mare dect INF(j), pentru toate
nodurile j din subarborele stng al arborelui cu rdcin i;
pentru fiecare nod i, INF(i) este mai mic dect INF(j), pentru toate
nodurile j din subarborele drept al arborelui cu rdcin i;
pentru orice vrfuri i,j, dac ij, atunci INF(i)INF(j).

Exemplu:
4.12. Arborele binar















este de sortare.

Operaiile uzuale efectuate asupra arborilor de sortare sunt inserarea unui
nod, tergerea unui nod i parcurgerea arborelui (n preordine, inordine sau
postordine). Inserarea i tergerea nodurilor ntr-un arbore de sortare trebuie realizate
astfel nct arborele rezultat s fie, de asemenea, arbore de sortare.
Parcurgerea n inordine a unui arbore de sortare determin secvena
vrfurilor arborelui n ordinea cresctoare a informaiilor ataate.

Exemplu:
4.13. Pentru arborele de sortare descris n exemplul 4.12, parcurgerea n
inordine determin secvena de valori: 20,30,40,50,60,70,80,90, adic exact vectorul
de informaii asociate nodurilor ordonat cresctor.
30
70
20
40
60
90
80
50
59
Structuri arborescente
Inserarea unui nod ntr-un arbore de sortare

Algoritmul de inserare a unei informaii nr n arborele de sortare de rdcin
rad este recursiv i const n efectuarea operaiilor. Vrful curent v la momentul
iniial este rdcina arborelui.
- 1. dac arborele de rdcin v este vid (v=nil), este generat arborele cu un
singur nod, avnd nr ca informaie ataat;
- 2. altfel
- a) dac informaia ataat nodului v este mai mare dect nr,
atunci vrful curent devine fiul stnga al lui v;
- b) dac informaia ataat nodului v este egal cu nr, atunci stop
(se previne duplicarea informaiilor ataate vrfurilor arborelui);
- c) dac informaia ataat nodului v este mai mic dect nr,
atunci vrful curent devine fiul dreapta al lui v.

Exemplu:
4.14. Aplicarea algoritmul descris pentru inserarea informaiei 55 n arborele
de sortare din exemplul 4.12 determin urmtoarele operaii:
INF(v)=50<55: se decide inserarea n subarborele drept cu rdcina avnd
informaia ataat 70 (cazul 2.c);
INF(v)=70>55: se decide inserarea n subarborele stng cu rdcina avnd
informaia ataat 60 (cazul 2.a);
INF(v)=60>55: se decide inserarea n subarborele stng cu rdcina nil
(situaia de la 1). Se decide crearea nodului cu informaie 55, fiu stng al nodului de
informaie 60.
Arborele rezultat este:















30
70
20
40
60
90
80
50
55
60
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
tergerea unei informaii dintr-un arbore de sortare

Algoritmul pentru tergerea unei informaii nr din arborele de sortare de
rdcin rad este recursiv este descris n continuare. Vrful curent v la momentul
iniial este rdcina arborelui.
- 1. dac arborele este vid (v=nil) atunci stop (nr nu se afl n mulimea
informaiilor ataate nodurilor arborelui);
- 2. altfel
- a) dac informaia ataat nodului v este mai mare dect nr,
atunci vrful curent devine fiul stnga al lui v ;
- b) dac informaia ataat nodului v este mai mic dect nr,
vrful curent devine fiul dreapta al lui v ;
- c) dac INF(v)=nr atunci:
- c1) dac subarborele stng este vid (v^.fius=nil), atunci
adresa vrfului v este memorat ntr-o celul suplimentar
aux, v devine fiul dreapta al lui v, iar celula aux este
eliberat din memorie (este disponibilizat celula
corespunztoare vrfului din arbore de informaie nr);
- c2) dac subarborele stng este nevid, atunci se determin
cel mai mare element din subarborele stng (este parcurs
subarborele stng pe legturile din dreapta, ct timp acest
lucru este posibil, cu pstrarea i a adresei nodului printe
corespunztor fiecrui vrf atins) :
p:=v^.fius;
while p^.fiud<> nil do
begin
p1:=p;
p:=p^.fiud;
end;
c2.1) dac fiul stnga al lui v nu are subarbore drept
(v^.fius^.fiud=nil), atunci informaia ataat fiului stnga se
transfer n vrful curent, iar fiul stnga (v^.fius) este
nlocuit cu fiul su stnga (v^.fius^.fius) i este eliberat
memoria corespunztoare celulei v^.fius.
c2.2) altfel, se transfer n rdcin informaia ataat
ultimului nod p determinat la c2), nodul p este nlocuit cu
fiul su stng i celula corespunztoare lui p este eliberat
din memorie.

Exemple:
4.15. tergerea informaiei 70 n arborele de sortare din exemplul 4.12 este
realizat astfel:
70>50, decide tergerea din subarborele drept (cu rdcin 70) - situaia 2.b;
70=70, decide tergerea din arborele curent: rdcina etichetat cu 70 -
situaia 2.c;
61
Structuri arborescente
Exist subarbore stng (rdcina lui p este etichetat cu 60) iar acesta nu are
subarbore drept - situaia 2.c.1.: nodul cu informaie 70 este etichetat cu 60, iar p este
nlocuit cu subarborele su stng (vid)
Arborele de sortare rezultat este:













4.16. tergerea informaiei 30 din arborele de sortare:



















este realizat astfel:
30>50, decide tergerea din subarborele stng (cu rdcin 30) - situaia 2.a;
30=30, decide tergerea din arborele curent: rdcina etichetat cu 70
situaia 2.c;
30
60
20
40
90
80
50
30
70
20
40
60
90
25
50
10
24
62
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Exist subarbore stng (rdcina este etichetat cu 20), iar acesta are
subarbore drept - situaia 2.c.2: nodul cu informaie 30 este etichetat cu 25
(informaia ultimului nod p detectat la c2)), iar p este nlocuit cu subarborele su
stng (cu rdcin 24).
Arborele rezultat este:















Punctul c) de la pasul 2 poate fi nlocuit cu:
c) dac INF(v)=nr atunci:
- c1) dac subarborele drept este vid (v^.fiud=nil), atunci adresa
vrfului v este memorat ntr-o celul suplimentar aux, v devine fiul stnga al lui v,
iar celula aux este eliberat din memorie (este eliberat vrful de informaie nr);
- c2) dac subarborele drept este nevid, atunci se determin cel mai
mic element din subarborele drept (este parcurs subarborele drept pe legturile din
stnga, ct timp acest lucru este posibil, cu pstrarea i a adresei nodului printe
corespunztor fiecrui vrf atins) :
p:=v^.fiud;
while p^.fius<> nil do
begin
p1:=p;p:=p^.fius;
end;
c2.1.) dac fiul dreapta al lui v nu are subarbore stng
(v^.fiud^.fius=nil), atunci informaia ataat fiului dreapta se
transfer n vrful curent, iar fiul dreapta este nlocuit cu fiul
su dreapta (v^.fiud^.fiud) i este eliberat memoria
corespunztoare celulei v^.fiud.
c2.2) altfel, se transfer n rdcin informaia ataat
ultimului nod p determinat la c2), nodul p este nlocuit cu
fiul su dreapta i celula corespunztoare lui p este eliberat
din memorie.
25
70
20
40
60
90
10
50
24
63
Structuri arborescente
4.2.3 Arbori de structur

Expresiile aritmetice n care intervin numai operatori binari pot fi
reprezentate prin intermediul arborilor strict binari (fiecare nod neterminal are doi
fii). Un arbore de structur are vrfurile etichetate astfel:
- fiecare nod neterminal este etichetat cu un simbol corespunztor unuia
dintre operatori;
- fiecare nod terminal este etichetat cu un operand (variabil sau constant);
Construcia arborelui de structur corespunztor unei expresii aritmetice date
se realizeaz pe baza parantezrii existente n expresie i a prioritilor
convenional asociate operatorilor (ordinea operaiilor) astfel nct rdcina fiecrui
subarbore este etichetat cu operatorul care se execut ultimul n evaluarea
subexpresiei corespunztoare acelui subarbore.

Exemplu:
4.17. Pentru expresia matematic (a+b)*(c-d)+e/g, arborele de structur este:


















Construcia arborelui de structur pentru o expresie s se face n dou etape, i
anume:
1. Ataarea prioritilor operatorilor i operanzilor (toi operanzii
au aceeai prioritate, egal cu prioritatea maxim). Prioritile ataate
permit eliminarea parantezelor fr ca semnificaia expresiei s se
modifice;
2. Construcia propriu-zis.
/
+

e
g
b
+
a
c d
64
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Prima etap este realizat astfel:
- prioritatea iniial a operatorilor +,- este 1 (dac expresia nu conine
paranteze, atunci n construcie operatorii vor fi primii luai n considerare,
n ordinea de la dreapta la stnga);
- prioritatea iniial a operatorilor /,* este 10 (dac expresia nu conine
paranteze, acetia sunt considerai dup operatorii de prioritate 1 n
ordinea de la dreapta la stnga);
- prioritatea fiecrui operator este incrementat cu valoarea 10 pentru
fiecare pereche de paranteze n interiorul crora se afl;
- prioritatea ataat fiecrui operand este maxint.
Dup stabilirea sistemului de prioriti, se elimin parantezele din expresie
(ordinea de efectuare a operaiilor n cadrul expresiei este indicat de vectorul de
prioriti ataat).

Exemplu:
4.18. Etapele calculului sistemului de prioriti pentru expresia de la
exemplul 4.17 sunt:

i j dim vectorul prioritate
1 10 0
2 10 1 (maxint)
3 10 2 (maxint,11)
4 10 3 (maxint,11,maxint)
5 0 3 (maxint,11,maxint)
6 0 4 (maxint,11,maxint,10)
7 10 4 (maxint,11,maxint,10)
8 10 5 (maxint,11,maxint,10,maxint)
9 10 6 (maxint,11,maxint,10,maxint,11)
10 10 7 (maxint,11,maxint,10,maxint,11,maxint)
11 0 7 (maxint,11,maxint,10,maxint,11,maxint)
12 0 8 (maxint,11,maxint,10,maxint,11,maxint,1)
13 0 9 (maxint,11,maxint,10,maxint,11,maxint,1,maxint)
14 0 10 (maxint,11,maxint,10,maxint,11,maxint,1,maxint,10)
15 0 11 (maxint,11,maxint,10,maxint,11,maxint,1,maxint,10,maxint)

Dup eliminarea parantezelor, expresia rezultat este s=a+b*c-d+e/g, avnd
ca vector de prioriti (maxint,11,maxint,10,maxint,11,maxint,1,maxint,10,maxint).

Construcia arborelui de structur pe baza expresiei s, din care au fost
eliminate parantezele i a vectorului de prioriti, poate fi realizeaz recursiv n
modul descris n continuare. La momentul iniial expresia curent este cea dat.
65
Structuri arborescente
- Pentru expresia curent se determin operatorul/operandul de prioritate
minim care se ataeaz ca etichet a rdcinii r a subarborelui de
structur corespunztor ei; fie i poziia acestuia n cadrul expresiei;
- Dac expresia are un singur simbol (operand) atunci r^.fius=r^.fiud=nil;
- Altfel, se consider subexpresiile s1 i s2, constnd din simbolurile de pe
poziiile 1 pn la i-1 i respectiv i+1 pn la length(s). Arborii de
structur corespunztori subexpresiilor s1 i s2 se ataeaz ca subarbore
stng, respectiv subarbore drept vrfului r.

Exemplu:
4.19. Pentru expresia de la exemplul 4.17, dup determinarea vectorului de
prioriti i a expresiei neparantezate corespunztoare, procedura cr_der realizeaz
urmtoarea construcie:

s=a+b*c-d+e/g,
prioritate=(maxint,11,maxint,10,maxint,11,maxint,1,maxint,10,maxint)

p=1,u=11 min=1, i=8, arborele:









p=1,u=7 min=10, i=4, arborele:













+



n construcie n construcie

+



* n construcie


n construcie n construcie
66
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
p=1,u=3 min=11, i=2, arborele:




















p=u=1 min=maxint, i=1, arborele:





















+
+
n construcie
n construcie
n construcie a

+
+
n construcie
n construcie
n construcie n construcie
67
Structuri arborescente

p=3,u=3 min=maxint, i=3, arborele:



















p=5,u=7 min=11, i=6, arborele:





















+
+
n construcie
n construcie
a
b

+
+
n construcie
n construcie
a
b

n construcie
68
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
p=5,u=5 min=maxint, i=5, arborele:




















p=7,u=7 min=maxint, i=7, arborele:




















+
+
n construcie
n construcie
a
b

c

+
+
n construcie
a
b

c
d
69
Structuri arborescente
p=9,u=11 min=10,i=10, arborele:




















p=9,u=9 min=maxint,i=9, arborele:





















+
+
n construcie
a
b

c
d
/
n construcie

+
+
a
b

c
d
/
n construcie
e
70
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
p=11,u=11 min=maxint,i=11, arborele:


















i construcia se termin.


Construcia arborelui de structur se face n ipoteza n care expresia este
corect. Procedura cr_der se apeleaz cu:nil,1,length(s),s,prioritate, unde s i
prioritate sunt cei rezultai dup apelarea procedurii prioriti.

Definiia 4.2.5. Se numete forma polonez direct a unei expresii, expresia
rezultat n urma parcurgerii RSD a arborelui de structur. . Se numete forma
polonez invers a unei expresii, expresia rezultat n urma parcurgerii SDR a
arborelui de structur.

Exemplu:
4.20. Pentru expresia considerat la exemplul 4.17, forma polonez direct
este +*+ab-cd/eg. Forma polonez invers a expresiei date este ab+cd-*eg/+.

Parcurgerea arborelui n inordine determin secvena de simboluri rezultat
prin eliminarea parantezelor din expresia dat. Restaurarea unei forme parantezate
poate fi realizat printr-o parcurgere SRD n modul urmtor. La momentul iniial,
vrful curent este rdcina arborelui de structur. Dac vrful curent v nu este vrf
terminal, atunci se genereaz (s1) eticheta(v) (s2), unde eticheta(v) este operatorul
etichet a vrfului, s1 este secvena rezultat prin traversarea SRD a subarborelui
stng, s2 este secvena rezultat prin traversarea SRD a subarborelui drept. Dac v
este vrf terminal, atunci este generat secvena eticheta(v).

+
+
a
b

c
d
/
e
g
71
Structuri arborescente
Exemplu:
4.21. Prin aplicarea traversrii SRD a arborelui de structur al expresiei din
4.2.6, rezult:
s=(((a)+(b))*((c)-(d)))+((e)/(g)).
Se observ c, prin aplicarea traversrii SRD i a parantezrii descrise,
expresia rezultat are aceeai semnificaie cu expresia iniial, dar apar multe
paranteze inutile. Propunem ca exerciiu scrierea unei proceduri Pascal pentru
eliminarea parantezelor inutile.

Evaluarea expresiilor aritmetice pe baza arborilor de structur

Traversarea SRD a arborelui de structur ataat unei expresii aritmetice
permite evaluarea expresiei pentru valorile curente corespunztoare variabilelor.
Evaluarea poate fi efectuat n mod recursiv. La momentul iniial, vrful curent este
rdcina arborelui. Dac v este vrf curent, atunci noua informaie asociat lui v este:
- val(eticheta(v)), dac v este vrf terminal;
- val(s1)eticheta(v)val(s2), dac v este neterminal,
unde val(s1), val(s2) sunt valorile rezultate prin evalurile subarborilor stng
i respectiv drept ai lui v; val(eticheta(v)) este valoarea curent a variabilei, dac
eticheta lui v este variabil, respectiv valoarea constantei, dac eticheta lui v este o
constant.
Dac v este vrf neterminal, atunci noua informaie asociat lui v este
val(s1)eticheta(v)val(s2), ce reprezint rezultatul operaiei eticheta(v) aplicat
valorilor val(s1), val(s2).

Exemplu:
4.22. Prin aplicarea metodei de evaluare descrise, se obine:
















15
5
18
3
2
3
5
2
3
6
2
72









Recursivitatea este o tehnic de programare bazat pe apelarea unui
subprogram de ctre el nsui. n cadrul capitolului sunt prezentate calculul recursiv,
metoda divide et impera i metoda backtracking implementat recursiv.



5.1 Calcul recursiv


Calculul valorii n! pentru n dat poate fi efectuat pe baza formulei n!=n(n-1)!,
pentru n 1 i 0!=1. Dac Fact(n) este funcia Pascal care calculeaz n!, atunci, dac
n 1 evaluarea lui Fact(n) rezult prin multiplicarea cu n a valorii calculate de apelul
Fact(n-1), cu Fact(0)=1. Cu alte cuvinte, apelul funciei Fact(n) realizeaz calculul
imediat dac n=0, altfel presupune un nou apel al aceleiai funcii pentru valoarea
argumentului egal cu n-1. Cazurile n care este posibil evaluarea imediat se
numesc condiii terminale.
n Pascal, funcia Fact, este:

function Fact(n:byte):word;
begin
if n=0 then Fact:=1
else Fact:=n*Fact(n-1);
end;

Utilizarea formulei
)! k n ( ! k
! n
C
k
n

= pentru calculul combinrilor (n, k date)


ridic dificulti deoarece n!, pentru n 13, nu poate fi reprezentat n calculator ca
dat de un tip ntreg, chiar dac numrul
k
n
C este relativ mic i poate fi reprezentat
ca ntreg. Pe baza relaiei de recuren
1 k
1 n
k
1 n
k
n
C C C


+ = rezult ceea ce este
cunoscut sub numele de triunghiul lui Pascal.
De exemplu, triunghiul lui Pascal, pentru n = 7, este:
ALGORITMI RECURSIVI
METODELE DIVIDE ET IMPERA
I BACKTRACKING
73
Programarea calculatoarelor Tehnica programrii n limbajul Pascal

1

1 1

1 2 1

1 3 3 1

1 4 6 4 1

1 5 10 10 5 1

1 6 15 20 15 6 1

1 7 21 35 35 21 7 1


Secvena de program pentru calculul
k
n
C , 0k n13 este:

var
n,i,j:word;
x:array[0..13,0..13] of word;
begin
write(Valoarea pentru n=);
readln(n);
if n>13 then
writeln(Eroare)
else
begin
x[0,0]:=1;
for i:=1 to n do
begin
x[i,0]:=1;
x[i,i]:=1;
end;
for i:=1 to n-1 do
for j:=1 to i do
x[i+1,j]= x[i,j-1]+x[i,j];
end;
for i:=0 to n do
begin
for j:=0 to i do write(x[i,j], );
writeln;
end;
end.

Valorile combinrilor sunt calculate n componentele tabelei x, fiind utilizat
numai
2
) 2 n )( 1 n ( + +
din cele 14
2
celule de memorie rezervate.
74
Algoritmi recursivi. Metodele divide et impera i backtracking
Se poate proceda, ns, altfel. Se presupune c function comb(n,k) calculeaz
k
n
C . Conform relaiei de recuren, dac n k 1, atunci evaluarea corespunztoare
apelului comb(n,k) revine la nsumarea rezultatelor obinute prin apelurile comb(n-
1,k) i comb(n-1, k-1), unde comb(n,0)=1, n 0. Dac evalurile comb(n-1,k) i
comb(n-1, k-1) sunt realizate n acelai mod, rezult c apelul comb(n,k) va
determina o secven de apeluri ale aceleiai funcii pentru valori ale argumentelor
din ce n ce mai mici, pn cnd este ndeplinit una din condiiile terminale
comb(n,0)=1, comb(k,k)=1.
Soluia recursiv a evalurii
k
n
C este:

function comb(n,k:byte):word;
begin
if k>n then comb:=0
else
if (k=0) or (k=n) then comb:=1
else comb:=comb(n-1,k)+comb(n-1,k-1);
end;

Un alt exemplu este urmtorul. Se presupune c f
0
, f
1
, , sunt numere
reale date i pentru p 2,
2 p 1 p p
f f f

+ = . Se cere s se calculeze f
n
pentru n dat.
irul definit de relaia precedent pentru f
0
=f
1
= = =1 se numete irul lui
Fibonacci. Dac Fib(n) este funcia Pascal care calculeaz cel de-al n-lea element din
irul considerat, atunci evaluarea lui Fib(n) revine la nsumarea valorilor lui Fib(n-1)
i Fib(n-2) ponderate de constantele i , adic rezolvarea problemei Fib(n)
poate fi redus la rezolvarea problemelor Fib(n-1), Fib(n-2) cu condiiile terminale
Fib(0)=f
0
, Fib(1)=f
1
.
Funcia Pascal Fib pentru calculul celui de-al n-lea termen al irului definit
anterior este:

function Fib(n:word;alfa, beta, f0,f1:real):real;
begin
if n=0 then Fib:=f0
else if n=1 then Fib:=f1
else Fib:=alfa*Fib(n-1)+beta*Fib(n-2);
end;
Fiecare apel Fib(n) pentru n>1 determin nc dou apeluri: Fib(n-1) i
Fib(n-2). Numrul total de apeluri efectuate pn la rezolvarea problemei Fib(n)
crete exponenial, n funcie de parametrul n. Mai mult, rezolvarea problemei
Fib(n-2) are loc att la apelul Fib(n-1), ct i la apelul determinat de Fib(n). Datorit
acestor inconveniente, este preferat o soluie iterativ pentru calculul unui termen de
rang dat al irului lui Fibonacci.
75
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Se spune c astfel de apeluri sunt recursive directe. Schema unui apel
recursiv poate fi descris n modul urmtor. Se verific dac este ndeplinit cel puin
una din condiiile terminale. Dac este ndeplinit o condiie terminal, atunci
calculul se ncheie i se revine la unitatea apelant. n caz contrar, este iniiat calculul
pentru noile valori ale parametrilor, calcul care presupune unul sau mai multe apeluri
recursive.
Mecanismul prin care este efectuat apelul unui subprogram se bazeaz pe
utilizarea stivei memoriei calculatorului. Fiecare apel determin introducerea n stiv
(operaia push) a valorilor/adreselor parametrilor formali, adresei de revenire i a
variabilelor locale. La momentul execuiei, aceste informaii sunt extrase cu
eliminare din stiv (operaia pop), eliberndu-se spaiul ocupat.
n cazul subprogramelor recursive, mecanismul funcioneaz astfel: se
genereaz un numr de apeluri succesive cu ocuparea spaiului din stiv necesar
efecturii acestor apeluri pn la ndeplinirea unei condiii terminale; apelurile sunt
executate n ordinea invers celei n care au fost generate, iar operaia push poate
produce depirea spaiului de memorie rezervat n stiv.
Astfel, n cazul apelului Fact(3), secvena de apeluri recursive iniiate este:
Fact(2), Fact(1), Fact(0). n continuare execuia determin Fact(0)=1,
Fact(1)=1*Fact(0)=1, Fact(2)=2*Fact(1)=2, Fact(3)=3*Fact(2)=6. Evoluia
determinat de apelul Fact(3) n stiv este ilustrat n figurile 5.1 i 5.2, unde ()
reprezint adresa de revenire n punctul de unde a fost efectuat apelul Fact(3).
Apelurile recursive ale unei proceduri sau funcii pot fi i indirecte, n sensul
c este efectuat un apel al unei alte proceduri sau funcii care, la rndul ei, iniiaz un
apel al procedurii sau funciei iniiale.
Un exemplu simplu l reprezint calculul valorilor funciei h=fgf , unde
f,g:RR sunt funcii date.Un mod de a rezolva aceast problem este descris n
continuare. Dac f(x), g(x) sunt funciile Pascal care descriu calculul necesar
evalurii funciilor date n punctul x, atunci pentru calculul valorii h(x) este necesar
apelul funciei f , urmat de apelul funciei g care, la rndul ei, apeleaz din nou
funcia f.
Pentru funciile f, g definite prin

> +
+
=

+
< +
=
1 x , 5 x 3
1 x , 2 x 3 x
) x ( g ,
3 x , 2 x
3 x , 1 x 2
) x ( f
2
2



funcia Pascal h(x) este:



76
Algoritmi recursivi. Metodele divide et impera i backtracking





































Fig. 5.1 Evoluia n stiv pn la condiia terminal Fact(0):=1



2

Fact=2*Fact(1)

Adresa de revenire
3

Fact=3*Fact(2)

Adresa de revenire
2

Fact=2*Fact(1)

Adresa de revenire
3

Fact=3*Fact(2)

Adresa de revenire
1

Fact=1*Fact(0)

Adresa de revenire
2

Fact=2*Fact(1)

Adresa de revenire
1

Fact=1*Fact(0)

Adresa de revenire
0

Fact=1

Adresa de revenire
(o)
(o)
(o)
(o)
3

Fact=3*Fact(2)

Adresa de revenire
3

Fact=3*Fact(2)

Adresa de revenire
77
Programarea calculatoarelor Tehnica programrii n limbajul Pascal













()





()
()



Stiva vid

Fig. 5.2 Eliberarea stivei dup execuia determinat de condiia terminal

function f(x:real):real;
begin
if x<3 then f:=2*x+1
else f:=x*x+2
end;

function g(x:real):real;
begin
if x<=1 then g:=x*x-3*x+2
else g:=3*x+5
end;

function h(x:real):real;
begin
h:=f(g(f(x)));
end;

2


Fact=2*Fact(1)


Adresa de revenire
3


Fact=3*Fact(2)


Adresa de revenire
1


Fact=1


Adresa de revenire
2


Fact=2


Adresa de revenire
3


Fact=3*Fact(2)


Adresa de revenire
3


Fact=6


Adresa de revenire
78
Algoritmi recursivi. Metodele divide et impera i backtracking
5.2 Metoda divide et impera

Metoda divide et impera presupune descompunerea problemei de rezolvat
n dou sau mai multe subprobleme (probleme mai simple), determinarea soluiilor
acestora care, apoi, compuse dup reguli simple, furnizeaz soluia problemei
iniiale.
De exemplu, se presupune c se dorete aflarea valorii maxime dintr-o
secven } a ,..., a {
n 1
de n numere. Pentru rezolvarea problemei se poate proceda n
mai multe moduri: se determin valoarea cea mai mare din prima jumtate, fie
aceasta x
1
, apoi se determin valoarea cea mai mare din a doua jumtate a secvenei,
fie aceasta x
2
. Soluia problemei este max(x
1
, x
2
). Problema iniial a fost
descompus n dou subprobleme de acelai tip, dar mai simple deoarece lungimea
fiecrei secvene este jumtate din lungimea secvenei iniiale. Problema poate fi
rezolvat pe baza unei metode care o reduce succesiv la o problem mai simpl,
determinndu-se valoarea maxim din primele n-1 componente ale secvenei (fie
aceasta x
1
), valoarea maxim fiind max(x
1
,a
n
). Ambele soluii sunt recursive i sunt
reprezentate prin funciile Pascal max1 i max2.

function max1(var a:vector; s,d:byte):real;
var x1, x2:real;
begin
if s=d then max1=a[s]
else
begin
x1:=max1(a,s,(s+d)div 2);
x2:=max1(a,(s+d)div 2+1,d);
if x1>x2 then max1:=x1
else max1:=x2;
end;
end;

function max2(var a:vector; n:byte):real;
var x1:real;
begin
if n=1 then max2=a[1]
else
begin
x1:=max1(a,n-1);
if x1>a[n] then max1:=x1
else max1:=a[n];
end;
end;

Un alt exemplu n care, pentru rezolvarea problemei, se poate efectua un
raionament similar este urmtorul. Se presupune c ecuaia f(x)=0 are o singur
soluie x
0
n intervalul (a,b). Se dorete obinerea unei valori aproximative x

astfel
nct < x

x
0
, pentru 0 > dat. Deoarece ecuaia f(x)=0 are o singur soluie x
0

n intervalul [a,b], rezult c f(a)f(b)<0 i, de asemenea, dac pentru a<<<b
f()f()<0, atunci ) , ( x
0
. Pe baza aceastei proprieti, dac c este mijlocul
79
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
intervalului (a,b), atunci este ndeplinit una i numai una dintre relaiile f(a)f(c)<0,
f(c)=0, f(b)f(c)<0. Dac f(c)=0, atunci x
0
=c. Dac f(a)f(c)<0 atunci ) c , a ( x
0
,
altfel ) b , c ( x
0
. Se presupune c f(a)f(c)<0. Se poate aplica acelai procedeu
intervalului (a,c) i se continu pn cnd sau este obinut soluia exact sau
intervalul care conine soluia este de lungime inferioar lui . n cazul n care
terminarea calculului se realizeaz prin identificarea unui interval de lungime
inferioar lui , x

poate fi considerat oricare dintre numerele din acel interval, de


exemplu mijlocul intervalului. Evident, numrul maxim de iteraii N pentru obinerea
preciziei rezult din inegalitatea <

N
2
a b
, adic 1
a b
log N
2
+
(

|
.
|

\
|

=

.
Se presupune c funcia f este calculat prin apelul funciei Pascal
f(a:real):real. O variant recursiv a metodei descrise este:

uses crt;
{$F+}

type
fct=function(x:real):real;

var
eps,a,b,x:real;
functie:fct;

function f(x:real):real;
begin
f:=x*x*x-8;
end;

procedure bisectie(a,b,eps:real;var f:fct;var x:real);
var xx:real;
begin
if f(a)=0 then x:=a
else if f(b)=0 then x:=b
else if b-a<eps then x:=(a+b)/2
else
begin
xx:=(a+b)/2;
if f(xx)*f(a)<0 then bisectie(a,xx,eps,f,x)
else bisectie(xx,b,eps,f,x)
end;
end;

begin
clrscr;
write('Introduceti a ');
readln(a);
write('Introduceti b ');
readln(b);
eps:=exp(-20);
functie:=f;
bisectie(a,b,eps,functie,x);
writeln('Solutia este:',x:5:2);
readln;
end.

80
Algoritmi recursivi. Metodele divide et impera i backtracking
De asemenea, rezolvarea problemei turnurilor din Hanoi a fost realizat tot
pe baza unei metode de reducere i anume: problema deplasrii a n discuri P(n) a fost
redus succesiv la rezolvarea problemelor mai simple P(n-1), P(n-2),,P(1).

Unul dintre cei mai eficieni algoritmi pentru sortarea cresctoare a unei
secvene de numere reale este cunoscut sub numele de algoritmul de quicksort
(sortare rapid) i reprezint, de asemenea, un exemplu de aplicare a metodei divide
et impera. Fie secvena (v
p
, v
p+1
, ,v
u
), unde iniial p=1, u=n (n=dimensiunea
vectorului).
Dac p = u, secvena este sortat.
Altfel, se poziioneaz v
p
n aceast secven astfel nct toate elementele ce
ajung n faa lui s fie mai mici dect el i toate cele care i urmeaz s fie mai mari
dect el; fie poz poziia lui corect n secvena (v
p
, v
p+1
, , v
poz
, v
poz+1
, ,v
n
).
Procedeul se reia pentru secvenele (v
p
, v
p+1
, ,v
poz-1
) i (v
poz+1
, v
poz+2
, ,v
n
), deci
p poz-1 i poz+1 u.
Poziionarea elementului v
p
se face astfel: se utilizeaz doi indicatori, i i j;
iniial i = p i j = u. Se compar v
i
cu v
j
, dac nu este necesar interschimbarea, se
micoreaz j cu 1, repetndu-se procesul; dac apare o interschimbare, se mrete i
cu 1 i se continu compararea, mrind i pn la apariia unei noi interschimbri.
Apoi se micoreaz din nou j, continundu-se n acelai mod pn cnd i = j.

Exemplu:
5.1. Aplicarea algoritmului de sortare rapid pentru
v = (10, 12, 19, 15, 3, 17, 4, 18)
1 2 3 4 5 6 7 8
p = 1, u = n = 8
a) poziionarea lui v
p
= v
1
= 10
i=1, j=8
Sensul de parcurgere:
i=1, j=8 10<18 j=j-1
i=1,j=7 10>4 se efectueaz interschimbarea i se atribuie i=i+1=2
v=(4, 12, 19, 15, 3, 17, 10, 18)
i=2, j=7
Sensul de parcurgere:
i=2, j=7 12>10 se efectueaz interschimbarea i se atribuie j=j-1=6
v=(4, 10, 19, 15, 3, 17, 12, 18)
i=2, j=6
Sensul de parcurgere:
i=2, j=6 10<17 j=j-1
i=2, j=5 10>3 se efectueaz interschimbarea i se atribuie i=i+1=3
v = (4, 3, 19, 15, 10, 17, 12, 18)
i=3, j=5
Sensul de parcurgere:
i=3, j=5 19>10 se efectueaz interschimbarea i se atribuie j=j-1=4
81
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
v=(4, 3, 10, 15, 19, 17, 12, 18)
i=3, j=4
Sensul de parcurgere:
i=3, j=4 10<15 j=j-1
i=3, j=3 i=j, poziionare realizat
b) Se obine vectorul:
v=(4, 3, 10, 15, 19, 17, 12, 18)
1 2 3 4 5 6 7 8
poz=3, se lucreaz cu secvenele
(4, 3) i (15, 19, 17, 12, 18)

Primul nivel de recursie:
Pentru Sv1=(4, 3) p=1, u=2
a1) poziionarea lui 4:
i=1, j=2
Sensul de parcurgere:
i=1,j=2 4>3 se efectueaz interschimbarea i se atribuie i=i+1=2
sv1 (3, 4) , poz=2
i=j=2, stop
b1) se ajunge la scevenele (3) i ; acestea sunt sortate
Pentru sv2 = (15, 19, 17, 12, 18)
4 5 6 7 8
a1) poziionarea lui 15
i=4, j=8
Sensul de parcurgere:
i=4, j=8 15<18 j=j-1=7
i=4, j=7 15>12 se efectueaz interschimbarea i se atribuie i=i+1=5
sv2=(12, 19, 17, 15, 18)
4 5 6 7 8
i=5, j=7
Sensul de parcurgere:
i=5, j=7
19>15 se efectueaz interschimbarea i se atribuie j=j-1=6
sv2=(12, 15, 17, 19, 18)
4 5 6 7 8
i=5, j=6
Sensul de parcurgere:
i=5, j=6 15<17 j=j-1
i=5, j=5 i=j poziionare realizat
sv2=(12, 15, 17, 19, 18)
4 5 6 7 8 poz = 5
b1)Se obine secvena sv2=(12, 15, 17, 19, 18)
4 5 6 7 8
poz=5; se lucreaz mai departe cu secvenele
82
Algoritmi recursivi. Metodele divide et impera i backtracking
sv3=(12) sortat
sv4=(17, 19, 18)
6 7 8
n acest moment, v=(3, 4, 10, 12, 15, 17, 19, 18)

Al doilea nivel de recursie - avem numai secvena
sv4=(17, 19, 18)
6 7 8
a2) poziionarea lui 17
i=6, j=8
Sensul de parcurgere:
i=6, j=8 17<18 j=j-1=7
i=6, j=7 19<19 j=j-1=6
i=j=6 - poziionare realizat
b2) Se obine sv4=(17, 19, 18), poz=6,
6 7 8
se lucreau mai departe cu secvenele
sv5= sortat
sv6=(19, 18)
7 8
n acest moment v=(3, 4, 10, 12, 15, 17, 19, 18)

Al treilea nivel de recursie - avem numai secvena
sv6=(19, 18)
7 8
a3) poziionarea lui 19
i=7, j=8
Sensul de parcurgere:
i=7, j=8 19>18 se interschimb i i=i+1=8
sv6=(18,19)
i=j=8, poziionare realizat
b3) S-a obinut secvena sv6=(18, 19), poz=8
Urmtoarele secvene sunt sv7=(18), sv8= , ambele sortate
Calculul se ncheie, v=(3, 4, 10, 12, 15, 17, 18, 19) este sortat cresctor.
program quick_sort;
uses crt;

var
x:array[1..100] of integer;
n,i:byte;

procedure poz(p,u:byte; var k:byte);
var
i,j:byte;
l,di,dj:shortint;
{di, dj: pasii de incrementare pentru i si j;
ei indica sensul parcurgerii}
v:integer;
83
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
begin
i:=p;j:=u;di:=0;dj:=-1;
while i<j do
if x[i]>x[j] then
begin
v:=x[i];
x[i]:=x[j];
x[j]:=v;
l:=di;di:=-dj;dj:=-l;
i:=i+di;j:=j+dj;
end
else begin
i:=i+di;j:=j+dj;
end;
k:=i;
end;

procedure quick(p,u:byte);
var
i:byte;
begin
if p>=u then
else begin
poz(p,u,i);
quick(p,i-1);
quick(i+1,u);
end;
end;

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

n programul quick_sort, pentru simularea sensurilor de parcurgere, s-a
lucrat cu incremeni pentru i i j, desemnai prin di, respectiv dj. Pentru sensul de
parcurgere (de la sfritul secvenei spre nceputul ei) i rmne constant (di=0)
i j este decrementat cu o unitate (dj=-1). Pentru cellalt sens, j rmne constant
(dj=0) i este incrementat i (di=1). Trecerea de la un sens la cellalt, efectuat n
momentul unei interschimbri, determin secvena de operaii:
l=dj;
di=dj;
dj=-l;
adic di este interschimbat cu dj. Vectorul de sortat x este variabil global
procedurii quick.

Soluiile recursive propuse n exemplele precedente se bazeaz fie pe o metod
de tip reducere, fie pe o metod de descompunere. n toate cazurile a fost posibil
sinteza unei soluii a problemei date din soluiile subproblemelor la care problema
84
Algoritmi recursivi. Metodele divide et impera i backtracking
s-a redus, respectiv n care s-a descompus. De asemenea, pentru fiecare dintre
problemele considerate au fost definite subproblemele primitive (condiiilor
terminale) a cror soluie este cunoscut sau dat. Metoda de rezolvare se numete
divide et impera (dezbin i stpnete) i semnific ideea prin care este realizat
construcia soluiei.



5.3 Metoda backtracking


Pentru rezolvarea anumitor probleme este necesar desfurarea unui proces
de cutare a soluiei aflate ntr-o anumit mulime, numit spaiul strilor. Pentru
fiecare element din spaiul strilor este definit o mulime de aciuni sau alternative.
Momentul iniial n rezolvarea problemei corespunde unei stri, numit iniial, iar
soluiile corespund drumurilor n spaiul strilor, de la cea iniial pn la una final.
Procesul de rezolvare a problemei poate fi imaginat ca o secven de aciuni care
asigur deplasarea (prin intermediul unei secvene de stri) n spaiul strilor din
starea iniial la cea final. n cazul anumitor probleme se dorete obinerea unei
singure soluii, altele solicit determinarea tuturor soluiilor sau determinarea unei
soluii optime, dintr-un anumit punct de vedere (soluie optimal).
Se presupune c problema const n a ajunge n vrful unui munte pornind de
la baza lui. n general, exist mai multe puncte din care se desprind mai multe poteci,
dar nu neaprat toate conduc spre vrful muntelui. n acest caz, starea iniial este
baza muntelui, exist o singur stare final i anume vrful muntelui, spaiul strilor
incluznd i toate punctele de ramificare a drumului. O soluie poate fi apreciat ca
optimal din mai multe puncte de vedere: un drum care solicit cel mai mic efort din
partea celui care-l urmeaz; un cel mai scurt drum; un drum care trece printr-un
punct preferat etc.
Un alt exemplu este un labirint avnd una sau mai multe ieiri. Starea iniial
poate fi considerat orice camer a labirintului, problema revenind la gsirea unui
drum din camera respectiv ctre una dintre ieiri. Desfurarea procesului de cutare
a unei stri finale presupune, la fiecare etap, alegerea opiunii pentru o alternativ
posibil a strii curente i detectarea acelor stri capcan din care nu mai este
posibil continuarea procesului, sau deja se cunoate excluderea atingerii unei stri
finale. Detectarea strii capcan trebuie s determine revenirea la starea din care
s-a ajuns la ea i selectarea unei noi opiuni de continuare. n cazul n care nu mai
exist alternative care s nu fi fost selectate anterior, o astfel de stare devine la rndul
ei capcan i pentru ea se aplic acelai tratament.
Prin soluie a problemei se nelege o secven de aciuni care determin
tranziia din starea iniial ntr-o stare final, fiecare component a unui drum soluie
reprezentnd o alternativ din mulimea de variante posibile. Cu alte cuvinte, x
1
este
alternativa aleas pentru starea iniial, x
2
este alternativa selectat pentru starea n
85
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
care s-a ajuns pe baza opiunii x
1
.a.m.d. Dup efectuarea aciunii corespunztoare
alegerii alternativei x
n
rezult o stare final.
Forma standard a metodei corespunde unei probleme n care trebuie gsit un
drum soluie x=(x
1
, x
2
, ..., x
n
) cu x
i
S
i
, unde fiecare mulime S
i
este finit i conine
s
i
elemente. n plus, se presupune c fiecare S
i
este ordonat i reprezint mulimea
alternativelor existente la momentul i al cutrii.
n anumite cazuri intereseaz obinerea unei singure soluii, n altele sunt
cutate toate soluiile problemei sau cele care ndeplinesc un criteriu dat (de
exemplu, se maximizeaz sau minimizeaz o funcie f definit pe mulimea
drumurilor soluie din spaiul strilor).
Procesul de cutare a unui drum soluie revine la tentativa de extindere a
poriunii de drum construit, alegnd prima alternativ disponibil pentru starea
curent atins. Continuarea drumului poate fi realizat pn la atingerea unei stri
finale sau pn la ntlnirea unei stri capcan (mulimea vid de alternative). Dac
este atins o stare capcan, atunci este necesar revenirea la starea anterioar i
selectarea urmtoarei alternative disponibile acestei stri. Dac nu mai exist
alternative disponibile, atunci se iniiaz o nou revenire .a.m.d. n cazul n care
exist cel puin nc o alternativ disponibil, atunci se reia procesul de extindere a
drumului rezultat. n condiiile n care revenirea poate conduce la atingerea strii
iniiale i pentru ea nu mai exist alternative disponibile, se consider c problema nu
are soluie.
Pentru implementarea cutrii este necesar reinerea alternativei selectate
pentru fiecare stare atins pn la cea curent, astfel nct, n cazul unei reveniri s
fie posibil alegerea alternativei urmtoare. Cu alte cuvinte, procesul de cutare
revine la tentativa de extindere a drumului curent (pasul de continuare), cu eventuala
revenire n cazul atingerii unei stri capcan (pasul de revenire - back), memornd
alternativele selectate pentru fiecare stare intermediar atins (track). De aici i are
geneza numele metodei backtracking.

Pentru determinarea unei singure soluii, descrierea pe pai a metodei este:
starea iniial a problemei este prima alternativ posibil pentru starea
curent ; fie aceasta x
1
S
1
;
dac starea curent rezultat prin alternativa x
1
este final, atunci x=(x
1
)
este soluie; stop;
altfel, este selectat prima alternativ din mulimea de aciuni posibile
pentru starea curent; fie aceasta x
2
S
2
;
dac secvena de alternative care a condus la starea curent este
x=(x
1
, x
2
,..., x
k
), atunci:
dac starea curent este final, soluia este x=(x
1
, x
2
,..., x
k
); stop;
altfel
B1: dac pentru starea curent exist alternative disponibile,
atunci se alege prima dintre ele i se continu;
86
Algoritmi recursivi. Metodele divide et impera i backtracking
B2: altfel, se revine la starea anterioar celei curente, soluia
parial construit devine x=(x
1
, x
2
,..., x
k-1
) i se efectueaz B1.
dac, n urma unui pas de revenire, s-a ajuns la starea iniial i nu
mai sunt alternative disponibile, atunci problema nu are soluie; stop.

n cazul n care trebuie determinate toate soluiile problemei, cutarea
continu dup determinarea fiecrei soluii prin efectuarea de reveniri succesive.
Terminarea cutrii este decis n momentul n care s-a revenit la starea iniial i nu
mai exist alternative disponibile.
Dac se dorete obinerea numai a soluiilor care optimizeaz o funcie
criteriu f, atunci metoda se aplic pentru determinarea tuturor soluiilor problemei,
fiecare nou soluie rezultat fiind comparat cu cea mai bun soluie determinat
anterior. Pentru aceasta este necesar reinerea celei mai bune soluii calculate la
fiecare moment.
Forma general a metodei backtracking este implementat de procedura
back.

procedure back(k:byte);
begin
if k=n+1 then final
else
begin
x[k]:=init(k);
while succ(k) do
if continuare(k) then back(k+1);
end;
end;

n care:
final este o procedur care descrie prelucrarea dorit pentru o soluie
determinat (se afieaz rezultatul, se testeaz o funcie criteriu pentru soluia
obinut samd);
init(k) efectueaz iniializarea lui x
k
cu o valoare prin care se indic faptul
c, pn la acel moment, nu a fost selectat nici o alternativ pentru poziia k;
succ(k) este o funcie boolean care calculeaz true, dac i numai dac
exist succesor pentru x
k
n S
k
;
continuare(k) este o funcie boolean pentru testarea condiiilor de
continuare; calculeaz true dac i numai dac este posibil extinderea drumului
curent.

n continuare sunt prezentate cteva probleme rezolvate prin metoda
backtracking.

1. S se genereze toate permutrile mulimii {1, 2,..., n}.
n acest caz, S
1
= S
2
= ... = S
n
= {1, 2,..., n}. Alternativele posibile pentru
starea iniial corespund alegerilor pentru prima poziie dintr-un vector soluie.
Pentru fiecare k, 1 n k 1 , dac x=(x
1
, x
2
,..., x
k
) este drumul calculat pn la
87
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
momentul k, atunci k j i 1 , x x
j i
i alternativele posibile pentru starea
curent sunt elementele x
k+1
din mulimea {1, 2,..., n}care ndeplinesc cerina
k i 1 , x x
1 k i

+
.
De exemplu, pentru n=3, soluiile problemei sunt:
x1=(1,2,3), x2=(1,3,2), x3=(2,1,3), x4=(2,3,1), x5=(3,1,2), x6=(3,2,1).

Funcia init(k) realizeaz iniializarea elementului x[k] cu valoarea 0, pentru
a marca faptul c, pn la momentul curent, nu a fost selectat nici o alternativ
pentru x[k]. Funcia succ(k) calculeaz true dac elementul x[k] are succesor n
mulimea {1, 2,..., n}, caz n care acesta este determinat prin incrementare. Altfel,
funcia calculeaz false. Funcia continuare(k) returneaz true dac i numai dac
secvena (x
1
, x
2
,..., x
k
) calculat pn la momentul curent este corect, conform
regulilor descrise anterior.
Conform schemei generale, programul Pascal este:

program permutare;
uses crt;
type tip_elem=0..7;
var x:array[1..7] of tip_elem;
n:byte;

function init:byte;
begin
init:=0;
end;

function succ(k:byte):boolean;
begin
succ:=x[k]<n; {atribuire de valoare logica}
inc(x[k]);
end;
function continuare(k:byte):boolean;
var i:byte;
begin
i:=1;
while(i<k)and(x[i]<>x[k]) do inc(i);
continuare:=i=k; {atribuire de valoare logica}
end;

procedure final;
var i:byte;
begin
for i:=1 to n do write(x[i],' ');
readln;
end;

procedure back(k:byte);
begin
if k=n+1 then final
else
begin
x[k]:=init;
while succ(k) do
if continuare(k) then back(k+1);
88
Algoritmi recursivi. Metodele divide et impera i backtracking
end;
end;

begin
clrscr;
write('Numarul de elemente ale permutarii: ');
readln(n);
back(1);
end.
n cazul acestei probleme este posibil operarea unor simplificri n scrierea
codului, pe baza observaiilor:
- funcia init(k) nu depinde de valoarea lui k i returneaz ntotdeauna
valoarea 0;
- funcia succ(k) nu depinde de valoarea parametrului k i realizeaz
ntotdeauna o incrementare (S
1
= S
2
= ... =S
n
= {1, 2,..., n}).
Procedura back(k) poate fi descris fr a utiliza funciile init i succ, astfel:

procedure back(k:byte);
var i:byte;
begin
if k=n+1 then final
else
for i:=1 to n do
begin
x[k]:=i;
if continuare(k) then back(k+1);
end;
end;
nlocuirea n procedura back a structurii repetitive while cu ciclul for este
posibil datorit faptului c funcia succ realiza incrementarea valorii elementului
x[k].

Varianta de program Pascal rezultat n urma acestor simplificri este:

program permutare_1;
uses crt;
type tip_elem=0..7;
var x:array[1..7] of tip_elem;
n:byte;

procedure final;
var i:byte;
begin
for i:=1 to n do write(x[i],' ');
readln;
end;

function continuare(k:byte):boolean;
var i:byte;
begin
i:=1;
while(i<k)and(x[i]<>x[k]) do inc(i);
continuare:=i=k;
end;

procedure back(k:byte);
89
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
var i:byte;
begin
if k=n+1 then final
else
for i:=1 to n do
begin
x[k]:=i;
if continuare(k) then back(k+1);
end;
end;

begin
clrscr;
write('Numarul de elemente ale permutarii: ');
readln(n);
back(1);
end.

2. Se presupune c se dispune de n tipuri de bancnote, n20, cu valori
diferite; din fiecare tip se dispune de un numr cunoscut de bancnote. Considern-
du-se dat o sum de bani s, s se determine o modalitatea de plat a sa utilizndu-se
un numr minim de bancnote.
Valorile i numrul de bancnote disponibile din fiecare tip sunt memorate
ntr-o tabel y cu 2 linii i n coloane, astfel: pentru fiecare 1 n i , y[1,i] reprezint
valoarea unei bancnote de tipul i i y[2,i] este numrul de bancnote disponibile din
tipul i. Vectorul xb memoreaz modalitatea optim de plat a sumei s, adic xb[i]
reprezint numrul de bancnote alese din tipul i ntr-o descompunere optim;
vectorul x memoreaz descompunerea curent. Numrul minim de bancnote utilizate
n plata sumei s este nrb.
Metoda utilizat n rezolvarea problemei este backtracking, urmrindu-se
minimizarea funciei

=
=
n
1 i
] i [ x ) x ( f , n condiiile n care s ] i , 1 [ y ] i [ x
n
1 i
=

=
i
n ,..., 1 i ], i , 2 [ y ] i [ x 0 = . Sunt generate toate descompunerile posibile ale sumei
s funcie de bancnotele disponibile i, la fiecare moment n care este determinat o
astfel de descompunere, aceasta este comparat cu precedenta. n vectorul xb este
memorat o cea mai bun descompunere pe baza criteriului f, dup fiecare astfel de
comparaie.

program bancnote;
uses crt;

var x,xb:array[1..100] of longint;
y:array[1..2,1..20]of longint;
n,i,nrb:word;
s:longint;

function init(k:word):longint;
begin
init:=-1;
end;

function urm(k:word):boolean;
begin
90
Algoritmi recursivi. Metodele divide et impera i backtracking
urm:=x[k]<y[2,k];inc(x[k]);
end;

function continuare(k:word):boolean;
var
sc,i:longint;
begin
sc:=0;
for i:=1 to k do sc:=sc+x[i]*y[1,i];
if k<n then continuare:=sc<=s
else continuare:=sc=s;
end;
procedure final(k:word);
var i:byte;
nr:longint;
begin
nr:=0;
for i:=1 to n do
begin
nr:=nr+x[i];
end;
if nr<nrb then
begin
for i:=1 to n do xb[i]:=x[i];
nrb:=nr;
end;
end;

procedure back(k:byte);
begin
if k=n+1 then final(k)
else
begin
x[k]:=init(k);
while urm(k) do
if continuare(k) then back(k+1)

end;
end;

begin
clrscr;
write('Dati numarul de bancnote');
readln(n);
writeln('Valorile si numarul de exemplare:');
for i:=1 to n do
begin
write('Valoarea:');readln(y[1,i]);
write('Numar de bancnote:');readln(y[2,i]);
end;
write('Suma schimbata:');
readln(s);
nrb:=maxint;
back(1);
writeln('Numarul minim de bancnote:',nrb);
writeln;
writeln('Numarul de bancnote alese din fiecare tip:');
for i:=1 to n do
writeln('Tip ',i,' numar de bancnote alese:',xb[i]);
end.

91









Forma i formatul afirii datelor pe monitor (ca ecou al introducerii de la
tastatur sau ca rezultat al scrierii) precum i modul n care se desfoar conversaia
n timpul acestui proces constituie interfaa programului cu utilizatorul. Realizarea
unei interfee eficiente i atractive trebuie s constituie pentru programator un
obiectiv la fel de important ca i cel al atingerii performanelor ridicate de eficien a
programului nsui.



6.1 Resursele i modurile de lucru video
ale unui microcalculator


n procesul afirii video a datelor sunt implicate componente hardware i
software, care interacioneaz pentru crearea imaginii pe ecranul monitorului
(figura 6.1).


Fig. 6.1 Componente implicate n afiarea video a datelor
Interfaa video
(Logic de comand)
Memoria ecran
Software
Monitor
Placa grafic


Memoria ecran, de tipul RAM, are rolul de a stoca, sub form binar,
imaginea care se afieaz pe ecran. Ea poate avea diferite capaciti - uzual, pn la 1
REPREZENTAREA VIZUAL
A DATELOR
92
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
MB i este mprit n pagini de o anumit mrime, n care se pot memora
concomitent una sau mai multe imagini de ecran. n plus, se pot memora definiiile
binare ale unor seturi de caractere pentru afiarea textelor cu modele de caractere
(fonturi) ale utilizatorului, altele dect cele definite de generatorul de caractere al
interfeei video.
Interfaa video (adaptorul video) are rolul de a comanda i controla
monitorul pentru crearea imaginii pe tub catodic. Ea comunic cu UC a
microcalculatorului i cu memoria ecran prin magistrale de date i de adrese. UC i
interfaa pot utiliza simultan memoria ecran (prin porturi diferite), astfel nct
microprocesorul poate nscrie date n memoria ecran n timp ce interfaa citete
memoria pentru a realiza afiarea (figura 6.2).


Fig. 6.2 Modul de interaciune a interfeei video
Microproceso
r
Memoria
ecran
Magistrala de date
Magistrala de adrese
Controler
video
Monitor
Generator
de semnale
Registru de
deplasare
Generator
de caractere
Sincronizare
Interfa video
Semnale de comand


Controlerul video (logica de comand) al interfeei citete periodic, cu o
anumit frecven, memoria de ecran i formeaz semnalele de comand pentru
monitor n vederea crerii i meninerii imaginii video. Dac frecvena de refacere a
imaginii pe ecran (frecvena de remprosptare) este de peste 50 Hz (de obicei
50-70 Hz), atunci, datorit ineriei ochiului, imaginea apare ca fiind continu i fr
plpiri.
Generatorul de caractere este dispozitivul interfeei care produce imaginile
(matricele) punctiforme ale caracterelor ASCII de afiat. Prin comanda dat de
controler i utiliznd caracterele ASCII citite din memoria ecran, generatorul de
caractere produce, la ieire, matricele discrete care definesc caracterele. Pe baza lor i
a atributelor de afiare asociate, aduse de controler din memoria de ecran, generatorul
de semnale produce semnalele seriale care comand monitorul. Serializarea n
producerea semnalelor este asigurat prin intermediul unui registru de deplasare care
furnizeaz, pe rnd, cte un element de imagine.
93
Reprezentarea vizual a datelor
Monitorul utilizeaz un tub catodic monocrom sau color i creeaz
imaginea pe ecran, de sus n jos. Fascicolul de electroni aprinde, pe rnduri sau
linii, puncte elementare din suprafaa fluorescent a tubului catodic, n conformitate
cu semnalele discrete de comand trimise de sistemul de baleere a ecranului.
Punctele elementare de imagine sunt denumite pixeli (picture elements) i
apar pe monitor organizate matriceal, definind spaiul fizic sau spaiul ecran
(figura 6.3). n acest spaiu, pixelii pot fi adresai printr-o pereche de numere naturale
(x, y), unde x este numrul coloanei i y este numrul liniei. De remarcat faptul c, n
acest spaiu, abscisa crete normal, de la stnga spre dreapta, dar ordonata crete de
sus n jos.

Fig. 6.3 Spaiul ecran
x
y
(0,0)
(x,y)










(x
max
,y
max
)


Numrul total de pixeli care pot fi tratai independent constituie o
caracteristic a monitorului, denumit rezoluia ecranului. Rezoluia poate fi joas
(cca.320 x 200 pixeli), medie (cca.640 x 200 pixeli) i nalt (peste 640 x 350 pixeli).
Interfeele video sunt proiectate astfel nct pot lucra cu monitoare de diferite
rezoluii, pentru un monitor simulnd toate rezoluiile inferioare celei date. Imaginea
este cu att mai clar cu ct rezoluia utilizat n realizarea ei este mai mare. De
regul, n construcia microcal culatoarelor, interfaa video i memoria de ecran sunt
realizate pe o plac unic, numit plac grafic. Puterea plcii grafice este cea care
d, n principal, puterea de afiare a datelor pe ecran. n prezent, microcalculatoarele
sunt echipate cu plci grafice de mare putere, de tipul SVGA (Super Video Graphic
Array), realizate dup standardul firmei IBM pentru utilizatori profesionali. Ele sunt
compatibile cu plci realizate anterior (MDA, CGA i EGA), al cror mod de lucru l
pot realiza, oferind n plus o rezoluie nalt i o palet bogat de culori i nuane de
gri (pentru monitoare monocrome).
Partea de software implicat n afiarea video are rolul de a comanda
interfaa video n realizarea diferitelor operaii necesare afirii: alegerea modului de
afiare - text sau grafic - definirea poziiei spaiului ecran pentru afiare, definirea
atributelor de afiare etc. Ea este constituit din rutine BIOS multifuncionale (cu mai
multe servicii) care se apeleaz prin intermediul tehnicii ntreruperilor software.
Tipic este INT 10h, care ofer o serie de servicii video standard. n program, nainte
de cererea ntreruperii, codul serviciului dorit trebuie ncrcat ntr-un registru special
94
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
(AH), iar ali parametri, dac sunt necesari, se ncarc n alte registre (AL, BH, BL,
DH, DL).



6.2 Moduri video


Din punctul de vedere al constituirii imaginii, interfaa video poate lucra n
dou moduri: text i grafic.
n modul text, ecranul este vzut ca o matrice de linii i coloane de text.
Locul de afiare a unui caracter n spaiul ecran este dat de o pereche (x,y) de numere
naturale, cu x=numrul coloanei i y=numrul liniei (figura 6.4.a).


Fig. 6.4 Ecranul n modul text
x
(nr. coloan)
y
(nr. linie)
caracter
0 1 2
0
1
l
max

c
max

ecran 25*80
l
max
=24
l
max
=24
c
max
=79
c
max
=39
ecran 25*40
a) Spaiul
######
######
#####
#####
#####
####
#####
####
#####
#####
#####
######
######
########
b) Matricea de caractere
8
14


Deoarece spaiul text rezult prin gruparea corespunztoare a liniilor i
coloanelor de pixeli, afiarea caracterelor se face, n mod natural, prin matrice de
caractere (figura 6.4.b). O astfel de matrice, de regul 8x14 sau 8x8, definete forma
caracterului prin pixelii aprini, iar fondul prin pixelii stini. n fondul caracterului se
cuprind pixeli de separare a caracterelor pe coloane i linii. Caracterele realizate
astfel se numesc caractere matriceale sau rastru. De regul, n memoria ROM a
calculatorului se definesc patru seturi de caractere, avnd forme (fonturi) tipice
(scriere standard, caractere italice etc). La pornirea calculatorului sau la cererea
95
Reprezentarea vizual a datelor
programatorului, ele sunt ncrcate n memoria de ecran pentru a fi accesibile
generatorului de caractere. Un anumit set, implicit sau cerut de utilizator (via INT
10h), va deveni set curent pentru generator. Exist posibilitatea ca programatorul
s-i defineasc n memoria calculatorului propriile seturi de caractere (cel mult patru
odat), pe care s le ncarce n memoria ecran i din care, apoi, s defineasc setul
curent (ambele sunt servicii INT 10h).
Datorit adresabilitii spaiului text, exist posibilitatea de a comanda (INT
10h) poziia de afiare a unui caracter. n acest scop, interfaa pstreaz n registre
speciale coordonatele locului de afiare, iar pe ecran acesta este marcat prin afiarea
unui caracter special, denumit cursor (de regul, un dreptunghi umplut sau luminos).
Atunci cnd se afieaz un caracter n poziia de la cursor (poziia curent), acesta se
suprascrie peste cursor, iar cursorul este mutat automat cu o poziie spre dreapta i n
jos, la nceputul noului rnd, dac este cazul. Prin servicii ale rutinei INT 10h se
poate defini o form proprie a cursorului n modul text i se poate afla locul acestuia
pe ecran.
Fiecrui caracter de afiat i se asociaz un caracater de atribute (figura
6.5.a).

Fig. 6.5 Definirea atributelor de afiare
a) caracter de atribute b) registru de palet
7 6 5 4 3 2 1 0
Culoare de
fond
Culoare de
caracter
Intensitatea
culorii
(1=da, 0=nu)
Clipire
(1=da, 0=nu)
byte 0 1 2 ... 15

culoare negru albastru ... alb

cod 0 1 ... 53


Caracterul de atribute, prin valorile biilor si, definete culoarea de fond a
caracterului (background color), culoarea de caracter (foreground color) i faptul c
imaginea caracterului se va stinge intermitent (clipire - blinking). Se observ c se
pot defini cel mult 8 culori pentru fond i 16 culori de caracter, dac se consider c
afiarea normal i intens definesc dou culori diferite. Dac ecranul este
monocrom, atunci se pot combina culorile alb i negru.
Pentru variabilitate n exprimarea culorilor i pentru asigurarea
independenei fa de conveniile de notare a lor la diverse plci grafice, s-a adoptat
ideea specificrii indirecte a culorilor. Interfaa posed un registru, de regul de
16 octei, denumit registru de palet, prin care se specific culorile care pot fi
utilizate la un moment dat (figura 6.5.b). Fiecare poziie din registrul de palet
definete, prin cod, o culoare i, n ansamblu, constituie paleta curent de culori.
96
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Astfel, n caracterele de atribute se specific numrul intrrii din paleta curent
(index), de unde trebuie extras codul culorii dorite. Pe baza acestei idei, n orice
moment, poate fi modificat coninutul registrului de palet (serviciu INT 10h), ceea
ce conduce, n mod automat, la modificarea culorilor pentru ntregul text afiat pe
ecran. La pornirea calculatorului, registrul de palet este ncrcat cu o palet iniial
(implicit), definit n memoria ROM. Programatorul poate schimba, total sau
parial, culorile n registrul de palet, depinznd de tipul plcii grafice i aceasta este
unica operaie pentru care trebuie cunoscute codurile culorilor la placa respectiv.
Trebuie remarcat c unele monitoare nu pot afia toate culorile, dei interfaa cu care
sunt cuplate accept specificarea oricrui atribut.
Definirea caracterului de atribute se face prin serviciul INT 10h, care
realizeaz scrierea caracterului text ca parametru ntr-un registru (registrul BL).
Scrierea unui caracter poate fi nsoit de operaia SAU EXCLUSIV (suma
modulo-2, notat ) ntre culoarea caracterului afiat ntr-o anumit poziie i
culoarea noului caracter, destinat a fi afiat n aceeai poziie. Operaia poate fi
utilizat pentru scrierea i tergerea caracterelor (tergerea selectiv). De exemplu,
pentru tergere, dac culoarea este 0101 i se aplic o suprascriere cu aceeai culoare,
atunci, cum 01010101=0000, se obine un cod care desemneaz culoarea fondului
curent, adic, de fapt, dispariia caracterului de pe ecran.
Avnd n vedere c necesarul de memorie ecran este n jur de 4KB 25*80,
depinznd de rezoluia n modulul text, n memoria video se pot focaliza una sau mai
multe pagini video (ecrane). Se creeaz posibilitatea constituirii textului ntr-o
anumit pagin, denumit pagin video, selectat din mulimea paginilor acceptate
de interfaa respectiv prin serviciul INT 10h. Orice poziie i deplasare a cursorului
pe ecran i are echivalentul ntr-o poziie i o deplasare corespunztoare n pagina
video selectat. Din mulimea paginilor definite, programatorul poate selecta una, ca
pagin de afiare pe ecran, denumit pagin activ. Astfel crete viteza de lucru prin
suprapunerea operaiei de afiare cu operaia de pregtire a imaginii, ntr-o nou
pagin video. Interogarea, prin INT 10h, n legtur cu atributele unui anumit
caracter al imaginii este, de fapt, o citire din pagina video a memoriei ecran, eventual
pagina activ.
Modul text permite definirea, n pagina activ, a ferestrelor de text. O
fereastr text este o zon de afiare, format din una sau mai multe linii i coloane
consecutive. Ferestrele text se definesc i se selecteaz prin INT 10h. Definirea se
realizeaz prin precizarea coordonatelor din spaiul text ale colului stnga sus i
respectiv ale colului dreapta jos. n fereastr se poate realiza o operaie de defilare n
sus (jos) care deplaseaz textul rndurilor cu un numr de poziii n sus (jos) i umple
rndurile eliberate, la partea de jos (sus), cu caracterul blank (tergere). Se pot scrie
rnduri noi de text n rndurile eliberate, eventual n toat fereastra activ. Rndurile
de text care ies din fereastr, prin defilare, se pierd. La limit i n mod implicit,
fereastra text este ntreaga pagin activ.
n modul grafic, imaginea se constituie prin aprinderea mulimilor de pixeli
(desen prin puncte - pixel mode). Imaginea se creeaz n memoria ecran, n pagini,
dac placa grafic permite mai multe pagini i se afieaz pe ecran, pagin cu pagin.
97
Reprezentarea vizual a datelor
O pagin video utilizeaz un bit pentru a defini starea fiecrui pixel al ecranului
(1=aprins, 0=stins) i un numr de bii suplimentari pentru a defini culoarea
acestora. Deoarece culorile se definesc pe baza registului de palet, dac se
utilizeaz concomitent 16 culori, sunt necesari 4 bii suplimentari. Rezult c o
pagin video trebuie s aib cel puin 4rezoluie bii. De exemplu, pentru o plac
EGA, cu rezoluie nalt, sunt necesari 4640350=896000 bii110 Kb i deci,
ntr-o memorie ecran de 256 Kb, pot fi create dou pagini video.
Modul grafic utilizeaz posibilitatea de adresare a pixelilor ntr-o pagin
video i un cursor grafic invizibil. Cursorul grafic are coordonatele ultimului pixel
adresat n pagina video selectat i poate fi deplasat n orice punct al acestui spaiu.
Se menin, de asemenea, facilitile de interogare asupra poziiei cursorului i asupra
culorii pixelului curent.
Ca i la modul text, la definirea unui pixel exist posibilitatea realizrii
operaiei SAU EXCLUSIV ntre biii de culoare ai unui pixel dintr-o pagin i
valorile noi ale acestora. n acest fel, pixelii pot fi scrii sau teri.
Toate aceste operaii se realizeaz ca servicii ale rutinei INT 10h. n modul
grafic, se selecteaz un anumit submod acceptat de placa grafic, submodurile
diferind prin rezoluie, numr de culori i numr de pagini de ecran pe care le
accept.



6.3 Faciliti de scriere a textelor prin unitatea CRT


n Pascal, operaiile de afiare pe monitor, n modul text, au fost
implementate n dou uniti de program: SYSTEM i CRT. Unitul SYSTEM
definete operaia de afiare pe monitor n mod standard, adic cu atribute de scriere
implicite i ncepnd din poziia curent a cursorului. Unitul CRT (anexa 3) definete
variabile, funcii i proceduri prin care programatorul poate defini i controla
contextul de scriere (ferestre, culori, poziie de scriere etc.)
Alegerea modului text. Programatorul are posibilitatea de a alege un
anumit mod de scriere, caracterizat, n principal, prin rezoluia de afiare i tipul de
monitor: monocrom sau color. Sunt acceptate modurile prezentate n anexa 3. Pentru
alegerea modului se apeleaz procedura:

TextMode (Mode);

n care parametrul Mode, de tip Word, definete modul dorit, prin numrul asociat.
Procedura salveaz vechiul mod n variabila predefinit LastMode, de unde, prin
aceeai procedur, poate fi restaurat. Procedura seteaz culoarea de fond zero
(culoarea neagr). Dac nu se apeleaz TextMode, atunci, implicit, se consider
modul de mare rezoluie al plcii grafice.
98
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Exemplu:
6.1.
. . .
User CRT;
. . .
TextMode(C080);
. . .
TextMode(LastMode);
. . .
TextMode(BW40)


Stabilirea culorii de fond i de scriere se face prin referire la paleta
implicit. Intrrile n palet, desemnate prin constante ntregi sau constante
simbolice, sunt asociate cu diferitele culori (anexa 3). Definirea culorii fondului se
face prin apelul procedurii:
TextBackGround(culoare);
n care parametrul culoare este de tipul Byte i poate avea valorile 0-7. Procedura
trateaz biii 4-6 ai unei variabile predefinite TextAtrr de tip Byte, prin care se
modific corespunztor octetul de atribute din memoria video.
Culoarea de scriere se definete prin apelul procedurii:
TextColor (culoare);
n care parametrul culoare poate s aib o valoare ntre 0 i 15 (anexa 2), eventual
mrit cu 128. Procedura modific biii 0-3 i 7 ai variabilei TextAtrr, scriind n
bitul 7, pentru definirea clipirii, 1 sau 0, dup cum a fost adunat sau nu constanta
128 (constanta simbolic corespunztoare este Blink).

Exemplu:
6.2.
. . .
TextColor (Red+128);
. . .
TextColor(Green+Blink);
. . .
Culoare:=6
. . .
TextColor(Culoare);

Programatorul poate controla intensitatea culorii, prin modificarea bitului 3
din variabila TextAtrr (ters de ctre TextColor) prin procedurile fr parametri:
HighVideo - intensitate mrit (bitul 3 are valoare 1);
LowVideo - intensitate mic (bitul 3 are valoare 0);
NormVideo - intensitate implicit.
Execuia procedurilor pentru stabilirea culorii de fond i de scriere afecteaz
numai fereastra curent. Atributele rmn valabile pn la o nou definire sau pn la
terminarea execuiei programului.
Definirea unei ferestre de scriere. Scrierea textului pe ecran se poate
realiza ntr-o anumit zon a acestuia, denumit fereastr curent de scriere (text
99
Reprezentarea vizual a datelor
window). O fereastr se definete ca un dreptunghi, prin coordonatele colurilor
stnga-sus, dreapta-jos. Ecranul ntreg este o fereastr de coordonate (1, 1, 80, 25)
sau (1, 1, 40, 25) etc., depinznd de modul text. Declararea ferestrei se face prin
procedura:
Window(x1, y1, x2, y2);
n care parametrii (de tipul Byte) definesc, n ordine, cele dou coluri: (x1, y1) -
colul stnga-sus, (x2, y2) - colul dreapta-jos (n exprimare matriceal, abscisele
x1,x2 reprezint numerele coloanelor, iar ordonatele y1, y2 sunt numerele de linii).

Exemplu:
6.3. Window (10, 5, 70, 20); definete o fereastr care se ntinde ntre liniile
5-20 i coloanele 10-70.
Unitatea CRT definete variabilele WindMin, WindMax, de tipul Word,
care conin coordonatele colurilor ferestrei curente. Octetul cel mai semnificativ
conine numrul liniei (y), iar cel mai puin semnificativ conine numrul coloanei
(x). Coordonatele ferestrei curente pot fi scrise ca:
(Lo(WindMin), Hi(WindMin)) - colul stnga-sus
(Lo(WindMax), Hi(WindMax)) - colul dreapta-jos
Dac nu se apeleaz procedura Window, fereastra implicit este ntregul
ecran, variabilele WindMin i WindMax fiind iniializate corespunztor modului
text selectat sau implicit. Fereastra selectat rmne activ pn la un nou apel al
procedurii Window, care poate defini o nou fereastr curent, eventual una utilizat
anterior.
Poziionarea cursorului. n fereastra curent, programatorul poate s
gestioneze poziia cursorului dup necesitile programului, impunnd locul pe ecran
ncepnd cu care se va realiza scrierea urmtorului text. Poziia curent a cursorului
poate fi aflat prin apelul funciilor, fr parametri, cu rezultat de tipul Byte:
WhereX (pentru abscis) i WhereY (pentru ordonat). Mutarea cursorului ntr-o
anumit poziie a fereastrei curente poate fi comandat prin apelul procedurii:
GotoXY(X, Y);
Exemplu:
6.4.
. . .
Window(20, 3, 100, 15); TextBackGround(Red); TextColor(Blue);
ClrScr; {sterge fereastra}
Writeln (Text 1); {Se scrie pe linia 1, coloana 1 a
ferestrei (coordonatele absolute: linia 3, coloana 20)}
GotoXY(5, 6); Write (Text 2);
{Se scrie pe linia 6, coloana 5 a ferestrei (coordonatele
absolute: linia 9, coloana 25)}
X:=WhereX;
Y:=WhereY;
Write;
Writeln (X=, X, Y=, Y); {Se scrie X=11, Y=6}
Dac programatorul nu gestioneaz poziia cursorului, atunci acesta se
deplaseaz, implicit, de sus n jos i de la stnga la dreapta, pe msur ce se scrie
100
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
textul n fereastr. Cnd cursorul este la sfritul ultimului rnd al ferestrei, se
produce defilarea textului n fereastra curent.

tergerea i inserarea n fereastra curent se pot realiza utiliznd
urmtoarele proceduri fr parametri:
ClrScr - terge ferestra curent i poziioneaz cursorul pe prima linie i
coloan a acesteia;
ClrEol - terge linia curent, de la cursor pn la sfritul ei, fr a muta
cursorul;
DelLine - terge rndul pe care se afl cursorul i mut, n sus cu un rnd,
textul de sub linia tears; nu este afectat poziia cursorului;
InsLine - deplaseaz n jos, cu un rnd, textul, ncepnd cu cel pe care este
cursorul i insereaz o linie goal, n linia din fereastr pe care este cursorul. Se
pierde ultimul rnd din fereastr.
Citirea caracterelor fr ecou. Prin intermediul a dou funcii, fr
parametri, programatorul poate citi fr ecou caracterul produs de ultima tast
apsat sau poate verifica dac a fost apsat o tast. Se utilizeaz funciile:
ReadKey - funcie de tipul CHAR care rentoarce caracterul existent n
buffer-ul tastaturii; dac nu exist un astfel de caracter, atunci ateapt pn la
tastarea unui caracter;
KeyPressed - funcie de tipul BOOLEAN care rentoarce valoarea True dac
a fost apsat o tast i False altminteri.
Funcia ReadKey ntoarce codul caracterului rezultat prin apsarea tastei,
dac aceasta produce un singur cod sau primul cod (valoare zero binar), dac tasta
apsat produce dou coduri. n acest ultim caz, se obine caracterul complet dac se
fac dou apeluri succesive ale funciei Readkey.
n general, tastele F1-F12, tastele de deplasare cursor (sgei), Home, Ins,
Del, PgUp, PgDwn cnd sunt apsate singure sau simultan cu CTRL, Shift ori
ALT, produc dou coduri. Pot, de asemenea, produce dou coduri tastele de litere
sau cifre, atunci cnd sunt apsate simultan cu tasta ALT.
n legtur cu funcia KeyPressed, trebuie menionat c rspunsul este
furnizat potrivit strii buffer-ului tastaturii de la acel moment (funcia nu ateapt
apsarea pe o tast). Dac KeyPressed este TRUE, atunci ReadKey returneaz
imediat caracterul.

101
Reprezentarea vizual a datelor
Pornirea i oprirea difuzorului. Programul poate provoca producerea
sunetelor de o anumit frecven pe o durat controlabil. n acest scop sunt
prevzute procedurile:
Sound(Hz) - pornirea difuzorului care emite un sunet continuu de frecven
dat de parametrul Hz, n Hertz;
NoSound - oprirea difuzorului;
Delay(Ms) - realizarea unei ntrzieri de Ms milisecunde pn la execuia
urmtoarei instruciuni.
Controlnd corespunztor frecvena Hz i intervalul de emisie Ms al
difuzorului se poate realiza o anumit linie melodic.
Pentru cei care doresc s se iniieze n tehnica compunerii muzicii cu ajutorul
calculatorului, sunt prezentate n continuare cteva elemente de baz.
n tabelul 6.1 sunt prezentate frecvenele notelor, n patru octave consecutive
(n total sunt 7 octave numerotate 06). Se poate constata c frecvena unei note
ntr-o octav se poate estima prin dublarea frecvenei acesteia din octava imediat
inferioar. Similar, se poate deduce frecvena notelor dintr-o octav inferioar prin
njumtirea frecvenelor notelor din octava imediat superioar.
Tonul unei note poate fi alterat (mrit sau micorat) cu o jumtate de ton n
octava respectiv (note cu diez i bemol). Aceasta nseamn c frecvena unei note
oarecare i cu diez se calculeaz cu relaia: nota
i
:=0.5(nota
i+1
+nota
i
); nota
i
=1,2,4,5,6.
Notele pot avea diferite durate: ntreag, doime, ptrime, optime etc. Dac se
stabilete durata notei ntregi ca durat iniial, atunci duratele celorlalte note se
calculeaz ca o fracie corespunztoare din aceasta (1/2, 1/4, 1/8 etc.).

Tabelul 6.1 - Frecvenele notelor muzicale n diverse octave

Octava 1 Octava 2 Octava 3
(mijlocie)
Octava 4
Nota Frecvena Nota Frecvena Nota Frecvena Nota Frecvena
Do 130.81 Do 261.63 Do 523.25 Do 1046.5
Re 146.83 Re 293.66 Re 587.33 Re 1174.7
Mi 164.81 Mi 329.63 Mi 659.26 Mi 1318.5
Fa 174.61 Fa 349.23 Fa 698.46 Fa 1396.9
Sol 186.00 Sol 392.00 Sol 783.99 Sol 1568.0
La 220.00 La 440.00 La 880.00 La 1760.0
Si 246.94 Si 493.88 Si 987.77 Si 1976.5

102
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Se tie c durata unitar este determinat de tempo-ul n care trebuie
cntate notele. n tabelul 6.2, sunt redate cteva tempo-uri, exprimate n
ptrimi/minut. Din tabel rezult duratele diferitelor note, n minute, pentru un tempo,
T, dat:
D
1
=4/T; D
8
=1/2T;
D
2
=2/T; D
16
=1/4T;
D
4
=1/T; D
32
=1/8T etc.
Durata unei note poate fi modificat prin punct. Astfel, durata real este 3/2
din durata notei fr punct. Pentru a obine stilul legato i stacatto, durata pe care se
cnt o not se modific astfel:
normal: 7/8 din durat; 1/8 pauz;
legato: 1/1 din durat;
stacatto: 3/4 din durat; 1/4 pauz.

Trebuie observat c, datorit dependenei duratei notelor de ceasul intern,
pentru unele tempo-uri nu se obin rezultate satisfctoare. De aceea, este necesar ca
durata notelor i tempo-urile s se stabileasc prin experimentri.

Tabelul 6.2 Duratele notelor n diverse tempo-uri

Tempo Denumire Ptrimi/minut

foarte ncet
Largo
Larghetto
Adagio
40-60
60-66
66-76
ncet Andante 76-108
mediu Moderato 108-120
repede Alegro
Presto
120-168
168-208



6.4 Implementarea modului grafic n Pascal


Subprogramele care implementeaz modul grafic se bazeaz pe
caracteristicile plcilor existente i se mpart n: primitive grafice i subprograme
ajuttoare. Ele sunt declarate n unitatea Graph i sunt memorate n urmtoarele
fiiere:
GRAPH.TPU - care conine codul obiect al subprogramelor definite n
unitatea Graph;
*.BGI - cte un fiier pentru fiecare tip de plac grafic, care
conine codul obiect al rutinelor de tratare a
ntreruperii pentru operaii grafice (driver de plac), ca
soft specific pentru comanda interfeelor grafice;
103
Reprezentarea vizual a datelor
*.CHR - fiiere care conin seturi de caractere suplimentare cu
diferite stiluri (fonturi).
Unitatea Graph definete, de asemenea, o serie de constante, variabile i
structuri de date care s-i uureze programatorului apelul acestor subprograme
(anexa 4). Pentru utilizarea subprogramelor de grafic, programatorul trebuie s
procedeze astfel:
a) S declare faptul c utilizeaz unitatea: uses Graph;
b) S selecteze modul (submodul) grafic dorit, prin utilizarea procedurii:
InitGraph (GraphDriver, GraphMode, PathToDriver)
Primii doi parametri sunt variabile de tipul INTEGER, iar ultimul este o
constant sau variabil de tipul STRING. Parametrii au urmtoarea semnificaie:
GraphDriver precizeaz tipul plcii grafice considerate. Variabila poate lua una
din valorile ntregi 0-10 sau constantele predefinite echivalente. Constanta Detect
(valoare 0) cere subprogramului s identifice tipul de plac a calculatorului.
GraphMode selecteaz unul din submodurile acceptate de placa grafic. Valoarea
parametrului nu este luat n considerare dac GraphDriver a fost Detect, caz n
care se selecteaz automat submodul cu cea mai mare rezoluie.
PathToDriver definete calea spre directorul de reziden a driver-ului de plac
(fiier de tip BGI), dac acesta nu este n director curent. irul vid definete o
cutare n directorul curent.

Exemple:
6.5.
GraphDriver:=EGA;
GraphMode:=EGALo;
InitGraph ('GraphDriver, GraphMode,');
6.6.
GraphDriver:=Detect;
GraphMode:=0;
InitGraph (GraphDriver, GraphMode,'C:\TP\BIN');

c) S verifice dac iniializarea modului grafic dorit, din pasul anterior, s-a desfurat
cu succes. n acest sens, se utilizeaz funcia special GraphResult, de tipul
INTEGER i fr parametri, care returneaz valoarea zero (GrOK) pentru succes.
Funcia poate fi utilizat dup execuia oricrei operaii grafice.
d) S apeleze subrutinele grafice necesare, dac iniializarea s-a derulat cu succes.
e) S revin n modul text, la terminarea operaiilor grafice, prin utilizarea procedurii
fr parametri, CloseGraph. Iniializarea sistemului grafic aloc memoria dinamic
necesar, iar nchiderea o elibereaz.

104
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
6.4.1 Fereastr i vizor

n grafica computerizat se consider c nregistrarea pe ecran este o
transpunere, micorat sau mrit, a desenelor din spaiul real (spaiul utilizator).
Partea imaginii reale care se deseneaz este cuprins ntr-un dreptunghi, numit
fereastr (window), cu laturile paralele cu axele de coordonate ale acestui spaiu.
Fereastra se proiecteaz pe spaiul ecran ntr-un dreptunghi, asemenea cu fereastra,
denumit vizor (viewport). Astfel, pe ecran, pot coexista mai multe imagini
independente. La limit, vizorul poate fi ntregul ecran.
Relaia ntre fereastr i vizor este evideniat n figura 6.6. De aici se deduce
o transformare de coordonate, care proiecteaz orice punct (x
r
,y
r
) din spaiul real, n
punctul (x
e
,y
e
) al spaiului ecran. Dac fereastra i vizorul se definesc prin
coordonatele colurilor stnga-sus i dreapta-jos, iar centrele celor dou dreptunghiuri
sunt notate ) y , x (
r
0
r
0
, ) y , x (
e
0
e
0
, din asemnarea imaginii din cele dou spaii se pot
scrie relaiile:

(1)
w w
v v
y y
y y
w w
v v
x x
x x
4 3
3 4
r
0
r
0
e e
1 2
1 2
0
r r
0
e e





Fig. 6.6 Relaia fereastr-vizor
(x
r
,y
r
)
(x
e
,y
e
)
(w
1
,w
3
)
(w
2
,w
4
)
(v
2
,v
4
)
(v
1
,v
3
)
(x y
r r
0 0
, )
(x y
e e
0 0
, )

x
x
y
y
fereastr
vizor

105
Reprezentarea vizual a datelor
Din (1) se expliciteaz coordonatele (x
e
,y
e
) i se obin relaiile:
(2)
y
w w
v v
y
w w
v v
y y
x
w w
v v
x
w w
v v
x x
0
r
4 3
3 4
r
4 3
3 4 0
e e
0
r
4 2
1 2
r
1 2
1 2 0
e e

+ =

din care, prin nlocuirea coordonatelor centrelor ferestrelor i vizorului, n funcie de
coordonatele colurilor acestora, se obin relaiile:
(3)
2
w w
w w
v v
y
w w
v v
2
v v
y
2
w w
w w
v v
x
w w
v v
2
v v
x
4 3
4 3
3 4
r
4 3
3 4 4 3
e
2 1
1 2
1 2
r
1 2
1 2 2 1
e

+
=
+

+
+
=

Realiznd calculul din (3) se obin relaiile:
(4)
w w
w v w v
y
w w
v v
y
w w
w v w v
x
w w
v v
x
4 3
4 3 3 4
r
4 3
3 4
e
1 2
1 2 2 1
r
1 2
1 2
e

=

Notnd:
(5)
w w
w v w v
b >
w w
w v w v
b
w w
v v
a >
w w
v v
a
4 3
4 3 3 4
2
1 2
1 2 2 1
1
4 3
3 4
2
1 2
1 2
1

=

se obin relaiile de transformare:
x = Round(a x + b )
y = Round(a y + b )
e 1 r 1
e 2 r 2
(6)
Relaiile (6) dau coordonatele absolute, n spaiul ecran, pentru orice punct
(x
r
,y
r
). Este, de multe ori, preferabil s se exprime punctele n spaiul ecran relativ la
vizor, adic ntr-un subspaiu cu originea n colul stnga-sus al acestuia. Dac se
noteaz (dx
e
,dy
e
) coordonatele absolute (x
e
, y
e
), se obin relaiile:
(7)
dy v y
dx v x
e 3 e
e 1 e

+ =
+ =

106
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Utiliznd relaiile (4), din (6) se obin relaiile:
) 8 (
) w y (
w w
v v
dy
) w x (
w w
v v
dx
3 r
4 3
3 4
e
1 r
1 2
1 2
e

=

Dac se noteaz:
k
v v
w w
k
v v
w w
1
2 1
2 1
2
4 3
3 4
=


atunci se pot considera coordonatele relative sub forma:
) 9 (
)) (
)) (

=
=
3 r 2 e
1 r 1 e
w y round(k dy
w x round(k dx

Utilizarea ferestrei i/sau vizorului n tehnica realizrii imaginilor grafice
ofer, n plus, posibilitatea de verificare a apartenenei punctelor la desenul curent.
Se pot implementa msuri de eliminare a punctelor strine (tehnica clipping-ului sau
tierii), pentru a asigura protecia imaginilor vecine mpotriva distrugerilor
accidentale, desenndu-se numai imaginea din fereastr.
n sistemul grafic Pascal, ideile tehnicii fereastr-vizor sunt implementate
parial, aa dup cum rezult din cele ce urmeaz.
Exist posibilitatea definirii vizorului ca spaiu curent pentru un anumit
desen (vizor curent). Declararea lui se face prin apelul procedurii SetViewport, n
forma:
SetViewport(v1,v3,v2,v4,Clip);
n care (v1,v3) i (v2,v4) sunt constante sau variabile de tipul INTEGER care dau
coordonatele colurilor vizorului, iar Clip este un parametru boolean care activeaz
sau inhib aplicarea clipping-ului.
Unitatea Graph definete funciile de tipul INTEGER fr parametri:
GetMaxX i GetMaxY care returneaz dimensiunile maxime ale spaiului ecran
pentru placa grafic cu care este echipat calculatorul. Pentru a crea independen
programului fa de calculator, se recomand utilizarea lor n definirea vizorului. De
asemenea, unitatea Graph definete constantele simbolice ClipOn (True) i ClipOff
(False) care pot fi folosite pentru parametrul Clip.

107
Reprezentarea vizual a datelor
Exemplu:
6.7.
SetViewport(10,25,GetMaxX-150,GetMaxY-50,ClipOn);
Vizorul implicit, stabilit la iniializarea modului grafic, este ntregul ecran, echivalent
cu un apel de forma:
SetViewport (0,0,GetMaxX,GetMaxY,ClipOn) ;

Vizorul curent poate fi ters, la culoarea de font curent, prin apelul
procedurii ClearViewport, care este fr parametri. Pentru a fi pus n eviden fa
de zonele vecine, vizorul poate fi ters cu o culoare de fond adecvat, stabilit n
prealabil (vezi 6.4.2.) i poate fi ncadrat ntr-un dreptunghi.

Exemplu:
6.8. Pentru un ecran monocrom (dar nu numai) se poate utiliza o secven de
forma:
Rectangle(9,24,GetMaxX-149,GetMaxY-49);
SetViewport(10,25,GetMaxX-150,GetMaxY-50,ClipOn)
ClearViewport;
n care procedura Rectangle deseneaz un dreptunghi cu liniile n culoarea curent de
desen (alb), iar SetViewport l terge, la culoarea fondului.

Procedura ClearDevice terge ntregul ecran i determin revenirea la
parametrii de lucru implicii, stabilii la iniializare.
Declararea vizorului determin rutinele sistemului grafic s lucreze n
coordonate relative. Aceasta nseamn c orice procedur sau funcie care primete
ca parametru de intrare coordonatele (dx
e
,dy
e
) nelege s le utilizeze pentru a
calcula coordonatele absolute (x
e
,y
e
), prin relaii de forma (6), iar cele care au aceste
coordonate ca parametru de ieire le determin prin relaiile:
dx x v
dy y v
e e 1
e e 3

=
=


Sistemul nu prevede posibilitatea declarrii ferestrelor n spaiul utilizator
i, de aici, lipsa facilitii de exprimare a coordonatelor, pentru rutinele de grafic,
direct n acest spaiu i transformarea lor automat n coordonatele ecran.
Programatorul trebuie s-i construiasc proceduri proprii care s-i transforme
coordonatele din spaiul utilizator n spaiul ecran, relative la vizorul curent. Dei pot
fi aplicate procedee diverse, dup natura desenului, pentru generalitate i
uniformitate n realizarea programelor de grafic se aplic tehnica fereastr-vizor
descris anterior.
108
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
6.4.2 Grafic n culori

Sistemul grafic Pascal implementeaz culorile pe principiul paletei. Sistemul
posed o serie de proceduri, funcii i date prin care se pot accesa facilitile de
culoare ale plcii grafice i modului grafic selectat.
Determinarea paletei. Deoarece caracteristicile de culoare depind de placa
grafic i modul grafic selectat, se poate obine un program relativ portabil, dac
acesta se scrie astfel nct s-i determine singur facilitile pe care le poate utiliza.
Pentru aceasta pot fi utilizate rutinele:
- GetMaxColor - funcie fr parametri care ntoarce o valoare de tipul WORD,
reprezentnd indexul maxim al paletei;
- GetPaletteSize - funcie fr parametri care ntoarce o valoare de tipul
INTEGER reprezentnd numrul maxim de culori care pot fi
utilizate simultan;
- GetDefaultPalette(paleta) - procedur care returneaz, n parametrul paleta,
numrul i culorile paletei implicate;
- GetPalette(paleta) - procedur care returneaz aceleai date ca procedura
anterioar, dar pentru paleta curent.
Parametrul paleta trebuie s fie declarat ca o variabil de tipul PaletteType, definit n
unitatea Graph ca un articol cu cmpurile: Size (Byte) i Colors (Shortint).
Modificarea paletei curente. Programatorul poate modifica una sau toate
intrrile paletei curente, dar pantru aceasta trebuie s cunoasc codurile de culoare.
Procedurile care se utilizeaz sunt:
- SetPalette(Index,Color) - care permite modificarea intrrii date de parametrul
Index (WORD), cu o culoare de cod Color (INTEGER). Att
pentru Index, ct i pentru Color pot fi utilizate constantele
simbolice predefinite n unitatea Graph.
- SetAllPalette(Palette) - nlocuiete paleta curent cu cea dat de parametrul
Palette. Parametrul este de tipul PaletteType i trebuie s fi
fost ncrcat corect cu codurile de culori.
n ambele situaii, procedurile modific automat culorilor desenului de pe
ecran, n concordan cu noua configuraie a paletei curente. Procedurile pot fi
utilizate i cu scopul de a produce efecte de culoare deosebite sau pentru a releva
treptat, prin modificri repetate, un desen ascuns.
Determinarea i modificarea culorilor de fond i de desen. Funciile i
procedurile din aceast categorie sunt cel mai frecvent utilizate deoarece definesc
fondul i culoarea de desen pe baza paletei curente.
-SetBkColor(Color) - procedur pentru selecia culorii de fond. Color este
parametrul de tip WORD care precizeaz indexul culorii
dorite. Implicit, se utilizeaz indexul zero care corespunde, n
general, culorii negre;
- GetBkColor - funcie fr parametri, de tipul WORD, care returneaz inde-
xul culorii curente pentru fond;
109
Reprezentarea vizual a datelor
- SetColor(Color) - procedur pentru selecia culorii de desen. Color are
aceeai semnificaie ca la procedura anterioar. Implicit, se
utilizeaz ultimul Index care, n general, corespunde culorii
alb;
- GetColor - funcie similar cu GetBkColor pentru a obine culoarea curent
de desen.
Modificarea culorii de fond atrage dup sine modificarea culorii pe ecran.
Culorile selectate, denumite culori curente, rmn active pn la o nou selecie sau
pn la ieirea din program.

Exemplu:
6.9. Presupunnd o plac EGA, secvena care urmeaz stabilete un vizor cu
fond albastru n care deseneaz un dreptunghi umplut. Dup 2000 ms se refac
culorile anterioare.

Uses Graph,Crt;
VAR
ColorBk,ColorFg:Word;
..
ColorBk:=GetBkColor;
ColorFg:=GetColor;
SetViewport(20,50,250,150,ClipOn);
SetColor(EGARed);
SetBkColor(EGABlue);
ClearViewport;
Bar(20,10,60,50);
Delay(2000);
SetBkColor(ColorBk);
SetColor(ColorFg);
. . . . . . . . . . . . . .


6.4.3 Desen prin puncte i vectori

Desenul prin puncte este modul natural de realizare a imaginii video.
Biblioteca de subprograme grafice Pascal conine pentru acest mod de lucru
procedura PutPixel(x,y,Color) i funcia de tipul WORD GetPixel(x, y).
Procedura PutPixel stabilete culoarea Color de aprindere a pixelului de
coordonate (x,y) din vizorul curent, iar funcia GetPixel ntoarce indexul culorii cu
care este aprins un astfel de pixel. Pe baza subprogramelor, se pot construi desene
complexe, dar cu dificultile pe care le implic gestionarea mulimii de pixeli care
compun imaginea video. Pentru a facilita realizarea desenelor, sistemul grafic
PASCAL implementeaz i alte moduri de lucru, cum este desenul prin vectori. n
acest mod, pot fi trasate segmente de dreapt, independente sau legate (linii frnte),
utiliznd pentru forma liniilor stilurile i culorile curente (setate). Culoarea de desen
i culoarea fondului sunt curente, setate prin SetBkColor i SetColor. Stilul de linie
este cel definit de procedura SetLineStyle,care se apeleaz astfel:
SetLineStyle(TipStil,Model,Grosime);
110
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Stilul definit rmne valabil pn la o nou setare. Stilul implicit este linia
continu normal. Parametrii, de tipul WORD, constante sau variabile, definesc
atributele liniei (stilul liniei):
- TipStil - definete tipul de linie din punctul de vedere al continuitii.
Parametrul poate avea valorile 0-4 sau constanta simbolic
corespunztoare;
- Grosime - precizeaz grosimea, n numr de pixeli i poate avea valorile:
1 (linie normal - NormWidth) i 2 (linie groas - ThickWidth);
- Model - definete un stil de utilizator printr-un fragment de 16 pixeli. Un pixel
este aprins, dac bitul corespunztor, din numrul dat de acest
parametru, este unu. De exemplu, dac Model=$F053 (n binar 1111
0000 0101 0011) atunci se definete modelul xxxx xx xx, n care
este pixel aprins.
Desenarea unui segment de dreapt se face prin procedura
Line(x1,y1,x2,y2). Prin parametrii x1, y1, x2, y2, de tip INTEGER, se precizeaz
coordonatele capetelor segmentului de dreapt. Coordonatele sunt relative la vizorul
curent i se pot exprima ca variabile sau constante. Se desemneaz numai poriunea
de segment care se afl n interiorul vizorului.

Exemplu:
6.10. Secvena care urmeaz:

SetViewport(20,20,150,100,ClipOn);
Line(10,10,150,150);

deseneaz un segment cu originea absolut n (30,30) i extremitatea final n
(170,120) din care se vede numai poriunea de coordonate absolute (30,30),
(138,100) - figura 6.7.

Desenarea segmentelor de dreapt cu procedura Line este incomod, cnd
trebuie desenate linii frnte, datorit redundanei de informaii, avnd n vedere
coincidena punctului final al unui segment cu originea segmentului urmtor.
Desenarea liniilor frnte este facilitat de introducerea n sistemul grafic a
noiunii de punct curent i de existena unor rutine care deseneaz linii relativ la
acesta. Punctul curent, definit prin coordonatele sale n spaiul ecran, este neles de
rutinele sistemului ca origine a urmtorului segment de dreapt posibil de desenat.
Sistemul prevede rutine pentru aflarea i modificarea poziiei punctului curent,
precum i reguli de comportare a rutinelor de trasare de linii, cu privire la
actualizarea acestuia. Locul punctului curent poate fi aflat cu ajutorul funciilor, fr
parametri, GetX i GetY, care returneaz abscisa i ordonata absolut, ca numere
ntregi.
111
Reprezentarea vizual a datelor
(20,20)
(30,30)
(138,100
(170,120)
(150,100)



(0,0)
Fig. 6.7. Desenarea liniilor relativ la vizor
x
y


Punctul curent poate fi mutat ntr-un alt loc din spaiul fizic, prin procedurile
MoveTo i MoveRel care se apeleaz sub forma: MoveTo(x,y); MoveRel(x,y).
Procedura MoveTo consider valorile (x,y) drept coordonate relative la vizorul curent
i calculeaz coordonatele absolute (x
e
,y
e
) ale punctului curent prin relaiile: x
e
=v
1
+x;
y
e
=v
3
+y, unde (v1,v3) sunt coordonatele originii vizorului. Procedura MoveRel
deplaseaz punctul curent relativ la poziia sa anterioar, adic x
e
=GetX+x;
y
e
=GetY+y, n care x,y apar ca deplasri. La intrarea n regim grafic, la definirea
i/sau tergerea vizoarelor, precum i la schimbarea modului grafic, punctul grafic
curent este nedefinit. Este sarcina programului s iniializeze punctul curent prin
procedura MoveTo. Toate procedurile de desenare de linii i scriere de text
deplaseaz poziia punctului curent n ultimul punct utilizat.
Desenarea liniilor care i au originea n punctul curent se realizeaz cu
ajutorul procedurilor LineTo(x,y); LineRel(x,y). Pentru LineTo, coordonatele
extremitii liniei sunt relative la vizorul curent i deci x
e
=v
1
+x, y
e
=v
3
+y, unde (x
e
,y
e
)
sunt coordonatele absolute ale extremitii liniei relativ la punctul curent x
e
=GetX+x;
y
e
=GetY+y. Dup trasare, punctul curent este deplasat n punctul x
c
=x
e
, y
c
=y
e
. Dac
la trasare a fost necesar operaia de clipping, punctul final al segmentului vizibil este
recalculat ca
(x
e
~
e
~
, ) y
, ns punctul curent este mutat tot n (x
e
,y
e
). Se evit astfel
deformarea desenelor.

Exemplu:
6.11. Dac se consider linia frnt P
1
, P
2
, P
3
, P
4
din figura 6.8, atunci
secvenele de instruciuni de trasare, avnd n vedere coordonate relative la vizor i
relative la punctul curent, pot fi scrise astfel:

Relativ la vizor Relativ la punctul curent
MoveTo(50,60) MoveTo(50,60)
LineTo(70,40) LineRel(20,-20)
LineTo(85,45) LineRel(15,5)
LineTo(140,30) LineRel(25,-15)
112
Programarea calculatoarelor Tehnica programrii n limbajul Pascal

(0,0)
(85,45)
[15,5]

x
y

(20,10)
(50,60)
(70,40)
[20,-20]
(110,30)
[25,-15]
Fig. 6.8. Desenarea segmentelor relativ la vizor i la punctul curent


n plus, trebuie menionat faptul c desenarea unei linii simple sau frnte
poate fi fcut astfel nct s distrug sau s conserve, ntr-un anumit sens, culorile
pixelilor care se suprapun. Comportamentul pixelilor depinde de modul de scriere a
noii imagini n raport cu imaginea existent pe ecran (setarea modului Write);


6.4.4 Raportul de aspect

n realizarea desenelor prin segmente apare un fenomen de deformare care
poate s fie deranjant (un ptrat apare ca dreptunghi, un cerc ca o elips etc).
Fenomenul se datoreaz formei pixelilor care, cu excepia unor plci de foarte mare
rezoluie, nu sunt de form ptratic, ci dreptunghiular. Aceasta face s se aplice,
implicit, uniti diferite de msur pe cele dou axe. Deformarea poate fi atenuat sau
chiar eliminat, dac n realizarea desenului se aplic un anumit raport ntre
lungimile segmentelor de pe orizontal i ale celor de pe vertical.
Dac se noteaz cu Lpx lungimea unui pixel, n sensul axei ox i cu Ipy
nlimea sa, n sensul axei oy, atunci raportul Ra=Ipy/Lpx este denumit raport de
aspect. El poate fi utilizat pentru a determina, n mod adecvat, lungimile segmentelor
(n pixeli) care se deseneaz. Pentru a obine dimensiunile pixelului plcii grafice se
utilizeaz procedura:
GetAspectRatio(Lpx, Ipy);
n care cei doi parametri sunt variabile de tipul WORD.
Dac se noteaz cu AB un segment vertical de lungime n pixeli i cu CD un
segment orizontal, de lungime m pixeli, atunci, pentru ca raportul AB/CD s fie k,
trebuie ca m, dac se cunoate n (respectiv n, dac se cunoate m), s se determine
cu relaiile:

k * Round(m n
n * Round(Ra = m

= ) Ra
) k

113
Reprezentarea vizual a datelor
Exemplu:
6.12. Desenarea unui ptrat, cu latura orizontal CD de m=50 pixeli i vrful
stnga sus n (30,60), pe un vizor egal cu ntregul ecran. Deoarece k=1, se poate
utiliza secvena:

GetAspectRatio(Lpx,Ipy);
Ra:=Ipy/Lpx;
n=Round(50/Ra);
MoveTo(30,60);
LineTo(80,60);
LineTo(80,60+n);
LineTo(30,60+n);
LineTo(30,60);

Exist, de asemenea, rutina SetAspectRatio care permite definirea software a
raportului de aspect pentru a fi utilizat de rutinele sistemului grafic. Programatorul
care utilizeaz rutinele sistemului pentru desenare de figuri poate s reduc
fenomenul de deformare, modificnd repetat, eventual interactiv, raportul de aspect.
Apelul acestei proceduri este similar procedurii GetAspectRatio.


6.4.5 Scrierea textelor n modul grafic

n mod uzual, imaginile de pe ecran sunt nsoite de texte explicative. Avnd
n vedere c, de multe ori, lucrul n modul text nu satisface cerinele de mrime,
form, culoare i direcie de scriere, n unit-ul Graph au fost introduse primitive
specifice prelucrrii textelor. Unitatea conine dou grupe de rutine: pentru definirea
atributelor textelor i pentru scrierea propriu-zis.
Rutinele de declarare a atributelor textelor trebuie apelate ori de cte ori
este necesar s se defineasc alte caracteristici de scriere dect cele curente.
Atributele astfel definite (setate) rmn active pn la o nou setare sau pn la
sfritul programului. Rutinele de declarare sunt proiectate pentru a putea trata
urmtoarele atribute de scriere:
a) Stilul de caractere, adic forma caracterelor imprimabile. Sistemul
recunoate cinci stiluri (fonturi), codificate 0-4, crora li s-au asociat constante
simbolice;
b) Culoarea: caracterele se afieaz pe fondul i culoarea de desen curent;
c) Mrimea se refer la limea i nlimea caracterelor, caracteristici care se
definesc pentru toate fonturile, cu excepia stilului DefaultFont, la care mrimea nu
poate fi modificat. Fonturile cu mrime de caracter modificabil definesc
caracterele prin vectori (caractere vectoriale). Mrimea se poate referi la spaiul
dreptunghiular pentru un caracter, n sensul micorrii sau creterii proporionale a
acestuia pentru ambele dimensiuni sau pentru fiecare dimensiune n parte
(dimensiuni de utilizator).
114
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
d) Direcia de scriere poate fi: orizontal sau vertical. Pentru direcia orizontal
(constanta simbolic HorizDir) scrierea se face de la stnga spre dreapta, iar pentru
direcia vertical (VertDir), de jos n sus;
e) Alinierea: precizeaz, pentru fiecare din cele dou direcii, modul de
amplasare a textului n raport cu punctul de scriere (punct de referin).
Pentru definirea atributelor se pot utiliza procedurile:
SetTextStyle (Font, Directie, Marime);
SetTextJustify (FtHorizDir, FtVertDir);
SetUserCharSize (MultX, DivX, MultY, DivY);
Parametrul de mrime, la procedura SetTextStyle, poate lua valori naturale
mai mari sau egale cu zero i precizeaz de cte ori s fie mrite, proporional,
caracterele fontului ales fa de dimensiunea normal a acestora. Pentru definirea
dimensiunilor de utilizator (independente pe cele dou direcii), valoare zero a
parametrului Marime declar intenia programatorului de a apela procedura
SetUserCharSize. La aceast procedur, se utilizeaz ideea c dimensiunea se
modific prin nmulire cu un raport. Raportul MultX/DivX va fi utilizat pentru a
modifica limea caracterelor, iar MultY/DivY pentru modificarea nlimii. Atunci
cnd raportul este unu, dimensiunea pe direcia respectiv va rmne nemodificat.
La procedura de definire a alinierii se cere s se precizeze modul de aliniere
a textului pe ambele direcii, chiar dac scrierea utilizeaz numai una din ele.

Exemple:
6.13. Se definete fontul SmallFont, cu mrire proporional, de 3 ori i cu
afiare centrat pe orizontal:

SetTextJustify(CenterText,CenterText);
SetTextStyle(SmallFont,HorizDir,3);

6.14. Se stabilete o cretere a dimensiunii caracterelor fontului
SansSerifFont numai n nlime, de 1,5 ori; scrierea se face pe direcia vertical, cu
aliniere la partea de jos:

SetTextStyle(SansSerifFont,VerDir,0);
SetUserCharSize(1,1,3,2);
SetTextJustify(LeftText,BottomText);

Dac atributele de scriere au fost deja definite, adic au devenit atribute
curente, programatorul poate utiliza funciile ntregi (de tipul WORD):
TextHeight(Text), TextWidth(Text), pentru a afla nlimea, respectiv limea, n
numr de pixeli, necesare pentru a afia ntregul text dat de parametrul Text. Pe baza
acestor informaii, se poate alege punctul de referin astfel nct scrierea textului s
fie posibil (totul s nceap n vizorul de scriere) sau acesta s fie mai bine amplasat,
pe direcia curent.
115
Reprezentarea vizual a datelor
Pentru scrierea efectiv a textelor se utilizeaz una din urmtoarele dou
proceduri:
OutText(Text);
OutTextXY(x,y,Text);
Textul de scris (parametrul Text) se poate prezenta ca o constant, variabil
sau expresie de tipul STRING. Scrierea se face n raport cu punctul de referin cu
coordonate (x,y) sau la cursor, dac nu se definete explicit un astfel de punct.
Dup scriere, cursorul se gsete pe poziia urmtoare celei utilizate pentru scrierea
ultimului caracter al textului, dac scrierea s-a fcut prin procedura OutText sau
rmne nemodificat, atunci cnd s-a utilizat procedura OutTextXY.
Dac exist definit vizor curent, cu acceptarea clipping-ului, textul este
decupat la limitele vizorului. Nu se aplic procedeul de clipping dac fontul este
DefaultFont i comportarea rutinei de scriere este nedefinit cnd survine o depire
a vizorului. n plus, trebuie menionat c primitivele de afiare in cont de setarea
modului de scriere.

Exemplu:
6.15. Se scrie orizontal textul "TURBO PASCAL", de 4 ori, cu cele patru
fonturi vectoriale. Fiecare rnd, centrat pe linia vertical a centrului ecranului, se
scrie cu o alt culoare.

Clear Device;
SetTextJustify(CenterText,CenterText);
y:=20;
For i:=1 to 4 do
Begin
SetColor (i);
SetTextStyle(i,HorizDir,2+i);
Y:=y+TextHeight('TURBO PASCAL')+8;
OutTextXY(GetMaxX Div 2,Y,'TURBO PASCAL');
End;


6.4.6 Primitive pentru figuri

Pentru a facilita realizarea imaginilor, sistemul grafic cuprinde cteva
primitive pentru desenarea unor figuri, majoritatea n plan. Unele din aceste
proceduri umplu figura desenat cu un anumit model de culoare i haur. Toate
rutinele au fost concepute s lucreze n condiiile existenei unei vizor curent, adic
n coordonate relative la vizor i s aplice clipping-ul, dac acesta a fost acceptat.
Cteva din ele in seama de modul de scriere selectat. Ca i rutinele prezentate
anterior, primitivele pentru figuri utilizeaz, pentru contur i linii, culorile i
atributele curente. Dac o primitiv umple figura, atunci ea folosete un model de
haurare i o anumit culoare. Modelul de haurare poate fi ales dintr-o mulime
predefinit sau poate fi definit de utilizator.
116
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Pentru a preciza stilul i culoarea de umplere se apeleaz procedura:
SetFillStyle(TipStil,Culoare);
n care parametrul Culoare este un index n paleta curent, iar TipStil o constant
ntre 0-12. Dac TipStil este 12 (UserFill), atunci el trebuie s fie definit ca un model
binar pe 8 byte (un vector) care este interpretat de rutinele respective ca o matrice de
8x8 bii. Matricea este traversat circular pe linii i pixelul curent este aprins, la
culoarea definit prin parametrul culoare, dac bitul din model este unu. n plus, tipul
definit rmne ca model curent.

Exemplu:
6.16.

CONST
MyPattern:Array[1..8]of Byte=($01,$01,$FF,$01,$01,$FF,$01,$01);
. . . . . . . . . .
SetFillStyle(MyPattern,3);

n figura 6.9 se prezint toate tipurile de hauri considernd numai culorile
alb i negru.


Fig. 6.9 Tipuri de hauri

Empty Solid Line LtSlash Slash BkSlash


Hatch XHatch Interline Wide Dot Close Dot User


Principalele primitive pentru figuri sunt prezentate n continuare.

a) Proceduri pentru dreptunghiuri:
Rectangle (x1,y1,x2,y2);
Bar(x1,y1,x2,y2);
Prima procedur deseneaz un dreptunghi simplu, neumplut, iar a doua un
dreptunghi umplut. Procedura Rectangle ine seama de setarea modului de scriere
(WriteMode). Parametrii de apel sunt coordonatele ntregi ale colului stnga-sus
(x1,y1) i dreapta jos (x2,y2) ale dreptunghiului.
b) Proceduri pentru linii poligonale i poligoane oarecare:
117
Reprezentarea vizual a datelor

DrawPoly(NumarVarfuri,CoordonateVarfuri);

FillPoly(NumarVarfuri,CoordonateVarfuri);
Procedurile sunt similare perechii de proceduri pentru desenarea
dreptunghiurilor. Coordonatele punctelor liniei poligonale trebuie s fie declarate ca
o variabil de tip masiv, la care tipul de baz trebuie s fie PointType, adic un
articol cu dou cmpuri: X i Y. Dac se dorete trasarea unui poligon, atunci fa de
linia poligonal cu n vrfuri trebuie declarate n+1 vrfuri i coordonatele ultimului
vrf trebuie s coincid cu cele ale primului. Procedura FillPoly se aplic numai
pentru poligoane, iar interiorul acestora este umplut cu haura i culoarea cerute.

Exemplu:
6.17.
CONST
Pentagon: Array[16]of PointType=
((x:20;y:45),(x:50;y:25),(x:100;y:10),
(x:120;y:40),(x:80;y:60),(x:20;y:45));
FillPoly (6,Pentagon);

c) Proceduri pentru arce, cercuri i elipse. Procedurile din aceast categorie
deseneaz marginile figurilor utiliznd culoarea curent, stabilit de SetColor. Cele
care haureaz sau umplu figura desenat utilizeaz atributele date de SetFillStyle.
Procedurile nu in seama de setarea modului de scriere.
Procedurile care deseneaz arce utilizeaz, ca parametri, unghiuri n grade.
Trebuie avut n vedere c acestea sunt considerate n sens trigonometric (sens invers
acelor de ceasornic, cu 0 grade la ora 3, 90 grade la ora 12, 180 grade la ora 9 etc.).
De asemenea, raza cercului i razele elipselor (raza orizontal - RazaX i raza
vertical - RazaY) se dau n numr de pixeli. Coordonatele centrului figurii
constituie, de asemenea, un parametru (x,y). Pentru asigurarea circularitii pe ecran,
procedurile utilizeaz raportul de aspect al plcii, eventual setat soft, prin
SetAspectRatio.
Procedurile de baz sunt:
Arc
(x,y,UnghiStart,UnghiFinal,Raza);
PieSlice
(x,y,UnghiStart,UnghiFinal,Raza);
Circle (x,y,Raza);
Ellipse
((x,y,UnghiStart,UnghiFinal,RazaX,RazaY);
Sector
(x,y,UnghiStart,UnghiFinal,Raza);
FillEllipse (x,y,RazaX,RazaY);
118
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Procedura Circle deseneaz un cerc (neumplut), iar procedura Arc deseneaz
un arc care, la limit, poate fi un cerc, depinznd de alegerea unghiurilor. Procedura
PieSlice deseneaz un sector umplut care poate fi, la limit, un cerc umplut.
Aproape similar este cazul elipselor. Procedura Ellipse deseneaz un arc de
elips sau o elips (neumplut), procedura Sector deseneaz un sector de elips sau o
elips umplut, iar procedura FillEllipse deseneaz o elips umplut.

Exemplu:
6.18.
Arc (150,100,0,270,50);
PieSlice (GetMaxX Div 2,GetMaxY Div 2,0,360,GetMaxX Div 4);
FillEllipse (150,150,300,75).

Trebuie remarcat i faptul c sistemul grafic posed o procedur de
interogare asupra centrului punctului de start i punctului final care au fost utilizate
n timpul execuiei uneia din procedurile: Arc, PieSlice, Ellipse, Sector. Aceste
informaii sunt furnizate prin apelul procedurii:
GetArcCoords(ArcCoords);
n care parametrul ArcCoords are tipul ArcCoordsType definit public n unitatea
Graph astfel:
Type
ArcCoords=Record
x,y:Integer; {Punct de centru}
xStart,yStart:Integer; {Punct de inceput}
xEnd,yEnd:Integer; {Punct de sfarsit}
End;
Procedura este util pentru racordarea arcelor cu segmente de dreapt sau
alte arce.

d) Procedura pentru paralelipiped dreptunghic
Bar3D (x1,y1,x2,y2,Grosime,Top);
Procedura permite desenarea paralelipipedelor dreptunghice colorate
(umplute). Parametrii au urmtoarele semnificaii:
- (x1,y1),(x2,y2) sunt coordonatele colurilor stnga-sus, dreapta-jos ale feei
(dreptunghiului din fa);
- Grosime, de tipul WORD, indic grosimea paralelipipedului;
- Top, de tip BOOLEAN, arat c faa superioar trebuie s fie vizibil (valoare
True sau constanta TopOn) sau s fie ascuns (valoare False sau TopOff). Parametrul
permite realizarea paralelipipedelor suprapuse, caz n care trebuie s fie vizibil
numai faa superioar a ultimului paralelipiped.
Procedura se poate utiliza pentru desenarea histogramelor prin bare (grafice
din bare) care prezint, comparativ, valorile unei (unor) caracteristici (mrimi).
119
Reprezentarea vizual a datelor
6.4.7 Elemente de animaie

Animaia poate fi considerat ca tehnic de realizare a micrii obiectelor
grafice pe ecran. Ea presupune refacerea imaginii video, de peste 30 de ori pe
secund, cu obiectele n diferite poziii, astfel nct s se asigure persistena imaginii
pe retina ochiului. Reuita n realizarea animaiei este strns condiionat de resursele
calculatorului, cum sunt: viteza microprocesorului, existena coprocesorului
matematic, numrul de pagini ale memoriei video etc.
1. Aspecte generale. Animaia este o tehnic complex prin multitudinea de
probleme pe care le pune realizatorului de programe.
n primul rnd, programul trebuie s ia n considerare comportarea
obiectului de animat n mediu. n cazurile simple, imaginea pe ecran se reduce la
obiectul n micare, adic nu exist mediu ambiant. Uzual, ns, pe ecran exist o
imagine peste care trebuie s se deplaseze obiectul. Aceast imagine este, pentru
obiectul animat, un mediu ambiant, pe care acesta trebuie s l conserve. Rezult de
aici c imaginea obiectului, n diferitele sale poziii, trebuie scris peste imaginea
mediu ntr-un anumit mod. De regul, regimul grafic al unui calculator accept cel
puin dou moduri de scriere (WriteMode): unul care distruge imaginea veche (modul
PUT) i altul care suprapune noua imagine peste cea veche (modul XOR). Trebuie
remarcat c realizarea a dou operaii logice XOR (sau exclusiv) succesive ale unei
imagini peste acelai mediu nseamn, de fapt, tergerea noii imagini din poziia
respectiv.
n al doilea rnd, programul crete n complexitate dac obiectul animat nu
rmne identic cu el nsui n toate poziiile sale de micare. Este mai simplu de
animat un obiect pentru care imaginea formei sale se conserv, deoarece aceast
imagine poate fi realizat o singur dat, memorat i, apoi, afiat n diferite poziii.
Dac obiectul animat i schimb forma de la o poziie la alta, aa cum este cazul
general, atunci imaginea sa trebuie refcut continuu. n acest caz, consumul de timp
este mult mai mare i animaia reuete numai n prezena unor resurse suplimentare
ale calculatorului care s asigure viteza necesar de afiare.
n al treilea rnd, obiectul n micare poate s aib un anumit
comportament la atingerea limitelor vizorului de afiare. Problema este simpl atunci
cnd obiectul poate iei i intra n vizor, deoarece se rezolv prin tehnica
clipping-ului. Dac obiectul nu poate prsi vizorul sau atingerea limitelor acestuia i
imprim o anumit traiectorie, atunci programul trebuie s prevad teste pentru a
sesiza situaia i s includ relaii adecvate de calcul.
n sfrit, probleme complexe ridic situaiile n care mediul nsui poate
modifica forma i/sau traiectoria obiectului sau cnd trebuie animate mai multe
obiecte concomitent. Din punct de vedere algoritmic, orice program de animaie
trebuie s aib ncorporai urmtorii pai:
a) Se afieaz pe ecran imaginea, cu obiectul n poziia a;
b) Se construiete imaginea cu obiectul ntr-o poziie nou, b (dac este
cazul);
c) Se terge obiectul din poziia a (eventual, prin afiarea a doua oar a
imaginii acestuia n a, cu scriere XOR);
120
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
d) Se atribuie lui a valoarea lui b i se reia, dac este cazul, de la punctul a.

2. Faciliti pentru realizarea animaiei n PASCAL. Sistemul grafic Turbo
Pascal prevede cteva rutine care faciliteaz realizarea animaiei.
Moduri de scriere. Pot fi definite moduri de determinare a culorii unui
pixel din noua imagine, n funcie de culoarea curent de scriere i culoarea pe care
acelai pixel o are n imaginea existent pe ecran (culoarea veche). Avnd n vedere
c noua imagine se constituie n memoria video, peste cea existent, sunt posibile
diferite operaii logice ntre biii care determin culoarea unui pixel i noile valori
dorite. Aceste operaii sunt denumite moduri de scriere i se definesc prin procedura:
SetWriteMode(Mode);
unde parametrul Mode poate lua valorile ntregi ntre 0-4. n mod implicit se aplic
NormalPut, cnd pixelul capt culoarea curent, indiferent de culoarea pe care o
avea (imaginea veche dispare). Cel mai frecvent se utilizeaz XOR, care determin
culorile dup o funcie sau exclusiv. Se are n vedere c specificarea culorilor se
face prin index n palet i, deci, rezultatul este tot o astfel de valoare.
Din exemplul urmtor se poate urmri i afirmaia c (A XOR B) XOR B = A.

Culoare veche
(A)
Culoare curent
(B)
Culoare nou
(A XOR B)
(A XOR B)
XOR B
0011 (3) 0101 (5) 0110 (6) 0011 (3)
1011 (11) 0010 (2) 1001 (9) 1011 (11)
1111 (15) 1101 (13) 0010 (2) 1111 (15)
0000 (0) 1111 (15) 1111 (15) 0000 (0)

Aa dup cum s-a mai remarcat, nu toate procedurile grafice in seama de
setarea modului de scriere. Rutinele care determin culoarea nou dup regulile
descrise sunt:
Line LineTo LineRel OutTextXY
DrawPoly Rectangle OutText
Salvarea i restaurarea unei imagini. Sistemul prevede salvarea, din
memoria ecran, a unei imagini ncadrat ntr-o zon dreptunghiular, ntr-un buffer
definit de utilizator n memoria intern, de regul n yona heap. Se utilizeaz
procedura:
GetImage(X1,Y1,X2,Y2,Buffer);
n care (X1,Y1), (X2,Y2) dau coorodnatele colurilor stnga-sus i dreapta-jos ale
drptunghiului care definete imaginea de salvat. Variabila Buffer trebuie s aib un
numr acoperitor de cuvinte pentru imagine, plus dou cuvinte, (la nceputul
acesteia) n care procedura nscrie limea i lungimea dreptunghiului de imagine.
Mrimea variabilei Buffer este returnat de funcia ImageSize(X1,Y1,X2,Y2) de
tipul WORD i nu poate depi 64KB. Imaginea salvat n buffer poate s fie afiat
din nou utiliznd procedura:
PutImage (X1,Y1,Buffer,WriteMode);
121
Reprezentarea vizual a datelor
n acest apel, (X1,Y1) sunt coordonatele punctului n care se va suprapune
colul stnga-sus al imaginii, iar WriteMode definete modul de scriere a imaginii i
are una din valorile definite pentru procedura SetWriteMode.

Exemplu:
6.19. Se deseneaz un cerc umplut, cu centrul n (50,50) i raza de 40 pixeli.
Imaginea se salveaz i apoi este afiat (restaurat) n punctul (200,50), fiind tears
din vechea sa poziie. Imaginea nou conserv imaginea existent pe ecran.

. . . . . . .
Uses CRT,Graph
. . . . . . .
p:Pointer;
Sz:Word;
. . . . . . . . .
PieSlice(50,50,0,360,40);
Sz:=ImageSize(0,0,50,100);
GetMem(p,Sz);
GetImage(0,0,50,100,p^);
Delay(2000);
PutImage(0,0,p^,XORPut);
PutImage(200,50,p^,XORPut);
. . . . . . . . .

Pagina activ i pagina video. Pentru modurile grafice care suport mai
multe pagini (EGA, VGA etc.), imaginea se poate constitui n pagina activ, n timp
ce pe ecran este afiat pagina video (vezi 6.2). Pentru selecia paginilor se
utilizeaz procedurile:
SetActivePage(NumarPagina);
SetVisualPage(NumarPagina);
n care parametrul NumarPagina, de tipul WORD, poate lua valori naturale,
ncepnd cu zero. Facilitatea de paginare n memoria video asigur o cretere de
vitez i uurin n realizarea imaginilor, mai ales, n animaie.

122







Pentru practica proiectrii, punerii la punct i dezvoltrii programelor,
mediul integrat Turbo Pascal ofer programatorului o serie de tehnici de lucru
speciale i instrumente puternice care s l asiste n acest proces complex.



7.1 Tehnici de reacoperire n construirea
programelor complexe


Programele complexe, de dimensiuni mari (uneori peste spaiul de memorie
disponibil), pot fi concepute modularizat, ntr-o structur arborescent, n care se
disting un modul monitor i mai multe module operaionale. Modulul monitor este
rezident n memorie pe parcursul execuiei programului i apeleaz succesiv
modulele operaionale care pot sau nu s fie prezente simultan n memoria principal.
Reacoperirea este tehnica prin care dou sau mai multe uniti se ncarc la
aceeai adres de memorie, evident nu simultan. Construirea structurilor de
reacoperire este posibil numai pentru modulele constituite ca uniti ale
utilizatorului (unitile standard nu pot face obiectul reacoperirii).
n general, un program realizat cu uniti poate fi construit ca program
executabil n dou forme: cu structur liniar, respectiv cu structur arborescent. La
programele cu structur liniar, spaiul de memorie necesar este dat de suma
lungimilor tuturor unitilor, la care se adaug lungimea programului principal.
Programul, cu toate componentele sale, va fi ncrcat complet n memorie i va
rmne rezident pe tot parcursul execuiei. La programele cu structur arborescent
se poate realiza o structur cu reacoperire (overlay), n care se disting dou tipuri de
componente: componenta rezident (rdcina arborelui), care rmne n memorie pe
tot parcursul execuiei programului; componentele reacoperibile (ramurile arborelui),
care folosesc pe rnd aceeai arie de memorie, n care se ncarc succesiv pe msura
referirii lor, cu eventuala suprascriere (reacoperire) a celor ncrcate anterior.
Componentele reacoperibile sunt formate din uniti ale utilizatorului.
Pe exemplul din figura 7.1, presupunnd c partea rezident este format din
programul principal i unitatea C, iar celelalte uniti se reacoper ntre ele, necesarul
TEHNICI SPECIALE
N PASCAL
123
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
de memorie intern este de 55 Ko, dat de suma lungimilor componentei rezidente i a
celei mai mari ramuri.
Programul principal i
unitile standard (30 KO)
Unitatea C (5 KO)
Unitatea A (10 KO)

Unitatea B (20 KO)
Fig. 7.1 Exemplu de structur cu reacoperire


Pentru construirea i gestiunea structurilor cu reacoperire, mediul de
dezvoltare Turbo Pascal are o component specializat (Overlay Manager), ale crei
proceduri i funcii sunt reunite n unitatea Overlay. Folosirea acestei componente
presupune:
a) Pe planul declaraiilor:
Includerea unitii Overlay n clauza USES a programului principal, cu
obligaia de a fi prima referit.
Introducerea directivelor {$O nume_unitate}, dup clauza USES. Fiecare
directiv nominalizeaz unitatea care va fi inclus n structura de reacoperire (se
genereaz instruciuni care vor include unitatea n fiierul Overlay).
Fiecare unitate care va fi inclus n reacoperire se va compila cu directiva
{$O+}. Prezena acesteia nu realizeaz includerea unitii n reacoperire, ci doar
semnaleaz compilatorului s asigure o structur a codului obiect, care s permit
eventuala sa includere ntr-o astfel de structur. n concluzie, o aceeai versiune de
unitate, compilat cu {$O+}, va putea fi folosit att n structuri cu reacoperire, ct i
n structuri liniare.
Pentru asigurarea generrii tuturor apelurilor dup modelul FAR (cu adres
de segment i cu deplasare), se va folosi directiva de compilare {$F+}, att n
programul principal, ct i n unitile care urmeaz a fi incluse n reacoperire.
b) Pe planul instruciunilor executabile, folosirea tehnicii de reacoperire
presupune apelul unor proceduri i funcii ale unitii Overlay, n cadrul programului
principal (n componenta rezident).
n primul rnd este necesar iniierea programului de gestiune a reacoperirii
segmentelor, naintea execuiei altor instruciuni (inclusiv a celor de iniializare din
uniti). Acest lucru se realizeaz cu procedura OvrInit, definit astfel:
OvrInit(nume_fisier:STRING), unde nume_fisier este numele fiierului, cu
extensia implicit .OVR, n care sistemul ncarc unitile incluse n structura de
reacoperire.
124
Tehnici speciale n Pascal
b) Programul
Pentru exemplul din figura 7.1, pot fi concepute, principial, structurile din
figura 7.2. n cazul n care una dintre unitile apelate conine parte de iniializare,
datorit restriciei ca procedura OvrInit s se execute prima, corelat cu faptul c
partea de iniializare a unei uniti se lanseaz n execuie cu prioritate, va trebui
construit o unitate separat, care s conin n partea de iniializare apelul
procedurii OvrInit i care s fie invocat prima n clauza USES a programului
principal (aceast unitate va conine USES Overlay).

{$O+,F+} {$O+,F+} {$O+,F+} (* Optional *)
UNIT A; UNIT B; UNIT C;
Interface Interface Interface
. . .
Implementation Implementation Implementation
. . .
END. END. END.

a) Unitile

{$O+,F+}
PROGRAM PP; {Apelatorul}
USES Overlay, A,B,C
{$O A}
{$O B}
.
BEGIN
OvrInit(ALFA.OVR);
.
END.


Fig. 7.2 Exemplu de principiu de realizare a unei structuri cu reacoperire

Pe parcursul execuiei programului, folosirea tehnicii de reacoperire se
traduce n ncrcarea succesiv a unitilor, pe msura referirii lor, ntr-un buffer al
structurii de reacoperire, cruia i se asociaz memorie la nceputul zonei heap. La
apelul procedurii OvrInit, mrimea buffer-ului de reacoperire este setat implicit la
mrimea celei mai mari uniti incluse n reacoperire, la care se adaug o zon
suplimentar pentru informaii de interfa. Dimensiunea curent a buffer-ului de
reacoperire n numr de octei poate fi determinat, n orice moment pe parcursul
execuiei programului, prin apelul funciei OvrGetBuf, definit astfel:
OvrGetBuf:Longint.
Referitor la mecanismul de folosire a buffer-ului, trebuie menionat c o
unitate deja ncrcat va fi tears (suprascris), numai dac nu exist suficient spaiu
liber n restul buffer-ului pentru a ncrca urmtoarea unitate. Dac exist spaiu
125
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
suficient, noua unitate va fi ncrcat, evitnd reluarea ncrcrii unora dintre uniti
de fiecare dat cnd sunt referite.
Dac utilizatorul dorete s mreasc dimensiunea buffer-ului, tocmai pentru
a rezolva asemenea probleme, se poate folosi procedura OvrSetBuf, definit astfel:
OvrSetBuf(bufsize:Longint), unde bufsize precizeaz noua mrime a buffer-ului,
care trebuie s fie mai mare dect cea implicit, fr a depi valoarea returnat de
funcia MemAvail: bufsize<=MemAvail+OvrGetBuf (MemAvail returneaz volumul
total de memorie nealocat n heap). Procedura OvrClearBuf elibereaz buffer-ul,
pentru utilizri n alte scopuri.
Pentru a elimina repetarea operaiilor de I/E necesare ncrcrii unitilor din
fiierul asociat structurii de reacoperire, este posibil folosirea memoriei EMS
(Expanded Memory System), prin apelul procedurii OvrInitEMS (fr parametri). n
acest caz, se va asigura ncrcarea fiierului n memoria EMS (dac aceasta are spaiu
suficient), preluarea unitilor n buffer-ul structurii de reacoperire realizn-du-se
foarte rapid, direct din aceast memorie, fr operaii de I/E. Dac nu exist spaiu
suficient, procedura este inefectiv.
Execuia procedurilor i funciilor de gestiune a structurilor de reacoperire se
poate ncheia cu succes sau cu eroare, situaie care poate fi determinat pe baza
folosirii variabilei predefinite OvrResult. n unitatea Overlay sunt declarate mai
multe constante simbolice asociate unor valori ale variabilei OvrResult (anexa 5).



7.2 Tehnica gestiunii proceselor


n cele ce urmeaz, prin proces se desemneaz un program executabil. n
cazul unor sisteme de programe, utilizatorul are de ales ntre dou variante de lansare
n lucru a programelor componente:
- lansare independent, caz n care intercondiionrile dintre programe se
rezolv prin ordinea de execuie a acestora. ntruct procesele nu pot comunica ntre
ele, eventuale informaii privind modul lor de ncheiere vor fi preluate i prelucrate
de sistemul de operare.
- lansare din interiorul altor programe, stabilindu-se raporturi de tipul
proces printe - proces fiu. Pentru sistemele de programe se poate constitui, la limit,
un singur proces printe, cu rol de monitor, care lanseaz succesiv n execuie
procesele fiu. Programul monitor poate prelucra informaiile referitoare la modul de
ncheiere a fiecrui proces fiu i poate lua decizii privind modul de continuare.
Unitatea Dos ofer posibilitatea implementrii acestei soluii prin intermediul unor
proceduri i funcii specifice.
Lansarea n execuie a unui proces fiu se poate realiza cu procedura al
crei antet este: Exec(specif,parametru:STRING). Procedura ncarc n memorie i
lanseaz n execuie programul al crui format executabil se gsete n fiierul cu
126
Tehnici speciale n Pascal
specificatorul specif. Argumentul parametru conine irul de caractere corespunznd
eventualilor parametri dai prin linia de comand la lansarea acestui program.
ntruct este necesar asigurarea de spaiu n memorie i pentru procesul fiu, n
programul corespunznd procesului printe trebuie s se reduc dimensiunea zonei
heap, folosind directiva $M.
Salvarea vectorilor de ntrerupere se realizeaz prin procedura
SwapVectors. Procedura este destinat asigurrii independenei dintre procesul
printe i un proces fiu n folosirea unor rutine de ntrerupere instalate de ctre
cellalt proces. Se apeleaz nainte i dup fiecare apel al procedurii Exec i schimb
ntre ei vectorii de ntrerupere cureni cu pointerii SaveIntxx din unitatea System.
Preluarea codului de retur al unui proces fiu se poate realiza prin funcia:
DosExitCode:WORD. Codul de retur al procesului fiu poate fi poziionat prin
parametrul folosit la apelul rutinei Halt.

Exemplu:
7.1. Se consider un program director (Monitor) care lanseaz n execuie trei
programe, n cadrul unei aplicaii multifunionale. Cele trei programe sunt memorate
n fiierele Fis1.EXE, Fis2.EXE, Fis3.EXE.

PROGRAM Monitor;
{$M 2048,0,0}
USES CRT;
VAR
c:CHAR;
BEGIN
REPEAT
ClrScr;
WriteLn( Functiile realizate de program sunt:);
WriteLn( :5,1 - Semnificatie functia 1);
WriteLn( :5,2 - Semnificatie functia 2);
WriteLn( :5,3 - Semnificatie functia 3);
WriteLn( :5,4 - STOP);
Write (Tastati functia dorita [1-4] : ); Readln( c );
CASE c OF
1: Exec(Fis1,);
2: Exec(Fis2,);
3: Exec(Fis3,);
4: WriteLn(<< Program terminat>>)
ELSE
WriteLn(***Cod eronat de functie***)
END
UNTIL c=4
END.



127
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
7.3 Lansarea programelor n execuie
prin linie de comand


n general, lansarea n execuie a programelor Turbo Pascal este posibil n
dou moduri: din interiorul mediului de programare, prin una din comenzile meniului
Run; la nivelul sistemului de operare, printr-o linie de comand. Prima variant este
util pe parcursul procesului de punere la punct a programelor, iar a doua este
preponderent n exploatarea curent a unui produs-program.
Pentru lansarea prin linie de comand, utilizatorul are posibilitatea includerii,
dup numele fiierului .EXE, a unor parametri destinai programului. Linia de
comand are formatul general:
...>nume parametru [parametru]...
Parametrii sunt iruri de caractere, separate prin spaii sau tab-uri, care sunt
accesibili din programele Turbo Pascal prin dou funcii aparinnd unitii System.
Numrul de parametri din linia de comand poate fi determinat folosind funcia
ParamCount, definit astfel: ParamCount:WORD. Accesul la un anumit parametru
este posibil prin funcia ParamStr, al crei antet are forma:
ParamStr(n:WORD):STRING. Funcia returneaz un ir de caractere care conine
al n-lea parametru de pe linia de comand. Este posibil i apelul de forma
ParamStr(0), caz n care irul returnat conine calea i numele fiierului .EXE asociat
programului.

Exemplu:
7.2. Se consider programul ExDir, care poate prelua din linia de comand
directorul n care se gsesc fiierele aplicaiei, transformndu-l n director curent. Se
asigur salvarea directorului n uz de la momentul lansrii, respectiv restaurarea lui la
ncheierea execuiei programului. Dac noul director nu exist, este prevzut
posibilitatea crerii i activrii lui ca director curent. n cadrul programului,
procedura OpDir asigur urmtoarele operaii: determinarea directorului curent ('D'),
schimbarea directorului curent ('S'), crearea unui nou director ('C'). Procedura
returneaz o variabil de eroare (rez) cnd operaiile asupra directoarelor nu se pot
executa.

PROGRAM ExDir;
VAR
r : INTEGER; c : CHAR;
dinc,dnou: STRING;
PROCEDURE OpDir(op:CHAR; VAR d:STRING; VAR rez:INTEGER);
BEGIN
CASE UpCase(op) OF
'D': GetDir(0,d);
'S': BEGIN {$I-} ChDir(d); {$I+} rez:=IOResult END;
'C': BEGIN {$I-} MkDir(d); {$I+} rez:=IOResult END
END
END;
PROCEDURE DetDir;
128
Tehnici speciale n Pascal
VAR
dir: STRING;
BEGIN
OpDir('d',dir,r);
WriteLn('Director curent: ',dir)
END;
BEGIN
WriteLn('Program in executie curenta: ',ParamStr(0));
DetDir;
IF ParamCount <> 0 THEN
BEGIN
dnou:=ParamStr(1);
OpDir('d',dinc,r);
OpDir('s',dnou,r);
IF r <> 0 THEN
BEGIN
WriteLn('Director inexistent: ',ParamStr(1));
Write('Se creeaza ca director nou?(Y/N): ');
ReadLn(c);
IF UpCase(c) = 'Y' THEN
BEGIN
OpDir('c',dnou,r);
IF r = 0 THEN
OpDir('s',dnou,r)
ELSE
BEGIN
WriteLn('Eroare la creare director. Executie
intrerupta!' );
RunError(r)
END
END
END
END;
DetDir
END; {restul programului se scrie normal}
IF ParamCount <> 0 THEN OpDir('s',dinc,r);
DetDir
END.



7.4 Tehnica tratrii ntreruperilor


Microprocesorul gestioneaz un sistem de ntreruperi. Datorit complexitii
proceselor ce se pot desfura n cadrul sistemului, unitatea central de prelucrare
(UCP) nu poate asigura simultan un control complet, fiind focalizat la un moment
dat pe o singur activitate. Pentru a suplini aceast lips, calculatorul este proiectat
astfel nct, la apariia oricrui eveniment ce presupune o anumit aciune, s se
genereze un semnal de ntrerupere prin care este informat UCP. Aceasta suspend
temporar alte activiti pentru a trata evenimentul aprut, transfernd controlul la o
rutin de tratare a ntreruperii, care poate provoca afiarea unui mesaj de avertizare,
reluarea sau ncheierea execuiei programului (normal, cu eroare sau forat) etc. La
ncheierea execuiei rutinei, UCP revine la activitatea iniial.
Microcalculatoarele IBM PC i compatibile accept 256 de ntreruperi, cu
coduri din intervalul 0..255 (n hexa, $00..$FF). n literatura de specialitate,
ntreruperile se regsesc clasificate n diverse moduri: hardware, software; ale
129
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
microprocesorului, hardware, software, DOS, Basic, de adres, de uz general; ale
microprocesorului, BIOS, ale sistemului de operare (din care fac parte i cele
referitoare la funciile DOS) etc.
Pentru asigurarea accesului la rutinele de ntrerupere, prima zon de 1 Ko din
memoria intern conine o tabel de pointeri ctre fiecare din rutinele disponibile,
dimensionat pentru a putea memora toate cele 256 de adrese teoretic posibile i
numit tabela vectorilor de ntrerupere. Considernd o rutin cu codul i din
intervalul 0..255, pointerul asociat ei n tabel se afl la adresa 4*i.
Utilizatorul poate determina adresa unei rutine de ntrerupere prin procedura
GetIntVec definit n unitatea DOS astfel: GetIntVec(int:BYTE;VAR
adrint:POINTER), unde int reprezint codul ntreruperii precizat n apelator, iar n
adrint se returneaz adresa rutinei de ntrerupere corespunztoare.
Pentru ilustrarea utilizrii acestei proceduri, se prezint programul
TabVectInt care afieaz, n mai multe ecrane succesive, ntreaga tabel a vectorilor
de ntrerupere, cu precizarea codului i a adresei rutinei asociate fiecrei ntreruperi,
cu componentele de segment i deplasare, exprimate n hexazecimal (conversia se
realizeaz de ctre funciile HexOctet i HexCuvint incluse n unitatea Hex).

PROGRAM TabVectInt;
USES Dos,Crt,Hex;
VAR
i : BYTE;
adrint: POINTER;
PROCEDURE Defilare;
VAR
car: CHAR;
BEGIN
GotoXY(1,25);
Write('Press any key ...');
car:=ReadKey;
ClrScr
END;
BEGIN
ClrScr;
FOR i:=0 TO 255 DO
BEGIN
GetIntVec(i,adrint);
IF (i+1) MOD 24 = 0 THEN Defilare;

WriteLn(HexOctet(i):5,HexCuvant(Seg(adrint^)):5,
HexCuvant(Ofs(adrint^)):5)
END;
Defilare
END.

UNIT Hex;
INTERFACE
FUNCTION HexOctet(nroct:BYTE):STRING;
FUNCTION HexCuvint(nrcuv:WORD):STRING;
IMPLEMENTATION
FUNCTION CifraHex(cifra:BYTE):CHAR;
130
Tehnici speciale n Pascal
BEGIN
IF cifra < 10 THEN CifraHex:=Chr(48+cifra)
ELSE CifraHex:=Chr(55+cifra)
END;
FUNCTION HexOctet;
BEGIN
HexOctet:=CifraHex(nroct DIV 16) + CifraHex(nroct
MOD 16);
END;
FUNCTION HexCuvant;
BEGIN HexCuvint:=HexOctet(Hi(nrcuv))+HexOctet(Lo(nrcuv))
END
END.

Apelul rutinei de ntrerupere se realizeaz prin procedura Intr, definit n
unitatea System astfel: Intr(ni:BYTE; VAR reg:Register), unde ni este codul
ntreruperii, iar reg este o variabil care specific, ntr-o form standard, diveri
parametri. Tipul Registers, definit n unitatea Dos (anexa 1), permite accesul la
registrele unitii centrale. nainte de apel, trebuie pregtite anumite registre, n
funcie de parametrii solicitai de ntrerupere. Astfel, n semiregistrul Reg.AH trebuie
ncrcat codul funciei, n Reg.AL codul subfunciei (cnd exist) etc.
Principalele caracteristici ale ntreruperilor (folosindu-se ultima clasificare
prezentat anterior) sunt:
ntreruperile microprocesorului sunt generate de el nsui: 0 corespunde
situaiei de mprire la zero, 2 corespunde erorii de paritate n memorie, 1 i 3 sunt
folosite n depanarea programelor; 5 provoac tiprirea coninutului ecranului pe
imprimant etc. Alte ntreruperi sunt generate de diverse componente hardware din
configuraia sistemului.
rutinele BIOS sunt realizate de ctre productorul echipamentului i
memorate n ROM. La nceputul unei sesiuni de lucru cu calculatorul, adresele din
ROM ale rutinelor BIOS sunt ncrcate n tabela vectorilor de ntrerupere. Cnd un
program cheam o rutin BIOS, Turbo Pascal preia adresa acesteia din tabel i o
execut. Exemple de ntreruperi BIOS: $09 - apsarea unei taste; $10 - servicii video;
$12 - determinarea dimensiunii memoriei existente n sistem; $13 - gestiunea
discurilor; $15 - determinarea unor caracteristici ale memoriei etc.
n programele Int15 i Int12 sunt prezentate exemple de activare a
ntreruperilor $15 i $12. Pentru ntreruperea $15, se apeleaz funcia $88, care
returneaz n registrul AX dimensiunea memoriei extinse exprimat n Ko.
ntreruperea $12 nu folosete registrul AH.

PROGRAM Int15;
USES Dos;
FUNCTION
ExtendedMemory:WORD;
VAR
reg: Registers;
BEGIN
reg.AH:=$88;
Intr($15,Reg);

ExtendedMemory:=reg.AX
END;
BEGIN
WriteLn('Memorie
extinsa= ',
ExtendedMemory,' Ko')
END.

PROGRAM Int12;
USES Dos;
FUNCTION MemorySize: WORD;
VAR
reg: Registers;
BEGIN
Intr($15,Reg);
MemorySize:=reg.AX
END;
BEGIN
WriteLn('Memorie interna= ',
MemorySize,' Ko')
END.

131
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
rutinele de ntrerupere ale sistemului de operare sunt memorate pe disc i
sunt ncrcate n memoria intern la nceputul fiecrei sesiuni de lucru. Acestea
corespund ntreruperilor software. Exemple de ntreruperi SO: $20 - terminare
program; $21 - funcii DOS; $22 - furnizarea adresei de terminare; $24 - rutina de
tratare a erorilor critice.
Una dintre cele mai utilizate ntreruperi este $21 (rutine DOS). Adresele
rutinelor, corespunznd diferitelor servicii DOS, sunt memorate n tabela vectorilor
de ntrerupere, n poziiile neocupate de rutinele BIOS. Exemple de funcii DOS:
$00 - terminare program; $01 - citire cu ecou de la tastatur; $08 - citire fr ecou de
la tastatur; $25 - setarea vectorului de ntrerupere; $2B - setarea datei din sistem;
$2C - citirea datei din sistem; $2D setarea orei din sistem etc.
Apelul unei rutine DOS se poate realiza cu Intr($21,Reg) sau cu o procedur
special definit n unitatea DOS astfel: MsDos(VAR Reg:Registers). ntruct toate
rutinele corespund unor funcii, este obligatorie ncrcarea prealabil a codului
acestora n semiregistrul AH, naintea apelului procedurii MsDos sau Intr.
Aproape toate cele 80 de funcii DOS se regsesc n cele peste 200 de
proceduri i funcii ale unitilor standard din Turbo Pascal. Analiznd evantaiul
posibilitilor ce se deschid programatorului care folosete Turbo Pascal, la extreme
se constat urmtoarele variante de abordare: folosirea exclusiv a procedurilor i
funciilor din unitile standard ale mediului Turbo Pascal (care apeleaz, la rndul
lor, funciile DOS); folosirea direct a rutinelor de ntrerupere asociate funciilor
DOS prin apeluri adecvate ale procedurilor MsDos (sau Intr). Prima soluie este mai
simplu de utilizat n scrierea programului surs, dar cea de-a doua conduce la
creterea vitezei de execuie a programelor. n concluzie, se poate reine
recomandarea ca a doua soluie, care presupune cunoaterea a o serie de detalii
tehnice, s fie folosit doar atunci cnd este important asigurarea unui timp de
rspuns ct mai scurt. Evident, la limit, este posibil "ocolirea" integral a
procedurilor i funciilor din bibliotecile Turbo Pascal, dar nici una din variante nu
poate fi absolutizat.
Pentru analiza comparat a celor dou variante se ilustreaz folosirea lor pe
exemplul funciilor DOS de acces la data din sistem. Accesul din Turbo Pascal se
poate realiza cu procedurile GetDate, pentru preluarea datei curente, respectiv
SetDate, pentru modificarea acesteia. Procedura GetDate are urmtorii parametri,
pentru care se precizeaz i limitele domeniului de valori admis: anul (1980..2099),
luna (1..12), ziua n cadrul lunii (1..31), ziua n cadrul sptmnii (0..6, cu
duminic=0, luni=1, ..., smbt=6). Procedura SetDate folosete numai primii trei
parametri.
n programul Calendar_1 se ilustreaz apelul acestor proceduri pentru
determinarea calendarului unei luni oarecare, din intervalul de ani acceptat
(1980..2099).

PROGRAM Calendar_1;
USES Dos,Crt;
VAR
ac,lc,zc,zsc: WORD;
132
Tehnici speciale n Pascal
an,ln,zn,zsn: WORD;
i,nrz: BYTE;
BEGIN
REPEAT
Write('Luna, an: '); ReadLn(ln,an);
UNTIL (an > 1979) AND (an < 2100) AND (ln IN [1..12]);
zn:=1;
GetDate(ac,lc,zc,zsc);
SetDate(an,ln,zn);
GetDate(an,ln,zn,zsn);
SetDate(ac,lc,zc);
CASE ln OF
1,3,5,7,8,10,12: nrz:=31;
4,6,9,11 : nrz:=30;
2 : IF an MOD 4 =0 THEN nrz:=29 ELSE nrz:=28
END;
ClrScr;
WriteLn(' ',ln:2,' - ',an:4,#13#10);
WriteLn(' L M M J V S D');
WriteLn(' ---------------------');
IF zsn = 0 THEN zsn:=7;
FOR i:=1 TO nrz+zsn-1 DO
BEGIN
IF i <= zsn-1 THEN Write(' ')
ELSE Write(i-zsn+1:3);
IF i MOD 7 = 0 THEN WriteLn
END;
WriteLn;
WriteLn(' ---------------------')
END.

Primul apel al procedurii GetDate asigur salvarea datei curente (n
variabilele ac, lc, zc, respectiv zsc), care se reface prin al doilea apel al procedurii
SetDate. Algoritmul folosit se bazeaz pe faptul c, intern, se asigur determinarea
zilei din sptmn asociat oricrei date din intervalul de ani acceptat. Astfel, dup
solicitarea lunii (ln) i a anului (an) pentru care se cere afiarea calendarului, se va
determina ziua din sptmn (zsn) pentru prima zi a lunii, urmat de toate celelalte.
Rutinele de ntrerupere DOS corespunztoare celor dou proceduri au
codurile $2A, respectiv $2B. Dup apelul rutinei $2A, rezultatele sunt furnizate n
urmtoarele (semi)registre: anul n CX, luna n DH, ziua n cadrul lunii n DL, iar
ziua n cadrul sptmnii n AL. Corespunztor, apelul rutinei $2B trebuie precedat
de ncrcarea valorilor asociate noii date din sistem n CX, DH i DL.
Folosirea acestei soluii presupune: adugarea unei declaraii de forma:
reg1,reg2: Registers; nlocuirea celor patru instruciuni de apel al procedurilor
GetDate i SetDate cu urmtoarea secven (restul programului rmnnd
nemodificat):


reg1.AH:=$2A;
MsDos(reg1);
ac:=reg1.CX;
lc:=reg1.DH;
zc:=reg1.DL;
zsc:=reg1.AL;
reg2.AH:=$2B;
reg2.CX:=an;
reg2.DH:=ln;
reg2.DL:=zn;
MsDos(reg2);

reg1.AH:=$2A;
MsDos(reg1);
zsn:=reg1.AL;
reg2.AH:=$2B;
reg2.CX:=ac;
reg2.DH:=lc;
reg2.DL:=zc;
MsDos(reg2);


133
Programarea calculatoarelor Tehnica programrii n limbajul Pascal


7.5 Tehnici de lucru la ncheierea execuiei programelor


ncheierea execuiei unui program este un eveniment important, care trebuie
tratat de programator cu toat atenia. Turbo Pascal asigur utilizatorului posibilitatea
implicrii directe, att n declanarea acestui eveniment, ct i n realizarea unor
prelucrri suplimentare asociate lui.
Terminarea unui program poate fi de mai multe categorii: normal, cu eroare
la execuie, forat. n primele dou cazuri, decizia de terminare a execuiei aparine
sistemului, iar n ultimul terminarea se execut naintea atingerii sfritului logic al
programului, la solicitarea expres a utilizatorului.
Variabilele ExitCode i ErrorAddr, definite n unitatea System, conin
informaii privind modul de ncheiere a execuiei. La ncheierea cu eroare la execuie,
ExitCode va conine numrul erorii, iar ErrorAddr puncteaz pe codul asociat
instruciunii care a generat aceast eroare. La lansarea n execuie a unui program,
cele dou variabile au valorile iniiale 0, respectiv nil. La ncheiere normal, situaia
celor dou variabile este ExitCode=0 i ErrorAddr=nil. Mediul Turbo Pascal
determin dac este necesar afiarea unui mesaj de eroare la execuie, pe baza
valorii variabilei pointer ErrorAddr. Mesajul de eroare se afieaz numai dac
ErrorAddr nil.
Teoretic, ncheierea forat a execuiei, naintea atingerii sfritului logic al
programului, contravine principiilor programrii structurate. Totui, practica
programrii conduce la situaii cnd o asemenea ncheiere devine necesar, dar se
recomand limitarea folosirii ei numai la cazurile cnd nu sunt posibile i alte soluii.
Procedura de ncheiere a execuiei blocului curent are antetul de forma:
Exit. n cazul subprogramelor, apelul procedurii provoac revenirea n apelator
(blocul din care a fost apelat subprogramul), iar pentru programe determin
ncheierea execuiei.
Procedura de ncheiere a execuiei cu un cod de retur precizat de utilizator
este definit astfel: Halt[(ExitCode:WORD)]. La apelul procedurii cu parametru,
ExitCode va primi valoarea transferat la execuia apelului, iar n cazul apelului fr
parametru rmne pe valoarea 0; n ambele cazuri, ErrorAddr rmne cu valoarea nil.
Prin apelul procedurii (care poate fi plasat chiar la sfritul logic al programului, fr
a nclca principiile programrii structurate), se poate face distincia ntre mai multe
moduri de terminare normal a unui program.

Exemplu:
7.3. Fiind dat un vector de mari dimensiuni, memorat ntr-un fiier binar, s
se realizeze programul de ventilare a fiierului cu obinerea a dou fiiere binare, cu
valorile pozitive, respectiv negative ale fiierului (valorile nule vor fi neglijate).
Programul Ventilare realizeaz ncheierea execuiei cu apelul procedurii Halt, care,
134
Tehnici speciale n Pascal
prin poziionarea codului de retur, permite distincia ntre diversele moduri de
ncheiere a execuiei: ambele fiiere nevide, ambele fiiere vide, respectiv unul sau
altul dintre fiierele de ieire vid.

PROGRAM Ventilare;
VAR
fi,fp,fn: FILE OF INTEGER;
v : INTEGER;
np,nn:WORD;
BEGIN
Assign(fi,'FI.DAT'); Assign(fp,'FP.DAT');
Assign(fn,'FN.DAT');
Reset(fi); Rewrite(fp); Rewrite(fn);
WHILE NOT Eof(fi) DO
BEGIN
Read(fi,v);
IF v > 0 THEN Write(fp,v)
ELSE IF v < 0 THEN Write(fn,v)
END;
np:=FileSize(fp); nn:=FileSize(fn);
IF (np <> 0) AND (nn <> 0)
THEN Halt {0 - ambele fisiere nevide}
ELSE IF np <> 0
THEN Halt(1) {1 - fisierul FN vid}
ELSE IF nn <> 0
THEN Halt(2) {2 - fisierul FP vid}
ELSE Halt(3) {3 - ambele fisiere vide}
END.

La revenirea n contextul de lansare a programului n execuie, exist soluii,
oferite de mediul Turbo Pascal (prin variabila DosExitCode) sau de sistemul de
operare DOS, pentru testarea valorii codului de retur i luarea unor decizii adecvate
de continuare a prelucrrilor. n programul GestProc se creeaz fiierul binar iniial,
se lanseaz n execuie programul Ventilare (considerat memorat n fiierul
VENT.EXE) i se prelucreaz codul de retur.

PROGRAM GestProc;
USES Dos;
{$M 2048,0,0}
VAR
fi : FILE OF INTEGER;
vi,n,i: INTEGER;
r : WORD;
BEGIN
Write('Numar de elemente si valoare initiala:');
ReadLn(vi,n);
Assign(fi,'FI.DAT');
Rewrite(fi);
FOR i:=vi TO vi+n-1 DO Write(fi,i);
Close(fi);
SwapVectors;
Exec('VENT','');
SwapVectors;
r:=DosExitCode;
IF r = 0 THEN
WriteLn('OK!')
ELSE IF r = 1 THEN
135
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
WriteLn('Fisierul FN vid')
ELSE IF r = 2 THEN
WriteLn('Fisierul FP vid')
ELSE
WriteLn('Ambele fisiere vide')
END.

Procedura de ncheiere cu eroare de execuie este definit astfel:
RunError[(ExitCode:WORD)]. La apelul fr parametru, ExitCode rmne cu
valoarea 0, iar n cazul apelului cu parametru valoarea parametrului real va fi
atribuit variabilei ExitCode.

Exemplu:
7.4. n programul Valid se realizeaz introducerea cu validare a unei valori
numerice, cu reluare pn la furnizarea unei valori corecte, respectiv pn la
depirea unui numr limit de reluri.
PROGRAM Valid;
VAR n,i,er : BYTE; x : REAL;
BEGIN
Write('Numar maxim admis de reluari:'); ReadLn(n); i:=0;
REPEAT
er:=0;
Write('x:'); {$I-} ReadLn(x); {$I+}
IF IOResult <> 0 THEN
BEGIN
Write('Valoare nenumerica');
er:=1
END;
Inc(i)
UNTIL (er = 0) OR (i > n);
IF i > n THEN
BEGIN
Write('Depasire numar de reluari admis');
RunError(106);
END
END.

Soluia propus conduce la ntreruperea forat prin apelul RunError, la
depirea numrului de repetri admis, cu mesajul standard de eroare corespunztor
codului dat de utilizator:
Runtime error 106: Invalid numeric format

Includerea rutinelor proprii de ncheiere a execuiei programelor. Pe lng
operaiile realizate de sistemul de operare MS-DOS, Turbo Pascal este prevzut cu
cteva rutine de serviciu, a cror lansare, ntr-o anumit succesiune, este declanat
implicit la terminarea execuiei unui program. La apariia evenimentului de terminare
a unui program, controlul este transferat primei proceduri din lanul rutinelor de
ncheiere a execuiei (exit procedures), a crei adres este memorat n variabila
ExitProc.
Utilizatorul are posibilitatea s includ propria rutin de tratare a terminrii,
al crei apel se va insera la nceputul lanului de apeluri. n acest scop, variabila
136
Tehnici speciale n Pascal
ExitProc va fi setat pe adresa procedurii proprii, cu asigurarea refacerii valorii
iniiale dup ncheierea execuiei acestei proceduri, asigurndu-se astfel continuarea
cu procedurile implicite de ncheiere.
Procedurile de ncheiere proprii ofer programatorului un mijloc de a
controla - nu i de a preveni - terminarea unui program. De exemplu, dac programul
folosete o imprimant, n acest mod se poate asigura sesizarea momentului pentru
extragerea ultimei pagini. Tehnica de includere n lan a procedurii proprii este
ilustrat n programul Ex_ExitProgram.

PROGRAM Ex_ExitProgram;
VAR
ExitOrig: POINTER;
{F+}
PROCEDURE ExitPropriu;
{$F-}
BEGIN
{Instructiuni ale utilizatorului la terminarea programului }
WriteLn('Terminarea programului...');
ExitProc:= ExitOrig; {restaurarea adresei rutinei implicite
de incheiere a executiei}
END;
BEGIN
ExitOrig:=ExitProc; {salvarea adresei rutinei implicite de
incheiere a executiei}
ExitProc:=@ExitPropriu; {includerea rutinei proprii de
incheiere la inceputul lantului de apeluri}
{Restul programului se scrie normal}
END.

Dei procedura ExitPropriu nu este chemat explicit, ea va fi prima
procedur apelat la terminarea execuiei programului, efectul vizibil fiind afiarea
mesajului inclus n cadrul ei. Se remarc folosirea directivei {$F}, necesar pentru a
fora tratarea procedurii ExitPropriu ca "ndeprtat" (far). Acest lucru este necesar
deoarece rutinele de ncheiere implicite aparin segmentului de cod al unitii
System, n timp ce procedura ExitPropriu este inclus n segmentul de cod al
programului principal.



7.6 Punerea la punct a programelor Turbo Pascal


n raport de momentul n care se manifest, pot fi identificate trei categorii
de erori: de compilare, la execuie i de logic.
Erorile de compilare (Compile-Time Errors) sunt, n general, rezultatul unor
greeli lexicale sau sintactice. Erorile lexicale apar cnd un identificator, un literal
sau un simbol folosit n program este ilegal. De exemplu, considernd declaraia:
CONST hex1=$FFHH;
137
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
se produce eroare lexical, deoarece n specificarea valorii constantei hexa apar
caractere nepermise (HH). Eroarea este semnalat printr-un mesaj de forma: Error 7:
Error in integer constant. O eroare similar ar produce i folosirea unui literal hexa
$-12, deoarece aceti literali nu pot avea semn.
Declaraia de constant simbolic:
CONST sir='pret unitar=;
genereaz eroare lexical, compilatorul interpretnd absena apostrofului de nchidere
a irului, n sensul urmtorului mesaj: Error 8: String constant exceeds line.
Erorile sintactice corespund cazurilor n care unele construcii folosite n
program ncalc regulile formale ale limbajului, cum ar fi specificarea unui numr
greit sau de tipuri neadecvate de parametri n apelul unor proceduri sau funcii,
omiterea caracterului ";" la ncheierea unei instruciuni sau folosirea lui ntr-un
context nepermis etc. Mesajele nu sunt ntotdeauna foarte explicite, dar deplasarea
cursorului n fereastra Turbo Pascal, exact n locul n care a fost sesizat eroarea, l
va ajuta pe utilizator s determine cauza acesteia. n plus, la folosirea tastei F1 se
afieaz o fereastr de informare cu explicaii suplimentare privind semnificaia
erorii. De semnalat faptul c unele erori, care la o prim analiz par lexicale, sunt
interpretate de compilator ca erori de sintax. Se consider declaraia:
VAR pret-unitar: REAL;
n sens strict, s-a produs o eroare lexical, identificatorul fiind construit
incorect ("-" n loc de "_"). Totui, mesajul de eroare al compilatorului este Error 86:
":" expected i nici cel suplimentar, afiat la apsarea tastei F1, A colon doesn't
appear where it should nu este cu mult mai explicit. Compilatorul interpreteaz c
identificatorul este pret, dup care, fiind n seciunea VAR a unui program, ateapt
caracterul ":", care ar trebui s urmeze n sintaxa declaraiei. Deoarece cursorul se
plaseaz sub caracterul "-", este de presupus c utilizatorul va sesiza uor adevrata
cauz a erorii.
n multe cazuri, eroarea sintactic este sesizat dup locul strict n care s-a
produs, n momentul n care compilatorul constat absena unui element pe care l
atepta n contextul respectiv. De exemplu, considernd secvena:

VAR
pret_unitar: REAL
BEGIN
absena caracterului ";" de ncheiere a declaraiei variabilei se sesizeaz doar la
nceputul liniei urmtoare, mesajul de eroare fiind: Error 85: ";" expected, iar
cursorul se va plasa la nceputul cuvntului BEGIN.
Pentru o instruciune de forma:
IF a > b THEN WriteLn(a,' > ',b);
ELSE WriteLn(a,' <= ',b);
mesajul de eroare este: Error 113: Error in statement. Cauza erorii este folosirea
incorect a terminatorului ";" la ncheierea ramurii THEN a instruciunii IF, iar
eroarea este sesizat la ntlnirea lui ELSE, cu plasarea cursorului la nceputul
138
Tehnici speciale n Pascal
acestuia. La folosirea tastei F1 se afieaz fereastra de informare cu mesajul This
symbol can't start a statement, care, de aceast dat, este suficient de explicit.
Erorile la execuie (Run-Time Errors) se mai numesc i semantice i apar
atunci cnd instruciuni valide pe plan sintactic sunt combinate incorect. Printre
cazurile mai frecvente din aceast categorie pot fi menionate: ncercarea de a realiza
operaii I/O cu fiiere nedeschise, tentativa de citire dincolo de sfritul unui fiier,
depirea domeniului de valori permis pentru unele tipuri de variabile, depirea
stivei, mprire la zero etc. n toate cazurile, execuia programului se ncheie
anormal, se afieaz un mesaj de eroare, iar cursorul se deplaseaz n fereastra de
editare a mediului Turbo Pascal, n contextul din care s-a generat eroarea,
ateptndu-se intervenia utilizatorului. Trebuie menionat c, depinznd de modul de
folosire a unor directive de compilare, programatorul poate inhiba sau nu semnalarea
unora dintre erori sau poate prelua controlul n caz de eroare, evitnd ncheierea
anormal i prematur a programului.
Un exemplu tipic din prima categorie este directiva {$R}, pentru controlul
depirii domeniului de valori al datelor de tip ntreg. ntruct valoarea ei implicit
este {$R-}, execuia programului:
VAR a: BYTE;
BEGIN
a:=255; a:=a+1;
END.
se va ncheiea fr eroare, dei la a doua operaie de atribuire se depsete domeniul
de valori admis pentru tipul BYTE. Introducnd n program o prim linie cu directiva
{$R+}, execuia se ncheie cu eroare, afindu-se mesajul Error 201: Range check
error, iar cursorul se va plasa la nceputul instruciunii care a generat eroarea.
Un exemplu pentru evitarea ncheierii anormale l poate constitui directiva
{$I}, care permite programatorului preluarea controlului n caz de eroare la realizarea
operaiilor de intrare/ieire (programul Valid).
Mesajele erorilor de execuie au forma: Runtime error 106 at ssss:dddd,
unde ssss reprezint segmentul, iar dddd deplasarea corespunznd adresei
instruciunii la care s-a produs eroarea. Execuia se ntrerupe, iar cursorul se va
deplasa pe linia din programul surs cu instruciunea care a generat eroarea (n
exemplul considerat, linia cu instruciunea de apel al procedurii ReadLn).
Erorile de logic (Logic Errors) sunt cel mai greu de ndeprtat, deoarece
programul se poate ncheia "normal", dar rezultatele nu sunt cele ateptate. Acestea
sunt generate de greelile de proiectare a programelor. Pentru depistarea lor este
necesar, de multe ori, folosirea unor tehnici speciale de depanare.
Depanarea interactiv se realizeaz n cadrul unei sesiuni de depanare, care
presupune execuia supravegheat a programului. Utilizatorul are posibilitatea s
aleag ntre: folosirea unui depanator integrat (Integrated Debugger), inclus n
mediul de programare; folosirea unui depanator autonom (Standalone Debugger),
respectiv pachetul de programe Turbo Debugger al firmei Borland.
Folosirea depanatorului integrat, abordat n cele ce urmeaz, presupune
setarea comutatorului Options|Debugger|Integrated. n procesul de depanare
139
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
interactiv pot fi identificate dou etape: pregtirea sesiunii de depanare, respectiv
desfurarea acesteia.
Pregtirea sesiunii de depanare interactiv corespunde operaiilor ce se
desfoar pe parcursul fazelor de compilare i editare de legturi i care, prin
informaiile produse, condiioneaz desfurarea sesiunii propriu-zise. Informaiile
necesare procesului de depanare sunt generate de directive de compilare sau de
comenzi echivalente din meniul Options. Folosirea depanatorului integrat depinde de
modul de specificare a directivelor de compilare {$D} i {$L}, crora le corespund
comutatoarele Options|Compile|Debug Information, respectiv
Options|Compile|Local Symbols.
Directiva {$D} activeaz sau inhib generarea unor informaii de depanare,
care constau dintr-o tabel ce precizeaz corespondena dintre numerele liniilor din
programul surs ce conin instruciuni executabile i adresa codului obiect generat
pentru fiecare dintre ele. Valoarea implicit a acestei directive este {$D+} i folosirea
ei permite execuia pas cu pas i definirea punctelor de ntrerupere n programele
compilate n acest mod. n plus, la apariia unor erori la execuie, comanda
Compile|Find Error asigur localizarea automat a instruciunii ce a produs eroarea.
Directiva condiioneaz i obinerea aa numitei "mape" a editorului de legturi,
respectiv un fiier cu extensia .MAP, ale crui caracteristici i coninut depind de
modul de setare a butoanelor radio din grupul Options|Linker|Map File:
(.) Off
( ) Segments
( ) Public
( ) Detailed
Butonul Off este selectat implicit i are ca efect neproducerea fiierului
.MAP. La selectarea butonului Segments, fiierul va conine informaii privind adresa
de start, lungimea i numele segmentelor de cod, date i stiv, precum i adresa de
nceput a zonei heap. Alegerea butonului Public face ca, pe lng informaiile privind
segmentele, n fiierul .MAP s se includ un tabel cu adresele obiectelor "publice",
adic ale subprogramelor interne, ale constantelor cu tip i ale variabilelor globale
definite n program, precum i ale variabilelor globale ale unitilor folosite (n
absena clauzei USES, numai cele ale unitii System). De asemenea, se precizeaz
adresa punctului de lansare n execuie a programului (program entry point). Cu
butonul Detailed se afieaz, n plus, un tabel cu numerele liniilor cu instruciuni
executabile din programul surs, urmate de adresa codului obiect generat n cadrul
segmentului de cod al programului principal. Sunt incluse i instruciunile
executabile ale eventualelor subprograme interne.
Directiva {$L} activeaz sau inhib generarea unor informaii despre
simbolurile locale, adic variabilele i constantele declarate n cadrul subprogramelor
interne ale unui program. Valoarea implicit a directivei este {$L+} i folosirea ei
condiioneaz examinarea i modificarea variabilelor locale, precum i urmrirea
succesiunii de generare i execuie a apelurilor de proceduri i funcii interne.
Directivele {$D} i {$L} se folosesc de obicei mpreun, cu precizarea c
{$L} este ignorat dac {$D} nu este activ. Pentru depanare, pentru a nu fi
140
Tehnici speciale n Pascal
condiionai de eventualele setri implicite pe parcursul sesiunii de lucru, se
recomand includerea la nceputul programului a configuraiei: {$D+,L+}. Deoarece
att {$D+} ct i {$L+} genereaz spaiu de memorie suplimentar, dup punerea la
punct a programelor se recomand resetarea acestora.
Desfurarea sesiunii de depanare interactiv. Depanatorul integrat ofer
utilizatorului mai multe comenzi incluse n meniurile Run, Debug i Window ale
mediului Turbo Pascal, utile n procesul de depanare: execuia pas cu pas a
programelor, cu sau fr execuia n aceeai manier a subprogramelor; vizualizarea
valorilor unor variabile (mai general, expresii), cu eventuala modificare a acestora;
crearea unor puncte de ntrerupere; vizualizarea coninutului stivei. n practica
programrii, comenzile se grupeaz pe parcursul sesiunii de depanare n funcie de
obiectivele urmrite. Sesiunea de depanare este format din urmtoarele componente:
deschiderea sesiunii; sesiunea propriu-zis; nchiderea sesiunii. Chiar dac tehnicile
de depanare sunt diferite, n cadrul lor se regsesc cel puin dou elemente comune:
execuia pas cu pas a instruciunilor, urmrirea n paralel a rezultatelor obinute.


a) Deschiderea sesiunii se realizeaz cu una din comenzile meniului Run:
- Run|Trace Into (F7) sau Run|Step Over (F8), cnd se urmrete
depanarea de la nceputul programului;
- Run|Go to Cursor (F4), n cazul unei depanri dintr-un anumit punct.
n primul caz, efectul comenzii este afiarea unei bare de execuie (run bar),
care supralumineaz linia BEGIN a programului principal. n al doilea caz, anterior
deschiderii sesiunii are loc deplasarea cursorului pe o anumit linie, iar la folosirea
comenzii se execut instruciunile n mod normal pn la linia marcat, dup care se
intr ntr-o manier de lucru asemntoare variantei anterioare.
O variant a depanrii dintr-un anumit punct o constituie crearea punctelor
de ntrerupere (breakpoints), cu ajutorul crora se selecteaz instruciunile din
program corespunznd locurilor unor prezumtive greeli de logic. Crearea punctelor
de ntrerupere se realizeaz anterior deschiderii sesiunii de depanare propriu-zise,
prin deplasarea cursorului n textul surs n contextul respectiv i folosirea comenzii
Debug|Toggle breakpoint (sau <Ctrl><F8>). Punctul de ntrerupere va fi marcat
printr-o bar luminoas, iar n timpul sesiunii de depanare execuia programului se va
ntrerupe nainte de executarea instruciunilor de pe linia marcat. Comanda poate
realiza i eliminarea punctelor de ntrerupere, dac este folosit pentru linii unde
exist deja definite asemenea puncte. Punctele de ntrerupere pot fi gestionate i cu
comanda Debug|Breakpoints, care, prin intermediul unei ferestre de dialog, permite
tergerea unor puncte (butonul de comand Delete), definirea unor noi puncte de
ntrerupere sau modificarea caracteristicilor celor existente (butonul de comand
Edit).
b) Sesiunea propriu-zis corespunde aplicrii unor tehnici de depanare,
bazate pe folosirea ntr-o anumit succesiune a unor comenzi din meniurile Debug i
Window, dup deschiderea acesteia cu una din comenzile menionate ale meniului
141
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Run. Urmrirea valorilor variabilelor este asociat cu execuia pas cu pas, de la
nceput sau dintr-un anumit punct, fiind posibil urmrirea modului cum evolueaz
valorile unor variabile (mai general, expresii) pe msura execuiei instruciunilor. n
consecin, fie de la nceput, fie pe parcursul sesiunii, este necesar precizarea
variabilelor (expresiilor) ale cror valori vor fi afiate ntr-o fereastr de urmrire
(watch window). Se folosesc comenzile din submeniul Debug|Watch, prin care se
poate specifica: includerea unui nou element (Add watch); tergerea unui element
(Delete watch); modificarea unui element (Edit Watch).
Submeniul are o fereastr proprie de dialog cu un cmp de intrare n care se
realizeaz operaii asupra elementului curent din lista expresiilor de urmrit, marcat
printr-o bar luminoas. La prima introducere a unui element n list are loc automat
deschiderea ferestrei de urmrire i amplasarea acestuia la nceputul listei, cu afiarea
valorii sale (la nceputul sesiunii valoarea este nedefinit).
Desfurarea sesiunii presupune execuia pas cu pas a instruciunilor, de la
nceput sau din punctul ales, cu afiarea valorilor variabilelor (expresiilor) incluse n
fereastra de urmrire. Activarea ferestrei de urmrire, att pentru urmrirea prin
defilare a tuturor valorilor ct i pentru operaii de editare asupra listei, se realizeaz
cu comanda Window|Watch.
Urmrirea coninutului stivei este legat de lucrul cu subprograme proprii,
permind controlul succesiunii apelurilor de proceduri i funcii, pn la atingerea
apelului procedurii aflat curent n execuie. Se bazeaz pe folosirea comenzii
Window|Call stack (<Ctrl><F3>), care deschide o fereastr pentru afiarea
succesiunii apelurilor de subprograme.
c) nchiderea sesiunii se realizeaz cu comanda Run|Program reset
(<Ctrl><F2>).
142











Sistemul de operare gestioneaz o structur arborescent de [sub]directoare i
fiiere. La fiecare nivel din arborescen exist tabele care ncorporeaz informaii de
legtur i identificare a ascendenilor i descendenilor. n suportul extern, un fiier
are, pe lng partea de date, o intrare n [sub]directorul printe, numit n continuare i
etichet. Aceasta memoreaz caracteristicile externe ale fiierului, cum ar fi: numele
extern, extensia, atributele, data i ora ultimei scrieri n fiier etc. Programele
utilizatorului pot avea acces la unele informaii memorate n etichetele fiierelor i n
alte tabele din structura DOS a discurilor, prin funcii i proceduri adecvate.



8.1 Structura fizic a discurilor DOS


Un disc magnetic, n structur DOS, este compus din urmtoarele pri: tabele
de alocare a fiierelor, tabela directorului rdcin, zona de date a fiierelor. n plus,
discul sistem mai conine zona programului de ncrcare a sistemului de operare
(BOOT), localizat pe primul sector al primei piste. Fiecare fiier (subdirector) are o
intrare (tip etichet) n directorul (subdirectorul) printe.
Tabela de alocare a fiierelor (FAT) este mprit n cmpuri care co-
respund cluster-elor de pe disc. Cluster-ul este format din unul sau mai multe sectoare
i reprezint unitatea de alocare pe disc. Numrul de sectoare ale unui cluster este
memorat n blocul de parametri ai BIOS i difer de la un tip de disc la altul (flexibil
sau Winchester) i de la un tip de calculator la altul. Oricum, el este o putere a lui doi.

Exemplu:
8.1. Disc flexibil simpl fa - 2
0
sectoare/cluster; disc flexibil dubl fa - 2
1
sec-
toare/cluster; disc Winchester pentru PC/AT - 2
2
sectoare/cluster; disc Winchester
pentru PC/XT - 2
3
sectoare/cluster.
PRELUCRAREA ETICHETELOR
DE FIIER I A ALTOR INFORMAII
EXTERNE MEMORATE N DISCURI
143
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Cmpurile din FAT au 16 bii (un cuvnt), prin care se pot adresa 2
16
clustere
(la unele sisteme, cmpurile din FAT au 12 bii).
Primul cuvnt din FAT (cu numrul zero) conine identificatorul tabelei de
alocare, numit i descriptorul suportului. El indic, codificat, tipul de disc utilizat. Al
doilea cuvnt din FAT (cu numrul unu) conine FFFF
16
. ncepnd de la cuvntul cu
numrul doi, sunt memorate lanuri de alocare pentru fiecare fiier. Un cuvnt din FAT
poate avea urmtorul coninut:
0000
16
- cluster-ul corespunztor este disponibil;
FFF0
16
-FFF6
16
- cluster-ul corespunztor este rezervat;
FFF7
16
- cluster-ul corespunztor este defect;
FFF8
16
-FFFF
16
- sfritul lanului de alocare;
0002
16
-FFEF
16
- adresa urmtorului cuvnt din FAT, corespunztor urmtorului clus-
ter ocupat de datele fiierului.
Lanul de legturi este realizat prin aceea c fiecare cuvnt indic numrul
urmtorului cuvnt din lan. Fiierul nu ocup o zon continu n disc. El are cel puin
un cluster (cnd are un singur cluster, cuvntul corespunztor din FAT este FFFF
16
).

Exemplu:
8.2. n figura 8.1 se prezint o tabel de alocare i lanul de legturi realizat
pentru un fiier, Fis.

Pentru fiierul Fis sunt alocate cluster-ele 09-0C, 14-16, 18-19. Cluster-ul 17
este defect. Cluster-ele 0D-13, 1A-1F sunt disponibile. Un alt lan ncepe cu cluster-ul
02 i se termin cu cluster-ul 07.
Prin algoritmi corespunztori, MS-DOS face conversia de la adres de cluster
la adres de sector. Pentru a evita pierderea informaiilor, n cazul deteriorrii unor
cmpuri, n disc sunt pstrate dou exemplare (adiacente) din FAT.
Zona tabelei directorului rdcin (DIR) urmeaz, n suport, tabelei de
alocare a fiierelor i conine cte o intrare pentru fiecare fiier sau subdirector
descendent. Intrarea este o zon de 32 octei cu o structur prestabilit. Fiecare disc are

Fig. 8.1 Exemplu de tabel de alocare
144
Prelucrarea etichetelor de fiier i a altor informaii externe memorate n discuri




un singur director rdcin, cruia i este asociat zona DIR. Dimensiunea i poziia
tabelei DIR sunt fixe, prestabilite prin comanda FORMAT, n momentul formatrii
discului. Numrul de intrri n DIR i poziia tabelei n disc sunt memorate n blocul de
parametri ai BIOS-ului. Dac discul este de sistem, primele dou intrri din DIR se
refer la fiiere care conin sistemul de operare (aceste fiiere sunt ncrcate n memoria
principal de ctre ncrctor, care se afl n sectorul zero al discului).
Zona de date a fiierelor (FILE) conine partea de date a acestora i
subdirectoarele. Subdirectoarele sunt tratate ca fiiere, cu articole speciale, de cte
32 octei. Structura intrrilor n subdirectoare este identic cu cea a intrrilor n director.
Numrul intrrilor n subdirectoare este nelimitat (spre deosebire de intrrile n
director). Sectoarele din zona de date sunt grupate n clustere care au cte un cuvnt
corespondent n FAT. Cnd un fiier (subdirector) este extins, se caut n FAT clustere
libere (cuvinte cu coninutul 0000
16
) i se prelungete lanul de alocare. Dac discul este
de sistem, fiierele IO.SYS i MSDOS.SYS sunt primele n zona de date.



8.2 Structura intrrilor n [sub]directoare


Fiecrui fiier sau subdirector i corespunde o intrare (etichet) n [sub]directo-
rul printe. Intrrile au lungimea 32 octei. Subdirectoarele se comport ca nite fiiere
cu articole speciale, gestionate de DOS. Structura unei intrri este prezentat n
tabelul 8.1.
Numele fiierului este format din 8 caractere, primul avnd urmtoarele
semnificaii:
00 - Intrarea n director nu a fost folosit;
2E - Intrarea corespunde unui [sub]director. 2E
16
reprezint caracterul
ASCII ".". Zona 1A-1B a intrrii conine mrimea subdi-
rectorului, exprimat n numere de clustere. Dac i octetul 01
al intrrii este tot 2E
16
, zona 1A-1B conine adresa de nceput
n FAT a lanului de alocare a subdirectorului printe (zona
1A-1B conine 0000
16
dac printele este directorul rdcin).
n ambele situaii, octeii 01-0A, respectiv 02-0A conin
caracterul spaiu;
E5 - Fiierul a fost ters;
Alt valoare - Primul caracter al numelui de fiier (subdirector).
Din analiza structurii numelui se poate deduce c se selecteaz urmtoarele
tipuri de intrri: intrare normal de fiier (subdirector) fiu; intrare de tip "."; intrare de
tip "..". O mai bun precizare a tipului de intrare se realizeaz prin cmpul de atribute.
145
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Tabelul 8.1 Structura intrrilor n [sub]director
Octei Semnificaie
00 - 07 Numele fiierului
08 - 0A Extensia fiierului
0B Atributele fiierului
0C - 15 Octei rezervai
16 - 17 Ora ultimei scrieri n fiier
18 - 19 Data ultimei scrieri n fiier
1A - 1B Adresa de nceput n FAT a lanului de alocare a fiierului
1C - 1F Dimensiunea fiierului, n numr de octei

Atributele fiierului au semnificaia din tabelul 8.2. Prin setarea sau ter-
gerea corespunztoare a biilor octetului 0B pot fi obinute i alte combinaii de atribute
(cea mai utilizat este valoarea 03
16
, care ar corespunde unui fiier readonly ascuns).
nsumarea tuturor valorilor (3F
16
) desemneaz un fiier oarecare (orice fiier).

Ora ultimei scrieri n fiier este memorat pe doi octei i are structura din
figura 8.2, unde:
O reprezint ora, cu valori binare cuprinse n intervalul [0,23];
M reprezint minutul, cu valori binare cuprinse n intervalul [0,59];
S reprezint numrul de incremente de dou secunde, exprimat n binar.

Data ultimei scrieri n fiier este memorat pe doi octei i are structura din
figura 8.3, unde:

Fig. 8.2 Structura orei ultimei scrieri n fiier
Fig. 8.3 Structura datei ultimei scrieri n fiier
146
Prelucrarea etichetelor de fiier i a altor informaii externe memorate n discuri




A este anul relativ la 1980, cu o valoare binar din intervalul [0-119];

L este luna exprimat n binar (valori din intervalul [1,12]);

Z este ziua exprimat n binar (valori din intevalul [1,31]).
Att pentru ora, ct i pentru data ultimei scrieri exist proceduri PASCAL care
"mpacheteaz", respectiv "despacheteaz", informaia.

Tabelul 8.2 Atributele unui fiier (octetul 0B al intrrii n [sub]director)

Valoarea octetului
0B
S e m n i f i c a i e
Bii
Hexa

76543210
00000000 00 Fiier obinuit. Asupra lui se pot realiza operaii de
citire i scriere.
00000001 01 Fiier readonly. Fiierul este protejat la scriere. Din
el se poate doar citi. Fiierul nu poate fi ters.
00000010 02 Fiier ascuns (hidden). Fiierul nu poate fi gsit
prin operaii obinuite de cutare n directori. Nu
poate fi afiat prin comanda DIR din DOS i nu
este disponibil prin comenzile COPY, DEL, REN,
XCOPY.
00000100 04 Fiier de sistem (system). Se refer la sistemul de
operare i este un fiier ascuns.
00001000 08 Identificator de volum. Un singur fiier, aflat n
directorul rdcin, are acest atribut.
00010000 10 [Sub]director (intrarea se refer nu la un fiier de
date, ci la un [sub]director).
00100000 20 Fiierul este de tip arhiv (archive). Bitul este
poziionat pe valoare 1 ori de cte ori are loc o
scriere n fiier. Bitul redevine zero n urma unei
procesri cu comenzile BACKUP, RESTORE,
XCOPY din DOS.


147
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Adresa de nceput n FAT indic adresa primului cuvnt din tabela de
alocare aferent fiierului. Aceast adres este mai mare ca unu. Drumul logic, de
principiu, parcurs pn la accesul la datele unui fiier cu identificatorul C:\D1\FIS este
prezentat n figura 8.4.



8.3 Tratarea informaiilor din etichetele fiierelor



Eticheta de fiier (intrarea n [sub]director) conine cmpuri referitoare la
nume, extensie, atribute, data i ora ultimei scrieri n fiier, adresa de nceput n FAT,
dimensiunea fiierului. Etichetele sunt create la deschiderea cu Rewrite a fiierelor. De
regul, valorile cmpurilor nume, extensie, atribute i adresa de nceput n FAT sunt
nscrise la crearea fiierului. Data i ora ultimei scrieri se modific la fiecare nou
scriere n fiier. Dimensiunea fiierului se modific la scrierea unui nou articol peste
sfritul iniial de fiier (pentru fiierele TEXT la scrierea dup o deschidere Append,
iar pentru fiierele binare la scrierea unui articol cu pointer mai mare ca FileSize(f)
iniial). Unele cmpuri pot fi modificate explicit, prin funcii i proceduri speciale.
Astfel, SetFAttr poziioneaz atributele, SetFTime poziioneaz data i ora, Rename
modific numele [i extensia], Truncate modific lungimea. Eticheta de fiier poate fi
tears cu procedura Erase (se terge intrarea n [sub]director).

D1
FF
Subdirectorul D1
...
...
FAT
ZONA DIR
Zona de
Date
AFAT
AFAT

Fig. 8.4 Accesul la datele fiierului C:\D1\FIS
148
Prelucrarea etichetelor de fiier i a altor informaii externe memorate n discuri




8.3.1 Prelucrarea atributelor unui fiier

n unit-ul Dos sunt definite proceduri pentru poziionarea sau citirea atributelor
unui fiier. Corespunztor valorilor pe care le poate lua octetul 0B din intrarea unui
fiier n [sub]director, n unit-ul Dos sunt definite urmtoarele constante:
ReadOnly = $01 fiier numai pentru citire;
Hidden = $02 fiier ascuns;
SysFile = $04 fiier de sistem;
Volumid = $08 identificator de volum;
Directory = $10 [sub]director;
Archive = $20 fiier arhiv;
AnyFile = $3F orice fiier
Fiierelor de date li se pot asocia atributele $01, $02, $20. n Turbo Pascal, un
fiier deschis are, n mod implicit, atributul $20 (arhiv) deoarece n el s-a scris sau
urmeaz s se scrie un articol. Fiierele binare cu atributul $01 pot fi prelucrate numai
dac sunt deschise cu Reset i dac variabilei FileMode din unit-ul System i se
atribuie, n program, valoarea zero. Fiierele TEXT cu atributul $01 pot fi doar citite
(suport numai deschiderea Reset).
Setarea pe o anumit valoare nseamn, uneori, cumularea de atribute. De
exemplu, dac unui fiier cu atributul $10 (subdirector) i se seteaz valoarea
2 (hidden), se obine un subdirector ascuns (atributul $18).
Procedura GetFAttr returneaz atributele unui fiier. Ea este definit astfel:
GetFAttr(VAR f; VAR attr:WORD)
F este variabila care indic fiierul, iar attr este variabila n care procedura
depune valoarea atributelor.


Exemplu:
8.3. n secvena care urmeaz se citesc atributele fiierului extern 'TEST.DAT'
i se afieaz valorile acestora:

USES Dos;
VAR
f:TEXT;
i:BYTE;
BEGIN
.............................
Assign(f,'TEST.DAT');
GetFAttr(f,i);
Writeln(i);
Reset(f);
.............................
Procedura SetFAttr poziioneaz (seteaz) atributele unui fiier. Ea este
149
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
definit astfel:
SetFAttr(VAR f; VAR attr:WORD)

F este variabila care indic fiierul, iar argumentul real corespunztor lui attr
este o expresie a crei valoare reprezint atributele i care va fi nscris extern n
intrarea ataat fiierului n [sub]director.

Exemple:
8.4. n secvena care urmeaz, fiierului TEST1.DAT i se asociaz atributul
Readonly, iar fiierului TEST2.DAT atributul Hidden:

USES Dos;
VAR
f1:TEXT;
f2:FILE OF READ;
BEGIN
........................
Assign(f1,'TEST1.DAT');
SetFAttr(f1,1); Reset(f1);
........................
Assign(f2,'TEST2.DAT');
SetFAttr(f2,Hidden); Reset(f2);
.......................

8.5. n programul care urmeaz, un subdirector capt atributul ascuns. Dup
setare, valoarea atributelor subdirectorului este 18 (Directory+hidden).

USES Dos;
VAR
f:FILE;
nume_dir:STRING[79];
BEGIN
Write('Director [n:\cale\director] : ');
Readln(nume_dir);
Assign(f,nume_dir);
SetFAttr(f,2);
END.

Procedurile GetFAttr i SetFAttr au funcii echivalente cu comanda ATTRIB
din DOS.


8.3.2 Prelucrarea datei i orei din eticheta unui fiier

n unit-ul Dos sunt definite proceduri pentru poziionarea sau citirea datei i
orei ultimei scrieri n fiier. Procedurile prelucrez cmpurile $16-$17 i $18-$19 din
eticheta fiierului (intrarea lui n [sub]director), ca o singur valoare de tip LONGINT.
"mpachetarea", respectiv "despachetarea" n/din LONGINT se pot realiza cu
procedurile PackTime, respectiv UnpackTime, definite n unit-ul Dos. Aceste
proceduri utilizeaz tipul de date DateTime predefinit n unit-ul Dos, astfel:
150
Prelucrarea etichetelor de fiier i a altor informaii externe memorate n discuri




DateTime = RECORD
Year : WORD;
Month : WORD;
Day : WORD;
Hour : WORD;
Min : WORD;
Sec : WORD;
END;
Procedura PackTime "mpacheteaz" un articol de tip DateTime ntr-o dat
de tip LONGINT. Ea este definit astfel:
PackTime(VAR Dc:DateTime; VAR l:LONGINT)
Dc este data i ora, exprimate pe componente, care urmeaz s fie
"mpachetate" sub form LONGINT n zona Dl.
Procedura UnpackTime "despacheteaz" o valoare de tip DateTime. Ea
este definit astfel:
UnpackTime(Dl:LONGINT, VAR Dc:DateTime)
Dl este expresie de tip LONGINT care va fi "despachetat" pe componentele
datei i orei n zona Dc.
Procedura GetFTime returneaz data i ora ultimei scrieri ntr-un fiier. Ea
este definit astfel:
GetFTime(VAR f; VAR Dl:LONGINT)
F este variabila care indic fiierul, iar Dl este variabila n care se recepio-
neaz data i ora, sub form "mpachetat". Despachetarea lui Dl se face cu procedura
UnpackTime.

Exemplu:
8.6.
USES Dos;
VAR
f1: FILE OF REAL
z: DateTime;
data_ora: LONGINT;
BEGIN
.....................
Assign(f1,'A:TEST.DAT');
GetFTime(f1, Data_ora);
UnpackTime(data_ora,z);
IF Z.Year < 1994
THEN Writeln('>> Varianta veche de fisier')
ELSE Writeln('>> Varianta OK');

Procedura SetFTime nscrie data i ora n eticheta fiierului. Ea este defi-
nit astfel:
SetFTime(VAR f; Dl:LONGINT)
F este variabila care indic fiierul, iar Dl este variabila care conine data i ora
151
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
sub form mpachetat, care se nscriu n intrarea fiierului n [sub]director. Forma
mpachetat poate fi obinut cu procedura PackTime.


Exemplu:
8.7.
USES Dos;
VAR
f1:FILE OF REAL;
z:DateTime; data_ora:LONGINT;
BEGIN
........................
ASSIGN (f1,'A:TEST.DAT');
z.Year:=1993; z.Month:=10; z.Day:=28;
z.Hour:=11; z.Min:=20; z.Sec:=0;
PackTime(z,Data_ora); SetFTime(f1,Data_ora);
..........................


8.3.3 tergerea fiierelor

n unit-ul System este definit procedura Erase care realizeaz tergerea unui
fiier existent (terge eticheta din director). Declaraia ei este:
Erase(VAR f)
Dac fiierul extern, asignat lui f, nu exist, execuia procedurii genereaz
eroare de I/E (IOResult are valoare diferit de zero). Procedura Erase nu se poate
executa asupra unui fiier deschis.

Exemplu:
8.8. Se citesc 100 de numere x. Elementele pozitive sunt memorate n fiierul
cu tip VECTOR.DAT. Dac toate numerele sunt negative, fiierul VECTOR.DAT nu
trebuie s existe.

VAR
Fis:FILE OF REAL;
x:REAL; i,j:1..100; s:BOOLEAN;
BEGIN
Assign(Fis,'VECTOR.DAT'); Rewrite(Fis);
j:=FALSE;
FOR i:=1 TO 100 DO
BEGIN
Readln(x)
IF x[i] >= 0 THEN
BEGIN
Write(Fis,x);
j:=TRUE;
END;
END;
Close(Fis);
IF NOT j THEN Erase(Fis);
END.

152
Prelucrarea etichetelor de fiier i a altor informaii externe memorate n discuri




8.3.4 Redenumirea fiierelor

Redenumirea unui fiier existent (modificarea numelui fiierului din etichet)
se realizeaz cu procedura Rename, declarat n unit-ul System, astfel:
Rename(VAR f; nume_nou:STRING)
Numele intern, f, trebuie asignat anterior unui fiier (vechi) prin procedura
Assign. Procedura Rename va redenumi acest fiier extern cu nume_nou (care este o
expresie de tip STRING, cu lungimea maxim de 80 caractere). Procedura nu copiaz
fiiere, ci doar le redenumete. De aceea, unitatea i calea fiierului vechi nu pot fi
modificate. Procedura nu se aplic fiierelor deschise. Dac fiierul extern, asociat lui f
prin Assign (fiierul vechi), nu exist, execuia procedurii genereaz eroare de I/E
(IOResult are valoare diferit de zero). Dac pe unitatea i n [sub]directorul unde este
memorat fiierul vechi exist deja un fiier cu numele nume_nou, procedura Rename
produce eroare de I/E.


8.3.5 Trunchierea fiierelor

n unit-ul System este definit procedura Truncate, care trunchiaz un fiier
binar de la poziia curent a pointerului. Ea este definit astfel:
Truncate(VAR f)
Procedura terge din fiier articolele ncepnd din poziia curent a pointerului,
pn la sfrit, modificnd lungimea fiierului din etichet. Dup execuia ei, funcia
Eof(f) va returna valoarea TRUE.



8.4 Crearea i manipularea [sub]directoarelor


n unit-ul System exist o serie de proceduri pentru crearea i tergerea
[sub]directoarelor, pentru definirea [sub]directorului curent i pentru obinerea valorii
cii curente. Toate aceste proceduri au echivalent n comenzi DOS i funcioneaz
identic cu acestea. n plus, avnd n vedere c subdirectoarele sunt tratate ca fiiere cu
articole speciale, asupra lor pot fi aplicate funciile referitoare la citirea i setarea
atributelor, datei i orei crerii subdirectorului.
Procedura GetDir returneaz calea complet a subdirectorului curent (path-
ul), dintr-o unitate de disc precizat. Declaraia ei este:
GetDir(Drive:BYTE; VAR s:STRING)
Drive specific unitatea de disc asupra cruia se aplic procedura i poate avea
valorile: 0 - unitatea de disc curent; 1 - unitatea de disc A; 2 -unitatea de disc B;
3 - unitatea de disc C etc.
153
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
S este variabila n care se recepioneaz calea complet a subdirectorului
curent, ncepnd cu rdcina. Forma cii returnate este n:cale, unde n este numele
unitii de disc. Procedura este echivalent cu comanda CHDIR (fr parametri) din
DOS.

Exemple:
8.9. Dac unitatea C: ar avea structura de directori din figura 1.4 i dac
directorul curent este D4, atunci procedura GetDir(3,Cale) ar returna, n variabila Cale,
irul: C:\D2\D4;

8.10. Procedura GetDir (9,Cale) returneaz, n variabila Cale, irul I:\, chiar
dac unitatea I:\ nu a fost definit pe discul fix.

Procedura ChDir schimb directorul curent. Ea are urmtoarea declaraie:
ChDir(s:STRING)
S conine un ir de forma [n:][cale] care definete noul subdirector curent.
Calea poate fi precizat complet, pornindu-se de la rdcin sau ntr-un mod relativ,
folosindu-se formele construite cu urmtoarele caractere: \ (directorul rdcin); .
(directorul curent); .. (directorul printe al celui curent).

Exemplu :
8.11. Dac n structura de directoare din figura 1.4, directorul curent este D4 i
se dorete ca D3 s devin curent, se poate proceda astfel:
ChDir('C:\D3'); sau
ChDir('\D3'); sau
ChDir('..'); ChDir('..'); ChDir('D3');

Cnd calea este specificat greit se genereaz eroare (path not found).
Procedura are funcie echivalent cu comanda CHDIR din DOS.
Procedura MkDir creeaz un director n disc. Ea are urmtoarea declaraie:
MkDir(s:STRING)
S conine un ir de forma [n:]cale care definete subdirectorul care se creeaz.
Lungimea maxim a cii, de la rdcin pn la nivelul dorit, nu trebuie s depeasc
63 caractere, inclusiv caracterele \. Calea poate fi precizat complet, pornindu-se de la
rdcin sau relativ, folosindu-se formele prescurtate construite cu caracterele \, .,
..(vezi ChDir). Procedura are funcie echivalent cu comanda MKDIR din DOS.

Exemplu:
8.12. Dac n structura de director din figura 1.4 se dorete crearea unui
subdirector D6, subordonat lui D3, se poate proceda astfel:

MkDir('C:\D3\D6') de oriunde;
MkDir('\D3\D6') de oriunde din unitatea C;
MkDir('D6') din D3;
154
Prelucrarea etichetelor de fiier i a altor informaii externe memorate n discuri





Procedura RmDir terge un subdirector gol. Ea are urmtoarea definiie:
RmDir(s:STRING)
S conine un ir de forma [n:]cale ce desemneaz subdirectorul care se terge.
Calea poate fi specificat complet, pornindu-se de la rdcin sau relativ, folosindu-se
formele prescurtate construite cu caracterele \, ., .. (vezi ChDir).
Subdirectorul care se terge nu trebuie s conin fiiere sau subdirectoare
ataate. n cazul n care subdirectorul nu exist sau nu este gol se produce eroare de I/E.
Directorul rdcin i subdirectorul curent nu pot fi terse. Procedura are funcie
echivalent cu comanda RMDIR din DOS.

Exemplu:
8.13. Se propune o procedur care asigur realizarea urmtoarelor operaii, n
funcie de valoarea unui parametru (op): determinarea directorului curent, schimbarea
directorului curent, crearea unui director. Procedura se construiete n cadrul unui unit
(GestDir), care poate fi extins i cu alte proceduri de interes general n lucrul cu
directoare i/sau fiiere.

UNIT GestDir;
INTERFACE
PROCEDURE OpDir(op:CHAR; VAR d:STRING; VAR rez:INTEGER);
IMPLEMENTATION
PROCEDURE OpDir;
BEGIN
CASE UpCase(op) OF
'D': GetDir(0,d);
'S': BEGIN
{$I-} ChDir(d); {$I+}
rez:=IOResult;
END;
'C': BEGIN
{$I-} MkDir(d); {$I+}
rez:=IOResult;
END;
END;
END;
END.

n continuare se prezint un apelator al subprogramului, prin care se urmrete
schimbarea directorului curent, cu salvarea directorului n uz de la momentul lansrii,
respectiv restaurarea lui la ncheierea execuiei programului. Dac noul director nu
exist, se asigur posibilitatea crerii lui, urmat de transformarea n director curent, n
aceleai condiii. Specificatorul noului director este furnizat ca parametru n linia de
comand cu care este lansat n execuie programul. Numrul parametrilor de pe linia de
comand este determinat prin funcia ParamCount:WORD. Accesul la un anumit
parametru se face prin funcia ParamStr(n:WORD):STRING, unde n este numrul
de ordine al parametrului n lista din linia de comand.
PROGRAM ExDir;
USES GestDir;
155
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
VAR r : INTEGER; c : CHAR; dinc,dnou: STRING;
PROCEDURE DetDir;
VAR dir: STRING;
BEGIN
OpDir('d',dir,r);
WriteLn('Director curent: ',dir);
END;
BEGIN
WriteLn('Program in executie curenta: ',ParamStr(0));
DetDir;
IF ParamCount <> 0 THEN
BEGIN
dnou:=ParamStr(1);
OpDir('d',dinc,r);
OpDir('s',dnou,r);
IF r <> 0 THEN
BEGIN
WriteLn('Director inexistent: ',ParamStr(1));
Write('Se creeaza ca director nou?(Y/N): ');
ReadLn(c);
IF UpCase(c) = 'Y' THEN
BEGIN
OpDir('c',dnou,r);
IF r = 0
THEN OpDir('s',dnou,r)
ELSE
BEGIN
WriteLn('>> Eroare la creare director.
Executie intrerupta!' );
RunError(r);
END;
END;
END;
END;
DetDir;
END;
{restul programului}
IF ParamCount <> 0 THEN OpDir('s',dinc,r);
DetDir;
END.



8.5 Cutarea fiierelor n [sub]directoare


n unit-ul Dos sunt definite proceduri care caut un fiier ntr-un [sub]director
sau ntr-o list de [sub]directore. Procedurile utilizeaz tipurile de data PathStr i
SearchRec, definite n unit-ul Dos, astfel:
PathStr=STRING[79];
SearchRec = RECORD
Fill : ARRAY[1..21] OF BYTE;
Attr : BYTE;
Time: LONGINT;
Size : LONGINT;
156
Prelucrarea etichetelor de fiier i a altor informaii externe memorate n discuri




Name : STRING[12];
END;
Semnificaia cmpurilor tipului SearchRec este urmtoarea:
Fill: rezervat pentru sistemul de operare. Cmpul nu trebuie modificat n
program.
Attr: atributele fiierului (valoarea octetului $0B din intrarea fiierului n
[sub]director).
Time: data i ora ultimei scrieri n fiier, sub form mpachetat (valoarea, ca
LONGINT, a octeilor $16-$19 din intrarea fiierului n [sub]director).
Size: lungimea, n octei, a fiierului (valoarea cmpului $1C-$20 din intrarea
fiierului n [sub]director).
Name: numele fiierului urmat de punct i extensia lui (valoarea cmpurilor
$0-$7 i $8-$A din intrarea fiierului n [sub]director).
Procedura FindFirst caut ntr-un [sub]director prima intrare a unui fiier
care are specificatorul i atributul precizate n lista de parametri. Ea are declararea:
FindFirst(F_extern:PathStr; Attr:Word; VAR zona:SearchRec)
F_extern este specificatorul extern al fiierului care este cutat. Specificatorul
este format din cale, nume fiier i, eventual, extensie. Cnd calea lipsete se presupune
[sub]directorul curent. Numele i extensia fiierului pot fi globale (formate cu
caracterele * sau ?). Attr reprezint valoarea atributelor fiierului care se caut. Zona
este o variabil de tipul SearchRec, definit n unit-ul Dos, care va conine informaii
despre fiierul f_extern, n cazul n care a fost gsit. Dac f_extern nu este gsit,
variabila zona rmne nemodificat. Cnd f_extern este gsit, variabila DosError
(definit n unit-ul Dos) va avea valoarea zero. n caz contrar, DosError are valoare
diferit de zero (vezi 8.3).
Procedura FindNext caut ntr-un [sub]director urmtoarea intrare a unui
fiier care are specificatorul i atributul precizate la apelul anterior al procedurii
FindFirst. De aici rezult faptul c procedura FindNext poate fi utilizat numai dac,
anterior, a fost apelat procedura FindFirst.
Procedura este definit astfel:
FindNext(VAR zona:SearchRec)
Zona are aceeai semnificaie ca la procedura FindFirst. Dac urmtoarea
intrare este gsit, variabila DosError (definit n unit-ul Dos) va avea valoarea zero.
n caz contrar, DosError are valoare diferit de zero.

Exemplu:
8.14. Urmtorul program afieaz toate fiierele cu extensia .DAT dintr-o cale
precizat de la tastatur. Pentru fiecare fiier se afieaz: numele, extensia, atributul,
lungimea, data i ora ultimei scrieri n fiier.

PROGRAM EX14;
USES Dos;
VAR
Cale:String[79];
Zona:SearchRec; {Tip definit in Dos}
157
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Dc:DateTime; {Tip definit in Dos}
BEGIN
Write('Calea de cautat ([u:]\d1\d2\):');
Readln(Cale); {Se citeste calea de la tastatura; pentru
directorul curent se poate tasta ENTER}
FindFirst(Cale+'*.DAT',$3F,Zona); {Cautarea primului fisier
cu extensia .DAT}
IF DosError <> 0
THEN Writeln('>> Nu exista fisier de tip .DAT')
ELSE
REPEAT
UnpackTime(Zona.Time,Dc);
Writeln(Zona.Name:12,'',Zona.Attr:2,'',Zona.Size:10,'',Dc.Year
:4,':',Dc.Month:2,':',Dc.Day:2,'',Dc.Hour:2,'H',Dc.Min:2,'M',Dc.
Sec:2,'S');
FindNext(Zona);
Until DosError=18;
END.

Funcia FSearch caut un fiier ntr-o list de [sub]directori. Ea este
asemntoare comenzii PATH din DOS. Funcia este definit astfel:
FUNCTION FSearch(Nume:PathStr; Lista:STRING):PathStr
Nume este variabil de tip PathStr (definit n unit-ul Dos), care conine
numele fiierului de cutat. Lista conine lista directoarelor n care se continu
cutarea, dac fiierul nu a fost gsit n directorul curent. Cile specificate n list
trebuie separate prin caracterul ;.
Funcia returneaz specificatorul extern al fiierului, n cazul n care l gsete.
Cnd fiierul este n directorul curent, specificatorul extern furnizat este format din
nume i, eventual, extensie, iar, cnd fiierul este n alt director, specificatorul este
complet (cale + nume [+ extensie]).
Cnd fiierul nu este gsit, funcia returneaz irul vid. Funcia nu verific
existena cilor. Cnd cile nu exist, se returneaz tot irul vid.

Exemplu :
8.15. Programul care urmeaz caut un fiier ntr-o list de directori. Cnd
fiierul este gsit se afieaz specificatorul extern. n caz contrar, se afieaz mesajul
>>Fiier negsit.

PROGRAM EX15;
USES Dos;
VAR
Nume:PathStr;
x:STRING;
BEGIN
Write('Numele extern al fisierului cautat (xxxxxxxx.eee):');
Readln(Nume);
x:=FSearch(Nume,'C:\wp51\;\wp51\rosca\;\tp\');
IF x[0] = #0
THEN Writeln('>>Fisier negasit')
ELSE Writeln('>>Fisierul are specificatorul extern : ',x)
END.

158
Prelucrarea etichetelor de fiier i a altor informaii externe memorate n discuri




8.6 Tratarea irului referitor la specificatorul
extern de fiier


n unit-ul Dos sunt definite o funcie i o procedur care prelucreaz irul de
caractere referitor la specificatorul extern al unui fiier. Funcia (FExpand) i
procedura (FSplit) nu fac nici o verificare sau cutare n suportul extern. Ele fac parte,
mai degrab, din categoria prelucrrii unor iruri de caractere, dect din cea de
prelucrare a fiierelor.
n definirea funciei i procedurii se folosesc urmtoarele tipuri de date
declarate n unit-ul Dos:
PathStr = STRING[79]; Specificator complet;
DirStr = STRING[67]; Unitate i cale;
NameStr = STRING[8]; Numele propriu-zis;
ExtStr = STRING[4]; Extensie.
Funcia FExpand expandeaz (completeaz) numele cu calea. Ea este
definit astfel:
FUNCTION FExpand(Nume:PathStr):PathStr
Nume este variabil de tip PathStr care conine numele ce urmeaz s fie
expandat cu calea. n procesul prelucrrii fiierelor, funcia are sens cnd este utilizat
pentru extinderea cu componente (unitate, cale) furnizate implicit.

Exemple: Se consider directorul curent C:\TP
8.16. FExpand('Test1.DAT') returneaz C:\TP\TEST1.DAT

8.17. FExpand('\TP\Test1.DAT') returneaz C:\TP\TEST1.DAT

8.18. FExpand('\Wp51\Test1.DAT') returneaz C:\WP51\TEST1.DAT

8.19. FExpand('A:TEST1.DAT') returneaz A:TEST1.DAT

8.20. Programul care urmeaz caut un fiier ntr-o list de directori. Cnd
fiierul este gsit se afieaz specificatorul extern. n caz contrar se afieaz mesajul
>>Fiier negsit.
Deosebirea fa de exerciiul 15 const n aceea c, n cazul n care fiierul este
gsit n directorul curent, se scrie specificatorul complet (n:\cale\nume_fiier.extensie).

PROGRAM EX20;
USES Dos;
VAR
Nume:PathStr;
x:STRING;
BEGIN
Write('Numele extern al fisierului cautat (xxxxxxxx.eee):');
Readln(Nume);
x:=FSearch(Nume,'C:\wp51\;\wp51\rosca\;\tp\');
159
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
IF x[0] = #0
THEN Writeln('>>Fisier negasit')
ELSE Writeln('>>Fisierul are specificatorul extern :
',FExpand(x))
END.

Procedura FSplit descompune specificatorul extern (format din unitate,
cale, nume, extensie) n trei componente: unitate+cale, nume, .extensie. Procedura este
definit astfel:
FSplit(specificator:PathStr;VAR unit_dir:DirStr;VAR name:NumeStr;VAR
ext:ExtStr)
Specificator este irul care se analizeaz i se descompune n componente.
Unit_dir, nume i ext sunt variabile n care se depun cele trei componente extrase din
specificator. Cnd unitatea i calea nu sunt prezente n specificator, se returneaz
valorile implicite. Cnd numele i extensia nu sunt prezente n specificator, se
returneaz iruri vide.

Exemplu:
8.21. Fie un program care lucreaz cu un fiier al crui nume este introdus de la
tastatur. n cazul n care de la tastatur se introduce <ENTER>, se lucreaz cu fiierul
implicit EX.DAT.

PROGRAM EX21;
USES Dos;
VAR
f:FILE OF REAL;
spec:PathStr; u:DirStr;
n:NameStr; e:ExtStr;
BEGIN
Write('Nume fiier (EX.DAT):');
Readln(Spec);
FSplit(Spec, u, n, e);
IF n = '' THEN n:='Ex';
IF e = '' THEN e:='.DAT';
Spec:=u+n+e;
Assign(f, spec);
Reset(f);
{Prelucrare}
Close (f);
END.


8.7 Funcii pentru determinarea capacitii
i a ocuprii discului


n unit-ul Dos exist definite dou funcii care returneaz capacitatea unui disc
i spaiul neocupat din el. Dac funciile se aplic unitilor de disc flexibil, n cazul n
care nu este montat discul, se genereaz un mesaj de sistem care solicit acest lucru
(afirmaia este valabil pentru toate funciile i procedurile Pascal care refer uniti de
discuri flexibile).
160
Prelucrarea etichetelor de fiier i a altor informaii externe memorate n discuri




Funcia DiskSize returneaz capacitatea total, n octei, a discului montat
n unitatea specificat. Ea are declaraia:
Function DiskSize(Drive:BYTE):LONGINT
Drive specific unitatea de disc, astfel: 0 - unitatea de disc curent; 1 - unitatea
de disc A; 2 - unitatea de disc B; 3 - unitatea de disc C etc.
Funcia returneaz valoarea -1 dac unitatea de disc nu exist, dac nu este
montat disc n unitate sau dac unitatea este defect.
Funcia DiskFree returneaz numrul de octei liberi de pe un disc montat
ntr-o unitate. Ea are declaraia:
Function DiskFree(Drive:BYTE):LONGINT
Drive are aceeai semnificaie ca la funcia DiskSize. Funcia returneaz
valoarea -1 dac unitatea de disc nu exist, dac nu este montat disc n unitate sau dac
unitatea este defect.

Exemplu:
8.22. Se presupune c urmeaz s fie creat un fiier, MAT.DAT, care are
aproximativ 10000 octei. Se poate testa, cu o oarecare aproximare, dac fiierul ncape
pe un anumit disc (fie el C:). Trebuie reinut faptul c octeii liberi sunt grupai n
clustere libere.

USES Crt;
.........
BEGIN
.........
IF DiskFree(3) = -1 THEN
Writeln('>>Unitatea C defecta')
ELSE
IF DiskFree(3) > 10000 THEN
{Asignare, deschidere, creare}
ELSE
Writeln('>>Spatiu insuficient pentru fisier');
..........
161










nelegerea corect a mecanismelor referitoare la prelucrarea fiierelor necesit
cunoaterea unor detalii tehnice de realizare a operaiilor de I/E. Cteva din ele sunt
prezentate n continuare, altele n anexa 3.



9.1 Realizarea fizic a transferului de date


Procedurile i funciile de I/E asigur, prin intermediul DOS, trecerea dintre
nivelul logic, specific utilizatorului, care consider fiierul ca o succesiune de articole
(blocuri, linii, cmpuri) i nivelul fizic de organizare a datelor, n raport cu care fiierul
apare ca o succesiune de octei. n suportul extern magnetic (disc), nregistrarea datelor
se face pe numr ntreg de sectoare. Sub sistemul de operare MS-DOS, sectorul are 512
octei i reprezint unitatea de transfer cu memoria principal. Fiecrui fiier i sunt
alocate dou tipuri de zone de memorie intern: zon utilizator i zon tampon.
Zona utilizator este descris n VAR sau CONST. La ea are acces programul
utilizatorului. Zon are semnificaii diferite, n funcie de tipul fiierului care se
prelucreaz. Ea este fie un articol (la fiiere cu tip), fie un bloc (la fiiere fr tip), fie este
o mulime de zone independente care sunt specificate n operaiile de citire/scriere (la
fiierele TEXT).
Zona tampon (buffer) reprezint zon de memorie principal n/din care se face
transferul datelor din/n exterior i are, sub MS-DOS, 528 octei. Un sistem poate lucra la
un moment dat cu mai multe buffer-e, numrul lor fiind stabilit la configurarea
sistemului (comanda BUFFERS din MS-DOS). Cu ct numrul de buffere este mai
mare cu att crete viteza de transfer, dar i memoria intern ocupat. La citiri succesive,
sectoarele sunt ncrcate n buffere "eliberate" i de aici n zonele utilizator. Dac, de
exemplu, se citete un articol de 120 octei, sistemul citete n buffer un sector ntreg i
mut, de aici, n zon utilizator, 120 octei. La urmtoarea citire, sistemul va utiliza alt
UNELE ASPECTE TEHNICE
REFERITOARE LA PRELUCRAREA
FIIERELOR
162
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
buffer etc., astfel nct, la un moment dat, buffer-ele vor conine cele mai recente date
citite. Dac citirea se face aleator (nu secvenial), se ncarc n buffer(e)
sectorul/sectoarele (ca ntregi) care conin(e) articolul. Dac articolul este deja n
buffer(e), nu are loc transfer din exterior ci numai din buffer(e) n zon utilizator.
Succesiunea de principiu a operaiilor, n cazul unui flux general de date care
implic un singur buffer, este prezentat n figura 9.1. Ea este urmtoarea:
1. citirea unui sector din fiierul de intrare n zon tampon asociat;
2. transferul datelor din buffer n zon utilizator asociat fiierului de intrare;
3. pregtirea coninutului zonei utilizatorului asociat fiierului de ieire, pe baza
datelor preluate din zona fiierului de intrare sau din alte surse.

n limbajul PASCAL, aceeai zon utilizator poate fi folosit att pentru fiierul
de intrare, ct i pentru cel de ieire;
4. Transferul datelor din zona utilizator n buffer-ul fiierului de ieire;
5. Scrierea n fiierul de ieire a sectorului (cnd este completat), din zona
tampon.
Cu toate c procesul de trecere dintre nivelurile fizic i logic are trsturi
principale comune, exist deosebiri eseniale de realizare pentru fiierele TEXT i cele
binare. Pentru fiierele binare (cu tip i fr tip) se poate considera valabil schema de
principiu din figura 9.1. Transferul intern dintre buffer i zon utilizator (operaiile 2 i 4)
are loc fr conversii, iar operaiile de intrare/ieire dintr-un program pot avea loc pe
acelai fiier. Pentru fiierele TEXT, o prima particularitate const n aceea c datele
sunt transferate n/din una sau mai multe zone de memorie independente i neomogene
ca tip (figura 9.2).



Fig.9.1 - Fluxul general de date n operaiile de I/E
163
Unele aspecte tehnice referitoare la prelucrarea fiierelor






n plus, datele sunt "decupate" din zona buffer n zonele de date, pe baza unor
caractere cu rol de separator sau dup alte reguli. Pentru datele numerice (ntregi i
reale), transferul din/n zonele buffer n/din zonele de date (operaiile 2 i 4 din figura
9.2) are loc cu conversie. Acelai lucru se ntmpl la scriere i cu datele de tip
BOOLEAN.
Att pentru fiierele binare ct i pentru cele TEXT, operaiile de transfer din
exterior n buffer (1) i din acesta n zona utilizator (2) au loc, de regul, ca urmare a
execuiei procedurilor de citire. n unele situaii, operaia (1) are loc ca urmare a
execuiei funciilor de testare a sfritului de fiier. Operaiile de transfer din zona
utilizator n buffer (4) i din acesta n exterior (5) au loc ca urmare a execuiei
procedurilor de scriere.
Operaiile 1 i 2 (respectiv 4 i 5) nu au loc, ntotdeauna, simultan. Operaia 1
are loc numai cnd buffer-ul de intrare este "eliberat", iar operaia 5 are loc numai cnd
buffer-ul de ieire este plin. Procesul se desfoar diferit la fiierele binare i la cele
TEXT.
La fiiere binare buffer-ul de intrare este "eliberat" ca urmare a execuiei
unei operaii de deschidere sau a citirii unui articol/bloc (Read, BlockRead) din fiierul
respectiv.

Exemplu:
9. 1. RESET(fis); buffer "eliberat"
..................
Read(fis,art); realizeaz operaiile 1 i 2 din
figura 9.1 (buffer "eliberat")



Fig.9.2 - Principiul transferului datelor n cazul fiierelor TEXT
164
Programarea calculatoarelor Tehnica programrii n limbajul Pascal

Funcia Eof gsete ntotdeauna buffer-ul "eliberat" (fie c este naintea unui
Read, fie c este dup acesta), ceea ce determin ca funcia s efectueze transferul din
exterior n zon buffer (operaia 1 din figura 9.1). Cnd procedura Read se execut dup
apelul funciei Eof, atunci ea realizeaz numai operaia (2).

Exemplu:
9.2.
WHILE NOT Eof(f) DO Transfera din fiier n zon buffer
(operaia 1)
BEGIN
Read(F,art); Transfera din buffer n zon articol
(operaia 2)
(* Prelucrare articol *)
END;

Dup testarea sfritului de fiier, funcia Eof nu modific pointerul, acesta
rmnnd pe nceputul buffer-ului. Tentativa de citire a unui articol, cnd Eof(f)=TRUE,
produce eroare de I/E (IOResult diferit de 0).
Buffer-ul de ieire se consider plin la fiecare scriere de articol/bloc. Procedurile
Write i BlockWrite realizeaz ntotdeauna operaiile 4 i 5 din figura 9.1.
La fiierele TEXT buffer-ul de intrare se consider "eliberat" dup execuia
unei operaii de deschidere (implicit sau explicit) sau cnd pointerul avanseaz n
buffer dup sfritul de linie (CR/LF) sau dup marcatorul de sfrit de fiier
(CTRL/Z).

Exemple:
9.3. Se presupun trei variabile a, b, c, de tip numeric i secvena de program:

Read(a); {primul Read din program}
Read(b);
Read(c);

naintea primului Read, buferul de intrare este "eliberat" (datorit deschiderii
implicite). De aceea, Read(a) transfer date din exterior n buffer. Se presupune c au
fost introduse urmatoarele valori:




165
Unele aspecte tehnice referitoare la prelucrarea fiierelor



Tot procedura Read(a) realizeaz transferul (cu conversie) din buffer n zona a
(a=12). Pointerul se plaseaz n poziia 1. Procedura Read(b) gsete bufferul
"neeliberat", deci nu execut transfer din exterior, ci numai din buffer n zona b (b=300).
Pointerul se plaseaz n poziia 2. Procedura Read(c) gsete buffer-ul "neeliberat", deci
nu execut transfer din exterior, ci analizeaz caracterele din buffer. Cum la citirea
datelor numerice spaiile i caracterele CR/LF sunt ignorate, pointerul avanseaz pn n
poziia 3, cnd buffer-ul devine "eliberat", producndu-se n acest moment o cerere de
transfer din exterior n buffer etc. n concluzie, secvena anterioar realizeaz:
Read(a) operaiile 1 i 2;
Read(b) operaia 2;
Read(c) analiza, operaia 1 etc..

9. 4. Se presupun trei variabile a, b, c de tip numeric i secvena de program:

ReadLn(a) ; {prima citire din program}
ReadLn(b) ;
ReadLn(c) ;

naintea primului ReadLn buffer-ul de intrare este "eliberat" (datorit deschiderii
implicite). De aceea, ReadLn(a) transfer date din exterior n buffer. Se presupune c au
fost introduse urmatoarele valori:


Tot procedura ReadLn(a) transfer (cu conversie) din buffer n zona a (a=12) i
plaseaz pointerul la sfritul liniei (n poziia 1), dup CR/LF.
Procedura ReadLn(b) gsete buffer-ul "eliberat" i provoac cerere de transfer
din exterior etc.

Funcia Eof poate gsi buffer-ul "eliberat" sau "neeliberat". Cnd l gsete
"eliberat" produce un transfer din exterior n buffer, plaseaz pointerul pe nceputul su
i testeaz dac este sfrit de fiier (CTRL/Z). Dac funcia Eof gsete buffer-ul
"neeliberat", testeaz dac pointerul indic sfritul de fiier. Dup testarea sfritului de
fiier, funcia Eof nu modific pointerul .
Eliberarea buffer-ului unui fiier TEXT, cu scrierea coninutului su n suportul
extern, se poate realiza cu procedura Flush(f). F trebuie deschis pentru scriere.
n concluzie, att pentru fiierele binare, ct i pentru cele TEXT, trebuie
reinute urmtoarele observaii importante: nu ntotdeauna operaiile Read, ReadLn,
166
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
BlockRead produc transfer din exterior n memoria principal. Transferul are loc numai
dac buffer-ul este "eliberat"; funcia Eof realizeaz i operaia de transfer din exterior
n memoria principal. Acest lucru se ntmpl cnd, la execuia funciei, buffer-ul de
intrare este "eliberat".



9.2 Accesul la blocul de informaii despre fiier


Declararea variabilei asociate fiierului, de orice tip, are ca efect rezervarea i
iniializarea parial de ctre compilator a unui bloc de informaii (File Informaion
Block). Unele cmpuri ale blocului primesc valori la execuia procedurii Assign, iar
altele la deschiderea fiierului. Pentru fiecare fiier din program, compilatorul genereaz
cte un FIB. Numele simbolic al blocului coincide cu numele intern asociat fiierului
prin descrierea din seciunea VAR. Informaiile din FIB sunt utilizate, la execuie, de
procedurile i funciile care realizeaz operaii de I/E.
Structura FIB este definit n unit-ul Dos prin dou declaraii de tip: FileRec,
pentru fiierele binare i TextRec, pentru fiierele TEXT.
Tipul FileRec reprezint structura FIB pentru fiiere cu tip i fr tip. El este
definit astfel:
FileRec = RECORD
Handle : WORD;
Mode : WORD;
RecSize : WORD;
Private : ARRAY[1...16] OF BYTE;
UserData : ARRAY[1...16] OF BYTE;
Name : ARRAY[0...79] OF CHAR;
END;
Tipul TextRec reprezint structura FIB pentru fiierele TEXT. El este
definit astfel:
TextRec = RECORD
Handle : WORD;
Mode : WORD;
BufSize : WORD;
Private : WORD;
BufPos : WORD;
BufEnd : WORD;
BufPtr : ^TextBuf;
167
Unele aspecte tehnice referitoare la prelucrarea fiierelor



OpenFunc : Pointer;
InOutFunc : Pointer;
FlushFunc : Pointer;
UserData : ARRAY[1...16] OF BYTE;
Name : ARRAY[0...79] OF CHAR;
Buffer : TextBuf;
Semnificaia principalelor cmpuri este urmtoarea:
Handle este o valoare ntreag care reprezint identificatorul pentru fiiere
deschise. Valorile 1-7 sunt utilizate pentru dispozitivele standard de I/E (intrare, ieire,
auxiliar, imprimant, fiierele n curs de folosire cu comanda PRINT din DOS i de
reea). Fiierele deschise ale utilizatorului au valori pentru handle ncepnd cu 8.
Fiierele nedeschise au handle=0. O valoare handle asociat unui fiier devine
disponibil la nchiderea acestuia.

Exemple:
9.5. Dac ntr-un program se lucreaz simultan cu trei fiiere, valorile handle
asociate sunt 8, 9, 10.

9.6. Dac ntr-un program se lucreaz cu trei fiiere deschise i nchise pe rnd,
fiecare va avea valoarea handle opt.

ntr-un program pot fi deschise simultan maxim 12 fiiere ale utilizatorului
(handle cu valori din intervalul [8, 19]).
Mode indic starea fiierului, care poate fi exprimat i prin urmtoarele
constante definite n unit-ul Dos:
FmClosed = $D7B0 fiier nchis;
FmInput = $D7B1 fiier deschis pentru citire;
FmOutput = $D7B2 fiier deschis pentru scriere;
FmInOut = $D7B3 fiier deschis pentru citire/scriere;
Fiierele TEXT pot avea strile FmClosed, FmInput, FmOutput. Fiierele
binare pot avea orice stare (implicit FmClosed sau FmInOut). n unit-ul System este
definit variabila FileMode astfel:
FileMode:BYTE=2
Variabila determin modul de deschidere a fiierelor binare de ctre procedura
Reset. Valorile ei posibile sunt: 0 - fiier FmInput; 1 - fiier FmOutput; 2 - fiier
FmInOut. Variabila are valoarea implicit 2. Atribuirea altei valori are ca efect folosirea
acestui mod de ctre toate apelurile ulterioare ale procedurii Reset.
RecSize indic lungimea articolului (blocului) rezultat din descrierea intern
programului.
168
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Name este identificatorul extern al fiierului, aa cum este precizat de pro-
cedura Assign.
BufSize reprezint lungimea buffer-ului fiierului TEXT.
BufPos, BufEnd, BufPtr reprezint pointeri folosii n gestiunea buffer-elor
asociate fiierului TEXT.
OpenFunc, InOutFunc, CloseFunc, FlushFunc reprezint adresa
driver-elor pentru deschidere, citire/scriere, nchidere, golire a buffer-ului.
Buffer reprezint zon tampon asociat fiierului (chiar buffer-ul fiierului).
Tipul TextBuf este definit n unit-ul Dos astfel: TextBuf = ARRAY[0...127] of CHAR.
Pentru a avea acces la informaiile din FIB, trebuie declarat o variabil de tip
FileRec (respectiv TextRec) care s aib aceeai adres cu FIB-ul (cu variabila de tip
fiier):
a) Pentru fiiere TEXT:
VAR
f: TEXT; inf_f: TextRec ABSOLUTE f;
b) Pentru fiiere cu tip:
VAR
f: FILE OF tip; inf_f: FileRec ABSOLUTE f;
c) Pentru fiiere fr tip:
VAR
f: FILE; inf_f:FileRec ABSOLUTE f;
Cmpurile zonei inf_f se adreseaz cu denumirile lor din definirea articolului
FileRec, respectiv TextRec, din unit-ul Dos.



9.3 Variabile i funcii pentru prelucrarea erorilor de I/E


n fiecare dintre unit-urile standard sunt definite variabile i funcii care pot
semnala modul de desfurare a operaiilor de intrare/ieire.
n unit-ul System sunt definite urmtoarele variabile i funcii:
Variabila InOutRes conine codurile de eroare la execuie, generate de rutinele
de I/E, corespunznd unor situaii cum sunt (anexa 3): eroare la citire de pe disc (codul
100), la scriere pe disc (101), fiier neasignat (102), fiier nedeschis (103), fiier
nedeschis pentru intrare (104), fiier nedeschis pentru ieire (105), format numeric
invalid (106). Variabila InOutRes are valoarea zero dac operaia de I/E s-a desfurat
normal. Ea este definit astfel: InOutRes:Integer=0;
Funcia IOResult returneaz programului valoarea variabilei InOutRes i o
169
Unele aspecte tehnice referitoare la prelucrarea fiierelor



pune pe aceasta pe zero. Dac valoarea InOutRes este diferit de zero i directiva de
compilare $I are valoarea {$I-}, programul nu se ntrerupe, dar urmtoarea operaie de
I/E nu se va mai executa; dac are valoarea {$I+} programul se oprete cu eroare de
execuie. De aceea, dac se dorete controlul desfurrii unei operaii de I/E, se
procedeaz astfel (pe exemplul procedurii READ):
{$I-} {inhib ntreruperea programului}
Read (f,zon);
{$I+} {autorizeaz execuia urmatoarei operaii de I/E}
IF IOResult <>0
THEN {eroare de I/E} ELSE {nu exist eroare de I/E};
Variabila ErrorAddr conine adresa unde s-a produs eroarea de execuie. n
cazul inexistenei erorii, conine valoarea nil. Variabila este definit astfel:
ErrorAddr:pointer=nil. Adresa este memorat sub forma ssss:dddd, unde ssss este
adresa segmentului de cod, iar dddd este offset-ul (deplasarea n cadrul segmentului).
n unit-ul Dos sunt definite urmtoarele proceduri i variabile:
Variabila DosError, de tip INTEGER, este iniializat de funciile i proce-
durile din acest unit, cu urmtoarele valori principale (vezi anexa 1):
0 - fr eroare;
2 - fiier negsit;
3 - cale negsit;
4 - prea multe fiiere deschise;
5 - acces interzis; etc.
Variabila DosError are valoarea zero cnd execuia functiilor i a procedurilor
definite n unit-ul Dos se termin normal.
Procedura SetVerify poziioneaz comutatorul verify din DOS. Comutatorul
are dou valori posibile: ON (valoare logic TRUE) sau OFF (valoare logic FALSE).
Cnd comutatorul are valoarea ON, sistemul de operare face verificare dup fiecare
operaie de scriere n fiiere (se verific dac datele scrise pot fi citite fr eroare). Poziia
On a comutatorului verify mrete timpul de execuie a programelor. Cnd comutatorul
are valoarea OFF, sistemul de operare nu face verificarea scrierii. Valoarea implicit a
comutatorului este OFF. Valoarea comutatorului rmne activ pn la o nou setare.
Procedura este defint astfel:
SetVerify(v:Boolean)
V este o variabil de tip BOOLEAN. Cnd v are valoarea TRUE, comutatorul
verify primete valoarea ON. n caz contrar primete valoarea OFF. Procedura are efect
similar cu comanda VERIFY din DOS. Dac comutatorul verify este ON, rezultatul
verificrii scrierii este memorat n variabila DosError.
n anexa 3 sunt prezentate principalele erori de execuie, care includ i pe cele
de intrare/ieire.
170
Programarea calculatoarelor Tehnica programrii n limbajul Pascal


9.4 Anomalii n tratarea lungimii articolelor (blocurilor)
fiierelor binare


Deoarece peste un fiier fizic poate fi suprapus orice tip de fiier, rmne n
sarcina programatorului s asigure compatibilitatea cu cerinele de prelucrare. n cazul
fiierelor binare, lungimea i structura articolelor (blocurilor) pot diferi ntre momentul
crerii i cel al exploatrii.

Exemplu:
9.7. La momentul crerii, o matrice este scris cte o linie pe articol:

TYPE
a=ARRAY[1..10] of REAL;
VAR
Fis:FILE OF a;
Linie:a;
.....................
BEGIN
Assign(Fis,'MATRICE.DAT');
Rewrite(Fis);
.....................
Write(Fis,Linie);
.....................

La momentul exploatrii, matricea poate fi citit cte un element pe articol:

VAR
Fis:FILE OF REAL;
Element:REAL;
.....................
BEGIN
Assign(Fis,'MATRICE.DAT');
Reset(Fis);
.....................
Read(Fis,Element);
.....................

Fie lart i lbloc lungimea articolelor, respectiv blocurilor unui fiier binar care
are lungimea lfis, exprimat n octei. O prelucrare corect a fiierului presupune s fie
ndeplinite urmtoarele condiii: lfis MOD lart=0, respectiv lfis MOD lbloc=0.
n caz contrar se produc anomalii n prelucrare, ultimii lfis MOD lart, respectiv
lfis MOD lbloc octei, neputnd fi prelucrai.

Exemplu:
9.8. n programul demonstrativ care urmeaz se creeaz fiierul TEST.DAT care
are lungimea 8 octei (se scriu patru articole de cte doi octei). Fiierul este exploatat cu
171
Unele aspecte tehnice referitoare la prelucrarea fiierelor



articole de 6 octei (REAL), FileSize(f2) returnnd valoarea 1 (8 DIV 6). Prima citire din
fiier transfer primii 6 octei. A doua citire produce eroare de I/E
(8 MOD 6 = 2).

PROGRAM Ex8A;
VAR
f1:FILE OF WORD;
x:WORD;
f2:FILE OF REAL;
y:REAL;
BEGIN
Assign(f1,'TEST.DAT'); Rewrite(f1);
x:=0;
Write(f1,x,x,x,x);
Close(f1);
Assign(f2,'TEST.DAT'); Reset(f2);
Writeln(FileSize(f2));
Read(f2,y);
Read(f2,y); {Error 100: Disk read error}
Close(f2);
END.

Este interesant de analizat i modul n care lucreaz funcia Eof(f), n situaia
fiierului anterior. Dac, dup prima citire (6 octei), se apeleaz funcia Eof(f2), aceasta
returneaz valoarea FALSE (programul de mai jos afieaz textul FALSE), cu toate c
pointerul este pe articolul cu numrul relativ FileSize(f2) (FileSize(f2)=
=lfis DIV lart = 1).

PROGRAM EX8B;
VAR
f1:FILE OF WORD;
x:WORD;
f2:FILE OF REAL;
y:REAl;
BEGIN
Assign(f1,'TEST.DAT'); Rewrite(f1);
x:=0;
Write(f1,x,x,x,x);
Close(f1);
Assign(f2,'TEST.DAT'); Reset(f2);
Read(f2,y);
IF Eof(f2) THEN BEGIN Writeln('TRUE'); Readln END
ELSE BEGIN Writeln('FALSE'); Readln END;
Close(f2);
END.

Din exemplul anterior se desprinde concluzia c funcia Eof(f) returneaz
valoarea TRUE dac pointerul este plasat dup lfis octei fa de nceputul fiierului.
Cnd nu se produce anomalie de lungime, afirmaia anterioar coincide cu faptul c
Eof(f) returneaz valoarea TRUE cnd pointerul este pe articolul cu numrul relativ
FileSize(f) (FileSize(f)*lart = lfis). De fapt, n cazul anomaliei de lungime, funcia
172
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Eof(f) nu poate returna niciodat valoarea TRUE, deoarece "articolul scurt" nu poate
fi niciodat citit. Din cele prezentate anterior, rezult c, n cazul prelucrrii unui
fiier cu structur necunoscut, este recomandabil s se lucreze cu articole de tip
CHAR sau cu blocuri de lungime unu.
173







Programarea orientat obiect (Object Oriented Programming - OOP)
reprezint o tehnic ce s-a impus n ultimii ani, dovedindu-se benefic pentru
realizarea sistemelor software de mare complexitate. Noiunea de obiect dateaz
din anii 60, o dat cu apariia limbajului Simula. Exist limbaje - ca Smalltalk i
Eiffel - care corespund natural cerinelor programrii orientate obiect, fiind
concepute n acest spirit, alturi de care o serie de alte limbaje procedurale, printre
care C++ i Turbo Pascal, au fost dezvoltate astfel nct s ofere suport pentru
aceast tehnic. n prezent exist n funciune sisteme software de mare anvergur
realizate n tehnica programrii orientat obiect, principiile ei fiind suficient de
bine clarificate, astfel nct s se treac din domeniul cercetrii n cel al produciei
curente de programe.



10.1 Modelul de date orientat pe obiecte


OOP reprezint o abordare cu totul diferit fa de programarea
funcional, devenit deja clasic. Dac n programarea clasic programatorul era
preocupat s rspund la ntrebarea ce trebuie fcut cu datele?, adic s
defineasc proceduri care s transforme datele n rezultate, n OOP accentul cade
asupra datelor i legturilor care exist ntre acestea, ca elemente prin care se
modeleaz obiectele lumii reale. Se poate afirma, ntr-o prim analiz, c OOP
organizeaz un program ca o colecie de obiecte, modelate prin date i legturi
specifice, care interacioneaz dinamic, adic manifest un anumit
comportament, producnd rezultatul scontat. n general, pentru modelul de date
orientat pe obiect, se consider definitorii urmtoarele concepte: obiect,
ncapsulare, motenire i polimorfism.
1. Obiectul este modelul informaional al unei entiti reale, care posed,
la un anumit nivel, o mulime de proprieti i care are, n timp, un anumit
comportament, adic manifest o reacie specific n relaiile sale cu alte obiecte
din mediul su de existen. Ca model, un obiect este o unitate individualizabil
prin nume, care conine o mulime de date, proceduri i funcii. Datele descriu
OBIECTE N PASCAL
174
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
proprietile i nivelul acestora, iar funciile i procedurile definesc
comportamentul.
Avnd n vedere proprietile comune i comportamentul similar ale
entitilor pe care le modeleaz, obiectele pot fi clasificate, adic mprite n
mulimi. O mulime de obiecte de acelai fel constituie o clas, care poate fi
descris prin modelul comun al obiectelor sale.
De exemplu, n figura 10.1, numerele raionale, ca perechi de numere
ntregi de forma (Numarator, Numitor) pot fi descrise printr-un model comun,
denumit ClasaRational. Modelul arat c orice obiect de acest fel se caracterizeaz
printr-o pereche de numere ntregi i c pe aceast mulime sunt definite operaii
unare i binare, care arat cum interacioneaz obiectele n interiorul mulimii: un
numr raional poate da natere opusului i inversului su, dou numere raionale
pot produce un alt numr raional ca sum, diferen etc.

ClasaRational

Numarator: Integer
Numitor: Integer

Obiecte
AddRational (b,c)
SubRational (b,c)
MulRational (b,c)
DivRational (b,c)
OpusRational (aopus)
InversRational (ainvers)
a: (5;7)
b: (3;1)
c: (2;5)
d: (7;5)
x: (0;1)

Fig. 10.1 Clas i obiecte mulimea numerelor raionale

Numerele complexe (figura 10.2), descrise ca perechi de numere reale de
forma (p_real, p_imaginar) pot fi grupate ntr-un model comun, denumit
Ccomplexe:

CComplexe
p_reala:real;
p_imaginara:real;
Conjugat(b)
Suma(b,c)
Inmultire(b,c)
Modul:real;
Diferenta(b,c)
Impartire(b,c)
Exemplu de obiect

a:(2, 7.5)
a reprezint numrul
complex 2+7.5i

Fig. 10.2 Clas i obiecte mulimea numerelor complexe

175
Obiecte n Pascal
Generaliznd, se poate afirma c o clas de obiecte se manifest ca un tip
obiect, iar modelul comun al obiectelor este modelul de definire a tipului obiect.
Astfel, obiectele individuale apar ca manifestri, realizri sau instanieri ale clasei,
adic exemplare particulare generate dup modelul dat de tipul obiect. Altfel spus,
o clas poate fi considerat ca un tip special de dat, iar obiectele sale ca date de
acest tip.
Acceptarea acestei semnificaii pentru clase de obiecte este de natur s
simplifice descrierea obiectelor i s asigure un tratament al acestora similar
tipurilor structurate de date din limbajele de programare: este suficient o descriere
a tipului obiect i apoi se pot declara constante i variabile de acest tip. Datele care
reprezint proprietile obiectelor se numesc atribute i sunt de un anumit tip, de
exemplu, ntregi, real, boolean etc. Procedurile i funciile care definesc
comportamentul obiectelor sunt cunoscute ca metode ale clasei. mpreun,
atributele i metodele sunt membrii clasei, identificabili prin nume. Pentru a pune
n eviden faptul c un membru aparine unui obiect se utilizeaz calificarea
(notaia cu punct): nume_obiect.nume_membru. n figura 10.1, a.Numarator
refer valoarea 5, iar a.AddRational(b,x) refer metoda AddRational a obiectului
a pentru a produce obiectul rezultat x= a+b.
Aa cum sugereaz figura 10.1, obiectele trebuie s conin valorile lor
pentru atribute, deoarece definesc starea obiectului respectiv. Metodele, fiind
comune, se specific o singur dat. Despre o metod, desemnat sau apelat cu un
anumit obiect, se spune c se execut n context obiect, iar obiectul respectiv este
numit curent. Apelul propriu-zis este considerat ca trimitere de mesaj la obiectul
curent, iar execuia metodei reprezint rspunsul obiectului curent la mesaj.
Faptul c o metod se execut n contextul obiectului curent nseamn c
are, n mod implicit, acces la atributele i metodele obiectului, altele dect metoda
respectiv. Pentru alte obiecte, din aceeai clas sau din clase diferite, metoda
trebuie s posede parametrii corespunztori. De asemenea, pentru a simplifica
scrierea, n interiorul unei metode referirea la membrii obiectului curent se face
fr calificare.
Pe baza acestor convenii, n procedurile AddRational i OpusRational,
scrise n pseudocod, s-a specificat cu un parametru mai puin dect numrul de
operanzi pe care i presupune operaia respectiv, deoarece un operand este
obiectul curent. Referirea la obiectul curent se distinge de celelalte prin lipsa
calificrii.

Procedure AddRational (b,c);
c.Numrtor:= Numarator * b.Numitor + Numitor * b. Numarator;
c.Numitor: = Numitor * b.Numitor;
End;
Procedure OpusRational (aopus);
aopus.Numarator: = -Numarator;
aopus.Numitor: = Numitor;
End;
176
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Descrierea n pseudocod a metodelor Conjugat, Suma i Modul din clasa
Ccomplexe (figura 10.2) poate fi fcut astfel:

procedure Conjugat(b);
begin
b.p_reala:=p_reala;
b.p_imaginara:=-p_imaginara;
end;
procedure Suma(b,c);
begin
c.p_reala:=p_reala+b.p_reala;
c.p_imaginara:=-p_imaginara+b.p_imaginara;
end;
function Modul:real;
begin
Modul:=sqrt(sqr(p_reala)+sqr(p_imaginra));
end;

Deoarece o clas este un tip de dat, n definirea unei clase B se pot declara
atribute de tip A, unde A este la rndul ei o clas. Mai mult, o clas A poate defini
atribute de tip A. De exemplu, clasa Carte din figura 10.3 are atributul Autor de
tipul Persoana care este, de asemenea, o clas. Mai mult, Persoana are atributul
Sef, care este de acelai tip (Persoana).

Persoana 1
100 Persoana Carte
Ionescu
Scriitor
Persoana 2
Marca: Integer
Nume: String
Profesia: String
Sef: Persoana
Cota: String
Titlu: String
Autor:Persoana
Pret: Real

Persoana 2
70
Popescu
Reporter
----------

Fig. 10.3 Atribute de tip

Definirea atributelor unei clase ca tipuri ale altei clase pune n eviden o
relaie ntre clase i, deci, ntre obiectele acestora.
Din punct de vedere funcional, metodele unei clase au destinaii diverse.
n multe cazuri i depinznd de limbaj, unei clase i se poate defini o metod
constructor i o metod destructor. Un constructor este o metod care creeaz un
177
Obiecte n Pascal
obiect, n sensul c i aloc spaiu i/sau iniializeaz atributele acestuia.
Destructorul este o metod care ncheie ciclul de via al unui obiect, elibernd
spaiul pe care acesta l-a ocupat.
2. ncapsularea exprim proprietatea de opacitate a obiectelor cu privire la
structura lor intern i la modul de implementare a metodelor. Ea este legat de
securitatea programrii, furniznd un mecanism care asigur accesul controlat la
starea i funcionalitatea obiectelor. Se evit astfel modificri ale atributelor
obiectelor i transformri ale acestora care pot s le deterioreze. Potrivit acestui
mecanism, o clas trebuie s aib membrii mprii n dou seciuni: partea public
i partea privat.
Partea public este constituit din membri (atribute i metode) pe care
obiectele le ofer spre utilizare altor obiecte. Ea este interfaa obiectelor clasei
respective cu lumea exterioar i depinde de proiectantul clasei. Modalitatea
extrem de constituire a interfeei este aceea a unei interfee compus numai din
metode. Dac se dorete ca utilizatorii obiectelor clasei s poat prelua i/sau stabili
valorile unor atribute ale acestora, interfaa trebuie s prevad metode speciale,
numite accesorii.
Partea privat cuprinde membri (atribute i/sau metode) care servesc
exclusiv obiectelor clasei respective. De regul, n aceast parte se includ atribute
i metode care faciliteaz implementarea interfeei.
De exemplu, o stiv, ca tip de dat, poate fi descris de o clas stack n
care interfaa este constituit din metodele Push, Pop, Top, Empty, n timp ce
pointerul la capul stivei, Cap i numrtorul de noduri, Contor, ca atribute, sunt
ascunse n partea privat. Ea se servete de obiectele altei clase, denumit Nod,
ale crei obiecte le nlnuiete n stiv (figura 10.4).
Trebuie remarcat c ncapsularea nseamn i faptul c utilizatorul
metodelor nu trebuie s cunoasc codul metodelor i nici nu trebuie s fie
dependent de eventuala schimbare a acestuia, interfaa fiind aceea care i ofer
funcionalitate obiectelor n condiii neschimbate de apelare.

Stack
Cap: Nod
Contor: Integer
Partea privat
Push ( )
Pop ( )
Top ( )
Empty ( )

Interfaa(partea public)

Fig. 10.4 Interfaa obiectelor

3. Motenirea reprezint o relaie ntre clase i este, probabil, elementul
definitoriu al OOP. Relaia permite constituirea unei noi clase, numit derivat,
pornind de la clase existente, denumite de baz. Dac n procesul de construire
particip o singur clas de baz, motenirea este simpl, altfel este multipl. n
178
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
continuare se vor aborda cteva aspecte legate de motenirea simpl, singura
implementat n Pascal.
Se spune c o clas D motenete o clas A, dac obiectele din clasa D
conin toate atributele clasei A i au acces la toate metodele acestei clase. Din
aceast definiie, dac D motenete A, atunci obiectele din D vor avea toate
atributele i acces la toate metodele lui A, dar n plus:
- D poate defini noi atribute i metode;
- D poate redefini metode ale clasei de baz;
- metodele noi i cele redefinite au acces la toate atributele dobndite sau
definite.
n figura 10.5, clasa Cerc motenete clasa Point, deci un obiect de tipul
Cerc va avea ca membri coordonatele x,y motenite i ca atribut propriu Raza.
Funcia Distana, definit pentru calculul distanei dintre punctul curent i punctul
p, dat ca parametru, este accesibil i pentru obiectele Cerc i va calcula distana
dintre dou cercuri (distana dintre centrele lor). Funcia Arie i procedura
Deseneaz sunt redeclarate de clasa Cerc, ceea ce nseamn redefinirea lor impus
de codul diferit pe care trebuie s-l aib n funcie de tipul figurilor geometrice
(cerc sau alt figur).

Point
x: Integer
y: Integer
Deseneaz ( )
Distana (p:Point): Real
x: 30
y: 150

Cerc
Raza: Integer
Arie ( ): Real
Deseneaz ( )
x: 200
y: 180
Raza: 50

Fig. 10.5 Motenirea simpl

Dac se au n vedere mulimi de clase, atunci se observ c relaia de motenire
simpl induce un arbore ierarhic de motenire pe aceast mulime. Exist o singur
clas iniial, i anume rdcina arborelui, fiecare clas are un singur ascendent
(printe) i orice clas care nu este frunz poate avea unul sau mai muli
descendeni (fii). n fine, cu privire la motenirea simpl se pot face urmtoarele
observaii:
dac se aduc modificri n clasa de baz, prin adugarea de atribute i/sau
metode, nu este necesar s se modifice i clasa derivat; motenirea permite
specializarea i mbogirea claselor, ceea ce nseamn c, prin redefinire i
adugare de noi membri, clasa derivat are, n parte, funcionalitatea clasei de baz,
179
Obiecte n Pascal
la care se adaug elemente funcionale noi; motenirea este mecanismul prin care
se asigur reutilizarea codului, sporind productivitatea muncii de programare.

4. Polimorfismul este un concept mai vechi al programrii, cu diferite
implementri n limbajele de programare care se bazeaz pe tipuri de date (limbaje
cu tip). Ea i-a gsit extensia natural i n modelul orientat pe date, implementat
prin limbaje cu tip, n care clasa reprezint tipul de date obiect.
Polimorfismul n limbajele de programare cu tip. Noiunea de
polimorfism exprim capacitatea unui limbaj de programare cu tip de a exprima
comportamentul unei proceduri independent de natura (tipul) parametrilor si. De
exemplu, o procedur care determin cea mai mare valoare dintr-un ir de valori
este polimorfic dac poate fi scris independent de tipul acestor valori. n funcie
de modul de implementare, se disting mai multe tipuri de polimorfism.
Polimorfismul ad-hoc se materializeaz sub forma unor proceduri care au
toate acelai nume, dar se disting prin numrul i/sau tipul parametrilor.
Polimorfismul este denumit i suprancrcare, avnd n vedere semantica specific
fiecrei proceduri n parte.
Polimorfismul de incluziune se bazeaz pe o relaie de ordine parial ntre
tipurile de date, denumit relaie de incluziune sau inferioritate. Dac un tip A este
inclus (inferior) ntr-un tip B, atunci se poate pasa un parametru de tip A la o
procedur care ateapt un parametru de tip B. Astfel, o singur procedur
definete funcional o familie de proceduri pentru toate tipurile inferioare celor
declarate ca parametri. Un exemplu clasic este cazul tipului ntreg, inferior tipului
real n toate operaiile de calcul.
Polimorfismul parametric const n definirea unui model de procedur
pentru care nsei tipurile sunt parametri. Polimorfismul, denumit i genericitate,
presupune c procedura se genereaz pentru fiecare tip transmis la apel ca
parametru.
Cele trei tipuri de polimorfism exist (toate sau numai o parte din ele) n
limbajele clasice de programare, dar unele pot s nu fie accesibile programatorului.
Aa este cazul limbajului Pascal n care polimorfismul ad-hoc este implicit numai
pentru operatorii limbajului (+, -, /, * etc), polimorfismul parametric nu este
implementat, iar polimorfismul de incluziune este aplicabil numai funciilor i
procedurilor de sistem.
Polimorfismul n limbajele orientate obiect. Limbajele orientate obiect
sau extensiile obiect ale unor limbaje cu tip ofer, n mod natural, polimorfismul
ad-hoc i de incluziune. Polimorfismul ad-hoc intrinsec reprezint posibilitatea de a
defini n dou clase independente metode cu acelai nume, cu parametri identici
sau diferii. Acest polimorfism nu necesit mecanisme speciale i decurge simplu,
din faptul c fiecare obiect este responsabil de tratarea mesajelor pe care le
primete. Polimorfismul este de aceeai natur i n cazul n care ntre clase exist o
relaie de motenire, cu precizarea c, n cazul n care o metod din clasa derivat
are parametrii identici cu ai metodei cu acelai nume din clasa de baz, nu mai este
180
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
suprancrcare, ci redefinire, dup cum s-a precizat n paragraful anterior.
Polimorfismul de incluziune este legat de relaia de motenire i de aceea se
numete polimorfism de motenire. ntr-adevr, relaia de motenire este de ordine
parial. Cnd clasa D motenete direct sau indirect clasa A, atunci D este inferior
lui A. n aceste condiii, orice metod a lui A este aplicabil la obiectele de clas D
i orice metod, indiferent de context, care are definit un parametru de tip A
(printe) poate primi ca argument corespunztor (parametru actual) un obiect de
clas D (fiu).
Observaie: un obiect de clas A nu poate lua locul unui obiect de clas D,
deoarece A acoper numai parial pe D, care este o extensie i o specializare a lui
A.
Limbajul Turbo Pascal, ca suport pentru programarea obiect, ofer ambele
forme de polimorfism pentru clase.
Legarea static i dinamic a metodelor. Legarea static a metodelor se
regsete att n limbajele orientate obiect ct i n cele clasice. Compilatorul poate
determina care metod i din care clas este efectiv apelat ntr-un anumit context
i poate genera codul de apel corespunztor.
n plus, datorit polimorfismului i lucrului cu pointeri, n limbajele
orientate obiect, unui obiect din clasa printe, desemnat indirect prin referin
(pointer) i nu prin nume, i se poate atribui un obiect fiu. n general, nu este posibil
de determinat dac, n contextul dat, metoda polimorfic trebuie apelat n varianta
clasei de baz sau a celei derivate. De aceea, compilatorul genereaz un cod care, la
momentul execuiei, va testa tipul efectiv al obiectului i va realiza legarea metodei
adecvate. n acest caz legarea este dinamic (sau la momentul execuiei). Legarea
dinamic este mai costisitoare dect cea static, dar reprezint o necesitate pentru a
asigura elasticitatea necesar n realizarea programelor OOP, obiectele putnd avea
caracter de variabile dinamice.


10.2 Clase i obiecte n Pascal


Turbo Pascal implementeaz tehnica OOP pe fondul caracteristicilor sale
de limbaj procedural, ceea ce nseamn c lucrul cu clase i obiecte se realizeaz
asemntor cu cel cu tipuri structurate de date, mecanismul de ncapsulare fiind
asigurat prin construirea unitilor.

10.2.1 Specificarea claselor

n Pascal, clasele sunt tratate asemntor datelor de tip articol. innd
seama de faptul c o clas conine att date ct i metode, specificarea unei clase
presupune declararea structurii i definirea metodelor.
181
Obiecte n Pascal
Declararea structurii. Declararea unei clase, ca tip, se face n seciunea
TYPE sub urmtoarea form general:
referinta_la_clasa = ^nume_clasa {optional}
nume_clasa=OBJECT
atribut_1;
...............
atribut_n;

metoda_1;
...............
metoda_m;
{ PRIVATE
atribut_1;
...............
atribut_p;

metoda_1;
...............
metoda_q; }
END;

Fiecare declaraie de atribut are forma: nume_atribut:tip, unde tip poate
fi predefinit sau definit anterior de utilizator, inclusiv numele unui alt tip de clas.
La fel ca i la tipul RECORD, unele atribute pot fi referine, chiar la tipul clasei
care se definete, caz n care declararea tipului referin aferent trebuie s precead
declararea clasei. O declaraie de metod cuprinde numai antetul unei funcii sau
proceduri (signatura), adic numele, parametrii formali (dac exist) i tipul
rezultatului, dac este cazul. Apariia opional a seciunii PRIVATE n declaraia
de clas anun partea privat a clasei. Toate atributele i metodele care preced
aceast seciune sunt considerate publice. n fine, se remarc prezena cuvntului
OBJECT ca declarator de tip obiect. n Turbo Pascal nu exist un declarator
CLASS, pentru a introduce o clas, aa cum exist, de exemplu, n C++. Deci
declaratorul, OBJECT, nu declar un obiect, ci o clas de obiecte.
Definirea. Definirea metodelor const n construirea corpurilor
subprogramelor a cror signatur a fost precizat. Deoarece ntr-un program pot s
existe mai multe clase, definirea trebuie s asigure recunoaterea metodelor
diferitelor clase. Acest lucru se realizeaz prin prefixarea numelui metodei cu
numele clasei. n rest, corpul metodelor se scrie n conformitate cu regulile
generale ale limbajului i avnd n vedere c metoda respectiv se execut n
contextul obiectului curent.



182
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Exemplu:
10.1. Declararea i definirea unei clase

{ Declararea clasei Point}
Point = OBJECT
Function Getx:Integer;
Function Gety:Integer;
Procedure Init (a, b: Integer);
Function Distance (p: Point): Real;
Private
x: Integer;
y: Integer;
END;
{ Definirea metodelor}
Function Point.Getx: Integer;
Begin
Getx: = x;
End;
Function Point.Gety: Integer;
Begin
Gety: = y;
End:
Function Point.Distance (p:Point): Real;
Var
dx, dy: Integer;
Begin
dx: = x-p.x;
dy: = y-p.y;
Distance: = sqrt(dx*dx-dy*dy);
End;
Procedure Point.Init(a, b: Integer);
Begin
x: = a;
y: = b;
End;

Din exemplul, 10.1 se observ modul de declarare a unei clase, n care,
pentru asigurarea ncapsulrii depline, comunicarea cu exteriorul se face numai
prin interfa. Funciile Getx i Gety sunt necesare ca accesorii pentru a returna
valorile atributelor x i y, iar procedura Init este un constructor care iniializeaz
(schimb) valorile celor dou atribute. Funcia Distance ilustreaz modul n care
trebuie neleas afirmaia c o metod se execut n context obiect. Se observ c,
dei calculul distanei presupune dou obiecte de tip Point, ca parametru figureaz
numai un punct, p. Unde este cellalt (primul)? n mod implicit, se consider c
primul punct este un obiect ascuns, obiectul de apel al funciei, numit curent,
coordonatele sale fiind x i y. n relaiile de calcul, referirea coordonatelor celuilalt
punct, transmis ca argument, se va face prin notaia cu calificri: p.x, p.y. Rezult
de aici c funciile Getx, Gety i procedura Init se refer la obiectul curent.
183
Obiecte n Pascal
Unit de clas. Deoarece clasele trebuie s fie prin definiie entiti
reutilizabile, se ncapsuleaz ntr-o unitate. Declararea claselor apare n seciunea
INTERFACE, iar definirea metodelor n seciunea IMPLEMENTATION. Se
recomand ca fiecare clas s fie o unitate.


10.2.2 Utilizarea obiectelor

Obiectele unei clase se comport asemntor variabilelor de tip articol.
Sintetiznd aceasta, nseamn c:
Obiectele se declar, ca i variabilele, ntr-o seciune VAR dintr-o
entitate de program (program principal, funcie, procedur sau unitate). De aici
rezult c obiectele pot avea caracter global sau local, ceea ce determin, pe de o
parte, spaiul de vizibilitate, iar, pe de alt parte, durata de via i segmentul de
alocare.
Un obiect poate fi declarat static sau dinamic. Atributul de static,
respectiv dinamic, se refer la momentul n care are loc alocarea spaiului pentru
obiect (la compilare sau la execuie).
Deoarece declararea obiectelor dinamice va fi tratat ntr-un alt paragraf, n
continuare se prezint numai aspectele privind obiectele statice. Pentru obiectele
statice declaraia are forma: nume_obiect:nume_clasa. De exemplu: p1, p2 :
Point. Ca i n cazul variabilelor, obiectele declarate trebuie s fie iniializate
nainte de a fi utilizate. Se apeleaz, n acest sens, o metod de tip constructor. De
exemplu, p2.Init (30,100) iniializeaz punctul p2 cu x = 30 i y = 100.
Dou obiecte de acelai tip pot participa ntr-o operaie de atribuire. De
exemplu, p1: = p2. Atribuirea ntre obiecte nu este ntotdeauna corect. Dac
obiectele au spaiu extins, atunci copierea nu este corect. De aceea, atribuirile
trebuie utilizate cu mult atenie, ele realizndu-se prin copiere bit cu bit.
Un obiect poate participa ca argument, prin valoare sau referin, la apelul
de procedur sau funcie. Deoarece transferul prin valoare corespunde unei copieri,
pot aprea aceleai neajunsuri ca i la operaia de atribuire. n plus, copierea poate
fi i costisitoare ca spaiu i timp. De aceea se prefer transferul prin referin. O
funcie nu poate returna ca rezultat un obiect, dar poate returna o referin la un
obiect.
Orice metod a unei clase, inclusiv constructorii, se apeleaz cu un anumit
obiect care devine acti sau curent . Apelul are forma:
obiect.nume_metoda(alte_argumente).
De exemplu:
pr. Init( 70,80);
d:= p1.Distance (p2).

Obiectul de apel este un parametru ascuns care se asociaz automat cu un
parametru formal denumit Self. Acest parametru formal prefixeaz, n mod
184
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
implicit, atributele i metodele utilizate de metoda apelat. Se poate spune c Self
este un pseudonim al obiectului de apel i, de aceea, n metoda apelat se poate
scrie: Self.atribut sau Self.metoda. Uneori Self se utilizeaz explicit pentru a evita
ambiguitatea referirii sau atunci cnd este nevoie de a obine adresa unui obiect
curent. n ultimul caz, adresa se desemneaz prin @Self.

Exemplu:
10.2. Se declar i se definete o clas de numere raionale ca perechi
(Numarator, Numitor) de numere ntregi. O astfel de clas poate fi util n calcule
cu fracii ordinale, atunci cnd transformarea acestora n fracii zecimale (numere
reale) nu este de dorit din cauza erorilor de trunchiere.

UNIT ClasaRat;
INTERFACE
Type
Rational = OBJECT
Procedure InitRat (x, y:Integer);
Procedure AddRat (b: Rational; VAR c: Rational);
Procedure SubRat (b: Rational; VAR c: Rational);
Procedure MulRat (b: Rational; VAR c: Rational);
Procedure DivRat (b: Rational; VAR c: Rational);
Procedure OpusRat (VAR c: Rational);
Procedure InversRat (VAR c: Rational);
Function GetNumarator: Integer;
Function GetNumitor: Integer;
Procedure ReadRat;
Procedure WriteRat;
Function CompRat (b: Rational): Integer;
PRIVATE
Numarator, Numitor: Integer;
Procedure SignRat;
END;
IMPLEMENTATION
Function Cmmdc (x,y: Integer ):integer:FORWARD;
Procedure Rational. InitRat (x, y: Integer);
{Initializeaza in forma inductiva functia (numarator,
numitor)}
Var d: Integer;
Begin
If (x=0) or (y=1)
then y=1
else begin
If (abs(x)<>1) and (abs(y)<>1) then
begin
d:= Cmmdc (x,y)
x:= x/d;
y:= y/d;
end;
SignRat;
End;
Numarator:= x;
Numitor:= y;
End;

Procedure Rational.AddRat (b: Rational; VAR c: Rational);
Var x, y: Integer;
Begin
x: = Numarator*b.Numarator+Numitor*b.Numarator;
185
Obiecte n Pascal
y: = Numitor*b.Numitor;
c.InitRat (x, y);
End;

Procedure Rational.SubRat (b:Rational; VAR c:Rational);
Var
r: Rational;
Begin
b. OpusRat ( r );
AddRat (r, c);
End;

Procedure Rational.MulRat (b: Rational; VAR c: Rational);
Var x, y: Integer;
Begin
x: = Numarator*b.Numarator;
y: = Numitor*b.Numitor;
c.InitRat (x, y);
End;

Procedure Rational.DivRat (b: Rational; VAR c: Rational);
Var r: Rational;
Begin
b.InversRat ( r );
MulRat (r, c);
End;

Procedure Rational.InversRat (VAR c: Rational);
Var d: Integer;
Begin
d:= Numarator;
if d=0 then d:=1;
c.Numarator: = c.Numitor;
c.Numitor: = d;
c.SignRat;
End;

Procedure Rational.OpusRat (VAR c: Rational);
Begin
c.Numarator: = - c.Numarator;
End;

Function Rational.GetNumarator: Integer;
Begin
GetNumarator: = Numarator;
End;

Function Rational.GetNumitor: Integer;
Begin
GetNumitor: = Numitor;
End;

Procedure Rational.SignRat;
Begin
if (Numarator>0) and (Numitor<0) or
(Numarator<0) and (Numitor<0)
then Begin
x: = -x;
y: = -y;
End:
End;

Function Cmmdc (x, y: Integer) : Integer;
186
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Begin
x: = abs (x); y: = abs (y);
While x< >y Do
if x>y then x: = x-y else y: = y-x;
Cmmdc: = x;
End;

Procedure Rational.ReadRat;
Var
txt: String [ 25];
i, x, y: Integer;
Begin
Read (txt);
i: Pos (txt, /);
If (i=0) then Begin {Numarator ntreg}
Val (txt, Numarator);
Numitor: =1;
End
else
Begin
Val(Copy (txt, 1, C-1), x);
Val (Copy (txt, i, 25), y);
InitRat (x, y);
End;
End;

Procedure Rational.WriteRat;
Begin
Write (Numarator, /, Numitor);
End;

Function Rational.CompRat (b: Rational): Integer;
Var d, n1, n2: Integer;
Begin
d: = cmmdc (Numitor, b.Numitor);
n1: = Numarator*(dDIVNumitor);
n2: = b.Numarator*(dDIV b.Numitor);
if (n1<n2)
then CompRat:=-1
else if (n1 = n2)
then CompRat: = 0
else CompRat: = 1;
End;
End.
Clasa construit poate fi testat printr-un program multifuncional, TestE2.
Operaiile care se testeaz se codific prin litere (A, S, M etc) la care se adaug o
operaie, T, pentru terminare. Pe baza unei variabile Op (pentru operaia curent)
se realizeaz o structur repetitiv, n corpul creia se alege modul de tratare printr-
o structur CASE OF.

Program TestE3;
Uses ClasRat;
Var
a,b,c: Rational;
Op: Char; r: Integer;
Procedure Meniu;
Begin
WriteLn ( Meniu);
WriteLn (A/a - Adunare);
WriteLn (S/s - Scadere);
187
Obiecte n Pascal
WriteLn (M/m - Inmulire);
WriteLn (D/d - Impartire);
WriteLn (C/c - Comparare);
WriteLn (G/g - Elemente);
WriteLn (T/t - Terminare);
WriteLn ( Alege operatia:);
ReadLn ( Op );
Op: = UpCase ( Op );
End;
BEGIN
Meniu;
While Op <>T Do
Begin
If (Op = G) then
Begin
a.ReadRat;
WriteLn (Numarator=, a.GetNumarator);
WriteLn (Numitor=, a.GetNumitor);
End
else If (Op = C) then
Case a.CompRat (b) of
-1: WriteLn ( a<b);
0: WriteLn ( a=b);
1: WriteLn (a>b);
End
else
Begin
CaseOp of
A: a.AddRat (b,c);
S: a.SubRat (b,c);
M: a.MulRat (b,c);
D: a.DivRat (b,c);
End;
C.WriteRat;
End;
Meniu;
End;
END.

La fel ca n exemplul 10.1, i n acest caz atributele sunt private, iar accesul
la valorile lor se asigur prin accesoriile GetNumarator, GetNumitor. n partea
privat apare o metod care este utilizat numai intern (n clas), n scopul asocierii
semnului numrului raional la numrtor. De asemenea, se remarc prezena
funciei Cmmdc (cel mai mare divizor comun) care nu ine de clas, dar este
necesar implementrii unor metode ale clasei.
La stabilirea numrului de parametri, n conceperea metodelor s-a avut n
vedere c un operand, eventual unicul pentru operaii unare, este obiectul curent.
Atunci cnd, n contextul obiectului curent, s-a apelat o metod care se refer la un
alt obiect, acesta este precizat explicit, (altfel s-ar considera acelai context). De
exemplu, n operaiile de scdere i mprire se aplic o reducere la operaiile de
adunare cu opusul, respectiv nmulire cu inversul. Acest rezultat intermediar se
obine prin b.OpusRat(r), respectiv b.InversRat(r), dup care, n contextul definit la
apelul lui SubRat, respectiv DivRat se invoc AddRat(r,c) i MulRat(r,c), ceea ce
188
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
nseamn c ele vor fi de fapt apelate ca Self.AddRat(r,c) i Self.MulRat(r,c), adic
a va fi prim operand.
O meniune aparte trebuie fcut cu privire la constructorul InitRat care
iniializeaz n form ireductibil fracia (Numarator, Numitor) a unui obiect. De
aceea, ea este apelat ori de cte ori se creeaz o astfel de fracie, fie n programul
principal, fie ntr-o alt metod.
Metodele ReadRat i WriteRat realizeaz legtura obiectelor cu tastatura i
monitorul. Procedura ReadRat ofer o alternativ de iniializare a obiectelor, prin
citirea fraciilor de la tastatur sub forma x/y sau x, dac numitorul este unu (numr
ntreg). Procedura WriteRat afieaz pe monitor un numr raional sub form de
fracie x/y, n poziia curent de scriere.
n cazul claselor numerice (dar nu numai), pe mulimea obiectelor unei
clase se poate defini o relaie de ordine. Deoarece limbajul nu permite
suprancrcarea operatorilor, este necesar s se introduc o metod, de regul o
funcie, care s defineasc relaia. Este cazul funciei CompRat care compar dou
numere raionale a, b i returneaz -1, 0, 1, dup cum ntre cele dou numere exist
una din relaiile: a<b; a=b; a>b.
Legat de precizrile referitoare la suprancrcarea operatorilor, se observ o
lips de naturalee n scrierea operaiilor definite pe mulimea obiectelor. De
exemplu, se scrie a.AddRat(b, c) n locul formei c:=a+b sau a.CompRat (b) n
loc de a<b etc., aa cum ar fi posibil dac operatorii +, < etc. ar putea fi
suprancrcai (cum este posibil n C++).
n fine, se face observaia c limbajul nu prevede faciliti de tratare a
cazurilor de eroare care pot aprea n legtur cu obiectele unei clase. Se presupune
c proiectantul clasei introduce eventuale msuri de tratare a erorilor sau c
utilizatorul clasei evit apelul unor metode n condiiile n care acestea pot produce
erori. n exemplul considerat, procedurile InitRat i InversRat trateaz i cazurile
de eroare, prin transformarea corespunztoare a obiectelor. n acest fel, programele
nu risc apariia erorii de mprire la zero, dar pot furniza rezultate neateptate.
Aceast modalitate poate semnala apariia unei erori, dar nu este forma cea mai
elaborat de semnalare i de prelucrare a erorii.


10.2.3 Constructori i destructori

De cele mai multe ori, spaiul unui obiect este compact, constituit din
spaiile necesare atributelor sale. n cazul n care unele atribute sunt de tip referin,
spaiul obiectelor clasei respective are o component dinamic denumit spaiu
extins (figura 10.6).




189
Obiecte n Pascal
Spaiu compact Spaiu extins
(static) (dinamic)
atribut _1
referinta _1
atribut _2
atribut _3
referinta _2

Fig. 10.6 Spaiul extins al unui obiect

Atunci cnd se declar o variabil obiect dintr-o astfel de clas,
compilatorul poate aloca spaiul compact necesar. Spaiul extins, la acest moment,
este necunoscut deoarece el trebuie s fie alocat n zona memoriei dinamice, la
momentul execuiei. Rezult de aici dou aspecte importante pe care trebuie s le
aib n vedere proiectantul clasei.
n primul rnd, trebuie s se prevad un constructor capabil s trateze nu
numai iniializarea atributelor statice, dar i a celor care ocup un spaiu dinamic.
Constructorul trebuie s utilizeze procedura New sau GetMem pentru a obine un
bloc de mrimea necesar, a crui adres trebuie ncrcat n cmpul referin al
obiectului, iar blocul respectiv trebuie apoi iniializat.
ntr-o clas pot fi prevzui mai muli constructori specializai, dac exist
mai multe cmpuri de tip referin la un obiect, dac un singur constructor ar fi
incomod de utilizat sau ar avea o list prea mare de parametri. Mai mult, limbajul
prevede o posibilitate special de a declara un constructor, utiliznd declaratorul
Constructor n loc de Procedure. Printr-o astfel de declarare, compilatorul are
posibilitatea s disting din mulimea metodelor pe cele care au acest rol special,
lucru necesar n cazul motenirii, dar util i programatorului pentru a putea verifica
mai uor dac a rezolvat corect problema iniializrii obiectelor.
n alt doilea rnd, atunci cnd un obiect trebuie s-i ncheie existena (de
exemplu, la ieirea dintr-o funcie/procedur n care a fost creat), este necesar s se
prevad o metod destructor care s elibereze spaiul extins. Destructorul trebuie s
apeleze procedura Dispose sau FreeMem pentru a returna acest spaiu zonei heap.
n lipsa unui destructor rmn blocuri de memorie ocupate, fr ca ele s mai poat
fi referite ulterior. Declaraia destructorului se poate face prin declaratorul
Destructor n loc de Procedure.
Constructorii i destructorii pot avea orice utilitate pe care o consider
programatorul, atunci cnd se creeaz sau se distrug obiecte.
Atribuirea ntre obiectele care au spaiu extins are unele particulariti.
Astfel, dac se specific atribuirea a:=b, atunci se realizeaz o copiere bit cu bit a
obiectului b n a. Dup operaie, a i b au acelai coninut n spaiul compact i,
deci, refer acelai spaiu extins (figura 10.7).

190
Programarea calculatoarelor Tehnica programrii n limbajul Pascal

x
y
z
.
.
.
Referin
x
y
z
.
.
.
Referin
Fig. 10.7 Atribuirea n cazul obiectelor cu spaiu extins
a:=b
Spaiu extins


Ulterior, modificarea realizat la unul din obiecte n spaiul extins
afecteaz starea i pentru cellalt obiect. Dac un obiect dispare, atunci cellalt
obiect va rmne fr spaiu extins, iar cnd i acesta va disprea, destructorul su
va ncerca s elibereze un spaiu care nu mai exist, fiind deja eliberat. n legtur
cu astfel de cazuri, deoarece operatorul de atribuire nu poate fi suprancrcat, este
necesar s se evite operaia i s se prevad o metod proprie de copiere prin care
s se iniializeze a cu valorile lui b, dar n spaiu complet separat. De asemenea, se
recomand ca obiectele de acest fel, utilizate ca argumente, s fie transmise, prin
referin i nu prin valoare, avnd n vedere c ultima metod este echivalent cu o
atribuire.

Exemplu:
10.3. Se ilustreaz modul de utilizare a referinelor n declararea claselor,
de realizare a constructorilor multipli i a destructorului de spaiu extins. Dei
simplificat, exemplul sugereaz modul n care se poate construi o clas matrice cu
elemente de tip Rational, prin utilizarea clasei din exemplul 10.2.
UNIT ClasaMRat;
INTERFACE
uses ClasaRat;
Const
MaxLin = 10; MaxCol = MaxLin;
ZeroRat : Rational = (Numarator:0; Numitor:1);
Type
DimLin = 1..MaxLin;
DimCol = 1..MaxCol;
Matrice = array [DimLin, DimCol] of Rational;
MatriceRat = OBJECT
Constructor SetNulMat (m, n:Integer);
Constructor ReadMat;
Procedure AddMat (b:MatriceRat; VAR c:MatriceRat);
Procedure WriteMat;
Destructor FreeExtMat;
PRIVATE
191
Obiecte n Pascal
Nlin, Ncol:Integer;
PMat:^Matrice;
END;
Var
ErrMat:Integer;
IMPLEMENTATION
Constructor MatriceRat.SetNulMat (m, n:Integer);
Var i, j:Integer;
Begin
m:=Max (m, MaxLin);
n:=Max (n, MaxCol);
GetMem (Pmat, m*n*SizeOf (Rational));
For i:=1 to m Do
For j:=1 to n Do
P.Mat^[i, j]:=ZeroRat;
Nlin:= m; Ncol:=n;
End;

Constructor MatriceRat.ReadMat;
Var m, n, i, j:Integer;
Begin
Repeat
Write (Numrul de linii:); ReadLn (m);
Until m<=MaxLin;
Repeat
Write (Numrul de coloane:);
ReadLn (n);
Until n<=MaxCol;
WriteLn(Elementele rationale ale matricei, pe
linii!);
GetMem (Pmat, m,*n*SizeOf (Rational));
For i:=1 To m Do
For j:=1 To n Do
Begin
Write (x(, i:2,,,j:2,)=);
PMat^[i,j].ReadRat;
WriteLn;
End;
Nlin:=m; Ncol:=n;
End;

Destructor MatriceRat.FreeExtMat;
Begin
FreeMem (PMat, Nlin*Ncol*SizeOf (Rational));
End;

Procedure MatriceRat.AddMat (b:MatriceRat; VAR c:MatriceRat);
Var i, j:Integer;
Begin
ErrMat:=0;
If (Nlin=b.Nlin) and (Ncol=b.Ncol)
then
For i:=1 To Nlin Do
For j:=1 To Ncol Do
PMat^[i,j].AddRat(b.PMat^[i,j],c.PMat^[i,j]);
else ErrMat:=1;
End;

Procedure MatriceRat.WriteMat;
Var i, j:Integer;
Begin
For i:=1 To Nlin Do
192
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Begin
WriteLn (Linia:, i);
For j:=1 To Ncol Do
Begin
PMat^[i, j].WriteRat;
If (i<>Ncol) Write (;);
End;
End;
End;

Program Test;
Uses ClasMat;
Var
A,B,C:MatriceRat;
Begin
A.ReadMat;
B.ReadMat;
A.AddMat (B,C);
If(ErrMat)then WriteLn (** Eroare:Dimensiuni
diferite)
else C.WriteMat;
A.FreeExtMat;
B.FreeExtMat;
C.FreeExtMat;
ReadLn;
END.

Analiza exemplului pune n eviden posibilitile tehnicii OOP n limbajul
Pascal.
Iniializarea unor variabile de tip obiect, n seciunea CONST. Este cazul
variabilei ZeroRat, pentru care se observ tratarea iniializrii ca n cazul
articolelor, definindu-se variabile pentru fiecare atribut, potrivit tipului su.
Definirea structurii de tip array, la care tipul de baz este un tip obiect.
Tipul Rational permite definirea unui tip nou, Matrice, ca un masiv bidimensional.
Alocarea dinamic a spaiului pentru matrice drept spaiu extins, potrivit
numrului de linii i coloane, dar fr a se depi dimensiunile declarate ale tipului
Matrice. Se elimin, astfel, risipa de spaiu prin alocarea static, la dimensiuni
constante, pentru structura de tip masiv. De observat modul de referire a
elementelor matricei i utilizarea metodelor clasei Rational pentru a trata aceste
elemente. Se spune c ntre clasa MatriceRat i clasa Rational exist o relaie de tip
client-server.
Prezena mai multor constructori i a unui destructor pentru iniializarea,
inclusiv a spaiului extins i, respectiv, eliberarea acestuia. Destructorul este apelat
la sfritul programului, pentru fiecare obiect. Spaiul compact al obiectelor face
obiectul eliberrii numai n cazul obiectelor locale, la ieirea din procedura sau
funcia n care obiectele au fost create, cnd este automat returnat stivei.
Tratarea erorilor clasei prin intermediul unei variabile publice (din
interfa). Aceasta este utilizat n cazul operaiei de adunare i returneaz valoarea
unu dac matricele nu au aceeai dimensiune, respectiv zero, n caz contrar. Este
sarcina programului care apeleaz metodele clasei s verifice, la rentoarcerea
193
Obiecte n Pascal
controlului, ce valoare are variabila public. Variabila nu este legat de clas, ci de
unitatea n care este ncorporat clasa.


10.2.4 Utilizarea obiectelor dinamice

Obiectele statice nu sunt, n general, reprezentative pentru tehnica OOP.
Cel mai frecvent, obiectele au un comportament dinamic, adic n timp se nasc,
triesc i dispar. n mod corespunztor, trebuie s existe posibilitatea gestionrii
dinamice a spaiului lor, astfel nct, cu aceleai rezerve de memorie, s poat fi
utilizate obiecte multiple, eventual de tipuri diferite. n limbajele orientate obiect,
obiectele sunt, prin definiie, dinamice i sistemul preia sarcina de a aloca i elibera
spaiul de memorie pentru acestea.Tehnica OOP implementat n Pascal face uz de
facilitile de definire a variabilelor dinamice, dar gestiunea obiectelor este lsat
exclusiv n sarcina programatorului.
n aceste condiii, declararea obiectelor dinamice se poate face n una din
formele:
nume_referinta_clasa : ^nume_clasa;
nume_referinta_clasa : nume_tip_referinta;
Prima form corespunde declarrii cu tip anonim a variabilelor i este mai
puin indicat. A doua form utilizeaz explicit un tip referin spre clas i este
posibil numai dac un astfel de tip a fost declarat. De regul, pentru a da
posibilitatea definirii obiectelor dinamice, orice clas se declar n forma:
nume_tip-referinta : ^nume_clasa;
nume_clasa =OBJECT.......END;
Aici se face uz de excepia introdus de limbaj, de a declara o referin
nainte de declararea tipului de date pe care l refer. Aceast permisiune asigur
referine n interiorul obiectelor, la obiecte din propria clas i posibilitatea practic
de a construi liste nlnuite de variabile i obiecte.
De exemplu, dac se presupun declaraii de tip de forma:
PPoint=^TPoint;
TPoint=OBJECT.....END;
PRational=^TRational;
TRational=OBJECT....END;
atunci este posibil s se declare variabile obiect de forma:
PtrP1,PtrP2 : Ppoint;
PtrRat1: PRational;
Dup o astfel de declarare, compilatorul aloc spaiu (static) pentru
variabilele referin. Este sarcina programatorului s aloce spaiul dinamic i s
apeleze constructorii/ destructorii de iniializare/eliberare. n acest scop se
utilizeaz procedurile New i Dispose, care au fost extinse astfel nct s accepte
drept parametru i apelul la un constructor sau destructor. Mai mult, procedurile
posed o replic sub form de funcie. Noua sintax a acestora se prezint astfel:
194
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
New(variabila_referinta);
New(variabila_referinta, apel_constructor);
Variabila_referinta := New(tip_referinta, apel_constructor);
Dispose(variabila_referinta)
Dispose(varaibila_referinta, apel_constructor);
De exemplu, dac Init(x,y:Integer) este un constructor pentru cazul clasei
Tpoint, se poate scrie:
New (PtrP1); PtrP1^.Init (30,20);
sau
New (PtrP1, Init(30, 20));
sau
PtrP1:=New (Ppoint, Init (30, 20));
n acest mod se asigur o posibilitate n plus pentru evitarea omisiunii
apelului constructorului.
Similar stau lucrurile i cu eliberarea spaiului. Dac obiectele dinamice nu
au spaiu extins, atunci eliberarea spaiului compact dinamic se va face prin apelul
procedurii Dispose, n prima form; de exemplu, Dispose (PtrP1). Dac obiectul
dinamic are spaiul extins, atunci clasa prevede i un destructor pentru acesta
(destructor de spaiu extins). n acest caz se poate utiliza procedura Dispose n a
doua form. De exemplu, dac se presupune clasa MatriceRat (exemplul_3),
declarat n forma: MatriceRat=^TMatriceRat; TMatriceRat= OBJECTEnd; i
declaraii de obiecte de forma: PtrA:TMatriceRat, se poate apela destructorul
FreeExtMat n forma: Dispose (PtrA, FreeExtMat). Prin acest apel se execut mai
nti destructorul, deci are loc eliberarea spaiului extins i apoi se elibereaz
spaiul compact dinamic.
Referirea unui obiect dinamic are forma referinta^ i accesul la membrii
obiectelor va avea formele:
referinta^.nume_metoda(argumente)
referinta^.atribut
Aa cum se pot construi masive de obiecte statice, tot aa se pot construi
astfel de structuri avnd ca tip de baz referine la obiecte dinamice. Accesul la
membrii obiectului k se va face sub forma:
numearray[k]^.nume_metoda(argumente);
numearray[k]^.atribut.



10.3 Motenirea n Pascal


Motenirea este o relaie de descenden ierarhic ntre clase, care ofer
mecanismele necesare pentru ca o clas derivat s dobndeasc atributele
195
Obiecte n Pascal
prinilor i s primeasc dreptul de acces la metodele acestora. Deoarece permite
reutilizarea de cod, motenirea este aspectul definitoriu al metodei OOP.

10.3.1 Aspecte de baz

n limbajul Pascal, motenirea este implementat sub forma simpl, ceea ce
nseamn c o clas nou poate fi derivat dintr-o singur clas printe (de baz).
Pentru ca o clas s fie recunoscut ca baz a unei clase noi, declaraia acesteia
trebuie s aib forma:
nume_clasa_derivata = OBJECT(nume_clasa_baza)
declaratii membri;
End;
n Pascal, clasa derivat poate s defineasc membri noi sau s utilizeze
suprancrcarea unor metode ale printelui. Dac se are n vedere arborele de
motenire, clasa derivat poate suprancrca metode ale oricrui ascendent. Totui,
suprancrcarea n Pascal are unele limite fa de alte implementri. Operatorii
limbajului nu pot fi suprancrcai, iar o metod nu poate fi suprancrcat de mai
multe ori n cadrul aceleiai clase. Din punct de vedere sintactic i semantic, aceste
limitri constituie neajunsuri, fiind necesar introducerea unor metode distincte
pentru operaii formal identice, dar care acioneaz asupra unor obiecte de tipuri
diferite. Dac este necesar ca ntr-o clas derivat, care suprancarc o metod a
unui strmo, s fie referit explicit aceast metod, atunci, sintactic, numele clasei
strmo trebuie s prefixeze numele metodei:
nume_clasa_stramos.nume_metoda_supraincarcata( )
Dac ntr-un arbore de motenire o clas nu posed o anumit metod, dar
o refer fr a preciza clasa strmo creia i aparine, compilatorul caut ascendent
pn la prima apariie a ei. Limbajul prevede, de asemenea, o regul adecvat
pentru asigurarea iniializrii corecte a obiectelor aparinnd unui arbore de
derivare. Se cere ca fiecare clas s aib un constructor care s apeleze
constructorul clasei printe pentru partea motenit i apoi s iniializeze atributele
proprii (figura 10.9).
O situaie similar, dar reciproc, este cea a destructorilor. Limbajul
prevede c, n cazul obiectelor unei ierarhii, apelul ascendent al destructorilor este
automat. Deci, dac o clas (final) posed un destructor pentru spaiul extins,
atunci execuia acestuia declaneaz procesul de eliberare, din aproape n aproape,
a spaiilor extinse motenite de la toi strmoii, prin execuia destructorilor
acestora. Pentru ca mecanismul s funcioneze corect i n cazul n care exist
clase strmo care nu posed spaiu extins, limbajul permite destructori cu corp vid,
pe care compilatorul i genereaz automat la clasele respective. Pentru mai mult
claritate, este recomandabil ca programatorul s defineasc destructori cu corp vid
pe ramurile care nu conin cel puin un destructor propriu-zis.
196
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
O meniune aparte trebuie fcut pentru cazul obiectelor dinamice ale unei
ierarhii de clase. Datorit polimorfismului, orice obiect este compatibil, la atribuire,
cu oricare obiect al unui strmo. n aceste condiii, o referin la un obiect strmo
poate conine adresa unui obiect descendent i apelul unei metode, de forma:
PtrStramos^.Numemetoda ( ), introducnd un element de nedeterminare n privina
obiectului de apel. Pentru astfel de cazuri, n limbajul Pascal s-a stabilit urmatoarea
regul care se aplic n lipsa altor informaii adiionale: se apeleaz metoda clasei
corespunzroare tipului referinei, dac o astfel de metod exist, sau metoda
corespunztoare primului ascendent care o posed.


a
d
c
b
a
c
b
a
Init Init Init
Fig. 10.9 Motenirea i apelul
Motenire
Clasa A Clasa A Clasa A



Exemplu:
10.4. n ramura TXTYTZTW, definit n continuare, apare o
procedur suprancrcat, p.

PX=^TX;
TX=OBJECT
Procedure p
END;
PY=^TY;
TY=OBJECT (TX)
Procedure p
END;
PZ=^TZ;
TZ=OBJECT (TY)
Procedure q
END;
PW=^TW;
TW=OBJECT (TZ)
Procedure r
END;

Dac se declar obiectele dinamice PtrX:PX; PtrW:PW i se face atribuirea i
apelul:
197
Obiecte n Pascal
..................
PtrX:=PtrW;
PtrX^.p;
se va apela procedura p a clasei TX, ghidndu-se dup referina PtrX care este
asociat acestei clase. Dac se declar PtrZ:PZ; PtrW:PW i se fac atribuirea i
apelul:
..................
PtrZ:=PtrW;
PtrZ^.p;

atunci se va apela metoda p a clasei TY, primul ascendent al clasei TZ,
deintoarea referinei PtrZ, care posed aceast metod.
Ipostazele incluse n compilator, dup regula de mai sus, permit legarea
static a metodelor, care este simpl i eficient, dar care poate s nu fie
convenabil n multe cazuri.


10.3.2 Legarea dinamic. Metode virtuale

Legarea dinamic se refer la metode suprancrcate, identice ca prototip,
care sunt declarate ntr-o ramur a unei ierarhii de clase. n acest caz particular de
suprancrcare, se spune c metoda este redefinit, avnd n vedere funcionalitatea
nou (corpul nou) care i se asociaz. Este de dorit ca metoda s fie apelat cu
obiectul a crui adres o conine referina de apel, fapt ce nu poate fi stabilit dect
la momentul execuiei. Devine evident necesitatea ntiinrii compilatorului
asupra acestei intenii, pentru a nu aplica regula legrii statice i, n consecin,
pentru a genera codul necesar determinrii obiectului real i metodei de apelat la
momentul execuiei. O astfel de tehnic de legare a unei metode cu obiectul
dinamic este denumit dinamic (late binding).
Declararea unei metode din aceast categorie se realizeaz prin
declaratorul VIRTUAL, inclus n linia de definire a prototipului:
procedure nume (parametri); VIRTUAL;
function nume (parametri): tip_rezultat; VIRTUAL;
Metodele redefinite sunt denumite virtuale. Dac o metod a fost declarat
virtual ntr-o clas, atunci trebuie s fie declarat la fel n toate clasele derivate
care au aceast clas la rdcin i redefinesc metoda n cauz. Totui, un
descendent nu este obligat s redefineasc o metod virtual a unui ascendent,
subnelegndu-se, n acest caz, c se aplic regula cutrii ascendente, dac un
obiect al su o refer.
O meniune aparte trebuie fcut cu privire la constructori i destructori. n
primul rnd, trebuie remarcat faptul c obiectele care posed metode virtuale
trebuie s fie iniializate prin constructor, dar constructorii nu pot fi declarai ca
metode virtuale. Regula este de natur s asigure o corect iniializare, prin evitarea
situaiilor necontrolabile de iniializare parial, posibile n cazul legrii dinamice.
n al doilea rnd, se menioneaz, ca regul, posibilitatea de a virtualiza
destructorii. Spre deosebire de constructori, virtualizarea destructorilor este, n
198
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
multe cazuri, absolut necesar, deoarece se recomand ca procedeu general. Ce se
poate ntmpla n cazul n care destructorii nu sunt virtualizai rezult i din
exemplul care urmeaz.

Exemplu:
10.5. Se presupune derivarea TATBTC i destructorul virtual D. Se
declar un masiv de referine la obiecte de clas TA care se iniializeaz cu adresele
unor obiecte. Se execut apoi tergerea obiectelor dinamice, cu apelul
destructorului D, pentru a elibera spaiul extins al acestor obiecte.

PA = ^ TA;
TA = OBJECT
........................................
Destructor D ; VIRTUAL;
End;
PB = ^ TB;
TB = OBJECT (TA)
........................................
Destructor D ; VIRTUAL;
End;
PC = ^TC;
TC = OBJECT (TB)
........................................
Destructor D; VIRTUAL;
End;
.............................................................
p:array [0..2] of PA;
.............................................................
..
p[0]: = new (PB,); {contine obiect TB}
p[1]: = new (PC,); {contine obiect TC}
p[2]: = new (PA,); {contine obiect TA}
.............................................................
dispose (p[0], D); {apel destructor TB, TC}
dispose (p[1], D); {apel destructor TC, TB, TA}
dispose (p[2], D); {apel destructor TA}

Se observ c p conine referine la diferite obiecte, n virtutea
polimorfismului. tergerea obiectelor ale cror adrese sunt n componentele lui p
implic o legare dinamic a destructorului potrivit. Astfel, pe baza regulii de apel
automat al destructorilor n sens ascendent, se elibereaz corect, n fiecare caz,
spaiul extins propriu i cel motenit. Dac D nu ar fi fost declarat virtual, deoarece
p are tipul de baz corespunztor referinei la clasa TA, n fiecare caz s-ar fi apelat
numai destructorul acestei clase, ceea ce ar fi nsemnat neeliberarea ntregului
spaiu extins al obiectelor respective.
Mecanismul metodelor virtuale este implementat prin intermediul tabelei
de metode virtuale VMT (Virtual Methods Table) a clasei care se ataeaz prii de
date a obiectelor din acea clas (figura 10.10).

199
Obiecte n Pascal


Obiect 1 Obiect 2
Fig. 10.10 Tabela de metode virtuale
Atribut 1
Atribut 2
.
.
.
@VMT
Atribut 1
Atribut 2
.
.
.
@VMT
Date de control
@Metod virtual 1
@Metod virtual 2
.
.
.
VMT


Tabela de metode virtuale este ataat la obiect de unul din constructori,
care este completat corespunztor de ctre compilator i este apelat nainte de
apelul oricrei metode virtuale a obiectului respectiv.


10.3.3 Motenirea i instanele

Un tip obiect descendent dintr-un altul motenete, n particular, atributele
ascendentului. El posed, deci, cel puin cmpurile ascendentului, plus, eventual,
altele noi. O instan a unui tip ascendent poate fi, deci, atribuit cu o instan a
descendentului (obiect_parinte:=obiect_fiu). O eventual atribuire invers este
incorect, pentru c ar avea ca efect neiniializarea atributelor noi ale
descendentului. De asemenea, n cazul unui transfer prin parametri valoare, o
instan printe poate fi substituit cu una fiu.
Dac, n schimb, obiectele conin spaiu extins i unuia dintre obiecte i
este disponibilizat spaiul extins, atunci i cellalt i va pierde spaiul extins i,
dac el i va apela destructorul, acesta va ncerca eliberarea unui spaiu de
memorie inexistent. De asemenea, dac tipurile de obiecte conin metode virtuale, o
atribuire nu este n general suficient n iniializarea corect a unei instane.
O instruciune de atribuire utilizeaz dimensiunea unei instane pentru
transferul de date. n cazul claselor ce conin metode virtuale, dimensiunea este
coninut ntr-un cmp al VMT, deci poate fi cunoscut numai dup apelul
constructorului respectiv. Efectul unei instruciuni de atribuire este, deci, consistent
doar n funcie de dimensiuni, acestea putnd fi determinate numai dup apelul
constructorului.




200
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Exemplu:
10.6. Lucrul cu metode virtuale

program virt;
uses crt;
type
parinte=object
a,b:word;
constructor init_p(a1,b1:word);
function suma:word;virtual;
end;

fiu=object(parinte)
c:word;
constructor init_f(a1,b1,c1:word);
function suma:word;virtual;
end;
var
p:parinte;
f:fiu;
constructor parinte.init_p;
begin
a:=a1; b:=b1;
end;
function parinte.suma:word;
begin
suma:=a+b;
end;
constructor fiu.init_f;
begin
a:=a1; b:=b1; c:=c1;
end;
function fiu.suma:word;
begin
suma:=a+b+c;
end;
procedure afis;
begin
writeln('Instanta parinte a=',p.a,' b=',p.b, ' dimensiunea
',sizeof(p));
writeln('Instanta fiu a=',f.a,' b=',f.b,' c=',f.c,'
dimensiunea ', sizeof(f));
readln;
end;

begin
clrscr;
fillchar(p,sizeof(parinte)+sizeof(fiu),#0);
afis; {1}
f.init_f(1,2,3);
afis;{2}
p:=f;
afis;{3}
p.init_p(4,5);
afis;{4}
p:=f;
afis;{5}
end.


201
Obiecte n Pascal
Rezultatul execuiei programului

{1} parinte
fiu
a=0
a=0
b=0
b=0

c=0
dimensiune 0
dimensiune 0
{2} parinte
fiu
a=0
a=1
b=0
b=2

c=3
dimensiune 0
dimensiune 8
{3} parinte
fiu
a=0
a=1
b=0
b=2

c=3
dimensiune 0
dimensiune 8
{4} parinte
fiu
a=4
a=1
b=5
b=2

c=3
dimensiune 6
dimensiune 8
{5} parinte
fiu
a=1
a=1
b=2
b=2

c=3
dimensiune 6
dimensiune 8



10.4 Proiectarea ierarhiilor de clase


Tehnica OOP se bazeaz pe date i pe clasificarea corespunztoare a
acestora. De aceea, pentru a asigura reutilizarea de cod, obiectivul principal al
proiectrii este construirea unui arbore de motenire ct mai judicios. n continuare
se vor face cteva recomandri de proiectare, ilustrate pe baza unui exemplu
didactic de obiecte grafice, redat n detaliu la sfritul capitolului.
10.4.1 Clase abstracte

Dac n procesul de analiz se privilegiez datele, atunci primul lucru care
trebuie pus n eviden sunt mulimile de obiecte care trebuie tratate. Pentru cazul
obiectelor vizuale, acestea sunt: puncte, linii, dreptunghiuri, cercuri etc. n
continuare trebuie cutate acele date (caracteristici) care sunt definitorii pentru
diferitele tipuri de obiecte i trebuie puse n eviden acele elemente care sunt
comune. Datele comune se constituie n clase i reprezint acele date care pot fi
motenite. n cazul figurilor geometrice, se poate constata c orice obiect se
identific printr-un punct de cordonate (x,y) reprezentnd nceputul liniei, colul
stnga sus al dreptunghiului, centrul cercului etc, c orice figur presupune o curb
de contur trasat cu o anumit culoare, c la figurile nchise se pune n eviden o
suprafa care poate fi umplut (haurat i colorat) ntr-un anumit mod etc.
Se poate uor constata c, aplicnd principiul gruprii datelor comune n
clase, se ajunge n situaia de a obine clase pentru care nu are sens s se declare
obiecte. Astfel, de exemplu, ar fi clasa care descrie curba de contur a obiectelor
(Contur) sau cea care conine elementele definitorii pentru suprafaa interioar a
obiectelor (Suprafaa). Astfel de clase se numesc abstracte (figura 10.11). Ele nu
pot fi instaniate, adic nu pot genera obiecte de acest tip. Rolul lor n ierarhii este
202
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
acela de clase de baz care grupeaz date i metode comune. Din ele, prin
specializare, se pot construi clase noi, care vor poseda caracteristicile clasei pe care
o motenesc i, n plus, vor defini elemente (membri) specifice. Aa de exemplu,
clasa Contur poate da natere unei clase Linie, de obiecte de tip linie dreapt, iar
clasa Suprafaa conduce la clasele Dreptunghi i Cerc, ca obiecte cu suprafa
specific.
Clasele abstracte pot fi definite la diferite niveluri n arbore, fiind posibil
ca o clas abstract s fie printe pentru o alt clas abstract mai specializat. De
regul, o clas abstract este rdcin n orice ierarhie. Dei clasele abstracte nu se
instaniaz, este permis s se declare referine ctre acestea. Acest lucru asigur
polimorfismul i, la limit, o referin de clas rdcin poate recepiona adresa
oricrui obiect din ierarhie i, n consecin, poate asigura tratarea dinamic a
obiectelor polimorfice.
Uneori, clasele abstracte sunt utilizate pentru a grupa clase care nu au date
comune, dar particip mpreun la realizarea programelor. Aceste clase sunt att de
generale nct, de regul, se reduc la un constructor vid i, eventual, la un
destructor vid i virtual. Ele se justific prin aceea c, n virtutea polimorfismului,
permit aplicarea unui cod comun i general la obiectele acestor clase, cum ar fi
constituirea de liste eterogene.
Definirea unei clase abstracte drept clas de baz a unei ierarhii conduce la
posibilitatea de a utiliza aceeai clas pentru toate ierarhiile. Principiul este aplicat,
n general, la construirea bibliotecilor de clase pe care limbajele orientate obiect le
ofer. De exemplu, n Turbo Pascal, biblioteca denumit Turbo Vision are drept
clas primordial pentru toate ierarhiile clasa TObject. Astfel se leag ntre ele
diferitele ierarhii i se poate utiliza facilitatea de polimorfism.
10.4.2 Definirea metodelor

Dup conturarea claselor, din punctul de vedere al membrilor de tip dat,
urmtoarea etap a proiectrii este definirea metodelor, innd cont de
comportamentul dorit al diferitelor tipuri de obiecte. n cazul considerat, obiectele
se creeaz, se afieaz, se ascund, i schimb culoarea de contur ori modul de
umplere etc. (figura 10.11).
n legtur cu definirea metodelor se fac urmtoarele precizri:
Fiecare clas trebuie s posede un constructor. Dup modelul Turbo
Vision, se recomand a fi denumit INIT. Constructorul unei clase trebuie s
apeleze constructorul clasei printe, pentru a se asigura iniializarea prii
motenite.
Fiecare clas care utilizeaz alocarea dinamic pentru spaiu extins
trebuie s posede un destructor, denumit DONE, declarat virtual.
Vor fi declarate virtuale, la nivelul claselor strmo, toate metodele care
urmeaz s fie redefinite n clasele derivate. Aceste metode trebuie s fie
redeclarate ca virtuale n toi descendenii.
Dac o clas instaniabil conduce la obiecte vizuale (grafice, texte),
atunci clasa trebuie s posede o metod proprie de afiare (se spune c obiectele se
203
Obiecte n Pascal
autoafieaz). Metoda de afiare se recomand s fie definit ca virtual, pentru a
se asigura o legare dinamic adecvat.
Pentru a asigura satisfacerea deplin a principiului abstractizrii i
ncapsulrii datelor, se recomand utilizarea seciunii PRIVATE pentru datele
specifice clasei i care nu intr direct n interfa. n acest sens trebuie prevzute,
pentru fiecare cmp, o metod de consultare i o metod de modificare a valorii.
Deoarece programele realizate prin tehnica OOP sunt de talie mare, se
recomand utilizarea memoriei dinamice, care trebuie eliberat sistematic, eventual
prin destructori adecvai.


10.4.3 Tratarea erorilor

n realizarea metodelor unei clase apar, de regul, dou tipuri de erori: de
domeniu i de alocare.
Erorile de domeniu sunt generate de nerespectarea domeniului de
definire a metodei (de exemplu, pentru o clas stiv, operaiile de citire i tergere
nu sunt definite n cazul n care lista este vid). Erorile nu sunt tratate de limbaj,
fiind sarcina programatorului s prevad mecanisme adecvate de comunicare ntre
metodele claselor i utilizatorul acestora. Dup agentul care provoac situaiile
de eroare, se pot aplica, n general, dou strategii:
a) Dac eroarea este determinat de starea obiectului curent, adic de
obiectul cu care urmeaz s se apeleze o anumit metod, atunci este detectabil
nainte de apel. Clasa prevede metode de detecie, ca funcii booleene, pe fiecare
tip de eroare sau o funcie unic pentru a sesiza prezena erorii. Obiectul curent va
utiliza o funcie de detecie adecvat i va proceda n consecin, adic va apela sau
nu metoda respectiv. De exemplu, pentru un obiect de tip list, o funcie Empty
poate testa dac pointerul pentru capul listei are valoarea NIL, ntorcnd valoarea
True, dac lista este vid sau False, n caz contrar.














204
Programarea calculatoarelor Tehnica programrii n limbajul Pascal


Figura


x, y
EsteVizibil
Culoare
INIT
AFISEAZA
ASCUNDE
ARIE
SCHIMBACULOARE

Punct Contur
AFISEAZA
ASCUNDE
TipLinie
GrosimeLinie
INITDEFAULT
SCHIMBACONTUR

Linie Suprafata
XSfarsit
YSfarsit
Init
AFISEAZA
ASCUNDE
TipHasura
CuloareUmplere
INITDEFAULT
SCHIMBAUMPLERE

Dreptunghi Cerc
Latime
Inaltime
INIT
AFISEAZA
ASCUNDE
ARIE
Raza
INIT
AFISEAZA
ASCUNDE
ARIE

Fig. 10.11 Ierarhie de obiecte grafice

b) Dac situaiile de eroare sunt datorate strii altor obiecte, care se
primesc ca parametri n metoda aplicat, atunci strategia anterioar nu este
aplicabil, deoarece numai metoda n cauz este n msur s sesizeze astfel de
cazuri prin testarea parametrilor si. n consecin, modul n care s-a terminat
execuia metodei se transmite ca o informaie apelatorului. Ea trebuie tratat ca o
informaie global metodei sau chiar clasei, deoarece este independent de obiectul
cu care s-a apelat metoda. Avnd n vedere ncapsularea claselor n uniti de
program, astfel de informaii pot fi valori ale unor variabile globale, declarate n
seciunea INTERFACE. Variabila global poate fi de tip enumerativ, tip n care
constantele definesc situaiile de eroare. O declarare pentru aceste elemente poate
avea, de exemplu, forma:

205
Obiecte n Pascal
INTERFACE
Type
TipError=(OK, ZeroNum, TooBigNum);
Var
classErr:TipError;

La nceputul metodelor implicate, variabilele de eroare se pun pe constanta
care semnific succes i, dup testrile parametrilor, se modific adecvat. Este
sarcina apelatorului metodei ca, la rentoarcerea controlului din metod, s testeze
dac execuia s-a realizat cu succes.
Erori de alocare. Alocarea spaiului dinamic pentru obiecte sau a
spaiului extins al acestora poate eua. O astfel de situaie conduce la abandonarea
programului. Programatorul trebuie s construiasc un mecanism propriu de tratare
a situaiei. El se bazeaz pe utilizarea variabilei HeapError, procedura Fail i
posibilitatea de a iniializa o unitate. Se procedeaz astfel:

n fiecare constructor sau metod care utilizeaz alocarea dinamic
trebuie s se testeze valoarea referinei returnat de funcia sau procedura de
alocare. Dac a aprut o situaie de eroare de alocare, procedura poate prevedea cod
pentru a recupera eroarea, dac acest lucru este posibil sau poate s ncheie n
ordine execuia apelnd procedura Fail. De exemplu:

Constructor TA.Init;
Begin

....................................................
new (Ptr1); {alocare de spatiu dinamic}
new(Ptr2);

....................................................
if (Ptr1=Nil) or (Ptr2=Nil).
Then
begin
{cod pentru recuperare}
sau
{cod de terminare + TA.DONE + Fail;}
end;
{continuare constructor}
End;

n partea de implementare a unitii de program a clasei se definete o
funcie proprie, avnd un argument de tip WORD, care este utilizat n locul
funciei standard ce se apeleaz n caz de lips de spaiu:

{$F+} {adresare far}
Function fallocerr (a:Word): Integer;
Begin
fallocerr:=1
End;
n partea de iniializare a unitii de program se introduce secvena:
206
Programarea calculatoarelor Tehnica programrii n limbajul Pascal

Begin
HeapError:=@fallocerr;
End.

n acest mod se nlocuiete funcia spre care puncteaz variabila
HeapError, care ntoarce valoarea zero n caz de lips de spaiu, cu o funcie
proprie care returneaz unu. Aceasta face ca sistemul s continue execuia
programului i n cazul de eroare de spaiu, fcnd posibil tratarea proprie a
situaiei.


207
ANEXA 1
UNITATEA DOS


1. Tipuri de date

Tipul Registers
Registers =
Record
CASE INTEGER OF
0: (AX,BX,CX,DX,BP,SI,DI,DS,ES,Flags:WORD);
1: (AL,AH,BL,BH,CL,CH,DL,DH:BYTE);
End;

Registrele AX, BX, CX i DX sunt de uz general. Pe lng referirea global,
ca registre de 16 bii, pot fi referite i semiregistre de opt bii (un octet), la nivelul
octetului inferior, prin AL, BL, CL, DL, respectiv al celui superior, prin AH, BH, CH,
DH. Registrul BP (base pointer) conine valoarea deplasrii curente n segmentul de
stiv. Registrele SI i DI corespund unor deplasri ale operandului surs i destinaie n
cadrul segmentului de date, iar DS i ES reprezint adresele de segment ale acestor
operanzi. Registrul Flags conine indicatorii de control i de stare (flags) ai
procesorului, asociai unora dintre cei 16 bii ai si, poziionai n funcie de rezultatele
executrii fiecrei operaii. Din perspectiva referirii prin programe Turbo Pascal,
prezint interes urmtorii indicatori de control (sau de condiie): CF (Carry Flag):
este setat la transportul n exterior al celui mai semnificativ bit n operaiile de calcul cu
numerele reprezentate pe 16 bii; PF (Parity Flag): este setat dac octetul inferior al
rezultatului unei operaii conine un numr par de bii cu valoarea unu. Este folosit cu
prioritate de programele de comunicaie; AF (Auxiliary carry Flag): este setat dac
cei patru bii de ordin inferior ai unei operaii genereaz un transport n exterior (folosit
pentru aritmetica BCD (Binary Coded Decimal); ZF (Zero Flag): este setat dac
rezultatul unei operaii este zero; SF (Sign Flag): este egal cu bitul de ordin superior
al rezultatului unei operaii de calcul ce folosete operanzi cu semn (0 - pozitiv, 1 -
negativ); OF (Overflow Flag): este setat dac o operaie de calcul cu operanzi cu
semn produce un rezultat prea mare (sau prea mic, operaie numit subdepire -
underflow) pentru a putea s fie reprezentat n zona rezultatului. Unitatea Dos conine
mai multe constante simbolice predefinite asociate acestor indicatori.

Data i ora
DateTime =
Record
Year : WORD; {Anul}
208
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Month : WORD; {Luna}
Day : WORD; {Ziua}
Hour : WORD; {Ora}
Min : WORD; {Minutul}
Sec : WORD; {Secunda}
End;

Articol pentru cutare
SearchRec =
Record
Fill : ARRAY[1..21] OF BYTE;
Attr : BYTE;
Time : LONGINT;
Size : LONGINT;
Name : STRING[12];
End;
Semnificaia cmpurilor este urmtoarea: Fill - rezervat pentru sistemul de
operare; cmpul nu trebuie modificat n program. Attr - atributele fiierului (valoarea
octetului $0B din intrarea fiierului n [sub]director). Time - data i ora ultimei scrieri
n fiier, sub form mpachetat (valoarea, ca LONGINT, a octeilor $16-$19 din
intrarea fiierului n [sub]director). Size - lungimea n octei a fiierului (valoarea
cmpului $1C-$20 din intrarea fiierului n [sub]director). Name - numele fiierului
urmat de punct i extensia lui (valoarea cmpurilor $0-$7 i $8-$A din intrarea
fiierului n [sub]director).

Tipuri pentru caracteristicile fiierelor
PathStr = STRING[79]; Specificatorul complet;
DirStr = STRING[67]; Unitatea i calea;
NameStr = STRING[8]; Numele propriu-zis;
ExtStr = STRING[4]; Extensia.

Structura FIB pentru fiiere cu tip i fr tip
FileRec =
Record
Handle : WORD;
Mode : WORD;
RecSize : WORD;
Private : ARRAY[1...16] OF BYTE;
UserData : ARRAY[1...16] OF BYTE;
Name : ARRAY[0...79] OF CHAR;
End;
209
Unitatea DOS
Structura FIB pentru fiierele TEXT

TextRec =
RECORD
Handle : WORD;
Mode : WORD;
BufSize : WORD;
Private : WORD;
BufPos : WORD;
BufEnd : WORD;
BufPtr : ^TextBuf;
OpenFunc : Pointer;
InOutFunc : Pointer;
FlushFunc : Pointer;
UserData : ARRAY[1...16] OF BYTE;
Name : ARRAY[0...79] OF CHAR;
Buffer : TextBuf;
END;

Semnificaia principalelor cmpuri este urmtoarea: Handle este o valoare
ntreag care reprezint identificatorul pentru fiiere deschise. Valorile 1-7 sunt
utilizate pentru dispozitivele standard de I/E (intrare, ieire, auxiliar, imprimanta,
fiierele n curs de folosire cu comanda PRINT din DOS i de reea). Fiierele deschise
ale utilizatorului au valori pentru handle ncepnd cu 8. Fiierele nedeschise au
Handle=0. O valoare handle asociat unui fiier devine disponibil la nchiderea
acestuia. ntr-un program pot fi deschise simultan maxim 12 fiiere ale utilizatorului
(handle cu valori din intervalul [8, 19]). Mode indic starea fiierului, care poate fi
exprimat i prin constantele publice specifice. Fiierele TEXT pot avea strile
FmClosed, FmInput, FmOutput. Fiierele binare pot avea orice stare (implicit
FmClosed sau FmInOut). RecSize indic lungimea articolului (blocului) rezultat din
descrierea intern programului. Name este identificatorul extern al fiierului, aa cum
este precizat de procedura Assign. BufSize reprezint lungimea buffer-ului fiierului
TEXT. BufPos, BufEnd, BufPtr reprezint pointeri folosii n gestiunea buffer-elor
asociate fiierului TEXT. OpenFunc, InOutFunc, CloseFunc, FlushFunc reprezint
adresa driver-elor pentru deschidere, citire/scriere, nchidere a fiierului, golire a
buffer-ului. Buffer reprezint zona tampon asociat fiierului (buffer-ul fiierului).
Tipul TextBuf este definit n unit-ul Dos astfel: TextBuf = ARRAY[0...127] of CHAR.
Pentru a avea acces la informaiile din FIB, trebuie declarat o variabil de tip
FileRec (respectiv TextRec) care s aib aceeai adres cu FIB-ul (cu variabila de tip
fiier). De exemplu: f: TEXT; inf_f: TextRec ABSOLUTE f.

210
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
2. Constante

Atributele fiierelor (octetul $0B din intrarea unui fiier n [sub]director)
ReadOnly = $01 fiier numai pentru citire;
Hidden = $02 fiier ascuns;
SysFile = $04 fiier de sistem;
Volumid = $08 identificator de volum;
Directory = $10 [sub]director;
Archive = $20 fiier arhiv;
AnyFile = $3F orice fiier

Constante asociate indicatorilor de stare
Fcarry = $0001;
Fparity = $0004;
Fauxiliary = $0010;
Fzero = $0040;
FSign = $0080;
Foverflow = $0800;
Constantele corespund unor mti cu care se poate testa dac un anumit
indicator este setat, valoarea lor fiind dat de poziia indicatorului n cadrul registrului
Flags. Astfel, indicatorul CF este plasat n bitul zero, deci masca asociat lui
corespunde lui 2
0
=$0001, indicatorul PF este plasat n bitul doi, cu masca 2
2
=$0004
etc. Dac se dorete, de exemplu, s se verifice dac ZF este setat, folosind o variabil
Reg de tipul Registers se va putea scrie: IF (Reg.Flags AND FZero) = 1 THEN ...

Constante pentru starea fiierului
FmClosed = $D7B0 fiier nchis;
FmInput = $D7B1 fiier deschis pentru citire;
FmOutput = $D7B2 fiier deschis pentru scriere;
FmInOut = $D7B3 fiier deschis pentru citire/scriere;


3. Variabile

DosError: INTEGER;
Este iniializat de funciile i procedurile din acest unit, cu urmtoarele valori
principale:0 - fr eroare; 2 - fiier negsit; 3 - cale negsit; 4 - prea multe
fiiere deschise; 5 - acces interzis etc. Variabila DosError are valoarea zero
cnd execuia funciilor i a procedurilor definite n unit-ul Dos se termin
normal.
211
Unitatea DOS
4. Proceduri i funcii

Prelucrarea fiierelor
Procedure GetFAttr(VAR f; VAR attr:WORD);
Returneaz atributele unui fiier.
Procedure SetFAttr(VAR f; VAR attr:WORD);
Poziioneaz (seteaz) atributele unui fiier.
Procedure GetFTime(VAR f; VAR Dl:LONGINT);
Returneaz data i ora ultimei scrieri ntr-un fiier. Dl este variabila n care se
recepioneaz data i ora, sub form "mpachetat".
Procedure SetFTime(VAR f; Dl:LONGINT);
nscrie data i ora n eticheta fiierului. Dl este variabila ce conine data i ora
sub form mpachetat, care se nscriu n intrarea fiierului n [sub]director.
Procedure FindFirst(F_extern:PathStr; Attr:WORD; VAR zona:SearchRec);
Caut ntr-un [sub]director prima intrare a unui fiier care are specificatorul i
atributul precizate n lista de parametri. F_extern este specificatorul extern al
fiierului cutat. Specificatorul este format din cale, nume fiier i, eventual,
extensie. Cnd calea lipsete se presupune [sub]directorul curent. Numele i
extensia fiierului pot fi generice (formate cu caracterele * sau ?). Attr
reprezint valoarea atributelor fiierului care se caut. Zona este o variabil de
tipul SearchRec, care va conine informaii despre fiierul f_extern n cazul
cnd a fost gsit. Dac f_extern nu este gsit, variabila zona rmne
nemodificat. Cnd f_extern este gsit, variabila DosError va avea valoarea
zero. n caz contrar, DosError are valoare diferit de zero.
Procedure FindNext(VAR zona:SearchRec);
Caut ntr-un [sub]director urmtoarea intrare a unui fiier care are
specificatorul i atributul precizate la apelul anterior al procedurii FindFirst.
Rezult c procedura FindNext poate fi utilizat numai dac, anterior, a fost
apelat procedura FindFirst. Zona are aceeai semnificaie ca la procedura
FindFirst. Dac urmtoarea intrare este gsit, variabila DosError va avea
valoarea zero. n caz contrar, DosError are valoare diferit de zero.
Function FSearch(Nume:PathStr; Lista:STRING):PathStr;
Caut un fiier ntr-o list de [sub]directori. Ea este asemntoare comenzii
PATH din MSDOS. Nume este variabil de tip PathStr, care conine numele
fiierului de cutat. Lista conine lista directoarelor n care se continu
cutarea, dac fiierul nu a fost gsit n directorul curent. Cile specificate n
list trebuie separate prin caracterul ;. Funcia returneaz specificatorul extern
al fiierului, n cazul n care l gsete. Cnd fiierul este n directorul curent,
specificatorul extern furnizat este format din nume i, eventual, extensie, iar
cnd fiierul este n alt director, specificatorul este complet (cale+nume [+
extensie]). Cnd fiierul nu este gsit, funcia returneaz irul vid. Funcia nu
verific existena cilor. Cnd cile nu exist, se returneaz irul vid.

212
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
Function FExpand(Nume:PathStr):PathStr;
Expandeaz (completeaz) numele cu calea. Nume este variabil de tip
PathStr ce conine numele care urmeaz s fie expandat cu calea. n procesul
prelucrrii fiierelor, funcia are sens cnd este utilizat pentru extinderea cu
componente (unitate, cale) furnizate implicit.
Procedure FSplit(specificator:PathStr;VAR unit_dir:DirStr;VAR name:NumeStr;VAR
ext:ExtStr);
Descompune specificatorul extern (unitate, cale, nume, extensie) n trei
componente: unitate+cale, nume, .extensie. Specificator este irul care se
analizeaz i se descompune n componente. Unit_dir, nume i ext sunt
variabile n care se depun cele trei componente extrase din specificator. Cnd
unitatea i calea nu sunt prezente n specificator, se returneaz valorile
implicite. Cnd numele i extensia nu sunt prezente n specificator, se
returneaz iruri vide.
Procedure SetVerify(v:BOOLEAN);
Poziioneaz comutatorul verify din DOS. Comutatorul are dou valori: ON
(valoare TRUE) sau OFF (valoare FALSE). Cnd comutatorul are valoarea
ON, sistemul de operare face verificare dup fiecare operaie de scriere n
fiiere (se verific dac datele scrise pot fi citite fr eroare). Poziia ON a
comutatorului verify mrete timpul de execuie a programelor. Cnd
comutatorul are valoarea OFF, sistemul de operare nu face verificarea scrierii.
Valoarea implicit a comutatorului este OFF. Valoarea comutatorului rmne
activ pn la o nou setare. V este o variabil de tip BOOLEAN. Cnd v are
valoarea TRUE, comutatorul verify primete valoarea ON; n caz contrar pri-
mete valoarea OFF. Procedura are efect similar cu comanda VERIFY din
DOS. Dac comutatorul verify este ON, rezultatul verificrii scrierii este
memorat n variabila DosError.

Ocuparea discului
Function DiskSize(Drive:BYTE):LONGINT;
Returneaz capacitatea, n octei, a discului montat n unitatea specificat.
Drive specific unitatea de disc, astfel: 0 - unitatea de disc curent; 1 - unitatea
de disc A; 2 - unitatea de disc B; 3 - unitatea de disc C etc. Funcia returneaz
valoarea -1 dac unitatea de disc nu exist, dac nu este montat disc n unitate
sau dac unitatea este defect.
Function DiskFree(Drive:BYTE):LONGINT;
Returneaz numrul de octei liberi de pe un disc montat ntr-o unitate. Drive
are aceeai semnificaie ca la funcia DiskSize. Funcia returneaz valoarea -1
dac unitatea de disc nu exist, dac nu este montat disc n unitate sau dac
unitatea este defect.

213
Unitatea DOS
Execuia programelor
Procedure Exec(specif,parametru:STRING);
ncrcarea n memorie i lansarea n execuie a programului aflat n fiierul
specif. Parametrii de pe linia de comand sunt specificai n parametru.
Function DosExitCode:WORD;
Codul de retur al unui proces (program).

ntreruperi
Procedure Intr(ni:BYTE; VAR reg:Registers);
Lansarea ntreruperii ni. n variabila reg se pregtesc argumentele.
Procedure MsDos(VAR reg:Registers);
Lansarea ntreruperii $21. n variabila reg se pregtesc argumentele.
Procedure GetIntVec(int:BYTE; VAR adrint:POINTER);
Obinerea, n adrint, a adresei ntreruperii cu numrul int.
Procedure SwapVectors;
Salvarea vectorilor de ntrerupere.

Data i timpul
Procedure GetDate(VAR an, luna, ziua_luna, ziua_sapt:WORD);
Obinerea datei din sistem.
Procedure SetDate(VAR an, luna, ziua:WORD);
Poziionarea datei n sistem.
Procedure GetTime(VAR ora, minut, sec, sec100:WORD);
Obinerea timpului din sistem.
Procedure SetTime(VAR ora, minut, sec, sec100:WORD);
Poziionarea timpului n sistem.
Procedure PackTime(VAR Dc:DateTime; VAR Dl:LONGINT);
"mpachetarea" unui articol de tip DateTime ntr-o dat de tip LONGINT. Dc
este data i ora, exprimate pe componente, care urmeaz s fie "mpachetate"
sub form LONGINT n zona Dl.
Procedure UnpackTime(Dl:LONGINT, VAR Dc:DateTime);
"Despachetarea" unei valori de tip DateTime. Dl este expresie de tip
LONGINT care va fi "despachetat" pe componentele datei i orei n zona Dc.

Alte funcii
Function DosVersion:WORD;
Returneaz un cuvnt ai crui octei conin numrul principal al versiunii
curente a sistemului de operare (octetul inferior), respectiv numrul secundar
(octetul superior).

214
ANEXA 2
UNITATEA CRT


1. Constante

Constante pentru culorile de fond i de text

Culori de fond i text Culori de text
Constant simbolic Constant
(cod)
Constant simbolic Constant
(cod)
Black (negru) 0 DarkGray (gri nchis) 8
Blue (albastru) 1 LightBlue (albastru deschis) 9
Green (verde) 2 LightGreen (verde deschis) 10
Cyan (turcoaz) 3 LightCyan (turcoaz deschis) 11
Red (rou) 4 LightRed (rou deschis) 12
Magenta (violet) 5 LightMagenta (violet deschis) 13
Brown (maro) 6 Yellow (galben) 14
LightGray (gri deschis) 7 White (alb) 15
Blink=128; {Adunat la codul culorii se obine afiare intermitent}

Constante care definesc modurile text

Constant simbolic Constant (cod) Explicaie
BW40 0 Adaptor color negru, rezoluie 40 x 25
BW80 2 Adaptor color negru, rezoluie 80 x 25
Mono 7 Adaptor monocrom negru/alb, rezoluie 80 x 25
CO40 1 Adaptor color, rezoluie 40 x 25
CO80 3 Adaptor color,rezoluie 80 x 25
Font8x8 256 Adaptor EGA/VGA, 43 i 50 linii


2. Proceduri i funcii

Pregtirea scrierii
Procedure AssignCrt (VAR f:TEXT);
Asigneaz fiierul f la dispozitivul CRT.
Procedure TextMode (Mode:WORD);
Selecteaz modul text.
Procedure Window (X1, Y1, X2, Y2:BYTE);
Definete fereastra text.
Procedure TextBackground (Color:BYTE);
Definete culoarea fondului.
Procedure TextColor (Color:BYTE);
215
Unitatea CRT

Definete culoarea de scriere.
Procedure HighVideo;
Definete atributul de intensitate mare.
Procedure LowVideo ;
Definete atributul de intensitate mic.
Procedure NormVideo;
Restabilete atributele implicite.
Procedure ClrScr;
terge fereastra curent.
Procedure ClrEol;
terge caracterele liniei curente, de la poziia cursorului pn la sfrit.
Procedure DelLine;
terge linia curent; textul este defilat n sus cu o linie.
Procedure InsLine;
Insereaz o linie goal n poziia cursorului; textul este defilat n jos cu o
linie.
Procedure GotoXY (X, Y:BYTE);
Mut cursorul pe linia Y, coloana X.
Function WhereX: BYTE;
Returneaz numrul coloanei n care se gsete cursorul.
Function WhereY: BYTE;
Returneaz numrul liniei pe care se gsete cursorul.

Programarea difuzorul intern
Procedure Sound (Hz:WORD);
Pornete difuzorul intern, care emite un sunet continuu de frecven Hz.
Procedure Delay (Ms:WORD);
Introduce o ntrziere n execuia urmtoarei instruciuni.
Procedure NoSound;
Oprete difuzorul intern.
Lucrul cu tastatura
Function KeyPressed: BOOLEAN;
ntoarce TRUE dac a fost apsat o tast.
Function ReadKey: CHAR;
Returneaz codul caracterului rezultat prin apsarea unei taste.
216
ANEXA 3
ERORI DE EXECUIE


Apariia unei erori de execuie determin ntreruperea programului i afiarea
unui mesaj de eroare, de forma: Run-time error nnn at xxxx:yyyy, unde nnn este
codul erorii de execuie, iar xxxx:yyyy este adresa ei (segment i offset). Erorile de
execuie se mpart n: erori DOS (coduri 1-99); erori de intrare/ieire (coduri 100-
149), erori critice (coduri 150-199) i erori fatale (coduri 200-255).


1. Erori DOS

1. Funcie inexistent. Generat de un apel al unei funcii DOS inexistente.
2. Fiier inexistent. Generat de execuia uneia din procedurile Reset, Append,
Rename sau Erase, dac identificatorul asignat variabilei de tip fiier nu corespunde
unui fiier existent.
3. Cale inexistent. Generat de execuia uneia din procedurile:
Reset, Append, Rewrite, Rename sau Erase, dac identificatorul asignat
variabilei de tip fiier este invalid sau include un sub[director] inexistent;
ChDir, MkDir sau RmDir, dac sub[directorul] este invalid sau inexistent.
4. Prea multe fiiere deschise. Generat de execuia uneia din procedurile Reset sau
Append dac, la un moment dat, sunt deschise simultan mai mult de 12 fiiere ale
utilizatorului. Dac se dorete raportarea erorii pentru un numr mai mic de fiiere
deschise simultan, trebuie ca fiierul CONFIG.SYS s nu conin clauza FILES=xx
sau s specifice numrul de fiiere dorit.
5. Acces interzis la fiier. Generat de execuia uneia din procedurile:
Reset sau Append, dac FileMode permite scrierea, dar identificatorul asig-
nat variabilei fiier specific un [sub]director/fiier read-only;
Rewrite, dac sub[directorul] este plin sau identificatorul asignat variabilei
fiier specific un [sub]director/fiier existent read-only;
Rename, dac identificatorul asignat variabilei fiier specific un fiier
existent;
Erase, dac identificatorul asignat variabilei fiier specific un sub[direc-
tor]/fiier read-only;
MkDir, dac: exist un fiier cu aceleai nume n sub[directoru] printe; nu
exist spaiu n sub[directorul] printe; este specificat n cale un dispozitiv;
RmDir, dac: sub[directorul] nu este vid; nu se specific un sub[director] n
cale; directorul specificat include rdcina;
Read/BlockRead pentru un fiier cu tip/fr tip, dac acesta nu a fost des-
chis pentru citire;
217
Erori de execuie
Write/BlockWrite pentru un fiier cu tip/fr tip, dac acesta nu a fost des-
chis pentru scriere.
6. Handle de fiier invalid. Generat la transmiterea unui handle (vezi 8.2) invalid
de fiier, la un apel al sistemului DOS.
12. Cod invalid de acces la fiier. Generat de execuia uneia din procedurile Reset
sau Append pentru fiiere cu tip/fr tip, dac valoarea variabilei FileMode este
invalid.
15. Numr dispozitiv invalid. Generat de execuia uneia din procedurile GetDir
sau ChDir, dac numrul dispozitivului periferic este invalid.
16. Sub[directorul] curent nu poate fi suprimat. Generat de execuia procedurii
RmDir, dac n calea specificat este inclus directorul curent.
17. Redenumire fiiere pe dispozitive diferite. Generat de execuia procedurii
Rename, dac specificatorii de fiiere nu sunt pe acelai dispozitiv.


2. Erori de intrare/ieire

Erorile de intrare/ieire determin ntreruperea execuiei programului, numai
dac instruciunea respectiv a fost compilat cu directiva {$I+} (valoare impicit).
n cazul n care se specific directiva de compilare {$I-}, execuia programului conti-
nu, iar apariia erorii este depistat cu ajutorul funciei IOResult.

100 Eroare la citirea de pe disc. Generat de execuia procedurii Read pentru
fiiere cu tip, dac se ncearc citirea sfritului de fiier.
101 Eroare la scrierea pe disc. Generat de execuia uneia din procedurile Close,
Write, WriteLn, Flush sau Page, dac s-a umplut discul (nu mai este spaiu pe disc).
102 Fiier neasignat. Generat de execuia uneia din procedurile Reset, Rewrite,
Append, Rename sau Erase, dac variabila fiier nu a fost asignat unui nume fizic,
prin procedura Assign.
103 Fiier nedeschis. Generat de execuia uneia din procedurile/funciile Close,
Read, Write, Seek, Eof, FilePos, FileSize, Flush, BlockRead sau BlockWrite, dac
fiierul nu este deschis.
104 Fiier nedeschis pentru intrare. Generat de execuia uneia din proceduri-
le/funciile Read, ReadLn, Eof, EoLn, SeeKEof sau SeeKEoln, dac fiierul TEXT
respectiv nu este deschis pentru consultare.
105 Fiier nedeschis pentru ieire. Generat de execuia uneia din procedurile
Write sau WriteLn, dac fiierul TEXT respectiv nu este deschis pentru creare/ex-
tindere.
106 Format numeric invalid. Generat de execuia uneia din procedurile Read sau
ReadLn, dac o valoare numeric citit dintr-un fiier TEXT nu concord cu formatul
numeric declarat.


218
Programarea calculatoarelor Tehnica programrii n limbajul Pascal
3. Erori critice

150 Disc protejat la scriere
151 Unit necunoscut
152 Dispozitivul nu este pregtit
153 Comand necunoscut
154 Eroare CRC n dat
155 Cerere pe un dispozitiv greit
156 Eroare de poziionare pe disc
157 Tip dispozitiv necunoscut
158 Sector negsit
159 Imprimant n ateptarea hrtiei
160 Incident la scrierea pe dispozitiv
161 Incident la citirea de pe dispozitiv
162 ntrerupere hardware


4. Erori fatale

200 mprire la zero. Generat de mprirea la 0 a unui numr, cu operatorii / ,
MOD sau DIV.
201 Nonapartenen la un interval. Generat de instruciunile compilate cu
directiva {$R+}, n urmtoarele condiii:
expresia de indice pentru referirea unui element de masiv este n afara
intervalului;
atribuirea unei valori n afara intervalului stabilit pentru variabila
respectiv;
atribuirea unei valori n afara intervalului stabilit pentru un parametru de
procedur/funcie.
202 Depire stiv. Generat la apelul unei proceduri/funcii, compilate cu directiva
{$S+}, cnd nu este spaiu suficient n stiv pentru memorarea variabilelor locale.
Stiva se poate mri cu directiva de compilare {$M}. Eroarea apare i n cazul unui
apel recursiv infinit.
203 Depire heap. Generat de execuia uneia din procedurile New sau GetMem,
cnd nu este suficient spaiu n heap, pentru alocarea unui bloc sau a unei zone de
mrime specificat.
204 Operaie cu pointer invalid. Generat de execuia uneia din procedurile
Dispose sau FreeMem dac: pointerul are valoarea nil sau indic o locaie n afara
zonei heap; lista blocurilor libere nu poate fi extins, deoarece este plin; HeapPtr
are o valoare prea apropiat de limita inferioar a listei libere.
205 Depire virgul mobil. Generat n urma unei operaii al crei rezultat este
un numr prea mare pentru a fi reprezentat ntr-un tip real de dat Pascal.
206 Depire inferioar virgul mobil. Generat n urma unei operaii al crei
rezultat este un numr prea mic pentru a fi reprezentat ntr-un tip real de dat Pascal.
219
Erori de execuie
Apare numai dac se utilizeaz coprocesorul matematic 8087. Se transmite, implicit,
valoarea zero.
207 Operaie virgul mobil invalid. Generat dac:
Argumentul funciilor Trunc sau Round este n afara intervalului
[-2147483648, 2147483647];
Argumentul funciei Sqrt este negativ;
Argumentul funciei Ln este negativ sau zero;
A aprut o depire a stivei 8087.
208 Managerul de reacoperire nu este instalat. Generat n urma apelului unei
funcii/proceduri de reacoperire, n cazul n care componenta de gestiune a
structurilor de reacoperire (Overlay Manager) nu a fost instalat (cel mai adesea nu
s-a apelat procedura OvrInit sau apelul ei a euat).
209 Eroare la citirea unui fiier de reacoperire. Generat n cazul n care se
produce o eroare cnd managerul de reacoperire ncearc s citeasc un unit dintr-un
fiier de reacoperire.

220




1. Apostol, C.,
Roca, I., Gh.,
Ghilic-Micu, B.,
Roca, V.
Introducere n programare. Teorie i practic Pascal,
Casa de editur i pres Viaa Romneasc, Bucureti,
1993


2. Apostol, C.,
Roca, I., Gh.,
Ghilic-Micu, B.,
Roca, V.
Prelucrarea fiierelor n Pascal, Editura Tehnic,
Bucureti, 1994


3. Ionescu, A.,
Cocianu, C.
Fundamentele programrii. Probleme rezolvate i
propuse, Editura ASE, Bucureti, 2000

4. Findlay, W.,
Watt, D.
Pascal. An Introduction to Methodical Programming,
Pitman Publishing, 1987


5. Knuth, D. The Art of Computer Programming, Vol. 2,
Seminumerical Algorithms, Addison-Wesley, 1981

6. Knuth, D. The Art of Computer Programming, Vol. 2,
Seminumerical Algorithms, Addison-Wesley, 1981

7. Roca, I., Gh.,
Apostol, C.,
Ghilic-Micu, B.,
Roca, V.
Programare sistematic n Pascal, Editura Didactic i
Pedagogic, Bucureti, 1998


8. Roca, I., Gh.,
Apostol, C.,
Ghilic-Micu, B.,
Stoica, M.,
Cocianu, C.,
Uscatu, C.
Bazele elaborrii programelor. Exerciii rezolvate i
propuse, Editura ASE, Bucureti, 1999

9. Stoer, I.,
Bulirsh, R.
Introduction to Numerical Analysis, Springer-Verlag,
1980


BIBLIOGRAFIE
221

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