Documente Academic
Documente Profesional
Documente Cultură
Limbaje de
Programare
Curs 9 - Pointeri
la Functii si
Recursivitate
Dan Novischi
Review
Functii Recursive
Pointeri la Functii
Limbaje de Programare
Definire Curs 9 - Pointeri la Functii si Recursivitate
Utilizare
Aplicatie
Dan Novischi
24 Apr
Sumar
Limbaje de
Programare
Curs 9 - Pointeri
la Functii si
Recursivitate
Dan Novischi
Review 1 Review
Functii Recursive
Pointeri la Functii
Definire
Utilizare
Aplicatie
2 Functii Recursive
3 Pointeri la Functii
Definire
Utilizare
Aplicatie
Review
Limbaje de
Programare
Curs 9 - Pointeri
la Functii si
Recursivitate In limbajul C putem re-denumi (redefini) orice tip de date folosind
Dan Novischi cuvantul cheie typedef.
Review
Definitiile de tipuri proprii sunt facilitate prin intermediul structurilor si
uniunilor (struct si union).
Functii Recursive
Pointeri la Functii
O structura reprezinta un record care agrega diferinte date intr-un singur
Definire tip in timp ce uniunile suprapun date de tipuri diferite.
Utilizare
Aplicatie
Accesul la campurile individuale se realizeaza in ambele cazuri prin
nume_variabila.nume_camp pentru variabile si
nume_pointer->nume_camp in cazul pointerilor.
Deoarece marimea variabilelor de tip structura nu este cunoscuta de la
bun inceput, intr-un program aceasta se poate obtine prin aplicarea
operatorului sizeof
Structurile si uniunile respecta identic sintaxa si lucrul cu array-uri,
pointeri, alocari dimanimice si functii ca si in cazul tipurilor de baza.
Bit Field-urile reprezinta facilitatea prin care putem defini nume pentru
diferinti biti (sau grupuri de biti) ai datelor. Acestea sunt omni prezente
in sistemele embedded.
Functii Recusive
Limbaje de
Programare Pana acum pentru a trata succesiv diverse conditii sau updateul unor
Curs 9 - Pointeri
la Functii si variabile am folosit cicluri. Spre exemplu, pentru a afla suma elementelor
Recursivitate
dintr-un vector am parcurs succesiv vectorul adunand fiecare element.
Dan Novischi
Acest tip de metoda, care foloseste cicluri, pentru a rezolva o problema se
Review numeste metoda iterativa.
Functii Recursive Un alt tip de metoda este cea recursiva. Lla baza acesteia stau functiile
Pointeri la Functii recursive.
Definire
Utilizare
O functie recursiva este o functie care se apeleaza pe ea insusi.
Aplicatie Pentru a evita un lant de apeluri infinite, o functie recursiva utilizeaza o
constructie if-else unde pe una din ramuri functia se apeleaza pe ea
insasi (apel recursiv) iar pe cealalta nu.
Ramura pe care o functie recursiva nu se apeleaza pe ea insasi se
numeste caz de baza.
Spre exemplu, functia pentru pentru calculul sumei dintr-un vector de
intregi se poate scrie iterativ astfel:
int suma(int *v, int len){
int s = 0; // cazul de baza
for(i = len - 1; i >= 0; i--)
s += v[i];
return s;
}
Functii Recusive
Limbaje de
Programare
Curs 9 - Pointeri In timp ce, varianta recursiva a functie arata in felul urmator:
la Functii si
Recursivitate int suma(int *v, int len){
Dan Novischi
/* cazul de baza - ramura nerecursiva */
if(len == 0) return 0;
Review /* ramura recursiva */
Functii Recursive else return (v[len - 1] + suma(v, len - 1));
Pointeri la Functii }
Definire unde, pentru lungimea len == 0 nu aveam ce aduna si prin urmare suma
Utilizare
Aplicatie
este zero. Iar in celelalte cazuri suma este data de elementul current
v[len - 1] adunat cu suma la restul de elemente dat de apelul recursiv
al functiei suma(v, len - 1));.
Astfel, considerand un vector int v[] = {0, 2, 3} si apelul initial
functiei recursive suma(v, 3) pasii pentru evaluarea sumei sunt sunt
urmatorii:
Pasul 1: lugimea este diferita de zero (3 != 0) si se executa ramura de else.
Deci, se va executa v[2] + suma(v, 2));.
Pasul 2: lugimea este diferita de zero (2 != 0) si se executa ramura de else.
Deci, se va executa v[1] + suma(v, 1));.
Pasul 3: lugimea este diferita de zero (1 != 0) si se executa ramura de else.
Deci, se va executa v[0] + suma(v, 0));.
Pasul 4: lugimea este zero, astfel suma(v, 0); va returna zero in functia
apelanta suma(v, 1);
Functii Recusive
Limbaje de
Programare
Curs 9 - Pointeri
Continuare:
la Functii si Pasul 5: Rezultatul returnat se va aduna cu v[0], Apoi se va returna 1+0=1 in
Recursivitate
functia apelanta suma(v, 2);.
Dan Novischi
Pasul 6: Rezultatul returnat se va aduna cu v[1], Apoi se va returna 1+2=3 in
Review
functia apelanta suma(v, 3);.
Pasul 7: Rezultatul returnat se va aduna cu v[2], Apoi se va returna 3+3=6 in
Functii Recursive
programul apelant.
Pointeri la Functii
Definire
Utilizare Astfel, etapele pentru constructia unei solutii recursive sunt:
Aplicatie Se scrie antetul functiei recursive la fel ca si in cazul celei iterative
Se determina cazul (sau cazurile de baza) si solutia acestuia.
Se imparte problema in sub-probleme mai mici. Altfel spus, se determina ce
inseamna o sub-problema.
Se compun recursiv rezultatele sub-problemelor pentru a afla razultatul
problemei initiale.
Mai multe informatii despre metoda recursiva puteti gasi la adresa:
www.cs.umd.edu/class/fall2002/cmsc214/Tutorial/recursion2.
html
Functii Recusive
Limbaje de
Programare Exemplu problema: Scrieti o functie recursiva care determina a n-lea termen
Curs 9 - Pointeri
la Functii si
din seria lui Fibonacci.
Recursivitate
int getNthFibonacci(int n){
Dan Novischi
/* caz de baza 1 */
Review
if(n == 0) return 0;
Functii Recursive
/* caz de baza 2 */
Pointeri la Functii
Definire
else if(n == 1) return 1;
Utilizare
Aplicatie /* ramura recursiva a sub-problemelor */
else return getNthFibonacci(n - 1) + getNthFibonacci(n - 2);
}
Definire Pointeri la Functii
Limbaje de
Programare Analog, definitiilor de pointeri la tipurile date, limabjul C permite
Curs 9 - Pointeri
la Functii si definirea pointerilor la o functie.
Recursivitate
Spre exemplu, presupunand ca am avem o functie care intoarce un intreg
Dan Novischi
si are ca parametrii doi intregi, atunci un posibil antet al acesteia ar fi:
Review
int fct(int a, int b);
Functii Recursive
Pointeri la Functii
Definire
Astfel definitia la un pointer capabil sa arate catre o astfel de functie este
Utilizare dat de:
Aplicatie
int (*pfct)(int a, int b);
tip_returnat (*nume_pointer)(lista_parametrii);
Limbaje de
Programare
Curs 9 - Pointeri Am observat in cursurile trecute ca exista o dualitate intre numele de
la Functii si
Recursivitate
array-uri si pointeri. Astfel, exista o dualitate intre numele unei functii si
pointeri la respectiva functie.
Dan Novischi
Acesta dualitate consta in faptul ca numele unei functii este in acelasi
Review timp si un pointer la respectiva functie. Alfel spus, numele functiei
Functii Recursive reprezinta adresa de inceput a functiei in memorie.
Pointeri la Functii Astfel, avand definitia anterioara putem utiliza pointer-ul pentru a stoca
Definire
Utilizare
adresa functiei int func(int a, int b) (sau orice alta functie care
Aplicatie intoarce un intreg si are ca parametrii doi intregi) prin:
pfct = fct;
a = fct; // pentru AFunctionPointer a;
Limbaje de
Programare
Curs 9 - Pointeri
Similar tipurilor de date obisnuite, pointerii la functii, pot fi organizati in
la Functii si array-uri, se pot transmite ca parametrii la alte functii si pot fi membrii ai
Recursivitate
unor structuri sau uniuni. De asemenea, aritmetica pointerilor se aplica si
Dan Novischi
in cazul pointerilor la o functie.
Review Spre exemplu, putem scrie definitii dupa cum urmeaza:
Functii Recursive // un array de 10 pointeri la functii
Pointeri la Functii int (*arr_pfct[10])(int a, int b);
Definire // antet de functie care primeste ca argument o alta functie
Utilizare
Aplicatie
void anotherFuction(float x, int (*pfct)(int a, int b));
// sau dupa utilizarea formei cu typedef
void anotherFuction(float x, AFunctionPointer y);
// Pointer la functie in cardul unei definitii de structura
typedef struct Student{
char *nume;
char *prenume;
...
int (*compareName)(struct Student *a, struct Student *b);
}Student;
// Utilzarea campului din structura
Student *a, *b;
...
a->compareName(a, b);
Aplicatie Pointeri la Functii
Limbaje de
Programare Realizati un program care sa implementeze o functie care poate sorta un array
Curs 9 - Pointeri
la Functii si
de orice tip.
Recursivitate
#include <stdio.h>
Dan Novischi
#include <stdlib.h>
Review
#include <string.h>
// Definitie student
Functii Recursive
typedef struct{
Pointeri la Functii
Definire
char* nume;
Utilizare char* prenume;
Aplicatie char cnp[14];
long id;
float gpa;
}Student;
Limbaje de
Programare // Antetul functiei de sortare
Curs 9 - Pointeri
la Functii si void bubleSort(void* arr, int len, int size, CompareFunc comp);
Recursivitate
Pointeri la Functii
int main(void){
Definire
Utilizare
int len, i, *iArr;
Aplicatie Student *sArr;
printf("Intoduceti numarul de elemente: ");
scanf("%d", &len);
// Citire studenti
for(i = 0; i < len; i++)
printf("sArr[%d]:\n", i); readStudentFromKB(sArr + i);
// Citire intregi
for(i = 0; i < len; i++)
printf("v[%d] = ", i); scanf("%d", iArr + i);
Aplicatie Pointeri la Functii
Limbaje de
Programare
Curs 9 - Pointeri
la Functii si
Recursivitate
// Sortare array-uri
Dan Novischi bubleSort(sArr, len, sizeof(Student), compareNumeStudent);
Review
bubleSort(sArr, len, sizeof(int), compareInts);
Functii Recursive
// Afisare array de studenti sortati dupa nume
Pointeri la Functii
for(i = 0; i < len; i++){
Definire
Utilizare
printf("sArr[%d]: [%s %s %s %l, %f] \n",i,
Aplicatie sArr[i].nume, sArr[i].prenume, sArr[i].cnp
sArr[i].id, sArr[i].gpa);
}
printf("\n");
Limbaje de
Programare
Curs 9 - Pointeri
// Dealocari
la Functii si for(int i = 0; i < len; i++)
Recursivitate
free(sArr[i].nume); free(sArr[i].prenume);
Dan Novischi free(sArr);
Review
free(iArr;)
return 0;
Functii Recursive
}
Pointeri la Functii
Definire
Utilizare
int compareInts(void* a, void* b){
Aplicatie int* x = (int*) a);
int y = *((int*) b);
if(x > y) return 1;
else if(x < y) return -1;
else return 0;
}
Limbaje de
Programare
Curs 9 - Pointeri void swap(void* a, void* b, int size){
la Functii si
Recursivitate
void* aux = malloc(size);
memcpy(aux, a, size);
Dan Novischi
memcpy(a, b, size);
Review memcpy(b, aux, size);
Functii Recursive
Pointeri la Functii
}
Definire
Utilizare void bubleSort(void* arr, int len, int size, CompareFunc comp){
Aplicatie
int i, j;
for (i = 0; i < ((len-1)*size); i += size){
for(j = 0; j < ((len - 1)*size - i ); j+=size)
if( comp(arr + j, arr + j + size) == 1)
swap(arr + j, arr + j + size, size);
}