Sunteți pe pagina 1din 11

Programare Procedural

Cursul nr.8

POINTERI LA FUNC II
Dup compilarea i linkeditarea unui program fiec rei func ii componente i se
asociaz o adresa de memorie care este de fapt adresa de nceput a func iei.
Un pointer c tre func ie este un pointer care poate con ine aceast adres .
S presupunem c o fun ie f are prototipul :
tip f ( lista_param_formali ) ;
Forma general a unui pointer pf la func ia f este de forma :
tip ( *pf ) ( lista param formali ) ;
Se observ c func ia i pointerul asociat func iei trebuie s aibe acela i tip, iar
lista parametrilor formali trebuie s fie identic .
De asemenea, pointerul precedat de stelu trebuie sa fie inclus ntre paranteze
rotunde datorit regulilor de preceden ale limbajului, deoarece in C numele
func iei este echivalent cu adresa ei de nceput.
Un pointer c tre o func ie poate primi adresa de nceput a func iei respective
printr-o atribuire de forma :
pf = f ;
Exemplu :
Un pointer p la func ia f
void f ( float, int ) ;
trebuie declarat in felul urmator :
void ( *pf ) ( float, int ) ;
Dup o atribuire de forma
pf = f ;
apelul func iei prin intermediul pointerului pf se face prin
( *pf ) ( lista_parametri_actuali) ;
1

dac func ia este de tip void, sau


nume_variabila = ( *pf ) ( lista param_actuali ) ;
dac ntoarce un rezultat .
Exemplu :
# include < stdio.h >
# include < conio.h >
int adunare (int x, int y) ;
int scadere (int x, int y) ;
int inmultire (int x ,int y) ;
int impartire (int x, int y) ;
void main ( )
{
int a,b,i ;
clrscr ( ) ;
printf (\ n intoduceti datele : ) ;
printf (\n a=);scanf(% d,& a);
printf (\n b=);scanf(% d,& b);
int( *t [ ] )(int, int)={adunare, scadere, inmultire ,impartire} ;
char *operatie[]={adunare ,scadere ,inmultire ,impartire };
randormize ( ) ;
i=randorm (4);
printf(\n s-a selectat functia % s, operatie [i] );
printf(\n rezultatul % s este % d ,operatie [i] ,( * t [i] )(a,b));
getche( );
}
int adunare(int x,int y)
{
return x+y ;
}
int scadere(int x,int y)
{
return x-y ;
}
int inmultire( int x,int y)
{
return x*y ;
}
int impartire(int x,int y)
2

{
return x/y ;
}
Exemplu :
Transmiterea ca parametri a pointerilor la func ii :
suma(a,b) dac x > 0
Fie func ia f(x)=
dif(a,b)

dac x

Se poate folosi o singur func ie f( )pentru definirea lui f(x), care va avea ca
argumente pe x i un pointer la func ie notat cu p. Acest pointer poate primi att
adresa func iei suma( ) ct i a func iei dif( ).
# include < stadio.h >
# include < conio.h >
int sum ( int a, int b);
int dif (int a ,int b);
void f (float x, int a, int b , int( *p )(int a, int b));
void main( )
{
float x;
int a,b;
clrscr ( );
printf(\n x=); scanf( % f ,&x );
printf(\n a =); scanf(% d ,&a );
printf(\n b =); scanf(% d ,&b);
if(x>0) f(x,a,b,sum) ;
else
f(x,a,b,dif);
getch ( );
}
int sum(int a,int b)
{
return(a+b);
}
int dif(int a,int b)
{
return (a-b);
}
void f(float x,int a,int b,int(*p)(int a,int b))
3

{
printf(\n f ( % f ) = % i ,x, ( *p )(a, b));
}
FUNC II RECURSIVE

Defini ie. O func ie este definit recursiv dac pornind de la anumite valori ale
ei se pot calcula alte valori prin autoapelarea func iei.
Valorile unei func ii recursive se calculeaz din aproape n aproape, pe baza
valorilor cunoscute ale func iei pentru anumite argumente ini iale. Pentru a
calcula noile valori ale unei func ii recursive, trebuie memorate deja valorile
calculate, care sunt strict necesare. Acest fapt face ca implementarea n program
a calculului unor func ii recursive s necesite un consum mare de memorie,
rezultnd timpi mari de execu ie.
Recursivitatea poate fi transformat n itera ie.
In general, forma iterativ a unei func ii este mai eficient dect cea recursiv n
ceea ce prive te timpul de execu ie i memoria consumat .
n alegerea c ii (interativ sau recursiv ) de rezolvare a unei probleme, trebuie
considera i o serie de factori: u urin a program rii, test rii i ntre inerii
programului, eficien a, complexitatea etc.
Dac o problem are o complexitate redus este preferat varianta interactiv .
Forma recursiv este preferat acolo unde transformarea recursivit ii n itera ie
cere un efort de programare deosebit, algoritmul pierzndu- i claritatea, testarea
i ntr tinerea devenind astfel foarte dificile. Calculul valorilor func iilor
respective se poate face direct sau indirect.
Func ia f( ) se nume te direct recursiv dac n corpul ei apar apeluri la ea ns i
(autoapeluri). Func iile f( ) i g( ) se numesc indirect recursive daca f ( ) con ine
apeluri la g( ), iar g( ) con ine apeluri la f( ).
Exemple :
1. Func ia n! pe care o notam cu fact, se define te recursiv astfel :
1 dac n=0 sau n=1
fact:N N

fact(n) =
n . fact(n-1) dac n>1

2. Func ia lui Fibonacci:


1 daca n=0 sau n=1
fib:N N

fib(n)=
fib(n-1)+fib(n-2) dac n>=2

3. Func ia Manna Pnuelli:


x-1
f:N N

dac

x>12

f( x ) =
f(f(x+2)) dac

0 x<12

4. Func ia care calculeaz coeficien ii binominali cu ajutorul triunghiului


lui Pascal :
o dac n < k
comb:NxN N, comb(n,k) = 1 dac n=k
comb(n-1,k)+comb(n-1,k-1), n>k
5. Func ia lui Akermann:
ac:NxN N

ac(m,n) =

n+1
dac m=0
ac(m-1,1)
dac n=0
ac(m-1,ac(m,n-1)) n rest

Clasificarea func iilor recursive


Func iile recursive se pot clasifica dupa modul n care descriu procesul de
calcul al valorilor func iilor pe care le definesc.
1. Recursia liniar define te recursiv func ia f(x) n termeni de alte func ii:
g(x),h(x),i(x)si (u,v) astfel:
f(x)=

if p(x) then g(x)


else (f(h(x)),i(x))
endif

O form particular este itera ia simpl :


if p(x) then g(x)
f(x)=
else f(h(x))
endif
2. Recursia neliniar de tip cascad este de forma :

if p(x) then g(x)


f(x)=
else (f(h(x)),f(i(x)))
endif
3. Recursia liniar de tip mpachetat :
if p(x) then g(x)
f(x)= else f(..f(f(..)))
endif
4.Defin ii recursive pentru sisteme de func ii:
f(x)=[defini ie recursiv n care figureaz f(x) i g(x)]
g(x)=[defini ie recursiv n care figureaz f(x) i g(x)]
Exemple:
1. Func ia factorial este de tip itera ie simpl :
if n=0 v 1 then 1
fact(n)= else n . fact(n-1)
endif
2. Func ia lui Fibonacci este recursie neliniar de tip cascad :
if(n=0) v (n=1)then 1
else fib(n-1)+fib(n-2)
endif
3. Func ia Manna Pnuelli este recursie liniar de tip mpachetat :
fib(n)=

if x > 12 then x - 1
else f (f ( x+2 ))
endif
4. Func ia lui Ackermann corespunde formei generale a tipului mpachetat :
f(x)=

if m=0 then n+1


else if n=0 then ac( n-1, 1)
ac(m,n)=
else ac (m-1, ac( m, n-1))
endif
endif
5. Func ia care calculeaz c.m.m.d.c a doua numere :
6

cmmdc : NxN N este de tipul sistemelor de functii definite recursiv :


cmmdc (a, b)=

mod (a, b)=

if b=0 then a
else cmmdc (b, mod ( a, b ))
endif
if a<b then a
else mod (a-b, b)
endif

unde mod : NxN N , (a,b) mod (a, b) este restul mp r irii lui a la b.
Exemple scrise n limbajul C :
1. Func ia factorial : fact : N N
1 dac n=0
fact(n)=
n x fact(n-1) dac n >= 1
# include < stdio.h >
# include < conio.h >
int fact ( int ) ;
void main( )
{
int n ;
clrscr ( ) ;
printf ( \ n n = ) ; scanf ( % d , & n ) ;
printf ( \ n % d ! = % d , n, fact ( n )) ;
getch ( ) ;
}
int fact(int a)
{
if ( a > = 1) return(a * fact ( a - 1) ;
else return 1;
}
sau folosind operatorul conditional
int fact ( int a )
{
return ( a >= 1 ) ? a* fact ( a 1 ) : 1 ;
7

}
Efectul unui apel de forma fact(5) const n declan area unui lan de apeluri ale
func iei factorial pentru 4,3,2,1,0
fact(5)
5 fact(4)
2 fact(1)
1 fact(0)
1
Apelul lui fact ( 5 ) declan eaz un lan de apeluri ale lui f pentru 4, 3, 2, 1, dup
care urmeaz revenirea din apeluri i evaluarea lui fact pentru 1,2,3,4,5.
Starea stivei in timpul execu iei succesive a autoapel rii :

4
Stiva vida

5
apel fact(5)

2
3

1
2
3

5
5
5
5
apel fact(4) apel fact(3) apel fact(2) fact( 1)

Pentru fiecare din aceste apeluri, n stiv se vor depune parametrii actuali:
5,4,3,2,1. St rile stivei dup ie irea din autoapel sunt urmatoarele:

1
2
3
4
5
fact(1)=1

2
3
3
4
4
4
5
5
5
5
Stiva vida
fact(2)=1.2 fact(3)=1.2.3 fact(4)=1.2.3.4 fact(5)=1.2.3.4.5
8

Rezolvarea fiec rui autoapel nseamn deplasarea pe un nivel inferior.


2. Func ia lui Fibonaci :
fib : N N,
1 pentru n=0 sau n=1
fib(n)=
fib(n-1)+fib(n-2) pentru n > = 2

fib(4)
fib(3)
fib(2)
fib(1)

fib(0)

fib(2)
fib(1)

fib(1)

fib(0)
1

1
int fib(int n)
{
if ( n == 0 || n == 1) return 1 ;
else return fib ( n-1 ) + fib( n- 2 ) ;
}

3. Func ia lui Ackermann :


ac ( m , n ) =

ac : N x N

n+1 dac m=0


ac ( m-1 , 1 ) dac n=0
ac ( m-1,ac ( m,n-1)) dac m > 0 , n >0

int ac ( int m , int n )


{
if ( m == 0) return n+1 ;
else if ( n == 0) return ac ( m-1, 1 ) ;
else return ( ac ( m-1 , ac ( m , n-1 ))) ;
}
m=2,n=1

ac(2,1)
ac(1,ac(2,0))
ac(1,3)

ac(0,ac(1,2))
ac(0,4)
5

ac(1,1)
ac(0,ac(1,1))
ac(0,3)
4

ac(0,ac(1,0))
ac(0,ac(1,0))
ac(0,2)

10

ac(0,2)
ac(0,1)

ac(0,1)
2

# include < stdio.h >


# include < conio.h >
int a ( int m, int n ) ;
void main ( )
{
int m, n ;
clrscr ( ) ;
printf ( \ n m = ) ; scanf ( % d , & m ) ;
printf ( \ n n = ) ; scanf ( % d , & n ) ;
printf ( \ n a ( % d, % d ) = % d , m, n, a ( m, n )) ;
getche ( ) ;
}
int a ( int m, int n )
{
if ( m == 0 ) return n + 1 ;
else if ( n == 0 ) return a ( m 1, 1 );
else return a ( m 1, a ( m, n 1 ));
}

11

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