Sunteți pe pagina 1din 17

58 Instruciunea switch Instruciunile de ciclare prezentate, while, do i for sunt folosite pentru realizarea blocurilor de instruciuni a cror execuie

ncepe cu prima linie i este controlat de ctre programator. Instruciunea switch este folosit tot pentru a construi un bloc de instruciuni dar punctul de unde ncepe execuia depinde de valoarea unei expresii avnd valori ntregi. Sintaxa instruciunii este: switch (expresie) { case constanta_1 : instruciuni case constanta_2 : instruciuni ... default : instruciuni; }

Fiecare dintre punctele de unde poate ncepe execuia blocului este etichetat printr-o constant avnd valoare ntreag. Dac expresia de testat corespunde uneia dintre constante, execuia blocului ncepe din punctul indicat de aceasta. Cazul default este facultativ.

Exemplu :
#include <iostream> #include <ctype.h> #include <math.h> using namespace std; void main() { char rasp, varianta; double x; rasp = 'd'; while (tolower(rasp) == 'd') { cout << "x = "; cin >> x; cout << "Ce doriti sa calculati : (s - sin, c - cos, t tan) : ";

59
cin >> varianta; switch (varianta) { case 's' : cout << "sin = " << sin(3.14159 * x / 180.) << endl; break; case 'c' : cout << "cos = " << cos(3.14159 * x / 180.) << endl; break; case 't' : cout << "tan = " << sin(3.14159 * x / 180.)/ cos(3.14159 * x / 180.) << endl; break; default: cout << "Caracter incorect!"; } cout << "Mai continuati? (d/n) : "; cin >> rasp; } }

Ca i n cazul ciclurilor, instruciunea break provoac o ieire imediat din blocul realizat folosind switch. Dac nu ar fi prezent, dup nceperea executrii instruciunilor ramurii pe care s-a intrat, se vor executa secvenial instruciunile ramurilor urmtoare, pn la ntlnirea unui break sau pn la sfritul instruciunii switch.

switch (v) { case v1 : case v2 : case v3 : case v4 : case v5 : default : bloc instructiuni 1 bloc instructiuni 2 bloc instructiuni 3 bloc instructiuni 4 bloc instructiuni 5 bloc instructiuni 6 blocuri de instruciuni fr break

60

Capitolul 3. Programarea aplicaiilor complexe

Aspecte generale
Pentru calcule elementare, n programe se folosesc tipuri de date simple i codul se poate scrie n funcia principal, main(). Scrierea programelor de mai mari dimensiuni necesit structuri de date i de cod adecvate, care s le confere claritate i s le fac uor de depanat. Pe de alt parte, s-a constatat n timp c fr tehnici de programare care s permit recuperarea ntr-o nou aplicaie a unor secvene ct mai consistente de cod din aplicaii deja realizate, productivitatea unui programator rmne modest. Un exemplu tipic de recuperare reuit a codului este realizarea aplicaiilor Windows folosind generatoare de aplicaii de tipul Visual C++. Acestea permit realizarea interfeei aplicaiei scriind foarte puine linii de cod, elementele interfeei pstrndu-i intacte caracteristicile funcionale i estetice.

Subprograme
Scrierea aplicaiilor complexe, avnd dimensiuni mari (zeci sau chiar sute de mii de linii de cod!) poate pune probleme deosebite. tiina programrii calculatoarelor ofer ns soluii de structurare att a codului ct i a datelor unor astfel de aplicaii. n ceea ce privete codul, divizarea sa n secvene de dimensiuni reduse, uor de realizat i mai ales de depanat, se realizeaz prin folosirea subprogramelor. Un subprogram este un modul de program separat de programul principal (apelant) i legat de acesta printr-un proces de transfer - revenire.

61

Modul apelant

Subprogram

n ultimul exemplu prezentat s-au folosit funcii fr a le defini (sin, cos sau tolower). Aceste funcii, i multe altele, sunt puse la dispoziie de realizatorii compilatorului folosit. Pentru utilizarea lor a fost totui necesar includerea unor fiiere care conin n principal declaraii de funcii.
#include <iostream> #include <ctype.h> #include <math.h>

n limbajul C i n limbajele derivate din acesta se folosesc subprograme de tip funcie. Practic codul unui program este realizat prin alturarea unui numr de funcii. ntre funciile unui program exist o funcie principal, de unde ncepe execuia programului. n C sau C++ aceasta poart numele main(). O funcie are : un antet, declaraii de variabile locale i instruciuni. Ultima instruciune din funcie este return dac funcia nu returneaz o valoare sau return v, dac funcia returneaz valoarea v. Definirea unei funcii respect sintaxa : tip_val_retur nume(declaraii parametri formali) { declaraii i instruciuni } antet

62

Corpul unei funcii poate s lipseasc : double prelucrez(double a, double b) {}; // nc prelucrarea nu este scris, aplicaia este n dezvoltare. O funcie din a crei declaraie lipsete tipul valorii returnate (tip_val_retur), returneaz prin convenie o valoare de tip int. Exemplu fundamental:
#include <iostream> using namespace std; double suma(double a[ ], int n); void main() { double x[] = {1., 34., -234., 43., -12}; cout << "Suma val. din sirul x este : " << suma(x, 5) << endl; } double suma(double a[ ], int n) { double s = 0.; int i; for (i = 0; i < n; i++) s = s + a[i]; return s; }

Programul cuprinde dou funcii: funcia main() i funcia suma(). Deoarece funcia main() nu returneaz o valoare, tipul ei este void. return s) i din acest motiv este declarat de tip double. Antetul ei este: double suma(double a[ ], int n) n timpul compilrii, pentru a putea verifica dac apelul funcie suma() s-a realizat corect, compilatorul are nevoie de tipul acesteia, de numrul i de tipul parametrilor transmii acesteia. Din acest motiv, la nceputul programului s-a inclus prototipul funciei suma(): Funcia suma() returneaz o valoare n dubl precizie (ultima instruciune executat este

63 double suma(double a[ ], int n); sau double suma(double [ ], int); Pentru scrierea prototipului unei funcii, antetului acesteia i se adug un caracter ";". Denumirile parametrilor formali pot s lipseasc. Antetul funciei suma() conine doi parametri formali: (double a [ ], int n). n momentul apelului, dup numele funciei trebuie indicai parametrii efectivi. n exemplul dat, pentru apelul funciei s-a scris suma(x, 5) , deci parametrii efectivi sunt x (ir de valori double) i 5 (constant int). Valoarea expresiei de pe a doua poziie, corespunztoare variabilei ntregi n este transmis subprogramului. n cazul primului parametru, un ir, subprogramul primete adresa acestuia. n cazul parametrilor de tip ir, n cazul variabilei subprogramul poate modifica valorile elementelor irului. transmiterea parametrului n se realizeaz prin valoare.

simple n, subprogramul primete valoarea parametrului efectiv. Se spune c Dac pentru apelul funciei s-ar fi scris suma(x, p), variabila p fiind de tip ntreg i egal cu 5, rezultatul ar fi fost evident acelai. Modificarea n subprogram a variabilei n corespunzatoare variabilei p nu ar afecta valoarea variabilei p din programul apelant. Astfel definit, o funcie poate s nu returneze nici o valoare sau poate returna o valoare (int, long, double, ...). n primul caz tipul funciei va fi void iar n al doilea caz va coincide cu tipul expresiei returnate.

Referine
Tipul referin definit n C++ permite utilizarea a dou nume diferite pentru aceeai celul de memorie. Pentru declararea unei variabile de tip referin se folosete structura tip&. Exemple:
double a; double& rf = a; // rf si a se refera la aceeasi locatie de mem. rf = 34.0; // identic cu a = 34.0;

64 Tipul referin utilizat ca n exemplul dat nu prezint interes. De regul acest tip este folosit la definirea unor funcii care trebuie s returneze mai mult dect o valoare. Exemplu:

#include <iostream> using namespace std; void schimb(int &, int &); void main() { int a = 1, b = 7; cout << "La inceput a = " << a << " si b = " << b << endl; schimb(a, b); cout << "Dupa schimb() a = " << a << " si b = " << b << endl; } void schimb(int& x, int& y) { int aux; aux = x; x = y; y = aux; return; }

Practic, n cazul n care o funcie trebuie s returneze mai mult dect o valoare, o soluie corect este utilizarea n lista de parametri formali a unui numr de variabile crora n funcie le corespund referine. Astfel se ocolete mecanismul normal de transmitere a valorilor parametrilor efectivi (transmitere prin valoare). Not: Un alt mod de ocolire a mecanismului transmiterii prin valoare a parametrilor efectivi este utilizarea irurilor (tablourilor) de valori, aa cum s-a artat deja.

Structura programelor mari


n C sau C++ programele au adesea o structur multifiier (sunt compuse din mai multe fiiere). Exemplu fundamental:

65 Se consider o aplicaie n care se opereaz cu un ir de valori double. Aplicaia realizeaz succesiv suma valorilor din ir i determinarea valorii minime. Prelucrrile vor fi realizate n funcii separate. Soluie: Se creaz un nou proiect denumit operatii:

Se alege ca tip Win32 Console Application i apoi se impune Empty Project. Se adaug apoi proiectului fiierul surs Operaii.cpp:

#include <iostream> using namespace std; double suma(double a[], int n); double maxim(double a[], int n);

66 void main() { double x[] = {1., 2., 1., 0., 1.}; double rez = suma(x, 5); cout << "Suma val. din sirul x este : " << rez << endl; double mx = maxim(x, 5); cout << "Max. val. din sirul x este : " << mx << endl; }

Funciile necesare vor fi incluse ntr-un alt fiier surs, Funcii.cpp.

Fiierul Functii.cpp va avea coninutul:

67 double suma(double a[ ], int n) { double s = 0.; int i; for (i = 0; i < n; i++) s = s + a[i]; return s; } double maxim(double a[], int n) { int i; double max; max = a[0]; for(i=1; i<n; i++) { if(max < a[i]) max = a[i]; } return max; }

Observaie: Deoarece naintea utilizrii toate funciile unui program C/C++ trebuie s fie definite (cu excepia funciei principale, main()), fiierul Operatii.cpp ncepe prin definirea prototipurilor funciilor utilizate: double suma(double a[], int n); double maxim(double a[], int n); n aplicaiile mari, numrul funciilor utilizate poate fi mare i din acest motiv este bine s fie plasate ntr-un fiier separat de tip header (antet), avnd de rehul extensia .h. Adugarea unui astfele de fiier proiectului Operatii se realizeaz astfel:

68

La nceputul fiierului Operatii.cpp n locul liniilor care conineau prototipurile funciilor utilizate va fi inclus fiierul Operaii.h: #include <iostream> #include "Operatii.h" using namespace std; void main() { double x[] = {1., 2., 1., 0., 1.}; double rez = suma(x, 5); cout << "Suma val. din sirul x este : " << rez << endl; double mx = maxim(x, 5); cout << "Max. val. din sirul x este : " << mx << endl; }

69 Se observ c numele fiierului Operaii.h este plasat ntre ghilimele. Spre deosebire de Operatii.h, fiierele antet care conin declaraiile funciilor din bibliotecile limbajului se includ folosind < ... > : #include <iostream> #include <ctype.h> #include <math.h>

Notaia diferit folosit pentru cele dou categorii de fiiere provine din faptul c fiierele antet create de programator (asemenea fiierului Operatii.h) vor fi pstrate pe disc n directorul coninnd celelalte fiiere surs ale acesteia.

Vizibilitatea variabilelor
Vizibilitatea unei variabile se refer la zona dintr-un program n care variabila este cunoscut i poate fi folosit. Din punct de vedere al locului declarrii, o variabil poate fi global (declarat n afara oricrei funcii) sau local (declarat n interiorul unei funcii, la nceputul acesteia sau ntr-un bloc din cadrul acesteia. Variabilele locale aparinnd unor module distincte (funcii sau blocuri) sunt diferite, chiar dac poart acelai nume. Unei variabile globale i se aloc spaiu n memorie n momentul definirii. Dup linia de definire ea poate fi folosit. Dac variabila global este definit ntr-un alt fiier aparinnd aceleiai aplicaii sau ntr-o alt poziie, spre sfritul fiierului n care este folosit, ea trebuie declarat. Pentru a nu i se aloca memorie nc o dat, numele tipului va fi precedat de cuvntul extern :

Fiier 1 double scara=1 ; // definire void main() { int i, n ;

Fiier 2 extern double scara ; // declarare void calcul(double a[], n) {

70

O variabil global este definit o singur dat, ntr-unul dintre fiierele aplicaiei. Odat cu definirea ea poate fi iniializat. Ea trebuie declarat ns (extern ) n toate fiierele n care este folosit.

Structura programului i declararea variabilelor


n C programul are o structur simpl, fiind o niruire de funcii. Fonciile pot fi plasate ntr-un singur fiier sau n mai multe fiiere. O funcie nu poate conine o alt funcie (ca n Pascal de exemplu). O variabil poate fi declarat practic n orice punct din program. De regul declaraiile de variabile sunt plasate : n afara oricrei funcii (variabila fiind global), la nceputul unei funcii, la nceputul unui bloc din cadrul unei funcii. Declararea poate fi nsoit de iniializare. Pentru variabilele statice aceasta are loc o singur dat, naintea nceperii execuiei programului. Pentru variabilele obinuite, aceasta este repetat la fiecare intrare n funcia sau blocul n care declaraia este inclus.

Variabilele statice
Variabilele declarate n interiorul unei funcii exist numai pe durata executrii acesteia. Variabilele declarate n interiorul unui bloc din cadrul unei funcii exist numai pe durata execuiei instruciunilor blocului n care au fost definite. nainte de a fi folosite, ele trebuie s primeasc o valoare, aceast iniializare repetndu-se la fiecare executare a funciei (blocului). Dac o variabil trebuie s nu-i schimbe valoarea ntre dou apeluri ale funciei n care este definit ea trebuie declarat ca variabil static : void calcul( ) { static int contor ;

71 static int num=1000 ; ... } naintea nceperii execuiei programului variabila contor va primi valoarea 0 iar variabila num va primi valoarea 1000. Valoarile rmase n contor i num dup execuia funciei calcul() vor fi regsite la reintrarea n funcie, dup o nou apelare.

Recursivitatea
n C o funcie se poate apela pe sine nsi. O astfel de funcie poart numele de funcie recursiv. Prin recursivitate se pot realiza structuri de cod repetitive similare celor realizate folosind instruciunile de ciclare. Exemple :
long factorial(int n); double suma(int n, double a[]); void main() { long f; double s; double a[5]={10., 33., -12.,1., 10.}; f=factorial(6); s=suma(5, a); } long factorial(int n) { if(n == 1) return 1; else return n * factorial(n-1); } double suma(int n, double a[]) { if (n == 0) return a[0]; else return a[n] + suma(n-1, a); }

72 La reapelarea funciei este necesar schimbarea cel puin a unei valori din lista parametrilor formali i anume a valorii variabilei care este testat n vederea opririi reapelrii.

Date structurate
Programele de calculator sunt scrise pentru a efectua prelucrri de date specifice unor procese fizice, aparinnd lumii reale. Tipurile de date simple, elementare, folosite pn acum sunt n multe cazuri improprii memorrii n calculator a caracteristicilor entitilor manipulate. Pentru apropierea modelului din memoria calculatorului de entitatea real, ale crei caracteristici sunt memorate, limbajele de programare permit definirea unor noi tipuri de date denumite structurate. Ca i n cazul tipurilor simple, dup definirea unui tip de dat structurat se pot declara variabile aparinnd noului tip. Exemplu fundamental : Pentru pstrarea coordonatelor punctelor de pe ecranul calculatorului se folosesc dou variabile ntregi, x i y. Dac un program opereaz mult cu puncte este bine s se defineasc un nou tip de dat denumit punct, astfel: y struct punct { int x, y ; }; p1 x Declaraia noului tip de dat va fi plasat la nceputul programului, naintea funciei main(). n program vor fi declarate n continuare variabile aparinnd noului tip i vor fi efectuate diverse prelucrri.
#include <iostream> #include <math.h> using namespace std;

73

struct };

punct { int x, y ;

double distanta(punct, punct);

//

Prototipul functiei distanta()

void main() { punct p1, p2; double dist; p1.x = 0; p2.x = 10; p1.y = 40; p2.y = 99; dist = distanta(p1, p2); cout << "Distanta este: " << dist << endl; } double distanta (punct a, punct b) { double v; v = (a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y); return sqrt(v); }

Se observ c referirea componentelor tipului structurat (denumite i cmpuri) se realizeaz scriind variabil.cmp. Componentele unui tip de dat structurat pot aparine unor tipuri simple dar pot aparine i unor tipuri structurate. Extinznd exemplul dat, se poate defini un tip structurat denumit cerc, astfel:

struct cerc { punct centru; int raza; }; . . . cerc c; . . .

n program se va putea atribui o valoare componentei x a centrului cercului c scriind:


c.centru.x = 120;

O funcie poate returna o valoare aparinnd unui tip structurat. exemplu:

De

74

punct pct_circum(cerc c, double u) { punct p; p.x = (int)(c.centru.x + raza * cos(3.1415926 * u / 180.)); p.y = (int)(c.centru.y + raza * sin(3.1415926 * u / 180.)); return p; }

Funcia pct_circum() returneaz un punct de pe periferia unui cerc dat ca argument. Observaie: ntr-un program de calculator care realizeaz construcii grafice, numrul de puncte, cercuri sau alte entiti grafice poate fi mic sau mare, dar de regul este necunoscut. Declarate ca n exemplele prezentate, variabilele c (de tip cerc) sau p1 i p2 (de tip punct) nu sunt de mare ajutor. Soluia acestei adevrate probleme este reprezentat de alocarea dinamic a memoriei calculatorului, n timpul exectrii aplicaiei. Pentru aceste variabile se aloc spaiu n memoria disponibil n timpul rulrii programului, atunci cnd este necesar. Mai mult, entitile grafice generate vor fi memorate probabil sub forma unei liste, fiecare element al listei coninnd printre altele, o referin la elementului urmtor. O astfel de soluie permite crearea unui numr nedefinit de entiti deoarece memoria unui calculator actual are o capacitate considerabil.