Sunteți pe pagina 1din 26

Prezentarea noiunii de limbaj de programare

Am vzut n seciunea precedenta cum pot fi reprezentai algoritmii prin utilizarea pseudo codului sau a schemelor logice, insa prelucrarea automata a datelor presupune scrierea algoritmului intr-o forma ce poate fi neleas de calculatorul electronic. Algoritmii vor fi scrii intr-un limbaj de programare, care va conine operaii asemntoare celor despre care am amintit, numite acum instruciuni. Limbajul de programare conine: ALFABETUL: o mulime de simboluri pentru scrierea cuvintelor din limbaj VOCABULARUL (LEXICUL): mulime de cuvinte acceptate ca fcnd parte din limbaj Se numete UNITATE LEXICALA cea mai mica "mbinare" de caractere din vocabular, care are un neles. Exista un set de reguli privind combinarea unitilor lexicale n cuvinte i a cuvintelor n "fraze" (reguli de SINTAXA), respectarea regulilor ducnd la obinerea unor construcii corecte. SEMANTICA unui limbaj se refera la nelesul structurilor obinute prin combinarea cuvintelor acceptate de limbaj. n vocabular avem: cuvinte cheie = cuvinte sau prescurtri ale unor cuvinte din limba engleza, ce reprezint comenzi (instruciuni) identificatori = nume folosite pentru variabile, tipuri de date i funcii definite de utilizator. Un identificator este format dintr-un ir de caractere care ncepe cu o litera i poate conine litere, cifre i caracterul "_" (underscore). Identificatorul nu poate conine spatii sau apostrof, virgula, ghilimele ... Identificatorii nu pot coincide cu cuvintele cheie. Prin PROGRAM se nelege o succesiune de comenzi(instruciuni) de prelucrare a datelor, scrise intr-un limbaj de programare. Programul este memorat intr-o entitate numita fiier sursa (este un fiier text). Prelucrrile dintr-un program C++ sunt grupate n FUNCII. Rezolvarea unei probleme se face prin utilizarea unor funcii definite n limbaj i / sau a unor funcii scrise de programator, atunci cnd funciile deja existente nu sunt suficiente. Funciile pe care limbajul le pune la dispoziia utilizatorului sunt grupate, dup tipul de prelucrare oferit, n mai multe fiiere numite "biblioteci" (fiiere HEADER). Pentru a putea utiliza o funcie trebuie s se specifice la nceputul programului numele bibliotecii care conine funcia respectiva. Orice program C++ trebuie s conin o funcie numita "main" (un fel de program principal), instruciunile coninute de aceasta fiind cele prelucrate atunci cnd programul este lansat n execuie. Pentru a se putea obine rezultatele prelucrrii datelor cu ajutorul programelor, trebuiesc parcurse urmtoarele faze: scrierea programului (editarea textului sursa); compilarea programului (= verificarea corectitudinii sintactice i semantice a textului sursa i prelucrarea sa fiier obiect) editarea legaturilor (fiierul / fiierele obiect obinute n urma compilrii sunt transformate intr-un fiier executabil, adic ntr-un fiier care poate fi lansat n execuie prin simpla scriere a numelui sau la prompterul sistemului de operare; Numim mediu de programare un program care permite asistarea programatorului n toate fazele de elaborare a unui program, scris intr-un limbaj de programare (editare, depanare, compilare, execuie). Mediul de programare Borland C++ poate fi lansat n execuie prin tastarea comenzii bc la prompterul MSDOS. n paragraful urmtor vor fi prezentate elementele de baza ale limbajului C.

Prezentarea generala a limbajului C++


Alfabetul
Alfabetul limbajului este format din acele simboluri utilizate la reprezentarea entitilor unui program, adic a unitarilor lexicale. Reamintim ca, prin uniti lexicale nelegem cele mai mici entiti cu valoare semantica (adic au o semnificaie), prin combinarea crora rezulta construciile sintactice ("propoziii i fraze"). Alfabetul limbajului C se compune din urmtoarele categorii de simboluri: Literele mari i mici ale alfabetului englez i caracterul de subliniere "_" (underscore) Cifrele arabe: 0-9 Semne de punctuaie: ; , " Alte caractere: +, -, *, / (, ), {, }, [, ], \, ~, ^, <, >, =, ?, !, #, &, Literele i cifrele, precum i caracterul underscore, de multe ori asimilat n mulimea literelor, sunt utilizate pentru construirea identificatorilor i cuvintelor cheie, dup reguli ce vor fi descrise n paragrafele corespunztoare. n limbajul C se face diferena dintre literele mici i majusculele corespunztoare, deci identificatorul "a" va fi diferit de identificatorul "A", iar turbo va fi diferit de TURBO sau TuRbO sau orice alt combinaie majuscul minuscul. 1

Identificatori
Identificatorul reprezint nume pe care le atribuim variabilelor, constantelor, funciilor, tipurilor de date definite de utilizator. Un identificator este o secvena de litere, cifre i caracterul underscore, primul caracter trebuind s fie litera sau underscore. Folosii cu multa precauie identificatori care ncep cu underscore, pentru a nu intra n conflict cu numele rutinelor sistem, a cror ortografiere nu se cunoate (numele rutinelor sistem ncep ntotdeauna cu "_"). Regulile de formare a identificatorilor sunt aceleai cu regulile din Pascal. Un identificator poate avea, teoretic, o lungime arbitrara, dar numai primele 31 de caractere sunt luate n considerare de compilator. Identificatorii urmtori: nume, Nume, NuME, NUMe sunt diferii, deoarece literele mici sunt considerate diferite de literele mari corespunztoare.

Cuvinte rezervate (keywords)


Numele rezervate instruciunilor, tipurilor predefinite i sintaxei de definire a funciilor i tipurilor de date se numesc cuvinte cheie. Lista cuvintelor cheie ale limbajului C este: auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while Identificatorii definii de utilizator nu trebuie s coincid cu cuvintele rezervate. n limbajul C++ se mai adaug cteva cuvinte cheie, care vor fi descrise la momentul oportun (n capitolul rezervat programrii orientate obiect).

Comentarii
Comentariile sunt acele iruri de caractere utilizate la explicarea programelor sursa, delimitate prin caractere speciale care determina ignorarea lor de ctre compilator. Un comentariu are urmtoarea forma: /* ir de caractere */ sau // ir de caractere unde prin ir de caractere se nelege o secvena de caractere din setul caracterelor reprezentabile, mai puin combinaia */. Nu se admit comentariile imbricate. Comentariul poate fi scris pe mai multe linii dac este scris n prima forma. A doua forma este specifica Borland C i permite scrierea unor comentarii ce nu depesc o linie.

Tipuri de date
Definiia noiunii de tip de dat cuprinde, pe lng mulimea de valori a tipului, i alte aspecte: dimensiunea memoriei alocate mulimea operaiilor ce acioneaz asupra elementelor tipului timpul de viata asociat datei, dat de clasa de memorie Tipurile de date sunt: tipuri de baza: tipuri predefinite n limbaj; caracter (char) ntreg (int) real (float, double) tipuri derivate: tipuri definite de utilizator; enumerare referina structurate: tablou structura uniune Spre deosebire de Pascal, n C nu este definit tipul logic, considerndu-se ca o expresie este adevrata dac are o valoare ne nul (adic diferit de 0) i fals n caz contrar. Tipul char difer de tipul caracter din Pascal, n C caracterele fiind de fapt numere ntregi, care desemneaz o echivalen cu codul ASCII. Se definete i tipul void, care desemneaz fie "orice tip", fie indica lipsa oricrui parametru intr-o funcie.

Tipuri de date predefinite


Tipurile de baza definite n limbajul C sunt: ntreg, real i caracter. Exista insa mai multe tipuri ntregi i reale, n funcie de numrul de bii pe care se pot memora valorile i dac valorile sunt cu sau fr semn. n plus, unele dintre aceste tipuri difer de la o implementare la alta a limbajului (n funcie de calculatorul pe care se lucreaz). n tabelul urmtor sunt prezentate tipurile fundamentale, memoria necesara stocrii valorilor de acel tip i limita valorilor ce pot fi memorate intr-o variabila de acel tip. 2

Tipul
char int short int unsigned char unsigned int long int unsigned long int float double long double

Dimensiune memorie
1 byte depinde de implementare (uzual 2 bytes) 2 bytes 1 byte depinde de implementare 4 bytes 4 bytes 4 bytes 8 bytes 10 bytes

Limita valorilor
-128127 -3276832767 -3276832767 0..255 -2147483648 2147483647 04294967295 -

Primul tip este tipul caracter. O variabila de acest tip va avea ca valoare codul ASCII asociat caracterului respectiv. De exemplu, dac unei variabile i se atribuie caracterul a, variabila va conine valoarea 97 (numrul de ordine al caracterului a n codul ASCII). Tipul ntreg cel mai des utilizat n programe este int, dar numrul de bytes pe care se memoreaz valorile de acest tip difer de la o implementare la alta a limbajului C (n funcie de tipul calculatorului). Astfel, tipul int este echivalent cu short int sau long int, n funcie de implementare. Celelalte tipuri ntregi sunt obinute prin folosirea prefixului signed sau unsigned, indicnd dac valorile respective sunt cu semn (conin i valori negative), respectiv fr semn ( valori naturale). Ultimele trei tipuri din tabel sunt tipuri reale, diferena dintre ele constnd n cantitatea de memorie utilizata, intervalul de valori i precizia memorrii valorilor (numrul de zecimale reinute). Valorile reale se reprezint conform notaiei din standardul IEEE (folosind semnul, mantisa i exponentul). De exemplu, pentru tipul float se utilizeaz reprezentarea n simpla precizie, folosind un bit de semn, 7 bii pentru exponent i 24 de bii pentru mantisa. Aceasta reprezentare are un exponent n limita a 10-37 i 1038 cu pn la 7 zecimale precizie. Valoarea maxima a unui float este de 1.701411 E38. Din tabel se observa ca nu exista un tip logic, aa cum este el definit n alte limbaje de programare. n limbajul Pascal, tipul logic e definit ca mulimea cu valorile {false, true} mpreuna cu operatorii logici cunoscui (i, sau , negaia logica). n limbajul C nu s-a definit acest tip dar se folosete urmtoarea convenie: o expresie este considerata adevrata dac valoarea obinuta la evaluarea ei este ne nul i fals n caz contrar. Variabilele care se vor folosi ca variabile logice vor fi declarate de tip ntreg. O alta caracteristica aparte o constituie introducerea tipului void, pentru a desemna nimic sau orice tip, n funcie de contextul n care este utilizat. n exemplele de pn acum tipul void a fost folosit pentru a indica faptul ca funcia main nu ntoarce nici o valoare. Pentru a putea utiliza o variabila intr-un program C, este obligatorie declararea acesteia, astfel:
[clasa_de_memorie] TIP_DE_DATE lista_variabile;

unde: clasa_de_memorie specifica locul unde se va aloca memorie pentru variabila i durata sa de viata, noiuni la care vom reveni mai trziu). Specificarea clasei de memorie este opionala; TIP_DE_DATE este orice tip predefinit sau derivat; lista_variabile conine lista variabilelor de acel tip, desprite prin virgula; Exemple: int a,b,c; char ch; float x,y; long int z; int g=7; Observaie: La declararea variabilei ntregi g s-a realizat i iniializarea acesteia ( adic stabilirea unei valori iniiale). Variabilele care sunt declarate n interiorul corpului unei funcii se numesc variabile locale, iar cele declarate n afara oricrei funcii din program se numesc variabile globale. Variabilele globale vor putea fi utilizate n toate funciile ce compun programul, iar variabilele locale doar n cadrul funciei n care au fost definite.

Citirea i afiarea datelor. Primele programe n C++


Pentru introducerea datelor prin intermediul tastaturii avem nevoie de funcia CIN, iar pentru afiarea valorilor sau mesajelor de funcia COUT. Exemplul 1: Cel mai simplu program este programul care nu realizeaz nici o prelucrare: void main( ) 3

{ } Exemplul 2: S se afieze pe ecran un mesaj. #include <iostream.h> void main() { cout<< "Salut!"; } Observaii: 1. Linia #include <iostream.h> declar c se va utiliza biblioteca de funcii cu numele "iostream.h", din care face parte funcia de afiare cout. 2. Funcia main() este funcia principal a unui program C, prelucrrile coninute de aceasta fiind primele efectuate la executarea unui program. 3. Prelucrrile ce apar intr-o funcie trebuiesc scrise intre { i } 4. Dup scrierea unei comenzi (funcie / instruciune) se pune ; Exemplul 3: Relum exemplul precedent: #include <iostream.h> void main() { cout<< "Acesta este primul program n C "; cout<<"\n scris n prima ora de laborator "; } Observaii: Caracterul "\n" are ca efect afiarea a ceea ce urmeaz pe linia urmtoare a ecranului. Mesajul trebuie precedat de << Exemplul 4: S se scrie un program pentru nsumarea a doua numere. #include <iostream.h> void main() { int a; //variabila care va memora primul numr int b; //variabila care va memora al doilea numr int s; //variabila care va memora suma celor doua numere cout <<"Introducei primul numr:"; cin >> a; cout <<"Introducei al doilea numr:"; cin >>b; s=a+b; cout<<"Suma "<<a<<"+"<<b<<"="<<c<<"\n"; } Observaii: Se folosesc trei variabile pentru a memora numerele i suma acestora. Prin "int a" se declara folosirea unei variabile de tip ntreg, avnd numele "a". "cin >> a" determina citirea unei valori de la tastatura, valoare ce va fi memorata n zona de memorie a variabilei "a". Cel care introduce date trebuie s tasteze o valoare ntreag, altfel semnalndu-se eroare. Dac se afieaz un mesaj, coninutul acestuia trebuie pus intre ghilimele. Dac se dorete afiarea valorii unei variabile atunci se scrie, dup <<, numele acesteia. Executnd programul de mai sus vei observa modul de afiare al rezultatului. n textul programului au fost introduse mici comentarii, precedate de //, pentru a facilita nelegerea textului sursa. Exemplul 5: Scriei un program care s afieze urmtorul meniu: Buturi Bere ..12500 Vin 34764 Suc5000 Cafea Nes.10000 Expreso6000 #include <iostream.h> void main( ) { cout <<Bauturi:; 4

cout <<\t Bere12500; cout <<\t Vin..34764; cout <<\t Suc5000; cout <<Cafea:; cout <<\t Nes.10000; cout <<\t Expreso6000; } Observaii: S-a folosit caracterul \t pentru a se ncepe un nou paragraf. Caracterele \t i \n fac parte dintre caracterele numite caractere escape, deoarece sunt caractere ne afiabile pe ecran dect prin utilizarea unor simboluri (secvene de evitare). Funcia fscanf Este utilizata pentru citirea datelor dintr-un fiier sau de la tastatura (dispozitivul standard de intrare) i are urmtoarea sintaxa: fscanf(tipul_valorii_citite, variabila); Modul de funcionare este urmtorul: se citete de la tastatura, n variabila dat, o valoare de tipul specificat. Tipul valorii citite se specifica prin %caracter, unde caracter poate fi: c - dac se citete un caracter d sau i - int x - ntreg n baza 16 - ntreg n baza 8 u - ntreg fr semn hd, hi, hx, ho, hu, hx - short int ld, li, l0, lu, lx - long int s - ir de caractere f , e, g, E, G- float le, lg, lf- double Le, Lg, Lf - long double naintea variabilei care stocheaz valoarea citita se va scrie ntotdeauna & (operatorul adresa), ca n exemplul urmtor: fscanf ("%f", &a); Se citete o valoare de tip float, valoarea fiind stocata n variabila a. Observaie: Nu se va folosi operatorul & pentru citire atunci cnd variabila este un pointer (care este el nsui o adresa, dar asta mai trziu...) Dac dorim s citim mai multe valori cu aceeai funcie fscanf, vom specifica pentru fiecare variabila tipul valorii: int a; char ch; float f; fscanf("%i%c%f",&a, &ch, &:f); Observaii: irul de caractere care definete tipul valorii citite se numete descriptor de format. Numrul descriptorilor de format trebuie s fie acelai cu numrul variabilelor din lista Ordinea de scriere a descriptorilor este importanta Nu introducei alte caractere intre descriptori dect cele permise Funcia fprintf Funcia fprintf este utilizata pentru scrierea datelor la dispozitivul standard de ieire. Sintaxa este: fprintf ( tipul_valorii_scrise, variabila) ; Semnificaia parametrilor este aceeai ca i pentru fscanf. Funcia are ca efect scrierea pe ecran a unei valori de tipul specificat, valoare stocata n variabila. Nu se mai folosete operatorul &. Exemplu: Calculai suma a doua numere. int a, b, suma; printf("Primul numr ="); scanf("%i",&a); printf("Al doilea numr = "); scanf("%i",&b); suma = a+b; printf("Suma dintre %i i %i este %i", a, b, suma); 5

Operatori
Operatorii constituie unul din conceptele cele mai importante i mai interesante care stau la baza unui limbaj de programare. Limbajul C este vestit pentru marea varietate de operatori pe care-i pune la dispoziia programatorului rezultnd i o diversitate de expresii ce se pot forma pe baza acestora. Dup cum se tie, o expresie este formata din variabile, constante, funcii i operatori. n acest paragraf voi aminti cteva din categoriile de operatori ai limbajului C:

Operatorii aritmetici:
+ adunare, - scdere, * produs, / mprire, % - restul mpririi ntregi ++, -- incrementare i decrementare

Operatori relaionali:
<,> == egal <= mai mic sau egal >= mai mare sau egal != diferit

Operatori logici:
&& - i logic || - sau logic ! - negaie logica Operatorii logici i relaionali sunt implicai n formarea expresiilor cu valoare logica. Spre exemplu: a<2, 7/5+2<s-1, (X>-3) &&(x<3), !(a==b) sunt expresii cu valoare logica.

Operatori de atribuire.
n seciunea precedenta am amintit, vorbind despre reprezentarea algoritmilor prin scheme logice, de operaia de atribuire. n limbajul C se considera ca atribuirea este un operator. Atribuirea are urmtoarea sintaxa: variabila = expresie; Modul de funcionare este urmtorul: 1. se evalueaz expresia; 2. valoarea obinuta este stocata n zona de memorie a variabilei, realizndu-se eventuale conversii de tip. 3. valoarea rezultata n urma atribuirii este valoarea atribuita variabilei. Observaie: Atribuirea fiind un operator, se considera ca operanzii sunt variabila din partea stnga, respectiv expresia din partea dreapta. Orice expresie trebuie s aib, n urma evalurii sale, o valoare (un rezultat). Valoarea expresiei de atribuire este valoarea obinuta prin evaluarea expresiei din partea dreapta a atribuirii. Dac valoarea obinuta prin evaluarea expresiei din dreapta atribuirii este de alt tip dect tipul variabilei din stnga atunci se ncearc conversia tipului valorii la tipul variabilei. Nu ntotdeauna conversia este posibila, caz n care se va afia un mesaj de eroare n urma compilrii. Exemplul 1 : Fie urmtoarea secvena de program: void main(void) { int a; float c; a=3./2.+9./4.; cout<<a=<<a<<\n; c=3./2.+9./4.; cout<<c=<<c<<\n /* aceeai expresie are valori diferite, n funcie de tipul variabilei din stnga atribuirii */ } Observaie: Executnd programul de mai sus se vor obine valori diferite pentru variabilele a i c, dei expresia care apare n dreapta ambelor atribuiri este aceeai. Pentru a se obine valoarea 3, iar pentru c se obine 3,75. Explicaia sta n modul n care se realizeaz conversiile de tip n cadrul atribuirilor. Valoarea expresiei 3./2.+9./4. este 3,75 dar variabilei a i se va atribui partea ntreaga a acestei valori, adic 3. Variabila c este de tip float (numr real), deci nu va mai fi nevoie de conversia rezultatului evalurii expresiei la tipul variabilei. Exemplul 2: void main(void) 6

{ float a; a=5/2; cout<<a; } Observaie: Executnd acest program se va afia valoarea 2 i nu valoarea 2,5 aa cum ar fi fost de ateptat. Explicaia este urmtoarea: operatorul / realizeaz, atunci cnd operanzii sunt ntregi, mprirea ntreaga, deci vom obine catul mpririi ntregi dintre 5 i 2. Exista doua modaliti de rezolvare a problemei: fie nlocuim expresia cu 5./2. (5.=5.0) fie utilizam operatorul de conversie explicita ( ). Acest nou operator ( numit cast), se utilizeaz astfel ( tip_de_date) expresie; Semnificaia este urmtoarea: Se cere convertirea valorii rezultate din evaluarea expresiei la o valoare de tipul specificat intre paranteze. n exemplul de mai sus vom nlocui atribuirea cu: a=(float) 5/2; (rezultatul expresiei va fi de tip float, deci variabilei a i se va atribui valoarea 2.5). Exerciiu: Fie urmtorul program, care calculeaz media aritmetica a trei numere a,b,c , primele doua introduse de la tastatura.: void main(void) { int a,b,c; float s; cin>>a; cin>>b; c=a/2+b/3; s=(a+b+c)/3; cout<<Media aritmetica este=<<s; } Executai acest program i identificai greelile. Corectai greelile gsite.

operatori de atribuire compusa: +=, -=, *=, /=, %=


Operatorii de atribuire compusa au fost introdui pentru a fi utilizai n locul atribuirilor de tipul: v=v+expresie; v=v-expresie; v=v*expresie; e.t.c unde: v-variabila expresie-orice expresie corecta n limbajul C n locul acestor expresii se vor folosi: v+=expresie; v-=expresie; e.t.c Folosirea operatorilor de atribuire compus sporete lizibilitatea programului i viteza de execuie. Dac atribuirea este de forma: v=v+1; sau v=v-1; se pot utiliza operatorii de incrementare i decrementare ++ i --. Expresiile de mai sus se vor putea scrie: v++; respectiv v--; Exemplul 3: Se da urmtorul program: void main(void) { int a,b,i=3; a=++i; //preincrementare a lui i cout<<a; 7

b=a--; //postdecrementare cout<<a=<<a<<\n; cout<<b=<<b<<\n; a+=++b; //atribuire compusa cout<<a=<<a<<\n; cout<<b=<<b<<\n; } Observaie: Cnd apar expresii de tipul : ++variabila sau --variabila; spunem ca se realizeaz o preincrementare, respectiv predecrementare. n cazul preincrementrii, variabila va primi ca valoare 1+valoarea iniial. Dac preincrementarea apare intr-o expresie se realizeaz nti aceasta operaie i abia apoi celelalte operaii care mai apar n expresie (preincrementarea are prioritate mai mare). n atribuirea a = ++I se realizeaz nti preincrementarea, n urma creia i va avea valoarea 4, i abia apoi se realizeaz atribuirea (a va avea valoarea 4). n expresia b = a se realizeaz o postdecrementare, adic se modifica valoarea variabilei a doar dup ce s-au efectuat celelalte operaii din expresie. n cazul nostru, b va primi valoarea lui a (4, n momentul acela) i abia apoi se va micora valoarea lui a cu o unitate. Exerciiu: Executai programul de mai sus i urmrii rezultatele care se obin. Mai exista operatori de atribuire compusa, folosindu-se operatorii logici ce acioneaz la nivel de bit, dar despre acetia vom vorbi intr-o seciune viitoare. Tot atunci vom discuta i despre atribuirea multipla.

Instruciunea alternativa (IF)


Pn acum am folosit ca exemple programe simple, care conineau doar funciile de intrare / ieire i operatorul de atribuire. Atunci cnd elaboram programe ceva mai complexe este necesar ca, intr-un anumit punct al programului, s decidem continuarea acestuia n funcie de o condiie. n primul laborator am dat ca exemplu de algoritm rezolvarea ecuaiei de gradul 1 (pseudocod i schema logica). Intr-o schema logica ni se permitea utilizarea unui bloc de decizie de urmtorul tip: cu semnificaia: dac este adevrata condiia se executa prelucrarea B, altfel se executa prelucrarea A. n limbajul C este utilizata instruciunea IF, cu urmtoarea sintax: if (expresie) instruciune1; [else instruciune2;}

N U A

C A B

D A

C B

unde: expresie - orice expresie valida n limbajul C instruciune1, instruciune2 - orice instruciune corecta din limbajul C ; Mod de funcionare: se evalueaz expresia dac expresia este ne nul (convenia pentru adevrat) se executa instruciune1 dac expresia este nula (fals) se executa instruciune2 se trece la urmtoarea instruciune a programului Observaie: alternativa else instruciune2 poate s lipseasc. Exemplul 4: S se scrie un program pentru calcularea maximului a doua numere. #include <iostream.h> void main(void) { int a,b; int max; cout<<a=; cin>>a; cout<<\nb=; 8

cin>>b; if (a<=b) max=b; else max=a; cout<<Maximul celor doua numere este=<<max<<\n; } Exemplul 5: Scriei un program care calculeaz maximul a 3 numere. #include <iostream.h> void main (void) { int a,b,c; int max; cout<<a=; cin>>a; cout<<\nb=; cin>>b; cout<<\nc=; cin>>c; if (a<=b) if (c<=b) max=b; else max=c; else if (c<=a) max=a; else max=c; cout<<\nMaximul este=<<max; } Observaie: Dup cum se vede din exemplu, instruciune1 i instruciune2 pot fi de asemenea instruciuni if. Spunem ca sunt instruciuni if imbricate. A se observa i modul cum a fost scris programul, astfel nct s se vad clar crei instruciuni if ii aparine fiecare else. Exemplul 6: Se dau trei numere ntregi a,b,c. S se testeze dac numerele date pot fi lungimile laturilor unui triunghi. #include <iostream.h> void main (void) { int a,b,c; cout<<a=; cin>>a; cout<<\nb=; cin>>b; cout<<\nc=; cin>>c; if (a<b+c) if (b<a+c) if c<a+b) cout<< Numerele pot fi lungimile laturilor unui triunghi !; else cout<<Numerele nu pot fi lungimile laturilor unui triunghi !; else cout<<Numerele nu pot fi lungimile laturilor unui triunghi !; else cout<<Numerele nu pot fi lungimile laturilor unui triunghi !; } Observaie: Nu am mai verificat dac a, b , c sunt pozitive. Exemplul 7. Relum exemplul precedent cu intenia de a folosi mai puine instruciuni if. #include <iostream.h> void main (void) { 9

int a,b,c; cout<<a=; cin>>a; cout<<\nb=; cin>>b; cout<<\nc=; cin>>c; if ((a<b+c) && (b<a+c) && (c<a+b)) cout<<Numerele pot fi lungimile laturilor unui triunghi !; else cout<<Numerele nu pot fi lungimile laturilor unui triunghi !; } Observaie: Am folosit o singura instruciune if, cele trei condiii anterioare fiind conectate prin operatorul I logic. Dup cum se tie, dac avem propoziiile p,q,r, atunci propoziia p&&q&&r va fi adevrata dac toate propoziiile componente sunt adevrate i fals dac una dintre propoziiile componente este fals. Este indicata aceasta scriere pentru ca sporete lizibilitatea programului. Exemplul 8: Rezolvarea ecuaiei de gradul I. #include <iostream.h> void main(void) { int a,b; float x; cout<<\na=; cin>>a; cout<<\nb=; cin>>b; if (a!=0) { x=(float) -b/a; cout<<\nx=<<x; } else if (b==0) cout<<\n x aparine lui R ; else cout <<\n Ecuaia nu are soluii; } Observaie: n cazul n care a este ne nul avem de realizat doua operaii: atribuirea valorii -b/a variabilei x i afiarea valorii rdcinii. Atunci cnd se realizeaz mai multe operaii acestea trebuiesc incluse intre { i }.

Instruciuni iterative
Toate problemele prezentate pn acum au putut fi rezolvate folosind numai funcii de citire / scriere, atribuiri i instruciunea de decizie (IF). Cele mai multe dintre probleme vor necesita structuri de date mai complexe precum i folosirea unor noi instruciuni, care s permit repetarea de un numr oarecare de ori a unor pari din algoritm. S luam ca exemplu algoritmul de calcul al sumei a 2 numere introduse de la tastatura. El consta n citirea valorilor pentru cele doua numere i afiarea sumei acestora. Nu era nevoie dect de doua variabile, cate una pentru fiecare numr. Acest exemplu este doar unul didactic, n practica ne ntlnindu-se prea des cazuri n care s fie nevoie de a suma doua numere. Generalizarea problemei pentru n numere va modifica substanial algoritmul nostru. Nu vom putea folosi cate o variabila pentru fiecare numr introdus deoarece nu cunoatem exact cate numere avem (n este introdus de utilizatorul programului, altfel algoritmul nu ar mai fi general). Chiar dac s-ar ti ca avem, s zicem, 2500 de numere ar fi cam dificil s utilizam 2500 de variabile distincte. Problema noastr se poate rezolva simplu dac utilizam o instruciune iterativa (ciclica), care s ne permit repetarea de n ori a urmtoarei secvene de operaii: 1. citim o valoare folosind variabila a; 2. adunam valoarea citita la rezultatul parial, memorat n variabila s; Instruciunile ce descriu aceste prelucrri ciclice sunt compuse din doua pri: corpul ciclului, format din prelucrrile ce se doresc a fi realizate de mai multe ori; condiia, pe baza creia se stabilete dac se vor mai executa prelucrrile din ciclu (este obligatorie executarea prelucrrilor din corpul instruciunii de un numr finit de ori); Corpul ciclului sau condiia trebuie s conin acele operaii care, dup efectuarea de un numr de ori a corpului instruciunii, s determine schimbarea valorii de adevr a condiiei, permind ncheierea executrii instruciunii 10

ciclice i trecerea la urmtoarele instruciuni ale algoritmului. n cazul n care este neglijat acest aspect, programul se va executa la infinit. Condiia trebuie s fie o expresie cu valoare logica. Reamintesc faptul ca n limbajul C++ nu exista un tip de date logic, dar se utilizeaz convenia ca orice valoare ne nula s fie considerata ca adevr iar valoarea zero ca valoarea fals. n consecin, orice expresie cu valoare de tip ntreg va putea fi utilizata drept condiie intr-o instruciune iterativa. n finalul paragrafului o chestiune de terminologie: o execuie a corpului instruciunii poarta numele se iteraie. Instruciunile iterative pot fi clasificate, n funcie de momentul evalurii condiiei, astfel: cicluri cu test iniial (While i For)- evaluarea condiiei se face naintea fiecrei iteraii; cicluri cu test final (Do .. While)- evaluarea condiiei se face la sfritul fiecrei iteraii;

Instruciunea While
Instruciunea While (att timp cat) este o instruciune iterativa cu test iniial i are urmtoarea sintaxa: while ( <condiie>) instruciune; unde: <condiie> - orice expresie cu valoare ntreaga; instruciune - orice instruciune valida a limbajului; Mod de funcionare: dac expresia este adevrat se executa prelucrrile din ciclu; altfel, se trece la urmtoarea instruciune de dup while; Cu alte cuvinte, prelucrrile din ciclu se executa att timp cat condiia este adevrata. Dac expresia este fals de la nceput corpul ciclului nu se va executa deloc. Problema propusa n paragraful precedent se poate rezolva astfel: Exemplul 1 Suma a n numere introduse de utilizator #include <iostream.h> void main() { float a; int i,n; float suma=0; i=1; cout<<"\nNumrul de elemente="; cin>>n; while(i<=n) { cout<<"Elementul "<<i<<"este: "; cin>>a; suma=suma+a; //se mai poate scrie suma+=a i++; } cout<<"Suma este= "<<suma; } Exemplul 2: Suma primelor n numere naturale. #include <iostream.h> void main() { int n; int i; int suma=0; cout<<"n="; cin>>n; i=1; while(i<=n) { suma=suma+i; i++; } cout<<"Suma este: "<<suma; } 11

Observaie: Se poate utiliza o scriere mai compacta, care elimina i necesitatea utilizrii variabilei i: while (n--) suma+=n; Modul de execuie este urmtorul: valoarea condiiei este valoarea variabilei n, valoare care scade cu o unitate dup fiecare iteraie (postdecrementare) condiia devine fals atunci cnd valoarea lui n devine zero;

Instruciunea do .. while
Instruciunea do .. while este o instruciune iterativa cu test final i are urmtoarea sintaxa: do instruciune; while (<condiie>) Mod de funcionare: se executa corpul instruciunii; se evalueaz condiia: dac aceasta este adevrata se reia execuia, altfel se trece la urmtoarea instruciune din program; Deosebirea esenial fa de instruciunea while este aceea ca expresia se evalueaz dup iteraie. n cazul n care condiia este fals de la nceput, corpul instruciunii se executa o singura dat. Utilizarea instruciunii do .. while este mai puin frecventa (se folosete pentru acele prelucrri care trebuiesc executate cel puin o dat). Dac rescriem exemplul 1 utiliznd do .. while, obinem: . do { cin>>a; suma+=a; i++; } while(i<=n); .

Instruciunea for
Una dintre cele mai puternice instruciuni iterative ale limbajului C (i nu numai) este instruciunea for, care are urmtoarea sintaxa: for (expresie1; expresie2; expresie3) [instruciune]; unde: expresie1, expresie2, expresie3 - expresii valide n C++; instruciune - orice instruciune a limbajului C++; Parantezele ptrate semnifica faptul ca instruciunea este opionala; Mod de execuie: expresiile au urmtoarea semnificaie generala: expresie1 - expresie de iniializare; expresie2 - condiia de continuare a execuiei ciclului; expresie3 - expresie de actualizare; att timp cat expresie2 este adevrata se executa corpul ciclului; de fiecare dat se evalueaz expresia de actualizare, care are rolul esenial de a determina ca, dup un numr de iteraii, expresie2 s devin fals; expresie1 se evalueaz o singura dat; Exemplul 3: Relum exemplul 1 folosind instruciunea for: #include <iostream.h> void main() { int i, n; float a, suma=0; cin>>n; for(i=1;i<=n;i++) { cin>>a; suma+=a; } 12

cout<<suma =<<suma; } Observaii: Variabila i este utilizata pe post de contor al instruciunii for, numrnd la a cta iteraie s-a ajuns. Execuia instruciunii for se ncheie atunci cnd numrul de iteraii devine egal cu n. Iniializarea lui i cu 1 se realizeaz o singura dat, la nceput; i <= n este condiia de continuare a execuiei; i++ se efectueaz dup fiecare execuie a ciclului (postincrementare). Aceasta forma a instruciunii for este cea mai utilizata. Un alt mod de a descrie execuia acesteia este urmtorul: pentru i de la 1 la n se executa corpul instruciunii. Nu este obligatoriu ca valoarea lui i s se mreasc de fiecare dat cu o unitate. Nu este obligatorie utilizarea tuturor celor trei expresii din for, dar este obligatorie scrierea separatorului ; . Exemplul de mai sus se poate rescrie astfel:

for( ;n--; ) { cin>>a; suma+=a; }

Noiunea de tablou
n laboratorul precedent explicam de ce nu putem s utilizam 2500 de variabile distincte atunci cnd dorim s nsumam 2500 de numere. Rezolvarea propusa atunci se baza pe citirea repetata a cate unei valori, folosind o variabila a, urmata de adugarea acesteia la suma pariala. Dezavantajul metodei este acela ca nu se pot memora toate valorile citite ci doar ultima (citind o valoare intr-o variabila, vechea valoare a acesteia se pierde). Cele mai multe programe presupun prelucrri complexe asupra datelor de intrare, deci va fi nevoie s memoram irul nostru de numere astfel nct s poat fi utilizat i n alte prelucrri, nu numai pentru calcularea sumei. Pentru a rezolva astfel de situaii s-a introdus n limbajele de programare noiunea de tablou. Tablourile ne permit memorarea unui numr mare de valori utiliznd o singura variabila. Prin tablou se nelege un numr de elemente de acelai tip, numit tip de baza, stocate intr-o zona compacta de memorie. Un tablou poate fi definit astfel: tip_de_baza nume [dimensiune1] [dimensiune2] [dimensiune_n]; unde: tip_de_baza = tipul elementelor tabloului; n = numrul de dimensiuni al tabloului; [dimensiune_i] = numrul de elemente pe dimensiunea I tabloul are dimensiune1**dimensiune_n elemente Noiunea de tablou multidimensional poate fi neleas mai bine dup parcurgerea noiunilor referitoare la vectori i matrice.

Tablouri unidimensionale
Declararea unui tablou unidimensional: tip_de_baza nume[dimensiune]; unde dimensiune specifica numrul de elemente al vectorului. De exemplu: int a[30]; declara un vector ce conine 30 de elemente de tip int, float b[50]; declara un vector cu 50 elemente reale; Numerotarea elementelor se face de la 0 la dimensiune-1, adic cele 30 de elemente ale primului tablou sunt: a[0], a[1], a[2], , a[29]. Spunem ca tabloul este o variabila indexata, deoarece fiecare element al tabloului poate fi gsit / utilizat cunoscnd numrul sau de ordine. Vectorul este un ir de valori n care se cunoate precis care este primul, al doilea, .,ultimul element. Numrul de ordine al unui element se numete indice. Exemplul 1: S se calculeze minimul elementelor unui ir de n numere, utiliznd vectori. #include <iostream.h> void main() { int n; //numrul de elemente 13

int a[50]; //se definete o variabila de tip tablou cu maxim 50 de elemente, deci n va trebui // sa fie mai mic dect 50 int min; //variabila ce va memora minimul int i; //contor n instruciunea for cout<<n=; cin>>n; /* se citesc elementele irului */ for(i=0;i<n;i++) { cout<<a[<<i<<]=; cin>>a[i]; } // se calculeaz minimul min=a[0]; //iniializam minimul cu primul element din ir for(i=1;i<n;i++) if (a[i]<min) min=a[i]; //afiare minim cout<<Minimul este=<<min; } Dup cum se poate observa din programul de mai sus, fiecare element al irului se poate utiliza ca i cum ar fi o variabila de tip int independenta, deci valoarea unui element al vectorului poate fi modificata independent de celelalte elemente. S presupunem ca utilizatorul introduce pentru n valoarea 4. Iniial, elementele vectorului nu au o valoare bine definita; putem reprezenta grafic vectorul astfel: S presupunem ca utilizatorul introduce valorile 3, 7, 2, 9 pentru cele patru elemente ale vectorului. Reprezentarea vectorului a va fi urmtoarea: a[0] a[1] a[2] a[3] 3 7 2 9 Valoarea oricrui element al vectorului poate fi modificata fie printr-o atribuire, fie prin introducerea unei valori (folosind funcia cin, de exemplu) de la tastatura. Dac vom introduce atribuirea a[2]=23; valoarea elementului al treilea din vectorul a nu va mai fi 2 (vechea valoare) ci 23. De asemenea, dac se scrie: cin>>a[2]; valoarea elementului va fi cea introdusa de utilizator de la tastatura. Exemplul 2: Se considera n numere ntregi introduse de la tastatura. S se afle cate numere sunt pare i cate impare. #include <iostream.h> #include <conio.h> void main() { int n; //numrul de elemente int v[30]; //vector cu maxim 30 elemente ntregi int pare, impare; //variabile ce memoreaz nr. Elementelor pare, respectiv impare int j; //variabila folosita n instruciunea for clrscr(); //citim numrul de elemente cout<<n=; cin>>n; /* se citesc elementele irului */ for(i=0;i<n;i++) { cout<<v[<<i<<]=; cin>>v[i]; } //iniializam variabilele pare=0; impare=0; //luam fiecare element din v i testam dac acesta este sau nu par for(j=0;j<n;j++) if (v[j] % 2 = =0) pare++; 14

else impare++; //afiam rezultatul cout<<Am gsit <<pare<< numere pare i <<impare; } n programul de mai sus verificam, pentru fiecare element, dac acesta se mparte exact la doi, caz n care am mai descoperit un element par. n caz contrar, numrul elementelor impare se mrete cu unu. Am utilizat operatorul % , numit i modulo aritmetic, care are ca rezultat restul mpririi lui v[j] la 2. Exemplul 3: S se introduc de la tastatura un cuvnt i s se afieze. #include <iostream.h> #include <conio.h> void main() { char cuvnt[30]; clrscr(); cout<<Introduceti cuvantul:; cin>>cuvant; cout<<Cuvantul introdus este:<<cuvant; } Observai cu atenie cum am declarat variabila ce va memora cuvntul: folosim un vector cu elemente de tip caracter. Acest mod de declarare ne permite s lucrm cu oricare dintre caracterele ce formeaz cuvntul. De exemplu, dac utilizatorul introduce cuvntul salariu, vectorul nostru de caractere arata cam aa: Dac dorim s modificam puin cuvntul putem scrie: cuvant[6]=i; i vom obine cuvntul salarii. Exemplul 4: S se citeasc un cuvnt i s se gseasc numrul de vocale pe care le conine. #include <iostream.h> #include <conio.h> # include <string.h> void main() { char c[30]; //vector pentru memorarea cuvntului int vocale; //variabila ce va memora numrul vocalelor int j; clrscr(); cout<<Introduceti cuvantul:; cin>>c; vocale=0; //cutam vocalele for(j=0;j<strlen(c);j++) if ( c[j]==a || c[j]==e || c[j]==i || c[j]==o || c[j]==u) vocale++; cout<<Am gasit <<vocale<< vocale.; } Observaii: Am utilizat funcia strlen, care are ca rezultat numrul de caractere al irului dat ca parametru. Funcia poate fi utilizata doar dac a fost inclus fiierul antet string.h, fiier ce conine funciile ce acioneaz asupra irurilor de caractere. Mecanismul algoritmului este urmtorul: se ia cate un caracter din irul introdus i se verifica dac elementul respectiv conine unul dintre caracterele a, e, i, o, u. De fiecare dat cnd condiia este adevrata se incrementeaz numrul de vocale. Mai multe despre irurile de caractere vom spune dup capitolul dedicat pointerilor. Exemplul 5 (Cutare secveniala) Se considera un ir de n elemente ntregi i un numr ntreg x. S se verifice dac numrul x face parte din irul considerat. #include <iostream.h> #include <conio.h> void main() { int v[25]; int n; 15

int x; int j; int gasit; //variabila logica ce indica dac x aparine sau nu lui v clrscr(); //citim numrul de elemente cout<<n=; cin>>n; /* se citesc elementele irului */ for(j=0;j<n;j++) { cout<<v[<<j<<]=; cin>>v[j]; } //se citeste elementul x cout<<x=; cin>>x; gasit=0; j=0; //cautam x n irul v while( (j<n)&&(!gasit)) { if (v[j]==x) gasit=1; j++; } if(gasit) cout<<Elementul apartine irului dat !; else cout<<Elementul nu aparine irului !; } Am utilizat instruciunea while, condiia de efectuare a ciclului fiind (j<n) && (!gsit). Corpul instruciunii while se va executa att timp cat nu s-a ajuns la sfritul irului i elementul x nu a fost gsit n v. Condiia de mai sus devine fals n doua cazuri: fie am epuizat elementele irului (j a ajuns egal cu n), fie am gsit un element egal cu x. Dup executarea ciclului while testam dac variabila gsit este ne nula (adevr), caz n care x aparine lui v, altfel x nu aparine irului. Exemplul 6. (sortare) Se considera un ir cu n elemente reale. S se aranjeze elementele n ordine cresctoare utiliznd acelai vector. #include <iostream.h> #include <conio.h> void main() { double v[40]; int n; int j, k; cout<<n=; cin>>n; for(j=0;j<n;j++) { cout<<v[<<j<<]=; cin>>v[j]; } //sortarea crescatoare a irului v for(j=0;j<n-1;j++) for(k=j+1; k<n;k++) if (v[j]>v[k]) { //interschimbam valorile v[j] i v[k] temp=v[j]; v[j]=v[k]; v[k]=temp; } //afisarea valorilor sortate crescator for(k=0;k<n;k++) cout<<v[k]<<\t; 16

Tablouri bidimensionale (matrice)


Pe lng vectori, cel mai utilizat tip de tablou de numere este tabloul bidimensional, numit de cele mai multe ori matrice. Declararea unei matrice se face astfel:
tip_de_baza nume[dimensiune_1][dimensiune_2];

Exemplu: double a[10][5]; //tablou cu 10 linii i 5 coloane de elemente reale int a[3][2]; //tablou cu 3 linii i 2 coloane de elemente ntregi Pentru a putea avea acces la valoarea unui element al matricei, trebuie s precizam linia i coloana pe care se afla acesta. Un element poate fi specificat prin a[i][j], i - reprezentnd linia i j - coloana. n cazul vectorilor citeam o valoare reprezentnd numrul de elemente. Pentru matrice vom citi o valoare m - numrul maxim de linii i o valoare n - numrul maxim de coloane. O matrice cu m linii i n coloane va avea m * n elemente. Dac m = n atunci matricea se numete matrice ptrata de ordin n. Exemplul 7. S se citeasc elementele unei matrice i s se afieze. #include <iostream.h> #include <conio.h> void main() { int a[20][20]; //matrice cu elemente ntregi int m, n; //numrul de linii, respectiv coloane int i, j; //variabile folosite n instr. For //citim numrul de linii i coloane cout<<Numrul de linii:; cin>>m; cout<<Numrul de coloane:; cin>>n; //se citesc elementele matricei for(i=0;i<m;i++) for(j=0;j<n;j++) { cout<<a[<<i<<][<<j<<]=; cin>>a[i][j]; } //afisarea elementelor matricei for(i=0;i<m;i++) { for(j=0;j<n;j++) cout<<a[i]][j]<<\t; cout<<\n; } } Exemplul 8. Se dau doua matrice cu m linii i n coloane. S se calculeze matricea suma. . int a[20][20], b[20][20], c[20][20]; int m,n; int i, j; .. //se citesc dimensiunile m, n i cele doua matrice a i b . //calculam matricea suma for(i=0;i<m;i++) for(j=0;j<n;j++) c[i][j]=a[i][j]+b[i][j]; //se afiseaza matricea c .. Atunci cnd lucrm cu matrice avem nevoie de doi indici: i pentru a parcurge liniile matricei i j pentru a parcurge coloanele acesteia. Pentru fiecare valoare a lui i, j ia toate valorile intre 0 i n-1, deci se parcurge linia i. n ultimul exemplu am utilizat trei matrice. Pentru mai multa claritate, putem declara un tip ale crui elemente s fie matrice: typedef int matrice[20][20]; matrice a, b, c; 17

Am definit un tip de date (tip de date definit de utilizator) ale crui elemente sunt matrice cu maxim 20 de linii i coloane cu elemente ntregi. Numele noului tip este matrice. Declararea variabilelor de acest tip se poate face oriunde n programul n care apare definiia. Definirea unui tip de date se poate face numai prin utilizarea cuvntului cheie typedef naintea declaraiei. Dac definim mai multe tipuri se va folosi typedef pentru fiecare definiie.

Noiunea de pointer
Pointerii au fost introdui n limbajele de programare pentru a putea rezolva mai eficient anumite probleme sau pentru a da mai multa claritate anumitor programe. O prima definiie poate fi urmtoarea: Pointerul este o variabila ce conine adresa unui obiect. Obiectul a crei adresa este reinuta de pointer poate fi: variabila funcie Fie urmtorul exemplu: int x; int *px; Am definit o variabila de tip ntreg x i o variabila pointer, care poate conine adresa unei variabile de tip ntreg. Simbolul * ce apare n stnga variabilei px arata ca px este o variabila pointer. Prin atribuirea px=&x; Pointerul va avea ca valoare adresa de memorie alocata variabilei x (vezi laboratorul nr.1, definiia variabilei). Operatorul unar & este utilizat pentru a se obine adresa variabilei x (operator unar = are un singur operand) Acum putem s lucrm cu coninutul variabilei x (adic cu valoarea acesteia) prin intermediul pointerului px, deci indirect, fr s mai folosim variabila x. La prima vedere, aceasta modalitate de lucru poate prea dificila i nu tocmai utila. Necesitatea utilizrii pointerilor va apare cu mai multa claritate n seciunea dedicata irurilor de caractere i funciilor. Exemplul 1. Fie programul urmtor: #include <iostream.h> void main() { int x,y; int *px; cout<<"x="; cin>>x; cout<<"y="; cin>>y; px=&x; cout<<"x are valoarea "<<*px; *px=y; cout<<"\nx a devenit "<<x; } n programul de mai sus am introdus valorile variabilelor ntregi x i y, am definit un pointer la variabila x i am atribuit acestuia adresa de memorie alocat variabilei x. S analizam atent linia: cout<<"x are valoarea "<<*px; Prin *px se nelege valoarea aflata n zona de memorie a crei adresa este memorata n pointerul px. Valoarea afiat va fi chiar valoarea introdusa pentru x deoarece, nainte de afiare, pointerul px a primit ca valoare adresa variabilei x, adresa la care se afla valoarea acesteia (valoare dobndita prin utilizarea funciei cin). Atribuirea *px=y; va modifica valoarea care se afla la adresa memorata de px, valoare care va fi valoarea introdusa de utilizator pentru variabila y. Astfel va fi modificata chiar valoarea pe care o are variabila x. Firete ca era mai simplu s folosim atribuirea x=y; care are acelai efect i ne scutete de de-a mai folosi pointeri, insa exemplul este pur didactic. Operatorul unar * este folosit sub forma *variabila_pointer, valoarea acestei expresii fiind valoarea care se gsete n memorie la adresa memorata de pointerul ce apare ca operand. n concluzie, prin px avem acces la adresa variabilei x, iar prin *px la valoarea variabilei x. Vom spune ca un pointer refera indirect un obiect sau ca pointeaza(arata) la obiectul respectiv. Variabilele pointer pot fi ncadrate ca fiind de tip referina. Exemplul 2. S se calculeze suma a doua numere reale folosind pointeri. #include <iostream.h> void main() 18

{ double x, y, z; double *px, *py, *pz; cin>>x; cin>>y; px=&x; py=&y; pz=&z; *pz=*px+*py; cout<<"Suma este: "<<*pz; }

Pointeri i tablouri
n limbajul C, exista o foarte strnsa legtura intre pointeri i tablouri, astfel ca pointerii i tablourile sunt tratate la fel. Orice program n care apar tablouri poate fi modificat astfel nct s foloseasc pointeri n locul tablourilor. n aceasta seciune vom discuta despre legtura dintre pointeri i vectori (tablouri unidimensionale). Fie urmtoarele declaraii: int a[20]; int *pa; Am declarat o variabila a , care este un vector cu maxim 20 elemente ntregi i un pointer la o variabila de tip ntreg. Dup cum se tie, o valoare int are nevoie de 16 bii pentru a fi memorata, adic 2 bytes ( o variabila int poate retine numere ntregi intre -32768 i 32767, vezi curs Bazele Informaticii). Pentru tabloul a vor fi alocai 2 20=40 bytes consecutivi n memorie adic, pentru primul element a[0] sunt alocai primii 2 bytes, pentru a[1] urmtorii 2 bytes,, pentru a[19] ultimii 2 bytes din cei 40 alocai. Fie atribuirea: pa=&a[0]; Dup aceasta atribuire, pointerul pa conine adresa primului element al vectorului, adic pa pointeaza la nceputul vectorului a. Dac scriem pa=&a[3]; atunci pa va referi elementul al 4-lea din vectorul a, iar *pa va conine valoarea sa. Operaiile care se pot realiza cu pointeri sunt: comparaia adunarea unui pointer cu un ntreg scderea unui ntreg dintr-un pointer Doi pointeri pot fi comparai folosind operatori relaionali. n comparaia: if(p1==p2) cout<<Adrese identice; else cout<<Adrese diferite; se verifica dac adresa memorata de p1 este aceeai cu adresa reinuta de p2, unde p1 i p2 sunt pointeri de acelai tip. Se poate compara un pointer cu valoarea NULL (sau 0). Un pointer are valoarea NULL (valoare nedefinita) dac nu refera nici un obiect. Adunarea unui pointer cu un ntreg este definita numai atunci cnd pointerul refera un tablou (un element al tabloului). Scderea este definita n acelai caz. Exemplul 3. S se citeasc elementele unui vector i s se afieze acestea utiliznd pointeri. #include <iostream.h> void main() { int a[20]; int *pa; int i,n; cout<<"Numrul de elemente= "; cin>>n; for(i=0;i<n;i++) { cout<<"Elementul"<<i<<"="; cin>>a[i]; } //afiarea vectorului folosind pointeri pa=&a[0]; for(i=0;i<n;i++) { cout<<*pa<<"\n"; pa++; } 19

} Prima pate a programului nu conine elemente noi, doar a doua parte meritnd atenie. Mai nti iniializam pointerul pa cu valoarea primului element al vectorului a. Ciclul for conine urmtoarele prelucrri: afieaz valoarea aflata la adresa indicata de pointer; aduna pointerul pa cu 1 Incrementarea pointerului pa are ca efect modificarea adresei memorate n pa. Noua adresa este adresa zonei de memorie corespunztoare elementului urmtor, o adresa cu 2 bytes mai mare dect precedenta. Observam ca mrirea pointerului cu o unitate nseamn de fapt trecerea la urmtorul element din vector. Dac vom introduce pentru n o valoare mai mare dect 20 (numrul maxim de elemente ale vectorului, aa cum reiese din declaraie) atunci pointerul pa va depi zona de memorie alocata vectorului i va referi o adresa la care se pot afla date importante pentru program. Urmrile pot fi imprevizibile, de la blocarea programului pn la blocarea sau nchiderea calculatorului !!!

Noiunea de funcie. Structura i definirea funciilor


Noiunea de funcie este o noiune de mare importanta n informatica, orice limbaj de programare furniznd faciliti de lucru cu funcii. n matematica, funcia era definita ca fiind tripletul (A, B, f), unde: A - domeniul de definiie; B - codomeniul sau domeniul de valori; f - lege, convenie, prin care fiecrui element din domeniul de definiie i se asociaz un unic element din codomeniu; n informatica, noiunea de funcie difer puin de modul matematic de abordare. n limbajul C, orice program trebuie s conin obligatoriu o funcie numita main. Dac prelucrrile ce compun programul sunt foarte complexe, utilizarea unei singure funcii duce la un program greu de neles i depanat. n acest caz este bine ca problema de rezolvat s fie mprita n sub probleme prin a cror combinare s se obin rezolvarea problemei iniiale. Pentru rezolvarea fiecrei sub probleme se poate utiliza cate o funcie separata. Funcia main (programul principal) nu va mai fi de mare ntindere, ea coninnd doar apeluri ctre funciile deja definite. Decizia de a folosi o funcie poate fi luata i n cazul n care anumite prelucrri trebuiesc realizate de mai multe ori, cum se va vedea i n exemplul de mai jos. Exemplul 1. S se calculeze aria a n triunghiuri, dac se cunosc lungimile laturilor acestora. #include <iostream.h> #include <conio.h> #include <math.h> float aria(int a, int b, int c) { float p,s; p=(float)(a+b+c)/2; s=sqrt(p*(p-a)*(p-b)*(p-c)); return s; } void main() { int a,b,c; float S; int i,n; cout<<"Numrul de triunghiuri= "; cin>>n; i=1; for(i=1;i<=n;i++) { cout<<"a="; cin>>a; cout<<"b="; cin>>b; cout<<"c="; cin>>c; S=aria(a,b,c); cout<<"Aria triunghiului "<<i<<" este "<<S<<"\n"; 20

} } Programul trebuie s calculeze aria a n triunghiuri, deci calculul ariei trebuie realizat de n ori. Am definit funcia aria, care calculeaz aria triunghiului cu lungimile laturilor a, b, c prin formula lui Heron. Structura funciei este urmtoarea: antet: float aria(int a, int b, int c) care conine urmtoarele elemente: tipul rezultatului funciei (codomeniul) - rezultatul funciei va fi o valoare de tipul declarat; numele funciei: - numele nu poate fi identic cu un cuvnt cheie lista parametrilor formali - variabilele de care depinde calcularea rezultatului (argumentele funciei); pentru fiecare parametru formal se specifica tipul. corpul funciei: { float p,s; p=(float)(a+b+c)/2; s=sqrt(p*(p-a)*(p-b)*(p-c)); return s; } Corpul funciei conine declaraiile variabilelor utilizate n funcie i prelucrrile realizate de funcie. Variabilele utilizate n funcia aria, numite i variabile locale, sunt semi perimetrul p i aria s. Nu declaram variabilele a, b, c (parametrii formali nu se declara n corpul funciei) i nici nu citim valori pentru ele n cadrul funciei. Orice funcie care are drept codomeniu un tip diferit de tipul void trebuie s conin n corpul funciei o instruciune return expresie; unde expresie este orice expresie corecta n C cu valoare de tipul declarat pentru codomeniu. Instruciunea return este utilizata pentru a semnala faptul ca valoarea funciei este valoarea expresiei. n programul principal (funcia main) se citete numrul de triunghiuri n. Instruciunea for va repeta de n ori (pentru fiecare triunghi) urmtoarele prelucrri: se citesc valori pentru variabilele a, b, c care reprezint lungimile laturilor triunghiului curent; se calculeaz aria triunghiului pentru valorile date; se afieaz valoarea ariei triunghiului curent; Modul de utilizare al funciei aria este interesant. Atribuirea: S=aria(a,b,c); are urmtorul efect; se evalueaz expresia din dreapta atribuirii, expresie ce consta din apelul funciei aria pentru valorile a, ,b, c evaluarea funciei nseamn executarea prelucrrilor din funcie pentru valorile parametrilor formali a, b, c valoarea ntoarsa de funcie este valoarea variabilei s, care apare n return; valoarea este memorata n zona de memorie a variabilei S. Funciile pot fi clasificate astfel: funcii predefinite = funcii deja definite de autorii mediului de programare C i grupate, n funcie de utilitatea lor, n biblioteci numite fiiere header. De exemplu, n biblioteca math.h sunt grupate funciile matematice, n string.h avem funciile de lucru cu iruri de caractere, n iostream.h funcii pentru introducerea i afiarea datelor, n malloc.h i alloc.h funcii pentru alocarea memoriei funcii definite de utilizator = funcii scrise de creatorul unui program pentru acele prelucrri pentru care nu exista funcii predefinite (caz destul de frecvent); O funcie poate s aib drept codomeniu orice tip predefinit scalar (ntreg, caracter sau real), tip compus (uniune sau structura), precum i pointeri la orice tip. Tipul void nseamn ca funcia nu returneaza nici o valoare. Programatorul poate s strng funciile definite de el intr-un fiier header propriu, care se poate include n program prin #include nume_fisier.h.

Apelul funciilor i transferul parametrilor


Orice apariie a numelui funciei nsoit de un numr de valori egal cu numrul parametrilor formali se numete apel al funciei. Puteam apela funcia i n modul urmtor: cout<<aria(3,4,5); 21

Aceasta instruciune are ca efect afiarea ariei triunghiului cu laturile de lungimi 3, 4, 5. Observai ca nu este obligatoriu ca parametrii din apel s fie variabile, ci pot fi expresii. Dac funcia noastr ar aprea intr-o expresie ca 23*aria(3,4,5)-2*aria(2,6,6), evaluarea expresiei ar ncepe cu executarea funciei aria pentru valorile 3, 4, 5 i apoi pentru 2, 6, 6; dup ce se obin rezultatele celor doua apeluri ale funciei se realizeaz evaluarea celorlalte operatori (nmulirile i apoi scderea). Funcia n care apare un apel al altei funcii se numete funcie apelanta. Parametrii sunt de doua tipuri: parametri formali: valoare referina (pointer) parametri efectivi (actuali) Parametrii sunt utilizai pentru a putea transmite din funcia apelanta valorile necesare prelucrrilor efectuate de funcia apelata. Atunci cnd parametrii formali sunt utilizai doar pentru a transmite valori n funcia apelata, aceti parametrii se numesc parametri valoare. Dac se dorete transmiterea ca parametru a unei variabile, n scopul modificrii valorii acesteia astfel nct modificarea s fie disponibila n funcia apelanta, avem de-a face cu un parametru formal referina (se realizeaz printr-o variabila de tip pointer). Pentru a putea apela o funcie, trebuie s precizam, pe lng numele acesteia, valorile parametrilor pentru care se realizeaz apelul (parametri actuali). Numrul parametrilor actuali dintr-un apel de funcie trebuie s fie acelai cu numrul parametrilor formali din definiia funciei apelate i s corespunda ca tip. De exemplu, n programul de mai sus, nu puteam apela funcia aria ca s = aria(4.56, 5, 5); deoarece primul parametru formal din definiia funciei este definit ca de tip int, iar parametrul actual (4.56) este de tip real (incompatibilitate de tip). Nu este obligatoriu s existe parametrii formali intr-o funcie dac nu este nevoie. De asemenea, nu toate funciile ntorc o valoare. Aceste aspecte sunt tratate n urmtoarele exemple. Exemplul 2. S se scrie o funcie care afieaz pe ecran un numr dat de asteriscuri. void asterisc(int nr) { int j; for(j=1;j<=nr;j++) cout<<* ; } Funcia are un singur parametru formal, un ntreg nr reprezentnd numrul de asteriscuri ce trebuie afiate. Funcia poate fi apelata prin asterisc(10); care are ca efect afiarea a 10 asteriscuri. Funcia nu ntoarce nici o valoare, deoarece nu este necesar (n-are sens s ntoarcem vreo valoare), deci codomeniul va fi tipul void. Din moment ce funcia nu ntoarce vreo valoare, nu se va mai utiliza return. Exemplul 3. Scriei o funcie care s afieze un mesaj. void mesaj( ) { cout<<Traiasca Reforma !!!; } Funcia mesaj nu ntoarce nici o valoare i nici nu conine parametrii formali (nu exista valori care s fie necesare execuiei funciei). Apelul funciei se va face prin: mesaj(), exact ca i pentru funcia pre definit clrscr( ). Dac am dori ca funcia s afieze un mesaj dat, obinem: void mesaj(char s[80]) { cout<<s; } Apelul funciei poate fi: mesaj(Triasc!!!); Exemplul 4. Scriei o funcie care stabilete dac un numr este prim. #include <iostream.h> int este_prim(int n) { int j; int este; este=1; //presupunem ca numrul este prim for(j=1;j<=n-1;j++) if(n%j==0) este=0; return este; } 22

void main() { int numr; cout<<Introduceti numrul=; cin>>numr; if(este_prim(numr)!=0) cout<<Numrul este prim !; else cout<<Numrul nu este prim !; } Exerciiul 1: Folosii funcia este_prim pentru a afia toate numerele prime mai mici dect un numr ntreg dat. Exemplul 5. Scriei o funcie care s citeasc un vector de numere ntregi. void citeste(int a[30], int n) { int k; for(k=0;k<n; k++) cin>>a[k]; } Funcia are doi parametri: variabila de tip vector care va retine numerele citite i variabila n, care ne spune cate elemente trebuiesc citite. Funcia main poate s arate astfel: void main () { int b[30]; int n; cout<<n=; cin>>n; citeste(a,n); } Exerciiul 6: Scriei o funcie pentru afisarea elementelor unui vector i adugai-o exemplului precedent. Exemplul 7. Scriei o funcie care calculeaz suma elementelor dintr-un vector. int suma(int a[40], int n) { int k; int s; s=0; for(k=0;k<n;k++) s=s+a[k]; return s; } Este necesar s introducem ca parametru i numrul de elemente din vector n. Exerciiul 8: Folosii funcia de mai sus n programul de la exerciiul precedent. Exemplul 9. Scriei o funcie care calculeaz ax, unde a real i x ntreg pozitiv. float putere(float a, int x) { int k; int p; //retine puterea p=1; for(k=1;k<=x;k++) p=p*a; return p; }

23

Exerciiul 10. Modificai funcia din exemplul 7 astfel nct s poat ridica pe a i la puteri negative. Exemplul 11. Scriei o funcie pentru a calcula cel mai mare divizor comun a 2 numere ntregi folosind algoritmul lui Euclid. #include <iostream.h> int cmmdc(int m, int n) { int r; int temp; if(n>m) { temp=m; m=n; n=temp; } do { r=m%n; m=n; n=r; }while(r!=0); return m; } void main() { int a,b; cout<<"Primul numr="; cin>>a; cout<<"Al doilea numr="; cin>>b; cout<<cmmdc(a,b); } Exemplul 12 S se scrie o funcie care verifica dac un ntreg x aparine unui vector v. int cauta(int v[50], int n) { int k; int apartine; apartine=0; //se presupune ca x nu este element n v for(k=0;k<n;k++) if(v[k]==x) apartine=1; return apartine; } Exemplul 13. S se scrie o funcie care realizeaz suma a doua matrice cu m linii i n coloane. void suma_mat(int a[20][20], int b[20][20], int c[20][20], int m, int n) { int j, k; //variabile contor n for for(j=0;j<m;j++) for(k=0;k<n;k++) c[j][k]=a[j][k]+b[j][k]; } Parametrii de care depinde rezolvarea sarcinii sunt: a - prima matrice b - a doua matrice c - matricea suma (rezultatul sumei) m - numrul de linii n - numrul de coloane Exerciiul 5. S se scrie funcia main corespunztoare funciei de mai sus, precum i funcii pentru citirea i afiarea unei matrice. O situaie interesanta apare atunci cnd vrem ca variabilele ce apar ca parametri formali s poat fi modificate n cadrul funciei, modificrile fiind disponibile n funcia apelanta. 24

S luam urmtorul exemplu: Exemplul 14. S se scrie o funcie care interschimb valorile a doua variabile ntregi. Varianta urmtoare este greita: void schimba(int x, int y) { int temp; temp=x; x=y; y=temp; } void main() { int a, b; cin>>a; cin>>b; schimba(a,b); cout<<a; cout<<b; } La prima vedere funcia pare corecta, insa lucrurile stau tocmai pe dos. Dac introducem valorile 5 pentru a i 7 pentru b, programul ar trebui s schimbe intre ele valorile celor doua variabile (a trebuie s devin 7, iar b s devin 5). Programul de mai sus nu va realiza acest lucru. Explicaia este ca, atunci cnd parametri formali sunt parametri valoare, chiar dac se modifica valoarea lor n cadrul funciei aceste modificri nu vor avea efect n funcia apelanta (n cazul nostru, n funcia main nu va fi sesizabila schimbarea realizata n funcia schimba). Problema se poate rezolva dac parametrii din funcia schimba vor fi parametri referina (pointeri). Varianta corecta este urmtoarea: void schimba(int *x, int *y) { int temp; temp=*x; *x=*y; *y=temp; } Singura schimbare din funcia main este apelul funciei, care devine schimba(&a, &b); Explicaia corectitudinii acestei variante este aceea ca se lucreaz cu adresele variabilelor, deci orice modificare a coninutului zonelor de memorie alocate variabilelor x i y va fi resimit i n funcia main. Parcurgei din nou exemplul 10 i privii cu atenie antetul funciei suma_mat. Parametrul formal c este o matrice calculata ca suma matricelor a i b, deci valoarea elementelor lui c este modificata n cadrul funciei, dar parametrul formal este corect ? Rspunsul este afirmativ deoarece, dup cum tii, tablourile sunt tratate exact ca i pointerii, deci tablourile care apar ca parametrii formali se considera parametri referina.

Variabile locale i variabile globale


Un program C este compus din una sau mai multe funcii (cel puin funcia main) repartizate n unul sau mai multe fiiere. Structura de principiu a unui program C este urmtoarea: directive de preprocesare (de exemplu #include) declaraii de tipuri i variabile globale (imediat dup directivele de preprocesare, n afara oricror funcii) definiii de funcii funcia main() Toate variabilele declarate n afara oricrei funcii se numesc variabile globale, acestea putnd fi utilizate n orice funcie din program. Variabilele definite n interiorul unei funcii se numesc variabile locale i pot fi utilizate doar n funcia unde au fost declarate. Putem declara o variabila k n mai multe funcii, fr s fie influenata corectitudinea programului. Este de preferat ca variabilele globale s fie n numr limitat, doar atunci cnd este nevoie neaprata. Folosirea neatenta a variabilelor globale poate duce la erori greu depistabile.

25

Bibliografie Suport de curs Universitatea de Vest Vasile Goldis Liviu Nergrescu Limbajul C++ Editura Albastra Cluj Napoca 1999 Doina Hrinciuc Logofatu C++ probleme rezolvate si algoritmi Editura Polirom 2001 Ana Intuneric Cristina Sichim Informatica Teste grila C/C++ Polirom 2003 Mariana Milosescu Informatica Editura Didactica si Pedagocica 2005 UVVG ARAD Suport de curs pentru forma de invatamant ID (preluare de pe CD)

26

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