Sunteți pe pagina 1din 22

ALGORITMI I PROGRAMARE

Prof. univ dr. GRIGORE ALBEANU


Lector univ. SILVIU BRZ
I. INTRODUCERE
I.1. Ce este informatica?
n anul 1642, matematicianul i fizicianul Blaise Pascal (1623-1662) a inventat prima masin
mecanic, cu roi dinate, capabil s realizeze operaii de adunare i scdere a numerelor naturale. Totui,
de-abia dup apariia mainilor electromecanice, n 1944, John von Neumann a formulat principiul
programului nregistrat i a sugerat constructorilor de calculatoare trei principii care trebuie avute n vedere
pentru realizarea unui calculator:
programele i datele trebuie s fie codificate sub form binar;
programele i datele trebuie stocate ntr-o memorie a mainii de calcul;
trebuie s existe o component (unitate central de prelucrare, procesor) special care tie att s
execute operaii de calcul, ct i s extrag, s decodifice i s execute instruciunile programului.
Astfel, aproape toate tipurile de sisteme de calcul ce au aprut mai trziu sunt calculatoare de tip von
Neumann.
Apariia sistemelor de calcul a dus la apariia i dezvoltarea unei noi tiine: informatica
(Informatique, Informatics, Informatik n Europa, respectiv Computer Science n SUA). Informatica
reprezint un complex de discipline prin care se asigur prelucrarea informaiilor cu ajutorul sistemelor de
calcul. Astzi, informatica este prezent n industrie, bnci, ferme, art, medicin, tiine sociale etc. i este
structurat n mai multe domenii precum:
arhitectura sistemelor de calcul: studiaz modul de organizare a sistemului fizic (hardware) pentru a
se obine o mai mare eficient, siguran i utilitate.
sisteme de operare: studiaz modalitile de gestiune eficient a resurselor fizice i a programelor.
algoritmi si structuri de date: studiaz metodele de rezolvare a problemelor i modurile de
organizare a datelor pentru a obine programe eficiente.
limbaje de programare: studiaz modalitile prin care algoritmii i structurile de date sunt
prezentate calculatorului pentru a fi prelucrate.
ingineria programrii: studiaz metodele de automatizare a proceselor de proiectare, analiz, testare
i reutilizare a programelor.
calcule numerice i simbolice: studiaz modalitile de reprezentare a informaiei numerice pentru
implementarea unor algoritmi numerici robuti, eficieni i de mare precizie.
sisteme de gestiune a bazelor de date: studiaz modalitile de structurare i organizare eficient a
coleciilor mari de date ce vor fi supuse diverselor prelucrri.
inteligena artificial: studiaz modalitile de reprezentare i manipulare a cunotinelor n vederea
obinerii de noi cunotine.
animaia i robotica: studiaz modalitile de reprezentare, prelucrare i analiz a informaiei audiovizuale.
n sfera sa de preocupri, informatica a atras i dezvoltat o mare varietate de discipline precum: logica
matematic, teoria automatelor, limbaje formale, cercetri operaionale, teoria grafurilor i reelelor, calcul numeric,
teoria fiabilitii, geometrie computaional, teoria calculabilitii, baze de date, baze de cunotine, sisteme expert .
I.2. Ce este un program? Noiunea de algoritm
Soluia unei probleme, din punct de vedere informatic, este dat printr-o mulime de comenzi
(instruciuni) explicite i neambigue, exprimate ntr-un limbaj de programare. Aceast mulime de
instruciuni prezentat conform anumitor reguli sintactice formeaz un program. Un program poate fi privit
i ca un algoritm exprimat ntr-un limbaj de programare. Totui, un algoritm descrie soluia problemei
independent de limbajul de programare n care este redactat programul.
Exist mai multe definiii ale noiunii de algoritm. A. A. Markov, a considerat algoritmul ca fiind o
noiune matematic primar i a descris-o astfel: Un algoritm este o reet care descrie precis i clar un
proces de calcul. El a descris un mecanism formal pentru a specifica o clas larg de activiti i anume:
215

algoritmii normali. Alte modaliti de descriere a algoritmilor ce au mai fost propuse sunt: maina Turing,
sistemele Post, funciile recursive etc. n aceast lucrare, prin algoritm vom nelege o secvena finit de
comenzi explicite i neambigue care, executate pentru o mulime de date (ce satisfac anumite condiii
iniiale), conduce n timp finit la rezultatul corespunztor. Observm c se face distincie ntre algoritm (care
se termin n timp) i procedur (care poate continua nedefinit).
Conform lui D. Knuth (The art of computer programming, Vol. I, 1997) un algoritm posed cinci
caracteristici importante:
Un algoritm are caracter finit. El este descris printr-o secvena finit de etape i trebuie ca, ori de
cte ori sunt parcurse etapele algoritmului pentru anumite date, procesul s se ncheie n timp finit.
Un algoritm are caracter determinist. Aciunile specificate de paii algoritmului sunt clare, fiind
riguros prezentate.
Un algoritm are date de intrare. Se poate admite c ntotdeauna un algoritm lucreaz asupra unor
date de intrare. Acestea pot fi evideniate din contextul n care este formulat problema a crei
soluie o reprezint algoritmul.
Un algoritm furnizeaz cel puin o valoare de ieire ce se afl ntr-o relaie specific cu datele de
intrare.
Un algoritm este eficace.
Trebuie spus c nu orice problem admite soluie descris algoritmic. Problemele pentru care exist
un algoritm de rezolvare se numesc probleme decidabile. Problemele pentru care s-a demonstrat (matematic)
c nu admit un algoritm de rezolvare se numesc probleme nedecidabile. Nu este suficient ca o anumit
problem (clas de probleme) s admit soluii (chiar si o singur soluie). Din punctul de vedere al
informaticii, intereseaz dac exist soluie ce poate fi descris algoritmic, deci dac soluia problemei poate
fi construit efectiv. De asemenea, pentru rezolvarea anumitor probleme pot exista mai muli algoritmi.
Stabilirea celui mai bun dintre acetia se realizeaz n urma unui proces de analiz prin care se determin
performantele fiecruia dintre algoritmi.
Am vzut c algoritmii accept date de intrare i furnizeaz rezultate (date de ieire). Introducerea
unei valori sau a unui ir de valori se va descrie folosind verbul citete. Afiarea unei valori sau a unui ir de
valori va fi descris prin verbul scrie. Vom conveni s numerotm paii (etapele) unui algoritm. Aceast
numerotare va fi utilizat eventual n ali pai. Acest mod de prezentare a algoritmilor se numete descriere
n limbaj convenional. n unele lucrri, limbajul convenional mai este numit i limbaj pseudocod.
Exemplul 1. Fie a i b dou variabile ntregi. Dorim s schimbm ntre ele valorile celor dou
variabile. Mai precis, dac a = 640 i b = 480, dorim s obinem a = 480 i b = 640.
Un mod de a realiza aceast schimbare presupune utilizarea unei variabile suplimentare, cu rol de
intermediar. Folosind trei operaii de atribuire, algoritmul are urmtorii pai:
1. citete a, b
2. t := a
3. a := b
4. b := t
5. scrie a,b
I.3. Cum rezolvm probleme cu ajutorul calculatorului?
Am vzut c exist probleme pentru care nu poate fi dat un algoritm de rezolvare. Totui cele mai
multe probleme cu care se confrunt informatica sunt probleme decidabile. Toate temele tratate n aceast
lucrare formuleaz probleme decidabile.
Se tie c nu nvarea unui limbaj de programare este o sarcin dificil, ci rezolvarea algoritmic a
problemelor decidabile. Este clar c, nainte de a ncepe scrierea unui program trebuie, mai nti, s gsim
(sau s cunoatem deja) soluia algoritmic a problemei puse. Cum se gsete soluia? Etapele descrise de G.
Plya (Cum rezolvm o problem? Editura tiinific, Bucureti, 1965), pentru rezolvarea unei probleme de
matematic, sunt valabile i n informatic.
nainte de a ncepe s vedem cum se face, trebuie s nelegem att ipotezele problemei, ct i ceea
ce se cere. Deci, nelegerea problemei, ocup primul loc n procesul cutrii unei metode de rezolvare a
acesteia cu ajutorul calculatorului. Trebuie evideniate datele de intrare si condiiile pe care acestea trebuie s
le ndeplineasc. Este important s identificm esenialul. De multe ori un enun al unei probleme conine
foarte multe elemente descriptive privind importanta problemei, consideraii de natur istoric, exemple,
uneori chiar i etape distincte pentru obinerea soluiei. Cerina problemei furnizeaz, de multe ori, chiar idei
privind modul de a ajunge la soluie. Considerarea unor configuraii particulare pentru datele de intrare i
ncercarea de a lucra asupra lor, pentru a gsi soluia, va contribui ntotdeauna la o nelegere mai bun a
enunului.
216

Dac n enun se sugereaz etapele rezolvrii, acestea implicnd rezolvarea unor subprobleme, atunci
trebuie s aflm soluia algoritmic corespunztoare fiecrei etape. Dac nu se specific etape, dar putem
descompune problema n subprobleme mai simple, atunci soluia algoritmic a problemei iniiale se va
obine prin "compunerea" soluiilor subproblemelor. Deci, este foarte important s tim s rezolvm
probleme simple, eventual probleme reprezentative pentru anumite clase de aplicaii i s tim s
descompunem (respectiv, s reducem) problema iniiala n (la) subprobleme uor de rezolvat i apoi s
construim soluia final. Abordarea prin descompuneri repetate, cu detaliere pas cu pas se numete abordare
top-down sau rafinare iterativ. Abordarea prin care, pornind de la soluii algoritmice ale unor probleme
cunoscute, construim soluii ale altor probleme care au ns legtur cu problema de rezolvat, iar n final,
urmnd aceeai modalitate construim soluia problemei a crei soluie se cere, se numete abordare bottomup. Aceast metod permite reutilizarea programelor existente i este tot mai important odat cu apariia
tehnicilor orientate obiect. De asemenea, pentru a obine o soluie a unei probleme este util s privim
problema i comparativ cu alte probleme ntlnite. Numai dup investigarea acestor variante putem trece la
stabilirea metodei de abordare.
Pentru probleme de complexitate ridicat, oricare din metodele de abordare
top-down sau bottom-up,
conduc la o soluie modular, bazat pe subprograme sau, mai nou, la o soluie orientat obiect.
Multe din problemele de programare pot fi rezolvate uor dac soluia verific anumite principii.
Dac soluia problemei este o mulime de elemente care se poate obine pas cu pas, pornind de la mulimea
vid, prin adugarea celui mai bun element neconsiderat nc (i ales conform unui anumit criteriu) spunem
c avem de-a face cu o abordare de tip greedy. Pentru probleme n care se cere o soluie optim care satisface
principiul optimalitii (principiul lui Bellman) se va aplica metoda programrii dinamice. Alte strategii
pentru elaborarea algoritmilor sunt: metoda divide et impera, metoda backtracking, euristica etc.

II. ALGORITMI: DESCRIERE, COMPLEXITATE,

CORECTITUDINE

II.1. Noiuni de teoria grafurilor


Un graf neorientat G este definit prin perechea G = (V, E), unde V este o mulime nevid de
elemente numite vrfuri (vertex), iar E este o mulime (posibil vid) de perechi neordonate cu componente
distincte ale lui V care se numesc muchii (edges). Dac E este mulimea vid spunem c G este trivial. n
cazul n care mulimea V este finit spunem c avem un graf finit. Numrul elementelor mulimii V
determin ordinul grafului finit. O muchie cu vrfurile x i y (numite extremiti) se noteaz prin [x, y] sau
[y, x]. Spunem c vrfurile x i y sunt incidente muchiei [x,y].
Un digraf este definit printr-o pereche G=(V, E), unde V este o mulime nevid de vrfuri, iar E este
o parte a produsului cartezian V x V ale crei elemente le numim arce. Un arc este notat prin (x,y) cu x
diferit de y, unde x se numete surs sau extremitate iniiala, iar y se numete destinaie sau extremitate
final. Atributele : trivial, respectiv finit, pentru un digraf se definesc similar.
Un graf (digraf) parial al unui graf (digraf) G = (V, E) este un graf (digraf) G1 = (V, E1), unde E este
submulime a mulimii E, deci este graful (digraful) G nsui sau se obine din G prin suprimarea anumitor
muchii (arce).
Un subgraf (subdigraf) al unui graf (digraf) G este un graf (digraf) H = (U, E'), unde U este
submulime a mulimii V, E' este submulime a mulimii E, iar muchiile (arcele) din E' sunt toate muchiile
(arcele) din E, care au ambele extremiti n mulimea de vrfuri U.
Uneori, arcele (muchiile) sunt etichetate. Dac etichetele sunt numere reale pozitive se spune c
digraful (graful) este ponderat.
n continuare vom considera numai grafuri (digrafuri) finite. De obicei un graf se reprezint prin
indicarea unor puncte din plan (ce corespund vrfurilor) i a unor segmente de curb (sau de dreapt) pentru
indicarea muchiilor. n cazul digrafurilor arcele sunt segmente de curb orientate, sensul fiind de la surs
spre destinaie.
Definiie. Fie G = (V,E) un digraf, iar x i y dou vrfuri. Numim x-y drum (de lungime n) o
(vi, vi+1) aparine mulimii E pentru toi i, 1
secvena de vrfuri D: v0, v1, ..., vn dac v0 = x, vn = y , iar
i n-1. Vrfurile x i y se numesc extremitile drumului D. Un drum fr nici un arc este un drum trivial.
Un
x-y drum se numete circuit (sau drum nchis) dac x=y; dac x diferit de y, se spune c drumul
este unul deschis. Circuitul este elementar dac toate vrfurile circuitului, cu excepia primului i a ultimului
vrf care coincid, sunt distincte dou cte dou.
Definiie. Fie G = (V, E) un graf neorientat, iar x i y dou vrfuri. Secvena de vrfuri L: v0, v1, ...,
vn este un x-y lan (de lungime n) dac [vi, vi+1] aparine mulimii E, pentru toi i, 0 i n-1, iar x=v0 si y=vn. L
este ciclu dac x=y. Atributul elementar, pentru un lan, poate fi introdus similar.
217

Uneori, chiar pentru un digraf, putem folosi noiunea de lan, dac se verific proprietatea c oricare
dou arce vecine au o extremitate comun.
Definiie. Numim lan (drum) hamiltonian un lan (drum) elementar al unui graf care conine toate
vrfurile grafului.
Definiie. Fie G = (V, E) un graf netrivial. Spunem c x, y din V sunt conectate n G dac exist un
x-y lan n G. Graful G este un graf conex dac oricare dou vrfuri din V sunt conectate n G. Dac G este
un graf trivial (E mulime vid) se accept c este graf conex. Dac G nu este conex, atunci exist cel puin
dou componente conexe (subgrafuri conexe maximale, disjuncte dou cte dou relativ la vrfuri). Un
digraf G cu proprietatea c pentru oricare dou vrfuri x i y exist att un x-y drum, ct si un y-x drum n
G se numete graf tare conex.
n seciunea urmtoare prezentm o metod de reprezentare a algoritmilor folosind schemele logice.
Acestea sunt introduse folosind terminologia teoriei grafurilor.
II.2. Scheme logice structurate
O transcriere grafic a etapelor (pailor) unui algoritm este numit organigram. De cele mai multe
ori este folosit denumirea de "schem logic". Fiecrui pas, al algoritmului, i se asociaz un bloc ce
constituie eticheta unui arc. Blocurile folosite ntr-o schem logic descriu instruciuni (comenzi) sau
predicate (expresii logice). Predicatele apar n cadrul instruciunii de ramificare. Celelalte instruciuni sunt:
1. Instruciunea START: eticheteaz arcul iniial (acel arc n a crui extremitate iniiala nu pot sosi alte
arce). Orice schem logic are un unic arc iniial. Acesta va indica punctul de unde ncepe execuia unui
program.
2. Instruciunea STOP: eticheteaz un arc final (acel arc din a crui extremitate final nu pot pleca alte
arce). O schem logic poate avea mai multe arce finale. Acestea indic oprirea execuiei programului
descris prin intermediul schemei logice.
3. Instruciunea CITESTE: eticheteaz un arc ce indic introducerea de la mediul de intrare (tastatur,
disc etc.) a unei secvene de valori (numite date de intrare). Cuvntul CITESTE este nsoit de variabilele ce
descriu datele de intrare.
4. Instruciunea SCRIE: eticheteaz un arc ce indic nregistrarea la mediul de ieire (display, disc etc.)
a rezultatelor (datelor de ieire). Cuvntul SCRIE este nsoit de variabilele sau constantele ce desemneaz
datele de ieire.
5. Instruciunea de atribuire: eticheteaz un arc cu eticheta v := e, unde v este o variabil, iar e este o
expresie de acelai tip (numeric sau logic) cu variabila v.
6. Instruciunea de ramificare: este caracterizat prin n arce ce pleac din acelai punct, arce etichetate
cu predicatele p1, p2, ..., pn definite astfel nct
p1 or p 2 or ... or pn = TRUE (adevrat)
i
pi and pj = FALSE (fals) pentru oricare i i j diferii.
Definiie. Se numete schem logic (sau program sub form de schem logic) un graf orientat, n
care:
exist o unic instruciune START i cel puin o instruciune STOP;
orice vrf (diferit de extremitatea final a unei instruciuni STOP) este extremitatea iniiala a unei

unice instruciuni;
orice arc este etichetat cu una dintre instruciunile: START, STOP, CITESTE, SCRIE, atribuire sau
cu un predicat. n ultimul caz, extremitatea iniiala a arcului trebuie s coincid cu extremitatea iniiala a
unei instruciuni de ramificare;
pentru orice arc exist cel puin un drum care ncepe cu instruciunea START, se termin cu o
instruciune STOP i conine arcul considerat.
Schemele logice sunt folosite pentru descrierea algoritmilor. Se pot pune n evident structuri
fundamentale precum:
1. structura secvenial - format din arce conectate etichetate cu instruciuni distincte de cea de
ramificare. O structur secvenial format din dou arce etichetate prin a, respectiv b se va nota prin
SEQ(a,b) i are semnificaia " execut a urmat de b".
2. structuri decizionale (alternative) - conin, obligatoriu, cel puin un predicat i cel puin un bloc
funcional (instruciune alta dect START sau ramificativ). Structurile decizionale sunt de urmtoarele
forme:
IF(p; a, b) - Dac p este adevrat, atunci execut a altfel execut b.
IF0(p; a) - Dac p este verificat, atunci a.
218

CASE(p1,p2,...,pn; a1, a2, ..., an) - Dac p1 atunci a1, dac p2 atunci a2, ..., dac pn atunci an.
3. Structuri repetitive (structuri de tip ciclu, structuri iterative) - conin obligatoriu un bloc predicativ i
un bloc funcional care se execut de un numr finit de ori pn cnd predicatul i schimb valoarea. Sunt
posibile trei situaii:
WHILE(p; a) - Ct timp condiia p este adevrata se execut a, apoi se continu cu urmtoarea
instruciune.
REPEAT(p; a) - Repet a pn cnd condiia p este adevrata, apoi execut instruciunea
urmtoare.
FOR(p; a, b, c) - Este echivalent cu SEQ(a, WHILE(p; SEQ(b, c))). Blocul a este un bloc
funcional de iniializare. Blocul b descrie instruciunea ce se va executa cnd condiia p este
adevrata. Blocul c (prezentat explicit n aceast structur) va descrie actualizarea strilor
variabilelor programului cu rol deosebit n evaluarea condiiei p.
Eticheta secvenei de mai sus este ET1, iar componentele secvenei sunt instruciuni Pascal. Secvena
descrie citirea a trei numere, calculul mediei aritmetice i afiarea rezultatului.
Definiie. Un algoritm exprimat n funcie de structurile SEQ, IF i WHILE se numete structurat,
schema logic asociat se numete schem logic structurat, iar programul corespunztor se numete
program structurat.
Evident, familia algoritmilor structurai este nevid. Un rezultat foarte important afirm: Orice
algoritm poate fi transformat ntr-un algoritm structurat. Aceast afirmaie are la baz teorema BohmJacopini. Pentru a transforma o schem logic (nestructurat) ntr-o schem logic structurat se poate folosi
regula variabilei booleene (ce rezult din demonstraia teoremei Bohm-Jacopini). Cititorul interesat de detalii
poate consulta lucrarea: Corrado Bohm, Giuseppe Jacopini - Flow-diagrams, Turing Machines and
languages with only two formation rules. Comm. ACM. 9 (May, 1966), 366-371. Una din consecinele
importante ale programrii structurate este eliminarea instruciunii de salt necondiionat (goto) din programe.
Totui, exist situaii cnd instruciunea goto este util. Lungimea programelor nu va creste, iar claritatea
algoritmului nu va avea de suferit. Important este ca numrul instruciunilor goto folosite s fie foarte mic,
iar salturile s fie locale.

II.3. Noiuni introductive privind organizarea datelor


Organizarea datelor, n vederea prelucrrii acestora, este un proces complex, dar de o deosebit
important. De modul n care sunt structurate datele, depinde eficienta algoritmilor de prelucrare. Unele date sunt
de tip simplu: data apare ca o entitate indivizibil att din punct de vedere a informaiei pe care o reprezint, ct i
n raport cu unitatea central de prelucrare. Alte date sunt descrise prin componente, cu acelai tip sau cu tipuri
diferite. O colecie de date pe care s-a evideniat un anumit mod de structurare i s-au stabilit procedeele de
nregistrare/identificare a componentelor se va numi structur de date. Componentele unei structuri de date pot fi
de tip elementar sau pot fi, la rndul lor, structuri. Identificarea unei componente se poate face prin poziia pe care
o ocup n structur sau prin nume.
Pentru o dat elementar trebuie specificate: un identificator, atribute (domeniul de valori, modul de
reprezentare n sistemul de calcul, precizia reprezentrii) i valorile datei (pot fi enumerate sau indicate
printr-o proprietate comun). Din punct de vedere al domeniului de valori asociat unei date se disting
urmtoarele clase:
date de tip integer (numere ntregi);
date de tip real sau float (cu elemente din mulimea numerelor raionale);
date de tip boolean (se refer la valorile de adevr true (adevrat), false (fals));
date de tip char (cu elemente ale mulimilor ASCII sau Unicode);
date de tip string (obinute prin concatenarea datelor de tip caracter);
date de tip array (structur cu componente de acelai tip ce ocup locaii succesive din memoria
sistemului de calcul, identificate prin poziie);
date de tip record (structur cu componente oarecare, identificate prin nume).
Un mod special de organizare a datelor este ntlnit cnd avem de prelucrat liste. O list liniar este o
structur de date omogen, secvenial, format din elemente aparinnd unei mulimi date. O list poate fi
vid (nu are nici un element) sau plin (nu mai exist spaiu pentru stocarea unor componente suplimentare).
Este foarte important s putem accesa un element al listei, s inserm sau s tergem un element etc.
Listele pot fi stocate n memoria unui sistem de calcul n dou moduri: secvenial i nlnuit. Modul
secvenial presupune stocarea elementelor listei n locaii succesive de memorie conform ordinii elementelor
din list i reinerea adresei primului element al listei (adresa de baz). Modul nlnuit presupune c fiecare
element al listei este nlocuit cu o celul format dintr-o parte de informaie (corespunztoare elementului
listei) i o parte de legtura ce conine adresa celulei urmtorului element din list. Se va retine adresa de
219

baz a listei, iar ultima celul va indica, n partea de legtura, o valoare special (ce nu poate desemna o
legtura).
Structura de date elementar adecvat reprezentrii secveniale a listelor este tabloul unidimensional.
Orice list liniar are un nceput i un sfrit pe care le numim baz, respectiv vrf. O list liniar la
care inserarea i extragerea elementelor se face prin vrful listei se numete stiv (stack). O list liniar n
care inserrile se efectueaz la baza listei, iar extragerile prin vrful listei se numete coad (queue).
Listele liniare pot fi transformate n liste circulare considernd c legtura ultimului element indic
adresa bazei listei.
II.4. Limbaj algoritmic
O alt modalitate de reprezentare a algoritmilor o constituie utilizarea limbajului algoritmic.
Limbajul algoritmic folosete o scriere similar limbajelor de programare moderne. El permite att
descrierea instruciunilor algoritmului, ct i descrierea exact a tipului datelor cu care lucreaz algoritmul.
Un algoritm descris folosind limbajul algoritmic este o succesiune finit de declarri si instruciuni.
Declarrile precizeaz tipul i organizarea datelor. Ele apar naintea instruciunilor ce descriu paii
algoritmului. Din punct de vedere al scrierii instruciunilor, o instruciune poate ocupa mai multe rnduri sau
pe un rnd pot fi scrise mai multe instruciuni. Instruciunile vor fi separate, ntre ele, folosind caracterul ';'.
Cuvintele care identific un tip de date sau o instruciune, numite n continuare cuvinte cheie, apar
evideniate pentru a fi deosebite de numele variabilelor. O declarare utilizeaz unul dintre cuvintele cheie
integer, real, boolean, char, string, array, record, stack, queue, urmat de o list de nume de variabile.
Declarrile sunt separate, ntre ele, folosind caracterul ';'. Variabilele prezente ntr-o list au tipul i
organizarea precizat prin cuvntul cheie respectiv.
O important deosebit o au declarrile de subprograme. n rezolvarea multor probleme apare
necesitatea executrii repetate a acelorai calcule pentru date diferite. Subprogramele permit descrierea
acestor calcule o singur dat. Subprogramul poate fi apelat ori de cte ori este necesar efectuarea acestor
operaii. Un subprogram este identificat printr-un nume i o list de parametri. Subprogramele se mpart n
proceduri i funcii. Declararea unei proceduri const n specificarea cuvntului procedure, a unui identificator
al procedurii i a unei liste de declarri (ntre paranteze rotunde) ce indic informaiile ce fac obiectul transferului
ntre apelant i apelat. Pentru declararea unei funcii se folosete cuvntul cheie function. Spre deosebire de
proceduri, funciile ntorc obligatoriu un rezultat. De aceea, n declaraii, declararea unei funcii ncepe cu
specificarea mulimii de valori ce corespunde rezultatului, a cuvntului function, a identificatorului funciei i a
listei parametrilor (similar ca la o procedur).
Un algoritm este complet cunoscut dac este descris i definiia subprogramelor folosite. Definiia
unui subprogram presupune descrierea (prin instruciuni) modului n care se efectueaz calculele i se
transmit rezultatele. Mai multe detalii prezentm n finalul acestei seciuni.
Instruciunile limbajului algoritmic sunt urmtoarele:
1. Instruciunea de atribuire. Aceast instruciune are forma: v := E (atribuire simpl) sau (v1, v2, ..., vn)
vi :=Ei, pentru oricare i = 1, 2, ..., n. Operaia de
:= (E1, E2, ..., En) ce realizeaz simultan atribuirile
atribuire este permis cnd variabila v (variabilele v1, v2, ..., vn) din membru stng i expresia E (expresiile
E1, E2, ..., En) sunt compatibile (se refer la aceeai clas de obiecte). O expresie conine paranteze (opional),
operanzi (inclusiv apeluri de funcii) i operatori adecvai.
2. Instruciuni de intrare/ieire. Vom presupune c citirea datelor (de intrare) se face de la un mediu de
intrare (de exemplu: tastatura sistemului de calcul), iar scrierea rezultatelor (de ieire) se face la un mediu de
ieire (de exemplu: ecranul, imprimanta, plotterul etc.). Forma instruciunilor de intrare/ieire este:
read v1, v2, ..., vn
write v1, v2, ..., vn
unde v1, v2, ..., vn sunt variabile de tip elementar.
3. Instruciunea repetitiv While. Aceast instruciune are forma:
while p do S, unde p este un
predicat, iar S este o secvena de instructiui. Deoarece instruciunile sunt separate ntre ele, folosind ';' va
trebui s delimitm secvena S. Pentru aceasta se utilizeaz construcia SEQ..END prezentat mai sus.
Semnificaia acestei instruciuni este aceeai ca pentru subschema logic While(p; S).
4. Instruciunea If_then_else. Aceast instruciune are forma:
if p then S1 [elseS2 ],
unde p este un predicat, iar S1 i S2 sunt secvene de instruciuni. Dac nendeplinirea predicatului p nu
indic vreo aciune, poriunea else S2 poate lipsi, fapt reprezentat prin includerea ntre paranteze drepte,
exprimarea fiind echivalent cu IF0(p; S1). Atunci cnd att S1, ct i S2 sunt aciuni prevzute,
instruciunea este echivalent cu subschema logic IF(p; S1, S2).
5. Instruciunile insert i extract. Aceste instruciuni sunt necesare pentru lucrul cu liste. Acestea sunt o
prelungire a instruciunii de atribuire. Dac se specific o list L, atunci insert i, L (sau L:=i) exprim
220

introducerea elementului specificat prin i n lista L, iar instruciunea extract i, L (sau i:=L) specific
extragerea elementului curent din lista L i depunerea acestuia n i.
6. Instruciunea apel de procedur. Apelarea unei proceduri se face prin instruciunea apel de procedur
care are una din formele:
identificator_procedura
sau
identificator_procedura(lista de argumente)
unde identificator_procedura specific o procedur declarat, iar argumentele sunt expresii separate prin
virgul.
Se presupune c, atunci cnd se ajunge la un apel de procedur, se stabilete corespondenta ntre
argumente i parametri, i se execut toate instruciunile specificate n definiia procedurii. Dup ultima
instruciune a procedurii se continu cu instruciunea urmtoare apelului de procedur. Un apel de procedur
este corect atunci cnd, ntre argumente i parametri exist o concordant ca numr, tip i mod de organizare.
Convenim ca atunci cnd referim o variabil (ntr-o procedur) de fapt, facem o referire la locaia de
memorie corespunztoare argumentului respectiv. Spunem c se realizeaz un transfer prin referin. Sunt
posibile i alte moduri de transfer, dar acestea nu sunt considerate momentan.
7. Instruciunea return. Aceast instruciune provoac prsirea corpului unui subprogram. n cazul n
care cuvntul return este urmat de o expresie, valoarea expresiei este folosit ca valoare de retur a
subprogramului. Instruciunea return fr valoare de retur este folosit pentru a prsi execuia unei
proceduri i a reveni n unitatea de program din care a avut loc apelul; i anume la instruciunea ce urmeaz
imediat acestui apel.
8. Pentru a uura descrierea algoritmilor admitem prezena, ca instruciuni ale limbajului algoritmic, a
instruciunilor Repeat i For. Instruciunea Repeat este modelat de structura repetitiv REPEAT (p; S). Ea
are forma: Repeat S until p; unde S este o secvena (eventual vid) de instruciuni, iar p modeleaz o expresie
logic.
Instruciunea For este modelat de structura iterativ FOR(p; a,b,c) i are forma simplificat
For v := e1, e2, e3 do S
unde: S este o secvena de instruciuni, iar expresiile e1, e2 i e3 au acelai domeniu de valori ca variabila v.
n forma prezentat, instruciunea determin executarea secvenei S pentru v lund succesiv valorile e1,
e1+e3, e1+2e3, ..., fr a trece dincolo de e2.
Formei de mai sus i corespunde structura iterativ:
FOR((v-v2)*v30; SEQ v:= e1; v1 :=e2; v3:=e3 END, S, v := v +v3).
II.5. Analiza complexitii
Existena unui algoritm de rezolvare a unei probleme genereaz, imediat, ntrebri ca: Mai exist un
alt algoritm de rezolvare? Este algoritmul gsit "cel mai rapid"? Acest paragraf introduce noiunile
fundamentale privind complexitatea algoritmilor i prezint exemple simple de algoritmi pentru care se
determin complexitatea.
Analiza complexitii unui algoritm presupune determinarea resurselor de care acesta are nevoie
pentru a produce datele de ieire. Prin resurs nelegem timpul de executare, dar uneori este necesar s
analizm i alte resurse precum: memoria intern, memoria extern etc. Modelul mainii pe care va fi
executat algoritmul nu presupune existena operaiilor paralele; operaiile se execut secvenial.
Timpul de executare al unui algoritm reprezint numrul de operaii primitive executate. Trebuie,
pentru fiecare algoritm, s definim noiunea de operaie primitiv, independent de maina secveniala pe care
se va execut algoritmul.
n analiza complexitii unui algoritm avem n vedere cazul cel mai defavorabil din mai multe
motive:
1. Timpul de executare n cazul cel mai defavorabil ofer o limit superioar a timpului de executare
(avem certitudinea c executarea algoritmului nu va dura mai mult).
2. Situaia cea mai defavorabil este ntlnit des.
3. Timpul mediu de executare este, uneori, apropiat de timpul de executare n cazul cel mai defavorabil,
dar dificil de estimat.
Notaia theta este utilizat pentru a specifica faptul c o funcie este mrginita (inferior si superior).
Semnificaia notaiei O este de limit superioar, n timp ce semnificaia notaiei Omega este de limit
inferioar.
Definiie. Fie A un algoritm, n dimensiunea datelor de intrare i T(n) timpul de executare estimat
pentru algoritmul A. Se spune c algoritmul A are comportare polinomial (aparine clasei P) dac exist
p>0, astfel nct
T(n) = O(np).
221

Definiie. O funcie care crete mai rapid dect funcia putere xp, dar mai lent dect funcia
exponeniala ax cu a>1 se spune c este cu cretere exponeniala moderat. Mai precis: f este cu cretere
exponeniala moderat dac pentru oricare p>0 avem f(x) = Omega(xp) i oricare M>0 avem f(x) = o((1+
M)x).
Definiie. O funcie f are cretere exponeniala dac exist a>1 astfel nct
f(x) = Omega(ax) i exist
x
b>1 astfel nct f(x) = O(b ).
Printre funciile n -> f(n), nemrginite, funciile ce cresc cel mai lent sunt, de exemplu, de forma log
log n sau (log log n)1,02. Pentru n = 1000000, log log n ~ 2,6. Deci un algoritm a crui complexitate este log
log n este preferabil unui algoritm (elaborat pentru rezolvarea aceleiai probleme) de complexitate log n.
Algoritmii de tip polinomial sunt mai leni (creterea funciei T(n) este mai rapid) dect algoritmii de tip
logaritmic. Urmeaz apoi algoritmii moderai (cu T(n) de forma nlogn etc.) i cei cu cretere exponeniala (2n,
n33n etc.). Algoritmii cei mai leni sunt cei pentru care funcia T(n) este foarte rapid cresctoare (de exemplu:
T(n) = n!).
n informatic sunt interesani numai algoritmii care conduc la un timp de calcul cel mult moderat.
Dac un algoritm necesit timp de calcul exponenial sau factorial, acesta va fi utilizat numai n cazuri
excepionale. Tabelul urmtor ilustreaz cele de mai sus.
n
10
100
1000
10000
n2
n

log n

100

10000

1000000

1000

1000000

1000000000 1000000000000

0.30103

0.47712

0.60206

log log n 0

100000000

Propoziie. Fie n i m dou numere ntregi pozitive. Algoritmul lui Euclid pentru a determina
cmmdc(m, n) efectueaz cel mult [2log2M]+1 operaii de mprire ntreag, unde M = max (m, n).
II.6. Elemente privind corectitudinea algoritmilor
A verifica corectitudinea unui algoritm nseamn a verifica dac algoritmul conduce ntr-un interval
finit de timp la obinerea soluiei corecte a problemei pentru care a fost elaborat. Vom vedea n capitolul 5 cteva
metode de rezolvare a problemelor, deci de a elabora algoritmi. Metodele descrise n acest capitol se vor
exemplifica pentru algoritmi simpli. Pentru aspecte suplimentare legate de corectitudinea algoritmilor se poate
folosi lucrarea: Tudor Blnescu. Corectitudinea algoritmilor. Editura Tehnic, Bucureti, 1995.
Notaie. Construcia {P}A{Q}, numit i formul de corectitudine total conine urmtoarele
elemente:
P - comentariu care descrie proprietile datelor de intrare (precondiia);
A - algoritmul (secvena de instruciuni) supus analizei;
Q - comentariu care descrie proprietile datelor de ieire (postcondiia).
Definiie. Un algoritm {P}A{Q} este corect cnd propoziia urmtoare este valid:
Dac
datele de intrare satisfac precondiia P
Atunci
1) executarea lui A se termin (ntr-un interval finit de timp) i
2) datele de ieire satisfac postcondiia Q.
Folosind elementele fundamentale ale logicii matematice rezult c urmtoarele observaii sunt
adevrate:
1. Algoritmul {false}A {Q} este corect, oricare ar fi A i Q.
2. Algoritmul {P}A{true} este corect dac i numai dac executarea lui A se termin, atunci cnd
datele iniiale satisfac proprietatea P.
3. Dac {P}A{Q} i {R}A{Q} sunt formule corecte, atunci {P v R}A {Q} este formul corect.
Pentru a stabili corectitudinea algoritmilor compleci se procedeaz la descompunerea acestora n
elemente simple a cror corectitudine se analizeaz. n continuare vor fi prezentate reguli pentru a analiza
corectitudinea unor astfel de algoritmi. Pentru o formalizarea avansat a acestor reguli, cititorul interesat
poate parcurge lucrarea: C. A. R. Hoare et al. Laws of Programming. Comm. ACM. 30(8), 1987, 672-687.
Regula compunerii secveniale (CS):
Dac A este de forma SEQ B; C END, atunci a verifica formula {P}A{Q}, revine la a verifica
formulele {P}B{R} i {R}C{Q}, unde R este un predicat asupra datelor intermediare.
222

Este evident c regula CS poate fi aplicat iterativ. Mai precis, dac A este de forma SEQ A1; A2; ...,
An END, atunci obinem regula compunerii secveniale generale:
&t9;CSG: Dac {P0} A1 {P1}, {P1} A2 {P2}, ...., {Pn-2}An-1{Pn-1} si
{Pn-1}An{Pn} sunt algoritmi coreci, atunci {P0}A{Pn} este algoritm corect.
Regula implicaiei (I):
Aceast regul este util n cazul algoritmilor ce urmeaz a fi aplicai n condiii mai tari dect pentru
cele care au fost deja verificai.
O proprietate P este mai tare dect proprietatea Q dac este adevrat propoziia compus: P -> Q.
Regula implicaiei are urmtoarea form:
I: Dac{P} A {Q} este algoritm corect, P1 -> P si Q -> Q1, atunci {P1} A {Q1} este algoritm corect.
Regula instruciunii de atribuire (A):
Fie notaiile:
x

Variabil simpl

Expresie;

Def(e)

Proprietatea satisfcut de acele elemente pentru care


evaluarea expresiei e este corect (Exemplu: pentru
integer array b(10), Def(b(i)):= (i=1, 2, ..., 10));

P(x)

Formul n care apare variabila x;

P(x/e)

Formula obinut din P(x) prin substituirea variabilei


simple x cu expresia e, ori de cte ori x este variabil
liber n P, iar dac e conine o variabil y care apare
legat n P, nainte de substituie variabila y se nlocuiete
printr-o nou variabil (care nu mai apare n e).

Valoarea de adevr a propoziiei P -> Q(x/e) nu se schimb dac n Q(x/e) se efectueaz substituia
descris de atribuirea x := e. Regula atribuirii este deci:
A: Dac P -> (Def(e) and Q(x/e)) atunci algoritmul {P} x:=e {Q} este corect.
Regula instruciunii if (IF si IFR):
Dac c este o expresie boolean i A i B sunt algoritmi, pentru cele dou forme ale instruciunii if
sunt valabile regulile de corectitudine:
IF: Dac
{P and c} A {Q}, {P and not c} B {Q} sunt corecte, iar P -> Def(c) este adevrata
Atunci formula
{P} if c then A else B {Q} este corect.
IFR: Dac
{P and c} A {Q} este corect, iar P and (not c) -> Q si P -> Def(c) sunt adevrate
Atunci
{P} if c then {Q} este formul corect.
Se poate observa c aplicarea regulilor instruciunii de decizie nu este n sine dificil corectitudinea
acestei instruciuni se reduce la corectitudinea instruciunilor componente.
Regula instruciunii while (W):
Regula instruciunii while trebuie s precizeze dac nu apare fenomenul de ciclare, iar prelucrrile
sunt corecte (n paranteze rotunde apare descrierea formal).
Fie algoritmul {P} A; while c do S {Q}. Presupunem c exist o proprietate invariant I (vezi mai
jos) i o funcie de terminare t cu valori numere ntregi care satisfac urmtoarele condiii:
Cnd I este adevrata atunci expresia boolean c este bine definit (adic I -> Def(c)).
Proprietatea I rezult prin executarea secvenei A (adic, {P} A {I} este algoritm corect).
La terminarea instruciunii while, proprietatea final Q poate fi dedus (adic, I and (not C) -> Q).
I este proprietate invariant la executarea unei iteraii: dac I este adevrat nainte de executarea
secvenei S i expresia boolean c este adevrat, atunci executarea secvenei S se termin ntr-un
interval finit de timp i I este adevrata la sfrit (adic, {I and c} S {I} este algoritm corect).
223

Dac rezultatul evalurii expresiei c este true i proprietatea I este adevrata, atunci exist cel puin o
iteraie de efectuat (adic,
I and c -> (t > =1)).
Valoarea lui t descrete dup executarea unei iteraii (adic,
{(I and c) and (t=a)} S {t
< a}).
n aceste condiii, algoritmul considerat este corect.

III. LIMBAJE DE PROGRAMARE


III.1. Vocabularul i sintaxa limbajelor de programare
Vocabularul unui limbaj de programare este format din cele mai simple elemente cu semnificaie
lingvistic numite entiti lexicale sau tokens. Elementele vocabularului sunt alctuite din caractere Unicode
(care constituie alfabetul limbajului). Standardul Unicode conine ca subset codul ASCII, dar reprezentarea
intern a caracterelor Unicode folosete 16 bii. Cele mai utilizate simboluri sunt: literele mari i mici ale
alfabetului englez, cifrele sistemului zecimal, diferite semne speciale.
Unitile lexicale sunt separate, ntre ele, prin comentarii i spatii. Pentru aproape toate limbajele de
programare se pot evidenia uniti lexicale precum: cuvinte cheie, identificatori, literali, separatori i
operatori. Cuvintele cheie sunt secvene de caractere ASCII rezervate (nu pot avea alt semnificaie) utilizate
pentru definirea unitilor sintactice fundamentale. Pentru exemplificare ne referim la limbajele de
programare Pascal si Java:
1. Cuvinte cheie Pascal: absolute, and, array, begin, case, const, div, do, downto, else, end, external,
file, for, forward, function, goto, if, implementation, in, inline, interface, interrupt, label, mod, nil, not, of, or,
packed, procedure, program, record, repeat, set, shl, shr, string, then, to, type, unit, until, uses, var, while,
with, xor.
2. Cuvinte cheie Java: abstract, boolean, break, byte, case, cast, catch, char, class, const, continue,
default, do, double, else, extends, final, finally, float, for, future, generic, goto, if, implements, import, inner,
instanceof, int, interface, long, native, new, null, operator, outer, package, private, protected, public, rest,
return, short, static, super, switch, synchronized, this, throw, throws, transient, try, var, void, volatile, while,
byvalue. Cuvintele cheie subliniate sunt prezente i n limbajul C alturi de altele.
Identificatorii sunt secvene, teoretic nelimitate, de litere i cifre Unicode, ncepnd cu o liter sau
liniua de subliniere (n limbajul C). Identificatorii nu pot fi identici cu cuvintele rezervate.
Literalii ne permit introducerea valorilor pe care le pot lua tipurile de date primitive i tipul ir de
caractere. Mai precis, lieralii sunt constante ntregi, flotante, booleene, caracter i, iruri de caractere.
Literalii ntregi, n general, pot fi descrii prin reprezentri n una din bazele de numeraie: 10, 16 sau
8. Lungimea reprezentrii interne depinde de implementarea limbajului. De exemplu, n limbajul Pascal, un
literal ntreg, cu semn, este reprezentat pe 16 bii, descrierea sa n baza 16 fiind o secvena a simbolurilor
asociate reprezentrii numrului ntreg n baza 16 avnd prefixul $.
Literalii flotani reprezint numere raionale. Ei sunt formai din urmtoarele elemente: partea
ntreag, partea fracionar i exponent. Exponentul, dac exist, este introdus de litera E sau e urmat
opional de un semn al exponentului.
Literalii booleeni sunt TRUE si FALSE, primul reprezentnd valoarea boolean de adevr, iar
cellalt valoarea boolean de fals. Dei TRUE si FALSE nu sunt cuvinte rezervate, acestea nu pot fi folosite
ca identificatori (n Pascal, Java).
Literalii caracter sunt folosii pentru a desemna caracterele codului Unicode (sau ASCII, acolo unde
este cazul). Descrierea unui literal caracter se fie folosind o liter, fie o secvena special. Secvenele speciale
(numite secvene escape n C, C++ i Java) permit specificarea caracterelor fr reprezentare grafic precum
i a unor caractere speciale. Caracterele ce au reprezentare grafic pot fi descrise ntre apostrofuri, ca n
exemplele: 'P', 'A', '3', '!'. Secvenele speciale se descriu diferit de la un limbaj la altul. Vom exemplifica
folosind limbajele Pascal i Java.
Secvene speciale n limbajul Pascal: 1) Un ntreg din domeniul 0, ..., 255 precedat de simbolul #
desemneaz un caracter dat prin codul su ASCII. 2) Un caracter imprimabil precedat de semnul ^
desemneaz un "caracter de control" avnd codul ASCII n domeniul 0, ..., 31.
Secvenele escape n limbajul Java se descriu folosind apostrofuri, semnul \, litere i cifre. Vom
exemplifica indicnd cteva secvene predefinite: '\b' (backspace = #8), '\n' (linefeed), '\r' (carriage return)
etc.
Un literal ir de caractere este constituit din zero sau mai multe caractere ntre delimitatori. Secvena
de caractere ce formeaz irul poate conine att caractere imprimabile, ct i secvene speciale. n limbajul
Pascal se utilizeaz apostroful ca delimitator, iar n limbajul C( C++, Java) ghilimelele.
224

Separatorii sunt caractere ce indic sfritul unui token i nceputul altuia. Acetia particip i la
construcia sintaxei limbajelor de programare. Ei nu trebuie confundai cu spatiile care, i acestea, separ
uniti lexicale distincte. Separatorii sunt necesari cnd unitile lexicale diferite sunt scrise fr spatii ntre
ele. Cei mai ntlnii separatori sunt: ( ) { } [ ] ; , . Exemple: x[10], f(x,y), carte.autor etc. Operatorii sunt
simboluri grafice ce desemneaz operaiile definite de un limbaj de programare. n unele limbaje de
programare este posibil redefinirea operatorilor, acelai simbol fiind utilizat pentru operaii diferite ce
rezult din contextul n care apar. Lista minimal a operatorilor aritmetici include: +(adunare), -(scdere),
/(mprire), *(nmulire). Mai sunt admise i operaii precum: % (C, Java) sau mod (Pascal, Modula), div
(mprire ntreag n limbajul Pascal). Ali operatori sunt: operatori logici, operatori relaionali, operatori
asupra irurilor de caractere etc. Toi operatorii pot fi privii i ca separatori.
O construcie aparte utilizat n programe pentru explicarea sau documentarea textului programului
este comentariul. Comentariile sunt delimitate de textul programului folosind anumii delimitatori. n
limbajul Pascal, un comentariu este scris ntre acoladele { } sau ntre secvenele (*, *). Programele C++, Java
pot conine comentarii pe o singur linie ;i ncep cu //, sau pe mai multe linii ;i sunt cuprinse ntre /* si */.
Alte elemente lexicale ce pot fi prezente ntr-un program sunt etichetele ;i clauzele. Etichetele sunt
iruri de cifre zecimale/hexazecimale sau identificatori folosite n legtura cu o instruciune de salt (goto)
pentru marcarea unor instruciuni. Clauzele (numite ;i directive) sunt cuvinte cheie ce desemneaz
instruciuni cu efect n timpul compilrii.
Prin sintaxa unui limbaj de programare se nelege, n general, un ansamblu de reguli privind
agregarea unitilor lexicale pentru a forma structuri mai complexe (declaraii, instruciuni, module,
programe etc.). Prezentarea acestor reguli se poate folosind limbajul natural sau mecanisme formalizate.
Descrierea sintaxei n limbaj natural poate conduce la neclariti sau specificaii incomplete. Cu ajutorul
mecanismelor formale sintaxa unui limbaj este complet specificat. Cea mai folosit notaie este cunoscut
sub numele de notaie BNF
(Backus-Naum-Form) ;i a fost folosit pentru prima dat, n anul 1959, la
specificarea sintaxei limbajului Algol-60. Aceast notaie are aceeai putere generativ cu gramaticile
independente de context introduse de N. Chomsky. Totui, limbajele de programare nu sunt independente de
context, ci numai poriuni ale acestora pot fi modelate cu ajutorul limbajelor independente de context. Pentru
a putea specifica un ntreg limbaj de programare se poate folosi notaia BNF extins. n prezentarea din acest
capitol vom utiliza opt metasimboluri: ::= < > { } [ ] | pentru a defini unitile sintactice ale limbajului
Pascal. Metasimbolurile < i > sunt folosite pentru delimitarea numelui unei uniti sintactice. Presupunem,
de asemenea, existenta unei operaii de concatenare pe mulimea unitilor sintactice. Metasimbolul ::= apare
dup numele unei uniti sintactice i are semnificaia "se definete prin". Metasimbolul | este utilizat pentru
a delimita mai multe variante de definire ale unei uniti sintactice, aceasta fiind obinuta prin reuniunea
variantelor. Metasimbolurile { i } indic repetarea posibil (de zero sau mai multe ori) a simbolurilor pe
care le delimiteaz. Pentru a desemna prezenta opional a unor simboluri se utilizeaz, ca delimitatori,
metasimbolurile [ i ]. Vom admite, pentru prescurtare metasimbolul ... care indic continuarea unui ir de
valori conform contextului n care apare. Iat cteva exemple:
1. <liter> ::= A ... Z descrie mulimea literelor mari;
2. <cifr> ::= 0 ... 9 descrie mulimea cifrelor zecimale;
3. <identificator> ::= <liter> { <liter> | <cifr>} descrie modul de formare a identificatorilor: un ir
de litere i/sau cifre, primul semn fiind o liter.
4. <secvena cifre> ::= <cifr> { <cifr>} descrie modul de formare a unei secvene de cifre;
5. <ntreg fr semn> ::= <secvena cifre> definete un numr ntreg fr semn;
6. <semn> ::= + | 7. <ntreg cu semn>::= [ <semn><ntreg fr semn> spune c un ntreg cu semn este un ntreg fr
semn precedat de un semn: + sau -.
Prin diagrame sintactice se realizeaz o reprezentare grafic a modului de agregare a unitilor
sintactice. n cele ce urmeaz vom prefera limbajul natural (n anumite cazuri) i notaia BNF extins (n alte
cazuri), cititorul interesat asupra diagramelor sintactice poate consulta, de exemplu: N. Wirth: Systematic
Programming: An introduction, Prentice Hall, 1972.
III.2. Tipuri de date. Constante. Variabile. Expresii
Un tip de date este o structur compus din: 1) o mulime X de valori numite date i 2) o mulime de
legi de compoziie pe X (operaii ce se pot efectua cu valori din X). O dat are un singur tip (aparine unei
singure mulimi). Exist limbaje de programare puternic tipizate (n sensul verificrii cu regularitate a
apartenei unei date la mulimea de valori a tipului su, nc din faza de compilare). Astfel de limbaje de
programare sunt: Pascal, Modula, Ada etc.
225

Tipurile de date sunt standard sau definite de utilizator. Tipurile definite de utilizator se introduc prin
intermediul unei definiii folosind un cuvnt cheie precum type (n Pascal), typedef (n C) sau class (n
limbajele C++ i Java). De asemenea, se vor utiliza diverse cuvinte cheie pentru a specifica structura tipului.
Dac pentru o anumit structur a unui tip nu este stabilit un identificator, spunem c avem de-a face cu un
tip anonim.
Valorile unui tip de date (elementele mulimii X sunt referite fie prin variabile, fie prin constante
(literali sau constante simbolice). O locaie de memorie care poate stoca o valoare a unui anumit tip de date
se numete, prin abuz de limbaj, variabil. Orice variabil trebuie s fie declarat pentru a putea fi folosit. O
declaraie conine un tip de valori - ce indic: ce se stocheaz, cum se stocheaz i n ce operaii intervin
valorile stocate - i un identificator pentru a ne referi la variabila ca obiectul declaraiei. Practic o variabil
este un obiect caracterizat de tip, adres i valoare, pentru care atributul valoare poate fi modificat.
Operaiile cu elemente ale unui tip sunt fie predefinite, fie sunt introduse prin declaraii function sau
procedure (n Pascal) sau operator (n C++). Agregarea variabilelor, constantelor i a operatorilor conduce la
construcii numite expresii. Expresiile sunt evaluate n cursul executrii unui program. Rezultatul unei
expresii depinde de valorile variabilelor n momentul evalurii.
Tipurile de date ntlnite n limbajele de programare actuale sunt clasificate n: tipuri de date simple;
tipuri de date structurate, tipuri referin (pointer), tipuri procedurale. n limbajele C, C++ i Java exist tipul
void. Aceast mulime notat prin void nseamn fie mulimea vid, fie o mulime neprecizat.
Tipurile de date simple numite i tipuri primitive (sau tipuri standard) se refer la mulimi de
elemente precum: numere ntregi, numere raionale, valori de adevr (logice sau booleene), caractere, valori
aparinnd unei enumerri sau unui interval (subdomeniu). O parte dintre tipurile simple sunt tipuri ordinale,
adic tipuri caracterizate printr-o mulime finit de valori, pe care este definit o ordine liniar i, prin
urmare, pentru orice element al unei asemenea mulimi se stabilete numrul de ordine ord(.), elementul
predecesor pred(.) i cel succesor succ(.). Tipurile ordinale sunt cele care se refer la mulimi precum:
mulimea numerelor ntregi, mulimea valorilor de adevr, mulimea caracterelor, mulimea valorilor unei
enumerri, mulimea valorilor dintr-un subdomeniu al uneia dintre mulimile anterioare. Tipurile raionale
(simpl precizie, dubl precizie, precizie extins etc.) nu sunt considerate tipuri ordinale, dei sunt tot
mulimi finite de elemente. Trebuie observat c metoda de reprezentare n memoria calculatorului a
numerelor raionale ar permite considerarea unei ordini liniare i, elementele unei astfel de mulimi ar avea
un numr de ordine.
Operatorii sunt simboluri care specific operaii efectuate asupra unor variabile sau constante
denumite operanzi. Combinaiile valide de operanzi i operatorii reprezint expresii.
Limbajele de programare ofer o multitudine de operatori: operator de atribuire (simbolizat prin :=
sau =), operatori aritmetici unari (utilizarea semnului, incrementare, decrementare), operatori aritmetici
binari (adunare, scdere, nmulire, mprire, obinerea ctului i restului mpririi a dou numere ntregi),
operatori logici (i, sau, negare), operatori relaionali (egal, diferit, mai mic, mai mic sau egal, mai mare, mai
mare sau egal, aparine), operatori la nivel de bit (i, sau, negare, sau exclusiv, deplasare stnga, deplasare
dreapta), operatori combinai (n limbajele C, C++ i Java), operatori asupra mulimilor (reuniune,
intersecie, diferen), operatori asupra irurilor de caractere (concatenare) precum i ali operatori.
Evaluarea expresiilor trebuie s tin seama de poziia parantezelor i de proprietile operatorilor
(precedent, asociativitate, conversii implicite n cazul tipurilor compatibile, conversii explicite). Precedenta
stabilete ordinea de evaluare a operaiilor n cazul expresiilor care conin mai muli operatori diferii. Dac
ntr-o expresie se ntlnesc operaii cu aceeai precedent, atunci ordinea de evaluare este dat de tipul
asociativitii (de la stnga la dreapta sau de la dreapta la stnga). Cnd ntr-o expresie apar operaii cu
operanzi de tipuri diferite, nainte de efectuarea operaiei are loc un proces de conversie implicit (cnd nu se
semnaleaz explicit i nu apare fenomenul de incompatibiltate) prin care tipul cu cardinalul mai mic este
promovat ctre tipul mai bogat (se presupune aici c natura elementelor celor dou tipuri este aceeai).
III.3. Programare n Turbo Pascal
Limbajul Pascal a fost definit de profesorul Niklaus Wirth (Universitatea Tehnic din Zrich,
Elvetia) n anul 1971. Exist foarte multe implementri ale acestui limbaj, cea mai popular aparine firmei
Borland International i este destinat calculatoarelor compatibile IBM-PC.
Structura unui program Turbo Pascal conine o parte declarativ i o parte principal. Partea
declarativ conine o descriere a datelor ce vor fi prelucrate pe calculator, ct si o descriere a operaiilor ce se
pot efectua asupra datelor. Partea principal (numit i corpul programului) descrie secvena de instruciuni
ce se execut n momentul lansrii programului pentru executare. Aciunile (reprezentate de instruciuni)
asupra datelor efective sunt descrise n partea principal. Partea declarativ indic un antet, o linie uses, una
226

sau mai multe declaraii (etichete (label), tipuri de date (type), constante (const) i variabile (var)) precum i
una sau mai multe declaraii i definiii de subprograme.
III.3.1. Instruciuni Pascal
Instruciunile limbajului Turbo Pascal sunt grupate n dou clase: instruciuni simple i instruciuni
structurate. Aciunile simple sunt: instruciunea de atribuire, instruciunea apel de procedur, instruciunea de
transfer necondiionat (goto) i instruciunea vid (cu efect nul). Aciunile structurate sunt reprezentate de:
instruciunea compus, instruciunile iterative (for, while, repeat), instruciuni condiionale (if, case) i
instruciunea with (n contextul prelucrrii datelor de tip record).
Din punct de vedere sintactic, o instruciune este alctuita dintr-o etichet (opional) pentru a putea
fi referit de alte instruciuni urmat de instruciunea propriu-zis (care descrie aciunea realizat n
momentul executrii sale).
Instruciunea de atribuire, n notaia BNF, are forma descris prin:
<instruciune de atribuire> ::= <variabil> := <expresie>
unde <variabil> i rezultatul dat de <expresie> trebuie s fie de tipuri identice, sau tipul uneia s fie un
subdomeniu al celeilalte, sau ambele trebuie s fie subdomenii ale aceluiai tip. Se accept, ca o excepie,
cazul n care <variabil> are tipul real, iar <expresie> conduce la un rezultat de tip ntreg.
Instruciunea apel de procedur se insereaz n program n locul n care se dorete executarea
instruciunilor specificate de o declaraie de procedur asupra unor date efective transmise procedurii n locul
de apel. Instruciunea write('Apel!'); apeleaz procedura write pentru irul 'Apel !'. O procedur cu antetul
procedure PROC(a, b, c:real; var s:real)
se poate apela n mai multe moduri. Urmtoarele apeluri sunt corecte:
PROC(3.0, 4.0, 5.0, S); PROC(L1,L2,L3,ARIA); PROC(2.0, Y, Z, A);
Apelul PROC(X,Y,Z,45.0); nu este un apel corect deoarece al patrulea parametru nu poate fi o
constant.
Instruciunea de transfer necondiionat, transfer controlul execuiei programului n alt loc din textul
surs implementnd mecanismul "Mergi la pasul ". Instruciunea ctre care se realizeaz transferul trebuie s
fie una etichetat
Exist anumite restricii privind utilizarea instruciunii goto (se transfer controlul n acelai bloc de
instruciuni redat prin begin ... end sau repeat ... until; transferul ctre o instruciune din interiorul unei
instruciuni compuse este permis, dar nu este recomandabil).
Instruciunea de efect nul (instruciunea vid), nu are efect asupra variabilelor programului (nu
schimb starea programului). Ea nu este redat printr-un cuvnt cheie, dar deoarece instruciunile Pascal
sunt separate prin delimitatorul ";", prezenta acesteia este marcat de apariia acestui delimitator. n
exemplul: begin i:=i+1; ; write(i); end instruciunea cu efect nul apare ntre cei doi delimitatori "; ;" i ntre ";
end".
Instruciunea compus. Cnd ntr-o instruciune este necesar specificarea unei alte instruciuni, se
poate utiliza instruciunea compus indicat prin secvena begin ... end. Instruciunile dintre begin i end se
execut n ordinea n care apar. n secvena de mai jos,
i:=1;
while <=n do
begin read(x); s:=s+x; i:=i+1 end;
pentru fiecare i pentru care este adevrat condiia i<=N se vor executa instruciunile dintre begin i end.
Instruciuni iterative (repetitive). De foarte multe ori, un algoritm exprim execuia de zero sau mai
multe ori a unui grup de operaii. Pentru specificarea acestui aspect se utilizeaz iteraia (ciclul sau bucla)
concretizat ntr-o instruciune iterativ. Conform teoremei fundamentale a programrii structurate,
instruciunea repetitiv cu test iniial (while) este suficient pentru exprimarea oricrui algoritm, deci i a
oricrui program pentru calculator. Totui, pentru uzul programatorilor, limbajele de programare includ i
alte construcii. Instruciunile repetitive Pascal sunt: instruciunea while, instruciunea repeat (ciclul cu test
final) i instruciunea for (ciclul cu contor).
Instruciunea while are forma While C do S; unde C este o expresie logic, iar S este o instruciune.
Dac S exprim mai multe operaii, atunci reprezint o instruciune compus. Instruciunea S se execut ct
timp expresia logic C este adevrat. Dac expresia logic C este fals execuia continu cu urmtoarea
instruciune (imediat dup while). Dac de la nceput expresia C are valoarea false, atunci instruciunea S nu
se execut. Trebuie observat c blocul S trebuie s asigure o schimbare, n timp, a valorii de adevr a
condiiei C; altfel se obine o bucl infinit. Astfel, execuia secvenei: i:=1; While i<10 do read(x); va
continua indefinit. Pentru a asigura terminarea ciclului trebuie s modificm valoarea variabilei i. Secvena
corect este:
227

i:=1;
while < 10 do begin read(x); i:=i+1 end;
Alte construcii interesante sunt:
While true do I; (o bucl infinit) i
While false do I; (instruciune de efect nul - secvena I nu se execut niciodat).
Instruciunea repeat are forma repeat S until C; unde S este o secvena de instruciuni (nu neaprat
incluse ntr-o instruciune compus), iar C este o expresie logic. Secvena S se execut cel puin o dat,
execuia ei continund pn cnd condiia C este ndeplinit (valoarea de adevr a expresiei C este true).
Practic, n loc de
repeat S until C;
putem scrie
S; while (not C) do S;
Instruciunea for are una din formele: for v:=i to f do S sau
for v:=i downto f do S.
Variabila v, numit contor, trebuie s fie de tip ordinal (pe mulimea de definiie trebuie s aib sens funciile
succ(esor) i pred(ecesor)), iar i i f trebuie s fie expresii compatibile cu tipul variabile v. Forma for v:=i to f
do S este echivalent cu secvena:
v:=i; while v<= f do begin S; v := succ(v) end;
iar forma for v:=i downto f do S este echivalent cu secvena:
v:=i; while v>=f do begin S; v:=pred(v) end;
Valoarea final a variabilei v se consider a fi nedefinit dup terminarea normal a instruciunii for.
Instruciuni condiionale (instruciuni de decizie). O instruciune condiional selecteaz o singur instruciune
dintre mai multe alternative posibile. Limbajul Pascal, alturi de instruciunea if, permite i utilizarea unei instruciuni
de selecie multipl: instruciunea case.
Instruciunea if are una din forma: if C then S1 sau forma
if C then S1 else S2.
Pentru oricare dintre forme, iniial se evalueaz expresia logic C. Dac valoarea de adevr a acestei condiii
este true se va executa secvena de pe ramura then (S1), altfel n primul caz se execut instruciunea de efect
nul, iar n al doilea caz se execut secvena de pe ramura else (S2).
Instruciunea case utilizeaz o expresie numit selector i o list de instruciuni, fiecare element din
list fiind precedat de o constant cu un subdomeniu de valori din mulimea de baz a selectorului. Conform
notaiei BNF, forma instruciunii case este:
<instruciunea case> ::= case <selector> of
[ <element case> {; <element case>}] [else <instructine>][;] end
<element case> ::= <constant> {<constant>}
<constant1> .. <constant2>: <instruciune>
Expresia ce definete selectorul are valori ordinale cuprinse ntre 32768 i 32767.
Instruciunea with are forma general:
with <variabil record>{ ,<variabil record>} do <instruciune>
unde: lista dintre cuvintele rezervate with i do conine identificatorii variabilelor de tip nregistrare (record)
crora li se aplic instruciunea ce apare dup cuvntul do. Acest instruciune simplific modul de referire la
componentele nregistrrilor. n <instruciune> se folosesc numai identificatorii cmpurilor nregistrrilor
specificate n lista dintre with i do.
III.3.2. Subprograme Pascal
Proceduri Pascal. Elementele introduse anterior: tip de date, variabil, expresie, instruciune permit
codificarea riguroas a prelucrrilor de date sub form de programe. Noiunile de expresie i instruciune pot
fi generalizate prin intermediul subprogramelor (funcii i proceduri). Se poate introduce tipul subprogram
(numit i tip procedural).
Declaraia unui subprogram Pascal asociaz un identificator unui bloc de instruciuni precedat,
eventual, de o secvena declarativ. Identificatorul subprogramului poate fi urmat de o list de parametrii
formali. Identificatorul unei proceduri (urmat, eventual, de o list a parametrilor efectivi) poate fi folosit prin
intermediul instruciunii apel de procedur. Identificatorul unei funcii urmat, eventual, de o list a
argumentelor efective, poate fi folosit n expresii sau n orice loc unde poate fi prezent o expresie.
Declararea unei proceduri Pascal se realizeaz conform urm-toarelor reguli:
<procedur> ::= <antet_procedur>;<corp>
<antet_procedur> ::= procedure <identificator> [ (<list_parametrii>)];
<corp> ::= [ interrupt ; | near ; | far ;] (bloc | forward; | external;| directiv INLINE | directiv ASM )
228

Instruciunile ce se execut la activarea unei proceduri (n general, a unui subprogram) sunt descrise
n blocul subprogramului, n liniile INLINE sau n blocul ASM.
Funcii Pascal. Declararea unei funcii Pascal se supune regulilor urmtoare:
<funcie> ::= <antet>; <corp>
<antet> ::= = function <identificator> [ (list_parametrii_formali) ] : <tip_rezultat>;
<corp>::= [ near ;| far ;] (bloc | forward ;| external ;| directiv INLINE | directiv ASM)
Tipul rezultatului returnat este fie un nume de tip simplu, fie string.
Un subprogram function este activat printr-un apel de funcie. Apelul de funcie const din
identificatorul funciei urmat, eventual, de lista argumentelor funciei, ntre paranteze. Un apel de funcie
apare ca un operand ntr-o expresie. La evaluarea expresiei, se apeleaz i se execut subprogramul function,
iar valoarea operandului devine valoarea returnat de funcie. Zona de instruciuni a corpului specific
instruciunile ce urmeaz a-tilde; a fi executate la apelul funciei. Acest bloc trebuie s conin cel puin o
instruciune de atribuire care asociaz o valoare identificatorului funciei. Rezultatul ntors este ultima
valoare asociat. Cnd o astfel de instruciune lipsete, valoarea returnat de funciei nu este precizat.
Comunicarea ntre uniti de program. Comunicarea ntre programul principal i subprograme, precum
si comunicarea ntre subprograme se poate face prin entiti globale i prin parametri.
Comunicarea prin intermediul parametrilor permite tratarea subprogramelor ca pe nite blocuri
specializate avnd un anumit numr de linii de intrare i un anumit numr de linii de ieire. Aceast
comunicarea este posibil prin specificarea listei parametrilor la declararea i definirea unui subprogram. La
execuia apelului subprogramului valorile parametrilor de apel sunt substituite parametrilor formali (blocul
primete semnale concrete) astfel c aciunile instruciunilor subprogramului au loc asupra acestor valori.
Exist trei categorii de parametri formali: parametri valoare, parametri variabil, parametri fr tip.
Din punct de vedere sintactic, declararea parametrilor formali urmeaz regulile:
<list_parametri_formali>::= (<declaratie_parametru>{ ; <declaratie_parametru>} )
<declaratie_parametru> ::= <list_identificatori> : <tip> |
var <list_identificatori> : <tip> |
var <list_identificatori>
<tip> ::= <tip_simplu> | string | file
Un grup de identificatori neprecedai de var, dar urmai de un tip reprezint parametri valoare. Un
parametru valoare, pentru subprogram, se comport ca o variabil local, cu excepia faptului c la execuie
va fi iniializat cu valoarea parametrului actual corespunztor. Orice schimbare asupra unui parametru
valoare nu va afecta valoarea parametrului actual. Un parametru actual corespunztor unui parametru
valoare, ntr-un apel de subprogram, trebuie s fie o expresie, nu de tip file i nici de tip structurat altul dect
string. Parametrul actual i cel formal trebuie s aib tipuri compatibile.
Un grup de parametri precedai de var i urmai de un identificator de tip reprezint parametri
variabil. Un parametru variabil este utilizat atunci cnd subprogramul trebuie s furnizeze valori
apelantului. Parametrul actual, ntr-un apel de subprogram, trebuie s fie declarat ca variabil n unitatea
apelant sau mai sus, cnd este vorba de un identificator global. Parametrul formal de tip variabil, n timpul
unui apel, reprezint chiar parametrul actual, deci orice modificare asupra parametrului formal se va reflecta
asupra parametrului actual. Parametrul formal i parametrul actual corespunztor trebuie s fie de acelai tip.
Fiierele pot fi transmise numai ca parametrii variabil.
Un grup de parametri precedai de var, dar neurmai de tip reprezint parametrii fr tip. Cu ajutorul
acestora se pot realiza prelucrri generice. Parametrul actual corespunztor unui parametru fr tip trebuie s
fie declarat n unitatea apelant sau mai sus ca variabil. Utilizarea unui parametru fr tip, n subprogram,
presupune o conversie de tip pentru a suporta corespondenta cu parametrul actual.
Tipuri procedurale. Extinznd limbajul Pascal standard, Borland Pascal permite ca subprogramele s
fie tratate ca elemente ale unor mulimi de subprograme, deci se pot definii tipuri de date asociate
subprogramelor. Un astfel de tip de date se numete tip procedural.
Odat definit un tip procedural, putem declara variabile de acest tip - numite variabile procedurale,
iar aceste variabile pot fi folosite n atribuiri, cu operatorul =, cu operatorul <> i ca parametri n apelurile de
subprograme.
Declaraia unui tip procedural include parametri, iar pentru funcii, i tipul rezultatului. Regulile
avute n vedere la o astfel de declarare sunt descrise prin:
<tip_procedural> ::= <tip_procedure>| <tip_function>
<tip_procedure> ::= procedure;|
procedure (<list_parametri_formal>);
<tip_function> :=
function : <tip_rezultat>;|
229

function (<list_parametri_formali>):<tip_rezultat>;
Identificatorii parametrilor n <list_parametri_formali> sunt pur decorativi, ei nu au o semnificaie
deosebit n partea declarativ. Exemple:
type proc = procedure;
proc2int = procedure(var a, b:integer);
procstr = procedure(var s:string);
funcmat = function(x: real):real;
funcmat2 = function(x, y: real):real;
Eqfunc = function (a, b: real; f:funcmat): real;
Nu putem scrie subprograme de tip funcie care s returneze variabile procedurale. Funciile pot
returna valori din urmtoarele categorii: string, real i variantele, integer si variantele, char, boolean, pointer
(referin) i enumerare (definit de utilizator).
O variabil procedural se declar ca orice alt variabil.
III.4. Programare n C
Limbajul C a fost creat la AT & T Bell Laboratories n anul 1972 de Dennis Ritchie. Versiunea
standard a limbajului C pn n anul 1988 a fost cea furnizata odat cu sistemul de operare UNIX i descris
n [14]. n anul 1983 a nceput redactarea standardului ANSI pentru limbajul C. Standardul ANSI a fost
finalizat n anul 1990.
III.4.1. Structura programelor C
n limbajul C programul este o colecie de module distincte numite funcii, organizate n una sau mai
multe uniti de translatare. Fiecare unitate de translatare poate fi compilat (analizat lexical i sintactic)
separat. O unitate de translatare trebuie s conin cel puin o declaraie sau o definiie de funcie. Ea const
din fiierul surs mpreuna cu oricare fiier antet i fiiere surs incluse prin directiva #include. O unitate de
translatare, prin compilare, conduce la un fiier obiect (.obj) relocabil.
Directivele precedate de delimitatorul # se numesc directive preprocesor, acestea specificnd operaii
anterioare procesului de compilare ce sunt efectuate de o componenta a mediului de programare numit
preprocesor.
O declaraie C specific atributele unui identificator sau mulime de identificatori. Regulile sintactice
ce stau la baza scrierii declaraiilor sunt redate prin:
<declaraie> ::= <specificator declaraie>
[ <lista declaratori de iniializare> ] ;
<specificator declaraie> ::=
<clasa de memorare> [ <specificator declaraie> ] |
<specificator tip> [ <specificator declaraie> ] |
<calificator tip> [ <specificator declaraie> ]
<lista declaratori de iniializate> ::= < declarator iniializare> |
<lista declaratori iniializare>, <declarator iniializare>
<declarator iniializare> ::= <declarator> |
<declarator> = <iniializare>
A face o declaraie nu presupune i alocarea memoriei pentru identificatorul declarat. Exista situaii
cnd alocarea se realizeaz n alt unitate de translatare (cazul datelor externe).
Declaraia unui identificator asociaz numelui n mod explicit sau implicit o serie de atribute din
mulimea urmtoare:
Clasa de memorare - localizeaz zona de memorie n care este plasat elementul declarat (zona de date,
un registru al procesorului, stiva mediului de programare, zona de alocare dinamic) i delimiteaz
durata alocrii (ntreg timpul de executare a programului, executarea unei funcii sau a unui bloc etc.).
Domeniul numelui - reprezint poriunea din program n care poate fi utilizat identificatorul pentru
accesarea informaiei asociate i este determinat de poziia declaraiei.
Durata de stocare - reprezint perioada ct elementul asociat exist efectiv n memorie.
Legtura - indic modul de asociere a unui identificator cu un anumit obiect sau funcie, n procesul de
editare a legturilor.
Tipul datei (standard sau definit de utilizator) - descrie informaia coninut de elementul definit de
identificator.
Clasa de memorare este specificat prin unul dintre cuvintele cheie: typedef, extern, static, auto,
register. Declaraia auto se poate utiliza pentru variabile temporare - alocate folosind stiva, cu domeniul
230

local. Variabilele declarate n interiorul unui bloc sunt implicit locale, deci auto este rar utilizat. n limbajul
C clasic, o declaraie register reprezint un apel la compilator pentru a stoca o variabil int sau char ntr-un
registru al procesorului pentru a creste viteza de executare. Versiunile actuale permit specificarea register
pentru orice tip, semnificaia apelului fiind de optimizare a timpului de acces. Specificatorul typedef indic
faptul c nu se declar o variabil sau funcie de un anumit tip, ci se asociaz un nume tipului de date.
Sintaxa este:
typedef <definiie tip> <identificator>;
Specificatorul static poate s apar n declaraii locale de variabile pentru a indica durata static sau
n declaraii globale de funcii i de variabile pentru a indica legtura intern. Specificatorul extern este
utilizat pentru declaraii de funcii sau variabile locale sau globale pentru a indica legtura extern i durata
static.
n C (precum i n Pascal), declaraia unei variabile trebuie s precead orice referire a ei. Ea poate
aprea n exteriorul oricrei funcii, n lista de parametri formali ai unei funcii sau la nceputul unui bloc.
Domeniul numelui este regiunea dintr-un program C n care identificatorul este "vizibil". Poziia declaraiei
determina urmtoarele domenii:
Domeniul bloc - caracterizeaz identificatorii locali (identificatorii declarai n interiorul unui bloc i au
domeniul cuprins ntre declaraie i sfritul blocului; parametrii formali din definiia unei funcii au ca
domeniu blocul funciei).
Domeniul fiier - caracterizeaz identificatorii declarai n exteriorul oricrei funcii - numii
identificatori globali - i care au domeniul cuprins ntre declaraie i sfritul fiierului.
Domeniul funcie - aplicabil pentru etichetele instruciunilor i este blocul funciei.
Domeniul prototip - definit pentru identificatorii specificai n lista de parametrii din prototipul unei
funcii - i care au domeniul limitat la acel prototip.
Partea din domeniu n care informaia asociata este accesibila se numete zona de vizibilitate. O
declaraie a unui identificator este vizibila n tot domeniul sau mai puin blocurile sau funciile n care
identificatorul este redeclarat. Pentru identificatorii globali se poate repeta declaraia, dar iniializarea trebuie
s se fac o singur dat.
Un identificator declarat n diferite domenii, de mai multe ori, sau redeclarat n acelai domeniu se
poate referi la acelai obiect sau funcie prin procesul numit legare. Legarea poate fi intern, extern sau
unic. Dac un identificator are domeniul fiier i clasa de memorare static, el se supune legrii interne. Daca
un identificator are clasa de memorare extern, el se supune aceluiai tip de legare precum orice declaraie
vizibila a identificatorului cu domeniu fiier; dac nu exist declaraii vizibile cu domeniul fiier, se supune
implicit legrii externe. Pentru identificatorii cu legtura extern sunt permise mai multe declaraii de
referin, dar trebuie s existe o singur definiie. Funciile au implicit legtura extern i durata static.
Specificatorii de tip indic modul de alocare asociat unei variabile sau tipul rezultatului unei funcii.
n C, exist urmtoarele categorii de tipuri: tipuri de funcii, tipuri de variabile i tipul void. Variabilele pot fi
de tip scalar, de tip structurat sau de tip uniune. Tipurile scalare sunt tipuri aritmetice i tipul pointer.
Tipurile structurate cuprind tablourile i nregistrrile (numite n C, structuri). n categoria tipurilor
aritmetice intr mulimile de elemente specificate prin cuvintele cheie: char, int, float, double; extinse cu
ajutorul modificatorilor de tip: signed, unsigned, short, long. Tot tip aritmetic este considerat a fi i tipul
obinut prin enumerare.
Tipul void indic absena oricrei valori i este utilizat n urmtoarele situaii: declaraia unei funcii
fr parametrii sau fr rezultat, tipul pointer generic i conversii de tip pentru pointeri.
Literalii sunt i ei afectai de existenta modificatorilor de tip prin indicarea unui sufix (U, u, L, l, f,
F). Efectul sufixului asociat unui literal ntreg este ilustrat prin situaiile: U sau u - unsigned int sau
unsigned long int (n funcie de valoare); L sau l - long int sau unsigned long int (n funcie de valoare);
UL, ul, Ul, uL - unsigned long int. Un literal de tip numr zecimal, este automat de tip double; dac se
utilizeaz sufixul F sau f va fi considerat de tip float, iar dac se utilizeaz sufixul L sau l, va fi considerat de
tip long double.
Tabloul este o list de elemente de acelai tip plasate succesiv ntr-o zona contigu de memorie. Nu
exist limit pentru numrul dimensiunilor tabloului.
Structura este o colecie de date eterogene (corespunde tipului record din limbajul Pascal). O
declaraie de structura precizeaz identificatorii i tipurile elementelor componente i constituie o definiie a
unui tip de date nou. Acestui tip i se poate asocia un nume. n cazul general, sintaxa declaraiei unei structuri
este:
<declaraie structura> ::=
struct < id _tip> {
<tip _camp _1> <id _camp _1>;
231

<tip _camp _2> <id _camp _2>;


...
<tip _camp _i> <id _camp _i>;
...
<tip _camp _n> <id _camp _n>;
} <lista identificatori de tip struct>;
in care:
struct - este cuvnt cheie pentru construirea unui tip nregistrare;
<id_tip> - este un identificator ce desemneaz numele tipului structur ce este declarat;
<tip_camp_i> - tipul cmpului i;
<id_camp_i> - identificatorul cmpului i (cmpurile structurii se mai numesc i membrii structurii);
<lista identificatori de tip struct> - lista identificatorilor declarai.
Referirea unui membru al unei variabile de tip structur se face folosind operatorul de selecie (.)
ntr-o expresie care precizeaz identificatorul variabilei i al cmpului.
Alocarea cmpurilor poate ridica probleme de portabilitate, deoarece organizarea memoriei depinde
de sistemul de calcul.
Uniunile sunt entiti care pot conine (la momente de timp diferite) obiecte de tipuri diferite. Practic,
mai multe variabile sunt suprapuse n acelai spaiu de memorie. Sintaxa declaraiei este similar cu cea a
structurii, dar identificatorii declarai ca membrii reprezint numele cu care sunt referite diferitele tipuri de
variabile ce ocup aceeai zona de memorie:
<declaraie uniune> ::=
union <id_tip> {
<tip_var_ 1> <id_var_1>;
<tip_ var_2> <id_ var_2>;
...
<tip_ var_i> <id _var_i>;
...
<tip_ var_ n> <id_ var_n>;
} <lista identificatori de tip union>;
Spaiul alocat n memorie corespunde tipului cu dimensiune maxima. Tipurile uniune sunt utile
pentru conversii de date, n implementarea programelor de comunicaie etc.
Tipul enumerare const dintr-un ansamblu de constante ntregi (cel puin un element), fiecare fiind
asociat cte unui identificator. Constanta unui element al enumerrii este fie asociat implicit, fie explicit.
Implicit, primul element are asociat valoarea 0, iar pentru restul este valoarea _precedenta+1.
Cel mai simplu program C este constituit din directive preprocesor, declaraii globale i funcii.
Printre funcii trebuie s existe una cu numele "main " cu care va ncepe executarea programului. Chiar dac
programul este organizat pe mai multe fiiere surs, numai ntr-un singur fiier, numai o singura funcie
poate purta numele "main". Celelalte funcii sunt subprograme definite de programator sau funcii din
biblioteca de subprograme. Limbajul C nu conine funcii predefinite cum sunt cele din unitatea System a
mediului Borland Pascal.
Funciile din bibliotecile C sunt declarate mpreuna cu constantele, tipurile i variabilele globale
asociate, n fiiere antet, cu extensia ".h", situate n subarborele include al arborelui asociat mediului de
programare. Operaiile de intrare-ieire necesit specificarea fiierului stdio.h, ncadrat de delimitatorii < i
>, ntr-o directiv{ # include. Fiierele antet ale programatorului vor fi ncadrate folosind delimitatorul ".
O funcie C are structura:
<tip_ rezultat> <id_functie> (<lista _parametri_ formali>){
declaratii_locale
secventa_instructiuni
}
unde <tip_ rezultat> indica tipul rezultatului returnat de funcie, <id _funcie> reprezint numele
(identificatorul) funciei, iar <lista_parametri_ formali> const n enumerarea declaraiilor parametrilor
funciei sub forma:
<tip_ parametru> <id_ parametru> [ ,<tip_parametru> <id _parametru>]
Acoladele { } sunt delimitatori ce ncadreaz o instruciune compus (bloc) alctuita din declaraii i
instruciuni.
Secvena de instruciuni a funciilor pentru care <tip _rezultat> este diferit de tipul void, trebuie s
conin o instruciune return, cu sintaxa general:
232

return <expresie>
Rezultatul funciei este valoarea expresiei.
Funcia main poate avea parametri i poate ntoarce un rezultat.
III.4.2. Funciile de intrare-ieire pentru consol
Consola sau dispozitivul standard de intrare-ieire reprezentate de tastatur (zona de date - stdin) i
ecran (zonele de date - stdout i stderr) permit utilizatorului interaciunea cu programul aflat n executare.
Sunt posibile operaii de citire/scriere fr formatare i operaii de citire/scriere cu formatare.
Operaii de citire/scriere fr formatare. Acestea permit lucrul cu caractere (char ) sau cu iruri de
caractere (* char).
Pentru citirea unui caracter din stdin pot fi utilizate funciile: int getchar(void), int getche(void ) i
int getch( void), ultimele dou variante nefiind prevzute de standardul ANSI, dar sunt prezente n versiunile
Borland (fiierul antet conio.h). Funcia getchar ntoarce primul caracter din stdin, care corespunde primei
taste apsate, dar numai dup apsarea tastei Enter. Caracterul este transformat n ntreg fr semn. n cazul
unei erori sau la ntlnirea combinaiei EOF (sfrit de fiier) funcia ntoarce valoarea -1 (codificat prin
EOF).
Funcia getche ateapt apsarea unei taste i ntoarce caracterul corespunztor pe care l afieaz pe
ecran (nu e nevoie de Enter ). Funcia getch este similara cu getche(), dar nu afieaz ecoul pe ecran.
Pentru scrierea unui caracter la stdout se utilizeaz funcia int putchar (int c) care afieaz pe ecran
caracterul cu codul ASCII c. Dac operaia reuete, ntoarce caracterul afiat, iar n caz de eec valoarea
EOF (-1).
Pentru citirea (resp. scrierea) irurilor de caractere se lucreaz cu funcia gets (respectiv puts).
Funcia cu prototipul char *gets (char *s) citete caractere din stdin i le depune n zona de date de la
adresa s, pn la apsarea tastei Enter. n ir, tastei Enter i va corespunde caracterul '\0'. Dac operaia
reuete, funcia ntoarce adresa irului, altfel valoarea NULL ( = 0 ). Funcia cu prototipul int puts( const
char *s) afiaz pe ecran irul de la adresa s sau o constant ir de caractere (secvena de caractere ntre
ghilimele) i apoi trece la linie noua. La succes, funcia ntoarce ultimul caracter, altfel valoarea EOF.
Operaii de citire/scriere cu formatare. La citire, formatarea specific conversia datelor de la
reprezentarea extern n reprezentarea binar. Pentru operaia de scriere se efectueaz conversia invers.
Pentru citirea datelor se utilizeaz funcia scanf cu prototipul:
int scanf( const char * format [ , lista_adrese_ variabile] );
iar pentru scrierea datelor se utilizeaz funcia printf cu prototipul:
int printf( const char *format, lista_valori);
irul de caractere format poate conine n general:
1. specificatori de format: iruri precedate de caracterul '%' care descriu fiecare cmp ateptat;
2. caractere de spaiere: spaiu (' '), tab ('\t'), linie noua ('\n');
3. orice alt caracter Unicode.
Fiecrei variabile din lista i corespunde o specificaie de format (tipul I.). Funcia scanf ntoarce
numrul de cmpuri citite i depuse la adresele din list. Dac nu s-a stocat nici o valoare, funcia ntoarce
valoarea 0. Funcia printf ntoarce numrul de octei transferai sau EOF n caz de eec.
Funcia scanf citete succesiv caractere din stdin pe care le interpreteaz prin compararea succesiv a
caracterului citit cu informaia curent din irul format. Prezena unui caracter de tip II determin citirea fr
memorare a secvenei pn la ntlnirea unui caracter de tip I sau III. Prezena unui caracter de tip III determin
citirea fr stocare a caracterului curent de la tastatur, dac este identic.
La scriere, caracterele de tip II i III se afieaz pe ecran aa cum apar n irul format. Forma
general a unui descriptor pentru scriere este:
% [ flags] [ width] [ .prec] [ lmod] type
specificaiile dintre [ i ] fiind opionale. Elementele de mai sus au urmtoarea semnificaie:
flags - poate fi unul dintre semnele: +, -, 0, spaiu, #. Semnele au urmtoarea semnificaie:
: aliniere la stnga a argumentului n cadrul cmpului;
+
: numerele vor fi obligatoriu tiprite cu semn;
0
: indic completarea la stnga cu zerouri (la numere);
spaiu: daca primul caracter nu e semnul , se va afia un spaiu;
width: este un numr care specifica limea minima a cmpului. Argumentul corespunztor va fi
afiat pe un cmp cu latine cel puin width. Dac sunt mai puine caractere de scris, se va completa cmpul
cu spatii la stnga (implicit) sau la dreapta, dac s-a specificat flag-ul -. Dac s-a specificat flagul 0, se va
233

completa la stnga cu zero. Dac width este caracterul *, atunci limea este dat de urmtorul argument din
list (trebuie s fie neaprat un int).
prec: este un numr care specifica precizia de scriere; pentru %s prec indic numrul maxim de
caractere ce se va scrie; pentru %e, %E si %f prec indic numrul de zecimale; pentru %g si %G prec indic
numrul de cifre semnificative, iar la descriptorii pentru ntregi indic numrul minim de cifre. Daca prec
este *, atunci se consider c limea de scriere este dat de urmtorul argument din list, care trebuie sa fie
de tip int.
lmod: este un specificator de lungime care corespunde unui argument short sau unsigned short (h),
long sau unsigned long (l), respectiv long double (L).
type: este descriptorul propriu-zis. Se utilizeaz urmtoarele caractere: d, i (int ) - notaie zecimal cu
semn; 0 (int ) - notaie n baza 16 fr semn; x, X (int ) - notaie n baza 16 fr semn cu abcdef pentru x i
ABCDEF pentru X; u (int ) - notaie zecimal fr semn; c (int ) - un caracter; s (char *) - ir de caractere
terminat cu '\0' ; f (double ) - numrul n virgul mobil cu format standard; e, E (double ) - numrul n
virgul mobil cu format exponenial; g, G (double ) - n loc de f, e, E; p (void *) - se tiprete argumentul
ca adres; % - se tiprete %.
Forma general a unui descriptor pentru citire este:
% [ *] [ width] [ lmod] type
unde:
* - suprim atribuirea urmtorului cmp din stdin la urmtoarea variabila;
width, lmod - ca mai sus;
type - descrie tipul de conversie. Cele mai importante specificaii de conversie sunt: d (int *) - ntreg
zecimal; i (int *) - ntreg oarecare (zecimal, octal sau hexa); o (int *) - ntreg octal; u (unsigned int *) ntreg zecimal fr semn; x (int *) - ntreg hexa, c (char *) - caractere; s (char *) - ir de caractere (se va
ncheia cu '\0 '); e, f, g (float *) - numere n virgul mobil; p (void *) - valoarea unei adrese aa cum e
tiprit de printf.
n descrierea de mai sus, ntre paranteze se indica tipul argumentului supus operaiei de intrareieire. Notaia tip * nseamn adresa unei locaii de tipul tip.
III.4.3. Operatori i expresii
Operatorii sunt simboluri care descriu operaii efectuate asupra unor variabile sau constante (numite
generic operanzi). O combinaie corect de operatori, variabile, constante, apeluri de funcii reprezint o
expresie. Pentru construcia expresiilor, limbajul C ofer o gam foarte larg de operatori.
Operatorul de atribuire. Operatorul de atribuire (=) permite crearea unei expresii de forma:
<variabila> = <expresie>
ce se evalueaz de la dreapta la stnga. Dup evaluarea membrului drept, valoarea rezultata este nscrisa n
<variabila>, iar ntreaga construcie are valoarea variabilei dup nscriere.
Operatori aritmetici. Operatorii aritmetici sunt: + (adunare), - (scdere), * (nmulire), / (mprire),
% (mprire modulo mpritor). Ordinea operaiilor este cea binecunoscut, dar se pot utiliza paranteze
pentru schimbarea ordinii operaiilor. Pentru scrierea instruciunii de atribuire <variabila> = <variabila> + 1;
se poate utiliza forma prescurtat <variabila>++, operatorul ++ fiind numit operator de incrementare. Exist,
de asemenea, i un operator de decrementare (--): <variabila>--; ce este echivalentul instruciunii:
<variabila> = <variabila> - 1;
Operatori logici i relaionali. Pentru scrierea expresilor booleene se utilizeaz operatorii logici i
operatorii relaionali. Exist trei operatori logici: || (SAU logic - SAU INCLUSIV), && (SI logic), ! (NU
logic). Operatorii relaionali ntlnii n limbajul C sunt urmtorii: < (mai mic strict), > (mai mare strict), <=
(mai mic sau egal), >= (mai mare sau egal), == (egal cu), != (diferit de). Ori de cte ori relaia este fals se
genereaz valoarea 0, valoarea 1 fiind generat atunci cnd relaia este adevrat. Trebuie evideniat c
operatorii aritmetici au prioritate fa de operatorii relaionali.
Operatori la nivel de bit. Operatorii la nivel de bit se pot aplica operanzilor de tip ntreg (char, int,
short, long , cu sau fr semn): & (SI logic la nivel de bit), (SAU logic la nivel de bit), ^ (SAU exclusiv la
nivel de bit), << (deplasare stnga), >> (deplasare dreapta) i (negare la nivel de bit).
Operatori de atribuire combinai. Pentru realizarea atribuirii
<variabila> = <variabila> <operator> <var _sau_const>;
se pot utiliza operatorii de atribuire combinai: += (atribuire cu adunare), -= (atribuire cu scdere), *=
(atribuire cu nmulire), /= (atribuire cu mprire), %= (atribuire cu mprire modulo); expresia fiind scris
prescurtat:
<variabila> <operator>= <var _sau_const>;
234

Operatorul virgul. n limbajul C, virgula (,) este un operator binar, care leag expresii oarecare.
Construcia <expresie_ 1>, <expresie_2> este una corect, constnd din evaluarea celor dou expresii, n
ordinea n care apar, valoarea ntregii construcii fiind dat de valoarea lui <expresie_2>. Asocierea
operatorului virgul se face de la stnga la dreapta, astfel nct o expresie de forma e1,e2,e3 este echivalent
cu: (e1, e2), e3.
Operatorul condiional (?:) Operatorul condiional este o construcie decizional a limbajului C care
are urmtoarea forma general:
<Expresie-booleana> ? <expresie_ 1> : <expresie _2>; avnd
urmtorul neles: Dac <Expresie-booleana> este adevrat. atunci ntreaga expresie condiional are
valoarea <expresie_1>, n caz contrar, valoarea expresiei condiionale fiind valoarea <expresie_2>.
Ali operatori: n aceast categorie includem operatorii specifici tipului referin, operatorii pentru
selectarea elementelor unui tip de date structurat, precum i operatorii introdui de extensia C++.
III.4.4. Instruciuni C
Cea mai simpl instruciune C este instruciunea <expresie>; ce ofer un echivalent n C pentru
urmtoarele instruciuni Pascal: atribuire, apel de procedur, instruciunea vid. O secven de instruciuni
ncadrat de acolade este considerat ca o singur instruciune i este numit instruciune compus sau bloc.
Spre deosebire de instruciunea compus a limbajului Pascal, instruciunea compus din limbajul C poate
conine att declaraii, ct i instruciuni, declaraiile fiind poziionate la nceputul blocului. n mod implicit,
identificatorii declarai n blocul delimitat de acolade, au ca domeniu de vizibilitate blocul, iar timpul de
via este limitat la timpul de executare a blocului.
Programarea unei structuri decizionale, n C, poate fi realizat folosind: instruciunea if...else ;
operatorul condiional (?:) i instruciunea switch. Sintaxa instruciunii if...else este:
<instructiune_if> ::=
if ( <Expresie>) <Instruciune _T>;
if ( <Expresie>) <Instruciune_ T> else <Instruciune_ F>
unde: <Expresie> are o valoare de tip scalar reprezentnd o constructe de tip expresie, <Instruciune_ T>
reprezint o instruciune C care se va executa cnd <Expresie> are o valoare nenul (adevrat), iar
<Instruciune_ F> reprezint acea instruciune C ce se va executa pentru valoare 0 (false) a lui <Expresie>.
Conform celor de mai sus, construcia: e1 ? e2 : e3; poate nlocui instruciunea if...else: if (e1) e2;
else e3;
Atunci cnd o selecie multipl este controlat de valoarea unei singure expresii, se poate utiliza
instruciunea switch , un pseudo-echivalent C a construciei Pascal case .
Sintaxa instruciunii switch este:
<instructiune_switch> ::= switch ( <expresie>) {
case <const_ 1> : <lista_ instruciuni> [ break;]
case <const_2> : <lista _instruciuni> [ break;]
...
[ default:] <lista_instructiuni> [ break ;]
}
unde: <expresie> este o expresie cu valoare ntreag (tip ntreg sau enumerare); <const_1>, <const _2>, ...
sunt constante de selecie, cu valori distincte, convertibile la tipul expresiei <expresie>, iar <lista
_instructiuni> este o secven de instruciuni C.
Fiecare etichet case indic o singur constant, dar se pot asocia mai multe etichete case , scrise
consecutiv, pentru aceeai secvena de instruciuni.
Instruciunea break ntrerupe lista de instruciuni i duce la ncheierea instruciunii switch . Dac
valoarea expresie nu apare n lista constantelor de selecie, se execut instruciunile asociate etichetei default
, dac exist.
Programarea ciclurilor poate fi realizat folosind instruciunile de ciclare: ciclul cu test iniial
(instruciunea while ), ciclul cu test final (instruciunea do...while ) i ciclul cu test iniial i contor
(instruciunea for ).
Forma instruciunii while este:
while (<expresie>) <instruc#iune>.
n particular, <instruciune> poate fi chiar instruciunea vid.
Sintaxa instruciunii do..while este:
do <instruciune> while (<expresie>);
Instruciunea dintre do i while se execut cel puin o dat i se repet ct timp <expresie> este
compatibil cu valoarea logic adevrat.
235

Instruciunea for, ofer cea mai compact metod pentru scrierea ciclurilor cu test iniial i are o
definiie care i extinde domeniul de aplicare fa de alte limbaje de programare. Forma instruciunii for este:
for ( <expresie_1> ; <expresie_3> ; <expresie_3> ) <instruciune>
i are efectul similar cu al secvenei:
<expresie_1>; while (<expresie_2>) { <instruciune> <expresie_3>;}
Cele trei expresii dintre paranteze pot fi toate vide, caz n care avem de-a face cu un ciclu infinit.
ntreruperea necondiionat a unei secvene de instruciuni i continuarea dintr-un alt punct al
programului este posibil prin utilizarea instruciunilor de salt: goto (salt la o instruciune etichetat), break
(n contextul instruciunii switch ct i n instruciunile de ciclare pentru a determina ieirea forat din ciclu,
indiferent de valoarea condiiei de ciclare) i continue (n cadrul blocului instruciunilor de ciclare pentru a
ntrerupe execuia iteraiei curente). n cazul instruciunilor while i do..while, instruciunea continue
determin activarea testului condiiei de ciclare, iar pentru instruciunea for se va continua cu evaluarea, n
aceast ordine, expresiilor <expresie_3>, <expresie_2>.
BIBLIOGRAFIE
1. Albeanu G., Algoritmi si limbaje de programare, Editura Fundaiei Romnia de Mine, Bucureti,
2000.
2. Albeanu G., Luminita Radu, Algoritmica i programare n Pascal, Editura Fundaiei Romnia de
Mine, Bucureti, 2001.
3. Knuth D., Arta programrii calculatoarelor, vol. I, Algoritmi fundamentali, Editura Teora, 2000.
4. Livovschi L., Georgescu H., Analiza i sinteza algoritmilor, Editura tiinific i Enciclopedic,
1974.
5. Albeanu G., Tehnici de programare, Lucrri practice de programarea calculatoarelor, Editura
Fundaia Romnia de Mine, 2003.
6. Brz S., Culegere de probleme de algoritmic i programare, vol I, Programare static, Editura
Universitii Bucureti, 2001.
7. Brz S., Algoritmic i programare. Note de curs, vol. I, Programare static, Editura Universitii
Bucureti, 2001.

236

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