Sunteți pe pagina 1din 7

9. Parametrii funcie/procedur, apel recursiv, definire simultan (Forward ).

9.1. Parametrii funcie / procedur.


Am vazut n lecia anterioar c parametrii unui subprogram pot fi funcii sau proceduri. Acest lucru este necesar n momentul n care dorim s scriem un subprogram care s rezolve aceeai subproblem pentru diverse funcii, utiliznd diverse metode. Acest lucru ne oblig s parametrizm funcia i metoda. De exemplu dac dorim s scriem o procedur Grafic care traseaz graficul unei funcii oarecare f:[a,b]R, atunci voi parametriza functia f i va fi apelat procedura Grafic astfel : Grafic (f,a,b); Grafic (g,...); Grafic (h,...). Dac dorim s realizm graficul cu puncte sau cu segmente sau cu alt metod, atunci vom parametriza metodele de trasare apelul fcndu-se astfel : Grafic (f,a,b,Puncte); Grafic (g,...,Segmente); Grafic (h,...,Puncte) etc. Pentru ca acest lucru s fie acceptat va trebui s utilizm opiunea de compilare {$F+}. De asemenea, pentru c n lista parametrilor formali trebuie s declarm tipul fiecrui parametru, vom fi obligai s declarm (cu Type) tipul funciilor sau procedurilor utilizate ca parametru. De exemplu : Type Functie = Function ( x : Real ) : Real ; ... );

Procedura = Procedure (

Aceste declaraii ne permit s declarm n altetul subprogramelor parametri de tip funcie i procedur astfel :
Function | Procedure <nume_subpr> ( ... f:Functie; ... p:Procedura; ... ) ...

Apelul subprogramelor va utiliza funcii sau proceduri ca parametri actuali : . . . <nume_subpr> ( ... f1, ... ,metoda1, ... ) ... . . . <nume_subpr> ( ... f2, ... ,metoda2, ... ) ...
. . .

70

unde fi i metodai sunt funcii i proceduri de tipul Funcie respectiv Procedur. n exemplul urmtor se poate observa c exist parametri att funcii ct i proceduri. Se genereaz irul X cu 10 elemente dup regula Xi=f(i), se ordoneaz cresctor i se tiprete, apoi irul Y cu 11 elemente dup regula Yi=g(i), se ordoneaz descrescator i se tiprete. Program Parametri_Functie_Procedura; Type Sir = Array [1..30] Of Integer; {$F+}

Functie = Function (x:Integer) : Integer; FctBool = Function (a,b:Integer) : Boolean; Procedura = Procedure(Var Z:Sir; n:Integer); Var X, Y : Sir;

Function f (x:Integer) : Integer; Begin f:=Sqr(x+1)-x End; Function g (x:Integer) : Integer; Begin g:=Sqr(x-1)+x End; Function Cresc(a,b:Integer):Boolean; Begin Cresc:=a<b End;

Function DesCresc(a,b:Integer):Boolean; Begin DesCresc:=a>b End; Procedure Ordonez (Var X:Sir; n:Integer; Relatie : FctBool ); Var Begin Ordonat : Boolean; k, i, v : Integer; k:=1; For i:=1 To n-k Do If Not Relatie(X[i],X[i+1]) Then Ordonat:=False k:=k+1 Until Ordonat; End; Procedure OrdCresc Begin Ordonez (Var A:Sir; n:Integer); ) End;
71

Repeat Ordonat:=True; Begin

v:=X[i]; X[i]:=X[i+1]; X[i+1]:=v; End;

( A, n, Cresc

Procedure OrdDesCresc (Var A:Sir; n:Integer); Begin Ordonez ( A, n, DesCresc ) End;

Procedure Gen_Ord_Tip (Var A:Sir; n:Integer; r : Functie; Ordonare : Procedura ); Var i:Integer; Begin For i:=1 To n Do A[i]:=r(i); Ordonare (A,n); For i:=1 To n-1 Do Write (A[i],,); Writeln(A[n]) End; Begin Gen_Ord_Tip (X,10, f, OrdCresc ); Gen_Ord_Tip (Y,11, g, OrdDesCresc ); End. Readln { Prel X } { Prel Y } {Generare} {Ordonare} { Tiparire }

9.2. Apel recursiv.


Spunem c un subprogram este recursiv dac se definete prin el nsui (n definirea sa se autoapeleaz). De multe ori o definiie recursiv este mult mai simpl i de aceea soluia recursiv va preferat fa de o soluie iterativ (vezi problema Turnurilor din Hanoi). Cnd gndim subprograme recursive, trebuie s fim ateni s nu uitm s dm consisten subalgoritmului recursiv (definirea direct n cazuri partculare, cnd nu se mai autoapeleaz). Ca exemplu propunem urmatoarea problema : Fiind date dou numere naturale de maxim 30 de cifre, sub forma a dou iruri de caractere, s se determine irul cifrelor sumei. Pentru aceasta ncercm s dm o formul recursiv pentru a aduna numrul A avnd n cifre cu numrul B avnd m cifre astfel :
Ad(B,n,A,m,Tr) Dac '1' Ad(A,m,B,n-1,Tr( '0'+B[n]))Cifra(0,B[n]) Ad(A,m-1,B,n-1,Tr(a[m],B[n]))Cifra(a[m],b[n]) m>n m=0, n=0, t=0 m=0, n=0, t=1 m=0, n>0 m>0, n>0 (1) (2) (3) (4) (5)

72

Ad (A,m,B,n,Tr) =

adic : suma a dou numere se poate obine prin nsumarea cturilor i a resturilor (mpririi la 10) celor dou numere (cturile sunt reprezentate de primele m-1 respectiv n-1 cifre, iar resturile sunt a[m] respectiv b[n]). Dac suma resturilor depete 9 atunci Transportul este 1 (altfel este 0). Este suficient s rezolvm problema doar n cazul mn. Dac m>n (1) atunci (pentru c adunarea este comutativ) se adun B cu A (Ad:=B+A). Suma a dou numere se poate obine prin adunarea resturilor (primele m-1 respectiv n-1 cifre) i a transportului rezultat din nsumarea cturilor (cifra m respectiv n ), la care se adaug cifra rezulat din nsumarea rsturilor (5). Dac nu mai sunt cifre n A care trebuiesc adunate, atunci se adun 0 (4). Dac toate cifrele au fost adunate (att ale lui A ct i ale lui B) atunci rezultatul este dat de ultimul transport calculat, adic 0 sau 1 , cazul (2) respectiv (3). Apelul funciei este Ad (A,m,B,n,0) pentru c transportul iniial este nul.

Program Adunare_Numere_siruri_cifre_baza_10; Const Type Var n=31; Numar = String[n]; a, b : Numar;

{ Adun_Str[n], n<=30 }

Function Adun (a, b : Numar) : Numar; Function Ad (m, n, t : Byte) : Numar; Var c:Char; Function Tr (a:Char):Byte; Var s : Byte; Begin Tr:=0;

{ Adun := A+B } { Aduna primele m resp. n cifre }

{ Tr:=a+b[n] Div 10 ; a = 0 sau a[m] }

{ c:=a+b[n] Mod 10

s:= Ord(a)+Ord(b[n])-$60+t; If s>9 Then Begin Tr:=1; s:=s-10 End;

{ s=suma cifrelor 0..19 }

73

c:= Chr(s Or $30); End;

{ c=caracterul sumei resturilor }

Begin If n=0 Then If t=0 Then Ad:= Else Ad:=1 Else Ad:=Ad(m-1,n-1,Tr(a[m]))+c End; Begin If Length(a)>Length(b) Then Adun := Adun (b,a) Else Adun := Ad (Length(a),Length(b),0) End; {Adun } Function Sp(a:Numar) : Numar; Begin If Length(a)<n Then Sp:=Sp( +a) Else Sp:=a End; Begin Write ( Dati a : ); Write ( Dati b : ); Writeln(Sp(a)+ + ); Writeln(Sp(b)); Write (Sp(Adun (a,b))); Readln End. Readln (a) ; Readln (b) ; { Tipareste : { { 1234 + } 123 1357 } } { Completeaza la stanga cu spatii } { Cazul (1), m>n } { Initial Transportul = 0 } Else If m=0 Then Ad:=Ad(m ,n-1,Tr( 0))+c { Cazul (2) } { { { (3) } (4) } (5) }

74

9.3. Definire simultan (Forward ).

n cazul n care dorim s definim funcii simultane (una prin cealalt) va apare problema urmtoare : Ce functie (procedur) se va scrie prima ?. Aceasta pentru c dac se refer un subprogram, acesta trebuie s fie deja definit (de exemplu subprogramul S1 refer (se definete prin) subprogramul S2, iar S2 se definete cu ajutorul lui S1). n aceast situaie se va defini doar antetul unui subprogram urmat de declaia Forward (ceea ce permite scrierea ulterioar a corpului subprogramului). Acest subprogram poate fi referit, de ctre alte

subprograme iar el va fi definit dup acestea astfel :


Function / Procedure S1 ( . . . ) ; Forward; Function / Procedure S2 ( . . . ) ;

{ Antetul lui S1 } { Subprogramul S2 apeleaz S1 }

Begin ... S1... End;


Function / Procedure S1 ( . . . );

{ Subprogramul S1 apeleaz S2 }

Begin ... S2... End; Exemplul care urmeaz va utiliza trei funcii simultane (mutuale) pentru a compara dou numere (a<b, a>b, a=b) reprezentate prin irul (caracterelor) cifrelor. Se observ c este usor de definit a<b (prin >) pentru c este b>a; a=b (prin <,>) nseamn Not a<b i Not a>b, iar a>b dac numrul cifrelor lui a este mai mare dect numrul cifrelor lui b sau dac numrul cifrelor lui a este egal cu numrul cifrelor lui b atunci sau ctul lui a este mai mare dect ctul lui b sau cturile sunt egale iar restul lui a este mai mare dect restul lui b (prin mprire la 10).

75

Program Comparare_Numere_Str_cifre_baza_10; Const Type Var n=10; Numar = String[n]; a,b : String;

{ < , > , = , n<=10 }

Function MaiMare(a,b : Numar) : Boolean; Forward; Function MaiMic (a,b : Numar) : Boolean; Begin MaiMic:=MaiMare(b,a) End;

Function Egale (a,b : Numar) : Boolean; Begin Egale := Not MaiMic(a,b) And Not MaiMare(a,b) End; Var m,n:Byte; { |A| > |B| } { = } { Cat(A) > Cat(B) } { Am > Bn }

Function MaiMare (a,b:Numar) : Boolean; Begin MaiMare:=(m>n) Or (m=n) And (m>0) And

m:=Length(a); n:=Length(b);

(MaiMare(Copy(a,1,m-1),Copy(b,1,n-1)) Or End; Begin Write ( Dati a : ); Write ( Dati b : ); Readln (a) ; Readln (b) ;

(Egale (Copy(a,1,m-1),Copy(b,1,n-1)) And (a[m]>b[n])))

If MaiMic (a,b) Then Write ( a < b ) Else If MaiMare(a,b) Then Write ( a > b ) Else If Egale End. (a,b) Then Write ( a = b ) Else Write ( a ? b ); Readln

76