380 likes | 607 Views
?. ?. ?. ?. Algoritmi și tehnici de programare. Pointeri la funcții (subprograme). Numele unei funcţii poate fi folosit ca pointer constant (asemănător masivelor) Semnificaţie adresa din memorie unde se află codul executabil al subprogramului respectiv Tip
E N D
? ? ? ? Algoritmi și tehnici de programare
Pointeri la funcții (subprograme) • Numele unei funcţii poate fi folosit ca pointer constant (asemănător masivelor) • Semnificaţie • adresa din memorie unde se află codul executabil al subprogramului respectiv • Tip • Pointer către un subprogram care primeşte o anumită listă de parametri şi întoarce un anumit tip de rezultat • Utilizare • Transmiterea subprogramelor ca parametri pentru alte subprograme
Pointeri la funcții (subprograme) • Exemplu void sortare(float v[], int n); sortare pointer către o funcţie care primeşte ca parametri un vector cu elemente float şi un întreg şi are rezultat de tip void float minim(float v[], int n, intpoz[], int* nr); minim pointer către o funcţie care primeşte ca parametri un vector cu elemente float, un întreg, un vector cu elemente întregi şi un pointer către întreg şi are rezultat de tip float
Pointeri la funcții (subprograme) • Declarare variabilă/parametru tip pointer la funcţie şi utilizare void sortare(float v[], int n); float minim(float v[], int n, intpoz[], int* nr); voidmain() { intdim; float a[100]; int unde[100], cite; void (*p)(float v[], int n); float (*q)(float v[], int n, intpoz[], int* nr); … p = sortare; q = minim; sortare(a,dim); // (*p)(a, dim); p(a, dim); minim(a,dim,unde,&cite); // (*q)(a,dim,unde,&cite); … }
Pointeri la funcții (subprograme) • Exemplu • Metoda bisecţiei pentru rezolvarea unei ecuaţii f(x) n, eps x1 x2 x
Pointeri la funcții (subprograme) #include <stdio.h> float ecuatie(float x) { return x*x - 7*x + 12; } intbisectie(float x1, float x2, float eps, int n, float (*f)(float), float *x) { int cod = 0; while ((n > 0) && (cod == 0)) { *x = (x1 + x2) / 2; if((*f)(*x) == 0) cod = 1; else if((x2-x1) < eps) cod = 2; else if((*f)(x1)*(*f)(*x)<0) x2 = *x; else x1 = *x; n--; } return cod; } void main() { float a, b, sol, prec; int nr, cod; printf("\na="); scanf("%f",&a); printf("\nb="); scanf("%f",&b); printf("\nprecizia="); scanf("%f",&prec); printf("\nnr="); scanf("%d",&nr); cod = bisectie(a,b,prec,nr,ecuatie,&sol); switch(cod) { case 0: printf("\nFarasolutie"); break; case 1: printf("\nSolutia exacta este %7.3f", sol); break; case 2: printf("\nSolutiaaproximativa este %7.3f", sol); } }
Recursivitate • Algoritmi iterativi • Algoritmi recursivi • Recursivitate simplă (algoritm unirecursiv) • Recursivitate multiplă (algoritm multirecursiv) • Formulă de start (una sau mai multe) • Formulă recursivă • Exemple • Numărarea valorilor care îndeplinesc o condiţie • Suma elementelor unui vector • Algoritmul lui Euclid • Şirul lui Fibonacci
Recursivitate, subprograme recursive • Un algoritm fie iterativ sau recursiv poate fi implementat printr-un subprogram fie iterativ, fie recursiv • Subprogram recursiv: generează (cel puţin) un apel către el însuşi • Recursivitate directă • Simplă • Multiplă • Recursivitate mutuală • Implicaţii • Mod de construire a subprogramelor • Necesar de memorie
Recursivitate, subprograme recursive • Construcţia subprogramelor recursive • Să asigure respectarea caracterului finit alalgoritmului: ieşirea după un număr finit de paşi • Condiţie de oprire a generării de noi apeluri • Aplicarea formulei de start dacă e îndeplinită condiţia • Aplicarea formulei recursive în caz contrar longfactorial( unsigned n ) { long f; if ( !n ) f = 1; else f = n*factorial( n-1); return f; }
Recursivitate, subprograme recursive • Necesarul de memorie
Recursivitate, subprograme recursive 1 1 1 1 1 6 2 3 2 fib(n) = fib(n-1) + fib(n-2), fib(1) = fib(0) = 1 fib( 4 ) fib( 1 ) fib( 3 ) fib( 2 ) fib( 0 ) fib( 1 ) fib( 0 ) fib( 1 ) fib( 2 )
Recursivitate, subprograme recursive • Cînd alegem subprograme iterative / recursive? • Avantaje şi dezavantaje • Consum memorie • Timp de execuţie • Uşurinţă în proiectare / implementare • Lungime cod sursă
Recursivitate, subprograme recursive • Consideraţii generale • Fiecare apel recursiv trebuie aplicat unei probleme mai simple decît în pasul anterior • Rezultă o metodă simplă de oprire a generării de noi apeluri • Cum se transformă un subprogram iterativ în unul recursiv? • instrucţiunea iterativă dispare • condiţia de la instrucţiunea iterativă devine (eventual modificată) condiţie de oprire a generării de noi autoapeluri • Repetarea este asigurată prin autoapel • Exemplu: metoda bisecţiei
Recursivitate, subprograme recursive • Calculul combinărilor de n luate cîte k longcomb(unsigned n, unsigned k) { long c; if (k>n) c = 0; else if((k==0)||(k==n)) c = 1; else c = comb(n-1,k) + comb(n-1,k-1); return c; }
Recursivitate, subprograme recursive • Suma elementelor unui vector • S(n) = x[n-1] + S(n-1), S(0) = 0 double suma(double v[], int n) { double s; if( n == 0) s = 0; else s = v[n-1] + suma(v, n-1); return s; } • Produsul elementelor unui vector
Recursivitate, subprograme recursive • Căutarea binară intcauta(float v[], int p, int u, float k) { int m; if (p > u) m = -1; else { m = (p + u) / 2; if(k < v[m]) m = cauta(v, p, m-1, k); else if(k > v[m]) m = cauta(v, m+1, u, k); } return m; }
Recursivitate, subprograme recursive if((*f)(x1)*(*f)(*x)<0) cod = bisectie( x1, *x, eps, n-1, f, x ); else cod = bisectie( *x, x2, eps, n-1, f, x ); intbisectie(float x1, float x2, floateps, int n, float (*f)(float), float *x) { int cod; if( n == 0 ) cod = 0; else { *x = (x1 + x2) / 2; if((*f)(*x) == 0) cod = 1; else if((x2-x1) < eps) cod = 2; else { if( (*f)(x1) * (*f)(*x) < 0 ) x2 = *x; else x1 = *x; n--; cod = bisectie( x1, x2, eps, n, f, x ); } return cod; } • Metodabisecției intbisectie(float x1, float x2, floateps, int n, float (*f)(float), float *x) { int cod = 0; while ((n > 0) && (cod == 0)) { *x = (x1 + x2) / 2; if((*f)(*x) == 0) cod = 1; else if((x2-x1) < eps) cod = 2; else if((*f)(x1)*(*f)(*x)<0) x2 = *x; else x1 = *x; n--; } return cod; }
Recursivitate, subprograme recursive • Teme: • Numărul de elemente negative dintr-un vector • Produs scalar între doi vectori • Algoritmul lui Euclid • Calculul c.m.m.d.c. • Metoda tangentei • Problema turnurilor din Hanoi • Sortarea unui vector
Biblioteci de subprograme • Bibliotecă: colecție de subprograme, grupate într-un singur fișier (compilat) • Scop • Reutilizarea codului în mai multe aplicații • Distribuirea către alți utilizatori • Tipuri • cod sursă, cod binar • statice, dinamice
Biblioteci de subprograme • Variante de lucru • În mod comandă • cl.exe- compilator • lib.exe- manager de biblioteci • link.exe- editor de legături • În mediul de programare (IDE) Visual Studio • În aceeași soluție (mai multe proiecte) • În soluție independentă
Biblioteci de subprograme: statice • Codul subprogramelor utilizate este inclus în executabil • Extensie • Windows: .lib • Linux: .a • Avantaje • Un singur fișier executabil • Din bibliotecă se extrage doar codul subprogramelor apelate • Dezavantaje • Dimensiune (mai) mare a fișierului executabil • Fiecare executabil va include propria copie a subprogramelor din bibliotecă
Biblioteci de subprograme: statice Fișiere cod sursă (.c, .cpp, .h) Fișiere cod obiect (.obj) Biblioteci cod obiect (.lib) Manager biblioteci Compilare Fișiere cod sursă (.c, .cpp, .h) Fișiere cod obiect (.obj) Compilare Editare de legături Cod binar executabil (.exe) Biblioteci cod obiect (.lib)
Biblioteci de subprograme: statice #include <stdio.h> #include <malloc.h> #include "matrice.h" //citire matrice patrata cu alocare // I - // E - adresa matrice, dimensiune double** citire_matrice(int *m) { int i,j; double** a; printf_s("\n\nDimensiune: "); scanf_s("%d",m); a=new double*[*m]; for(i=0;i<*m;i++) a[i]=new double[*m]; for(i=0;i<*m;i++) for(j=0;j<*m;j++) { printf_s("a[%d,%d]= ",i,j); scanf_s("%lf",&a[i][j]); } return a; } //afisare matrice patrata // I - adresa matrice, dimensiune // E - void afisare_matrice(double** a, int m) { int i,j; //cout<<"\nMatricea este: \n"; for(i=0;i<m;i++) { for(j=0;j<m;j++) printf_s("%10.6lf ",a[i][j]); printf_s("\n"); } printf_s("\n"); } //alocaredinamicamatrice // I - nr. linii, nr. coloane // E - adresamatricei double **aloca_matrice(int m, int n); //dezalocarematricedinamica // I - adresamatricei, nr. linii // E - adresamatricei (NULL) double** dezalocare_matrice(double **a, int m); //produsmatricepatrate de dimensiuniegale, prealocate // I - a, b, n // E - c void produs_mpn(double** a, double **b, int n, double** c); //copiazamatriceprealocate // I - a, m, n // E - b void copiaza(double** a, int m, int n, double** b); //citirematricepatrata cu alocare // I - // E - adresamatrice, dimensiune double** citire_matrice(int *m); //afisarematricepatrata // I - adresamatrice, dimensiune // E - void afisare_matrice(double** a, int m); • Fișiere sursă • antetmatrice.h • implementare matrice.cpp • test test.cpp #include <stdio.h> #include <conio.h> #include "matrice.h" void main() { double** a; intm,n; a=citire_matrice(&m); afisare_matrice(a,m); _getch(); }
Biblioteci de subprograme: statice • În mod comandă • Se creează un director nou pentru proiect în care se salvează cele 3 fișiere • Se executăvcvars32.bat, aflat in subdirectorul binal Visual Studio • C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin • cl -cmatrice.cpp • matrice.obj • libmatrice.obj /out:matrice.lib • matrice.lib • cl test.cppmatrice.lib • test.exe
Biblioteci de subprograme: statice • În IDE – creare bibliotecă binară • Se creează un proiect nou de tip Win32 Console Application • numele soluției: BSIDE, al proiectului: matrice • În fereastra Applicationsettings se alege • Applicationtype: Static library • Additionaloptions:Emptyproject, fără Precompiledheaders • Se adaugă la proiect fișierele sursă (antet și implementare) • Se compilează soluția (Build) • În directorul BSIDE\Debug se va genera bibliotecabinară • numele bibliotecii:matrice.lib
Biblioteci de subprograme: statice • În IDE – utilizare bibliotecă binară în aceeași soluție • Se creează un proiect nou de tip Win32 Console Application • numele proiectului: Test, se adaugă la soluția matrice • În fereastra Applicationsettings se alege • Applicationtype: Console Application • Additionaloptions:Emptyproject, fără Precompiledheaders • Se adaugă la proiect fișierul sursă (cu funcția main) • Project> Properties> Common Properties > Framework and References > Add New Reference… > matrice • Project> Properties> Configuration Properties > C/C++ > General> Additional Include Directories > calea cătrematrice.h • Project> Set As StartUp Project • Se compilează soluția (Build) • Se lansează în execuție din IDE sau separat • Test.exese află în BSIDE\Debug
Biblioteci de subprograme: statice • În IDE – utilizare bibliotecă binară în altă soluție • Se creează un proiect nou de tip Win32 Console Application • numele soluției (și al proiectului): TestS • În fereastra Applicationsettings se alege • Applicationtype: Console Application • Additionaloptions:Emptyproject, fără Precompiledheaders • Se adaugă la proiect fișierul sursă (cu funcția main) • Se copiază în directorul proiectului fișierele matrice.h și matrice.lib • Project> Properties> Configuration Properties > Linker> Input> Additional Dependencies > se adaugă matrice.lib • Se compilează soluția (Build) • Se lansează în execuție
Biblioteci de subprograme: dinamice • Codul subprogramelor utilizate este separat de executabil • Extensie • Windows: .dll • Linux: .so • Avantaje • Dimensiune (mai) mică a executabilului • Biblioteca este utilizată în paralel de mai multe aplicații • Dezavantaje • Mai multe fișiere (executabil + biblioteci dinamice) • Timp suplimentar la execuție • Asigurarea accesului la bibliotecă (calea curentă, PATH)
Biblioteci de subprograme: dinamice Fișiere cod obiect (.obj) Tabela de import (.lib) Fișiere cod sursă (.c, .cpp, .h) Biblioteci dinamice (.dll) Editare de legături Compilare Fișiere cod sursă (.c, .cpp, .h) Fișiere cod obiect (.obj) Compilare Cod binar executabil (.exe) Editare de legături Biblioteci dinamice (.dll) Biblioteci cod obiect (.lib) Cod binar executabil (.exe)
Biblioteci de subprograme: dinamice • Crearea și utilizarea este asemănătoare cu a bibliotecilor statice • Diferențe • Antetul funcțiilor trebuie să conțină (doar în .h) __declspec(dllexport) • La execuție, fișierul .dlltrebuie să poată fi găsit (cale cunoscută)
Biblioteci de subprograme: dinamice • În mod comandă • Se creează un director nou pentru proiect în care se salvează cele 3 fișiere • Se executăvcvars32.bat, aflat in subdirectorul binal Visual Studio • C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin • cl matrice.cpp /LD • matrice.dll, matrice.lib • cl test.cppmatrice.lib • test.exe • Pentru execuție sînt necesare: • text.exeșimatrice.dll
Biblioteci de subprograme: dinamice • În IDE – creare bibliotecă binară • Se creează un proiect nou de tip Win32 Console Application • numele soluției: BDIDE, al proiectului: matrice • În fereastra Applicationsettings se alege • Applicationtype: DLL • Additionaloptions:Emptyproject • Se adaugă la proiect fișierele sursă (antet și implementare) • Se compilează soluția (Build) • În directorul matrice\matrice\Debug se va genera bibliotecabinară • fișiere: matrice.dll, matrice.lib
Biblioteci de subprograme: dinamice • În IDE – utilizare bibliotecă binară în aceeași soluție • Se creează un proiect nou de tip Win32 Console Application • numele proiectului: Test, se adaugă la soluția matrice • În fereastra Applicationsettings se alege • Applicationtype: Console Application • Additionaloptions:Emptyproject, fără Precompiledheaders • Se adaugă la proiect fișierul sursă (cu funcția main) • Project> Properties> Common Properties> Framework and References> Add New Reference… > matrice • Project> Properties> Configuration Properties > C/C++ > General> Additional Include Directories > calea cătrematrice.h • Project> Set As StartUp Project • Se compilează soluția (Build) • Se lansează în execuție
Biblioteci de subprograme: dinamice • În IDE – utilizare bibliotecă binară în altă soluție • Se creează un proiect nou de tip Win32 Console Application • numele soluției (și al proiectului): TestD • Se copiază în directorul proiectului fișierele matrice.hși matrice.lib • În fereastra Applicationsettings se alege • Applicationtype: Console Application • Additionaloptions:Emptyproject, fără Precompiledheaders • Se adaugă la proiect fișierul sursă (cu funcția main) • Project> Properties> Configuration Properties > Linker> Input> Additional Dependencies > se adaugă matrice.lib • Project> Properties> Configuration Properties > Debugging> Environment > se adaugă calea către matrice.dll • Se compilează soluția (Build) • Se lansează în execuție
Biblioteci de subprograme: dinamice • Comparație dimensiuni: T E M Ă ! • Cînd folosim biblioteci? • Cînd folosim biblioteci statice / dinamice?
Biblioteci de subprograme: dinamice • Temă • Creați și testați o bibliotecă formată din funcțiile necesare prelucrării vectorilor • Bibliotecă statică • Lucrați în mod comandă • Lucrați în IDE • Bibliotecă dinamică • Lucrați în mod comandă • Lucrați în IDE