Documente Academic
Documente Profesional
Documente Cultură
Definiţiile de bază
Referinţe locale
Cu transmitere prin valoare, parametrii actuali sunt evaluaţi în timpul chemării, iar
valorile calculate sunt atribuite parametrilor formali locali corespunzători, înainte de
începerea execuţiei.
Ex:
void schimba(int a, int b)
{ int aux; aux=a; a=b; b=aux ; }
Acum putem vedea de ce procedura schimba nu va lucra când parametrii ei sunt
apelati prin valoare, analizăm mecanismul de functionare, a apelarii
procedurii schimba (j, k) pentru j= 1 si k=2 şi în rezultat a=1 iar b=2.
Ultimele doua atribuiri nu sunt prezentate explicit în programul sursa al
procedurii schimba; ele însă sunt executate automat. Acum, este clar ca
deşi j si k nu s-au schimbat, a şi b şi-au schimbat valorile. Acest lucru este inutil,
evident, deoarece a si b fiind locale, valorile acestora vor dispărea imediat după
execuţia procedurii (schimba). Chiar daca procedura schimba pare a fi ineficace, nu
există lacune referitoare la tehnica apelarii prin valoare, în general. Acest mecanism
a fost ales în mod deliberat (se refera la mecanismul transmiterii parametrilor) pentru
a furniza protecţie maxima împotriva modificarilor nechibzuite ale variabilelor actuale
(efective).
Cu transfer prin nume, expresia sub forma simbolică a fiecărui parametru actual este
substituită la fiecare apariţie a parametrului formal care îi corespunde, iar după
aceea, şi numai după aceea, procedura/funcţia în cauză este executată.
p(a,b)
Primul apel
Segmentul de date
urătorul rezultat:
c
a
d
3
8860
16
6
4 8
8233
d
-
-
doi obţinem:
16690
AVANTAJELE UTILIZĂRIISUBPROGRAMELOR:
realizarea codului – o dată scris, un subprogram poate fi utilizat de mai multe programe;
elaborarea algoritmilor prin descompunerea problemei în altele mai simple. În acest fel,
rezolvăm cu mult mai uşor problema;
reducerea numărului de erori care pot apărea la scrierea programelor;
depistarea cu uşurinţă a erorilor – verificăm la început subprogramele, apoi modul în
care le-am apelat în cadrul programului.
Tipuri de parametri
Parametrii care se găsesc în apelul funcţiei se numesc parametri formali.
Atunci când scriem o funcţie nucunoaştem valoarea propriu-zisă aparametrilor. Funcţia
trebuie să întoarcărezultatul corect, oricare ar fi valoarea lor.Din acest punct de vedere
ei se numesc formali
2. Vizibilitate
Precizează liniile textului sursă din care variabilarespectivă poate fi accesată. Astfel avem:
Vizibilitate la nivel de bloc(instrucţiune compusă);
Vizibilitate la nivel de fişier – în cazul în care programul ocupă un singur fişier sursă;
Vizibilitate la nivel de clasă – este în legătură cu programarea pe obiecte.
3. Durata de viaţă
Reprezintă timpul în care variabila respectivă arealocat spaţiul în memoria internă. Astfel avem:
Durata statică – variabila are alocat spaţiu în tot timpul execuţiei programului
Durata locală – variabila are alocat spaţiu în timpul în care se execută instrucţiunile blocului
respectiv
Durată dinamică – alocarea şi dezalocarea spaţiului necesar variabilei respective se face de
către programator prin operatori sau funcţii speciale.
FUNCTIA
este un subprogram, care calculeaza si returneaza o singura valoare.Ea extinde
notiunea de expresie Pascal.
Prima linie esteantetul functiei,format din:
F- numele functiei;F(X1,X2,«.,Xn)- lista optionalade parametri formali, fiind argumentele
functiei;Tr ±tipul rezultatului, trebuiesa fie tip simplu saureferinta
F
unctie care returneaza media aritmetica a 5 numere intregi:
Function media (x,y,z,k,m:integer):real;BeginMedia := (x+y+z+k+m)/5End;
T
ype natural=0..MaxInt;Function pro(N:natural):natural;BeginP:=1;RepeatC:=N Mod 10;
P:=P*C; N:=N div 10Until N=0; pro:=PEnd;
PRO
CEDU
R
A
-
este un subprogram care prelucreaza datele transmise la apel.
Scrie o procedura care afiseaza la ecrans o l u t i a e c u a t i e i A x + B = 0 :
Procedure ecuatie(a,b:real);BeginIf A<>0 then writeln (solutia=,b/a:7:2)ElseIf b=0 then writeln
(infinit)Else writeln (nu exista)End;
Subprograme (proceduri si functii)
Proceduri
Sa vedem cum rescriem programul folosind o procedura care sa faca acelasi lucru (sa
initializeze variabila i cu 1).
LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL
1. var vector : array[1..200] of integer;
2. i, n: integer;
3.
4. procedure Init;
5. begin
6. i := 1;
7. end;
8.
9. begin
10. Write('Dati N: '); ReadLn(n); {N = numarul de elemente}
11.
12. Init; {*}
13. while (i <= N) do {citim elementele}
14. begin
15. Write('Dati elementul ', i, ': ');
16. ReadLn(vector[i]);
17. i := i + 1;
18. end;
19.
20. Init; {*}
21. while (i <= N) do {impartim fiecare element la 2 si salvam catul}
22. begin
23. vector[i] := vector[i] div 2;
24. i := i + 1;
25. end;
26.
27. Write('Vectorul modificat este : ');
28.
29. Init; {*}
30. while (i <= N) do {afisam noile valori din vector}
31. begin
32. Write(vector[i] : 5);
33. i := i + 1;
34. end;
35.
36. ReadLn; {asteptam sa fie apasat Enter}
37.end.
Probabil ca acum va ganditi "Ce mare branza a rezolvat ? Numarul de linii este acum
mai mare !". Da, asa e, dar asa cum am mentionat, acest program este doar un
exemplu simplist.
Sa vedem un alt program care foloseste o procedura pentru a calcula factorialul unui
numar (pentru cei care nu stiu, factorialul unui numar N este produsul lui 1 x 2 x ... x N).
LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL
1. var i, n, f: integer;
2.
3. procedure Fact;
4. begin
5. f := 1;
6.
7. for i := 1 to n do
8. f := f * i;
9. end;
10.
11.begin
12. Write('Dati N: '); ReadLn(n);
13.
14. Fact;
15. Write('Factorial de N este egal cu : ', f);
16.
17. ReadLn; {asteptam sa fie apasat Enter}
18.end.
Destul de clar, cred. Sa trecem la ...
Functii
Haideti sa vedem cum ar putea arata un program care calculeaza factorialul unui
numar, folosind o functie de data asta:
LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL
1. var i, n, f: integer;
2.
3. function Fact: Longint;
4. var lFact: Longint; {variabila locala}
5. begin
6. lFact := 1;
7.
8. for i := 1 to n do
9. lFact := lFact * i;
10.
11. Fact := lFact; {am asignat rezultatul in numele functiei !}
12. end;
13.
14.begin
15. Write('Dati N: '); ReadLn(n);
16.
17. F := Fact;
18. Write('Factorial de N este egal cu : ', f);
19.
20. ReadLn; {asteptam sa fie apasat Enter}
21.end.
Alta modificare este faptul ca folosim o variabila locala pentru a calcula factorialul. Acest
lucru nu este strict necesar, l-am facut doar pentru a exemplifica rolul variabilelor locale.
Parametri
Lista de parametri este scrisa, practic, ca o lista de variabile. Parametrii pot fi scrisi in
orice ordine sau pot fi grupati dupa tipul variabilelor.
Bun. Am calculat din nou factorialul, dar, de data aceasta, functia noastra Fact a primit
un parametru prin valoare, pe care-l foloseste sa calculeze factorialul. Pe scurt, o data
intrati in corpul functiei (care este apelata ca Fact(N), X este egal cu N. Ce vreau sa
remarcati este faptul ca, desi am dat o noua valoare lui X in interiorul functiei, aceasta
nu este transmisa inapoi lui N, dovada fiind faptul ca noua valoare a lui N (care este
afisata) este aceeasi cu cea introdusa de la tastatura.
Din punctul de vedere al functiei si al metodei de lucru, admitand ca valoarea lui N era
egala cu 5, puteam apela Fact(5). Numele generic al parametrului ("prin valoare") este
dat tocmai din acest motiv: indiferent ca functia este apelata cu o constanta sau o
variabila, doar valoarea ei este transmisa.
Sa vedem acelasi cod, singura diferenta fiind ca acum folosim un parametru prin
adresa.
LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL
1. var i, n, f: integer;
2.
3. function Fact(var X: Integer): Longint; {X este un parametru transmis prin
adresa}
4. var lFact: Longint; {variabila locala}
5. begin
6. lFact := 1;
7.
8. for i := 1 to X do
9. lFact := lFact * i;
10.
11. X := -1;
12. Fact := lFact; {am asignat rezultatul in numele functiei !}
13. end;
14.
15.begin
16. Write('Dati N: '); ReadLn(n);
17.
18. F := Fact(N);
19. WriteLn('Factorial de N este egal cu : ', f);
20. WriteLn('Noua valoare a lui N este : ', n);
21.
22. ReadLn; {asteptam sa fie apasat Enter}
23.end.
Diferenta principala intre parametrii transmisi prin valoare si cei transmisi prin adresa
este faptul ca, in cazul celor transmisi prin valoare, variabila trimisa ca parametru
este copiata intr-o zona de memorie temporara si trimisa functiei, ca si copie, in timp
ce in cazul celor transmisi prin adresa variabila trimisa ajunge in functie neschimbata,
ca original. Din acest motiv, transmiterea parametrilor prin adresa poate rapidiza
executia programului (totusi, sa nu va asteptati la minuni - vorbim de milisecunde si
chiar mai putin).
Atentie: Un subprogram poate avea o lista de parametri micsti: o parte dintre ei sa fie
trimisi prin valoare, iar altii prin adresa. Tot ce conteaza este modul de declarare al
listei.
De remarcat ca parametrii listati in headerul subprogramului se numesc parametri
formali (X este un parametru formal in programul de mai sus), care sunt inlocuiti
de parametri efectivi, in momentul apelului subprogramului (N este un parametru
efectiv in programul de mai sus).
Vizibilitatea variabilelor
Dupa cum am explicat mai sus, se pot declara variabile in interiorul subprogramelor,
chiar si cu nume de variabile care exista deja definite in programul principal. Problema
care se ridica este urmatoarea : de unde stie compilatorul (si implicit, programatorul)
care variabila va fi folosita in anumite zone ale programului ?
Sa vedem un exemplu.
LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL
1. var i, n, f, lFact: integer;
2.
3. function Fact(X: Integer): Longint; {X este un parametru, transmis prin valoare}
4. var lFact: Longint; {variabila locala}
5. begin
6. lFact := 1;
7. WriteLn('lFact local = ', lFact);
8.
9. for i := 1 to X do
10. lFact := lFact * i;
11.
12. X := -1;
13. Fact := lFact; {am asignat rezultatul in numele functiei !}
14. end;
15.
16.begin
17. Write('Dati N: '); ReadLn(n);
18.
19. lFact := 157;
20. WriteLn('lFact global = ', lFact);
21.
22. F := Fact(N);
23. WriteLn('Factorial de N este egal cu : ', f);
24.
25. ReadLn; {asteptam sa fie apasat Enter}
26.end.
Acest program va afisa urmatoarele linii (pentru N egal cu 5):
LINE NUMBER ON/OFF | EXPAND/CONTRACT | SELECT ALL
1. Dati N: 5
2. lFact global = 157
3. lFact local = 1
4. Factorial de N este egal cu : 120
Recursivitate
Pe scurt, daca avem un caz initial caruia ii stim rezultatul, iar restul cazurilor se pot
rezolva in functie de cazul initial, problema poate fi rezolvata recursiv. Cazul initial, pe
functia de mai sus, este cazul in care X nu este mai mare decat 1 (adica este mai mic
sau egal !), acest caz avand rezultatul 1. Pentru orice alta valoare pozitiva a lui X,
rezolvarea se face in functie de X-1, pana cand X ajunge in cazul initial.
Deci, daca avem o problema care poate fi exprimata prin subprobleme ale ei si putem
gasi o conditie de terminare a apelurilor recursive (in acest caz, X = 1), problema poate
fi rezolvata printr-un subprogram recursiv.
Atentie: Apelurile recursive consuma relativ multa memorie. Daca o problema poate fi
rezolvata iterativ (fara apeluri recursive), e de preferat (in general) ca problema sa fie
rezolvata iterativ. O lista prea lunga de apeluri recursive poate genera "stack overflow"
si bloca programul / calculatorul.
Pentru edificare, atasez acelasi program care calculeaza factorialul, modificat pentru a
afisa ce se intampla. Sper sa va fie de ajutor, impreuna cu explicatiile de mai sus.
Recursivitate
Un lucru important de stiut, legat de subprograme, este ca ele sunt necesare daca vrem sa
folosimrecursivitate.
Recursivitatea poate fi un concept destul de greu de inteles, asa ca vom incepe cu un exemplu. Sa
vedem cum rescriem functia care calculeaza factorialul, folosind recursivitatea.
1. function Fact(X: Integer): Longint;
2. begin
3. if X > 1
4. then Fact := Fact(X - 1) * X
5. else Fact := 1
6. end;
Pe scurt, daca avem un caz initial caruia ii stim rezultatul, iar restul cazurilor se pot rezolva in
functie de cazul initial, problema poate fi rezolvata recursiv. Cazul initial, pe functia de mai sus,
este cazul in care X nu este mai mare decat 1 (adica este mai mic sau egal !), acest caz avand
rezultatul 1. Pentru orice alta valoare pozitiva a lui X, rezolvarea se face in functie de X-1, pana
cand X ajunge in cazul initial.
N! = (N-1)! x N
1! = 1
1. Fact(3)
2. X = 3 -> apelam Fact(2) si inmultim cu 3
3. X = 2 -> apelam Fact(1) si inmultim cu 2
4. X = 1 -> 1, se termina functia, revenim in apelul precedent
5. Fact = 1, care inmultit cu 2 este egal cu 2, revenim in
apelul precedent
6. Fact = 2, care inmultit cu 3 este egal cu 6, se termina
functia si revenim in locul unde a fost initial apelata
functia.
Deci, daca avem o problema care poate fi exprimata prin subprobleme ale ei si putem gasi o
conditie de terminare a apelurilor recursive (in acest caz, X = 1), problema poate fi rezolvata
printr-un subprogram recursiv.
Atentie: Apelurile recursive consuma relativ multa memorie. Daca o problema poate fi rezolvata
iterativ (fara apeluri recursive), e de preferat (in general) ca problema sa fie rezolvata iterativ. O
lista prea lunga de apeluri recursive poate genera "stack overflow" si bloca programul /
calculatorul.
Pentru edificare, atasez acelasi program care calculeaza factorialul, modificat pentru a afisa ce se
intampla. Sper sa va fie de ajutor, impreuna cu explicatiile de mai sus.
Codul sursa al programului:
1. uses crt;
2.
3. const lin = 9;
4. line
= '---------------------------------------------------------
--------';
5. Wait = 1000;
6.
7. var i, n, f, lFact, test: longint;
8.
9. function Fact(X: Integer): Longint; {X este un parametru,
transmis prin valoare}
10. begin
11. if X > 1
12. then
13. begin
14. WriteLn('Fact(', X, ') = Fact(', X - 1 ,') *
', X);
15. WriteLn(line);
16. Delay(Wait);
17.
18. Fact := Fact(X - 1) * X;
19. Delay(Wait);
20.
21. TextColor(LightGreen);
22. if Test > 0 then
23. Test := Test * X;
24. GotoXY(40, (N - X) * 2 + lin);
25. Write('Fact(', X,') = ', Test);
26. end
27. else
28. begin
29. TextColor(LightRed);
30. WriteLn('X = 1
' +
31. 'Fact(1) = 1, caz initial !');
32. TextColor(LightGray);
33. WriteLn(line);
34. Delay(Wait);
35. WriteLn('Functia s-a terminat, revenim din
apel ^^^');
36. Delay(Wait);
37. Fact := 1;
38. Test := 1;
39. end;
40. end;
41.
42. begin
43. test := 0;
44. repeat {verificam daca 1 <= N <= 6}
45. ClrScr;
46. Write('Dati N (maxim 6): '); ReadLn(n);
47. until (N > 0) and (N < 7);
48. ClrScr;
49.
50. TextColor(LightRed);
51. GotoXY(Length(line) div 2 - 16 ,2);
52. WriteLn('Calculul factorialului - recursiv');
53. WriteLn(line);
54. WriteLn;
55. TextColor(LightGray);
56. WriteLn('Se apeleaza Fact(', N,') ...');
57. Delay(Wait);
58.
59. TextColor(lightGray);
60. GotoXY(1, lin);
61. F := Fact(N);
62.
63. Delay(Wait);
64. GotoXY(1, N * 2 + lin + 3);
65. TextColor(LightGray);
66.
67. Write('Fact(', N, ') este egal cu : ');
68. TextColor(LightGreen);
69. WriteLn(f);
70. TextColor(LightGray);
71. Write('... apasa orice tasta pentru a termina
programul ...');
72.
73. While Keypressed Do
74. Readkey; {daca s-a apasat o tasta in timp ce
programul rula,
75. va astepta totusi apasarea urmatoarei
taste}
76. ReadKey;
77. end.
Dupa cum am explicat mai sus, se pot declara variabile in interiorul subprogramelor, chiar si cu
nume de variabile care exista deja definite in programul principal. Problema care se ridica este
urmatoarea : de unde stie compilatorul (si implicit, programatorul) care variabila va fi folosita in
anumite zone ale programului ?
Variabilele globale ale programului sunt vizibile oriunde in program. Daca un subprogram isi
defineste o variabila cu acelasi nume, atunci variabila locala e prioritara in acel subprogram (si
in posibilele subprograme ale subprogramului !).
1. var i, n, f, lFact: integer;
2.
3. function Fact(X: Integer): Longint; {X este un parametru, transmis
prin valoare}
4. var lFact: Longint; {variabila locala}
5. begin
6. lFact := 1;
7. WriteLn('lFact local = ', lFact);
8.
9. for i := 1 to X do
10. lFact := lFact * i;
11.
12. X := -1;
13. Fact := lFact; {am asignat rezultatul in numele functiei !}
14. end;
15.
16. begin
17. Write('Dati N: '); ReadLn(n);
18.
19. lFact := 157;
20. WriteLn('lFact global = ', lFact);
21.
22. F := Fact(N);
23. WriteLn('Factorial de N este egal cu : ', f);
24.
25. ReadLn; {asteptam sa fie apasat Enter}
26. end.
1. Dati N: 5
2. lFact global = 157
3. lFact local = 1
4. Factorial de N este egal cu : 120
65
8. Subprograme Pascal :
Procedure, Function , parametri, vizibilitate.
8.1. Subprograme Pascal : Procedure, Function.
În limbajul Pascal exist• dou• tipuri de subprograme: func•ii •i proceduri.
Definirea acestor subprograme în cadrul unui program Pascal se face în
partea de declara•ii, astfel :
<Def_subprogram> ::= <Def_func•ie> | <Def_procedur•>
unde :
<Def_func•ie> ::= <Antet_func•ie> ; <Bloc>
<Def_procedur•> ::= <Antet_procedur•> ; <Bloc>
iar
<Antet_func•ie> ::= FUNCTION <Nume> [ (L_p_f) ] : <Tip_f>
<Antet_procedur•> ::= PROCEDURE<Nume> [ (L_p_f) ]
<Nume> este un identificator care reprezint• numele subprogramului definit, iar
lista parametrilor formali <L_p_f> este optional• •i ea precizeaz• variabilele de
care depinde subprogramul •i tipul acestor variabile;
<Tip_f> reprezint• codomeniul func•iei •i poate fi un tip simplu (Real, Integer,
Byte, Boolean, Char, String, etc). Este obligatoriu ca în corpul func•iei s• existe
cel pu•in o instruc•iune (de atribuire) prin care func•iei s• i se atribuie o valoare
(<Nume>:= . . . ) .
Apelarea unei func•ii se face scriind într-o expresie numele func•iei urmat
de lista parametrilor actuali, iar apelarea unei proceduri se face scriind numele
procedurii urmat de lista parametrilor actuali pe locul unei instruc•iuni, ceea ce
echivaleaz• cu execu•ia tuturor instruc•iunilor din bloc, astfel
<Apel-procedura> ::= <Nume> [ (<Lista-p.a.> ]
Dac• apelul unei func•ii apare în cadrul unei expresii într-o anumit•
instruc•iune, apelul unei proceduri constituie o instruc•iune de sine st•t•toare.66
8.2. Parametri.
Un subrogram este apelat pentru a rezolva o anumit• subproblem•. În
acest scop îi vom furniza ni•te date de intrare •i el ne va da ca rezultate ni•te date
de ie•ire prin care se realizeaz• comunicarea între modulul apelant (parametri
actuali) •i subprogram (parametri formali).
Parametrii actuali de intrare sunt expresii (cu a c•ror valori lucreaz•
subprogramul) pe când cei de ie•ire vor fi variabile (unde se vor depune
rezultatele).
Parametrii formali reprezint• datele de intrare (c•rora le corespunde
valorile expresiilor date prin parametrii actuali, deci vor fi de tip valoare) •i de
ie•ire (c•rora le corespunde adresele variabilelor corespunz•toare parametrilor
actuali, deci vor fi de tip variabil•) ale subprogramului.
Lista parametrilor formali este format• din mai multe sec•iuni de
parametri separate între ele de caracterul ';' . Sintaxa acestei liste este:
<L_p_f.> ::= <spf> { ; <spf> }
unde prin <spf> s-a notat o sec•iune de parametri formali care are sintaxa
<spf> ::= <sp_val> | <sp_var> | <p_functie> | <p_procedura>
Sec•iunea de parametri valoare <sp_val> are sintaxa
<sp_val> ::= <lista_id> : <id_tip>, iar
sec•iunea de parametri variabil• <sp_var> are sintaxa
<sp_var> ::=VAR <lista_id> : <id_tip>
unde <id_tip> este un identificator de tip, definit anterior, deci asem•n•toare
sec•iunii parametrilor valoare, singura diferen•• fiind prezen•a cuvântului VAR în
fa•a listei.
Trebuie s• existe o coresponden•• biunivoc• (ca num•r, pozi•ie, tip,
semnifica•ie, etc.) între parametrii actuali •i cei formali.
Date de intrare Date de iesire Subprogram67
8.3. Vizibilitate.
În defini•ia unui subprogram apare la început un antet, dup• care urmeaz•
un bloc, care con•ine o list• de declara•ii. Elementele definite în lista de
declara•ii sunt locale pentru blocul în care sunt definite. Acesta constituie
domeniul de vizibilitate al acestor elemente; ele pot fi folosite numai în interiorul
subprogramului în care au fost declarate, nu •i în afara acestuia.
Fie S un subprogram al programului P (vezi figura de mai jos). Pe lâng•
variabilele locale ale subprogramului S , toate elementele declarate în lista de
declara•ii ale programului P sunt considerate globale pentru subprogramul S •i
pot fi folosite în acest subprogram. Deci elementele declarate în S pot fi folosite
numai în S, nu •i în restul programului P. Ele sunt locale pentru S, dar sunt
globale •i pot fi folosite în subprogramele S1 •i S2 incluse în S. Elementele
definite în P sunt globale •i pot fi folosite în S, S1 •i S2.
Considerând programul principal
ca un bloc de nivel 0, vom considera
subprogramele definite în el ca blocuri
de nivel 1. În general, un bloc definit
întrun bloc de nivel i are nivelul i+1.
Dac• într-un bloc de nivel i se folose•te o variabil• v, •i acela•i
identificator v noteaz• o variabil• într-un bloc de nivel i+1, atunci cele dou•
variabile se consider• distincte de•i au acela•i nume. În acest caz variabila din
blocul interior este cea considerat• existent• în acest bloc, iar cea exterioar• nu
exist• decât în partea blocului de nivel i exterioar• blocului de nivel i+1.
În exemplul urm•tor se realizeaz• reuniunile (A∪B, A∪C •i B∪C) a trei
mul•imi date de la tastatur• (A, B •i C) pe o linie, fiecare mul•ime fiind introdus•
element cu element, acestea fiind separate cu spa•iu sau virgul• ( de exemplu :
100,200,404,6789 ). Mul•imile fiind memorate sub form• de •iruri, se va memora
cardinalul mul•imii pe pozi•ia 0, iar elementele pe pozi•iile 1,2,3,... .
P
n0 (nivelul 0)
S
n1
S1
n2
S2
n2
S2a
n3
S2b
n2368
Pentru c• o mul•ime (de tip •ir) apare ca parametru formal, va trebui s•
declar•m acest tip ( Type Multime = . . . ).
Procedura Cite•te nu are decât un parametru de ie•ire (mul•imea A care se
cite•te), declarat ca parametru de tip variabil• :
Procedura Tip•re•te are un singur parametru de intrare (mul•imea A care
se tip•re•te), declarat ca parametru de tip valoare :
Procedura Reuniune calculeaz• reuninunea a dou• mul•imi. Are doi
parametri de intrare (A •i B) tip valoare •i un parametru de ie•ire (C) de tip
variabil•:
Reuniunea mul•imilor A •i B se calculeaz• astfel :
• se ini•ializeaz• mul•imea C cu A (C:=A) ;
• se adaug• mul•imii C elementele b∈B care nu apar•in mul•imii A (C:=C ∪
B\A).
Func•ia Apart (b,A) determin• dac• b∈A sau nu (returneaz• valoarea
True respectiv False), prin compararea succesiv• a lui b cu elementele mul•imii
A pân• când g•se•te o valoare egal• cu b sau termin• toate posibilit••ile.
Program AuB_AuC_BuC;
Type Multime = Array[0..100] Of Integer;
Var A, B, C, AuB, AuC, BuC : Multime;
Procedure Citeste (Var A:Multime); { Citeste o multime de la tastatura }
Tip•re•te A
Cite•te A
Reuniune
A
B
C69
Var c,p,n : Integer; s : String;70
Begin
Write (’ Dati elementele multimii : ’); Readln (s); n:=0;
While s<>’’ Do Begin
n:=n+1; Val(s,A[n],p);
If p>0 Then Val(Copy(s,1,p-1),A[n],c) Else p:=Length(s);
Delete (s,1,p)
End;
A[0]:=n; { n=Card(A)→ A[0] }
End;
Function Apart (b:Integer; A:Multime) : Boolean; {Apartine b multimii A?}
Var i,n : Integer;
Begin i:=1; n:=A[0];
While (i<=n) And (b<>A[i]) Do i:=i+1;
Apart := i<=n {Apartine, daca i<=n }
End;
Procedure Reuniune (A,B:Multime; Var C:Multime); { C := A ∪ B }
Var i,p,q,r : Integer;
Begin C:=A; p:=A[0]; q:=B[0]; r:=C[0];
For i:=1 To q Do
If Not Apart(B[i],A) Then Begin
r:=r+1; C[r]:=B[i] End C[0]:=r
End;
Procedure Tipareste (A:Multime); { Tipareste pe ecran o multime A }
Var n,i : Integer;
Begin
n:=A[0]; Write (’ {’);
For i:=1 To n Do Write (A[i],’,’);
Writeln (Chr(8),’}’) { Rescrie peste ultima virgula, acolada }
End;
Begin { Modulul principal }
Citeste (A); Citeste (B); Citeste (C);
Reuniune(A,B,AuB); Tipareste (AuB);
Reuniune(A,C,AuC); Tipareste (AuC);
Reuniune(B,C,BuC); Tipareste (BuC); Readln
End.
Subprograms
A subprogram is a program unit/module that performs a particular task. These subprograms
are combined to form larger programs. This is basically called the 'Modular design'. A
subprogram can be invoked by a subprogram/program, which is called the calling program.
Functions
A function is a group of statements that together perform a task. Every Pascal program has
at least one function which is the program itself, and all the most trivial programs can define
additional functions.
A function declaration tells the compiler about a function's name, return type, and
parameters. A function definition provides the actual body of the function.
Pascal standard library provides numerous built-in functions that your program can call. For
example, function AppendStr() appends two strings, function New() dynamically allocates
memory to variables and many more functions.
Defining a Function:
In Pascal, a function is defined using the function keyword. The general form of a function
definition is as follows:
function name(argument(s): type1; argument(s): type2; ...): function_type;
local declarations;
begin
...
< statements >
...
name:= expression;
end;
A function definition in Pascal consists of a function header, local declarations and a
function body. The function header consists of the keyword function and a name given to the
function. Here are all the parts of a function:
Arguments: The argument(s) establish the linkage between the calling program and
the function identifiers and also called the formal parameters. A parameter is like a
placeholder. When a function is invoked, you pass a value to the parameter. This value is
referred to as actual parameter or argument. The parameter list refers to the type, order, and
number of the parameters of a function. Use of such formal parameters is optional. These
parameters may have standard data type, user-defined datatype or subrange data type.
The formal parameters list appearing in the function statement could be simple or subscripted
variables, arrays or structured variables, or subprograms.
Return Type: All functions must return a value, so all functions must be assigned a
type. Thefunction-type is the data type of the value the function returns. It may be standard,
user-defined scalar or subrange type but it cannot be structured type.
Local declarations: local declarations refer to the declarations for labels, constants,
variables, functions and procedures, which are application to the body of function only.
Function Body: The function body contains a collection of statements that define what
the function does. It should always be enclosed between the reserved words begin and end. It
is the part of a function where all computations are done. There must be an assignment
statement of the type - name := expression; in the function body that assigns a value to the
function name. This value is returned as and when the function is executed. The last
statement in the body must be an end statement.
Function Declarations:
A function declaration tells the compiler about a function name and how to call the function.
The actual body of the function can be defined separately.
For the above defined function max(), following is the function declaration:
Function declaration is required when you define a function in one source file and you call that
function in another file. In such case you should declare the function at the top of the file
calling the function.
Calling a Function:
While creating a function, you give a definition of what the function has to do. To use a
function, you will have to call that function to perform the defined task. When a program calls
a function, program control is transferred to the called function. A called function performs
defined task and when its return statement is executed or when it last end statement is
reached, it returns program control back to the main program.
To call a function you simply need to pass the required parameters along with function name
and if function returns a value then you can store returned value. Following is a simple
example to show the usage:
program exFunction;
var
a, b, ret : integer;
(*function definition *)
function max(num1, num2: integer): integer;
var
(* local variable declaration *)
result: integer;
begin
if (num1 > num2) then
result := num1
else
result := num2;
max := result;
end;
begin
a := 100;
b := 200;
(* calling a function to get max value *)
ret := max(a, b);
writeln( 'Max value is : ', ret );
end.
Procedures are subprograms that, instead of returning a single value, allow to obtain a group
of results.
Defining a Procedure:
In Pascal, a procedure is defined using the procedure keyword. The general form of a
procedure definition is as follows:
procedure name(argument(s): type1, argument(s): type 2, ... );
< local declarations >
begin
< procedure body >
end;
A procedure definition in Pascal consists of a header , local declarations and a body of
the procedure. The procedure header consists of the keyword procedure and a name given to
the procedure. Here are all the parts of a procedure:
Arguments: The argument(s) establish the linkage between the calling program and
the procedure identifiers and also called the formal parameters. Rules for arguments in
procedures are same as that for the functions.
Local declarations: local declarations refer to the declarations for labels, constants,
variables, functions and procedures, which are application to the body of the procedure only.
Procedure Body: The procedure body contains a collection of statements that define
what the procdure does. It should always be enclosed between the reserved words begin and
end. It is the part of a procedure where all computations are done.
Following is the source code for a procedure called findMin(). This procedure takes 4
parameters x, y, z and m and stores the minimum among the first three variables in the
variable named m. The variable m is passed by reference (we will discuss passing arguments
by reference a little later):
procedure findMin(x, y, z: integer; var m: integer);
(* Finds the minimum of the 3 values *)
begin
if x < y then
m := x
else
m := y;
if z <m then
m := z;
end; { end of procedure findMin }
Procedure Declarations:
A procedure declaration tells the compiler about a procedure name and how to call the
procedure. The actual body of the procedure can be defined separately.
Calling a Procedure:
While creating a procedure, you give a definition of what the procedure has to do. To use the
procedure, you will have to call that procedure to perform the defined task. When a program
calls a procedure, program control is transferred to the called procedure. A called procedure
performs the defined task and when its last end statement is reached, it returns the control
back to the calling program.
To call a procedure you simply need to pass the required parameters along with the procedure
name as shown below:
program exProcedure;
var
a, b, c, min: integer;
procedure findMin(x, y, z: integer; var m: integer);
(* Finds the minimum of the 3 values *)
begin
if x < y then
m:= x
else
m:= y;
if z < m then
m:= z;
end; { end of procedure findMin }
begin
writeln(' Enter three numbers: ');
readln( a, b, c);
findMin(a, b, c, min); (* Procedure call *)
writeln(' Minimum: ', min);
end.
When the above code is compiled and executed, it produces following result:
Recursive Subprograms
We have seen that a program or subprogram may call another subprogram. When a
subprogram calls itself, it is referred to as a recursive call and the process is known as
recursion.
To illustrate the concept, let us calculate the factorial of a number. Factorial of a number n is
defined as:
n! = n*(n-1)!
= n*(n-1)*(n-2)!
...
= n*(n-1)*(n-2)*(n-3)... 1
The following program calculates the factorial of a given number by calling itself recursively.
program exRecursion;
var
num, f: integer;
function fact(x: integer): integer; (* calculates factorial of x - x! *)
begin
if x=0 then
fact := 1
else
fact := x * fact(x-1); (* recursive call *)
end; { end of function fact}
begin
writeln(' Enter a number: ');
readln(num);
f := fact(num);
writeln(' Factorial ', num, ' is: ' , f);
end.
When the above code is compiled and executed, it produces following result:
Enter a number:
5
Factorial 5 is: 120
Following is another example which generates the Fibonacci Series for a given number using
arecursive function:
program recursiveFibonacci;
var
i: integer;
function fibonacci(n: integer): integer;
begin
if n=1 then
fibonacci := 0
else if n=2 then
fibonacci := 1
else
fibonacci := fibonacci(n-1) + fibonacci(n-2);
end;
begin
for i:= 1 to 10 do
write(fibonacci (i), ' ');
end.
When the above code is compiled and executed, it produces following result:
0 1 1 2 3 5 8 13 21 34
Arguments of a Subprogram:
If a subprogram (function or procedure) is to use arguments, it must declare variables that
accept the values of the arguments. These variables are called the formal parameters of the
subprogram.
The formal parameters behave like other local variables inside the subprogram and are
created upon entry into the subprogram and destroyed upon exit.
While calling a subprogram, there are two ways that arguments can be passed to the
subprogram:
-------------
procedure DecodeDate( Date: TDateTime; out Year: Word; out Month: Word;
12 out Day: Word );
Decode DateTime to year month and day
procedure DecodeTime( Time: TDateTime; out Hour: Word; out Minute: Word;
13 out Second: Word; out MilliSecond: Word );
Decode DateTime to hours, minutes and seconds
The following example illustrates the use of some of the above functions:
Program DatenTimeDemo;
uses sysutils;
var
year, month, day, hr, min, sec, ms: Word;
begin
writeln ('Date and Time at the time of writing : ',DateTimeToStr(Now));
writeln('Today is ',LongDayNames[DayOfWeek(Date)]);
writeln;
writeln('Details of Date: ');
DecodeDate(Date,year,month,day);
writeln (Format ('Day: %d',[day]));
writeln (Format ('Month: %d',[month]));
writeln (Format ('Year: %d',[year]));
writeln;
writeln('Details of Time: ');
DecodeTime(Time,hr, min, sec, ms);
writeln (format('Hour: %d:',[hr]));
writeln (format('Minutes: %d:',[min]));
writeln (format('Seconds: %d:',[sec]));
writeln (format('Milliseconds: %d:',[hr]));
end.
When the above code was compiled and executed, it produced following result:
This chapter explains dynamic memory management in Pascal. Pascal programming language
provides several functions for memory allocation and management.
var
name: array[1..100] of char;
But now let us consider a situation where you have no idea about the length of the text you
need to store, for example you want to store a detailed description about a topic. Here we
need to define a pointer to string without defining how much memory is required.
When the above code is compiled and executed, it produces following result:
function GetMem(
size: PtrUInt
):pointer;
In the previous example, we declared a pointer to a string. A string has a maximum value of
255 bytes. If you really don't need that much space, or a larger space, in terms of
bytes, getmem subprogram allows specifying that. Let us rewrite the previous example,
using getmem:
program exMemory;
var
name: array[1..100] of char;
description: ^string;
begin
name:= 'Zara Ali';
description := getmem(200);
if not assigned(description) then
writeln(' Error - unable to allocate required memory')
else
description^ := 'Zara ali a DPS student in class 10th';
writeln('Name = ', name );
writeln('Description: ', description^ );
freemem(description);
end.
When the above code is compiled and executed, it produces following result:
So you have complete control and you can pass any size value while allocating memory unlike
arrays where once you defined the size cannot be changed.
Pascal provides the procedure dispose to free a dynamically created variable using the
procedurenew. If you have allocated memory using the getmemsubprogram, then you need to
use the subprogram freemem to free this memory. The freemem subprograms have the
following syntax:
procedure Freemem(
p: pointer;
Size: PtrUInt
);
function Freemem(
p: pointer
):PtrUInt;
Alternatively, you can increase or decrease the size of an allocated memory block by calling
the functionReAllocMem. Let us check the above program once again and make use
of ReAllocMem and freememsubprograms. Following is the syntax for ReAllocMem:
function ReAllocMem(
var p: pointer;
Size: PtrUInt
):pointer;
Following is an example which makes use of ReAllocMem and freemem subprograms:
program exMemory;
var
name: array[1..100] of char;
description: ^string;
desp: string;
begin
name:= 'Zara Ali';
desp := 'Zara ali a DPS student.';
description := getmem(30);
if not assigned(description) then
writeln('Error - unable to allocate required memory')
else
description^ := desp;
S.
Function Name & Description
N