1. Generalitati
2. Elemente de sintaxa
3. Structura unui program
4. Tipuri de date predefinite
5. Expresii
6. Declaratii si definitii
7. Instructiuni
8. Subprograme Pascal
9. Tipuri de date structurate
10. Structuri dinamice de date
11. Elemente de modularizare
12. Abstractizarea datelor
13. Programarea orientata pe obiecte
Analiza problemei
Problema initiala se poate reformula astfel: se dau coeficientii ecuatiei de gradul II a*X^2 + b*X + c =
0 si se cere sa se determine radacinile x1, x2 ale acesteia, reale sau complexe.
Descompunerea (nivelul 1)
Din acest enunt identificam deja trei subprobleme
P1: Citirea datelor de intrare (CitesteDate)
P2: Determinarea solutiei ecuatiei de gradul II
P3: Afisarea solutiei determinate (AfiseazaRezultate)
Solutia problemei initiale P se obtine prin compunerea solutiilor subproblemelor P1, P2, P3 (aici
compunerea Œnseamna rezolvarea lor Œn ordinea enumerarii date).
Arborele de structura al programului este:
ÚÄÄÄ¿
³P³
ÀÄÂÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÄÄÁÄ¿ ÚÄÁÄÄ¿ ÚÄÁÄÄ¿
³ P1 ³ ³ P2 ³ ³ P3 ³
ÀÄÄÄÄÙ ÀÄÄÄÄÙ ÀÄÄÄÄÙ
Continuarea descompunerii
Subproblema P1: Citirea coeficientilor ecuatiei de gradul II
Specificare: Sa se citeasca trei numere reale a, b si c
Descompunere (nivelul 2)
Se identifica Œn acest caz o singura subproblema, numita P4:
CitesteReal care va trebui aplicata (rezolvata) de trei ori:
1) CitesteReal pentru a
2) CitesteReal pentru b
3) CitesteReal pentru c
Subproblema P4 (CitesteReal) este suficient de simpla si nu mai trebuieste descompusa (se poate
implementa direct)
Subproblema P2: Determinarea solutiei ecuatiei de gradul II
Specificare: Sa se rezolve ecuatia de gradul II cu coeficientii a, b si c
Descompunere (nivelul 2)
2
Se identifica Œn acest caz doua subprobleme:
P5: verifica daca ecuatia este de gradul II (DateCorecte)
P6: determina solutia ec. de gradul II (Prelucreaza)
Solutia subproblemei P2 este
Daca DateCorecte atunci Prelucreaza
Subproblema P3: Afisarea rezultatelor
Specificare: Sa se afiseze rezultatele rezolvarii ec. de gradul II
Nu mai este nevoie de descompunere
Arborele de structura al programului este:
ÚÄÄÄ¿
³P³
ÀÄÂÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
ÚÄÄÁÄ¿ ÚÄÁÄÄ¿ ÚÄÁÄÄ¿
³ P1 ³ ³ P2 ³ ³ P3 ³
ÀÄÄÂÄÙ ÀÄÂÄÄÙ ÀÄÄÄÄÙ
³ ÚÄÄÄÄÄÁÄÄÄÄÄÄ¿
ÚÄÄÁÄ¿ ÚÄÄÁÄ¿ ÚÄÄÁÄ¿
³ P4 ³ ³ P5 ³ ³ P6 ³
ÀÄÄÄÄÙ ÀÄÄÄÄÙ ÀÄÄÄÄÙ
Programul P1a apeleaza subprogramul local P2, care nu are parametri si care
foloseste variabila globala Contor, declarata Œnainte de declaratia lui P2.
El va afisa ca rezultat
Valoarea lui Contor este 1
Valoarea lui Contor este 2
Valoarea lui Contor este 3
Programul functioneaza corect deoarece P2 este Œn domeniul de vizibilitate al variabilei Contor.
Daca Œnsa declaratia variabilei Contor apare dupa declaratia subprogramului P2, ca Œn exemplul
urmator,
Program P1b;
{ foloseste un subprogram local, P2 }
Procedure P2;
Begin
WriteLn('Valoarea lui Contor este', Contor:4)
{ aici se va produce eroare de compilare: Contor este
6
identificator necunoscut }
End; {P2}
Var
Contor: Integer;
Begin {programul principal}
For Contor := 1 To 3 Do P2
End; { P1b }
atunci se va produce o eroare de compilare la compilarea lui P1b, deoarece identificatorul Contor (referit
acolo) nu este Œnca declarat (P2 nu este Œn DoV al variabilei Contor si refera aceasta variabila).
Cum se corecteaza eroarea de mai sus?
- varianta 1 (nerecomandata): Programul P1a
- varianta 2 (recomandata): Programul P1c - Contor devine parametru al lui P2
Program P1c;
{ foloseste un subprogram local, P2 }
Procedure P2(C: Integer);
Begin
WriteLn('Valoarea lui Contor este', C:4)
End; {P2}
Var
Contor: Integer;
Begin {programul principal}
For Contor := 1 To 3 Do P2(Contor)
End; { P1c }
Sfaturi:
- Concepeti orice subprogram astfel Œncƒt el sa poata fi inclus Œntr-un modul.
- Nu folositi Œntr-un subprogram variabile globale.
- In locul variabilelor globale folositi parametri.
- Pentru a fi siguri ca subprogramele locale nu folosesc variabile globale, puneti declaratiile de variabile
(Var) dupa declaratiile de subprograme (ca Œn programul P1c). Aceasta va garanta faptul ca variabilele
globale se vor folosi numai Œn corpul programului, nu si Œn subprograme.
Exemplu:
Program P2a;
{ foloseste o procedura locala, ScrieSuma }
Procedure ScrieSuma(A, B, C: Integer);
Var
S: Integer;
Begin
S := A + B + C;
WriteLn('Suma numerelor este', S:4);
A := 0;
B := 0;
C := 0
End; {ScrieSuma}
Var
N1, N2, N3: Integer;
Begin {programul principal}
N1 := 12;
N2 := 23;
N3 := 34;
WriteLn('Se aduna numerele: ', N1:3, N2:3, N3:3);
ScrieSuma(N1, N2, N3);
WriteLn('S-au adunat numerele: ', N1:3, N2:3, N3:3)
End; { P2a }
In exemplul de mai sus, ScrieSuma contine o parte de declaratii locale, Œn care este declarata variabila
Œntreaga S. Aceasta variabila are ca domeniu de vizibilitate corpul procedurii ScrieSuma si poate fi
referita numai Œn acesta.
Daca se Œncearca referirea ei Œn programul principal, se va produce o eroare de compilare.
Parametrii formali ai procedurii ScrieSuma sunt declarati astfel:
A, B, C: Integer,
declaratie echivalenta cu
A: Integer; B: Integer, C: Integer (cƒnd mai multi parametri formali consecutivi au acelasi tip de date,
ei pot fi pusi Œntr-o lista (numele lor se separa prin virgule) si se scrie o singura data tipul (la fel ca la
declaratia de variabile). Declararea parametrilor formali ai procedurii se poate considera tot o declaratie
de variabile locale: acestia au semnificatie doar atƒta timp cƒt procedura se executa.
Antetul procedurii ScrieSuma stabileste modalitatea Œn care aceasta poate fi apelata. Prin urmare am
dedus o regula importanta: declaratia de procedura stabileste modul de apel al acesteia. Orice apel care
nu se conformeaza declaratiei va fi respins (Œn cazul limbajului Pascal de catre compilator).
9
Apelul procedurii ScrieSuma din exemplul de mai sus se conformeaza regulii enuntate. Toti parametrii
actuali de intrare pot fi orice expresii care se pot evalua Œn momentul apelului (Œn cazul nostru ei sunt
expresii simple, formate din variabile declarate Œn zona de declaratii a programului apelant).
Executia acestui program va produce afisarea urmatoarelor mesaje:
Se aduna numerele: 12 23 34
Suma numerelor este 69
S-au adunat numerele: 12 23 34
8.4.3. Proceduri cu parametri de intrare si de iesire
De cele mai multe ori, o procedura trebuie sa efectueze o operatie care modifica mediul programului
apelant. Am vazut anterior ca acest lucru se poate face Œn doua moduri:
- prin modificarea unei variabile globale (declarata Œn programul appellant Œnainte de declaratia
procedurii apelate, care este vizibila Œn corpul procedurii)
- prin transmiterea modificarii spre programul apelant printr-un parametru de iesire
Apare aici un element nou: cum se poate extrage (scoate) din procedura o valoare calculata Œn ea si
apoi aceasta sa se faca disponibila Œn programul apelant, care sa o poata folosi Œn continuare? Cu alte
cuvinte, cum se specifica faptul ca un parametru formal de procedura este parametru de iesire?
Sintaxa declaratiei de procedura cu parametri de intrare si de iesire este identica cu cea pentru
procedurile cu parametri de intrare, cu singura deosebire ca declaratiile parametrilor formali de iesire
trebuie prefixate cu Var. Din nou, daca o procedura are mai multi parametri de iesire de acelasi tip, si
care sunt consecutivi, declararea acestora se poate condensa.
Apelarea unei proceduri cu parametri de intrare si de iesire se face la fel ca Œn cazul procedurilor cu
parametri de intrare. Exista Œnca o restrictie privitoare la parametrii actuali de iesire. Daca parametrii
actuali de intrare pot sa fie orice expresii care se pot evalua Œn momentul apelului, parametrii actuali de
iesire trebuie sa fie obligatoriu variabile care au punctual apelului Œn domeniul lor de vizibilitate.
Exemple:
Declaratia de procedura
este echivalenta cu
Procedure Imparte(a: Integer; b: Integer; Var c: Integer; Var r: Integer);
In declaratiile de mai sus, a si b sunt parametri de intrare, iar c si r sunt parametri de iesire.
In exemplul de mai sus, CalculSuma nu mai contine declaratia locala a variabilei Œntregi S, aceasta
transformƒndu-se Œn parametru de iesire, fiind declarat ca atare Œn antetul procedurii.
Parametrii formali ai procedurii CalculSuma sunt declarati astfel
A, B, C: Integer; var S: Integer.
Aceasta declaratie specifica faptul ca primii trei sunt parametri de intrare, iar S este parametru de iesire.
Daca analizam programul principal, constatam ca:
- s-a declarat o noua variabila Œntreaga, Suma
- apelul procedurii CalculSuma contine patru parametri actuali, primii trei cu semnificatia din exemplul
anterior, iar al patrulea pe post de parametru de iesire (Œn cazul nostru variabila Suma joaca acest rol,
valoarea ei fiind folosita Œn continuare pentru afisare
- afisarea sumei numerelor s-a transferat din subprogram Œn programul appellant (motiv pentru care
numele subprogramului s-a schimbat)
Executia acestui program va produce afisarea acelorasi mesaje ca si cele de la programul precedent:
Se aduna numerele: 12 23 34
Suma numerelor este 69
S-au adunat numerele: 12 23 34
O categorie speciala de subprograme este formata din functii. Scopul unei functii este calculul unei
valori, care este Œntoarsa (folosita) Œn programul apelant. Asemanarile dintre proceduri si functii sunt
urmatoarele
- ambele sunt subprograme
- declaratiile lor formeaza un bloc
- ambele au parametri.
Deosebirile dintre proceduri si functii sunt cel putin urmatoarele:
- functiile Œntorc un singur rezultat, de un tip simplu (Œn Pascal)
- apelul de procedura este considerat Œn Pascal instructiune, pe cƒnd apelul de functie este considerat
operand Œntr-o expresie
- functiile nu trebuie sa aiba parametri de iesire
- la functii trebuie precizat tipul rezultatului intors (calculat), care este folosit in programul apelant
Din punct de vedere sintactic, declaratia de functie are forma:
Function Nume_Functie[(<lista_parametri_formali>)]: tip_rezultat;
[declaratii]
Begin { corpul functiei }
instr_1;
...
instr_n
End; { Nume_Functie }
11
unde
- Function, Begin, End sunt cuvinte rezervate
- Nume_Functie este numele functiei (identificator)
- lista_parametri_formali este o lista de declaratii de parametri formali (poate sa lipseasca)
- tip_rezultat este tipul de data al rezultatului Œntors de functie (este obligatoriu)
- declaratia de functie introduce un bloc
- prima linie a declaratiei de functie se numeste antet (la fel ca la programul principal)
- zona declaratii contine declaratiile locale Œn functie, care vor avea ca
DoV blocul functiei; se pot include aici toate tipurile de declarati discutate
- instr_1, ..., instr_n sunt instructiuni Pascal (simple sau compuse); Œntre aceste instructiuni trebuie sa
apara cel putin odata o instructiune de atribuire de forma
Nume_Functie := expresie;
Apelul unui subprogram de tip functie se face identic cu cel de procedura, adica se scrie numele
subprogramului (urmat Œn paranteza de parametrii actuali, daca functia are parametri). Ceea ce difera
este semnificatia apelului: deoarece functia Œntoarce o valoare, apelul de functie are semantica unui
operator Œntr-o expresie si nu semantica unei instructiuni simple, ca apelul de procedura. Prin urmare,
apelul de functie poate sa apara oriunde poate apare o expresie de tipul sau.
Exemplul urmator este echivalent cu cele prezentate anterior, folosind de aceasta data un subprogram de
tip functie:
Program P2c;
{ foloseste o functie locala, CalculSuma }
Function CalculSuma(A, B, C: Integer): Integer;
Begin
CalculSuma := A + B + C;
A := 0;
B := 0;
C := 0
End; {CalculSuma}
Var
N1, N2, N3: Integer;
Begin {programul principal}
N1 := 12;
N2 := 23;
N3 := 34;
WriteLn('Se aduna numerele: ', N1:3, N2:3, N3:3);
WriteLn('Suma numerelor este', CalculSuma(N1, N2, N3):4);
WriteLn('S-au adunat numerele: ', N1:3, N2:3, N3:3)
End; { P2c }
In exemplul de mai sus, CalculSuma nu mai contine declaratia locala a variabilei Œntregi S, si nici
declaratia parametrului de iesire S; rezultatul Œntors de functie va avea semnificatia lui S din exemplele
precedente. Acest lucru se specifica folosind Œn corpul functiei numele acesteia Œn membrul stƒng al
operatiei de atribuire: CalculSuma := A + B + C;.
Parametrii formali ai functiei CalculSuma sunt declarati la fel ca Œn
exemplul P2a.
Daca analizam programul principal, constatam ca:
- nu mai este nevoie de variabila Œntreaga Suma
- apelul functiei CalculSuma apare ca parametru al instructiunii de afisare a rezultatului:
12
Executia acestui program va produce afisarea acelorasi mesaje ca si cele dela programele precedente:
Se aduna numerele: 12 23 34
Suma numerelor este 69
S-au adunat numerele: 12 23 34
Vom comenta Œn cele ce urmeaza programul P2a. Presupunem ca s-a facut verificarea corespondentei
dintre parametrii actuali din apelul procedurii ScrieSuma si ca acestia corespund cu parametrii formali
precizati Œn declaratia procedurii.
Constatam ca numarul parametrilor actuali si tipul acestora coincide (parametru cu parametru), deci din
punct de vedere formal conditiile de apelare sunt Œndeplinite. Ce se Œntƒmpla mai departe pentru
executia apelului?
Urmatorul pas este evaluarea parametrilor actuali si punerea lor Œn corespondenta cu cei formali.
Evaluarea este simpla: parametrii actuali au fost initializati anterior, deci au valori bine determinate, iar
corespondenta se stabileste astfel:
- N1 este pus Œn corespondenta cu A
- N2 este pus Œn corespondenta cu B
- N3 este pus Œn corespondenta cu C
Punerea Œn corespondenta Œnseamna (Œn cazul nostru) copierea valorilor parametrilor actuali Œn
parametrii formali corespunzatori, deci se poate scrie printr-o secventa de atribuiri:
A := N1; { atribuie lui A valoarea expresiei N1 }
B := N2; { atribuie lui B valoarea expresiei N2 }
C := N3; { atribuie lui C valoarea expresiei N3 }
Explicatia de mai sus justifica de ce se pot folosi expresii pe post de parametri formali: acestea trebuie
doar sa se poata evalua Œn momentulapelului.
Acum procedura ScrieSuma se poate executa. Prima instructiune din corpul ei realizeaza calcului sumei
S := A + B + C;
care va folosi valorile parametrilor initializate anterior. Valoarea lui S este afisata apoi pe ecran Œn a
doua instructiune, iar urmatoarele trei instructiuni initializeaza pe A, B si C cu 0. Dupa aceasta se
13
Œntƒlneste cuvƒntul rezervat 'end', adica s-a terminat corpul procedurii. Prin urmare, s-a terminat si
executia procedurii ScrieSuma si se revine Œn programul apelant, la instructiunea urmatoare apelului.
Aceasta va afisa valorile dinainte de apel ale variabilelor N1, N2 si N3, cu toate ca parametrii
corespunzatori lor au fost modificati Œn timpul executiei corpului procedurii ScrieSuma.
Motivul pentru care se Œntƒmpla asa este acela ca modificarea valorilor parametrilor formali Œn
ScrieSuma nu influenteaza mediul de apel (adica valorile parametrilor actuali din programul apelant)
deoarece parametrii formali sunt tratati drept variabile locale ale subprogramului si ca la terminarea
executiei acestuia ei se distrug - nu mai are loc o atribuire inversa de valori de forma:
N1 := A:;
N2 := B;
N3 := C;
Cu alte cuvinte, A, B si C sunt doar copii ale parametrilor actuali N1, N2 si N3 si modificarea valorii lor
nu influenteaza valorile originalelor.
Aceasta modalitate de transmitere a parametrilor catre un subprogram (procedura sau functie) se
numeste 'transmitere prin valoare'. Fiecarui parametru actual transmis prin valoare Œi corespunde Œn
subprogramul apelat o pseudo-variabila locala, care are chiar numele parametrului formal corespunzator.
Concluzia acestei analize este urmatoarea:
Parametrii actuali transmisi prin valoare dintr-un program apelant P spre un subprogram apelat SP Œsi
pastreaza valorile dinainte de apelul SP, indiferent daca parametrii formali corespunzatori lor se
modifica sau nu Œn SP.
15
8.6.4. Variabile globale si locale Œntr-un subprogram
Am discutat Œn capitolul 6 (Declaratii) despre domeniul de vizibilitate al unui identificator Œn general
si despre domeniul de vizibilitate si durata de viata a variabilelor. Exemplul urmator, pe care-l vom
comenta, contine atƒt variabile globale cƒt si variabile locale si exista o pereche de declaratii pentru
aceeasi variabila.
Program P3;
{ Domeniul de vizibilitate al variabilelor -
variabile locale si globale }
Var
Contor : Integer; { globala }
Indice : Integer; { globala }
Procedure Afiseaza_Date;
Var
Contor, { locala }
Alta : Integer; { locala }
Begin
Contor := 7;
Writeln('In Afiseaza_Date Contor =', Contor:5,
' Indice =',Indice:5);
End; { Afiseaza_Date }
Procedure Scrie_Sfarsit;
Begin
Writeln('Programul s-a terminat');
End; { Scrie_Sfarsit }
Begin { Programul principal }
For Indice := 1 to 3 do Begin
Contor := Indice;
Writeln('In programul principal Contor =',Contor:5,
' Indice =',Indice:5);
Afiseaza_Date;
Writeln('In programul principal Contor =',Contor:5,
' Indice =',Indice:5);
Writeln;
End; { For }
Scrie_Sfarsit
End. { Programul principal }
{ Rezultatul executiei
In programul principal Contor = 1 Indice = 1
In Afiseaza_Date Contor = 7 Index = 1
In programul principal Contor = 1 Indice = 1
Program P4a;
{ Apelul unei proceduri din alta procedura }
Procedure Unu;
Begin
Writeln('Aceasta este procedura Unu');
End; { Unu }
Procedure Doi;
Begin
Unu;
Writeln('Aceasta este procedura Doi');
End; { Doi }
Procedure Trei;
Begin
Doi;
Writeln('Aceasta este procedura Trei');
End; { Trei }
Procedure Scrie_Sfarsit;
Begin
Writeln('Programul s-a terminat');
End; { Scrie_Sfarsit }
{ Rezultatul executiei
se observa ca declaratiile procedurilor Unu, Doi, Trei, Scrie_Sfarsit sunt continute (Œn aceasta ordine)
Œn partea de declaratii a sa. De aici rezulta ca:
- DoV al numelui Unu contine declaratiile procedurilor Unu, Doi, Trei, Scrie_Sfarsit, precum si
programul principal, deci procedura Unu va putea fi apelata Œn oricare dintre acestea (inclusiv Œn Unu
- vezi paragraful urmator);
- DoV al numelui Doi contine declaratiile procedurilor Doi, Trei, Scrie_Sfarsit, precum si programul
principal, deci procedura Doi va putea fi apelata Œn oricare dintre acestea, mai putin Œn Unu - care nu
face parte din DoV al lui Doi
- DoV al numelui Trei contine declaratiile procedurilor Trei, Scrie_Sfarsit, precum si programul
principal, deci procedura Trei va putea fi apelata Œn oricare dintre acestea, mai putin Œn Unu si Doi -
care nu fac parte din DoV al lui Trei
- s.a.m.d.
19
Unknown identifier - Identificator necunoscut
la apelul procedurii Doi Œn corpul lui Trei si (daca comentam acest apel) la
apelul lui Doi din programul principal.
Program P4b;
{ Apelul unei proceduri din alta procedura }
Procedure Unu;
Procedure Doi;
Begin
Writeln('Aceasta este procedura Doi din Unu');
End; { Doi }
Begin { Unu }
Writeln('Aceasta este procedura Unu');
Doi; { corect! Doi este locala in Unu }
End; { Unu }
Procedure Trei;
Begin
Doi; { eroare de compilare: Identificator necunoscut }
Writeln('Aceasta este procedura Trei');
End; { Trei }
Procedure Scrie_Sfarsit;
Begin
Writeln('Programul s-a terminat');
End; { Scrie_Sfarsit }
Program P4b;
[declaratii]
Procedure Unu;
Procedure Doi; { locala Œn Unu si invizibila Œn afara }
Procedure Trei;
Procedure Scrie_Sfarsit;
begin { Programul principal }
[corp]
end. { P4b }
20
din care se observa ca procedurile locale Œn program sunt procedurilor Unu,
Trei, Scrie_Sfarsit care sunt continute (Œn aceasta ordine) Œn partea de
declaratii a sa, iar procedura Doi este locala Œn Unu. De aici rezulta ca:
- DoV al numelui Unu contine declaratiile procedurilor Unu, Doi, Trei,
Scrie_Sfarsit, precum si programul principal, deci procedura Unu va putea
fi apelata Œn oricare dintre acestea (inclusiv Œn Unu - vezi paragraful
urmator);
- DoV al numelui Doi contine doar declaratiile procedurilor Doi si Unu, fara
programul principal, deci procedura Doi nu va putea fi apelata decƒt Œn
corpul lui Unu - unde este locala si Œn propriul sau corp (apel recursiv -
vezi sectiunea urmatoare)
- DoV al numelui Trei contine declaratiile procedurilor Trei, Scrie_Sfarsit,
precum si programul principal, deci procedura Doi va putea fi apelata Œn
oricare dintre acestea, mai putin Œn Unu si Doi - care nu fac parte din DoV
al sau
- s.a.m.d.
program P4c;
{ Apelul unei proceduri din alta procedura }
Procedure Unu;
Begin
Writeln('Aceasta este procedura Unu');
End; { Unu }
Procedure Doi;
Procedure Unu;
Begin
Writeln('Aceasta este procedura Unu din Doi');
End; { Unu }
Begin { Doi }
Unu; { apelul procedurii locale Unu }
Writeln('Aceasta este procedura Doi');
End; { Doi }
Procedure Trei;
Procedure Doi;
Procedure Unu;
Begin
Writeln('Aceasta este procedura Unu din Doi din Trei');
End; { Unu }
Begin { Doi }
Unu; { apelul procedurii locale Unu }
Writeln('Aceasta este procedura Doi din Trei');
End; { Doi }
Begin { Trei }
Doi; { apelul procedurii locale Doi }
Writeln('Aceasta este procedura Trei');
21
End; { Trei }
Procedure Scrie_Sfarsit;
Begin
Writeln('Programul s-a terminat');
End; { Scrie_Sfarsit }
{ Rezultatul executiei
Program P4c;
[declaratii]
Procedure Unu;
Procedure Doi;
Procedure Unu; { locala Œn Doi si invizibila Œn afara }
Procedure Trei;
Procedure Doi; { locala Œn Trei si invizibila Œn afara }
Procedure Unu; { locala Œn Doi si invizibila Œn afara }
Procedure Scrie_Sfarsit;
begin { Programul principal }
[corp]
end. { P4c }
n! = n * (n-1)!
23
Un alt exemplu simplu de aplicare a recursivitatii este determinarea
minimului unui sir de numere a1, a2, ..., an. Plecam de la urmatoarea
constatare:
program P5;
{ Proceduri recursive }
Uses Crt;
Procedure Afiseaza_Titlu;
Begin
ClrScr;
WriteLn('Program care foloseste o procedura recursiva');
End; { AfiseazaTitlu }
Procedure Scrie_Sfarsit;
Begin
Writeln('Programul s-a terminat');
End; { Scrie_Sfarsit }
Var
Contor: Integer;
{ Rezultatul executiei
24
Program care foloseste o procedura recursiva
Valoarea indicelui este 7
Valoarea indicelui este 6
Valoarea indicelui este 5
Valoarea indicelui este 4
Valoarea indicelui este 3
Valoarea indicelui este 2
Valoarea indicelui este 1
Programul s-a terminat
program P6;
{ Functii recursive }
Uses Crt;
Procedure Afiseaza_Titlu;
Begin
ClrScr;
WriteLn('Program care determina CMMDC a doua numere');
End; { AfiseazaTitlu }
Procedure Scrie_Sfarsit;
Begin
Writeln('Programul s-a terminat');
End; { Scrie_Sfarsit }
25
Var
Numar1: LongInt; { primul numar citit }
Numar2: LongInt; { al doilea numar citit }
{ Rezultatul executiei
cmmdc(a, 0) ::= a
iar reducerea problemei la una de dimensiune mai mica (dimensiune mai mica
Œnseamna aici parametri cu valori mai mici) se bazeaza pe relatia amintita:
Cu ceea ce stim pƒna acum despre Pascal, acest lucru este imposibil. Sa vedem
de ce.
Program P;
Procedure A;
[corp A] {contine apelul lui B - eroare! B nedeclarat Œnca}
Procedure B;
[corp B] {contine apelul lui A}
Begin
A;
B
End.
Program P;
Procedure A;
Procedure B; { locala Œn A }
[corp B] {contine apelul lui A - corect! A este declarat}
[corp A] {contine apelul lui B - corect! B este declarat}
Begin
27
A;
B {eroare de compilare! B nu este vizibil aici}
End.
Program P;
Procedure B(parametri); Forward;
Procedure A(parametri);
[corp A] {contine apelul lui B - corect!
apelul lui B este precizat Œn Forward}
Procedure B;{nu mai este obligatorie precizarea parametrilor}
[corp B] {contine apelul lui A}
Begin
A;
B
End.
Program P;
Procedure A(parametri); Forward;
Procedure B(parametri);
[corp B] {contine apelul lui A - corect!
apelul lui A este precizat Œn Forward}
Procedure A;{nu mai este obligatorie precizarea parametrilor}
[corp A] {contine apelul lui B}
Begin
A;
B
End.
program P7;
{ Proceduri mutual recursive }
Uses Crt;
Procedure Afiseaza_Titlu;
Begin
28
ClrScr;
WriteLn('Apel recursiv - proceduri mutual recursive');
End; { AfiseazaTitlu }
Procedure Scrie_O_Linie;
begin
Writeln('Valoarea contorului este acum ',Contor:4);
Micsoreaza(Contor);
end; { Scrie_O_Linie }
Procedure Scrie_Sfarsit;
Begin
Writeln('Programul s-a terminat');
End; { Scrie_Sfarsit }
Var
De_Cate_Ori : integer;
{ Rezultatul executiei
Apelez Scrie_O_Linie
Valoarea contorului este acum 7
29
Valoarea contorului este acum 6
Valoarea contorului este acum 5
Valoarea contorului este acum 4
Valoarea contorului este acum 3
Valoarea contorului este acum 2
Valoarea contorului este acum 1
Programul s-a terminat
Incepƒnd cu versiunea 5.0, mediul Turbo Pascal poseda doua tipuri de date noi,
numite generic 'tipuri procedurale': tipul Procedure si tipul Function.
Aceste tipuri se pot declara de catre utilizator si se includ Œn sistemul de
tipuri al limbajului. Prin urmare, se pot declara si folosi variabile de
tipurile respective.
Type
Nume_Tip_Proc = Procedure(lista_parametri_formali);
Nume_Tip_Func = Function(lista_parametri_formali): tip_rezultat;
program P8a;
{ Tipuri procedurale }
30
Uses Crt;
Type
Op_Aritm = Procedure(a, b, c : Integer;
var r : Integer); { tip procedural }
Procedure Afiseaza_Titlu;
Begin
ClrScr;
WriteLn('Program care foloseste tipuri procedurale si');
WriteLn('efectueaza operatii aritmetice cu trei numere')
End; { AfiseazaTitlu }
Procedure Scrie_Sfarsit;
Begin
Writeln('Programul s-a terminat');
End; { Scrie_Sfarsit }
Var
Numar1, Numar2, Numar3: Integer;
Rezultat_Final: Integer;
Operatie: Op_Aritm;
Afiseaza_Titlu;
Write('Introduceti primul numar: ');
ReadLn(Numar1);
31
Write('Introduceti al doilea numar: ');
ReadLn(Numar2);
Write('Introduceti al treilea numar: ');
ReadLn(Numar3);
Operatie := Adunare;
Operatie(Numar1, Numar2, Numar3, Rezultat_Final);
Operatie := Inmultire;
Operatie(Numar1, Numar2, Numar3, Rezultat_Final);
Operatie := Medie;
Operatie(Numar1, Numar2, Numar3, Rezultat_Final);
Scrie_Sfarsit
end. { P8a }
{ Rezultatul executiei
Programul de mai sus defineste tipul procedural Op_Aritm, care are trei parametri Œntregi de intrare
(transmisi prin valoare) si unul Œntreg de iesire (transmis prin adresa). In partea sa de declaratii sunt
definite si trei proceduri care efectueaza operatii aritmetice (numite Adunare, Inmultire si Medie) care au
aceeasi signatura ca si Op_Aritm (chiar daca numele parametrilor difera, numarul lor este acelasi, si ei
corespund ca tip si ca modalitate de transmitere). Zona de declaratii de variabile a programului contine
declararea unei variabile procedurale (de tipul Op_Aritm) numita Operatie, care va fi folosita Œn corpul
programului pentru apelul indirect al procedurilor aritmetice precizate anterior.
Operatie := Adunare;
Operatie(Numar1, Numar2, Numar3, Rezultat_Final);
32
Adunare(Numar1, Numar2, Numar3, Rezultat_Final);
program P8b;
{ Tipuri functionale }
Uses Crt;
{$F+} { Aceasta directiva forteaza apelurile far si este necesara cand dorim sa lucram cu tipuri
procedurale sau functional in Turbo Pascal }
Type
Op_Aritm = Function(a, b, c : integer): Integer;
Procedure Afiseaza_Titlu;
Begin
ClrScr;
WriteLn('Program care foloseste tipuri functionale si');
WriteLn('efectueaza operatii aritmetice cu trei numere')
End; { AfiseazaTitlu }
Procedure Scrie_Sfarsit;
Begin
Writeln('Programul s-a terminat');
End; { Scrie_Sfarsit }
Var
Numar1, Numar2, Numar3: Integer;
Rezultat_Final: Integer;
Operatie: Op_Aritm;
Afiseaza_Titlu;
Write('Introduceti primul numar: ');
ReadLn(Numar1);
Write('Introduceti al doilea numar: ');
ReadLn(Numar2);
Write('Introduceti al treilea numar: ');
ReadLn(Numar3);
Operatie := Adunare;
Rezultat_Final := Operatie(Numar1, Numar2, Numar3);
Operatie := Inmultire;
Rezultat_Final := Operatie(Numar1, Numar2, Numar3);
Operatie := Medie;
Rezultat_Final := Operatie(Numar1, Numar2, Numar3);
Scrie_Sfarsit
end. { P8b }
{ Rezultatul executiei
Program care foloseste tipuri procedurale si
efectueaza operatii aritmetice cu trei numere
Introduceti primul numar: 12
Introduceti al doilea numar: 23
Introduceti al treilea numar: 34
Suma numerelor este 69
Produsul numerelor este 9384
Media numerelor este 23
Programul s-a terminat
}
Sa remarcam ca s-au modificat corespunzator declaratiile tipului procedural (functional) Op_Aritm, ale
subprogramelor aritmetice (care sunt acum functii) si apelul acestora din programul principal.
1. Generalitati
2. Elemente de sintaxa
3. Structura unui program
4. Tipuri de date predefinite
34
5. Expresii
6. Declaratii si definitii
7. Instructiuni
8. Subprograme Pascal
9. Tipuri de date structurate
10. Structuri dinamice de date
11. Elemente de modularizare
12. Abstractizarea datelor
13. Programarea orientata pe obiecte
In cazul unui tablou, selectarea unui element se face pe baza unei expresii
de indice, atasata numelui variabilei tablou. Pe baza expresiei de indice si
a informatiilor despre tablou se efectueaza calculul adresei elementului Œn
cauza. Expresia de indice nu se poate evalua la compilare (ea contine de
regula identificatori), valoarea ei fiind obtinuta la executie.
Pentru fiecare tip de date T introdus printr-o declaratie de tip, Turbo Pascal
pune la dispozitia programatorului o functie numita SizeOf, care Œntoarce
numarul de octeti pe care se reprezinta o variabila de tipul respectiv.
SizeOf poate se poate folosi
- cu parametrul T: SizeOf(T); T este un nume de tip de date
- cu parametrul V: SizeOf(V); V este o variabila de tipul T
[declararea lui T]
Var
V: T;
begin
If SizeOf(V) = SizeOf(T) Then ... {expresia este True}
End.
- numele (optional),
- lista dimensiunilor,
- tipul elementului de tablou,
- domeniul pentru multimea indicilor.
Numele unui tip tablou este un identificator. Exista si tipuri tablou anonime,
care nu necesita declarare de tip, ele putƒndu-se folosi la declararea de
variabile. Lista dimensiunilor precizeaza numarul de dimensiuni al tabloului
respectiv (monodimensional, bidimensional, tridimensional s.a.m.d), existƒnd
restrictii de la limbaj la limbaj privind numarul maxim de dimensiuni permis.
Tipul elementului de tablou defineste natura acestui element, precizƒnd
reprezentarea lui, iar domeniul pentru multimea indicilor este de obicei
(dar nu Œntotdeauna) de tip subdomeniu, oferind informatie despre indicii
37
valizi: pentru fiecare dimensiune se specifica limita inferioara 'li' si
limita superioara 'ls', cu Ord(li) <= Ord(ls); numarul de elemente al
dimensiunii respective este Ord(ls) - Ord(li) + 1. Numarul de elemente al
tabloului este produsul numerelor de elemente din fiecare dimensiune.
Lungimea de reprezentare (dimensiunea alocata) al unei variabile de tip
tablou este egal cu produsul dintre numarul de elemente al tabloului si
lungimea de reprezentare a elementului de tablou.
unde:
- Array si Of sunt cuvinte rezervate
- tip_element, numit tipul componentei, poate fi orice tip recunoscut de
sistemul de tipuri
- tip_index este o lista de tipuri de indici; numarul elementelor din aceasta
lista denota numarul de dimensiuni al tabloului, care nu este limitat.
Tipurile indicilor trebuie sa fie ordinale (cu exceptia lui Longint si a
subdomeniilor de Longint). Daca tipul componentei este tot un tip tablou,
rezultatul acestei declaratii de tip poate fi tratat fie ca un tablou de
tablouri, fie ca un tablou monodimensional. De exemplu, a doua declaratie:
type D = 20..30;
type T = array[boolean] of array[1..10] of array[D] of real;
var
A: T;
A1: T1;
Var
V: Array[1..10] Of Integer;
Array[1..10] Of Integer;
39
In acest caz se spune ca folosim un tip de data anonim, adica fara nume
(el n-are numele declarat Œntr-o declaratie de tip de date). Nu recomandam o
asemenea practica, deoarece sistemul de tipuri al limbajului nu lucreaza asa
cum ne-am astepta noi cu tipurile anonime. Deci sa nu uitam o noua regula:
Memorare pe linii:
toate elementele liniilor anterioare liniei i plus primele j-1 elemente ale
liniei i;
Memorare pe coloane:
toate elementele coloanelor anterioare coloanei j plus primele i-1
elemente ale coloanei j;
Type
Luni = (Ian, Feb, Mar, Apr, Mai, Iun, Iul, Aug, Sep, Oct, Nov, Dec);
Var
temp : array[Luni] of real; {contine temperaturile lunare }
i : luni;
Const
x: real = 0.0; { suma temperaturilor lunare }
instructiunea de ciclare:
Type
DomeniuLinii = 1..25;
DomeniuColoane = 1..80;
Element = Record
Car: Char;
Atr: Byte
End;
TabEcran1 = Array[DomeniuLinii, DomeniuColoane] Of Element;
TabEcran2 = Array[DomeniuLinii] Of Array[DomeniuColoane] Of
41
Element;
Var
EcranColor1: TabEcran1 Absolute $B800:0000;
EcranMono1: TabEcran1 Absolute $B000:0000;
EcranColor2: TabEcran2 Absolute $B800:0000;
EcranMono2: TabEcran2 Absolute $B000:0000;
Begin
EcranColor1[12, 33].Car := 'A';
Write(EcranColor2[12][33].Car);
EcranMono2[11][25].Car := 'B';
Write(EcranMono1[11,25].Car);
End.
9.1.7. Stringuri
In Turbo Pascal este definit tipul String, cu lungime dinamica, Œn doua forme:
Type
String = Array[0..255] Of Char;
String[N] = Array[0..N] Of Char;
In Turbo (Borland) Pascal 7.0 se pot folosi si tablouri deschise (engl. open
arrays) pe post de parametri formali Œn declaratiile de subprograme.
Declararea unui tablou deschis nu se poate face cu sintaxa:
ci doar ca tip anonim, Œntre parametrii unei proceduri sau functii. Pentru
tablourile deschise, Turbo Pascal are doua functii standard, numite Low si
High (parametrul lor este numele tabloului deschis) care Œntorc limita
inferioara, respectiv limita superioara a tabloului deschis.
-----------------------------------------------------------------------
Tipul lui A Ce Œntoarce Low(A)
-----------------------------------------------------------------------
Ordinal cea mai mica valoare a domeniului tipului
Array cea mai mica valoare a domeniului indicilor
tabloului
String 0
Open array 0
parametru String 0
-----------------------------------------------------------------------
------------------------------------------------------------------------
Tipul lui A Ce Œntoarce High(A)
------------------------------------------------------------------------
Ordinal cea mai mare valoare a domeniului tipului
43
Array cea mai mare valoare a domeniului indicilor
tabloului
String dimensiunea declarata a sirului de caractere
Open array numarul de elemente din tablou - 1
parametru String numarul de caractere din sir - 1
------------------------------------------------------------------------
Program TabDesc;
Begin
WriteLn(Min(CA1):10:2);
WriteLn(Min(CA2):10:2);
WriteLn
End. { TabDesc }
T : Array[li..lf] of Real,
care este argument de apel al functiei Min din exemplul anterior, la executia
acesteia parametrul formal A va fi considerat de tipul:
A : array[0..nr-1] of Real;
Limbajul Pascal este unul din primele limbaje care a introdus tipul multime.
Fiind dat un tip ordinal B, numit tip de baza, tipul multime T se declara
folosind sintaxa:
{{}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}}.
Exemple:
Type
Luni = (Ian, Feb, Mar, Apr, Mai, Iun, Iul, Aug, Sep, Oct, Nov, Dec);
Anotimp = Set Of Luni;
Caractere = Set Of Char;
Var
Iarna, Primavara, Vara, Toamna: Anotimp;
Litere, Cifre: Caractere;
Begin
Iarna := [Dec, Ian, Feb, Mar];
Vara := [];
Toamna := [Aug, Sep, Oct, Nov];
Primavara := [Apr, Mai, Iun, Iul];
If Vara = [] Then WriteLn('Anul asta n-a fost vara!');
Litere := ['A'..'Z', 'a'..'z'];
Cifre := ['0'..'9']
End.
Asa cum am discutat Œn cap. 5, Pascal are cinci operatori relationali care
opereaza cu expresii de tipuri multime ca operanzi si care sunt prezentati Œn
tabelul urmator. Primii patru dintre ei cer ca ambii operanzi sa fie tipuri
multime compatibile, iar ultimul are un operand de tipul B si altul de tipul
T unde T este Set Of B.
----------------------------------------------------------------------------
Operator Descriere Exemplu de folosire Rezultat
----------------------------------------------------------------------------
= egalitate de multimi [Ian, Feb] = [ ] False
<> diferit [Ian, Mar] <> [Apr] True
<= incluziunea A <= B [Ian, Mar] <= [Ian, Aug, Mar] True
inseamna ca orice element [Ian, Mar] <= [Feb] False
din A apartine si lui B
>= include: A >= B Œnseamna [Ian, Aug, Mar] >= [Ian, Apr] False
ca orice element din B [Ian, Mar] >= [Mar] True
apartine si lui A
in x in A Œnseamna x Ian in [Aug, Feb] False
apartine lui A Mar in [Ian, Aug, Mar] True
x trebuie sa fie din 'P' in ['A'..'Z'] True
tipul de baza
----------------------------------------------------------------------------
46
9.2.4. Operatii cu multimi
Incepƒnd cu versiunea 7.0, Turbo Pascal poseda doua noi proceduri, Include
si Exclude. Procedura Include, declarata prin
Type
DataC = Record
zi : 1..31;
lu : 1..12;
an : 1800..2000;
End;
Timp = Record
ora: 0..23;
min: 0..59;
sec: 0..59
End;
Element = Record { definitia unui element pe ecranul text }
Car: Char;
Atr: Byte
End;
Var
DataNasterii, DataCasatoriei: DataC;
OraDeIncepere: Timp;
Ecran: Array[1..25] Of Array[1..80] Of ElementEcran;
nume_variabila.nume_cƒmp
Var
Data1, Data2: DataC;
----------------------------------------------
Atribuire globala Echivalenta cu
----------------------------------------------
Data1 := Data2 Data1.zi := Data2.zi
Data1.lu := Data2.lu
Data1.an := Data2.an
----------------------------------------------
Type
DataC = Record
zi : 1..31;
lu : 1..12;
an : 1800..2000;
End;
A40 = Array[1..40] Of Char;
TipSex = (masc,fem);
StareCiv = (necas,casat,vaduv,divortat);
Persoana = Record
Nume : String[30];
NrId : Longint;
Adr : A40;
Sex : TipSex;
StareC : StareCiv;
DataN : Datac;
inalt : Real
End;
Var p : Persoana;
With P Do Begin
P.Nume := 'IONESCU'; Nume := 'IONESCU';
P.Sex := masc; Sex := masc;
P.StareC := casat; StareC := casat;
P.Inalt := 1.80; Inalt := 1.80;
P.DataN.zi := 23; DataN.zi := 23
End
Const
Max_Persoane = 100;
Max_Discipline = 20;
Type
Personal: Array[1..Max_Persoane] Of Persoana;
Medie = Record {facem economie: Medie: Real ar ocupa 6 byte }
Parte_Int: Byte; {SizeOf(Medie) = 2}
Parte_Zec: Byte
End; { Medie }
Medii = Array[1..Max_Discipline] Of Medie;
Trimestru = 1..3;
Elev = Record
Nume: String[40];
DataN: DataC; {declarat Œn exemplul de mai sus}
SitScolara: Array[Trimestru] Of Medii;
End; { Elev }
50
Inregistrarile cu variante respecta principiul de reprezentare a celor cu
structura fixa. Lungimea de reprezentare a unei variabile de tip Œnregistrare
cu variante este de obicei lungimea partii fixe plus maximul lungimii
variantelor. Partea fixa contine inclusiv cƒmpul discriminant. Prin urmare,
Œntr-o Œnregistrare cu variante, primele cƒmpuri ale variantelor au aceeasi
adresa relativa la Œnceputul Œnregistrarii.
Type
CuloareOchi = (caprui,albastru,negru,verde);
Sex = (Masc,Fem);
Persoana = record
Nume : string[30];
NrId : longint;
Adr : array[1..40] of char;
Case s:Sex of { discriminant }
Masc : (Inalt: Real; DataN: DataC);
Fem : (CO: CuloareOchi; Bust:Real)
End;
Un alt exemplu:
Type
ambele = (by,ch);
bc = record
case t:ambele of
by : (b:byte);
ch : (c:char);
end;
var a1, a2, a3 : bc;
Prin urmare variabilele a1, a2, a3 vor contine fie cƒmpuri de tip byte, fie
cƒmpuri de tip caracter. Sunt permise urmatoarele instructiuni:
Nu se pot initializa Œnregistrari ale caror tipuri contin cƒmpuri de tip file.
type
Punct = record
X, Y: Real;
end;
Vector = array[0..1] of Punct;
Luna = (Ian,Feb,Mar,Apr,Mai,Iun,Iul,Aug,Sep,Oct,Nov,Dec);
DataC = Record
zi : 1..31;
lu : Luna;
an : 1800..2000;
End;
const
Origine: Punct = (X: 0.0; Y: 0.0);
Linie: Vector = ((X: -3.1; Y: 1.5), (X: 5.8; Y: 3.0));
ZiuaMea: DataC = (zi: 2; lu: Dec; an: 1960);
52
Fisierul este o colectie de informatii. Aceste informatii se pot structura Œn
Pascal sub forma de text, sub forma de date atomice (de tipuri simple,
predefinite) sau sub forma de Œnregistrari (record). Turbo Pascal poseda si
fisiere cu structura nedefinita, numite fisiere fara tip. Fisierul se poate
considera din doua puncte de vedere
- fizic sau extern programului (respectƒnd conventiile sistemului de operare):
specificator de fisier
- logic sau intern programului care-l foloseste: identificator logic de fisier.
si ea Œntoarce:
- 0 daca ultima operatie de intrare/iesire s-a terminat cu succes
- o valoare diferita de 0 (de obicei un cod al erorii produse) daca ultima
operatie de intrare-iesire a esuat.
var
fis_text: Text; { fisier text }
fis_intregi = File of Integer; { fisier de intregi }
fis_nedefinit: File; { fisier nedefinit }
unde:
- var_fis este o variabila fisier de oricare tip (identificatorul logic de
fisier), iar
- nume_fis este un sir de caractere ce desemneaza numele extern al fisierului
(specificatorul de fisier)
Daca nume_fis este sirul de caractere vid, var_fis va fi asociata unuia dintre
fisierele sistem. Daca nume_fis este numele unui fisier deja deschis, se
produce o eroare de executie.
Dupa Œnchidere, fisierul se poate folosi din nou, respectƒnd etapele descrise
anterior. Variabila fisier devine disponibila, ea putƒnd fi folosita Œntr-un
alt apel al procedurii Assign.
Program CitireT;
var f: text;
linie: string;
numeFis: String;
este: Boolean;
begin
WriteLn('CitireT - afisarea unui fisier text pe ecran');
Repeat
Write('Dati numele fisierului: ');
ReadLn(numeFis);
este := Exista(numeFis);
if not este then WriteLn('Fisier inexistent!');
Until este;
Assign(f, numeFis); { asociaza f la numeFis }
Reset(f); { deschide f in citire }
While not Eof(f) do begin { cat timp nu s-a ajuns la sfarsit }
Readln(f, linie); { citeste o linie din fisier }
Writeln(linie) { scrie linia la iesirea standard }
end;
Close(f); { inchide fisierul }
end. { CitireT }
9.4.2.4. Pozitionarea
Œn care:
- var_fis este o variabila fisier, asociata unui fisier deschis Œn prealabil
- pozitie este un Œntreg, cu urmatoarele valori valide:
- Œntre 0 si FileSize(var_fis) - 1: contorul de pozitie al fisierului
var_fis se va seta la valoarea pozitie
- FileSize(var_fis): Œn fisierul var_fis se va adauga (la sfƒrsit) o noua
Œnregistrare
Citirea se face diferit pentru fiecare clasa de fisiere Borland (Turbo) Pascal.
Ea poate sau nu sa fie Œnsotita de conversii.
9.4.2.6. Scrierea
Fisierele text sunt fisiere speciale, care se pot citi sau edita de orice
editor de texte standard. Un fisier text este o succesiune de caractere ASCII
organizate Œn linii. Numarul de linii este variabil, iar fiecare linie contine
un numar variabil de caractere. O linie se termina cu o combinatie speciala de
caractere (de regula CR+LF, adica ASCII 10 + ASCII 13), iar sfƒrsitul de
fisier poate fi determinat cu ajutorul functiei EOF. Aceasta poate folosi:
- functia FileSize (care determina numarul de caractere din fisier)
- un caracter special de sfƒrsit de fisier (cu codul ASCII 26, recunoscut
prin combinatia CTRL+Z de la tastatura).
Mediile Borland si Turbo Pascal permit specificarea unui fisier text prin
cuvƒntul cheie text, care are declaratia:
59
In cele ce urmeaza, cu exceptia locurilor unde se face o referire explicita,
prin var_fis vom desemna o variabila fisier de tip text, deschis Œn prealabil.
Declaratia sa este:
Procedura standard Read citeste valori dintr-un fisier text Œntr-una sau mai
multe variabile. Citirea se efectueaza Œncepƒnd de la contorul de pozitie,
avansƒndu-se spre sfƒrsitul fisierului. Se pot efectua conversii, Œn functie
de tipul variabilelor prezente ca parametri ai lui Read. Declaratia procedurii
este:
60
procedure Read( [ var var_fis: Text; ] V1 [, V2,...,Vn ] );
unde V1, V2, ..., Vn sunt variabile pentru care Read este Œn domeniul lor de
vizibilitate. Citirea se opreste la sfƒrsitul de linie sau de fisier, fara a
se citi si aceste caractere speciale.
Functia SeekEOF Œntoarce True daca s-a ajuns la sfƒrsitul de fisier si False
altfel. Declaratia sa este:
Functia SeekEOLN Œntoarce True daca s-a ajuns la sfƒrsit de linie si False
altfel. Declaratia sa este:
unde:
- Buf este numele unei variabile (de obicei de tipul unui tablou de caractere)
care va fi folosita pe post de buffer
- Lung este dimensiunea bufferului (Œn octeti)
Procedura Write scrie valoarea uneia sau mai multor variabile Œntr-un fisier
text. Scrierea se efectueaza Œncepƒnd de la contorul de pozitie, avansƒndu-se
spre sfƒrsitul fisierului. Se pot efectua conversii, Œn functie de tipul
variabilelor prezente ca parametri ai lui Write. Declaratia procedurii este:
unde P1, P2, ..., Pn sunt expresii de formatare, formate din nume de
variabile sau expresii (de una din tipurile Char, Integer, Real, String si
61
Boolean) ce contin variabile Œmpreuna cu specificatori de lungime si de
numar de zecimale. Pentru tipurile numerice, se face conversia la string
Œnainte de scrierea Œn fisier. Fisierul trebuie sa fie deschis cu Rewrite
sau Append. Contorul de pozitie se va mari cu lungimea stringurilor scrise.
Fisierele cu tip (pe care le numim si fisiere record) sunt accesate prin
intermediul unei variabile fisier declarata astfel:
var
var_fis: file of tip_componenta;
type
tip_componenta = ... { definitia tipului componentei }
tip_fisier = file of tip_componenta;
var
var_fis: tip_fisier;
type
fisier_integer = file of Integer;
fisier_boolean = file of Boolean;
fisier_persoane = file of Persoana; { tipul Persoana din 9.3.4. }
62
9.4.4.1. Bufferul fisierului
var
var_fis: tip_fisier;
bufferul este o zona de memorie speciala, fara nume, care o vom nota Œn cele
ce urmeaza cu var_fis^. Initializarea variabilei fisier var_fis se face prin
apelul procedurii standard Assign; deschiderea fisierului se face folosind
procedurile standard Reset (Œn citire sau Œn scriere si citire) si Rewrite
(Œn scriere). Odata cu deschiderea, devine accesibil si bufferul fisierului,
adica variabila var_fis^.
type
tip_componenta = Integer;
tip_fisier = file of tip_componenta;
var
var_fis: tip_fisier;
componenta: tip_componenta;
vom deschide acum Œn citire fisierul TEST.DAT si vom putea accesa deja prima
componenta a lui:
Begin
Assign(var_fis, 'TEST.DAT');
63
Reset(var_fis);
componenta := var_fis^
End.
Begin
Assign(var_fis, 'TEST.DAT');
Reset(var_fis);
While not Eof(var_fis) do begin
componenta := var_fis^;
get(var_fis);
WriteLn(componenta)
end;
Close(var_fis)
end.
Am vazut Œnsa ca Œn Pascal exista procedura standard Read pentru citirea din
fisier. De fapt, semantica exacta a procedurii Read este data Œn tabelul
urmator:
-------------------------------------------------------
Procedura standard Este echivalenta cu
-------------------------------------------------------
Read(var_fis, componenta) componenta := var_fis^;
get(var_fis);
-------------------------------------------------------
Begin
Assign(var_fis, 'TEST.DAT');
Reset(var_fis);
While not Eof(var_fis) do begin
Read(var_fis, componenta);
WriteLn(componenta)
end;
Close(var_fis)
64
end.
type
tip_componenta = Integer;
tip_fisier = file of tip_componenta;
var
var_fis: tip_fisier;
componenta: tip_componenta;
i: Integer;
vom deschide acum Œn scriere fisierul TEST.DAT si vom pune prima componenta a
lui Œn buffer:
Begin
Assign(var_fis, 'TEST.DAT');
Rewrite(var_fis);
var_fis^ := componenta
End.
Begin
Assign(var_fis, 'TEST.DAT');
Rewrite(var_fis);
For i := 1 to 10 do begin
componenta := i;
var_fis^ := componenta;
put(var_fis)
end;
Close(var_fis)
end.
-------------------------------------------------------
Procedura standard Este echivalenta cu
-------------------------------------------------------
65
Write(var_fis, componenta) var_fis^ := componenta;
put(var_fis);
-------------------------------------------------------
Begin
Assign(var_fis, 'TEST.DAT');
Rewrite(var_fis);
For i := 1 to 10 do begin
componenta := i;
Write(var_fis, componenta)
end;
Close(var_fis)
end.
type
file = file of byte;
procedure BlockRead(var F: File; var Buf; Count: Word [; var Result: Word]);
unde:
F Variabila fisier fara tip
Buf variabila de orice tip (de obicei un tablou de byte), de
lungime cel putin egala cu RecSize
Count expresie de tip Word
Result variabila de tip Word
procedure BlockWrite(var F: File; var Buf; Count: Word [; var Result: Word]);
unde:
F Variabila fisier fara tip
Buf variabila de orice tip (de obicei un tablou de byte), de
lungime cel putin egala cu RecSize
Count expresie de tip Word
Result variabila de tip Word
Var
Input: Text { Input standard file }
Output: Text { Output standard file }
5.1. Stive
vezi STIVE.LEC - directorul STIVE
5.2. Cozi
vezi COZI.LEC - directorul COZI
6. Arbori
vezi ARBORI.LEC - directorul ARBORI
68
1. Programarea modulara.
1.2.1. Antetul
Unit Nume_Modul;
Toti clientii unit-ului pot folosi numele care sunt declarate in aceasta
parte. In situatia in care exista conflict de nume, numele in conflict se
califica cu numele modulului:
Nume_Modul.Nume
70
Partea de implementare este obligatoriu sa contina corpul subprogramelor
(proceduri si functii) declarate in partea de interfata. In plus, aceasta
parte poate contine si obiecte (etichete, constante, tipuri de date,
variabile, subprograme) locale. Termenul de "local" inseamna ca aceste
obiecte sunt folosibile numai in partea de implementare, nefiind vizibile
in afara acesteia.
1.3. Exemple:
Unit-urile standard
Crt
Dos
Printer
Pana la un punct, intr-un modul putem concentra definitia unui nou tip
de date, impreuna cu operatiile pe acest tip. Am spus pana la un punct,
deoarece daca declaram un tip de date nou, declaratia trebuie sa fie
publica - deci in partea de interfata. O declaratie publica de tip are ca
deficienta faptul ca orice variabila de tipul respectiv este modificabila
(toate componentele sale sunt accesibile) - deci se incalca pe jumatate
principiul ascunderii informatiei).
Toate aceste operatii sunt utile, insa unit-ul UDataC nu ascunde "structura"
DataC, deci nu se elimina posibilitatea modificarii accidentale (sau
neautorizate) a unei variabile de tip DataC in programele client ale
unit-ului.
2. Abstractizarea datelor
2.1. Istoric
2.2. Ce este abstractizarea datelor
2.2.1. Tipuri de date definite de utilizator
2.2.2. Nivele de abstractizare a tipurilor de date
2.3. Tipuri abstracte de date
2.3.1. Specificarea tipurilor abstracte de date
2.3.2. Proiectarea operatiilor unui TAD
2.3.3. Implementarea tipurilor abstracte de date
2.3.4. Avantajele TAD
2.4. Exemple
2.1. Istoric
75
Date Operatii Imbunatatire
--------------------------------------------------------------
adrese de memorie instructiuni masina performanta
Abstractizarea inseamna
- neglijarea detaliilor nesemnificative
- concentrarea asupra esentei.
Exemple:
Type T = ... tip definit de utilizator
var a1,a2: T; a1 si a2 sunt variabile de tipul T
77
Abstractizarea poate fi vazuta si ca o modalitate de ordonare a
gƒndirii umane. Conceperea unui TAD Œnseamna:
- identificarea TAD (Œn termenii rationamentului uman),
- stabilirea unui nume (care sa sintetizeze proprietatile sale),
- precizarea domeniului si a operatiilor.
OM MASINA
ÄÄÄÄÄÄÄÄÄÄÄ> TAD ÄÄÄÄÄÄÄÄÄÄÄÄ> TVD ÄÄÄÄÄÄÄÄÄÄÄÄ> TFD
specificare implementare traducere
ÚÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Nivel ³ Limbaj ³
ÃÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
³ abstract ³ de specificare ³
³ virtual ³ de programare ³
³ fizic ³ masina ³
ÀÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄ¿
³ Nivel ³ Nivel virtual ³ Nivel fizic ³
³ abstract ³ (Turbo Pascal) ³ (procesor 80x86) ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄ´
³ Adresa ³ Record ³ Implementarea ³
³ ³ Localitate:string[20]; ³ TD Record pe ³
79
³ ³ Strada:String[10]; ³ IBM-PC ³
³ ³ Numar:Integer ³ 34=21+11+2 oct. ³
³ ³ End; ³ ³
³ ³ ³ ³
³ Temperaturi ³ Array[1..12] of Real; ³ Implementarea ³
³ medii ³ ³ TD Array pe ³
³ lunare ³ ³ IBM-PC ³
³ ³ ³ 12*6=72 octeti ³
³ ³ ³ ³
³ Vƒrsta ³ Integer ³ Œntreg 80x86 ³
³ ³ ³ 2 octeti ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ a) Schema de specificare a unui TAD simplu ³
³ ³
³ Domeniu: descrierea multimii valorilor posibile ³
³ ³
³ Operatii: specificarea fiecarei operatii, vezi c) ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
80
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄ¿
³ b) Schema de specificare a unui TAD structurat ³
³ ³
³ Elemente: descrierea elementelor componente ³
³ ³
³ Structura: descrierea relatiilor sau legaturilor Œntre ³
³ elemente ³
³ ³
³ Domeniu: descrierea multimii valorilor posibile ³
³ ³
³ Operatii: specificarea fiecarei operatii, vezi c) ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄ¿
³ c) Schema de specificare a unei operatii ³
³ ³
³ Nume: numele operatiei (identificator, cƒt mai sugestiv) ³
³ ³
³ Lista de parametri: specificarea parametrilor, ca ³
³ perechi (identificator, TD) ³
³ ³
³ Rezultat: (cƒnd operatia are sensul unei functii Pascal) ³
³ TD al rezultatului Œntors ³
³ ³
³ Pre: preconditia (eventuale conditii impuse parametrilor ³
³ de intrare) ³
³ ³
³ Post: postconditia (precizarea legaturilor dintre ³
³ rezultatele obtinute si parametrii ³
³ de intrare) ³
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÙ
Figura 3. Scheme de specificare
84
Vom discuta Œn cele ce urmeaza caracteristicile fiecarei clase de
operatii. Exemplele furnizate apartin specificarii 4.
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄ¿
³ Meyer ³ Riley ³
ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄ´
³ constructori ³ constructori initiali ³
³ ³ operatii de conversie spre TAD ³
³ ³ operatii de intrare ³
³ modificatori ³ constructori (altii decƒt cei ³
³ ³ initiali) ³
³ accesori ³ operatii de test ³
³ ³ operatii de conversie de la TAD ³
³ ³ operatii de selectare ³
³ ³ operatii de iesire ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄÙ
I(r:Monede) =
0 <= r.Lei <= MaxLongInt si
0 <= r.Bani <= 99 .
2.4. Exemple
Vezi UZile.PAS
Vezi UMonede.PAS
a) Clasa
1. La nivelul abstract:
clasa este un tip abstract de date;
campurile definesc reprezentarea sa;
operatiile definesc comportamentul obiectelor (instantelor) sale;
2. La nivelul virtual:
- clasa este un mecanism existent intr-un limbaj de programare, ce
permite:
- incapsularea datelor si operatiilor;
- stabilirea unor reguli de vizibilitate (acces la campuri din
mediul extern ei;
mecanism de protectie a datelor);
- asocierea unui nume entitatii respective (mecanism de tipizare);
- posibilitatea creerii si distrugerii instantelor (realizarilor)
sale (mecanism de instantiere, constructori, destructori);
- campurile clasei se numesc variabile de instanta sau variabile de
stare;
- operatiile (serviciile) se numesc metode; multimea metodelor clasei
formeaza protocolul de comunicatie al obiectelor ei
Deci, la nivelul abstract clasa este un tip abstract de date, iar in a doua
acceptiune, clasa este un tip virtual de date.
b) Obiectul
send(R,S[,A])
sau
R.S(A)
unde:
R(receptor) este obiectul destinatar al mesajului
S(selector) este metoda apelata
A(argumente, optional) contine parametrii actuali ai apelului
Tinand cont de observatiile de mai sus, primul lucru care trebuie facut este
identificarea obiectelor. In cazul nostru, sistemul real este compus cel
putin din urmatoarele categorii de obiecte (fiinte, lucruri, compartimente):
- marfuri,
- magazii,
- case de marcaj,
- standuri de vanzare,
- personal,
- cumparatori.
Dintre toate aceste obiecte, vom discuta in continuare doar despre marfuri.
In sistemul real (supermagazinul), obiectele (reale) care sunt manipulate
(vandute) sunt marfuri. Prin urmare am identificat obiectele reale si urmeaza
sa le clasificam. Un supermagazin comercializeaza o mare diversitate de
marfuri. Din multe considerente (o gestiune mai usoara, atractivitate si
usurinta in gasirea marfii pentru cumparatori), spatiul comercial al
supermagazinului este impartit in raioane, a caror denumire caracterizeaza
genul de marfuri comercializate. Uzual putem gasi raioanele:
- alimentar,
- textile,
- librarie-papetarie,
- tutungerie,
- cosmetice,
- incaltaminte,
- menaj,
- electrice,
- electronice,
- articole de lux s.a.
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Clasa ³
³ nume, identificator ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Campuri ³ ³ Specificare camp ³
³ specificare camp_1 ³ ³ nume si explicatie ³
³ specificare camp_2 ³ ³ tip de date ³
³ ... ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
³ specificare camp_n ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Metode ³ ³ Specificare metoda ³
³ specificare metoda_1 ³ ³ nume si explicatie ³
³ specificare metoda_2 ³ ³ parametri formali ³
³ ... ³ ³ algoritm ³
³ specificare metoda_m ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Ä¿
³ Clasa ³
³ Marfa ³
95
³ Campuri ³
³ Cod codul marfii, numar intreg ³
³ Denumire denumirea marfii, sir de caractere ³
³ UM unitatea de masura, sir de caractere ³
³ Pret_ach pretul de achizitie, numar real ³
³ TVA procent TVA, numar real ³
³ Adaos_c procent adaos comercial, numar real ³
³ Stoc cantitatea existenta in magazin, ³
³ numar intreg (real) ³
³ Metode ³
³ Pret_tr pret transport ³
³ Pret_tr := 0.1 * Pret_ach ³
³ Pret_v pret vanzare ³
³ Pret_v := Pret_ach (1+(TVA+Adaos_c)/100) ³
³ + Pret_tr ³
³ Intrare(c) intrarea unei cantitati c din marfa ³
³ Stoc := Stoc + c ³
³ Iesire(c) vanzarea unei cantitati c de marfa ³
³ Stoc := Stoc - c ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÙ
4.1.3. Mostenirea
In ierarhia de mostenire, o clasa aflata intr-un nod intern sau terminal are
doua tipuri de caracteristici:
- caracteristici mostenite de la parinti (clasele aflate in aval de ea in
ierarhie);
- caracteristici proprii, specificate in definitia ei (fie caracteristici
noi, fie redefiniri ale caracteristicilor parintilor).
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Clasa ³
³ nume ³
³ Superclasa ³
³ lista de superclase ³
³ Campuri ³
³ specificarea campurilor ³
³ Metode ³
³ specificarea metodelor ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
ÚÄÄÄÄÄÄÄ¿
³ MARFA ³
ÀÄÄÄÂÄÄÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-¿
ÚÄÄÄÄÄÁÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÁÄÄÄÄ¿
98
³ ELECTRICE ³ ³ ARTICOL_DE_LUX ³ ³ ALIMENTE ³
ÀÄÄÄÄÄÂÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÂÄÄÄÄÙ
³ ÚÄÄÄÄÁÄÄÄÄÄ¿ ÚÄÄÄÄÄÁÄÄ-¿
ÚÄÄÄÄÄÁÄÄÄÄ¿ ÚÄÄÄÄÁÄÄ¿ ÚÄÄÄÁÄÄÄ¿ ÚÄÄÁÄÄ¿ ÚÄÄÄÄÁÄÄÄÄÄ¿
³ FRIGIDER ³ ³ VIDEO ³ ³ HOMAR ³ ³ OUA ³ ³ BISCUITI ³
ÀÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÙ
ÚÄÄÄÄÄÄÄ¿
³ MARFA ³
ÀÄÄÄÂÄÄÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄ-¿
ÚÄÄÄÄÄÁÄÄÄÄÄ¿ ÚÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÁÄÄÄÄ¿ ÚÄÄÄÄÄÁÄÄÄÄÄÄ¿
ÚÄÄÄÄÄÁÄÄÄÄ¿
³ ELECTRICE ³ ³ ARTICOL_DE_LUX ³ ³ FRAGILE ³ ³ PERISABILE ³ ³ ALIMENTE ³
ÀÄÄÄÂÄÄÄÂÄÄÄÙ ÀÄÄÄÄÄÂÄÄÄÄÄÄÄÄÂÄÙ ÀÄÄÄÂÄÄÄÄÄÂÙ
ÀÄÄÂÄÄÄÄÄÂÄÄÄÙ ÀÄÄÂÄÄÄÄÂÄÄÙ
³ ³ ³ ³ ³ ³ ÚÄÄÄÄÙ ³ ³ ³
³ ³ ³ ³ ³ ³ ³ ÚÄÄÄÄÄÄÄÄÁÄÄÄ¿ ³ ³
³ ³ ³ ÚÄÄÄÄÄÄÅÄÄÄÄÄÄÄÙ ³ ³ ³ ALTERABILE ³ ³ ³
³ ³ ³³ ³ ³ ³ ÀÄÄÄÄÄÂÄÄÄÄÄÄÙ ³ ³
³ ÀÄÄÄÄÄÄÄÄÄ¿ ³ ³ ³ ÚÄÄÄÄÄÄÄÄÄÅÄÙ ³ ³ ³
³ ³³³ ³ ³ ³ ÚÄÄÄÄÄÄÄÙ ³ ³
³ ³³³ ³ ³ ³ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
ÚÄÄÁÄÄÄÄÄÄÄ¿ ÚÄÁÄÁÄÁÄ¿ ÚÁÄÄÄÁÄÄ¿ ÚÁÄÁÄÁ¿ ÚÄÄÄÄÄÄÄÁÄÄ¿
³ FRIGIDER ³ ³ VIDEO ³ ³ HOMAR ³ ³ OUA ³ ³ BISCUITI ³
ÀÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÙ
from SC inherits A.
(dela SC mosteneste A).
Intre clasele abstracte, un loc aparte il ocup_ clasele generice sau clasele
parametrizate. Daca mostenirea permite rafinarea caracteristicilor unei
multimi de obiecte, plecand de la cele comune si specializand, obtinandu-se
o ierarhie in care fiecare clasa are cel putin o caracteristica diferit in
raport cu celelalte, genericitatea inseamna acelasi comportament pentru clase
diferite. De exemplu, o stiva de intregi, o stiva de siruri de caractere sau
o stiva de inregistrari PERSOANA vor avea (toate) comportamentul generic al
stivei (operatiile Push, Pop si Top), dictat de disciplina de servire LIFO
(Last In First Out). Ceea ce difera la cele trei exemple de stive este tipul
elementului supus manipularii: intreg, sir de caractere, inregistrare de tip
PERSOANA. Genericitatea (in acele limbaje in care este implementata) permite
parametrizarea claselor. Pentru exemplul nostru, va fi suficienta declararea
unei clase Stiva[Type] unde Type este tipul generic al elementului stivei.
Utilizarea acestei clase generice in cazurile particulare enumerate inseamna
instantierea acestei clase generice:
Instantele unei clase generice sunt vazute diferit in limbaje diferite. Spre
exemplu, in Ada (clasa=pachet), instanta unui pachet generic este tot un
pachet, generator de instante terminale (obiecte). Ca si in cazul mostenirii,
genericitatea are ca efect reutilizarea codului scris.
4.1.4. Polimorfismul
Intr-un program pot exista obiecte diferite, care sa fie instante ale unor
clase legate intre ele prin relatia de mostenire. Le numim obiecte inrudite
(polimorfice) deoarece:
- ierarhia claselor ale caror instante sunt are o clasa radacina, clasa de
baza;
- clasa de baza defineste protocolul de comunicatie comun tuturor obiectelor
inrudite: toate obiectele sunt capabile sa raspunda la aceleasi mesaje
(cum raspund e alta problema, important este ca inteleg aceleasi mesaje);
- sunt de tipuri (instante de clase) diferite.
M.Pret_v
MARFA.Pret_v := MARFA.Pret_ach +
(1 + (MARFA.TVA + MARFA.Adaos_c) / 100) +
MARFA.Pret_tr
OUA.Pret_v := OUA.Pret_ach +
(1 + (OUA.TVA + OUA.Adaos_c) / 100) +
OUA.Pret_tr
Dintre acestea, doar Pret_tr este metoda proprie clasei OUA (fiind redefinita
in specificarea 5, la mostenirea simpla, respectiv mostenita de la FRAGILE
sau PERISABILE in specificarea 7, la mostenirea multipla). Toate celelalte
elemente de calcul sunt proprii clasei MARFA, prin urmare pretul ar trebui
sa se calculeze astfel:
OUA.Pret_v := MARFA.Pret_ach +
(1 + (MARFA.TVA + MARFA.Adaos_c) / 100) +
OUA.Pret_tr
OUA.Pret_v := MARFA.Pret_ach +
(1 + (MARFA.TVA + MARFA.Adaos_c) / 100) +
MARFA.Pret_tr
astfel:
1) pentru OUA.Pret_v se deduce (din arborele sau graful de mostenire) ca
MARFA este clasa in care Pret_v este metoda proprie;
2) Pentru elementele de calcul (Pret_ach, TVA, Adaos_c, Pret_tr) se deduce
ca toate sunt proprii clasei MARFA; daca n-ar fi asa, ele ar fi cautate
103
in ierarhia de mostenire, in superclasele clasei MARFA (daca ar exista
asemenea superclase) si nicidecum inapoi, in subclase.
Constructori si destructori
Implementarea polimorfismului
send(EC,S[,A])
sau
EC.S(A)
unde:
EC (receptorul) este un element al colectiei;
S (selectorul, numele metodei) apartine protocolului de
comunicatie definit de clasa de baza.
Obiectele la munca
Revenind la mesajul:
send(R,S[,A])
sau
R.S(A)
A. Legarea statica
Observatie
Unele limbaje (C++, Ada) permit existenta unor proceduri cu acelasi nume,
care difera prin lista argumentelor (se spune ca numele sunt supraincarcate).
In cazul lor, trebuie facuta o verificare in plus: metoda este identificata
dupa nume si dupa lista argumentelor.
B. Legarea dinamica
send(EC,S[,A])
sau
EC.S(A)
unde:
EC este un element al unei colectii polimorfice;
S este o metoda virtuala.
La compilare:
1. se determina C - clasa de baza a elementelor colectiei EC;
2. se verifica daca S este o metoda (virtuala) a lui C, identificandu-se
punctul de intrare in VMT pentru S;
109
3. Daca DA, se verifica sintaxa apelului;
4. Daca sintaxa apelului este corecta, se pune in cod adresa relativa a
metodei S din VMT a lui C.
La executie:
1. se determina C - clasa efectiva a EC (din EC avem adresa VMT; de fapt se
identifica VMT a clasei efective, din semnatura pusa in obiectul EC de
constructor);
2. se identifica S in VMT determinata la pasul anterior (1), pe baza adresei
relative a lui S din VMT, determinata la compilare;
3. din VMT se ia punctul de intrare determinat la pasul 2 si se continua la
fel ca la legarea statica.
In explicatiile de mai sus, am considerat ca, deoarece clasa de baza este cea
care defineste protocolul de comunicatie (prin metodele sale virtuale), in
tabelele de metode virtuale ale claselor derivate o metoda virtuala S va ocupa
aceeasi locatie (va avea aceeasi adresa relativa a unui nume de metoda in
toate VMT ale unei ierarhii de clase). Prin urmare, la compilare se va
determina locatia din tabela (adresa relativa) corespunzatoare metodei
virtuale apelate, iar la executie se va determina in care tabela de metode
virtuale se face cautarea.
110
Nivelul 2 (Abstractizarea datelor)
Al treilea pas este de natura mai putin conceptuala si mai mult practica,
reflectand o cerinta importanta de implementare: cum se creeaza obiectele.
Programatorii nu trebuie sa se preocupe de alocarea sau dealocarea memoriei
pentru obiecte:
Urmatorul pas este cel care face o separare clara a limbajelor bazate pe
obiecte de restul lumii. Se poate spune ca ecuatia de definire a acestor
limbaje este identitatea:
Nivelul 4 (Clase)
Nivelul 5 (Mostenire)
procedure nume_clasa.nume_metoda[(parametri_formali)];
sau
function nume_clasa.nume_metoda[(parametri_formali)] : tip;
112
Instantele unei clase, numite obiecte, sunt declarate ca variabile de tip
nume_clasa:
ob1.nume_metoda(lista_de_parametri_actuali);
sau
pob1^.nume_metoda(lista_de_parametri_actuali);
in care ob1 (respectiv pob1^) este receptorul, iar numele metodei este
selectorul.
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄ¿
³ campuri: X,Y (private) ³
³ metode: Init {modifica campurile X si Y ale obiectului ³
³ la valorile specificate prin aX si aY} ³
³ XCoord {intoarce valoarea abscisei X} ³
³ YCoord {intoarce valoarea ordonatei Y} ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÄÄÙ
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄ¿
³ campuri:X,Y (private si mostenite de la Locatie) ³
³ Vizibil (privat) ³
³ metode: Init {redefineste metoda Init de la Locatie ³
³ initializeaza in plus campul Vizibil} ³
³ XCoord, YCoord {mostenite de la Locatie} ³
³ Deseneaza {desenarea obiectului pe ecran} ³
³ Ascunde {stergerea obiectului de pe ecran} ³
³ EVizibil {intoarce valoarea campului Vizibil} ³
³ MutaIn {muta obiectul in locatia nouX, nouY} ³
³ Translateaza {efectueaza o translatie, marind ³
³ valorile coordonatelor cu valoarea pas} ³
³ Roteste {roteste obiectul in jurul locatiei ³
³ centru, cu unghiul unghi} ³
³ Caracteristici {intoarce un sir de caractere ce ³
³ contine valorile coordonatelor} ³
³ Listeaza {afiseaza caracteristicile obiectului} ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÙ
Type
Cerc = Object(Punct)
procedure Init(aX,aY,aRaza:Integer);
procedure Deseneaza;
procedure Ascunde;
procedure MutaIn(nouX,nouY:Integer);
procedure Translateaza(pas:Integer);
procedure Roteste(centru:Locatie; unghi:Integer);
procedure Mareste(CuCit:Integer);
function Raza : Integer;
function Caracteristici : String;
private
R : Integer;
End;
ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄ¿
³ campuri: X,Y,Vizibil (private si mostenite de la Punct) ³
³ R (raza, privat) ³
³ metode: Init {redefineste metoda Init de la Punct ³
³ initializeaza in plus campul R} ³
³ XCoord {mostenita de la Locatie} ³
³ YCoord {mostenita de la Locatie} ³
³ EVizibil {mostenita de la Punct} ³
³ Listeaza {mostenita de la Punct} ³
³ Deseneaza {trasarea obiectului pe ecran ³
³ redefineste metoda omonima de la Punct} ³
³ Ascunde {stergerea obiectului de pe ecran ³
³ redefineste metoda omonima de la Punct} ³
³ MutaIn {muta obiectul in locatia definita ³
³ de coordonatele nouX, nouY ³
³ redefineste metoda omonima de la Punct} ³
³ Translateaza {efectueaza o translatie, marind ³
³ valorile coordonatelor cu pas ³
³ redefineste metoda omonima de la Punct} ³
³ Roteste {roteste obiectul in jurul locatiei ³
³ centru, cu unghiul unghi ³
³ redefineste metoda omonima de la Punct} ³
³ Mareste {mareste raza cercului cu ³
³ valoarea parametrului pas} ³
³ Raza {intoarce valoarea campului R} ³
³ Caracteristici {intoarce un sir de caractere ce ³
³ contine valorile coordonatelor si razei} ³
³ redefineste metoda omonima de la Punct} ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ÄÄÄÄÄÙ
116
Exemplul 2. Unit-ul UPctS.PAS: Implementarea metodelor clasei Punct
A[2] := PC;
Analizand textele sursa ale metodelor clasei Cerc ce sunt redefiniri ale
metodelor clasei Punct, constatam ca MutaIn, Translateaza, Roteste si Listeaza
sunt identice din punctul de vedere al apelului (este clar ca, semantic,
actiunile sunt diferite). Se pune intrebarea:
117
Nu s-ar putea ca metodele amintite sa fie mostenite de la clasa Punct?
Toate metodele prevazute in exemplele discutate pana acum sunt metode statice
(implicit, orice metoda este statica in Turbo Pascal). Cand un mesaj contine
apelul unei metode statice cu selectorul nume_metoda, apelul se poate rezolva
la compilare prin parcurgerea arborelui de mostenire de la clasa obiectului
receptor (cunoscuta la compilare) spre radacina arborelui. Prima metoda gasita
ce are ca selector nume_metoda va fi metoda apelata si acest apel se rezolva
in mod obisnuit (ca apelul unei proceduri din Pascal Standard). Algoritmic,
legarea statica pentru mesaje de forma
ob1.nume_metoda_statica(lista_de_parametri_actuali);
sau
pob1^.nume_metoda_statica(lista_de_parametri_actuali);
inseamna:
Prin urmare, in timpul executiei, o instanta nu-si "cunoaste" clasa sa. Acest
lucru este valabil in situatia in care clasele nu poseda metode constructor,
toate exemplele anterioare fiind din aceasta categorie. Rolul unui constructor
este in primul rand acela de a atasa fiecarei instante "semnatura" clasei la
care aceasta apartine. In Turbo Pascal acest lucru se realizeaza atasand
inca doi octeti reprezentarii fiecarei instante. In spatiul astfel rezervat,
constructorul va pune un pointer la tabela de metode virtuale (VMT) a clasei
la care apartine instanta. Informatia de instantiere este accesibila numai
in citire, ea putand fi modificata doar printr-un alt constructor. Reamintim
ca, pe langa aceasta functie (principala in POO), un constructor are de
obicei sarcina de a initializa campurile instantei (rolul metodelor Init din
exemplele discutate) sau de a aloca memorie dinamica pentru instanta sau
pentru acele campuri ale acesteia ce refera variabile dinamice.
constructor nume_constructor[(parametri_formali)];
si
destructor nume_destructor[(parametri_formali)]; [virtual;]
constructor nume_clasa.nume_constructor[(parametri_formali)]
respectiv
destructor nume_clasa.nume_destructor[(parametri_formali)];
Asadar, VMT este proprie clasei. Am vazut mai inainte ca fiecare instanta
creata cu un constructor poarta in ea "semnatura" clasei prototip, care nu
este altceva decat adresa VMT.
TypeOf(ob) = TypeOf(nume_clasa);
iar faptul ca doua obiecte ob1 si ob2 sunt instantee ale aceleiasi clase prin:
TypeOf(ob1) = TypeOf(ob2);
ob1.nume_metoda_virtuala(lista_de_parametri_actuali);
sau
pob1^.nume_metoda_virtuala(lista_de_parametri_actuali);
Spre deosebire de legarea statica, unde conteaza doar tipul clasei instantei
(cunoscut la compilare), aceasta maniera de legare a selectorului de receptor
120
in timpul executiei a fost numita in 4.1.5.2 'legare dinamica'. Accentuam
faptul ca se apeleaza metoda adecvata instantei, in conformitate cu atributele
ei din timpul executiei, si nu metoda adecvata clasei statice a instantei,
declarata la compilare prin 'var'. Un obiect 'o', instanta a unei clase 'c',
poate fi considerat in dOUA ipostaze distincte:
Vom relua specificatiile claselor Punct si Cerc in care vom folosi metode
virtuale. Conform precizarilor V1-V5, aceasta inseamna ca in fiecare clasa vor
fi prevazute:
- un constructor;
- un destructor (necesar pentru dealocarea obiectelor dinamice);
- metode virtuale.
Inainte de a discuta noile specificatii, ne vom referi la lucrul cu obiecte
dinamice in Turbo Pascal.
121
Un obiect dinamic este alocat in memoria dinamica (heap), fiind referit de un
pointer ce contine adresa lui. Programele ExObSt2 si ExObSt3 contin exemple de
obiecte dinamice din clasele Punct si Cerc. Uzual, in situatia:
New(pob,Init(...));
respectiv
Dispose(pob,Done(...));
pob := New(pointer_nume_clasa,Init(...));
122
type
PointerLaPunct = ^Punct;
Punct = Object(Locatie)
constructor Init(aX,aY:Integer);
destructor Done; virtual;
procedure Deseneaza; virtual;
procedure Ascunde; virtual;
function EVizibil : Boolean;
procedure MutaIn(nouX,nouY:Integer);
procedure Translateaza(pas:Integer);
procedure Roteste(centru:Locatie; unghi:Integer);
function Caracteristici: String; virtual;
procedure Listeaza(c,l:Integer);
private
Vizibil : Boolean;
End;
PointerLaCerc = ^Cerc;
Cerc = Object(Punct)
constructor Init(aX,aY,aRaza:Integer);
procedure Deseneaza; virtual;
procedure Ascunde; virtual;
procedure Mareste(CuCit:Integer);
function Raza : Integer;
function Caracteristici : String; virtual;
private
R : Integer;
End;
var P : Punct;
C : Cerc;
P.Ascunde; {Punct.Ascunde}
Locatie.Init(100,200);
P.Deseneaza {Punct.Deseneaza}
123
C.Ascunde; {Cerc.Ascunde}
Locatie.Init(100,200);
C.Deseneaza {Cerc.Deseneaza}
si
A[1] := New(PointerLaPunct,Init(100,200));
A[2] := New(PointerLaCerc, Init(150,230,50));
A[1]^.Ascunde; {Punct.Ascunde}
Locatie.Init(100,200);
A[1]^.Deseneaza {Punct.Deseneaza}
A[2]^.Ascunde; {Cerc.Ascunde}
Locatie.Init(100,200);
A[2]^.Deseneaza {Cerc.Deseneaza}
In proiectarea ierarhiei claselor, exista unele dintre ele care nu vor poseda
instante. Rolul lor este o mai buna structurare a acestei ierarhii, ele
colectand caracteristicile comune (campuri si metode) pentru mai multe clase
descendente. Clasa Locatie din specificarea 1 este un exemplu de clasa
abstracta. Rolul ei este definirea caracteristicilor (coordonatele, metodele
de initializare si de accesare a acestora) comune pentru clasele descendente.
Toate aceste clase, avand clasa Locatie in arborele lor de mostenire, vor
poseda atributele respective.
124
4.2.6.1. Liste
A doua categorie de metode foloseste din plin apelul de metode virtuale, fie
direct, fie indirect. O atentie speciala trebuie acordata metodei Mareste,
care nu este comuna tuturor claselor mentionate, fiind proprie numai claselor
Cerc si Arc (prototipuri de obiecte rotunde). In implementarea ei se foloseste
functia TypeOf pentru determinarea clasei efective a obiectului. O alta
solutie de implementare ar fi adaugarea metodei virtuale Mareste la clasa
Punct (la care ea n-ar face nimic sau eventual ar desena obiectul), caz in
care implementarea metodei Mareste a clasei s-ar face in aceeasi maniera ca
si metodele anterioare. Aceasta se poate realiza astfel:
- la clasa Punct se declara metoda virtuala Mareste, care se implementeaza
astfel:
Procedure Punct.Mareste(CuCit:Integer);
Begin
125
Deseneaza
End; { Mareste }
Procedure Lista.Mareste(CuCit:Integer);
Var
N : PointerLaNod;
PP : PointerLaPunct;
Begin
N := Ultimul;
While N <> Nil do
Begin
PC := N^.Element;
PC^.Mareste(CuCit)
N := N^.Precedentul
End;
End; { Mareste }
Pentru implementarea unor functii grafice specifice exemplelor discutate anterior, s-a proiectat unit-ul
UGraph, ce exporta o serie de astfel de operatii. Textul sursa este prezentat in unit-ul UGraph.PAS.
Elemente de discutie
Etape
- initializarea modului grafic (trecerea de la modul text la modul grafic)
- lucrul in modul grafic
- terminarea modului grafic (revenirea la modul text)
0 x GetMaxX-1
0ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³ ³
³ ³ ³
³ ³ ³
yÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ.P(x, y) ³
³ ³
³ ³
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
GetMaxY-1
Pixel
- picture element
- coordonate (numere intregi)
- culoare
0 u1 u2 GetMaxX-1
0ÚÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³ P1(u1, v1) ³ ³
v1ÅÄÄÄÄÄÄÄ ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ³
³ º º ³
³ º º ³
³ º º ³
v2ÅÄÄÄÄÄÄÄ ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ ³
³ P2(u2, v2) ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
GetMaxY-1
8.2.1. Terminologie
- ecranul grafic corespunde unui driver grafic
- driverul grafic
- corespunde placii grafice din calculator
127
- este specificat printr-o constanta simbolica cu urmatoarele valori
Constanta ³ Valoare/comentariu
ÍÍÍÍÍÍÍÍÍÍÍÍÍÍØÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
CurrentDriver ³ -128 pentru GetModeRange
Detect ³ 0 Provoaca autodetectie
CGA ³ 1
MCGA ³ 2
EGA ³ 3
EGA64 ³ 4
EGAMono ³ 5
IBM8514 ³ 6
HercMono ³ 7
ATT400 ³ 8
VGA ³ 9
PC3270 ³ 10
- modul grafic
- un driver grafic poate avea mai multe moduri grafice
- la un moment dat pentru driverul grafic existent se lucreaza
intr-un singur mod grafic
- modul grafic defineste
- rezolutia pe verticala si pe orizontala (GetMaxX, GetMaxY)
- numarul de culori (GetMaxColor)
- modul grafic se reprezinta printr-un numar (constanta simbolica)
- informatii de desenare
- culoarea de fond - culoarea fondului (GetBkColor)
- culoarea cernelii - culoarea cu care se deseneaza (GetColor)
- punctul curent (GetX, GetY) - punctul in care se afla
cursorul grafic
128
- pagini grafice
- pentru driverele EGA (256K), VGA si Hercules, memoria grafica se
imparte in mai multe pagini
- fiecare pagina este identificata printr-un numar
- pagina curenta este pagina care este afisata pe ecran (SetVisualPage)
- pagina activa este pagina in care se face desenarea (SetActivePage)
- pagina curenta si pagina activa nu sunt neaparat una si aceeasi
- la animatie se procedeaza astfel:
- se seteaza ca pagina activa alta pagina decat cea curenta si se
deseneaza in ea
- cand pagina este desenata, se declara ca pagina curenta
- se pot folosi mai multe pagini, care se declara pe rand pagini
curente
- culorile pentru modul curent se codifica prin numere intregi
prin urmatoarele constante simbolice
Coordonate ecran
- intregi definiti de rezolutia ecranului
- sunt coordonate absolute - originea este coltul din stanga sus
al ecranului (0, 0)
Coordonate reale
- coordonatele punctelor din planul real
- se reprezinta prin numere reale
Coordonate din fereastra fizica
- sunt relative la coltul din stanga sus al ferestrei
- se obtin din coordonatele ecran prin scaderea coordonatelor
coltului stanga sus
0 GetMaxX-1
133
0ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³ M1(u1, v1) ³ ³
v1ÅÄÄÄÄÄÄÄ ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ³
³ º º ³
v ÅÄÄÄÄÄÄÄĶÄÄÄÄÄÄÄÄÄÄ.M(u, v) º ³
³ º ³ º ³
v2ÅÄÄÄÄÄÄÄ ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ M2(u2, v2) ³
³ ³ ³ ³ ³
ÀÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
GetMaxY-1 u1 u u2
(a, d) x
dÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ (b , d)
³ ³ ³
³ ³ ³
³ ³ ³
yÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ.P(x, y) ³
³ ³
³ ³
³ ³
cÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ (b, c)
a b
Relatii de transformare
x - a u - u1
----- = ------- u1 = 0, u2 = GetMaxX-1
b - a u2 - u1
y - d v - v1
----- = ------- v1 = 0, v2 = GetMaxY-1
c - d v2 - v1
de unde rezulta
134
u := Round((x-a)*(u2-u1)/(b-a)) + u1
v := Round((y-d)*(v2-v1)/(c-d)) + v1
u' := Round((x-a)*(u2-u1)/(b-a))
v' := Round((y-d)*(v2-v1)/(c-d))
Pascal este unul dintre limbajele de programare de referinţă în ştiinţa calculatoarelor, fiind cel care a
definit programarea calculatoarelor. Pascal a fost dezvoltat de elveţianul Niklaus Wirth în 1970 pentru a
pune în practică programarea structurată, aceasta fiind mai uşor de compilat. Unul din marile sale
avantaje este asemănarea cu limbajul natural limba engleză, ceea ce îl face limbajul ideal pentru cei care
sunt la primul contact cu programarea. Pascal este bazat pe limbajul Algol şi a fost denumit astfel în
onoarea matematicianului Blaise Pascal, creditat pentru construirea primelor maşini de calcul numeric.
Wirth a mai dezvoltat limbajele Modula-2 şi Oberon, similare cu Pascal.
Cele mai populare implementări a acestui limbaj au fost Turbo Pascal şi Borland Pascal, ambele ale
firmei Borland cu versiuni pentru Macintosh şi DOS, care i-au adăugat limbajului obiecte şi au fost
continuate cu versiuni destinate programării vizuale pentru Microsoft Windows (limbajul Delphi) şi
pentru Linux (Kylix).
În prezent există şi alte implementări mai mult sau mai puţin populare, dar gratuite, printre care se
remarcă Free Pascal şi GNU Pascal.
Deşi în prezent este relativ rar folosit în industria software, el este încă util elevilor şi studenţilor care
doresc să se iniţieze în programare. Spre deosebire de BASIC, care a stat în trecut la baza învăţării
programării, Pascal este un limbaj structurat. De aceea, el formează un anumit tip de gândire, similar
limbajelor moderne, precum C++, dar nu deţine complexitatea şi abstractizarea acestuia din urmă, fiind
mai uşor de înţeles datorită sintaxei simple şi apropiate de pseudocod.
Cuprins
[ascunde]
135
1 Tipuri de date de bază
2 Operatori (clasificare după tipul de date)
o 2.1 Pentru datele numerice (integer, real, byte, word)
2.1.1 Operatori relaţionali
o 2.2 Pentru datele de tip şir de caractere (string)
2.2.1 Operatori relaţionali
3 Instrucţiuni de bază
o 3.1 Instrucţiune multiplă
o 3.2 Condiţie
o 3.3 Cicluri
3.3.1 Cu test iniţial
3.3.2 Cu test final
3.3.3 Cu număr cunoscut de paşi
4 Structura unui program Pascal
5 Câteva instrucţiuni
o 5.1 WRITE
5.1.1 Exemplu
o 5.2 READ
5.2.1 Exemple
o 5.3 READKEY
5.3.1 Exemplu
o 5.4 STR
5.4.1 Exemplu
o 5.5 VAL
5.5.1 Exemplu
o 5.6 BREAK
o 5.7 EXIT
o 5.8 HALT
5.8.1 Exemplu
o 5.9 DELETE
5.9.1 Exemplu
o 5.10 INSERT
5.10.1 Exemplu
Char (caractere)
136
Array (vectori)
( ) grupează expresiile
= egal
<> diferit
137
[modifică] Operatori relaţionali
<,> mai mare sau mai mic, pe baza ordinii lexicografice în funcţie de codurile ASCII
[modifică] Condiţie
if <condiţie> then
<instrucţiune>;
sau
if <condiţie> then
<instrucţiune>
else
<instrucţiune>;
[modifică] Cicluri
while <condiţie> do
<instrucţiune>;
repeat
<instrucţiuni>
until <condiţie>;
sau
Este o instrucţiune pentru afişarea pe ecran a unui text (şir de caractere) sau a valorii unor constante,
unor variabile sau unor expresii, exceptând date de tip vector sau fişier. Conţinutul a ceea ce urmează să
fie afişat pe ecran este încadrat de două paranteze rotunde. Lista a ceea ce urmează să fie afişat pe ecran
este despărţită prin virgulă. Instrucţiunea WRITELN face aceeaşi acţiune ca şi WRITE dar după afişare
mută cursorul la începutul rândului următor al ecranului.
[modifică] Exemplu
Descriere: afişează pe ecran şirul a= după care afişează valoarea variabilei sau constantei a.
[modifică] READ
Este o instrucţiune care citeşte de la tastatură o variabilă, cu excepţia tipului boolean şi a vectorilor.
Variabilele se scriu între paranteze şi, dacă sunt mai multe variabile, se despart prin virgulă.
Instrucţiunea READLN face acelaşi lucru ca READ dar aşteaptă un <ENTER> înainte de a prelucra
datele primite. În caz că sunt citite mai multe variabile, introducerea acestora se va face prin separarea
valorilor prin spaţii albe (<Space>, <TAB> sau <ENTER>).
[modifică] Exemple
Descriere: afişează pe ecran Dati x= după care citeşte de la tastatură valoarea variabilei x.
readln;
Descriere: aşteaptă apăsarea tastei <ENTER> după care continuă cu restul de instrucţiuni din program.
[modifică] READKEY
Este o instrucţiune de citire de la tastatură a caracterelor (valori de tip char) fără ca acestea să fie afişate
pe ecran. Variabila caracter citită se scrie între paranteze.
[modifică] Exemplu
139
write ('Parasiti aplicatia? (d/n)'); readkey (x);
Descriere: afişează pe ecran Parasiti aplicatia? apoi aşteaptă să fie introdusă de la tastatură o literă.
[modifică] STR
Transformă un număr într-un string (şir de caractere). Odată transformat în string, numărului nu i se mai
pot efectua operaţii matematice deoarece acum este considerat un cuvânt.
[modifică] Exemplu
[modifică] VAL
Transformă un string într-un număr atât timp cât stringul conţine o reprezentare validă.
[modifică] Exemplu
Descriere: creează un număr din stringul s în variabila x. Dacă în timpul execuţiei se întâlneşte o eroare,
variabila de tip integer er va conţine poziţia caracterului de la care s-a constatat că nu se poate
transforma stringul în număr. Spre exemplu, pentru şirul de caractere ' 1234a6 ' variabila er va conţine 5.
[modifică] BREAK
Opreşte forţat un ciclu (FOR, REPEAT sau WHILE), chiar dacă acesta nu s-a încheiat.
[modifică] EXIT
[modifică] HALT
[modifică] Exemplu
halt (5);
[modifică] DELETE
[modifică] Exemplu
140
delete (s, 8, 4);
[modifică] INSERT
[modifică] Exemplu
141