Documente Academic
Documente Profesional
Documente Cultură
Cuprins
Apeluri de funcții
Recursivitate
Recursivitate vs iterație
Bibliografie selectivă
Apeluri de funcții
Ce face o funcție?
◦ Calculează o valoare
int suma(int a, int b) {
return a+b; }
◦ Produce un efect (ex. afișează un mesaj)
void eroare(int cod) {// tipul void: nu returnează nimic
printf("Eroare cu codul %d\n", cod); }
◦ Efect + valoare (scrie și calculează)
int sqr(int x){
printf("Calculam patratul lui %d\n", x);
return x * x; }
Apeluri de funcții
Să ne amintim! #include <stdio.h>
int f(int x) //definirea funcției f
Pentru ca o funcție să producă un efect
{
sau să calculeze o valoare, ea trebuie
să fie apelată. return x*x;
}
Exemplu de apel: int main()
{
int z, y;
printf("Dati valoarea numarului : ");
scanf("%d", &z);
y = f(z); //apelul funcției f
printf("%d la patrat = %d\n",z,y); //afisarea rezultatului
return 0;
}
Apeluri de funcții
Declararea unei funcții:
int suma(int a, int b); //tip returnat, nume funcție, tip și nume parametri
Atenție:
Nu apelăm funcții cu variabile neinițializate!
Apeluri de funcții
Să ne amintim:
Orice program are o funcție main
int main(void)
{ // --> AICI <-- scriem ce sa faca programul
return 0;
}
Execuția programului începe cu funcția main.
De aici apelăm celelalte funcții (scrise înainte).
Apeluri de funcții
Observație: Codul se scrie doar în funcții
tip functie1 ( parametri )
{ // codul functiei 1 }
// NU scriem cod între funcții
tip functie2 ( parametri )
{ // codul functiei 2 }
// NU scriem cod aici
int main(void)
{ // apelează funcție1, funcție2
return 0;
// NU scriem cod după return }
Apeluri de funcții
Exemplul alăturat calculează X6=(x*x2)2 #include <stdio.h>
int sqr(int x)
Rezultatul execuției programului este: {
printf("Patratul lui %d e %d\n", x, x*x);
return x * x;
}
int main(void)
{
printf("2 la a 6-a e %d\n", sqr(2 * sqr(2)));
return 0;
}
Apeluri de funcții
Transmiterea parametrilor la funcții:
◦ se evaluează (calculează valoarea) pentru toate argumentele funcției
◦ valorile se atribuie la parametrii formali (numele din definiția funcției) apoi se începe execuția
funcției cu aceste valori
◦ ca orice program în C, programul anterior începe cu execuția funcției main (în cazul anterior
cu apelul la printf );
◦ funcția printf are nevoie de valoarea argumentelor sale.
◦ valoarea primului argument se știe (o constantă șir) pentru al doilea argument trebuie apelat:
sqr(2 * sqr(2)) la rândul lui, sqr exterior are nevoie de valoarea argumentului 2 * sqr(2),
pentru care trebuie apelat întâi sqr(2) ⇒ ordinea apelurilor: sqr(2), apoi sqr(8), apoi printf din
main
Atenție: Funcția NU începe execuția fără să aibă toate argumentele calculate!
Apeluri de funcții
Funcțiile pot avea sau nu parametri și rezultat
int f(int x)
{
return (x + 2) % 26;
}
Folosim rezultatul:
◦ îl atribuim: int y = f(3);
◦ îl tipărim: printf("%d\n", f(25));
◦ într-o expresie: a=b+f(83); (inclusiv în apelul la altă funcție)
Apeluri de funcții void afisare_n(int n)
{ //functie fara rezultat
Putem scrie funcții fără rezultat ⇒ tipul returnat e void int i;
for (i=0;i<n;i++)
Folosim funcția într-o instrucțiune: printf(“%d “,i);
afișare_n(16); }
Funcții fără parametric - definim cu void în locul listei parametrilor int citeste_n(void)
{ //functie fara parametri
Apelăm întotdeauna cu paranteze: int n;
int nr = citeste_n(); scanf(“%d”, &n);
afisare_n(5); return n;
}
Recursivitate
În matematică am întâlnit șiruri recurente ca de exemplu:
◦ progresie aritmetică:
𝑥0 = 𝑏
𝑥𝑛 = 𝑥𝑛−1 + 𝑟, 𝑝𝑒𝑛𝑡𝑟𝑢 𝑛 > 0
Exemplu: 1,4,7,10,13,... (b = 1, r = 3)
◦ progresie geometrică:
𝑥0 = 𝑏
𝑥𝑛 = 𝑥𝑛−1 ∗ 𝑟, 𝑝𝑒𝑛𝑡𝑟𝑢 𝑛 > 0
Exemplu: 3,6,12,24,48,... (b = 3, r = 2)
Nu se calculează xn direct, ci din aproape în aproape, folosind xn−1.
O noțiune este recursivă dacă este folosită în propria sa definiție.
Recursivitate
Recursivitatea este importantă în informatică pentru că reduce o problemă la un
caz mai simplu al aceleiași probleme
(un singur element)
obiecte: un șir este
un element urmat de un șir
Recursivitate Stiva
Segmentul de cod
Spațiu pentru valoarea
Directia de creștere de retur
Variabile locale
Recursivitate Funcția apelantă
Parametru_n
…
Modul de funcționare al unei stive este LIFO (last Parametru_2
in first out). Parametru_1
Figura alăturată este o reprezentare a unei stive în Adresa de retur
momentul apelului unei funcții.
Pointer fereastra de
Întotdeauna trebuie avut grijă în lucrul cu funcţii memorie anterioara
recursive deoarece, la fiecare apel recursiv, Spațiu pentru valoarea
Funcția apelată de retur
contextul este salvat pe stivă pentru a putea fi
refăcut la revenirea din recursivitate. Variabile locale
În funcţie de numărul apelurilor recursive şi de
dimensiunea contextului (variabile, descriptori de
fişier, etc.) stiva se poate umple foarte rapid, Vârful stivei
generând o eroare de tip ”stack overflow”. Varful stivei
- -
Retur
Apel 5;3 5;3
Adresa corespunzatoare Adresa corespunzatoare
instructiunii de pe linia 6 instructiunii de pe linia 6
#include <stdio.h> - -
1
double pow(double x, int n) 2 5;2 5;2
{ 3 Adresa corespunzatoare Adresa corespunzatoare
if (n == 0) 4 instructiunii de pe linia 6 instructiunii de pe linia 6
return 1; 5
return x*pow(x, n - 1); 6 - -
} 7
5;1 5;1
Adresa corespunzatoare Adresa corespunzatoare
instructiunii de pe linia 6 instructiunii de pe linia 6
Exemplu apel pow(5,3)
- 1
5;0 5;0
Adresa corespunzatoare Adresa corespunzatoare
instructiunii de pe linia 6 instructiunii de pe linia 6
- -
Retur
Apel 5;3 5;3
Adresa corespunzatoare Adresa corespunzatoare
instructiunii de pe linia 6 instructiunii de pe linia 6
#include <stdio.h> - -
1
double pow(double x, int n) 2 5;2 5;2
{ 3 Adresa corespunzatoare Adresa corespunzatoare
if (n == 0) 4 instructiunii de pe linia 6 instructiunii de pe linia 6
return 1; 5
return x*pow(x, n - 1); 6 - 5
} 7
5;1 5;1
Adresa corespunzatoare Adresa corespunzatoare
instructiunii de pe linia 6 instructiunii de pe linia 6
Exemplu apel pow(5,3)
-
5;0
Adresa corespunzatoare
instructiunii de pe linia 6
- -
Retur
Apel 5;3 5;3
Adresa corespunzatoare Adresa corespunzatoare
instructiunii de pe linia 6 instructiunii de pe linia 6
#include <stdio.h> - 25
1
double pow(double x, int n) 2 5;2 5;2
{ 3 Adresa corespunzatoare Adresa corespunzatoare
if (n == 0) 4 instructiunii de pe linia 6 instructiunii de pe linia 6
return 1; 5
return x*pow(x, n - 1); 6 -
} 7
5;1
Adresa corespunzatoare
instructiunii de pe linia 6
Exemplu apel pow(5,3)
-
5;0
Adresa corespunzatoare
instructiunii de pe linia 6
- 125
Retur
Apel 5;3 5;3
Adresa corespunzatoare Adresa corespunzatoare
instructiunii de pe linia 6 instructiunii de pe linia 6
#include <stdio.h> -
1
double pow(double x, int n) 2 5;2
{ 3 Adresa corespunzatoare
if (n == 0) 4 instructiunii de pe linia 6
return 1; 5
return x*pow(x, n - 1); 6 -
} 7
5;1
Adresa corespunzatoare
instructiunii de pe linia 6
Exemplu apel pow(5,3)
-
5;0
Adresa corespunzatoare
instructiunii de pe linia 6
Recursivitate #include <stdio.h>
long factorial(int n)
{
Alt exemplu de funcție recursivă:
if (n == 0)
factorial: return 1; //conditia de oprire
else
N->N return(n * factorial(n - 1));
}
1, 𝑛 = 0
n!= int main() {
𝑛 ∗ 𝑛 − 1 !, 𝑛 > 0 int n;
printf("Introduceti valoarea pentru n (>=0):");
scanf("%d", &n);
printf("n! = %ld\n", factorial(n));
return 0;
}
Recursivitate #include <stdio.h>
long Fib(int n){
if (n == 0)
Alt exemplu de funcție recursivă:
return 0;
fibonacci: if (n == 1)
return 1;
N->N else
0, 𝑛 = 0 return Fib(n - 1) + Fib(n - 2);
}
Fib(n)= 1, 𝑛 = 1
int main() {
𝐹𝑖𝑏 𝑛 − 1 + 𝐹𝑖𝑏(𝑛 − 2) int n;
printf("Introduceti valoarea pentru n (>=0):");
scanf("%d", &n);
Atenție: În acest exemplu avem două printf("Fibonacci(n) = %ld\n", Fib(n));
cazuri de bază, deoarece formula de return 0;
recurență folosește doi termeni. }
#include <stdio.h>
void citeste_recursiv(int nr)
{
if (nr <= 0) /*se citesc
Recursivitate doar numere naturale*/
return;
Cazuri de folosire a recursivității: else
◦ Implementarea unor funcții/noțiuni recursive {
printf("\nIntroduceti un
◦ Divizarea unei probleme în subprobleme de numar stric pozitiv (>0) sau
același tip (tehnica divide et impera). 0 pentru a termina
◦ Afișarea/prelucrarea unor elemente în ordine programul:");
inversă scanf("%d", &nr);
citeste_recursiv(nr);
Exemplu de prelucrare a elementelor în ordine }
inversă. if (nr>0)
Pentru prelucrarea elementelor în ordine inversă ne printf("%d ", nr);
folosim de stiva sistem. }
int main() {
Pentru a implementa funcția în variantă iterativă int n=1;
trebuie să ne folosim de structuri suplimentare citeste_recursiv(n);
(stivă/tablou). return 0;
}
Recursivitate vs. iterație
De multe ori, soluția unei probleme poate fi elaborată mult mai ușor, mai clar și mai simplu de
verificat, printr-un algoritm recursiv.
Dar, cel mai mare dezavantaj al recursivității este folosirea stivei, care se poate umple foarte rapid.
=> Atenție: Numeroase platforme de calcul (îndeosebi cele încorporate) nu suportă recursivitatea.
Alternativă:
Transformarea recursivității în iterații.
Orice program recursiv poate fi transformat în unul iterativ!
Recursivitate vs. iterație
RECURSIVITATE ITERAȚIE
Avantaje Avantaje
◦ Ușor de implementat – nu este necesară o ◦ Consum redus de memorie – necesar în
structură de date (se folosește stiva cazul dispozitivelor cu memorie puțină
implicită)
◦ Ieșirea din ciclu se poate face facil, folosind
◦ Cod lizibil și scurt
instrucțiunea break
Dezavantaje
◦ Consum mare (chiar excesiv) de memorie Dezavantaje
◦ Ieșirea din ciclu poate fi dificilă, dacă nu ◦ Cod lung
sunt bune condițiile ◦ Poate necesita structuri de date auxiliare
◦ Optimizarea memoriei presupune, în
general, folosirea de variabile globale
#include <stdio.h>
double pow(double x, int n) { //recursiva
Recursivitate vs. if (n == 0)
return 1;
iterație }
return x*pow(x, n - 1);
Pentru mai multe informații despre subiectele abordate în acest curs accesați:
http://staff.cs.upt.ro/~marius/curs/pc/old/notes2.pdf
Bibliografie selectivă
◦ Kernighan, B. W., & Ritchie, D. ”The C programming language - Second
edition”, 1988 Prentice Hall Software Series
◦ Minea, M., Limbaje de programare, materiale de curs
http://staff.cs.upt.ro/~marius/curs/lp/index.html
◦ Holotescu, C., Limbaje de programare, materiale de curs
http://labs.cs.upt.ro/~oose/pmwiki.php/LP/Lectures
◦ Iorga,V., Programarea Calculatoarelor, materiale de curs
http://andrei.clubcisco.ro/cursuri/anul-1/semestrul-1/programarea-
calculatoarelor.html