Sunteți pe pagina 1din 10

Borland C++

Programarea procedurala

Programarea procedurala
1. Definirea si apelarea functiilor
Inca de la primele limbaje de programare de nivel inalt s-a utilizat programarea
procedurala. Aceasta a aparut si s-a dezvoltat din necesitatea de a folosi intr-un program,
aceeasi secventa de instructiuni de mai multe ori. Pentru a evita scrierea repetata a acestor
instructiuni, ele sunt organizate ca o parte distincta a programului, si se executa un salt la
aceasta zona ori de cate ori este necesar. Acest salt este un salt cu revenire la instructiunea ce
urmeaza dupa cea care a comandat saltul. Secventa de instructiuni organizata in acest fel are
diferite denumiri in limbajele de programare: subprogram, subrutina, procedura etc. Pentru
inceput o vom numi subprogram.
Uneori subprogramul trebuie sa execute aceleasi operatii de prelucrare, dar cu date
diferite. In acest caz, subprogramul trebuie realizat la modul general, facandu-se abstractie de
datele respective. Spre exemplu, pentru a evalua expresia:
4**10 – 3**20
putem crea un subprogram de ridicare la putere, care sa fie general, facandu-se abstractie de
valorile concrete ale bazei si exponentului. Pentru a realiza aceasta generalizare se va
considera ca atat baza cat si exponentul sunt variabile, iar valorile lor se vor precizeaza la
fiecare apel al subprogramului respectiv.
Variabilele folosite pentru implementarea unui subprogram general si a caror valori sunt
concretizate la fiecare apel se numesc parametri formali (fictivi sau argumente).
Valorile transmise la apel parametrilor formali se numesc parametri efectivi (actuali sau
reali).
Programarea procedurala are la baza utilizarea subprogramelor, iar acestea la randul
lor realizeaza o abstractizare prin parametri.
In toate limbajele de programare subprogramele sunt considerate a fi de doua categorii:
a. Subprograme care definesc o valoare de revenire, denumite de obicei functii.
Valoarea de revenire se mai numeste si valoare de intoarcere sau valoarea returnata
a functiei.;
b. Subprograme care nu definesc o valoare de revenire, care in anumite limbaje de
programare se numesc subrutine sau proceduri.
Limbajul C (C++) permite utilizarea numai a suprogramelor de tip functie, care pot
returna sau nu o valoare la revenirea in programul apelant. In plus, functiile limbajului C (C++)
pot fi folosite atat independent (apelate ca procedurile in celelalte limbaje) cat si intr-o expresie
ca operand (utilizand-se astfel valoarea returnata).
1.1. Definirea functiilor
Intr-un program functia are o singura definitie, dar ea poate fi apelata ori de cate ori este
necesar in respectivul program.
Definitia unei functii are urmatorul format:
tip nume(lista_parametri_formali)
{
[declaratii]
instructiuni
}
Primul rand din formatul de mai sus reprezinta antetul functiei, iar partea inclusa intre
acolade, impreuna cu acoladele, formeaza corpul functiei.
Daca functia returneaza o valoare, atunci tip desemneaza tipul rezultatului prin
intermediul unui cuvant cheie (cum ar fi: int, char, float etc.) sau al unui nume de tip definit de

1
Borland C++
Programarea procedurala
utilizator. Daca functia nu returneaza o valoare, atunci ca tip se va folosi cuvantul cheie void,
care semnifica lipsa unei valori returnate la revenire.
O functie poate avea mai multi parametri sau nici unul. Daca lista_ parametri_formali
este vida, atunci functia nu are parametrii formali. In acest caz antetul functiei se reduce la:
tip nume()
Lipsa parametrilor formali poate fi mentionata explicit folosind cuvantul cheie void. Deci antetul
de mai sus poate fi scris si sub forma:
tip nume(void)
In cazul in care functia are parametrii, adica in antet este prezenta lista cu parametrii
formali, declaratiile parametrilor sunt separate prin virgule.
Constructia nume din antet reprezinta numele functiei si trebuie sa respecte conventiile
de denumire ale identificatorilor specifice limbajului C (C++).
Zona declaratii din corpul functiei se poate folosi pentru definirea variabilelor care se
utilizeaza numai in functia respectiva. Aceasta zona poate lipsi.
Zona instructiuni contine instructiunile care descriu operatiile de prelucrare pentru care
a fost realizata functia si formeaza corpul functiei.
1.2. Apelarea functiilor
Pentru a putea utiliza o functie intr-un program, ea trebuie apelata. Apelul de functie
trebuie sa fie precedat de definitia sau de prototipul ei. Prototipul unei functii contine informatii
asemanatoare cu cele din antetul ei:
 tipul valorii returnate;
 numele functiei;
 tipurile parametrilor formali.
Prototipul functiei poate avea acelasi format ca si antetul functiei, fiind urmat insa de
caracterul punct si virgula (;) sau poate avea un format prescurtat. Deci prototipul unei functii
poate fi de forma:
tip nume(lista_parametri_formali);
adica identic cu antetul functiei, sau
tip nume(lista_tipuri_parametri_formali);
o forma prescurtata, in care in lista_tipuri_parametri_formali sunt precizate doar tipurile
parametrilor formali.
Spre exemplu, daca intr-un program este definita o functie a carui antet este urmatorul
(vezi pag. Error: Reference source not found):
long double putere(long double x, int n)
prototipul functie poate fi:
long double putere(long double x, int n);
sau
long double putere(long, int);
Prototipul unei functii este obligatoriu atunci cand functia este definita in acelasi fisier cu
apelantul, dar dupa acesta (vezi exemplul de la pagina 4).
Limbajul C (C++) se livreaza cu o serie de functii ce au o utilizare frecventa in programe.
Ele sunt stocate intr-un fisier in format obiect, adica compilat si se adauga la fiecare program in
faza de editare. Aceste functii se numesc functii standard de biblioteca. Prototipurile lor sunt
pastrate in diferite fisiere de extensie .h (numite si fisiere header).
Prototipurile functiilor standard se includ in program inaintea apelurilor lor folosind
constructia #include, care are urmatorul format:
#include <specificator_fisier>
unde:
 specificator_fisier este format din numele fisierului cu prototipurile functiilor
standard necesare, urmat de caracterul punct (.) si de extensia h.

2
Borland C++
Programarea procedurala
Spre exemplu, pentru a executa intr-un program operatii de intrare/iesire se pot apela
functiile printf si scanf, al caror prototipuri se gasesc in fisierul stdio.h. Pentru a le apela
este necesar ca inaintea primei utilizari, in codul sursa trebuie sa apara urmatoarea linie:
#include <stdio.h>
Observatie: Pentru ca in program sa se includa un fisier sursa, in locul
parantezelor unghiulare se folosesc ghilimelele (“).
Spre exemplu, linia
#include “fis1.cpp”
indica includerea fisierului fis1.cpp aflat in directorul curent, iar linia
#include “C:\BC31\Programe\Citire.cpp”
specifica includerea fisierului Citire.cpp din subdirectorul Programe al directorului
BC31 din radacina discului C.
Apelul unei functii care nu returneaza o valoare, se realizeaza printr-o instructiune de
apel, care are urmatorul format:
nume(lista_parametri_efectivi);
unde:
 nume – este numele functiei cre se apeleaza;
 lista_parametri_efectivi – este fie vida, cand functia a fost declarata fara parametri
formali, fie una sau mai multe expresii separate prin virgula.
O functie care returneaza o valoare, poate fi apelata fie printr-o instructiune de apel, fie
ca operand al unei expresii. Daca functia este apelata printr-o instructiune de apel, valoarea
returnata de ea se pierde. Cand functia este apelata ca operand al unei expresii, valoarea
returnata de ea se utilizeaza la evaluarea expresiei respective.
Spre exemplu, urmatoarea instructiune de atribuire
c = getch();
atribuie variabilei c valoarea codului ASCII al caracterului citit de la tastatura, in timp ce in cazul
apelului din urmatoarea linie
getch();
valoarea codului ASCII al caracterului citit de la tastatura nu se foloseste. Aceasta forma de
apel a functiei getch() se foloseste pentru a bloca executia programului pana la actionarea
unei taste oarecare, astfel incat utilizatorul sa poata citi rezultatele afisate pe ecran.
La apelul unei functii, valorile parametrilor efectivi se atribuie parametrilor formali
corespunzatori, apoi executia continua cu prima instructiune din corpul functiei apelate. In cazul
in care tipul unui parametru efectiv difera de tipul parametrului formal care-i corespunde, in
limbajul C se converteste automat valoarea parametrului efectiv spre tipul parametrului formal
respectiv. In limbajul C++ se foloseste o regula mai complexa pentru apelul functiilor si de
aceea se recomanda utilizarea conversiei explicite, folosind operatorul (tip), adica utilizand asa
numitele expresii cast.
De exemplu, daca functia f are un parametru formal de tip double si n este o variabila
de tip int, atunci in locul apelului:
f(n);
se recomanda utilizarea unui apel cu conversie explicita a lui n la tipul double:
f((double) n);
Din cele prezentate pana in prezent, rezulta ca intre lista parametrilor efectivi ai apelului
de functie si lista parametrilor formali ai definitiei functiei trebuie sa existe o concordanta din
punct de vedere al ordinii si al tipului parametrilor. De cele mai multe ori aceasta concordanta
se extinde si la numarul parametrilor.
Revenirea dintr-o functie se poate realiza in unul din urmatoarele moduri:
 Dupa executia ultimei instructiuni din corpul functiei (s-a ajuns la acolada inchisa care
termina corpul functiei).
 La intalnirea instructiunii return.

3
Borland C++
Programarea procedurala
Instructiunea return poate sa apara oriunde in corpul functiei si are urmatoarele
formate:
return;
return expresie;
Primul format se foloseste numai in corpul unei functii care nu returneaza o valoare,
pentru a forta terminarea executiei functiei si revenirea in programul apelant.
Cel de-al doilea format se foloseste in corpul unei functii care returneaza o valoarea la
revenirea din ea. Valoarea furnizata de expresie este chiar valoarea returnata de functie. Daca
tipul acestei expresii difera de tipul care precede numele din antetul functiei, valoarea expresiei
se converteste automat spre tipul din antet, inainte de a se reveni din functie.
Spre exemplu, sa consideram urmatoarea functie, numita factorial, care primeste ca
parametru un intreg din intervalul [0, 170] si returneaza factorialul valorii receptionate.
double factorial(int n)
{
double f;
int i;
// se verifica daca n este in intervalul [0, 170]
if (n < 0 || n > 170) return –1.0;
for (i = 2, f = 1.0; i <= n; i++) // Calculeaza n!
f *= i;
return f
}
Functia factorial poate fi editata impreuna cu programul apelant la sfarsitul sau la
inceputul acestuia. Daca functia este plasata la sfarsitul programului, atunci inainte de primul
apel trebuie sa apara prototipul functie, asa cum se arata in exemplu urmator:
#include <stdio.h>
#include <conio.h>
double factorial(int); // Proptotipul functiei factorial
void main()
{
int m;
double rezult;
printf("m = "); scanf("%d",&m);
rezult = factorial(m);
if (rezult < 0)
printf("Numarul introdus este < 0 sau > 170");
else
printf("m= %d\tm! = %g\n", m, rezult);
getch();
}
double factorial (int n)
{
double f;
int i;
if ((n < 0) || (n > 170)) return -1.0;
for (i = 2, f = 1.0; i <= n; i++)
f *= i;
return f;
}
In cazul in care functia este editata intr-un fisier separat, numit fact.cpp din subdirectorul
Programe al directorului BC31 din radacina discului C, atunci in programul apelant trebuie
inclusa o directiva #include, care sa specifice numele fisierului ce contine functia si locul unde
se gaseste acest fisier, ca in urmatorul exemplu:
4
Borland C++
Programarea procedurala
#include <stdio.h>
#include <conio.h>
#include “C:\BC31\Programe\fact.cpp”
void main()
{
int m;
double rezult;
printf("m = "); scanf("%d",&m);
rezult = factorial(m);
if (rezult < 0)
printf("Numarul introdus este < 0 sau > 170");
else
printf("m= %d\tm! = %g\n", m, rezult);
getch();
}

2. Transferul parametrilor
In limbajul C, la apelul unei functii, fiecarui parametru formal i se atribuie valoarea
parametrului efectiv care-i corespunde. Datorita faptului ca la apelare se transfera valori, acest
mod de transmitere se numeste apel prin valoare.
In unele limbaje de programare, printre care si limbajul C++, exista posibilitatea ca in
locul valorilor paramterilor efectivi se se transmita adresele acestor valori. Acest mod de
transmitere se numeste apel prin referinta.
Intre cele doua moduri de apelare exista o mare diferenta si anume:
 In cazul apelului prin valoare, functia apelata nu poate modifica parametri efectivi din
functia apelanta. Adica, functia apelata nu are acces la zonele de memorie alocate
parametrilor efectivi, ci doar primeste o copie a acestor valori.
 In cazul apelului prin referinta, functia apelata poate modifica valorile parametrilor
efectivi primiti, deoarece ea primeste adresele zonelor de memorie alocate parametrilor
efectivi si nu valoarea acestora.
In exemplele prezentate anterior, apelul functiilor s-a realizat prin valoare.
Pentru a putea intelege diferenta dintre apelul prin valoare si cel prin referinta vom
considera urmatoarea functie:
void perm(int x, int y)
{
int aux:
aux = x;
x = y;
y = aux;
}
care asigura interschimbarea valorilor parametrilor formali x si y. Considerand declaratia:
int a,b;
atunci apelul:
perm(a, b);
nu va afecta parametri efectivi, deoarece asa cum este definita functia, apelul se face prin
valoare. Pentru ca interschimbarea valorilor sa afecteze si parametri efectivi este necesar sa se
transmita adresele zonelor de memorie in care se gasesc valorile respective. Adresele acestor
zone se poate transmite prin intermediul pointerilor si deci trebuie sa fie definita astfel:
void pperm(int *x, int *y)
{
int aux:
aux = *x;

5
Borland C++
Programarea procedurala
*x = *y;
*y = aux;
}
in care *x si *y sunt doua variabile de tip pointer catre tipul de date int. In acest caz, functia
pperm se va apela astfel:
int a, b;
...
pperm(&a, &b);
...
Prin apelul pperm(&a, &b); parametrilor formali de tip pointer x si y li se atribuie
adresele parametrilor efectivi a si b, ceea ce inseamna ca x si y acceseza aceleasi zone de
memorie ca si a si b. Functia pperm nu permuta valorile pointerilor x si y ci valorile intregilor
spre care refera cei doi pointeri, adica chiar valorile variabilelor a si b.
In limbajul C++, spre deosebire de limbajul C, se poate defini functia de permutare ca o
functie cu parametri formali de tip referinta, astfel:
void rperm(int& x, int& y)
{
int aux:
aux = x;
x = y;
y = aux;
}
In acest situatie, functia rperm se va apela astfel:
int a, b;
...…
rperm(a, b);
...
In acest caz x si y sunt sinonime cu variabilele a si b. Aceasta inseamna x si y vor
accesa aceleasi date din memorie ca si a si b. Din aceasta cauza permutarea valorilor referite
de x si y inseamna permutarea valorilor referite de a si b.
Comparand functiile perm si rperm se poate observa ca ele se apeleaza la fel iar sigura
diferenta dintre ele consta in modul de declarare al parametrilor formali. In cazul functiei perm
parametri formali sunt date de tip int, iar in cazul functiei rperm acestia sunt referinte la date de
tip int.
Daca transmitem un parametru care este un tablou, atunci transmiterea prin valoare se
comporta identic cu transmiterea prin referinta, deci functia va putea sa modifice oricare dintre
componentele tabloului. Acest lucru se produce datorita faptului ca numele de tablou reprezinta
adresa zonei in care sunt stocate componentele sale. Exemplu urmator foloseste trei functii:
 CitVect - citeste numarul de componente ale vectorului si valorile componentelor;
 SortAsc – ordoneaza crescator elementele vectorului;
 SortDesc – ordoneaza descrescator elementele tabloului.
#include <stdio.h>
#include <conio.h>
typedef double DVector[100]; // Declara DVector ca tip utilizator
DVector vector; // Declara o variabila a tipului utilizator
int nr; // Numarul de componente ale vectorului
void CitVect(DVector);
void SortAsc(DVector);
void SortDesc(DVector);
void main()
{
int i;
char sort;
CitVect(vector); // Citeste dimensiunea si componentele vectorului
6
Borland C++
Programarea procedurala
printf("Sortarea va fi ascendenta sau descendenta (A/D)? ");
do
{
sort = getch();
if(sort >= 'a' && sort <= 'z') sort -=32;
if(sort == 'A' || sort == 'D') break;
} while(1);
clrscr(); printf("Sirul initial este:\n");
for(i=0; i<nr; i++)
printf("%g ", vector[i]); printf("\n");
if(sort == 'A')
SortAsc(vector); // Sortare ascendenta
else
SortDesc(vector); // Sortare descendenta
printf("Sirul sortat este:\n");
for(i=0; i<nr; i++)
printf("%g ", vector[i]); printf("\n");
}
void citvect(Dvector vec) // Citeste dimensiunea si componentele vectorului
{
int i, x, y;
printf("Numarul de componente [2, 100]: "); x = wherex(); y = wherey();
do
{
scanf("%d", &nr);
if(nr >=2 && nr <=100) break;
gotoxy(x, y); clreol();
} while(1);
for(i=0; i< nr; i++)
{
printf("vector[%d]= ", i+1); scanf("%lf", &vec[i]);
}
}
void SortDesc(DVector vec) // Sortarea descendenta a vectorului
{
int i, flag = 1; double aux;
while (flag)
{
flag = 0;
for (i = 0; i < nr -1; i++)
if (vec[i] < vec[i+1])
{
flag = 1; aux = vec[i];
vec[i] = vec[i + 1]; vec[i + 1] = aux;
}
}
}
void SortAsc(DVector vec) // Sortarea ascendenta a vectorului
{
int i, j; double aux;
for(i=0; i<nr-1; i++)
for(j=i+1; j<nr; j++)
if (vec[i] > vec[j])
{
aux = vec[i]; vec[i] = vec[j];
vec[j] = aux;
}
}

7
Borland C++
Programarea procedurala
Se poate constata ca in program a fost definit un tip utilizator DVector, ca fiind un tablou
unidimensional de 100 elemente de tip double. Am ales aceasta solutie pentru a simplifica
scrierea prototipurilor si antetelor functiilor. Daca nu declaram tipul utilizator DVector, atunci ar fi
trebuit sa folosesc o declaratie de forma:
double vector[100];
pentru a declara un tablou cu 100 elemente de tip double. In aceasta situatie prototipurile
functiilor ar fi trebuit sa fie urmatoarele:
void CitVect(double vec[]);
void SortAsc(double vec[]);
void SortDesc(double vec[]);
iar antetele de functie ar fi fost urmatoarele:
void CitVect(double vec[])
void SortAsc(double vec[])
void SortDesc(double vec[])

Concluzii:
 Tablourile sunt transmise prin referinta in mod prestabilit; pentru ca un tablou sa se
pransmita prin valoare, el trebuie sa fie inclus intr-o structura, care va fi transmisa
functiei prin valoare.
 In general, parametrii efectivi trebuie sa corespunda din punct de vedere al numarului,
ordinii si tipului cu parametrii formali.
 Functia poate returna cel mult o valoare. Pentru a obtine mai multe rezultate la
revenirea dintr-o functie, se vor folosi fie tablourile sau structurile pentru a grupa
rezultatele de iesire, fie variabile globale, fie transferul prin referinta.

3. Clase de functii
In limbajul C++, spre deosebire de alte limbaje, exista un numar imens de functii de
biblioteca, care sunt grupate dupa domeniul prelucrarilor efectuate astfel: prelucrarea fisierelor,
manipularea de siruri, conversii, lucru cu zone de memorie, calcule matematice, alocare
dinamica de memorie, grafica etc.: Prototipurile acestor functii se gasesc in fisiere de tip header
(extensie .h). In tabelul urmator sunt prezentate pe scurt fisierele de tip header din C++.
Nume fisier Destinatie
header
alloc.h Declara functiile de manipulare a memoriei dinamice(alocare, dealocare etc.).
assert.h Defineste macrocomanda assert de depanare.
bcd.h Declara clasa bcd din C++ si suprascrie operatorii bcd1 si functiile matematice bcd.
bios.h Declara diferite functii folosite la apelarea rutinelor IBM-PC ROM BIOS.
complex.h Declara functiile matematice complexe din C++.
conio.h Declara diferite functii folosite la apelarea rutinelor I/O ale consolei DOS.
ctype.h Contine informatii folosite de catre macrocomenzile de clasificare caractere si de
conversie caractere.
dir.h Contine structuri, macrocomenzi si functii pentru lucru cu directoare si cai.
direct.h Defineste structuri, macrocomenzi si functii pentru lucru cu directoare si cai.
dirent.h Declara functii si structuri pentru operatii cu directoare POSIX.
dos.h Defineste diferite constante si declaratiile necesare pentru apeluri specifice DOS si
8086.
errno.h Defineste constantele mnemonice pentru codurile de eroare.
fcntl.h Defineste constantele simbolice folosite la conectarea cu rutina de biblioteca
deschisa.
float.h Contine parametrii pentru rutinele in virgula mobila.
fstream.h Declara clasele stream din C++ ce suporta fisierele de intrare si iesire.
generic.h Contine macrocomenzi pentru declaratii de clase generice.
1
bcd - numar zecimal codificat binar
8
Borland C++
Programarea procedurala
io.h Contine structurile si declaratiile pentru rutinele de intrare/iesire de nivel inferior.
iomanip.h Declara manipulatorii de stream-uri de I/O din C++ si contine macrocomenzile pentru
crearea manipulatorilor parametrizati.
iostream.h Declara rutinele de baza ale stream-urilor (I/O) din C++ (version 2.0).
limits.h Contine parametrii mediului, informatiile despre limitarile din timpul compilarii..
locale.h Declara functiile care asigura informatiile specifice tarii si limbii.
math.h Declara prototipurile functiilor matematice, defineste macrocomanda HUGE_VAL si
declara structura utilizata de matherr.
mem.h Declara functiile de manipulare a memoriei (multe dintre ele sunt definite si in
string.h.)
memory.h Functii de manipularea memoriei.
new.h Accesul la operatorul new si newhandler.
process.h Contine structurile si declaratiile pentru functiile spawn si exec.
search.h Declara functiile de sortare si cautare.
setjmp.h Defineste un tip folosit de longjmp si setjmp.
share.h Defineste parametrii utilizati in functiile care folosesc fisiere partajate.
signal.h Defineste constante si declaratii pentru signal si raise.
stdarg.h Defineste macrocomenzile folosite pentru citirea listei de argumente din functiile
declarate pentru a accepta un numar variabil de argumente.
stddef.h Defineste cateva tipuri de date si macrocomenzi generale.
stdio.h Defineste tipurile si macrocomenzile necesare Standard I/O Package definit in
Kernighan si Ritchie si extins sub sistemul UNIX System V. Defineste stream-urile
standard de I/O prestabilite: stdin, stdout, stdprn si stderr; declara tutinele de I/O la
nivel de stream.
stdiostr.h Declara clasele stream C++ (version 2.0) pentru a fi folosite cu structurile FILE
pentru stdio.
stdlib.h Declara cateva rutine folosite in mod normal: rutine de conversie, rutine de
cautare/sortare si alte operatii.
string.h Declara cateva rutine de manipulare siruri de caractere.
strstrea.h Declara clasele stream C++ pentru folosirea cu tablourile de byte din memorie.
sys\locking.h Definitii pentru parametrul mode al functiilor de blocare.
sys\stat.h Defineste constantele simbolice folosite pentru deschiderea si crearea fisierelor.
sys\timeb.h Declara functia ftime si structura timeb ce este returnata de ftime.
sys\types.h Declara tipul time_t folosit de functiile de timp.
time.h Defineste o structura completata de rutinele de conversie ale timpului si un tip folosit
de catre alte rutine de timp; de asemenea asigura prototipurile pentru aceste rutine.
utime.h Declara functiile utime si structura utimbuf.
values.h Defineste constante importante, inclusiv cele dependente de masina pentru
compatibilitatea cu UNIX System V.
varargs.h Defineste macrocomenzile de stil vechi pentru procesarea listelor de argumente
variabile. Se foloseste stdarg.h

4. Functii recursive
Una din caracteristicile de baza ale algoritmilor este recursivitatea. Recursivitatea
defineste modalitatea de a determina valoarea unei variabile pe baza valorilor ei anterioare si
eventual a altor valori cunoscute.
O parte din limbajele de programare asigura implementarea algoritmilor recursivi cu
ajutorul structurilor repetitive, utilizand tablouri pentru memorarea rezultatelor obtinute in fiecare
iteratie si variabile temporare de lucru.
Limbajul de programare C++, ca de altfel si alte limbaje de programare, permite
descrierea algoritmilor recursivi cu ajutorul functiilor care se apeleaza pe ele insele, fie direct fie
prin intermediul altor functii.

9
Borland C++
Programarea procedurala
Pentru exemplificarea recursivitatii vom considera o problema simpla, si anume
determinarea sumei elementelor unui vector. Pentru vectorul A = (a0, a1, …, an), suma
elementelor se poate descrie recursiv astfel:
0, daca n = 0
Sn =
Sn-1 + an, daca n>0
Functia care se va realiza aceasta operatie are urmatoarea forma:
double sum(double v[], int n)
{
return n ? v[n-1] + sum(v, n – 1):0;
}
La utilizarea functiilor recursive se va acorda o atentie deosebita controlului finitudinii
algoritmului si numarului de apeluri, deoarece apar restrictii datorate dimensiunii stivei. Pentru
aceasta in componenta functiei recursive distingem intodeauna conditia de terminare a
procesului recursiv (in cazul exemplului anterior, n = 0) si modalitatea prin care se modifica
valoarea parametrilor efectivi la apeluri succesive (in cazul exemplului de mai sus, n –1). Practic
prin apelul recursiv, functia este impartita in doua: o portiune se executa in mod repetat cu
incarcarea in stiva a contextului si a adresei de revenire si o portiune a carei executie repetata
incepe numai dupa ce s-a atins nivelul maxim de profunzime a recursivitatii (impus prin conditia
de terminare).
Un exemplu sugestiv in acest sens il constituie functia care realizeaza afisarea unui
numar a, din baza 10 intr-o baza b [2 , 10]. Pentru afisare, trebuie sa se obtina resturile
impartirilor succesive la baza in ordinea inversa si deci afisarea cifrei se va face dupa apelul
recursiv. Functia de conversie a unui numar din baza 10 intr-o baza oarecare mai mica decat 10
este:
void afis(int a, unsigned b)
{
if (a < b)
printf(“%d”, a);
else
{
afis(a/b, b);
printf(“%d”, a % b);
}
}

Implicatiile claselor de memorare asociate variabilelor locale din functie sunt importante;
astfel, variabilele automatice exista in cate un set pentru fiecare apel recursiv (stiva se va
incarca cu aceste variabile), in timp ce variabilele statice si externe exista intr-un singur
exemplar pentru toate apelurile. Modificarile dintr-un apel nu se regasesc la revenire in cazul
variabilelor automatice, in timp ce variabilele statice reflecta efectul cumulat al tuturor
modificarilor anterioare. Deci conditia pentru controlul recursivitatii se poate baza pe
modificarea argumentelor de apel, pe variabile statice al caror continut se pastreaza intre doua
apeluri succesive sau pe variabile globale.

10

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