Sunteți pe pagina 1din 31

CAPITOLUL 1. ALGORITMI 1.1.

Noiuni generale
Noiunea de algoritm este primar, nu se poate defini. n schimb algoritmul poate fi descris, n esen putnd s l privim ca pe o succesiune de etape care se pot aplica mecanic, n vederea obinerii unui anumit rezultat. De exemplu algoritmul prin care se adun dou fracii presupune etapele: fraciile se aduc la acelai numitor, se fac nmulirile, adunrile, apoi fracia este simplificat. Se pot face urmtoarele observaii, valabile pentru orice algoritm: 1. Se pornete de la ceva (datele de intrare) i se dorete obinerea unui anumit rezultat (datele de ieire). n exemplul de mai sus, se pornete de la cele dou fracii (datele de intrare) i se obine suma lor (aceasta reprezentnd singura dat de ieire). 2. Se opereaz cu anumite "obiecte" asupra crora sunt permise anumite operaii. n exemplul de mai sus, obiectele cu care se opereaz pot fi valori numerice sau simbolice (cu ajutorul crora se reprezint numrtorul i numitorul fiecrei fracii), iar operaiile sunt descrise de reguli matematice. 3. n cele mai multe cazuri cel care elaboreaz algoritmul este diferit de executant. n cele ce urmeaz se va trata numai cazul elaborrii algoritmilor pentru programarea calculatoarelor, executantul fiind calculatorul iar cel care elaboreaz algoritmul fiind programatorul. Frecvent intervine nc o persoan, diferit de programator, utilizatorul, creia i este necesar doar o pregtire minim de specialitate n informatic, trebuind doar s utilizeze programul obinut i s beneficieze de avantajele lui.

x pentru x < 0 . Considerm pentru exemplificare urmtoarea funcie: f:R->R, f ( x) = 2 x pentru x 0 Se cere calculul valorilor pe care le ia funcia f pentru fiecare x dintr-un un set de 10 valori, furnizate ca i date de intrare. Pentru fiecare dintre cele 10 valori trebuie executat urmtorul grup de operaiuni (grup pe care l vom nota G1). Compararea lui x cu 0; n funcie de rezultatul comparaiei, alegerea ramurii care furnizeaz expresia de calcul pentru f i calculul lui f; Afiarea perechii corespunztoare (x,f). Executarea manual a acestor operaiuni este plicticoas, supus erorilor i mare consumatoare de timp. Problema se poate rezolva mai repede i fr erori cu ajutorul unui program. Acesta se obine prin codificarea algoritmului corespunztor ntr-un limbaj de programare. n linii mari, etapele obinerii unui algoritm sunt: 1. Identificarea datelor de intrare i a celor de ieire. n exemplul nostru, datele de intrare sunt x1, x2,..., x10 iar cele de ieire sunt cele 10 perechi de forma (x,f). 2. Elaborarea algoritmului de rezolvare a problemei. Algoritmul specific operaiile pe care calculatorul trebuie s le efectueze pentru ca, pornind de la datele de intrare s obin datele de ieire. Pentru exemplul nostru, aceste operaii au fost prezentate deja (grupul de operaii G1). Algoritmul a fost descris n limbaj natural, n practic utilizndu-se limbaje de tip pseudocod sau, mai rar, scheme logice. Algoritmii se scriu n pseudocod pentru a se elimina diferenele generate de regulile proprii fiecrui limbaj. Un limbaj de tip pseudocod are caracteristicile: a) Nu are multe reguli, dar seamn cu orice limbaj de programare. b) Un algoritm redactat n pseudocod nu poate fi rulat direct pe calculator. Trebuie convertit n limbajul de programare dorit. c) Permite o conversie uoar n orice limbaj de programare. 3. Transpunerea algoritmului ntr-un limbaj de programare (Pascal, C, etc.) 4. Testarea programului i corectarea sa pn cnd acesta funcioneaz corect. Observaie Algoritmul poate fi codificat direct n limbajul de programare dorit, dac programatorul are suficient experien.

1.2. Enunul unei probleme, date de intrare i de ieire, etapele rezolvrii unei probleme

1.4. Obiectele cu care lucreaz algoritmii i operaii permise


1.4.1. Date Dup tipul lor, datele se pot clasifica n 3 categorii mari: a) Numerice, cu tipurile ntreg, respectiv real. n informatic printr-o dat real se nelege o valoare cu un numr finit de zecimale, iar virgula care separ partea ntreag de cea zecimal se reprezint prin simbolul "." (punct zecimal). b) Logice. O astfel de dat poate lua doar dou valori: TRUE i FALSE. c) ir de caractere. O astfel de dat este reprezentat de un ir de caractere cuprins ntre apostroafe. Un exemplu de dat de acest tip este "aaa-rfger8 fff". Observaie O categorie aparte de date este format din constante, care pot avea oricare dintre tipurile prezentate. Constantele nu pot fi citite i nici obinute din calcule. C1/ 1

n exemplul de la paragraful 1.2 operaiile din grupul G1 fac referire la xi pentru i=1,10 folosind notaia unic x. Asemntor nu s-a folosit f(xi) , ci simplu f. Acest lucru este posibil deoarece atunci cnd se calculeaz f(x1) n x este memorat x1 iar n f este memorat f(x1), cnd se calculeaz f(x2) n x este memorat x2 iar n f este memorat f(x2), .a.m.d. Pentru algoritmul respectiv x i f sunt variabile. Variabilele pot fi imaginate ca nite cutiue care rein date. Principalele caracteristici ale unei variabile sunt: 1. Are un nume. 2. Are un tip, care determin natura datelor care pot fi reinute de variabila respectiv. Se folosesc notaiile integer pentru tipul ntreg, real pentru tipul real, boolean pentru variabilele logice i respectiv string pentru variabilele de tip ir de caractere. 3. Trebuie declarat (anunat) nainte de a o utiliza. Exemplu: integer a; boolean c,d; n acest exemplu s-au declarat variabilele de tip ntreg a i respectiv de tip logic c,d. 4. I se rezerv spaiu de memorie n memoria intern a calculatorului.

1.4.2. Variabile

1.4.3. Expresii
n scopul efecturii calculelor, algoritmii folosesc expresii. O expresie este alctuit din unul sau mai muli operanzi, legai ntre ei prin operatori. Operanzii pot fi constante sau variabile. Operatorii desemneaz operaiile care se execut spre a obine rezultatul i pot fi de 3 feluri: aritmetici, relaionali i respectiv logici. Modul n care se face legtura ntre operanzi i operatori respect anumite reguli sintactice. n timpul execuiei, expresiile sunt evaluate (se efectueaz calculele impuse de operanzi). Exemplul 1. Fie dou variabile de tip ntreg: a reine valoarea 1 i b reine valoarea 3. Considerm expresia: n aceast expresie s-au marcat prin cerculee operanzii, iar + i * sunt operatori. n urma evalurii expresiei se obine valoarea ntreag 16. Exemplul 2. Fie a o variabil ntreag ce reine valoarea 3 i b o variabil real ce reine valoarea 1.9. n urma evalurii expresiei

se obine valoarea logic TRUE.

1.4.3.1. Operatori aritmetici


Operatorii aritmetici sunt de dou feluri: a) Operatori unari. Exist doi operatori unari: + i respectiv -. Acetia acioneaz asupra unui singur operand, care poate fi o variabil sau o constant de tip numeric. Operandul se afl totdeauna la dreapta operatorului unar. Exemplu: Fie a o variabil ntreag ce reine valoarea 2. Atunci evaluarea expresiei - a are ca rezultat valoarea - 2, pe cnd evaluarea expresiei - - a are ca rezultat valoarea 2. b) Operatori binari . Urmtorii operatori sunt de tip binar: +, - , * , / , div, mod. Aceti operatori apar n construcii sintactice de forma: O1 OB O2 unde prin O1 i respectiv O2 s-au notat operanzii, iar prin OB s-a notat operatorul binar. b1) Operatorul + semnific adunarea. ntr-o construcie de forma O1+O2, O1 i O2 pot fi de tip ntreg sau real. Dac cel puin unul dintre cei doi operanzi este real, rezultatul evalurii expresiei O1+O2 este de tip real, altfel este de tip ntreg. Exemplu Dac c este o variabil de tip real ce conine valoarea 2.3, atunci expresia c+1 produce valoarea 3.3, rezultatul fiind deci de tip real. b2) Operatorul - semnific scderea. b3) Operatorul * semnific nmulirea. Observaie La operatorii - i respectiv * se aplic aceleai reguli sintactice ca i la operatorul +. b4) Operatorul / semnific mprirea real. Operanzii pot fi de tipul ntreg sau real dar totdeauna rezultatul este de tip real. Exemplu 3/2 are ca rezultat valoarea real 1.5, iar 4/2 are ca rezultat valoarea real 2.0. b5) Operatorul DIV semnific mprirea ntreag. Apare n construcii sintactice de forma O1 DIV O2 .O1 i O2 sunt obligatoriu de tip ntreg, rezultatul evalurii acestei expresii fiind partea ntreag a ctului obinut dup mprirea operanzilor. Observaie DIV furnizeaz rezultatul corect numai dac ambele valori sunt numere naturale. Exemplu 14 DIV 5 furnizeaz rezultatul 2. C1/ 2

b6) Operatorul MOD are semnificaia de rest al mpririi pentru numere ntregi. Apare n construcii sintactice de forma O1 MOD O2. O1 i O2 sunt obligatoriu de tip ntreg. Exemplu 14 DIV 5 furnizeaz rezultatul 4.

1.4.3.2. Operatori relaionali


Exist 5 operatori relaionali: >, >=, <, <= i =. Aceti operatori sunt totdeauna binari i apar n construcii sintactice de forma: O1 OR O2, unde O1 i O2 sunt operanzii iar OR este unul dintre cele 5 tipuri de operatori relaionali. Operanzii pot fi variabile sau constante de oricare dintre tipurile prezentate anterior. n acest capitol se va studia numai modul de acionare al operatorilor relaionali asupra operanzilor de tip numeric (ntreg sau real). Rezultatul evalurii unei expresii E de forma E=O1 OR O2 este totdeauna o valoare logic. De exemplu dup evaluarea expresiei 2<3 se obine valoarea TRUE.

1.4.3.3. Operatori logici


Se definesc dou tipuri de operatori logici: unari i binari. Exist un singur operator logic unar , i anume NOT (negare), care acioneaz astfel: NOT(TRUE)=FALSE i respectiv NOT(FALSE)=TRUE. Toi ceilali 3 operatori logici sunt binari, definindu-se operatorii binari: AND, OR i respectiv XOR. Acetia apar n construcii sintactice de forma:

O1 OL O2,
unde O1 i O2 sunt operanzii iar OL este unul dintre cele 3 tipuri de operatori logici. O1 i O2 pot fi de tip numeric sau logic, dar n cele ce urmeaz ne vom referi numai la operanzi de tip logic. n tabelul urmtor se centralizeaz rezultatele evalurii expresiilor de tip E=O1 OL O2 folosind convenia: 0 FALSE i respectiv 1- TRUE. Se observ c: O1 O2 O1 AND O2 O1 OR O2 O1 XOR O2 - la aplicarea operatorului AND se obine TRUE 0 0 0 0 0 numai dac ambii operanzi sunt TRUE; 0 1 0 1 1 - la aplicarea operatorului OR se obine FALSE 1 0 0 1 1 numai dac ambii operanzi sunt FALSE; 1 1 1 1 0 - la aplicarea operatorului XOR se obine TRUE numai dac operanzii difer.

1.4.3.4. Prioritatea operatorilor


Operatorii sunt mprii n 4 grupe dup prioritate. Cei din grupa 1 au prioritate maxim, apoi prioritatea scade atunci cnd numrul grupei crete, cei din grupa 4 avnd prioritatea minim. mprirea operatorilor dup grupe de prioritate se face astfel: grupa 1 conine operatorii UNARI; grupa 2 conine operatorii MULTIPLICATIVI (AND, *, /, DIV, MOD); grupa 3 conine operatorii ADITIVI (OR, XOR, +, -); grupa 4 conine cei 5 operatori RELATIONALI.

1.4.3.5. Evaluarea expresiilor


Pentru a nelege modul n care se evalueaz o expresie E vom prezenta urmtoarele 4 cazuri distincte: Cazul 1 Expresia E nu conine paranteze i este format din mai muli operanzi, legai prin operatori de acelai tip. Expresiile de acest tip se evalueaz de la stnga la dreapta. Exemplu: Fie variabilele a i b de tip ntreg, a=1 i b=3. Expresia E=a+1+b se evalueaz n ordinea descris de numerele ncercuite din figura 1.1 Cazul 2 Expresia E nu conine paranteze. n expresie intervin operatori care nu sunt de acelai tip dar au aceeai prioritate. Ca i n cazul 1, expresia se evalueaz de la stnga la dreapta. Exemplu: expresia 2*3 div 4 se evalueaz ca n figura 1.2. Cazul 3 Expresia E nu conine paranteze. n interiorul su apar mai muli operatori care au prioriti diferite. n acest caz se efectueaz mai nti, de la stnga la dreapta, operaiile descrise de operatorii cu prioritate maxim. Procedeul se reia pn cnd sunt efectuate toate operaiile cerute de operatorii cu cea mai mic prioritate existeni n expresie. Exemplul 1 Expresia 2+3*5 6/2 se evalueaz ca n figura 1.3, cu observaia c, datorit operatorului de mprire real se va obine un numr real. Exemplul 2 Expresia FALSE OR TRUE AND TRUE se evalueaz ca n fig. 1.4. Cazul 4 Acesta este cazul cel mai general. Comparativ cu cazul 3, aici apar i paranteze. Pentru evaluarea unei expresii care se ncadreaz n acest caz se procedeaz astfel: se parcurge de la stnga la dreapta expresia pentru a identifica prima parantez deschis. Apoi se continu parcurgerea de la stnga la dreapta, C1/ 3

putnd exista dou cazuri: a) Se detecteaz nti paranteza de nchidere. Se evalueaz expresia dintre paranteze ca i n cazul 3. b) Se detecteaz nc una (sau mai multe) paranteze de deschidere. Dac s-au detectat n paranteze de deschidere, se evalueaz nti expresia delimitat la stnga de cea de a n-a parantez, apoi cea delimitat la stnga de cea de a (n-1)-a parantez, etc., aplicndu-se regulile de la cazul 3. Exemplu: Expresia 3+5*(4 3/(2+1)) se evalueaz ca n figura 1.5.

1.4.3.8. Tipul expresiilor


La evaluarea expresiilor se obine un rezultat. Tipul rezultatului stabilete tipul expresiei. Acesta este determinat de tipurile operanzilor i de operatorii aplicai n cadrul expresiei: Exemple: tipul expresiei 4>2 este boolean, tipul expresiei 1+2 este integer, iar tipul expresiei 1.3+2 este real.

1.5. Operaiile pe care le efectueaz un algoritm 1.5.1. Operaii de intrare/ieire


Prin operaia de intrare (citire) se nelege preluarea unei date de la un dispozitiv de intrare ctre memoria intern a calculatorului, n zona de memorie rezervat pentru aceasta, adic n variabila care memoreaz data respectiv. Dispozitivele de intrare cele mai cunoscute sunt: tastatura (care este i cel mai des utilizat), o unitate de disc (flexibil, CD-ROM, hard disk), etc. Prin operaia de ieire (scriere) se nelege preluarea unei date din memoria intern a calculatorului (adic din variabila care o memoreaz) ctre un dispozitiv de ieire. Cele mai cunoscute dispozitive de ieire sunt: monitorul, o unitate de disc, imprimanta, etc. n pseudocod vom folosi cuvntul cheie read pentru a desemna o operaie de citire i respectiv vom folosi cuvntul cheie write pentru a desemna o operaie de scriere. integer a; Exemplu: Presupunem c dispozitivul de intrare este tastatura iar cel de ieire este monitorul. read a; Atunci algoritmul pentru citirea i apoi afiarea unui numr ntreg este descris in caseta 1_5_1_1. write a; n acest exemplu se observ c pentru nceput se declar variabila a, care este de tip ntreg. Apoi, prin instruciunea read a se ateapt introducerea de la tastatur a unei date de tip Caseta 1 _5_1_1 ntreg. Dup introducerea datei, aceasta este scris (afiat) pe monitor. Observaii integer a; 1. Dup scriere, coninutul variabilei rmne nemodificat. read a; 2. La o nou citire, coninutul vechi al variabilei se pierde. read a; Exemplu Presupunem c introducem dou numere ntregi de la tastatur (de exemplu 7 i respectiv write a; 20, n aceast ordine). Se execut secvena de instruciuni din caseta 1_5_1_2: Caseta 1 5 1 2 n urma primei citiri a a primit valoarea 7, n urma celei de a doua citiri a a primit valoarea 20, cu care rmne. Deci se va afia 20. 3. Se pot citi mai multe variabile cu o singur operaie read i se pot tipri valorile reinute de mai real a,b,c; multe variabile folosind o singur operaie write. write c,a,b; Exemplu Fie secvena de instruciuni din caseta 1_5_1_3: Caseta 1 5 1 3 Dac introducem setul de valori numerice 1.2, -0.7, 1.5, a va reine 1.2, b va reine -0.7 i c va reine 1.5. n urma execuiei instruciunii write c,a,b, pe monitor vor apare 1.5, 1.2, -0.7. 4. O practic des ntlnit n programare este aceea prin care o instruciune de citire este precedat de afiarea unui mesaj pe ecran, prin care utilizatorul este atenionat c se ateapt introducerea unei date sau a unui set de date.

1.5.2. Atribuiri
Prin operaia de atribuire se reine o anumit dat ntr-o variabil. Aceast operaie are 3 forme: Forma 1 v:=dat unde v este numele unei variabile de un tip oarecare, iar dat reprezint o valoare de un tip oarecare. C1/ 4

Tipul variabilei trebuie s coincid cu tipul valorii atribuite (ex. 1, caseta 1_5_2_1), cu o singur excepie: unei variabile de tip real i se poate atribui o dat de tip ntreg (ex. 2, , caseta 1_5_2_1). Forma 2 Ex. 1 Ex. 2 v1:=v2 real b; real d; unde v1 i v2 sunt nume de variabile. Cu o singur excepie (aceeai de la forma 1), b:=-7.25; d:=7; tipul variabilelor trebuie s coincid. Efectul operaiei de atribuire este c variabila Caseta 1_5_2_1 v1 va reine coninutul variabilei v2. Dup efectuarea operaiei, coninutul variabilei v2 rmne nemodificat, iar coninutul iniial al variabilei v1 se pierde. Ex. 1 Ex. 2 n ex. 1 (caseta 1_5_2_2) iniial a coninea valoarea 2, iar dup atribuirea a:=b integer a,b; integer a,b; att a ct i b vor conine valoarea 3. n ex. 2, dup atribuirea b:=a att a ct i b a:=2; b:=3; a:=2; b:=3; vor conine valoarea 2. a:=b; b:=a; Este foarte important de reinut c atribuirea a:=b nu are acelai efect cu Caseta 1_5_2_2 atribuirea b:=a. Forma 3 v:=expresie n acest caz, nti se evalueaz expresia, iar valoarea obinut este atribuit variabilei v. Observaie Dup atribuire, coninutul variabilelor care sunt operanzi n expresia din membrul drept rmne nemodificat. Excepie face, eventual, variabila v dac ea figureaz i ca operand n expresie. Exemplul 1 Dup evaluarea expresiei v:=a+2*b/c, singura variabil care se modific este v, coninutul variabilelor a,b i c care particip ca i operanzi n expresie rmnnd nemodificat. Formele 1 i 2 sunt de fapt particularizri ale formei 3. Exemplul 2 Fie o variabil v de tip ntreg care conine valoarea 7. Dup atribuirea v:=v+1, variabila v va conine valoarea 8. nti s-a evaluat valoarea expresiei v+1=8, apoi v a primit aceast valoare, distrugndu-se, prin suprascriere, vechiul coninut al lui v. O eroare des ntlnit este atunci cnd atribuirea este confundat cu o ecuaie, n care se egaleaz cei doi membri. Pentru cei care fac aceast confuzie, o operaie de forma v:=v+1 este eronat, conducnd la inepia 0=1! Atribuirea nu trebuie confundat cu o ecuaie. Exemple tipice de utilizare a atribuirii 1. Iniializri S:=0; Stabilirea valorilor cu care anumite variabile intr n calcule se numete iniializare. P:=1; Iniializrile se fac cu ajutorul instruciunii de atribuire. Dou exemple sunt furnizate n Caseta 1_5_2_3 caseta 1_5_2_3. Aceste dou exemple sunt tipice pentru cazul n care S va reine valoarea unei sume iar P va reine valoarea unui produs, pentru c 0 este elementul neutru pentru adunare iar 1 este elementul neutru pentru nmulire. 2. Calcule Exist n principal dou forme n care atribuirea intervine n calcule Forma direct Unei variabile (o vom nota v) i se atribuie o expresie n care printre operanzi nu se regsete i ea nsi. Exemplu v:=a+b; Forma indirect Variabilei v i se atribuie o expresie n care particip i ea nsi ca operand: Exemplu v:=a+v*x. 3. Copiere De multe ori este necesar ca o valoare reinut de o variabil s fie reinut i de o alt variabil. Un caz particular, des ntlnit, este interschimbarea coninutului a dou variabile. Fie x,y dou variabile al cror coninut dorim s l interschimbm. Dac de exemplu iniial x coninea valoarea 3 i y coninea valoarea 4, dup interschimbare x va conine valoarea 4 iar y va conine valoarea 3. Un programator neatent ar putea utiliza secvena greit de instruciuni din caseta 1_5_2_4 (a). x:=y; y:=x; Rezultatul execuiei acestei secvene este: dup ce se execut x:=y, x primete y:=x; x:=y; valoarea 4, pierzndu-i vechiul coninut. Apoi, dup ce se execut y:=x, y primete tot (a) (b) valoarea 4, cea memorat actual de x. n consecin, n loc s obinem interschimbarea Caseta 1_5_2_4 coninutului celor dou variabile, obinem egalarea coninutului acestora cu valoarea memorat de y. Dac am fi scris aa cum este descris n 1_5_2_4 (b), efectul ar fi fost egalarea coninutului celor dou variabile cu y! O secven corect de instruciuni trebuie s utilizeze o variabil intermediar m, n care s se salveze coninutul uneia dintre variabile nainte ca aceasta s-i piard coninutul, urmnd ca apoi cealalt variabil s foloseasc valoarea variabilei intermediare. Ambele posibiliti de rezolvare a interschimbrii sunt prezentate n cele ce urmeaz: Varianta 1 Varianta 2 m:=x; m:=y; x:=y; y:=x; y:=m; x:=m; C1/ 5

Cursul 2 1.5.3. Operaii de decizie


if expresie logic then operaia1 else operaia 2 end if Fig. 1.6 integer a,b; read a,b; if a>b then write a else write b endif Fig. 1.7 real a,b,c,d,E; read a,b,c,d; if (c+d)>0 then E:=a+b else if (c+d)=0 then E:=a-b else E:=a*b end if end if; write E; Fig. 1.8 n pseudocod i n majoritatea limbajelor de programare operaia de decizie este desemnat folosind cuvntul cheie if. n pseudocod, forma general a operaiei de decizie este descris n fig. 1.6. (s-au subliniat cuvintele cheie). Modul de execuie este urmtorul: 1. Se evalueaz expresie logic (o vom nota cu E). 2. Dac rezultatul evalurii lui E este TRUE, se execut operaia 1 ; dac acest rezultat este FALSE, se execut operaia 2. Exemplul 1. Se citesc dou numere ntregi, a i b. Se cere s se tipreasc cel mai mare dintre ele. Secvena de instruciuni scris n pseudocod care realizeaz acest lucru este descris n fig. 1.7: Exemplul 2. Se citesc 4 valori reale a,b,c,d. S se evalueze expresia:

a + b daca c + d > 0 E = a b daca c + d = 0 a * b daca c + d < 0


Secvena de instruciuni scris n pseudocod care realizeaz acest lucru este descris n fig. 1.8. Dac presupunem ca exemplu numeric setul de date de intrare a=1, b=2, c=3 i d=4, atunci rezultatul afiat este 3. Observaie Testul if (c+d)<0 lipsete deoarece atunci cnd (c+d) nu este nici mai mare i nici egal cu 0, nu mai exist dect o singur posibilitate, anume aceea ca (c+d) s fie mai mic dect 0. Forma particular a operaiei if se folosete atunci cnd pe ramura else nu mai trebuie executat nici o operaie. Aceast form particular se codific aa cum este descris de fig. 1.9: Modul de execuie este urmtorul: 1. Se evalueaz expresia logic notat cu E. 2. Dac rezultatul evalurii lui E este TRUE, se execut operaie.

CAPITOLUL 2. PRINCIPIILE PROGRAMRII STRUCTURATE


2.1. Generaliti

Un algoritm poate fi reprezentat n mod simplificat ca n fig. 2.1, ordinea de execuie a operaiilor find indicat de sgeat. O problem special apare atunci cnd o anumit operaie trebuie executat de mai multe ori. n exemplul urmtor se propune obinerea (prin calcul iterativ) a sumei primelor 1000 de numere naturale. Nu se va aplica formula direct S=n*(n+1)/2. O prim soluie este prezentat n fig. 2.2. Soluia prezentat n aceast figur prezint dezavantajul scrierii repetate. n acest context a aprut operaia de salt , a crei sintax este if E then GOTO etichet. operatie Atunci cnd, pe parcursul execuiei , se ntlnete aceast operaie, controlul execuiei se end if transfer la linia marcat prin "etichet". Folosind GOTO, algoritmul propus ca exemplu se rescrie aa cum este prezentat n fig. 2.3: Fig. 1.9 n acest fel am programat un ciclu, adic o secven de operaii care se repet. Utilizarea operaiei GOTO prezint anumite dezavantaje, un astfel de algoritm fiind greu de urmrit chiar i pentru cei care l-au elaborat. Datorit dezavantajelor operaiei GOTO a aprut conceptul de programare structurat, care a condus la uurarea scrierii

algoritmilor, respectiv a citirii (urmririi) lor. Definiie Prin structur nelegem o anumit form de mbinare a operaiilor cu care lucreaz algoritmii. n cadrul programrii structurate, algoritmii se elaboreaz prin utilizarea exclusiv a anumitor structuri. Programarea structurat nu nseamn doar eliminarea operaiei de salt. nseamn de fapt un alt mod de gndire a algoritmilor. Curs2/ 1

Astfel, problema pentru care se elaboreaz algoritmul se descompune dup structurile permise, rezultatul descompunerii fiind mai multe subprobleme. La rndul lor, subproblemele se descompun din nou, dup aceleai reguli, pn se ajunge la operaii elementare.

2.2. Structuri de baz i descrierea lor n pseudocod


Exist 3 tipuri de structuri de baz utilizate n descrierea algoritmilor: liniar, alternativ i respectiv repetitiv.

2.2.1. Structura liniar


Definim structura liniar astfel: - orice operaie (citire, scriere, atribuire, decizional) considerat ca un tot unitar se constituie ntr-o structur liniar; - dac S1 i S2 sunt structuri (de orice tip) atunci secvena

S1 S2

reprezint o structur liniar.

Pornind de la aceast definiie, se ajunge la forma de structur liniar din fig. 2.1. Considerm acum urmtoarea problem: se citete un numr natural format din 3 cifre. S se afieze suma cifrelor sale. (Dac de exemplu numrul introdus este 217, se va afia 10, provenit prin nsumarea 2+1+7). Pentru rezolvarea acestei probleme, apelm la operatorii aritmetici div i mod. O soluie a acestei probleme este reprodus n cele ce urmeaz: Observaii se iniializeaz suma se adun ultima cifr se rein doar primele cifre din numr,eliminndu-se ultima se adun penultima cifr se rein doar primele cifre din numrul trunchiat, eliminndu-se ultima se adun prima cifr if E then S1 else S2 end if integer x,S; read x; S:=0; S:=S+x mod 10; x:=x div 10; S:=S+x mod 10; x:=x div 10; S:=S+x mod 10; write S; Exemplu numeric S:=0; 217 mod 10=7, deci S:=0+7=7 x:=217 div 10, deci x:=21 21 mod 10=1, deci S:=7+1=8 x:=21 div 10, deci x:=2 2 mod 10=2, deci S:=8+2=10

Se observ caracterul repetitiv al operaiilor S:=S+x mod 10, respectiv x:=x div 10. Algoritmul poate fi rescris mai eficient, folosind structuri repetitive, descrise n paragraful 2.2.3.

2.2.2. Structura alternativ

Definim structura alternativ astfel: dac S1 i S2 sunt dou structuri i E este o expresie logic, atunci secvena reprezentat n fig. 2.4 este o structur alternativ. Mecanismul de execuie al acestei structuri este urmtorul: Fig. 2.4. - se evalueaz expresia E - dac E are valoarea TRUE, se execut S1, altfel se execut S2. integer a,b,S1,comanda; Observaie Structura alternativ reprezint o generalizare a operaiei decizionale. Caracterul de real x,y,S2; generalitate provine din faptul c fie sub then, fie sub else pot exista mai multe operaii, nu ca n read comanda; cazul operaiei decizionale, cnd era admis o singur operaie. if comanda=0 Ca i n cazul operaiei decizionale, i structura alternativ admite o form particular, then reprodus mai jos: read a,b; S1:=a+b; if E write S1; then S else end if read x,y; Exemplu Se citete un numr natural, care este reinut n variabila comanda. Dac numrul S2:=x+y; citit este 0, se vor citi numerele ntregi a i b i se va tipri suma lor (reinut de variabila S1). n write S2; cazul n care numrul citit este diferit de 0, se vor citi numerele reale x i y i se va tipri suma lor end if (reinut de variabila S2). Soluia propus este reprodus n fig. 2.5. Fig. 2.5

2.2.3. Structura repetitiv


Structura repetitiv poate apare n mai multe variante, descrise n cele ce urmeaz: 1. Structur repetitiv condiionat anterior (cu test iniial), existnd dou tipuri de astfel de structuri: a) Structura WHILE DO; b) Structura FOR. 2. Structur repetitiv condiionat posterior (cu test final), adic structura REPEAT UNTIL. Singura structur repetitiv indispensabil este WHILE DO, celelalte putndu-se obine din aceasta. Curs2/ 2

2.2.3.1. Structura WHILE DO


Structura WHILE DO se definete astfel: dac E este o expresie logic i S este o structur, atunci secvena reprezentat n fig. 2.6 reprezint o structur de tip WHILE DO. Principiul de execuie al acestei structuri este urmtorul: Pasul 1 (marcat n figur prin P1 ncercuit): se evalueaz expresia logic E i dac se obine TRUE, se trece la pasul 2 (marcat n figur prin P2 ncercuit); dac se obine FALSE, execuia structurii se ncheie. Pasul 2: Se execut structura S i se reia execuia de la pasul 1. Deoarece S se execut numai dac E ia valoarea TRUE, structura face parte dintre integer x,S; read x; S:=0; WHILE x<>0 DO S:=S+x mod 10; x:=x div 10; ENDWHILE write S; Fig. 2.7 structurile condiionate anterior. Utilizarea structurii WHILE DO este obligatorie dac se ndeplinesc simultan dou condiii: 1. S se execut (de cte ori este cazul) numai dac este ndeplinit o anumit condiie (cea exprimat cu ajutorul expresiei E). 2. Nu se cunoate de cte ori se va executa S (este vorba despre un ciclu cu numr necunoscut de pai). Exemplu Se citete un numr natural x, x 0. S se tipreasc suma cifrelor sale (exemplul a mai fost prezentat n paragraful 2.2.1, dar fr a se utiliza structuri repetitive). O soluie a problemei, folosind structura WHILE DO, este reprodus n fig. 2.7.

2.2.3.2. Structura de tip FOR


Fie i o variabil de tip ntreg, numit variabil de ciclare. Fie a i b dou variabile de tip ntreg, numite valoare iniial, respectiv valoarea final i S o structur. Atunci secvena reprezentat n fig. 2.8 reprezint o structur de tip FOR. Principiul de execuie al acestei structuri este urmtorul: Pasul 1 (marcat n figur prin P1 ncercuit): i ia valoarea iniial a. Pasul 2 Dac i b , se execut S, apoi se incrementeaz i (se efectueaz i:=i+1) i se reia execuia de la pasul 2. n caz contrar (i>b) execuia structurii ia sfrit. Structura FOR poate fi simulat folosind WHILE DO aa cum se reprezint n fig. 2.9. Structura FOR se utilizeaz dac sunt ndeplinite simultan urmtoarele dou condiii: - execuia structurii S se repet; - se cunoate dinainte de cte ori se execut S. Se spune c FOR este un ciclu cu un numr cunoscut de pai. Exemplul 1 Se citete un numr natural n. S se calculeze i afieze suma tuturor numerelor naturale mai mici sau egale cu n (problema a mai fost tratat n paragraful 2.1). O soluie a problemei folosind ciclul FOR este prezentat n fig. 2.10. Exemplul 2 Se citete un numr natural n. S se calculeze i afieze urmtoarea sum:

i:=a; WHILE i<=b DO S i:=i+1; ENDWHILE Fig. 2.9 integer n, S, i; read n; S:=0; FOR i:=1,n S:=S+i; REPEAT write S; Fig. 2.10

integer n, S, P, i; read n; S:=0; P:=1; FOR i:=1,n P:=P*i; S:=S+P; REPEAT write S; Fig. 2.11

Numrul de pai ai ciclului FOR este n (este dat de numrul de termeni ai sumei). Fiecare al i-lea termen al sumei se calculeaz ca un produs de forma 1*2*3*...*i, dar calculul se poate simplifica dac se calculeaz pe baza Fig. 2.12 termenului de ordinul (i-1) nmulindu-l pe acest cu i. O soluie a problemei folosind ciclul FOR este prezentat n fig. 2.11.

integer i, n, max,nr; read n; read nr; max:=nr; FOR i:=2,n read nr; if nr>max then max:=nr; end if REPEAT write max;

S = j = 1 + 1* 2 + 1* 2 * 3 + ...+ 1* 2 * 3 * ...* n
i =1 j =1

Exemplul 3 Se citesc n numere ntregi. S se afieze cel mai mare dintre ele. O soluie posibil a problemei utilizeaz doar 3 variabile: n, care reine numrul de numere citie, variabila nr care reine ultimul numr citit, i respectiv variabila max n care se reine maximul dintre numerele citite i analizate pn la momentul respectiv al execuiei. O soluie a problemei folosind ciclul FOR este prezentat n fig. 2.12.

2.2.3.3. Structura de tip REPEAT UNTIL


REPEAT UNTIL este o structur repetitiv condiionat posterior (cu test final). Structura REPEAT UNTIL se definete astfel: dac E este o expresie logic i S este o structur, atunci secvena Curs2/ 3

reprezentat n fig. 2.13 reprezint o structur de tip REPEAT UNTIL. Principiul de execuie al acestei structuri este urmtorul: Pasul 1: Se execut S; Pasul 2: Se evalueaz expresia logic E. Dac la evaluare se obine FALSE, se trece la pasul 1. n caz contrar execuia structurii se ncheie. Observaie Structura S se execut totdeauna cel puin o dat. Structura REPEAT UNTIL se poate simula cu ajutorul structurii WHILE DO aa cum se nfieaz WHILE NOT E n fig. 2.14. S Exemplu S se calculeze i afieze suma primelor n numere naturale (ex. 1 de la paragraful 2.2.3.2). ENDWHILE O soluie posibil a acestei probleme folosind structura REPEAT UNTIL este prezentat n fig. 2.15. Fig. 2.14

CAPITOLUL 3. ELEMENTE DE BAZ ALE LIMBAJULUI C

Limbajul C++ are cteva caracteristici majore, cele mai importante fiind: 1. Este extrem de flexibil, acest lucru nsemnnd c aceeai secven scris n pseudocod poate fi codificat n mai multe feluri. 2. Permite ca anumite secvene s poat fi scrise "ermetic", dar acest lucru prezint un mare dezavantaj: dup o anumit perioad, chiar i cel care le-a scris are dificulti n nelegerea lor. Ex: a+=++b reprezint o scriere "ermetic" pentru secvena de instruciuni: b=b+1; a=a+b. Limbajul C++ conine, pe lng setul de instruciuni, i o mulime de funcii care au rolul de a ajuta programatorul n elaborarea programelor. Fig. 2.15 Atunci cnd o firm (ex. Borland, Microsoft, etc.) vinde un mediu de dezvoltare C++, acesta trebuie s includ toate funciile cerute de standardul pentru limbaj elaborat de ANSI (American National Standard Institute). Firma poate introduce i alte funcii, neprecizate de standarde, dar utilizarea lor duce la crearea de programe neportabile.

integer n, i, S; read n; i:=1; S:=0; REPEAT S:=S+i; i:=i+1; UNTIL i>n; write S;

3.1. Generaliti

3.2. Structura programelor


Un program C este alctuit din una sau mai multe funcii. Prin respectarea structurilor (liniar, alternativ, repetitiv), orice algoritm poate fi descompus n ali algoritmi mai mici (subalgoritmi). n general se poate spune c: 1. Fiecrui algoritm sau subalgoritm i o corespunde o anumit funcie care l codific n instruciuni. 2. Dac funcia nu ntoarce (nu returneaz) nici un rezultat, spunem c tipul rezultatului este void. Funciile care returneaz un rezultat se clasific n funcii cu rezultat de tip ntreg, de tip real, etc. 3. Un program este alctuit din una sau mai multe funcii. Una dintre acestea este funcia rdcin (numit main), care nu poate lipsi. Execuia programului ncepe automat cu funcia main. n general aceast funcie se folosete fr parametri. La rndul ei, funcia main poate apela alte funcii definite de utilizator sau existente n biblioteci. Cel mai simplu program C arat ca n fig. 3.1.Programul e corect, dei nu efectueaz nici o operaie. Funcia void main() r d cin este de tipul void - nu ntoace nici un rezultat. Parantezele rotunde () se ataeaz oricrei funcii. ntre ele { se scriu, opional, anumii parametri. n acest exemplu nu se folosesc parametri. } ntre acoladele {} se scrie corpul funciei, format din instruciuni i/sau apeluri de funcii. n Fig. 3.1 exemplul nostru, mulimea instruciunilor este vid. 4.Din punct de vedere sintactic, orice instruciune trebuie terminat cu caracterul ";". Grupurile de instruciuni pot fi delimitate prin {} pentru a forma uniti sintactice noi de tip bloc. Dac avem un program compus din dou funcii, anume funcia principal i o funcie apelat f(), atunci o posibil structur a acestui program este reprodus de fig. 3.2. Observaii 1. Se face diferen ntre litere mici i litere mari. 2. Nu are importan nici plasarea cuvintelor pe linie, nici numrul spaiilor dintre ele. Este corect deci i o scriere de forma : void main( ) { } 3. Este permis ca tipul funciei s lipseasc (s nu fie precizat). n acest caz se presupune c funcia returneaz un rezultat ntreg (de tipul int). La o scriere de tipul main() {}, compilarea genereaz un avertisment: pentru c nu este precizat tipul funciei, se ateapt ca n corpul funciei s apar o instruciune prin care funcia s returneza un rezultat de tip int i de fapt funcia nu returneaz nimic. Avertismentul poate fi ignorat.

Curs2/

Cursul 3
Standardul ANSI definete o structur general a unui program care, schematizat, arat ca astfel: 1 includere biblioteci 2 definire macrouri 3 declaratii de variabile globale vizibile n toate funciile programului 4 definire funcii utilizator folosite n program 5 declararea prototipurilor funciilor care vor fi definite dup apelarea lor sau care nu se afla in fisierul sursa curent 6 definirea funciei principale main 7 void main(void){ 8 declaratii de variabile locale pentru funcia principal main 9 descrierea n C a algoritmului funciei main} 10 definire funcii utilizator folosite n program , declarate anterior prin prototipuri n seciunea includere biblioteci apar directive cu forma general #include <nume_fisier.h>. Acestea precizeaz compilatorului s adauge la textul programului surs textul din fiierul nume_fisier.h. De obicei directivele #include sunt utilizate pentru a include n textele de program ale utilizatorilor fiierele antet (header) standard (stdio.h, conio.h, math.h, ...). n seciunea definire macrouri apar directive cu forma general #define nume_macro secventa_de_caractere. O astfel de directiv definete un identificator utilizator numit macrocomand i o secven de caractere. #define doi 2 La ntlnirea unei astfel de directive, toate apariiile cu numele nume_macro din fiierul surs al #define sase 3*doi programului vor fi nlocuite cu secvena de caractere care i urmeaz. n exemplul din fig. 3.3, n #define opt sase+doi urma compilrii, macrocomenzile doi, sase i opt vor primi valorile 2, 6 i respectiv 8. Fig. 3.3 Macrocomenzile sunt cel mai des utilizate pentru atribuirea #include<stdio.h> de valori speciale unor identificatori folosii de program (ca de #define SUMA(x,y) ((x)+(y)) exemplu valoarea lui pi, dimensiunea maxim a tablourilor, etc.). void main(void) Dac se dore te modificarea acestor valori speciale prin folosirea {printf("suma numerelor 3+5 este %d\n",SUMA(3,5)); macrocomenzilor, o va face ntr-un singur loc, anume n printf("suma numerelor 9+2 este %d\n",SUMA(9,2));} directivele define respective. Fig. 3.4 Macromenzile se mai pot utiliza i ca alternativ pentru definirea unor funcii simple. Un exemplu de utilizare a unei #include<stdio.h> astfel de macrocomenzi este prezentat n fig. 3.4. int SUMA(int x,int y) Acelai efect l-am fi obinut i cu programul din fig. 3.5. {return (x+y)} Declararea variabilelor folosite n program void main(void) Variabilele folosite n program se declar n 3 locuri de baz: {printf("suma numerelor 3+5 este %d\n",SUMA(3,5)); a) n interiorul funciilor, caz n care se numesc variabile locale printf("suma numerelor 9+2 este %d\n",SUMA(9,2));} i sunt vizibile numai n interiorul funciei unde au fost declarate. Fig. 3.5 b) n lista de parametri formali folosii la definirea sau declararea funciilor. c) n exteriorul tuturor funciilor, caz n care se numesc variabile globale i sunt vizibile n toate funciile, inclusiv n main. Declararea acestor variabile se face naintea definirii sau declarrii tuturor funciilor programului.

3.3. Interfaa cu dispozitivele periferice


O modalitate de realizare a operaiilor de intrare-ieire este prin intermediul unor funcii din biblioteca standard I/O. Programele care utilizeaz aceast bibliotec trebuie s conin #include<stdio.h>. Intrarea standard, n mod implicit, este terminalul utilizatorului de la care s-a lansat programul (de obicei tastatura). Ieirea standard, n mod implicit, este tot terminalul utilizatorului, de obicei ecranul. Pentru a realiza intrri/ieiri sub controlul formatelor se utilizeaz funciile scanf (pentru intrare) i respectiv printf (pentru ieire). Pentru a realiza intrri/ieiri de caractere, deci fr controlul unui format de la intrarea (respectiv ieirea) standard se folosesc funciile getchar() i respectiv putchar(), incluse tot de stdio.h. Att intrarea standard ct i ieirea standard pot fi redirectate spre alte dispozitive periferice dect terminalul standard. De exemplu se poate redirecta ieirea standard spre imprimant sau disc, ori se poate redirecta intrarea standard spre un fiier de pe disc. Biblioteca stdio.h conine mai multe funcii prin care intrrile i ieirile standard pot fi i ele precizate prin denumiri specifice. Astfel, fiecare program are o intrare standard i dou ieiri standard, acestea avnd denumirile:stdin - intrarea standard;stdout - ieirea standard;stderr - ieirea standard pentru erori. n exemplul din fig. 3.6 se transmite un mesaj ctre mediul de ieire. Funcia printf are rolul de a transmite pe mediul de ieire argumentele primite la apelul funciei, n conformitate cu un format specificat. n acest exemplu singurul argument primit la apel este irul de caractere primul program in C\n. ntr-un ir pot apare caractere afiabile i caractere neafiabile. Se observ prezena caracterului neafiabil n (care apare, ca toate caracterele neafiabile, precedat de "\", adic n forma \n). n C \n reprezint un caracter special, anume caracterul NL - new line. Prezena sa are ca efect trecerea la o linie nou. Exemplu Fie programul din fig. 3.7. n acest caz funcia printf are dou argumente: Curs3/ 1 #include <stdio.h> void main(void) { printf(primul program in C\n);} Fig. 3.6

3.4.Mediul de ieire

a) varsta mea este:%d\n , care conine un ir de caractere si un caracter de conversie (%d). Utilizarea (%d) conduce la afiarea unui ntreg n format zecimal (reprezentat n baza 10). Orice caracter de conversie (denumit i specificator de format) ncepe cu %. b) variabila ntreag varsta. Forma general a funciei printf este: printf(param_control, parametrul_1, parametrul_2,..., parametrul_n) Primul parametru, denumit i "parametru de control", trebuie s fie un ir de caractere. Dac prin printf urmrim numai scrierea unui text, parametrul de control nu va conine nici un specificator de format. Ceilali parametri pot fi numere, variabile, expresii sau chiar alte iruri de caractere. Dac printf va afia o valoare sau o variabil, n primul parametru se introduce informaia aferent tipului valorii sau variabilei, folosind specificatori de format. Un specificator de format ncepe cu %. n continuare specificatorul conine i alte caractere, descrise n continuare (primele 3 categorii sunt opionale): - un caracter "-" (minus), cnd se dorete ca la afiarea datei corespunztoare s se folosesc alinierea la stnga; - un ir de cifre zecimale, care definete numrul minim de caractere folosite la afiarea datei corespunztoare ; - un punct, urmat de cifre zecimale, care vor defini precizia cu care se va tipri data; + una sau dou litere care definesc tipul de conversie aplicat datei care se scrie. Atunci cnd se folosesc dou litere, prima liter va fi l (long). Aceasta indic faptul c, atunci cnd a doua liter este d,o,x sau u, se face o conversie a variabilelor numerice din tipul de date long, nu din tipul de date int. Cele mai uzuale valori folosite pentru a doua liter sunt: d - pentru scrierea numerelor de tip int cu caractere zecimale (decimal); o - pentru scrierea numerelor de tip int convertite n baza 8, prin caractere octale ; x - pentru scrierea numerelelor de tip int convertite n baza 16, cu caractere hexazecimale; u - pentru scrierea numerelor unsigned cu caractere zecimale (pentru numere ntregi pozitive); c - valoarea parametrului corespunztor se consider c reprezint codul ASCII al unui caracter, acesta scriindu-se; s - pentru scrierea unui ir de caractere (string); f - valoarea parametrului corespunztor (de tip real float sau double) se scrie n forma dd...d . dd..dd (unde d =cifr zecimal); e - valoarea parametrului corespunztor (de tip real float sau double) se scrie n formatul dd...d . edd..dd ; g - se aplic una din conversiile definite de literele e sau f, alegndu-se cea care se reprezint pe un numr minim de caractere; Dac folosim d,o,x, data afiat este convertit din tipul int, dac folosim f,e data afiat este convertit din tipul float sau double. Exemple: a) ...int valoare=5; printf("%3d\n",valoare) se afieaz " 5". b) ...int valoare=5; printf("%03d\n",valoare): se afieaz 005. c) ...int valoare=9; printf("%#o\ n",valoare): se afieaz O11 (n octal, 9 se reprezint ca 11 ). d) ...int val=11; printf("%#x\ n",val): se afieaz 0xB (n hexazecimal, 11 se reprezint ca B ). e) ...float valoare=1.23456; printf("%8.3f\n",valoare): se afieaz 1.234, precedat de 3 spaii, adic n total 8 caractere. f) ...float valoare=1.23456; printf("%12.3e\n",valoare): se afieaz 12 caractere, adic 1.234e+00 precedat de 3 spaii. g) ...int valoare=5; printf("%-3d\n",valoare) conduce la afiarea cifrei 5 pe 3 spaii, aliniat stnga, sub forma "5 ". h) ...char a[4]="sir";printf("acesta este un %s\n",a): se afieaz "acesta este un sir". #include <stdio.h> void main(void) { int varsta; varsta=19; printf(varsta mea este:%d\n,varsta);} Fig. 3.7 Programul din fig. 3.8 realizeaz conversia unei valori exprimate n inchi ntr-o valoare exprimat n centimetri. n acest exemplu s-a utilizat funcia scanf, care permite citirea datelor sub controlul formatelor. scanf este foarte asemntoare cu funcia printf, realiznd conversii inverse. Literele d,o,x i u pot fi precedate de litera l i n acest caz conversia se realizeaz spre long, nu spre int. Specificatorul de format f poate fi precedat de litera l pentru a face conversii spre formatul double. Formatul general al funciei este: scanf(param_control, parametrul_1, parametrul_2,..., parametrul_n) Fiecare parametrul_i reprezint adresa unei zone de memorie unde se va memora data citit. Un astfel de parametru este de forma &nume_variabila. A doua liter a specificatorului de format poate fi: d,o,x,u,c,s,f. #include<iostream.h> 3.6. Funcii de intrare/ieire furnizate n C++ de biblioteca iostream.h void main(){ n C++ citirile/scrierile se mai pot face i cu ajutorul unor funcii speciale, furnizate de int a; biblioteca iostream.h, pentru care exist o modalitate special de apel. Pentru citire se folosete cin>>a: cin>>, iar pentru scriere se folosete cout<<, un exemplu de utilizare fiind prezentat n fig. 3.9. cout<<a;} Funcia cin are sintaxa: cin>>a1>>a2>>...>>an. a1,a2,..,an sunt variabile de un tip oarecare. Valorile corespunztoare fiecrei variabile care se citete se introduc pe rnd, apsnd tasta Fig. 3.9 Enter dup fiecare valoare. Observaie Dac pentru o anumit variabil se introduce o valoare care nu coincide cu tipul ei (de exemplu se introduce o valoare real pentru o variabil ntreag), citirea se blocheaz. Acest lucru semnific faptul c urmtoarele variabile nu mai sunt citite, iar calculatorul execut instruciunea urmtoare, fr a semnaliza aceast blocare. Curs3/ 2 #include<stdio.h> void main(void) { float val_inchi=0; printf("introduceti numarul in inchi\n"); scanf("%f",&val_inchi); /* se intr. nr. de la tastatura */ printf("val. n inchi este= %f\n",val_inchi); printf("val. n centimetri este= %f\n",2.54*val_inchi);} Fig. 3.8

3.5.Mediul de intrare

#include<iostream.h> void main(){ int nrlat; cout<<introduceti numar de laturi; cin>>nrlat: cout<<numarul de laturi este <<nrlat;} Fig. 3.10

Funcia cout are sintaxa: cout<<a1<<a2<<...<<an unde a1,a2,..,an sunt variabile de un tip oarecare. Constantele de tip ir de caractere vor fi scrise ntre apostroafe (de exemplu "un ir"). n mod normal datele se scriu una dup alta, fr a lsa spaiu ntre ele. Dac ns se dorete separarea datelor la scriere prin mai multe spaii, aceste spaii se tipresc separat, ca n exemplul urmtor: cout<<a<<" "<<b. Dac vrem ca dup scrierea lui ai , scrierea lui ai+1 s se fac pe rndul urmtor, se folosete constanta endl, adic se folosete o scriere de forma:

cout<<a1<<a2<<... ai<<endl<< ai+1 <<...<<an. n exemplul din fig. 3.10 se citete de la tastatur i apoi se afieaz variabila nrlat.

3.7. Vocabularul limbajului


Vocabularul oricrui limbaj de programare este format din: setul de caractere, identificatori, separatori i comentarii. Setul de caractere al limbajului C reprezint ansamblul de caractere cu ajutorul crora se poate realiza un program n acest limbaj. Este alctuit din: - literele mici i mari ale alfabetului englez (a...z, A...Z), precum i cifrele din baza 10 (0...9); - caractere speciale: +,-,*,/,=,^,<,>,(,),[,],{,} ,", ' , . , , , ; , : , # , $ , @ , _ , ,%,&,?. Un identificator reprezint o succesiune de litere, cifre sau caracterul _ (adic liniua de subliniere). Primul caracter nu poate fi o cifr. Cu ajutorul identificatorilor se asociaz nume constantelor, variabilelor, funciilor, etc. Exemple de identificatori coreci: a1, tasta, un_numr. Exemple de identificatori eronai: 2ae (nu poate ncepe cu o cifr), mt& (ultimul caracter nu este nici cifr, nici liter, nici _), doua cuvinte (nu poate conine spaiu), a*b (interpreteaz a X b). Dac un identificator este format din dou sau mai multe cuvinte, pentru o mai bun lizibilitate se pot folosi literele mari pentru prima liter din fiecare cuvnt component (ex. SumaPozitivelor) sau liniua de subliniere (ex. Suma_Pozitivelor). Observaie Numele care ncep de obicei cu litera de subliniere (_) sunt folosite pentru faciliti speciale n contextul execuiei, a.. nu este recomandabil s se foloseasc astfel de nume n programele de aplicaie. O categorie special de identificatori este dat de cuvintele cheie ale limbajului. Acestea au un neles bine definit i nu pot fi folosite n alt context. Exemple de cuvinte cheie: nume de instruciuni (if, while, ...), nume de tipuri de date (int, float,...), etc. Literalii reprezint valori concrete corespunztoare unor tipuri de date cum ar fi: valori ntregi sau reale (numite i numere), caracterele ASCII, irurile de date, valorile logice, etc. Cele mai simple elemente alctuite din caractere cu semnificaie lingvistic se numesc uniti lexicale. Acestea se separ ntre ele, dup caz, prin unul sau mai multe blanc-uri (spaii libere), caracterul "sfrit de linie" (introdus de tasta Enter), tab sau caracterul ";". Se pot considera separatori i caracterele din fig. 3.11. parantezele () - delimiteaz lista argumentelor unei funcii sau pri ale unei expresii; Pentru ca un program s fie parantezele {} - delimiteaz corpul unei instruciuni compuse sau corpul unei funcii; u or de neles, se folosesc parantezele [] - delimiteaz dimensiunea unui tablou sau indicii elementelor tabloului; comentariile , care se pot plasa ghilimelele "" - delimiteaz un literal ir de caractere; oriunde n program. apostroafele ' ' - delimiteaz un literal de tip caracter; Un comentariu care ocup perechea "/* */" - delimiteaz un comentariu mai multe linii trebuie ncadrat de Fig. 3.11 perechile de caractere /* ...*/. Un comentariu scris pe o singur linie se poate marca prin plasarea a dou linii oblice // /* comentariu naintea sa. n fig. 3.12 sunt prezentate exemple de utilizare a comentariilor. pe dou linii */ S=0; //initializare suma. 3.8. Tipuri de date Fig. 3.12 Toate variabilele trebuie declarate naintea utilizrii lor. Fiecare identificator dintr-un program C are asociat un tip. Prin tip de date se nelege: (a) o mulime de valori; (b) o regul de codificare a valorilor (modul n care se reprezint n memorie); (c) o mulime de operaii definite pe mulimea valorilor. Se spune c variabilele au tip standard dac acesta este cunoscut de ctre limbaj fr a fi definit n cadrul programului. Programatorul poate ns i s i defineasc propriile tipuri, pentru ca apoi s declare #include<iostream.h> variabile cu tipurile definite de el. void main(){ n C exist 5 tipuri de date de baz: character, integer, floating-point, double-floatingchar a; point i valueless, crora le corespund cuvintele cheie: char, int, float, double i void. int b; Observaie n C nu exist tipul boolean, prezentat n pseudocod. n schimb se folosete convenia: a=y;b=71; - orice valoare diferit de zero, a oricrui tip de date, este considerat ca fiind TRUE; cout<<a<< <<a+b;} - orice valoare egal cu zero, a oricrui tip de date, este considerat ca fiind FALSE. Fig. 3.13 Observaie n C tipul character este asimilat tipurilor ntregi. Un bit (Binary Digit - cifr binar) reprezint cea mai mic unitate de informaie pe care o poate manipula calculatorul. Un bit poate lua doar valorile 0 i 1. Un octet (byte) reprezint o unitate de memorare care reine 8 bii. Considerm exemplul din fig. 3.13. n acest exemplu operaia a+b are sens pentru c se adun codul ASCII aferent valorii variabilei a cu valoarea ntreag b. Conform codului ASCII, fiecare caracter se memoreaz pe cte un octet. n consecin rezultatul afiat n urma executrii secvenei de cod din exemplu este 192, deoarece codul ASCII corespunztor litererei y este 121. Caracteristicile tipurilor de baz sunt descrise n tabelul din fig. 3.14, cu observaia c variabilele de tip float i double pot Curs3/ 3

lua i valori negative, la rubrica rang precizndu-se valorile pe care le poate modulul lor. Exceptnd tipul void, tipurile de baz pot avea anumii modificatori Tipul Nr. bii Rang care le preced. Tipurile char i int pot fi prefixate cu signed i unsigned, 7 7 char 8 -128127, adic (2 2 -1) tipul int poate fi prefixat cu short i long, iar double poate fi prefixat cu long. int 32 -21474836482147483647 Tipurile char, short int, int, long int sunt folosite pentru a float 32 0, (3.4E-383.4E+38) reprezenta numere ntregi de diferite dimensiuni, tipurile float, double i double 64 0, 1.7E-3081.7E+308 long double pentru a reprezenta numere reale, iar tipurile unsigned char, void 0 fr valoare unsigned short int, unsigned int, unsigned long int pentru a reprezenta Fig. 3.14 numere ntregi, fr semn, valori logice, vectori de bii, etc. De exemplu o variabil de tipul int poate lua valori n plaja de valori precizat n fig. 3.14 (limita stnga fiind egal cu -231, iar cea din dreapta fiind egal cu 231-1, numrul total de valori din plaj fiind egal cu 232), pe cnd o variabil de tip unsigned int va lua doar valori pozitive, plecnd din 0 pn la valoarea 4294967295 (adic 232). Modificatorul short are ca efect njumtirea numrului de bii pe care se reprezint variabila. De exemplu domeniul n care va lua valori o variabil de tip short int va fi (-215 215 1), adic (-32768 32767), deci numrul total de valori posibile este egal cu 216. Din contr, modificatorul long are ca efect dublarea numrului de bii pe care se reprezint variabila.Astfel, domeniul n care va lua valori o variabil de tip long int va fi (-263 263 1), adic valorile extreme ale intervalului sunt n modul aproximativ egale cu 9.2233372036854776x1018, deci exist un numr total de valori posibile egal cu 264. Se poate renuna la sufixul int de la combinaiile de mai multe nume. Astfel long semnific long char a=y,b=75,c; int, iar unsigned semnific unsigned int. n general, atunci cnd lipsete un tip ntr-o declaraie, se int d,e=178; consider c este de tipul int. Se fac observaiile: Fig. 3.15 1. La declarare este permis i iniializarea variabilelor, ca n exemplul din fig. 3.15. 2. La tiprirea unei variabile de tip caracter, se tiprete caracterul care i corespunde i nu codul char a=99,b=c; ASCII al acestuia. Astfel, n exemplul din fig. 3.16 se tiprete de dou ori caracterul 'c'. cout<<a<< <<b; Constantele se refer la valori fixe, nemodificabile prin program. Se definesc tipurile: 1) Constante ntregi, care se clasific n 3 categorii, dup cum urmeaz: a) Constante zecimale (numere ntregi scrise n baza 10). Exemple: 23 sau 541, etc. b) Constante octale (numere ntregi scrise n baza 8). Cnd se declar o astfel de constant, ea trebuie precedat de o cifr zero (0) nesemnificativ. De exemplu folosind 0123 se declar constanta octal cu valoarea (123)8. c) Constante hexazecimale (numere ntregi scrise n baza 16). Cnd se declar o astfel de constant, ea trebuie precedat de 0x sau 0X. De exemplu folosind 0x1A2 se declar constanta hexazecimal (1A2)16. O constant ntreag poate valori ca i tipul unsigned long int i este totdeauna pozitiv. Dac se folosete semnul - (de exemplu -123), este vorba despre o expresie constant, care este evaluat (n acest caz semnul - este tratat ca i operator unar). 2) Constante caracter. O astfel de constant este delimitat cu ajutorul apostroafelor i este memorat utiliznd tipul char i codul ASCII. De exemplu '1' se memoreaz sub forma (49)10. Constantele caracter pot fi folosite n calcule exact ca i ntregii. O constant caracter mai poate fi declarat i sub forma unei secvene escape. O secven escape ncepe prin caracterul \. Exemplu Caracterul 'a' are codul ASCII (97)10. Dar (97)10=(141)8=(61)16. Programul din fig. 3.17 tiprete de 4 ori caracterul 'a. Secvenele escape sunt utile n cazul caracterelor care nu se pot declara #include<iostream.h> n mod obinuit (ntre dou apostroafe) pentru c nu se pot tasta. De exemplu void main() { caracterul newline (salt la linie nou) are codul ASCII egal cu 10 i poate fi char x1=97, x2=' \141 ', x3=' \x61 ', x4='a'; declarat '\10' , '\n' sau '\xa'. Exemple uzuale de secvene escape: \b - caractecout<<x1<<x2<<x3<<x4;} rul backspace , \0 - caracterul NULL,\t caracterul horizontal TAB, etc. Un rol aparte este deinut de caracterele albe (whitespaces): blanc, \t, \v, Fig. 3.17 \n sau \r, care au un rol special pentru operaiile de citire/scriere. De exemplu tab-ul orizontal poate fi folosit la operaiile de scriere, el determinnd saltul cursorului cu 8 poziii. #include<istream.h> De exemplu programul din fig. 3.18 tiprete litera i precedat de 8 spaii. void main(){ char a='\t',b='i'; 3. Constante reale Ex: -45.6, 1. (reine 1.0), .2 (memoreaz 0.2), 0.3, -2.5E-12 (memoreaz -2,5x10-12). cout<<a<<b;} 4. Constante ir de caractere Acestea se folosesc pentru reprezentarea irurilor de caractere. O astfel de constant se declar prin ncadrare ntre caractere ". Exemplu: "acesta este un text". Fig. 3.18 Constantele ir de caractere, spre deosebire de alte tipuri de constante, au o locaie n memoria calculatorului. Pentru a da nume constantelor folosim cuvntul const. Forma general a unei astfel const int numar=10; de declaraii este: const [tip] nume_constant=valoare. n fig. 3.19 sunt prezentate dou exemple. const float pi2=3.14; Constantele ntregi mai pot cpta nume i prin mecanismul care are la baz tipul enum. n Fig. 3.19 tabelul urmtor sunt prezentate cteva exemple de utilizare a acestui mecanism. Instruciune Efect Explicaii enum timp(ieri,azi,maine) ieri = 0, azi = 1,maine=2 Prima constant ia implicit valoarea 0, celelalte iau valori consecutive enum timp(ieri,azi=3,maine=7) ieri = 0, azi = 3,maine=7 Ultimele dou iniializri sunt explicite enum timp(ieri,azi=3,maine=azi) ieri = 0, azi = 3,maine=3 azi i maine sunt iniializate cu aceeai valoare, adic 3. enum timp(ieri=7, azi) ieri=7, azi=8 Cnd o constant este iniializat, celelalte sunt iniializate implicit pornind de la valoarea sa, la care se adaug, pe rnd, cte o unitate. Curs3/ 4 Fig. 3.16

3.9. Constante

Curs3/

Cursul 4 3.10. Expresii


3.10.1. Generaliti Expresiile se construiesc folosind operatori, constante, variabile i funcii. Operanzii din componena unei expresii pot avea tipuri diferite. De exemplu doi operanzi legai de un operator binar pot fi de tipuri diferite. n acest caz compilatorul convertete tipurile diferite la acelai tip, mai exact la tipul operandului mai mare, aplicnd regula conversiilor implicite. Se aplic urmtoarele 8 conversii, n ordine, de la prima pn la ultima: 1. Exceptnd valorile de tip unsigned short, toate valorile ntregi mici sunt 2. A long double, B long double. convertite (promovate) la int. Tipul unsigned short este promovat la unsigned int. 3. A double, B double. Pentru a descrie urmtoarele 7 conversii (fig. 3.20), vom folosi urmtoarea 4. A float, B float. schem de scriere prescurtat: notm prin A exprimarea : "Dac unul dintre 5. A unsigned long, B unsigned long. operanzi este de tipul", i prin B exprimarea : "compilatorul promoveaz pe 6. A long, B long. cellalt la tipul". 7. A unsigned, B unsigned. Dup execuia acestor pai, cei doi operanzi sunt de acelai tip, iar rezultatul va fi 8. n celelalte cazuri, compilatorul trateaz de tipul comun lor. Se observ o regul: se promoveaz tipul celei mai mici valori. ambii operanzi ca fiind de tipul int. Exemplu Se consider programul reprodus n fig. 3.21. Acest program, datorit conversiei de la char la int tiprete 97 i nu caracterul a. Fig. 3.20 La evaluarea unei expresii se ine cont de asociativitatea operatorilor, care este de include#<iostream.h> dou feluri: de la stnga la dreapta (o vom nota prin -->) i respectiv de la dreapta la stnga (<--). void main(void){ n fig. 3.22 se prezint un exemplu pentru modul n care sunt convertii operanzi de int a=0; char b=a; tipuri diferite care particip ntr-o expresie format din operanzi legai prin operatori cout<<a+b;} aritmetici. n exemplu se folosesc declaraiile: char ch; int i; float f; double d, rezultat; Pentru a nelege noiunea de asociativitate, pornim de la o expresie n care operanzii Fig. 3.21 sunt legai prin operatori de aceeai prioritate. Dac asociativitatea operatorilor este -->, prima operaie care se efectueaz este cea corespunztoare primului operator din stnga, a doua este cea corespunztoare celui de-al doilea operator din stnga, .a.m.d. Dac asociativitatea operatorilor este <--, prima operaie care se efectueaz este cea corespunztoare primului operator din dreapta, .a.m.d. Exist civa operatori binari (din construcii de forma O1 OB O2) pentru care nu se garanteaz ordinea de evaluare a expresiilor care i leag. Aici apare o problem nedecelabil, adic nu se poate spune cine se evalueaz nti: O1 sau O2. Dac se scriu expresii de acest tip, rezultatul evalurii expresiei depinde de tipul compilatorului utilizat, caz n care se obin programe neportabile. 3.10.2. Operatori C++ 3.10.2.1. Operatori aritmetici Exist dou categorii de operatori aritmetici: a) Operatori unari: + i -; b) Operatori binari: +, -, *, /, %. Observaii 1. Operatorul / acioneaz n mod diferit n funcie de operanzii pe care i leag, dup cum urmeaz: a) Dac ambii sunt de tip ntreg, rezultatul este de tip ntreg i are semnificaia de mprire ntreag (se obine ctul). b) Dac cel puin un operand este de unul din tipurile reale, rezultatul este real (se efecteaz mprirea obinuit). 2. Operatorul % se aplic doar la operanzi de tip ntreg. Rezultatul evalurii expresiei O1 % O2 este restul mpririi lui O1 la O2. 3. Rezultatul evalurii unei expresii de forma O1 / O2 sau O1 % O2 este matematic corect numai dac O1 i O2 sunt pozitive. Exemplul 1 Fie variabila a de tip int cu valoarea 10. Atunci expresia 4*a/3 este de tipul int i la evaluare se obine [4*a/3]=13. (Prin paranteze drepte s-a simbolizat partea ntreag). n aceleai condiii, expresia 4*(a/3) are ca rezultat valoarea 12. Exemplul 2 Fie declaraia float a=10; Atunci expresiile 4*a/3 i respectiv 4*(a/3) au ca rezultat valoarea de tip float 13.3333... Exemplul 3 Fie declaraia int a=-10. Atunci, evalund expresia a*-3 obinem 30. Exemplul 4. Fie declaraiile: int a=10; char b=2; float c=5.; Expresia a+b+c are ca rezultat valoarea de tip float 17.000000. 3.10.2.2. Operatori relaionali n C exist urmtorii operatori relaionali: <, <=, >, >=. ntruct n C nu exist valorile logice TRUE i FALSE din pseudocod, rezultatul evalurii unei expresii este 1 dac valoarea de adevr a expresiei este TRUE i 0 dac este FALSE. Exemplu La evaluarea expresiei 3+7>=11-1 se obine 1. 3.10.2.3. Operatori de egalitate n C se definesc urmtorii operatori de egalitate: == pentru egalitate, respectiv != pentru inegalitate. i n cazul aplicrii acestor operatori se utilizeaz convenia prezentat anterior: 1 semnific TRUE i 0 semnific FALSE. Exemplu Dac se evalueaz 3!=4 se obine 1. 3.10.2.4. Operatori de incrementare i decrementare Operatorii de incrementare i decrementare sunt operatori unari care acioneaz asupra coninutului unei variabile i au rolul de a incrementa (caz n care se adun 1) sau decrementa (caz n care se scade 1). Se folosete ++ pentru incrementare, Curs4/ 1

respectiv -- pentru decrementare. Operatorii pot fi: - prefixai - dac sunt aplicai n faa operandului (exemplu ++a, --a) - postfixai - dac sunt aplicai dup operand (exemplu a++, a--). Dac operandul este prefixat, variabila este incrementat (decrementat) nainte ca valoarea reinut de ea s intre n calcul. n cazul postfixrii, variabila este incrementat (decrementat) dup ce valoarea reinut de ea a intrat n calcul. n tabelul din fig. 3.23 se prezint exemple de aplicare a operatorilor de incrementare i decrementare, considernd c variabilele a i b care apar n expresiile prezentate ca exemple sunt de tip ntreg i au valorile iniiale: a=1, b=3. Eroarea care apare la evaluarea expresiei 1+++a se datoreaz urmtorului fapt: compilatorul a considerat c operatorul ++ este aplicat postfixat pentru constanta 1 i nu prefixat pentru variabila a, iar incrementarea este permis numai asupra unei variabile. n cazul utilizrii formei prefixate, apar cazuri n care nu se poate decide care Expresie Rezultat a i b este valoarea produs de expresie la evaluare. La operatorii postfixai e posibil ca evaluare dup evaluare incrementarea s se fac n oricare dintre momentele urmtoare: 1+a++ 2 a=2 momentul 1 (l vom nota cu M1): imediat ce valoarea a intrat n calcul sau 1-++a -1 a=2 momentul 2 (l vom nota cu M2): dup ce a fost calculat ntreaga expresie sau 1+++a Eroare sintactic momentul 3 (l vom nota cu M3): ntre momentele M1 i M2. a++*b++ 3 a=2; b=4 Specificaiile C++ nu prevd cum se procedeaz n astfel de cazuri, iar momentul n care are loc incrementarea poate conduce la generarea de rezultate diferite. ++a*++b 8 a=2; b=4 Fig. 3.23 3.10.2.5. Operatori logici Exist 3 operatori logici: ! semnific negarea logic, || se utilizeaz pentru operaia SAU logic i && semnific I logic. Aceti operatori se pot aplica oricrei variabile sau constante. Operatorul ! acioneaz astfel: dac operandul este o valoare diferit de zero, rezultatul este 0. Altfel rezultatul este 1. Operatorul || funcioneaz aa cum s-a descris n pseudocod: numai dac ambii operanzi sunt 0 se obine 0, altfel se obine 1. Operatorul && funcioneaz aa cum s-a descris n pseudocod: doar cnd ambii operanzi sunt diferii de 0 se obine 1, altfel se obine 0. n tabelul din fig. 3.24 sunt reproduse cteva exemple de evaluare a unor expresii n care intervin operatori logici. Observaie Operatorii logici binari garanteaz modul n care se trateaz Operanzi Expresie Valoare operanzii: nti cel din stnga, apoi, dac este cazul, cel din dreapta. expresie Astfel, ntr-o expresie de forma O1 || O2, dac O1 O2 , O2 nu mai float a=2 !a 0 este evaluat pentru c rezultatul este evident 1. Analog, ntr-o expresie de int a=1, b=3 a&&b 1 forma O1 && O2, dac O1 este 0, nu se mai evalueaz O2, pentru c int a=0, b=3 a&&b 0 rezultatul este evident 0. De aceea, n cazul unei expresii de forma a && b--, int a=0, b=3 a||b 1 dac a=0, nu se mai evalueaz b, deci nu se mai face decrementarea postfixat. int a=0, b=0 a||b 0 3.10.2.6. Operatori logici pe bii Fig. 3.24 Operatorii logici pe bii acioneaz numai asupra operanzilor de tip ntreg. Exist 4 tipuri de astfel de operatori: a) Operatorul << apare n expresii de forma O1 << O2. Aplicarea acestui operator are ca efect deplasarea ctre stnga a tuturor biilor operandului O1 cu un numr de poziii egal cu valoarea lui O2. Poziiile lui O1 rmase libere (n dreapta) vor reine valoarea 0. Dac O2 reine o valoare pe care o notm cu m, o astfel de deplasare este echivalent cu nmulirea cu 2m (dac m este mai mic dect numrul de bii pe care este reprezentat O1). b) Operatorul >> apare n expresii de forma O1 >> O2. Efectul su este analog cu cel al operatorului <<, dar deplasarea se face la dreapta. Exist dou cazuri distincte: - dac O1 este de tip ntreg fr semn, poziiile rmase libere (n stnga) se completeaz cu 0, i o astfel de deplasare este echivalent cu mprirea cu 2m ; - dac O1 este de tip ntreg cu semn, poziiile rmase libere n stnga se completeaz cu valoarea reinut de bitul de semn (0 pentru numere pozitive, 1 pentru numere negative). c) Operatorii binari pe bii: &, | i ^. Aceti operatori apar n expresii de forma O1 OB O2. Rezultatul evalurii unei expresii de forma E= O1 OB O2 se obine aplicnd pentru fiecare pereche de bii aflai pe aceeai poziie regulile prezentate n tabelul de la paragraful 1.4.3.3. Observaie Trebuie fcut distincia fa de operatorii logici, care folosesc notaiile dublate && i respectiv ||. Operatorii logici au aceleai denumiri, dar ei trateaz ntregul operator ca pe o singur valoare, adevrat sau fals. d) Operatorul unar ~ (negare pe bii). Acest operator are rolul de a inversa coninutul biilor (dac un bit conine valoarea 0, dup evaluare el va conine 1 i invers). Pentru exemplificare s considerm declaraiile: int a=0 x 000f, b=0 x 0f03. Fiecare cifr hexazecimal se poate exprima n baza 2 conform tabelului din fig. 3.25 (unde prin H s-a notat cifra hexazecimal iar prin E s-a notat echivalentul su n baza 2). Valorile hexazecimale ale variabilelor a i b din exemplul nostru pot fi scrise n baza 2 astfel: H E H E H E H E a= 0000 0000 0000 1111; b= 0000 1111 0000 0011. 0 0000 4 0100 8 1000 C 1100 Atunci : 1 0001 5 0101 9 1001 D 1101 a & b= 0000 0000 0000 0011=0 X 0003 2 0010 6 0110 A 1010 E 1110 a | b=0000 1111 0000 1111=0 X 0F0F 3 0011 7 0111 B 1011 F 1111 a^b=0000 1111 0000 1100 = 0X 0F0C Fig. 3.25 Curs4/ 2

a<<2=0000 0000 0011 1100= 0 X 003C a>>2= 0000 0000 0000 0011= 0X 0003 ~a=1111 1111 1111 0000= 0 X FFF0. Exemplul urmtor realizeaz un SAU i un I pentru dou caractere: 'a' | 'c'= 0110 0001 | 0110 0011 = 01100011='c' 'a' & 'c'= 0110 0001 & 0110 0011 = 0110 0001='a' 3.10.2.7. Operatori de atribuire Spre deosebire de limbajele de tip pseudocod, n C atribuirea este operator. n C exist mai muli operatori de atribuire. 1. Operatorul "=" apare ntr-o expresie de forma : v=expresie, iar principiul de execuie este urmtorul: se evalueaz expresia, apoi variabilei v i se atribuie valoarea obinut (dac este cazul se face i conversia de tip necesar). Se pot face i atribuiri multiple, de forma: v=v1=v2=...=vn=expresie. In acest caz principiul de execuie poate fi descris de urmtorii pai: (a) se evalueaz expresie; (b) valoarea obinut n urma evalurii precedente se atribuie variabilei vn; (c) coninutul variabilei vn se atribuie variabilei vn-1 ; (d) Se continu prin atribuiri prin care coninutul variabilei vi se atribuie variabilei vi-1...pentru ca n final coninutul variabilei v1 s i se atribuie variabilei v. La fiecare pas se fac conversiile necesare. 2. Operatorii de atribuire compui Operatorii de atribuire compui apar n construcii sintactice de forma: v op= expresie. Aceast construcie are acelai efect ca i scrierea v=v op expresie. Se pot forma urmtorii operatori de atribuire compui: +=, -=, *=, /=, %=, <<=, >>=, &=, |=, ^=. Exemplul 1 int a=3; a*=2 va produce rezultatul 6. Observaie Dac unei variabile de tip ntreg i se atribuie coninutul unei variabile de tip real, acesta este trunchiat. Exemplul 2: int a; float b=-1.9; Dup ce se execut a=b , a va reine -1. Observaie Trunchierea nu nseamn "parte ntreag". Dac lui a i s-ar fi atribuit partea ntreag a lui b, a ar fi trebuit s rein -2. 3.10.2.8. Operatorul virgul n C se pot scrie mai multe expresii separate prin virgul, astfel: expr1, expr2, ..., exprn. int a=1, b=5; float c; Deoarece operatorul "," se asociaz "-->", expresiile se evalueaz n ordinea expr1, expr2, ..., exprn. Expresia Dac notm E= expr1, expr2, ..., exprn, prin convenie, E produce ca rezultat valoarea c=a=b+1, a=c+2, b=b+1 obinut n urma evalurii ultimei expresii, tipul acestei valori fiind i tipul lui E. n fig. 3.26 se evalueaz astfel: se red un exemplu de utilizare a operatorului virgul. Expresia din exemplu, n ansamblul ei, a=b+1=6 este de tipul int si produce valoarea 6. c=a=6 3.10.2.9. Operatorul condiional (sau ternar) a=c+2=6+2=8 Operatorul condiional apare n expresii cu forma general: expr1 ? expr2: expr3 b=b+1=6. Principiul de execuie este urmtorul: Fig. 3.26 - se evalueaz expr1; - dac n urma evalurii se obine o valoare diferit de 0 (TRUE), se evalueaz expr2 i expr3 #include<iostream.h> este ignorat; void main(void){ - dac n urma evalurii se obine o valoare egal cu 0 (FALSE), se evalueaz expr3 i expr2 este ignorat. float x; n ansamblu, o expresie E de forma E= expr1 ? expr2: expr3 este de tipul expr2 sau expr3 (n cout<<x; funcie de care dintre ele este evaluat) i produce n mod corespunztor valoarea expresiei expr2 cin>>x; sau pe cea a expresiei expr3. cout<<(x>0?x;-x);} Exemplu Programul din fig. 3.27 citete o variabil x de tip float i afieaz modulul acesteia. Fig. 3.27 Observaie Ultima linie din program se putea nlocui cu secvena de instruciuni din fig. 3.28: 3.10.2.10. Operatorul sizeof if (x>0) Operatorul sizeof are rolul de a returna numrul de octei utilizai pentru memorarea unei valori i poate fi cout<<x; utilizat ntr-una dintre urmtoarele forme: sizeof(expresie) sau sizeof(tip). else Expresia expresie care apare n prima dintre forme nu este evaluat, deci nu apar efecte secundare. cout<<-x; Exemplul 1: Fie declaraia float a. Atunci size(a)=4 (pentru c float se memoreaz pe 32 bii, adic 4 octei). Fig. 3.28 (Dac se evalueaz size(float) se obine 4). Exemplul 2: int a; double b; size(a+b)=8. 3.10.2.11. Operatorul cu conversie explicit (operatorul cast) Atunci cnd se dorete ca unul sau mai muli operanzi s intre n calcul convertii la un anumit tip de date, specificat de programator, i nu aa cum se realizeaz n mod implicit, se folosete o construcie sintactic de forma: (tip_dorit)operand_convertit Exemplul 1: float x=-1.9; Atunci (int)x=-1 (s-a fcut conversia de la float la int prin trunchiere). Exemplul 2: float x=-1.9; Atunci (int)(++x+3)=2. 3.10.2.11. Operatori utilizai n manipularea pointerilor Un pointer este n esen adresa de memorie a unei variabile de un anumit tip. O variabil pointer este o variabil pentru care s-a precizat n mod explicit c memoreaz un pointer. Exist 2 operatori pentru manipularea pointerilor: 1. Operatorul adres (ampersand), simbolizat prin & Cnd ntr-un program trebuie s se determine adresa unei varibile, se utilizeaz operatorul adres. Acesta este un operator unar, ce returneaz adresa de memorie a operandului specificat. Considerm construcia sintactic: adresa_de_memorie=&variabila. Curs4/ 3

n aceast construcie variabila reprezint identificatorul unei variabile de un anumit tip iar adresa_de_memorie este o variabil de tip pointer care, dup execuia atribuirii de mai sus, primete ca valoare adresa de memorie a variabilei specificate. n exemplul din fig. 3.29 se efectueaz operaiunile: (a) declarare variabil p de tip pointer, care va memora o adres de memorie a unei variabile de tip int; (b) memorare n p a adresei de memorie a varibilei x. n acest exemplu, x s-a memorat la adresa 3460H; dup execuia p=&x, p a primit valoarea 3460H. Deci, pentru a declara o variabil de tip pointer trebuie precizat tipul valorii pe care o indic pointerul i un asterisc naintea numelui variabilei de tip pointer. Astfel float *x are ca efect declararea variabilei de tip pointer x care va memora o adres a unei variabile de tip real (va indica spre o variabil de tip real). 2. Operatorul de redirectare (asterisc) simbolizat prin * Utiliznd adresa pe care o conine un pointer se poate determina informaia coninut la adresa indicat de el. Dereferenierea unui pointer reprezint procesul de accesare a informaiei coninute la adresa indicat de pointer. Operatorul * este tot un operator unar, complementar operatorului &. Considerm construcia sintactic urmtoare: variabila = *adresa_de_memorie. n aceast construcie adresa_de_memorie este o variabil de tip pointer care conine adresa unei variabile de un anumit tip, iar variabila este identificatorul unei variabile de acelai tip cu tipul variabilei a crei adres este memorat n adresa_de_memorie. n urma executrii acestei operaii de atribuire variabila specificat prin variabila va primi valoarea variabilei a crei adres de memorie este memorat de adresa_de_memorie. Considerm exemplul din fig. 3.30. n acest exemplu variabila y de tip int memoreaz valoarea 8. Presupunem c sistemul de operare a memorat-o la adresa 1200H. Dup executarea v=*p, v primete valoarea 8. 3.10.2.12. Operatori utilizai la referirea termenilor individuali ai structurilor i uniunilor Structurile i uniunile sunt tipuri colective de date (structurate) care pot fi definite i utilizate sub un singur nume. Pentru referirea termenilor individuali ai acestora se folosesc 2 operatori. Operatorul "." (punct) se folosete atunci cnd se lucreaz cu o structur sau uniune pentru a ne referi la cmpuri elementare din aceasta. Operatorul "->" (sgeat dreapta) se folosete pentru a ne referi la cmpuri elementare reperate prin intermediul unor pointeri care le indic. Considerm exemplul din fig. 3.31. Aici utilizatorul declar un tip colectiv de date, mai exact o structur. Aceasta este format din dou cmpuri elementare, char nume[20] (vector cu maxim 21 struct tip_student *p=&student; de componente, fiecare avnd tipul char), respectiv float media. Dup declararea student.media=7.20; structurii se declar i o variabil de acest tip, identificat prin nume - student. p->media=7.20; Considerm exemplul din fig. 3.32. Aici se declar i iniializeaz variabila Fig. 3.32 pointer p. Ea va reine adresa unde se memoreaz variabila student care are tipul tip_student. Instruciunile student.media=7.20 i respectiv p#include <iostream.h> >media=7.20 au acelai efect, respectiv reactualizarea valorii reinute de void main(){ cmpul media, astfel nct n acest cmp s se memoreze valoarea 7.20. int a,b; float medie; CAPITOLUL 4. INSTRUCTIUNILE LIMBAJULUI C cout<<a=?; cin>>a; 4.1. Instruciunea expresie cout<<b=?; cin>>b; C-ul utilizeaz o instruciune care nu exist n pseudocod, anume medie=(float)(a+b)/2; // instr. expresie instruciunea expresie, cu sintaxa: expresie; cout<<media=<<medie;} Dac expresia este vid (nu are nici un operand i nici un operator), Fig. 4.1 obinem instruciunea vid. Instruciunea expresie este des utilizat n atribuiri. Forma 1 Observaie Este permis scrierea unor instruciuni expresie ca cea din exemplul urmtor: if(expresie) instruciune_1; 7+2;. Efectul execuiei unor instruciuni de acest tip este urmtorul: se evalueaz expresia, else instruciune_2; dar rezultatul obinut nu este utilizat n nici un fel. Forma 2 n exemplul din fig. 4.1 se citesc numerele ntregi a i b i se afieaz media lor aritmetic. if(expresie) instruciune_1; 4.2. Instruciunea if Fig. 4.2 Ca i n pseudocod, i n C instruciunea if prezint dou forme, prezentate n fig. 4.2 Efectul execuiei instruciunii if reprezentate prin prima form este urmtorul: se #include <iostream.h> evalueaz expresie. Dac valoarea obinut este diferit de 0, se execut instruciune_1. n caz void main(){ contrar (valoarea obinut este 0) se execut instruciune_2. La a doua form nu se mai execut int a; nimic atunci cnd n urma evalurii expresiei se obine o valoare egal cu 0. cout<<a=?; cin>>a; Exemplu (fig. 4.3). Se citete o valoare ntreag. Dac aceasta este par, se afieaz mesajul if(a%2==0) "par". Altfel nu se afieaz nimic. cout<<par;} Fig. 4.3 Curs4/ 4

Cursul 5
{ i1; i2; ... in; } Fig. 4.4

4.3. Instruciunea compus


Pentru a putea scrie mai multe instruciuni care s fie interpretate de compilator ca una singur se utilizeaz instruciunea compus, cu forma general din fig. 4.4, unde i1, i2, ...in reprezint instruciunile din care este format corpul instruciunii compuse. Un exemplu de utilizare este reprodus n fig. 4.7 (instruciunile ngroate).

4.4. Instruciunea switch

Instruciunea switch are forma general din fig. 4.5. n aceast form general, expresie reprezint o expresie de tip int. expr1, expr2, ..., exprn reprezint expresii constante de tip int. switch(expresie){ Principiul de execuie este urmtorul: case expr1: secven_de_instruciuni_1; break; - se evalueaz expresie; case expr2: secven_de_instruciuni_2; break; - dac n urma evalurii se obine o valoare egal cu cea produs de .... oricare dintre celelalte expresii (s considerm c este egal cu cea case exprn: secven_de_instruciuni_n; break; produs de expri), atunci se execut, n ordine, instruciunile care [default: secven_de_instruciuni_n+1]; formeaz secven_de_instruciuni_i. Se iese apoi de sub controlul } instruciunii switch; Fig. 4.5 - n caz contrar (atunci cnd n urma evalurii se obine o valoare care nu este egal cu nici una dintre valorile produse de expresiile expri), #include <iostream.h> dac eticheta default este prezent, se execut secven_de_instruciuni_n+1. void main(){ Observaie Alternativa default este facultativ. n absena ei, n cazul n care n urma int a; evalurii se obine o valoare care nu este egal cu nici una dintre valorile produse de cout<<a=?; cin>>a; expresiile expri, nu se execut nimic. switch(a) Exemplu Programul reprodus n fig. 4.6 execut urmtoarele operaiuni: citete { valoarea variabilei i. Dac aceasta este 1 sau 2, se afieaz un mesaj de forma : "am case 1:cout<<am citit 1;break; citit ...", altfel se afieaz mesajul "am citit altceva". case 2:cout<<am citit 2;break; 4.5. Instruciunea while default: cout<<am citit altceva; Instruciunea while reproduce structura WHILE DO prezentat la pseudocod. Are } urmtoarea form general: while(expresie) instruciune. Fig. 4.6 Varianta 1 Varianta 2 #include <iostream.h> #include <iostream.h> void main(){ void main(){ int n,S=0; int n,S=0; cout<<n=?; cin>>n; cout<<n=?; cin>>n; while(n) { while(S+=n % 10, n /= 10); S=S+n % 10; cout<<S=<<S; n=n / 10;} } cout<<S=<<S;} Fig. 4.7 do instruciune while(expresie) Fig. 4.8 Principiul de execuie al acestei instruciuni este urmtorul: Pasul 1: Se evalueaz expresie. Pasul 2: Dac rezultatul obinut la pasul precedent este diferit de 0 (expresia are valoarea de adevr TRUE), atunci se execut instruciune i apoi se revine la pasul 1. Altfel (s-a obinut 0), se iese de sub controlul instruciunii while. Exemplu (fig. 4.7) Se citete un numr natural n. S se calculeze suma cifrelor sale (de exemplu, dac numrul citit este 426, se va afia 12). n pseudocod fig. 2.7.

4.6. Instruciunea do while

Efectul execuiei instruciunii do while este asemntor cu cel prezentat la pseudocod, la structura REPEAT UNTIL. Forma general a acestei instruciuni este reprodus n fig. 4.8, iar principiul de execuie al acestei instruciuni este urmtorul: Pasul 1: Se execut instruciune. Pasul 2: Se evalueaz expresie. Dac se obine valoarea 0, execuia instruciunii do while se ncheie, altfel se reia execuia de la pasul 1. Varianta 1 Varianta 2 Observaie Secvena se execut cel puin o dat, indiferent de #include <iostream.h> #include <iostream.h> valoarea pe care o produce expresie. void main(){ void main(){ Exemplul 1 (fig. 4.9) Se citete un numr natural n>=1. S se int n,S=0,i=1; int n,S=0,i=1; calculeze suma primelor n numere naturale. cout<<n=?; cin>>n; cout<<n=?; cin>>n; Exemplul 2 (fig. 4.10) Dndu-se o valoare real x s se calculeze do { do x x x suma S a urmtoarei serii: S = + ... S=S+i; S+=i++; 1! 3! 5! i=i+1;} while(i<=n); Se dore te calculul cu o precizie relativ eps dat de while(i<=n); cout<<S=<<S; x cout<<S=<<S;} } expresia: < eps Fig. 4.9 (2i 1)! Observaie Pentru uurarea calculului un termen t al seriei se poate

calcula aplicnd urmtoarea relaie de recuren: t = t * Curs5/

1 i (i 1)
1

#include<iostream.h> #include<math.h> void main(void){ float x,S,t,eps; int i; cout<<introduceti x;cin>>x; cout<<introduceti eps;cin>>eps; S=x;t=x;i=1; do { i=i+2; t=-t / i / (i-1); S += t; } while( abs(t) >= eps); cout<<S=<<S;} Fig. 4.10 #include <iostream.h> void main(){ unsigned long produs=1; int i,n; cout<<n=?; cin>>n; for(i=1; i<=n; i++) produs=produs*i; cout<<produs=<<produs;} Fig. 4.11

4.7. Instruciunea for


Instruciunea for are urmtoarea form general: for( expr_iniializare ; expr_test ; expr_incrementare ) instruciune Expresia expr_iniializare se folosete de regul pentru iniializarea variabilei de ciclare. Expresia expr_test se folosete pentru a testa dac se va executa instruciune. Doar dac expr_test produce o valoarea diferit de 0 se va executa instruciune. Expresia expr_incrementare se folosete de obicei pentru incrementarea variabilei de ciclare. Principiul de execuie al acestei instruciuni este urmtorul: Pasul 1: Se evalueaz expr_iniializare. Pasul 2: Se evalueaz expr_test. Dac se obine o valoare diferit de 0, se execut instruciune, apoi se trece la pasul 3. n caz contrar se iese de sub controlul instruciunii for. Pasul 3: Se evalueaz expr_incrementare i se revine la pasul 2. Observaie Oricare dintre cele 3 expresii din forma general a lui for poate fi vid. n exemplul din fig. 4.11 se citete un numr natural n. Se afieaz produsul numerelor naturale mai mici dect n.

Probleme particulare relative la utilizarea instruciunii for Nu totdeauna sunt necesare toate cele 3 expresii care apar n forma general a instruciunii for. De exemplu, dac variabila de ciclare a fost iniializat nainte de intrarea n ciclu, expresia de iniializare nu mai este necesar, n acest caz folosindu-se urmtoarea form particular: for( ; expr_test ; expr_incrementare) instruciune . n fig. 4.12 (a), cu ajutorul instruciunii for se afieaz numerele naturale de la 0 la 9999. Variabila contor s-a iniializat nainte de intrarea n ciclu cu valoarea 0 . In fig. 4.12 (b) nu se folosete nici expr_incrementare, acest lucru realizndu-se n corpul ciclului prin operatorul de postincrementare, iar instruciunea for(;;) va produce o ciclare infinit. Instruciunea for accept ca variabila contor s aib i un tip de date diferit de int. In exemplul din fig. 4.13 se utilizeaz 3 instruciuni for: prima afieaz literele mari de la A la Z, a doua afieaz literele mici n ordine invers, de la z la a i ultima afieaz numerele 0,0.1, 0.2,...,0.9.

for( ; contor<1000; contor++) for( ; contor<1000 ; ) printf(%d,contor); printf(%d,contor++); (a) (b) Fig.4.12 #include<stdio.h> void main(void){ char litera; float procent; for(litera=A;litera<=Z;litera++) putchar(litera); for(litera=z;litera<=a;litera--) putchar(litera); putchar( \n); for(procent=0; procent <1;procent+=0.1) printf(%3.1f\n, procent);} Fig. 4.13 #include<iostream.h> void main(void){ int i; for(i=0;i<100;i++){ cout<<i<<i<< ; if(i==10) break;} } Fig. 4.14 #include<iostream.h> void main(void){ int i; for(i=0;i<100;i++){ if( i % 2) continue; cout<<i:} } Fig. 4.15

4.8. Instruciuni de salt


n C exist 4 instruciuni de salt necondiionat, care determin continuarea execuiei programului din alt parte, alta dect cea corespunztoare secvenei care ar fi urmat n derularea normal a execuiei. Aceste 4 instruciuni sunt descrise n cele ce urmeaz. n plus, un salt necondiionat se mai poate realiza i cu funcia exit.

4.8.1. Instruciunea break Instruciunea break are dou utilizri. Prima const n terminarea unui case n cadrul unei instruciuni switch. A doua utilizare const n terminarea imediat a unui ciclu, fr a se mai ine cont de testul condiional normal al ciclului. Dac ntr-un ciclu se ntlnete o instruciune break, controlul programului se transfer imediat la prima instruciune de dup ciclu. n fig. 4.14 se prezint un program prin care se afieaz numerele naturale de la 0 pn la 10. n absena lui break s-ar fi afiat i numerele de la 10 la 99. 4.8.2. Instruciunea continue Dac n interiorul unui ciclu se execut instruciunea continue, acest lucru are ca efect oprirea iteraiei curente i trecerea imediat la iteraia urmtoare. n exemplul din fig. 4.15, datorit utilizrii instruciunii continue nu se afieaz toate numerele de la 0 la 99, aa cum s-ar derula execuia programului n mod obinuit, ci se afieaz numai numerele pare. De exemplu la iteraia aferena valorii i=3 , la execuia instruciunii continue se abandoneaz celelalte instruciuni care trebuiau efectuate pentru i=3 (adic nu se mai execut cout) i se trece la execuia grupului de instruciuni aferente iteraiei i=4. n cazul instruciunilor while i do while, o instruciune continue determin trecerea direct la testul condiional. n cazul instruciunii for se realizeaz mai nti operaia de incrementare a variabilei de control a ciclului, apoi se testeaz condiia de continuare a ciclului.

Curs5/

#include<iostream.h> void main(void){ int i,n,S; cout<<n;cin>>n; i=1;S=0; etich: S+=i;i++; if(i<=n) goto etich; cout<<S; } Fig. 4.16 #include<iostream.h> int f(int x){ return(x*x);} void main(void){ int x,y; cout<<x;cin>>x; cout<<y;cin>>y; cout<<f(x)+f(y);}

4.8.3. Instruciunea de salt goto Instruciunea de salt goto are urmtoarea sintax: goto etichet;. etichet servete la localizarea unei alte instruciuni. Efectul execuiei este urmtorul: instruciunea urmtoare care se va executa este cea etichetat cu ajutorul etichet. n programarea structurat nu exist situaii unde folosirea instruciunii goto este imperios necesar. n exemplul din fig. 4.16 se calculeaz suma primelor n numere naturale. 4.8.4. Instruciunea return Instruciunea return este folosit n definirea unei funcii i poate preciza valoarea pe care o "ntoarce" funcia. Un exemplu de utilizare este dat n fig. 4.17, unde se definete funcia f, care ntoarce (returneaz) ptratul variabilei furnizate ca parametru. Apoi, n programul principal, se citesc valorile variabilelor x i y i se afieaz suma ptratelor lor, apelnd funcia f.

CAPITOLUL 5. FUNCTII
5.1. Generaliti

n limbajul C o funcie este o structur de program, care descrie un subalgoritm al unui algoritm i poate fi apelat de mai multe ori pe parcursul execuiei unui program. O funcie poate utiliza unul sau mai muli parametri de intrare numii si argumente (sunt ns cazuri cnd nu se folosete nici un argument). Funcia poate returna, n urma apelrii i executrii sale cel mult o valoare de ieire (sau rezultat) numit valoarea funciei. Dar exist i funcii care nu returneaz nimic. n Fig. 4.17 practic, de multe ori, valorile returnate de funcie sunt ignorate. Orice funcie care se utilizeaz n program trebuie descris sau declarat totdeauna naintea apelrii sale de ctre funcia principal (main) sau de ctre o alt funcie, definit de utilizator.

5.2. Definirea sau descrierea funciilor


Din punctul de vedere al proprietarului funciilor se cunosc: a) Funcii predefinite (sau standard), care sunt livrate mpreun cu mediul de programare C i se gsesc n diferite fiiere sau biblioteci (ex. stdio.h, iostream.h, math.h, etc.) b) Funcii utilizator, care sunt definite de utilizator i se pot gsi: - n fiierele si bibliotecile utilizator unde au fost introduse anterior de ctre utilizator; - n fiierul surs al programului curent, caz n care trebuie definite(descrise) sau declarate naintea apelrii lor. Sintaxa de definire(descriere) a unei funcii utilizator este descris n fig.5.1, putndu-se evidenia urmtoarele elemente: - tip_functie poate fi orice tip de date valid, adic poate fi un tip de baz (char, int, float, double, etc.) sau un tip derivat (pointer, structur, etc.). Nu poate fi un tablou. Dac funcia nu returneaz nici un rezultat, atunci tip_functie trebuie s fie void, iar dac nu este specificat, se consider implicit tipul int; - nume_functie reprezint un identificator utilizator, prin intermediul cruia se apeleaz funcia pentru execuie; - a1, a2, .., an reprezint parametrii formali sau argumentele formale ale funciei, care n general reprezint datele formale de intrare n funcie (reprezentate prin variabile formale sau prin adrese de variabile formale). La o funcie fr argumente lista de parametri se nlocuiete cu void; t1, t2, .., tn reprezint tipurile parametrilor formali (int, char, float i derivatele lor). Cnd tipul unui int max(int a,int b) parametru formal lipsete, el este implicit considerat ca fiind int; { - lista_de_declaraii_locale , opional, conine toate declaraiile locale ale funciei, valabile n if(a>b) interiorul acesteia (aici intr declararea variabilelor locale); return(a); lista_instruc iuni reprezint toate instruciunile executabile care descriu subalgoritmul funciei; else - return, opional, precizeaz, prin evaluarea expresiei pe care o precede, valoarea returnat de ctre return(b); funcie ctre structura de program apelant. Aceast valoare trebuie s fie de acelai tip cu tipul funciei. } n fig. 5.2 se prezint un exemplu de funcie care returneaz cel mai mare dintre numerele ntregi Fig. 5.2 a i b furnizate ca parametri.

5.3. Declararea funciilor


Dac att antetul ct i corpul unei funcii utilizator se afl n fiierul surs naintea oricrui apel al funciei, avem de-a face cu definirea sau descrierea funciei. n cazul n care funcia utilizator respectiv este definit dup apelul su ori atunci cnd aceasta nu se afl n fiierul surs curent, este necesar declararea funciei naintea oricrui apel la aceasta. Declararea funciei presupune precizarea antetului su.

5.4. Variabilele locale


Aa cum reiese din sintaxa general a unei funcii, i n C (ca i n alte medii de programare), n cadrul unei funcii se pot declara variabile locale. Numele i valoarea unei astfel de variabile sunt valabile doar n cadrul funciei care conine declaraia Curs5/ 3

#include<iostream.h> void val_local(void){ int a=1,b=2,c=3; cout<<a=<<a<<b=<<b<<c=<<c;} void main(void){ cout<<a=<<a<<b=<<b<<c=<<c;} Fig. 5.3 #include<iostream.h> int a=1,b=2,c=3; //variabile globale void val_global(void){ cout<<a=<<a<<b=<<b<<c=<<c;} void main(void){ val_global();} Fig. 5.4

sa. n fig. 5.3 se prezint un exemplu n care, n interiorul funciei val_local se declar 3 variabile locale: a,b i c. Apoi, tot n cadrul acestei funcii, se atribuie valori acestor variabile locale. Funcia main ncearc s tipreasc valoarea fiecrei variabile, dar compilatorul genereaz erori care anun c simbolurile a,b i c sunt nedefinite.

5.5. Variabilele globale


Pe lng variabilele locale programele mai pot folosi i variabile globale, ale cror nume, valori i existen sunt recunoscute n ntregul program. Fig. 5.4 - exemplu de utilizare a acestora. Deoarece valoarea unei variabile globale se poate modifica din orice punct al programului care o utilizeaz, un alt programator care modific un program n care sunt variabile globale le-ar putea modifica din greeal. Ca regul, funciile trebuie s modifice doar acele variabile care le sunt transmise ca parametri.

In ceea ce privete rezolvarea conflictelor dintre numele variabilelor locale i ale celor globale, se pot specifica urmtoarele: este posibil ca numele unor variabile globale s fie identic cu cel al unor variabile locale. n a =100 b=2 c=3 exemplul din fig. 5.5 (a) se utilizeaz a =1 b=2 c=3 variabilele globale a,b i c. Funcia conflict_a (); conflict_a folosete o variabil local cout<<a=<<a<<b=<<b<<c=<<c<< endl;} numit a i variabilele globale b i c. n (a) (b) urma executrii programului, pe ecran se Fig. 5.5 vor afia valorile reprezentate n fig. 5.5. (b) Cnd numele unei variabile globale intr n conflict cu numele unei variabile locale se va folosi ntotdeauna variabila local. Se spune c variabila local o ascunde pe cea global. Alegnd locul n care se definete o variabil global se pot stabili funciile care se pot referi la variabila respectiv. Altfel spus, se poate controla domeniul de valabilitate al variabilei (numit i scope). Atunci cnd programul declar o variabil global, orice funcie care urmeaz declaraiei poate face referin la aceast variabil, pn la sfritul fiierului surs. Funciile definite naintea unei variabile globale nu o pot accesa. #include<iostream.h> int a=1,b=2,c=3; //variabile globale void conflict_a(void){ int a=100; cout<<a=<<a<<b=<<b<<c=<<c<<endl;} void main(void){

5.6. Apelarea unei funcii


Orice funcie definit sau declarat de utilizator poate fi apelat de o alt funcie definit de utilizator sau de funcia main. Cnd apeleaz o funcie, programatorul trebuie s precizeze numele ei i lista de parametri efectivi (numii i actuali sau reali). La executarea funciei, aceti parametri vor nlocui parametrii formali precizai la definirea sau declararea funciei. Apelarea unei funcii se poate face n dou moduri: a) Apelarea independent (de sine stttoare), cu urmtoarea sintax: nume_funcie([ae1],[ae2],...,[aen]), unde ae1,ae2,...,aen reprezint datele efective de intrare (literali, constante, variabile, funcii sau expresii) sau adresele datelor efective de intrare. Pentru o funcie fr argumente nu se pune nimic n locul listei de parametri efectivi. Dac o funcie apelat n mod independent returneaz o valoare, aceasta nu are nici o contribuie la desfurarea algoritmului. De exemplu n instruciunea f(2,9.5,8); se apeleaz n mod independent funcia f . b) Apelarea dependent , cu urmtoarea sintax: e=...nume_funcie([ae1],[ae2],...,[aen])... Exemplu: e=9.6+3.2*f(7,3.1). In cazul apelrii dependente n cadrul unei instruciuni de atribuire, funcia apelat n mod dependent trebuie s returneze o valoare de un anumit tip, compatibil cu celelalte date i cu operatorii din instruciunea de atribuire n care apare. Transferul parametrilor ntre funcia apelant i funcia apelat Transferul parametrilor poate fi de dou tipuri: prin valorile parametrilor i respectiv prin adresele parametrilor (prin referin). 1. Transferul parametrilor prin valoare n cazul transferului parametrilor prin valoare la apelul unei funcii, funciei i se transmite o copie a valorilor parametrilor efectivi. Orice modificare pe care funcia o efectueaz asupra parametrilor efectivi transmii prin valoare pe parcursul execuiei sale este valabil numai n interiorul funciei (modificrile se opereaz numai asupra unor cpii ale parametrilor efectivi). Dup terminarea execuiei funciei apelate i revenirea n funcia apelant, valorile efective ale parametrilor rmn neschimbate (ele sunt aceleai cu valorile avute naintea apelrii funciei). De aceea n acest caz se returneaz funciei apelante numai valorile prevzute n instruciunile return din corpul funciei apelate precum i valorile parametrilor modificai transmii prin adresele lor. n exemplul din fig. 5.6 se transmit 3 parametri (variabilele a,b i c) funciei afis_si_modif, care va afia valorile, le va aduga valoarea 100 i apoi va afia rezultatul. Dup execuia funciei, programul va afia valorile variabilelor. Deoarece se folosete apelul prin valoare, funcia nu modific valorile variabilelor n cadrul funciei apelante. Curs5/ 4

2. Transferul parametrilor prin adrese sau referine Dac se utilizeaz transferul parametrilor prin adrese sau valorile originale ale parametrilor functiei sunt 1 2 3 referine, atunci cnd se apeleaz funcia, acesteia i se transmit valorile finale ale parametrilor functiei sunt 101 102 103 adresele parametrilor efectivi. valorile finale ale parametrilor in main sunt 1 2 3. n acest caz, pe parcursul execuiei sale, orice modificare Fig. 5.7 pe care o efectueaz funcia asupra parametrilor efectivi este valabil att n interiorul funciei ct i n exteriorul su. Dup terminarea execuiei funciei apelate i revenirea n funcia apelant, valorile efective ale parametrilor rmn cele modificate n timpul execuiei funciei apelate. Ca urmare, n urma apelrii i executrii unei funcii ai crei parametri au fost transmii prin adres, se returneaz funciei apelante: - valorile expresiilor prevzute de return din corpul funciei; - valorile parametrilor modificai, transmii prin adresele lor. Deci, pentru ca n urma apelrii i execuiei sale o funcie s poat modifica valorile unor parametri efectivi, trebuie ca: - la definirea sau declararea funciei s se indice adresele acestor parametri formali (adic variabile de tip pointer spre variabilele respective); - la apelarea funciei s se transmit adresele parametrilor efectivi (folosind operatorul &). Spre deosebire de apelul prin valoare, la apelul prin adres al unui parametru efectiv se transmite funciei apelate #include <iostream.h> adresa de memorie a variabilei ce reprezint parametrul void modif_prim(int *prim, int al_doilea){ efectiv. La apelul prin adres, funcia efectueaz modificarea // atribuie primului param. val. celui de-al 2-lea param. variabilei nu ntr-o copie ci direct n zona de memorie n care *prim=al_doilea; se salveaz variabila, modificarea meninndu-se i dup al_doilea=100;} execuia funciei i revenirea n funcia apelant. void main(void){ n fig. 5.8 este redat un program n care se definete i int a=0,b=5; apeleaz funcia modif_prim. n antetul funciei apar doi modif_prim(&a,b); parametri: primul, numit prim, este transmis prin referin, iar cout<<a=<<a<<, b=<<b;} al doilea, numit al_doilea este transmis prin valoare. n urma Fig. 5.8 execuiei programului, se afieaz valorile celor doi parametri, adic se va afia: a=5, b=5. ntre parametrii formali utilizai la definirea sau declararea funciei i respectiv parametrii efectivi utilizai la apelul funciei trebuie s existe o compatibilitate biunivoc referitoare la tipul parametrilor i respectiv la numrul lor. n plus, poziiile ocupate de acetia n lista de definire a parametrilor formali trebuie s fie aceleai cu cele ocupate n lista parametrilor efectivi. Dac tipurile nu sunt compatibile, compilatorul nu va semnala eroare, dar apar rezultate imprevizibile dup apelarea i executarea funciilor. .... De obicei variabilele locale utilizate n interiorul unei funcii se declar f1(){ la nceputul blocului de cod al acesteia. Acest lucru nu este ns neaprat char c; necesar, declararea putndu-se face oriunde n interiorul blocului, dar nainte cout<<continuam?Y/N<<endl; de a fi folosite. n exemplul din fig. 5.9, funcia f1 creeaz variabila local s cin>>c; doar dup intrarea n blocul aferent lui if . if(c==y){ char s[80]; // cout<<introduceti numerele<<endl; ...... } Fig. 5.9

#include<iostream.h> void afis_si_modif(int prima, int a_doua, int a_treia ){ cout<<valorile originale ale parametrilor functiei sunt<<prima<< a_doua<<a_treia<< endl; prima+=100; a_doua+=100; a_treia+=100; cout<<valorile originale ale parametrilor functiei sunt<<prima<< a_doua<<a_treia<<endl;} void main(void){ int a=1,b=2,c=3; afis_si_modif(a,b,c); cout<<valorile finale ale parametrilor in main sunt<<a<< b<<c<<endl;} Fig. 5.6

n urma executrii programului, pe ecran se vor afia rezultatele din fig. 5.7. Se observ c modificrile variabilelor sunt vizibile numai n ca-drul funciei. Dup execuia main, valorile variabilelor rmn nemodificate.

Curs5/

Cursul 6 5.7. Specificatori de clas de memorie


Atunci cnd se declar o variabil, naintea tipului su se poate preciza i un specificator de clas de memorie. Sintaxa general utilizat pentru declararea unei liste de variabile este: [specificator_de_clas_de_memorie] specificator_de_tip lista_de_variabile; Specificatorul de clas de memorie specific Fisier sursa 1 Fisier sursa 2 clasa de memorie creia i aparin variabilele din lista de variabile i poate fi: auto, extern, static i register. #include<iostream.h> extern int i; 1. Variabilele declarate cu ajutorul specificatoint i; extern float a,b; rului de clas de memorie auto sunt variabile float a,b; void g(){ automate. O astfel de variabil va fi local unei //declarare prototip functie f { funcii sau unui bloc. Dac la declararea unei vavoid f(); i*=100;//i=100*30=3000 riabile declarat ntr-o funcie sau ntr-un bloc nu void main(void){ a*=100;//a=50.25*100=5025 s-a fcut nici o declarare de clas de memorie, i=10; b*=100;//b=49.75*100=4975 atunci aceasta se consider implicit auto. a=20.25; } 2. Variabilele locale declarate explicit folosind b=79.75; cuvntul cheie extern sunt de fapt tot variabile //se afiseaza i=10,a=20.25,b=79.75 globale. Dac programul utilizatorului este cout<<i=<<i<<,a=<<a<<,b=<<b; compus din mai multe fiiere surs, atunci f(); variabilele externe se declar ca globale ntr-un //se afiseaza i=30,a=50.25,b=49.75 singur fiier surs i ca externe n celelalte cout<<i=<<i<<,a=<<a<<,b=<<b; fiiere surs. // se va apela functia g din fisierul sursa 2 Cuvntul cheie extern anun compilatorul g(); c variabila respectiv a fost declarat extern (n //se afiseaza i=3000,a=5025.0,b=4975.0 afara fiierului surs curent) de un alt program. cout<<i=<<i<<,a=<<a<<,b=<<b; n exemplul din fig. 5.10 se utilizeaz un } proiect format din dou fisiere surs. n functia //descrierea functiei f main din fisierul sursa 1 se apeleaz funciile f i void f(){ g. f modific valorile variabilelor i,a,b, care sunt i+=20; declarate ca i variabile globale n fisierul sursa a+=i; 1. Modificarea acestora este resimit i de b-=i;} functia g, pentru c i, a i b sunt declarate cu Fig. 5.10 specificatorul de clas extern n fisierul sursa 2. La rndul su, atunci cnd este apelat, g modific aceste variabile, modificarea respectiv resimindu-se n funcia main. 3. Variabilele statice sunt declarate cu specificatorul de clas static. O astfel de variabil i pstreaz valoarea pe parcursul executrii programului. Atunci cnd se declar o variabil ca static ntr-o funcie, la primul apel, compilatorul va iniializa variabila cu valoarea indicat. La un nou apel ulterior al aceleiai funcii, nu se mai face iar iniializarea. Variabilele statice pot fi interne sau externe. a) Variabilele statice interne sunt locale funciilor, dar spre deosebire de cele declarate cu auto i pstreaz valoarea pe parcursul executrii programului. Aceste variabile sunt importante n definirea funciilor de sine-stttoare atunci cnd se dorete pstrarea valorii lor ntre dou apelri. Un exemplu de astfel de funcii este cel al funciilor utilizate la generarea seriilor de numere care calculeaz o valoare plecnd de la valoarea precedent. O alt soluie care se poate adopta pentru pstrarea valorii anterioare const n utilizarea unei variabile globale, care ar #include<iostream.h> trebui s fie declarat de fiecare dat. n plus, trebuie avut grij ca aceasta s int serie(int q) { nu interfereze cu alte variabile globale deja amplasate n alte fiiere surs. static int termen_serie=10; n exemplul din fig. 5.11 se genereaz seria aritmetic cu n numere termen_serie+=q; ntregi care are primul termen 10. return (termen_serie);} b) Variabilele statice externe se declar n afara oricrei funcii (sunt globale), dar sunt recunoscute doar de ctre toate funciile care fac parte din void main(void){ acelai fiier surs. Dac se dorete ca anumite variabile globale dintr-un int ratia,n,i; anumit fiier s nu poat fi accesate de funcii din afara acestuia (din alte cout<<dati numarul de termeni<<endl; fiiere), trebuie ca respectivele variabile s fie declarate utiliznd static. cin>>n; 4. Variabilele registru sunt declarate cu specificatorul de clas register. cout<<dati ratia<<endl; Aceste variabile sunt locale funciilor i blocurilor. Iniial specificatorul de cin>>ratia; clas register cere compilatorului s pstreze valoarea variabilei de tip for(i=1;i<=n;i++) register ntr-un registru al procesorului n loc de a o stoca n memoria intern cout<<serie(ratia)<<endl;} (a a cum procedeaz n mod obinuit). Acest lucru determin ca operaiile Fig. 5.11 aplicate asupra unei variabile de acest tip s se desfoare cu o vitez mult mai mare n raport cu o variabil normal. ntr-un program, numrul permis de variabile register care beneficiaz de optimizarea vitezei este determinat att de mediul de programare ct i de varianta de implementare a compilatorului. Curs6/ 1

#include<iostream.h> int factorial(int val){ if (val==1) return (1); else return (val*factorial(val-1));} void main(void){ int i; for(i=1;i<=5;i++) cout<<factorial de<<i<<=<<factorial(i)<<endl;} Fig. 5.12

5.8. Funcii recursive


O funcie recursiv este o funcie care se apeleaz pe sine nsi pentru a efectua o anumit operaie, iar procesul n care o funcie se apeleaz pe sine nsi se numete recursivitate. n exemplul din fig. 5.12 este definit o funcie factorial, care calculeaz factorialul numrului ntreg furnizat ca parametru. Apoi, n funcia main , se apeleaz factorial ntr-un ciclul for pentru a afia factorialul primelor 5 numere naturale. Se observ ca funcia factorial returneaz un rezultat care se bazeaz pe propriul ei rezultat. n fig. 5.13 se descrie lanul de apelri recursive i de returnri de valori la apelul factorial(3). O funcie recursiv este oarecum asemntoare cu o structur ciclic, deoarece trebuie precizat o condiie de ncheiere. Dac nu se face aceast precizare, funcia nu se sfrete niciodat. n acest exemplu, condiia de ncheiere este factorial(1) care, prin definiie, este 1. Dac funcia se apeleaz pe sine nsi pentru a ndeplini o sarcin, funcia execut un proces recursiv direct . Forma mai dificil a recursivitii, recursivitatea indirect, are loc atunci cnd o funcie (s o notm cu A) apeleaz o alt funcie (s o notm cu B), care la rndul su o apeleaz pe A. Acest tip de recursivitate poate conduce la realizarea unui cod dificil de neles, aa c de obicei trebuie evitat utilizarea sa. Funciile recursive sunt lente, pentru c la fiecare apel se introduce n program o suprasarcin de apel. De aceea se recomand pe ct posibil evitarea utilizrii recursivitii. Orice funcie care poate fi scris ntr-o form recursiv poate fi de asemenea scris ntr-o structur ciclic. n exemplu din fig. 5.14 se prezint rezolvarea problemei din fig. 5.12, dar fr a utiliza recursivitatea. n exemplul din fig. 5.15 se prezint un program n care se calculeaz i afieaz suma, diferena i produsul a dou numere reale, furnizate sub form de date de intrare de ctre utilizator. Se utilizeaz o funcie f care returneaz suma. Diferena i produsul sunt transmise ctre funcia care o apeleaz pe f deoarece n lista de parametri formali ai lui f se utilizeaz doi parametri transmii prin adres: xy va memora produsul iar x_y va memora diferena. Un alt exemplu de utilizare a funciilor este urmtorul: se dau numerele naturale n i k ( n k ). S se determine combinri de n luate cte k. Se utilizeaz formula:

#include<iostream.h> int factorial(int val){ int rezultat=1; int contor; for(contor=2;contor<=val;contor++) rezultat*=contor; return (rezultat);} void main(void){ int i; for(i=1;i<=5;i++) cout<<factorial de<<i<<=<<factorial(i)<<endl;} Fig. 5.14 #include<iostream.h> float f(float x, float y, float *xy, float *x_y){ *xy=x*y; *x_y=x-y; return(x+y);} void main(void){ float a,b,s,d,p; cout<<a=<<endl;cin>>a; cout<<b=<<endl;cin>>b; s=f(a,b,&p,&d); cout<<suma=<<s<<,dif.=<<d<<,prod=<<p;} Fig. 5.15

C k n = n! /(( n k )!* k! ) . Se va folosi o funcie definit de


utilizator pentru calculul unui produs factorial (fig. 5.16). n acest exemplu s-a artat i cum se poate face validarea datelor introduse de utilizator. Astfel, dac se dau valori greite, se reia citirea datelor.

CAPITOLUL 6. TABLOURI SI SIRURI DE CARACTERE


6.1. Declararea i iniializarea unui tablou. Referirea elementelor unui tablou

Un tablou reprezint o variabil care poate s pstreze mai multe valori de acelai tip. Pentru a declara un tablou, trebuie specificat tipul elementelor care l compun precum i numrul lor. Sintaxa de declarare a unui tablou este: tip_elemente_tablou nume_tablou[dim_1] [dim_2],...,[dim_n], unde:

Curs6/

#include<iostream.h> int fact(int val){ int rezultat=1; int contor; for(contor=2;contor<=val;contor++) rezultat*=contor; return (rezultat);} void main(void){ int n,k,combinari; do { cout<<n;cin>>n; cout<<k;cin>>k;} while((k>n) || (k<1) || (n<1)); combinari=fact(n) / fact(n-k) / fact(k); cout<<comb. de<<n<<luate cate<<k<<=<<combinari;} Fig. 5.16

- tip_elemente_tablou precizeaz tipul elementelor tabloului (int, char, float sau derivate ale lor); - nume_tablou este un identificator utilizator care reprezint numele tabloului prin intermediul cruia vor fi referite componentele (elementele) tabloului; - dim_i (i=1,...n) sunt date ntregi, strict pozitive (literali, constante) care precizeaz mrimea tabloului. Numrul datelor dim_i determin dimensiunea tabloului. Pentru tablourile unidimensionale (vectori, iruri) se precizeaz o singur dat dim_1, pentru matrici bidimensionale (dreptunghiulare) se precizeaz dou date dim_1, dim_2, .a.m.d. Adresarea unei componente se face prin indice, ncadrat de paranteze drepte. Tabloul declarat prin int v[100] poate conine maxim 100 de componente de tip int. Indicii componentelor lui v pot lua valori n gama [0,99]. De

exemplu, cnd vrem s adresm componenta a doua, scriem v[1]. De exemplu prin float a[10][9] se declar o matrice de 10 linii, 9 coloane, cu elemente de tip float. Indicii liniilor pot avea valori n plaja [0,9], iar cei afereni coloanelor pot lua valori n plaja [0,8]. Primul element este a[0,0], iar ultimul este a[9,8]. Observaie n C nu se poate declara o variabil de tip tablou cu un numr variabil de componente. De aceea, cnd nu se cunoate dinainte valoarea la care poate ajunge un indice, se rezerv un numr maxim de componente, cel care este necesar pentru acea execuie a programului n care indicele este maxim. Astfel, de multe ori, o parte din componente rmn neutilizate. Tablourile pot fi iniializate. Cnd se atribuie valori iniiale, acestea trebuie ncadrate ntre acolade. De exemplu prin int a[5]={3,2,5,10,77} s-a iniializat tabloul a a..: a[0]=3; a[1]=2; a[2]=5;a[3]=10;a[4]=77. Urmtoarea instruciune atribuie 3 valori unui tablou care poate pstra 20! float s[20]={2.0,-3.0,0.0} n funcie de compilator, se poate atribui valoarea 0 elementelor pentru care programul nu atribuie n mod explicit o valoare. Ca regul ns, nu trebuie s se presupun c va iniializa compilatorul celelalte elemente. Mai mult, dac nu se precizeaz dimensiunea tabloului, compilatorul va aloca atta memorie ct este necesar pentru a pstra numai valorile specificate. Pentru a se evita, prin iniializare, depirea dimensiunilor tablourilor i deci apariia erorilor legate de aceast situaie, se folosesc tablouri adimensionale, conform sintaxei: tip_element_tablou nume_tablou[ ][ ]...={lista_de_valori}; Compilatorul va crea automat #include <stdio.h> #include <stdio.h> tablouri suficient de mari pentru a void main(void) { #define DIMENSIUNE 5 memora toi literalii de iniializare. int val[5]={4,2,19,5,7}; void main(void) { Exemplu: int e[ ]={1,5,12}. int i; int val[DIMENSIUNE]={4,2,19,5,7}; Atunci cnd se lucreaz cu un for(i=0;i<5;i++) int i; tablou trebuie specificat printf(val[%d] %d\n,i,val[i]);} for(i=0; i<DIMENSIUNE; i++) dimensiunea acestuia. n programul printf(valorile[%d] %d\n,i,val[i]);} din fig. 6.1 a) se declar un tablou cu (a) (b) 5 valori i apoi se utilizeaz un ciclu Fig. 6.1 for pentru a afia valorile sale. Dac ulterior se dorete modificarea acestui program a.. acesta s accepte 10 valori, trebuie operate dou modificri, att n dimensiunea declarat a tabloului ct i n ciclu. Cu ct se aduc mai multe modificri programului, cu att va crete i ansa de a se produce erori. O alternativ este utilizarea de constante pentru dimensiunile tablourilor, ca n fig. 6.1 b). Dac ulterior trebuie modificate dimensiunile tabloului se pot modifica numai valorile constantelor utilizate pentru dimensiuni. Relativ la iniializarea elementelor intr-un tablou bidimensional, se utilizeaz o #include <iostream.h> void main(void){ int v[100],n,i; cout<<introduceti numarul de componente; cin>>n; for(i=0;i<n;i++) { cout<<v[<<i<<]=; cin>>v[ i ];} for(i=0;i<n;i++) cout<<v[ i ]<<endl; } Fig. 6.3 tehnic asemntoare cu cea utilizat la iniializarea unui tablou cu o singur dimensiune, ca n exemplul urmtor: int tabel[2][3]={{2,3,1}, {3,-2,5}}; Tablourile pot avea i mai mult de dou dimensiuni (exemplu n fig. 6.2). Pentru a nelege cum se iniializeaz un tablou cu 3 dimensiuni, se prezint exemplul de mai jos. int b[2][3][4]={ { {1,2,3,4},{5,6,7,8},{2,4,2,1}}, { {9,2,3,1},{3,6,8,8},{2,4,6,2}} } 3

Curs6/

#include <iostream.h> void main(void){ float a[100], b[100]; int n,i; cout<<introduceti numarul de componente; cin>>n; for(i=0; i<n; i++){ cout<<a[<<i<<]=; cin>>a [ i ]; b[ i ]=a[ i ];} for(i=0; i<n ;i++) cout<<b[ i]<<endl; } Fig. 6.4 #include <iostream.h> void main(void){ int m,n,i,j,a[9][9]; cout<<introduceti nr. de linii; cin>>m; cout<<introduceti nr. de coloane; cin>>n; for(i=0;i<m;i++) for(j=0;j<n;j++) {cout<<a[<<i<<][<<j<<]=; cin>>a[ i ][ j ];} for(i=0;i<m;i++){ for(j=0;j<n;j++) cout<<a[ i ][ j ]<< ; cout<<endl;} } Fig. 6.5 struct Angajat{ char nume[30]; int varsta; char numar_asig[11]; int categ_salarizare; float salariu; unsigned nr_angajat; struct Date { int luna; int ziua; int anul; } date_angajat[3]; } personal[100]; Fig.6.6

Se observ c fiecare iniializare a unui tablou este redat ntre acoladele exterioare. ntre cele dou acolade exterioare, fiecare dintre elementele tabloului este definit ntre alte acolade. Exemple de programe care utilizeaz tablouri Exemplul 1: Programul din fig. 6.3 citete i apoi tiprete componentele unui vector v[n]. Exemplul 2: n programul din fig. 6.4 se citete vectorul a, care are componente de tip float. Apoi se copiaz valorile sale, prin atribuire, n componentele vectorului b. Observaie Dac a i b sunt tablouri, nu sunt permise atribuiri de forma b=a. Atribuirea trebuie s se fac pe componente. Exemplul 3: n programul din fig. 6.5 se citesc i tipresc elementele unui tablou (m x n). La afiare fiecare linie a tabloului apare pe o linie separat.

6.2. Tablouri de structuri ce conin alte tablouri de structuri


Tablourile i structurile permit gruparea informaiilor nrudite. Se pot crea tablouri de structuri i se pot utiliza tablouri ca membri ai unor structuri. De exemplu declaraia din fig. 6.6 creeaz un tablou de 100 de structuri de angajai. n cadrul fiecrei structuri exist un alt tablou, cu 3 componente care sunt structuri de tip Date, acestea corespunznd datei de angajare a salariatului, datei corespunztoare primei i respectiv ultimei sale examinri. Pentru accesarea membrilor i elementelor matricei se va lucra de la stnga la dreapta, ncepnd din exterior spre interior. n fig. 6.7 se prezint un exemplu prin care se atribuie data de angajare a celui de al 11-lea salariat memorat de tabloul personal.

6.3.Uniunea (UNION)
Structurile permit pstrarea de informaii legate ntre ele. Uneori trebuie stocate ntr-o structur informaii care nu vor consta numai din una sau dou valori. De exemplu s presupunem c un program urmrete valorile a dou date speciale pentru fiecare angajat. Pentru persoanele angajate n prezent intereseaz numrul de zile lucrate de angajat. Pentru persoanele care nu mai lucreaz n cadrul societii intereseaz data ultimei sale zile de lucru. O cale pentru a memora o astfel de informaie poate fi utilizarea unei structuri, ca n fig. 6.8 (a). Deoarece programul va utiliza fie membrul zile_lucru, fie membrul ultima_zi, memoria care pstreaz informaia neutilizat se va irosi. Ca alternativ, compilatorul permite utilizarea union-ului, care aloc numai memoria cerut de cel mai mare dintre membrii structurii, aa cum se prezint n fig. 6.8 (b). Accesarea membrilor structurii se face ca i n cazul structurilor, folosind operatorul ". " (dot). Spre deosebire de structur, uniunea pstreaz numai valoarea unui membru. Fig. 6.9 ilustreaz modul n care compilatorul aloc memorie pentru structur i uniune (s-a presupus c pentru memorarea unei variabile de tip int se utilizeaz 4 octei).

personal[10].date_angajat[0].luna=11; personal[10].date_angajat[0].ziua=3; personal[10].date_angajat[0].anul=2001; Fig. 6.7 struct date_angajat{ union date_angajat{ int zile_lucru; int zile_lucru; struct Ultima_data struct Ultima_data { { int luna; int luna; int ziua; int ziua; int anul; int anul; } ultima_zi; } ultima_zi; } } (a) (b) Fig. 6.8 Curs6/ 4

Cursul 7 6.4. Structurile cmp de bii


Atunci cnd biii care compun o valoare au o semnificaie specific, programele pot utiliza operatorii C pe bii pentru a extrage biii respectivi. S presupunem de exemplu c ntr-un program se manipuleaz 10000 de date calendaristice. O prim abordare a problemei este cea n care se utilizeaz o structur de date de tip data, ca n fig. 6.10. O alt soluie este cea care utilizeaz bii specifici, acetia fiind reunii n cadrul unei valori unsigned short int n scopul memorrii celor 3 cmpuri, ca n fig. 6.11 (s-a presupus c o variabil de tipul int se memoreaz pe 32 bii). Observaie Numrul de unsigned data; bii necesari pentru ... memorarea fiecrei zone data=luna;// se atribuie cei mai din dreapta 4 biti pentru luna de bii s-a calculat astfel: data=data | (ziua<<4); // se face OR pe biti pentru campul ziua deplasat la stanga cu 4 pozitii pentru memorarea // corespunzatoare memorarii campului luna cmpului luna , care data=data | (anul<<9); // se face OR pe biti pentru campul anul deplasat la stanga cu 9 pozitii poate atinge valoarea // corespunzatoare memorarii campurilor luna si ziua maxim 12 (adic 24 -4) ... sunt necesari 4 bii, deci Fig. 6.12 se rezerv primii 4 bii (0...3) .Pentru memorastruct Data data.luna=12; rea cmpului ziua , care poate atinge valoarea maxim { data.ziua=31; 5 31 (adic 2 -1) sunt necesari 5 bii, deci se rezerv unsigned luna:4; data.anul=94; urm torii 5 bi i (4...8). Pentru memorarea cmpului unsigned ziua:5; cout<<data.luna<<data.ziua<<data.anul; anul , care va re ine doar ultimele dou cifre i poate unsigned anul:7; atinge valoarea maxim 100 (adic 27 -28) sunt } data; necesari 7 bii, deci se rezerv urmtorii 7 bii (9...15). (a) (b) Apoi, ori de cte ori programul urmeaz s Fig. 6.13 atribuie data, el poate executa operaiile corecte pe bii, ca n fig. 6.12. Pentru a face programele mai uor de neles, compilatorul de C permite crearea unei structuri cmp de bii. Atunci cnd se declar o astfel de structur, se definete o structur care specific nelesul biilor corespunztori, aa cum se prezint n fig. 6.13 a). Programele vor face referire individual la cmpul de bii, dup cum se exemplific n fig. 6.13 b). Observaie Atunci cnd se declar o structur cmp de bii, fiecare membru al structurii trebuie s fie o valoare de tip unsigned int. struct data { int luna; int ziua; int anul; } Fig. 6.10

6.5. Funcii care folosesc ca argumente tablouri


Atunci cnd se apeleaz o funcie care are ca argument un tablou, acesteia i se va transmite un pointer la primul element al tabloului (acest pointer reine adresa de la care ncepe memorarea tabloului). Observaie n C numele unui tablou unidimensional urmat de dou paranteze drepte ntre care nu se specific nimic reprezint un pointer la primul element al tabloului. (Ex. v [ ]). Asemntor v [ ] [ ] reprezint un pointer spre primul element al tabloului bidimensional v, etc. Relativ la declararea unui parametru formal al unei funcii care urmeaz s primeasc un pointer la un tablou, se poate spune c n C exist 3 modaliti prin care se poate realiza acest lucru, prezentate n cele ce urmeaz. a) Declararea parametrului formal ca i tablou dimensionat Exemplificm acest caz prin programul din fig. 6.14 , n care n funcia main se genereaz elementele unui vector a cu formula: a[i]=3*i. Apoi se apeleaz o funcie definit de utilizator, numit #include<iostream.h> afiseaza, care are ca parametru un tablou dimensionat. Funcia afieaz void afiseaza(int v[15]) { componentele vectorului a generat n funcia main. int k; b) Declararea parametrului formal ca i tablou nedimensionat Considerm cout<<compon. vect.<<endl; acelai program prezentat la punctul a). Se nlocuiete v [15] cu v [ ]. n acest for(k=0;k<15;k++) caz compilatorul convertete automat pe v [ ] la un pointer spre o valoare de cout<<v[<<k<<]=<<v[k]<< ;} tip ntreg, valoare care este prima component a tabloului. c) Declararea parametrului formal ca pointer void main(void) { Considerm acelai program prezentat la punctul a). Se nlocuiete v[15] int a[15],i; cu *v. Acest tip de declaraie este permis deoarece orice pointer poate fi for(i=0;i<15;i++) a[i]=3*i; indexat folosind paranteze drepte, asemntor unui tablou. afiseaza(a);} Toate cele 3 metode de declarare a unui tablou ca parametru produc Fig. 6.14 acelai rezultat: un pointer. Exemplu Se dau matricile a,b i c de dimensiuni n x n. S se calculeze matricea s=a*b+c*a. S se afieze a,b,c,s. Soluia este prezentat n fig. 6.15. O constant de tip ir de caractere se reprezint prin ncadrarea caracterelor irului ntre ghilimele, ca n exemplul urmtor: Curs7/ 1

#include<iostream.h> #define nmax 10 void citeste(int n, char nume, float x[nmax][nmax]) { int i,j; for(i=0;i<n;i++) for(j=0;j<n;j++) { cout<<nume<<"["<<i<<"]["<<j<<"]="; cin>>x[i][j];}} void scrie(int n, float x[nmax][nmax]) { int i,j; for(i=0;i<n;i++) { for(j=0;j<n;j++) cout<<x[ i ][ j ]<<" "; cout<<endl;}} void produs(int n, float x[nmax][nmax],float y[nmax][nmax],float xy[nmax][nmax]) { int i,j,k; for(i=0;i<n;i++) for(j=0;j<n;j++){ xy[ i ][ j ]=0; for(k=0;k<n;k++) xy[ i ][ j ]= xy[ i ][ j ]+x[ i ][ k ]*y[ k ][ j ];}} void main(void) { int n,i,j; float a[nmax][nmax], b[nmax][nmax], c[nmax][nmax]; float ab[nmax][nmax], ca[nmax][nmax], s[nmax][nmax]; do { cout<<"n=";cin>>n;} while((n<1) || (n>nmax)); //validare introducere date citeste(n,'a',a); citeste(n,'b',b); citeste(n,'c',c); produs(n,a,b,ab); produs(n,c,a,ca); for(i=0;i<n;i++) for(j=0;j<n;j++) s[ i ][ j ]=ab[ i ][ j ]+ca[ i ][ j ]; cout<<"matricea a"<<endl;scrie(n,a); cout<<"matricea b"<<endl;scrie(n,b); cout<<"matricea c"<<endl;scrie(n,c); cout<<"matricea s"<<endl;scrie(n,s);} Fig. 6.15 #include <stdio.h> void main(void){ char sir[256]; int i; for(i=0;i<26;i++) sir[i]=A+i; sir[i]=NULL; printf(sirul de caractere contine %s\n,sir);} Fig. 6.17 #include <stdio.h> void main(void){ char sir[256]; int i; printf(introduceti sirul si apoi apasati Enter:\n ); gets(sir); for(i=0;sir[i]!=NULL;i++) putchar(sir[i]); printf(numarul de caractere in sir este %d\n,i);} Fig.6.18 Curs7/

"Sir de caractere 234"

Atunci cnd se utilizeaz o constant de acest tip ntr-un program, compilatorul C va aduga automat caracterul NULL (\0) la sfritul irului. Constanta din exemplul nostru va fi stocat n memorie aa cum reiese din fig. 6.16.

6.6.2. Stocarea unui ir de caractere Unele programe utilizeaz pe scar larg iruri de caractere. De exemplu unele programe utilizeaz iruri de caractere pentru a citi fiiere sau date de la tastatur, precum i pentru alte operaii. n C un ir de caractere este un tablou de caractere terminat cu NULL. Pentru a crea un ir de caractere, se declar pur i simplu un tablou de caractere, ca n exemplul urmtor: char sir[256]. Compilatorul va crea pentru irul din acest exemplu un ir capabil s pstreze 256 de caractere, pe care le va indexa ncepnd cu sir[0] pn la sir[255]. Deoarece irul poate conine mai puin de 256 de caractere, se utilizeaz NULL pentru a reprezenta ultimul caracter al irului. n exemplul din fig. 6.17 se definete un ir de caractere de dimensiunea 256 i apoi se atribuie primelor 26 de locaii literele mari ale alfabetului latin. Observaie Atunci cnd se lucreaz cu caractere se poate utiliza valoarea numeric a caracterului n reprezentarea ASCII sau se poate plasa caracterul respectiv ntre apostrofuri (ex. 'A'). Dar atunci cnd se utilizeaz ghilimelele (ex. "A"), compilatorul creeaz un ir de caractere care conine litera specificat i termin irul cu caracterul NULL. n concluzie, deoarece sunt stocate n mod diferit, constantele de tip caracter i cele de tip ir de caractere nu sunt similare i trebuie tratate diferit n cadrul programelor. Exemplu n fig. 6.18 se prezint un program care realizeaz urmtoarele: utilizatorul este invitat s introduc de la tastatur un ir de caractere, iar dup ce a introdus i ultimul caracter trebuie s introduc Enter. Apoi, printr-un ciclu for se afieaz unul cte unul caracterele irului, pn cnd condiia sir[i]=NULL este evaluat ca fiind fals. 6.6.3. Funcii mai importante pentru lucrul cu iruri de caractere 1. Calculul lungimii unui ir n exemplul din fig. 6.18 nu s-au utilizat funcii specifice lucrului cu iruri de caractere. Exist ns o bibliotec (string.h) n care sunt implementate numeroase astfel de funcii. De exemplu funcia strlen returneaz numrul de caractere al irului furnizat ca parametru. n exemplul din fig. 6.19 se prezint un exemplu de utilizare a acestei funcii. 2

#include <stdio.h> #include <string.h> void main(void){ char sir[ ]=exemplu de sir; printf(%s contine %d caractere \n,sir,strlen(sir));} Fig. 6.19 #include <stdio.h> #include <string.h> void main(void){ char sir_copiat[ ]="exemplu de sir"; char sir_destinatie[128]; strcpy(sir_destinatie,sir_copiat); printf("sirul destinatie are continutul %s",sir_destinatie);} Fig. 6.20

Atunci cnd se execut programul, se afieaz: exemplu de sir contine 14 caractere. 2. Copierea unui ir de caractere in altul Cu ajutorul funciei strcpy se poate copia coninutul unui ir de caractere (parametrul surs) n alt ir de caractere (parametrul destinaie). Funcia strcpy returneaz un pointer care indic nceputul irului destinaie i are urmtorul prototip: char *strcpy(char *destinatie, const char *sursa); n programul din fig. 6.20 se prezint un exemplu de copiere a unui ir (memorat de variabila cu numele sir_copiat) ntr-un alt ir (memorat de variabila cu numele sir_destinatie).

3. Alte funcii utile pentru lucrul cu iruri Biblioteca string.h este vast, coninnd multe funcii utile. Spaiul cursului nu permite explicarea tuturor. Merit menionate ca mai uzuale: - strchr si strrcchr care primesc 2 parametri: primul este un sir n care se efectueaz cutarea caracterului precizat ca al doilea parametru. Prima funcie returneaz pointer la prima apariie a caracterului, a doua la ultima apariie a caracterului. Dac acesta nu este gsit, se returneaz NULL. - strcmp primeste ca parametri dou siruri s1 si s2 care sunt comparate (conform ordinii lexicografice). Returneaz o valoare care este: negativ dac s1<s2, egal cu 0 dac s1=s2 si respectiv pozitiv dac s1>s2. - strrev inverseaz sirul primit ca parametru; - strstr primeste 2 parametri: sir1 si sir2. Se returneaz pointer spre acel element din sir1 de la care ncepe sir2 (dac sir1 include pe sir2) sau NULL n caz contrar.

CAPITOLUL 7. FUNCII MATEMATICE


n fig. 7.1. este prezentat coninutul bibliotecii math.h aferente versiunii de Turbo C cu care se lucreaz la laborator (asa cum l prezint help-ul). Nume functie asin acos atan atan2 sinh,cosh,tanh ceil floor frexp #include <stdio.h> #include <math.h> void main(void) { double x; printf(x acos(x) asin(x) atan(x)\n); for(x = - 0.5;x<=0.5; x+=0.2) printf(%f %f %f %f \n, x, acos(x), asin(x), atan(x));} Fig. 7.2 #include <stdio.h> #include <math.h> void main(void) { double numarator=10.0; double numitor=3.0; printf(fmod(10,3) este %f \n,fmod(numarator,numitor));} Fig. 7.3 Argumente Observatii x Rezultat in radiani, in [-pi/2,pi/2] x Rezultat in radiani, in [0,pi] x Rezultat in radiani, in [-pi/2,pi/2] x,y Arctang(x/y) x X in radiani x Returneaza cel mai mic intreg>=x x Returneaza cel mai mare intreg<=x x Calculeaza mantisa si exponentul Tabelul 7.1

n tabelul 7_1 se prezint informaii sumare despre cele mai importante dintre acestea. Funciile matematice incluse pot fi grupate astfel: 1) Funcii trigonometrice inverse. Forma general a prototipului acestor funcii este: double nume_funcie(double expresie), unde nume_funcie poate fi: asin, atan, acos Excepie face atan2, care are prototipul: double atan2(double y, double x). n exemplul din fig. 7.2 se calculeaz i afieaz valorile funciilor arccos, arcsin i atan pentru argumentul funciei variind n intervalul [-0.5,0.5], cu pasul de incrementare 0.2. 2) Funcii trigonometrice directe si hiperbolice. Forma general a prototipului acestor funcii este:

double nume_funcie(double expresie), unde nume_funcie poate fi: sin, tan, cos, sinh, tanh, cosh. 3) Funcii pentru rotunjirea numerelor reale n virgul mobil. Prototipul lor este la fel cu cel al funciilor trigonometrice directe, nume_funcie putnd s fie: floor si respectiv ceil. 4) Funcie pentru determinarea restului real al mpririi a dou numere de tip double. Are prototipul : double fmod(double x, double y) si returneaz restul real al mpririi lui x la y. Curs7/ 3

Programul din fig. 7.3 afieaz restul real al mpririi numrului real 10.0 la numrul real 3.0. Programul afieaz: fmod(10,3) este 1.000000 #include <stdio.h> #include <math.h> void main(void) { double val=1.2345; double parte_intreaga; double fract; fract=modf(val,&parte_intreaga); printf(valoare %f, parte intreaga %f parte fractionara %f\n,val, parte_intreaga, fract);} Fig. 7.4 #include <stdio.h> #include <math.h> void main(void) { float val; printf( argument exponentiala\n); for(val = 0.0; val<=1.0; val+=0.1) printf (%f %f \n, val, exp(val));} Fig. 7.5 5) Funcie pentru determinarea prii ntregi si respectiv a celei fracionale dintr-un numr real. Pentru a determina partea ntreag si respectiv fracionar dintr-un numr real se poate utiliza funcia modf, care are prototipul:

double modf(double x, double *ipart) Efectul execuiei funciei este urmtorul: returneaz partea fracionar si memoreaz partea ntreag n *ipart. Atunci cnd se execut programul din fig. 7.4, se afieaz: valoare 1.234500 parte intreaga 1.000000 parte fractionara 0.234500 6) Funcii pentru lucrul cu funcia exponenial si cu logaritmi. Forma general a prototipului acestor funcii este: double nume_funcie(double expresie), unde nume_funcie poate fi: #include <stdio.h> #include <math.h> exp, log si log10. void main(void) { Programul din fig. 7.5 calculeaz i afieaz ex pentru x parcurgnd int putere; domeniul [0,1], cu pasul de 0.1. printf( p 2 la puterea p\n); 7) Funcii pentru lucrul cu puteri for(putere = -1; putere<=2; putere++) printf (%d %f \n, putere, pow(2.0,putere)); Funcia pow returneaz rezultatul evalurii expresiei xN . Prototipul printf( p 10 la puterea p\n); este: for(putere = -1; putere<=2; putere++) double pow(double x, double N) printf (%d %f \n, putere, pow10(putere));} Funcia pow10 returneaz rezultatul evalurii expresiei 10x. Fig. 7.6 Prototipul este: double pow10(double x) Programul din fig. 7.6 calculeaz i apoi afieaz puterile ntregi ale lui 2, #include <stdio.h> respectiv 10, puterile fiind cuprinse n plaja de valori [-1,2]. #include <math.h> void main(void) { 8) Funcii pentru calculul modulelor float val; Valoarea absolut (modulul) unei expresii de tip ntreg se calculeaz printf( argument modul\n); folosind funcia abs, implementat n biblioteca stdlib.h. for(val = - 1.0; val<=1.0; val+=0.1) Prototipul funciei este : int abs(int expresie). printf (%f %f \n, val, fabs(val));} n math.h este implementat si funcia labs, care primeste si returneaz Fig. 7.7 valori de tip longint. Pentru modulul unei expresii reale se utilizeaz fabs #include <stdio.h> (din math.h) , cu prototipul: #include <math.h> float fabs(float expresie) void main(void) { n programul din fig. 7.7 se calculeaz i afieaz struct complex numar_complex; valorile absolute ale numerelor reale din domeniul [-1,1], numar_complex=complex(3,4); parcurs cu pasul 0.1. printf(modulul lui (3,4) este %f\n, abs(numar_complex));} Obinerea modului unui numr complex Fig. 7.8 n biblioteca complex.h se defineste structura complex cu ajutorul creia se poate reprezenta un numr #include <stdio.h> complex. Prin funcia complex acesta poate fi creat, dac #include <math.h> funcia primeste ca parametri partea sa real si respectiv void main(void) { pe cea imaginar. Modulul unui numr complex se double val; poate calcula folosind funcia abs din biblioteca for(val = 0.0; val<=10.0; val+=0.1) complex.h , cu prototipul: double abs(struct complex printf (valoarea %f radacina patrata %f \n, val, sqrt(val));} valoare) . Fig. 7.9 n fig. 7.8 se prezint un exemplu de utilizare a acestei funcii. Dup executarea programului, se va afia: modulul lui (3,4) este 5. 9) Calculul rdcinii ptrate a unei valori reale Funcia sqrt, implementat n math.h, se utilizeaz pentru extragerea rdcinii ptrate a valorii precizate ca parametru. Prototipul funciei este: double sqrt(double val); n fig. 7.10 se prezint un program utilizat pentru calcularea i afiarea rdcinilor ptrate ale numerelor din [0,10], echidistanate printr-un pas de 0.1. 10) Calculul valorii unui polinom este posibil datorit funciei poly, cu prototipul: double poly(double x,int grad,double coeficieni[]). Aceast funcie returneaz valoarea polinomului precizat prin coeficienii si gradul su, pentru valoarea argumentului x. Curs7/ 4