Sunteți pe pagina 1din 204

ANDREI BUTU PAUL VASILIU

Academia Naval Mircea cel Btrn


Constan#a, 2009
BAZELE PROGRAM$RII
CALCULATOARELOR
Referen#i $tiin#ifici: Conf. univ. dr. Ion Col#escu
Conf. univ. dr. Ioan Popoviciu
Editura Academiei Navale Mircea cel B'trn
Str. Fulgerului nr.1, 900218, Constan#a
Tel. 0241/626200/1219, fax 0241/643096
Email: editura@anmb.ro
Descrierea CIP a Bibliotecii Naionale a Romniei








Editura Academiei Navale Mircea cel B'trn, 2009,
pentru prezenta edi#ie.
1
P
PPR
RRE
EEF
FFA
AA)
))

Programarea calculatoarelor este una dintre
disciplinele din domeniul informaticii care are un loc bine
definit n planurile de nv'#'mnt ale universit'#ilor cu
profil tehnic, cu impact real n formarea viitorilor ingineri.
Limbajul de programare C este folosit pe scar'
larg' att de programatorii de sistem pentru scrierea $i
dezvoltarea sistemelor de operare (Windows, Unix,
Linux), ct $i de programatorii de aplica#ii din diverse
domenii. Datorit' caracteristicilor sale (portabilitate,
controlul modern al fluxurilor, setul bogat de operatori,
multitudinea func#iilor de bibliotec') limbajul poate fi
utilizat pe orice platform' $i asigur' accesul
programatorului la toate resursele calculatorului.
Cui se adreseaz cartea?
Cartea se adreseaz' studen#ilor din universit'#ile
cu profil tehnic care parcurg programa cursului de
programarea calculatoarelor $i limbaje de programare,
celor care doresc s' programeze n limbajul C, dar $i
celor care au deja experien#' n programare.

2
Con#inutul c'r#ii urmeaz' programa cursului
Programarea calculatoarelor $i limbaje de programare
predat de autori studen#ilor din anul nti la Academia
Naval' Mircea cel B'trn din Constan#a.
Nota#ii folosite n carte
Carte con#ine urm'toarele nota#ii pentru a nlesni
urm'rirea explica#iilor $i secven#elor de program:
secven#ele de program sunt scrise cu font
propor#ional simplu:
printf("Bine ai venit!").
dac' secven#a de program este mai mare, atunci
va fi scris' ntr-un paragraf separat, cu o linie de
marcare n partea stng':
puts("Programarea");
puts("Calculatoarelor in");
puts("Limbajul C");
rezultatele execu#iei programelor sunt scrise cu
font propor#ional ngro$at:
Bine ai venit!
dac' rezultatele sunt mai multe, atunci vor fi scrise
ntr-un paragraf separat, ntr-o caset' cu chenar
ntrerupt:
Programarea
Calculatoarelor in
Limbajul C
observa#iile $i informa#iile suplimentare legate de
diverse no#iuni vor fi marcate printr-un paragraf
special, astfel:

3
i Acest paragraf v' ofer' informa#ii suplimentare
referitoare la no#iunile prezentate anterior.
Mul#umiri
Mul#umim familiilor noastre care ne-au sus#inut n
realizarea acestei c'r#i $i au ndurat orele trzii de
munc'. Mul#umim colegilor care au f'cut observa#ii
pertinente privind con#inutul acestei c'r#i $i colectivului
Editurii Academiei Navale Mircea cel B'trn pentru
sfaturile $i suportul tehnic acordat.
De asemenea, mul#umim anticipat celor care vor
aduce sugestii pentru mbun't'#irea acestei c'r#i.


Autorii.
Aprilie 2009
5
C
CCU
UUP
PPR
RRI
IIN
NNS
SS
1. Algoritmi $i limbaje algoritmice...................................11
1.1. De la problem' la program.................................. 11
1.1.1. Specificarea problemei ................................. 11
1.1.2. Proiectarea algoritmului de rezolvare a
problemei................................................................ 13
1.1.3. Codificarea algoritmului ................................ 13
1.1.4. Testarea $i validarea programului.................14
1.2. No#iunea de algoritm...........................................14
1.3. Reprezentarea algoritmilor .................................. 16
1.3.1. Scheme logice ..............................................16
1.3.2. Limbajul pseudocod...................................... 19
1.4. Exemple ..............................................................24
1.5. Exerci#ii................................................................ 36
2. Unit'#i lexicale............................................................39
2.1. Mul#imea caracterelor..........................................39
2.2. Comentarii ...........................................................41
2.3. Tipuri de date primare .........................................42
2.4. Constante............................................................43
2.4.1. Constante de tip caracter..............................44
2.4.2. Constante de tip $ir de caractere..................45
2.4.3. Constante de tip ntreg ................................. 46
2.4.4. Constante de tip flotant................................. 47
2.5. Cuvinte cheie.......................................................47
2.6. Identificatori .........................................................48
Algoritmi $i limbaje algoritmice
6
2.6.1. Variabile........................................................48
2.6.2. Masive ..........................................................49
2.7. Exemple ..............................................................50
2.8. Exerci#ii................................................................ 51
3. Expresii. Operanzi. Operatori..................................... 53
3.1. Expresii ............................................................... 53
3.2. Operanzi..............................................................54
3.3. Conversii implicite de tip...................................... 54
3.4. Operatori ............................................................. 55
3.4.1. Operatori de adresare...................................59
3.4.2. Operatori unari..............................................60
3.4.3. Operatori multiplicativi .................................. 62
3.4.4. Operatori aditivi.............................................63
3.4.5. Operatori pentru deplasare...........................64
3.4.6. Operatori rela#ionali ...................................... 65
3.4.7. Operatori de egalitate ...................................65
3.4.8. Operatori pe bi#i ............................................66
3.4.9. Operatori logici..............................................67
3.4.10. Operatorul condi#ional................................. 67
3.4.11. Operatori de atribuire.................................. 68
3.4.12. Operatorul virgul' .......................................69
3.5. Exemple ..............................................................70
3.6. Exerci#ii................................................................ 77
4. Instruc#iuni ................................................................. 79
4.1. Instruc#iuni expresie ............................................79
4.2. Instruc#iuni de decizie..........................................80
4.2.1. Instruc#iunea if ..............................................80
4.2.2. Instruc#iunea switch ...................................... 81
4.3. Instruc#iuni de ciclare...........................................83
4.3.1. Instruc#iunea do-while...................................83
4.3.2. Instruc#iunea while........................................84
4.3.3. Instruc#iunea for ............................................84
4.4. Instruc#iuni de salt ...............................................86
4.4.1. Instruc#iunea break .......................................86
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
7
4.4.2. Instruc#iunea continue...................................87
4.4.3. Instruc#iunea goto .........................................87
4.5. Exemple ..............................................................88
4.6. Exerci#ii..............................................................104
5. Func#ii standard de intrare/ie$ire..............................107
5.1. Func#ii pentru caractere.....................................107
5.2. Func#ii pentru $iruri de caractere.......................108
5.3. Func#ii cu formatare...........................................109
5.3.1. Codurile de format ale func#iei printf ...........110
5.3.2. Codurile de format ale func#iei scanf...........114
5.4. Func#ii cu formatare pentru $iruri de caractere.. 117
5.5. Exemple ............................................................118
5.6. Exerci#ii..............................................................122
6. Tipuri de date compuse ...........................................123
6.1. Masive............................................................... 123
6.2. Structuri............................................................. 125
6.3. Uniuni ................................................................ 128
6.4. Cmpuri............................................................. 129
6.5. Exemple ............................................................130
6.6. Exerci#ii..............................................................147
7. Func#ii ......................................................................149
7.1. Declararea $i definirea func#iilor ........................149
7.1.1. Prototipul func#iilor ......................................151
7.1.2. Transferul parametrilor ............................... 152
7.2. Apelul func#iilor ..................................................152
7.3. Transmiterea parametrilor .................................154
7.3.1. Transferul prin parametri............................. 154
7.3.2. Transferul prin variabile globale..................159
7.4. Recursivitate......................................................161
7.5. Exemple ............................................................163
7.6. Exerci#ii..............................................................202
8. Pointeri $i gestiunea dinamic' a memoriei...............205
8.1. Pointeri ..............................................................205
8.2. Operatorii &, * $i ->............................................206
Algoritmi $i limbaje algoritmice
8
8.3. Aritmetica pointerilor..........................................207
8.4. Leg'tura ntre tablouri $i pointeri .......................209
8.5. Gestiunea dinamic' a memoriei ........................209
8.6. Func#ii pentru opera#ii cu blocuri de memorie.... 212
8.7. Exemple ............................................................214
8.8. Exerci#ii..............................................................222
9. Func#ii pentru $iruri de caractere..............................225
9.1. *iruri de caractere.............................................225
9.2. Func#ii pentru $iruri de caractere.......................226
9.3. Func#ii pentru clasificarea caracterelor..............231
9.4. Exemple ............................................................233
9.5. Exerci#ii..............................................................248
10. Func#ii matematice.................................................251
10.1. Exemple ..........................................................255
10.2. Exerci#ii............................................................267
11. Func#ii pentru gestiunea fi$ierelor ..........................269
11.1. Structura FILE.................................................269
11.2. Fi$iere standard de intrare/ie$ire.....................270
11.3. Deschiderea $i nchiderea fi$ierelor ................270
11.4. Func#ii pentru caractere...................................271
11.5. Func#ii pentru $iruri de caractere.....................273
11.6. Func#ii cu formatare.........................................274
11.7. Func#ii pentru blocuri de date ..........................275
11.8. Func#ii pentru acces aleator n fi$iere..............277
11.9. Alte func#ii pentru fi$iere $i directoare..............278
11.10. Exemple ........................................................279
11.11. Exerci#ii..........................................................293
12. Metode de programare ..........................................295
12.1. Metoda Divide et Impera............................... 295
12.2. Exemple ..........................................................296
12.3. Metoda Backtracking.......................................301
12.4. Backtracking nerecursiv .................................. 306
12.5. Exemple ..........................................................308
12.6. Backtracking recursiv ......................................320
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
9
12.7. Exemple ..........................................................323
12.8. Metoda Greedy................................................336
12.9. Exemple ..........................................................340
12.10. Metoda program'rii dinamice........................350
12.11. Exemple ........................................................352
13. ntreb'ri de autoevaluare.......................................365
13.1. Unit'#i lexicale.................................................365
13.2. Expresii. Operanzi. Operatori ..........................366
13.3. Instruc#iuni .......................................................368
13.4. Func#ii standard de intrare/ie$ire .....................370
13.5. Tipuri de date compuse...................................371
13.6. Func#ii..............................................................372
13.7. Pointeri $i gestiunea dinamic' a memoriei ......374
13.8. Func#ii pentru $iruri de caractere.....................375
13.9. Func#ii matematice ..........................................377
13.10. Func#ii pentru gestiunea fi$ierelor..................378
14. Anexa 1 Mediul de programare Dev-C++ ...........381
14.1. Instalare ..........................................................382
14.2. Configurare......................................................384
14.2.1. Prima pornire............................................384
14.2.2. Editorul......................................................385
14.2.3. Tastele rapide...........................................386
14.2.4. Alte instrumente........................................387
14.3. Utilizare ...........................................................388
14.3.1. Scrierea unui program C...........................388
14.3.2. Compilarea codului surs' .........................389
14.3.3. Rularea programului .................................389
14.3.4. Depanarea................................................390
15. Anexa 2 Mediul de programare Raptor ...............393
16. Anexa 3 Setul de caractere ASCII ......................397
11
1
11.
.. A
AAL
LLG
GGO
OOR
RRI
II T
TTM
MMI
II !
!!I
II L
LLI
IIM
MMB
BBA
AAJ
JJE
EE A
AAL
LLG
GGO
OOR
RRI
II T
TTM
MMI
IIC
CCE
EE
1.1. De la problem la program
Rezolvarea unei probleme ncepe cu specificarea
acesteia $i se ncheie cu ob#inerea unui program concret
$i corect. Programele sunt scrise pentru a instrui ma$inile
s' lucreze cu sarcini specifice sau s' rezolve probleme
specifice. O procedur' (descris' pas cu pas) asociat'
unei sarcini se nume$te algoritm. Programarea este
activitatea de codificare a algoritmilor n calculatoare.
Procesul de programare are (n general) patru pa$i:
1. Specificarea problemei;
2. Proiectarea unui algoritm pentru rezolvarea sa;
3. Codificarea algoritmului ntr-un limbaj de programare;
4. Testarea programului.
1.1.1. Specificarea problemei
n prima faz', procesul de rezolvare const' n
analiza problemei care are drept scop elaborarea unui
enun# complet $i precis al problemei, #innd n acela$i
timp seam' de condi#iile de realizare $i execu#ie ale
problemei.
Algoritmi $i limbaje algoritmice
12
Din enun#ul problemei trebuie s' rezulte clar
func#iile programului. Pentru aceasta, trebuie s' se
delimiteze clar informa#iile de intrare (care trebuie
prelucrate de program) $i rezultatele a$teptate de la
program.
Pentru referirea la datele de intrare $i cele de
ie$ire se folose$te no#iunea de variabile de intrare,
respectiv variabile de ie$ire. Trebuie s' privim variabilele
ca nota#ii simbolice pentru valorile concrete pe care le
prelucreaz' algoritmul. Tot acum, n aceast' etap',
trebuie precizat' maniera de reprezentare $i organizare a
datelor de intrare $i de ie$ire. Rezultatul acestei etape
este specifica#ia (sau cerin#a) programului.
De exemplu, ne propunem s' scriem un program
care s' primeasc' de la tastatur' coeficien#ii reali a, b, c
ai unei ecua#ii de grad 2 $i s' calculeze solu#iile reale ale
acesteia, dac' exist'. Din enun#, ob#inem urm'toarele
informa#ii despre problema noastr':
Date de intrare: a, b, c numere reale
Date de ie$ire: x1, x2 numere reale
Func#ionalitate: dac' exist', atunci calculeaz'
r'd'cinile reale (x1 $i x2) ale ecua#iei de grad 2
(specific' prin a, b, c), altfel afi$eaz' mesajul
Ecua#ia nu are r'd'cini reale.
Organizarea $i reprezentarea datelor de intrare $i
de ie$ire: datele de intrare se citesc de la tastatur'
$i rezultatele se afi$eaz' pe monitor.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
13
1.1.2. Proiectarea algoritmului de rezolvare a
problemei
n aceast' etap', programatorul trebuie s'
specifice o list' de comenzi care s' descrie secven#a de
opera#ii executate de calculator pentru a rezolva
problema. n sens general, un program reprezint'
scrierea unui algoritm ntr-un limbaj de programare.
Aceast' etap' este evident cea mai dificil' etap'
din procesul de programare. n general, procesul de
scriere al unui algoritm este unul iterativ, descrierea
algoritmului realizndu-se la diferite nivele de detaliere.
Acest mod de specificare pas cu pas a rezolv'rii se mai
nume$te proiectare descendent'.
De asemenea, pentru problemele mai complicate
este posibil' descompunerea lor n subprobleme care s'
se rezolve separat mai u$or. Acest proces se nume$te
modularizare $i u$ureaz' modificarea programelor,
deschiznd calea c'tre programe mai u$or de reutilizat.
1.1.3. Codificarea algoritmului
Dup' elaborare, algoritmul trebuie codificat cu
ajutorul unui limbaj de programare astfel nct s' poat' fi
n#eles de c'tre calculator (altfel spus s' poat' fi tradus
mai departe ntr-un limbaj executabil pe calculator).
Codificarea algoritmului este facilitat' de utilizarea unor
simboluri $i reguli speciale cum sunt schemele logice sau
limbajul pseudocod.
Algoritmi $i limbaje algoritmice
14
1.1.4. Testarea $i validarea programului
Programul ob#inut prin implementarea
algoritmului trebuie verificat n scopul elimin'rii erorilor de
sintax', dar mai ales al elimin'rii erorilor de logic'. Este
posibil ca n urma execu#iei programului s' se ob#in'
rezultate incorecte, adic' sunt eliminate erorile de sintaxa
$i programul poate fi executat pe calculator, dar acesta
nu rezolv' corect problema de la care s-a plecat (datorit'
unei gre$eli de proiectare sau implementare a
algoritmului). De aceea, testarea programului trebuie s'
se fac' cu seturi de date de intrare care s' acopere ct
mai multe dintre cazurile posibile. Aceast' etap' poart'
numele de validarea programului.
Activitatea de scriere a unui program nu se
ncheie o dat' cu validarea acestuia, ci urmeaz' etap' de
ntre#inere. n aceast' etap' este posibil s' fie efectuate
modific'ri ale programului, datorate fie unor corecturi, fie
schimb'rii unor cerin#elor. De asemenea, o etap'
important' o constituie realizarea documenta#iei
programului explica#ii despre cum trebuie utilizat
programul (e.g. Help) care s' permit' att modific'ri
ulterioare ale acestuia, dar $i utilizarea programului de
c'tre alte persoane dect cele care l-au creat.
1.2. No#iunea de algoritm
No#iunea de algoritm ocup' un loc central n
informatic'. Calculul algoritmic for#eaz' precizia gndirii,
algoritmizarea unei metode matematice presupune
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
15
detalierea tuturor etapelor ei, urm'rirea pas cu pas a
fiec'reia dintre aceste etape, deci o n#elegere profund' a
ntregii metode.
Ca $i alte no#iuni matematice, no#iunea de
algoritm se caracterizeaz' printr-o mare generalitate.
n#elesul mai larg al no#iunii de algoritm este acela de
procedeu, metod', re#et'. Astfel, prin algoritm se n#elege
o mul#ime ordonat' $i finit' de reguli care descriu o
succesiune finit' de opera#ii necesare rezolv'rii unei
probleme, care pornind de la date (intr'ri) produce
rezultate (ie$iri).
Fiecare propozi#ie din descrierea unui algoritm
este de fapt o comand' care trebuie executat' de
calculator. Comanda specific' o ac#iune care se aplic'
unor date determinnd modificarea acestora.
Principalele propriet'#i pe care ar trebui s' le
posede un algoritm sunt urm'toarele:
s' fie bine definit adic' opera#iile cerute s' fie
specificate riguros $i f'r' ambiguitate, astfel nct
s' poat' fi executat pe o ma$in' programabil';
s' fie efectiv adic' s' se termine ntotdeauna
dup' un num'r finit de opera#ii;
s' fie universal adic' s' permit' rezolvarea unei
clase de probleme (nu o instan#' a unei
probleme).
Un algoritm trebuie s' fie determinist, adic'
executat de mai multe ori pentru acela$i set de date de
intrare, s' produc' acelea$i rezultate.
Algoritmi $i limbaje algoritmice
16
1.3. Reprezentarea algoritmilor
Odat' cu elaborarea unui algoritm, acesta trebuie
prezentat ntr-o form' ct mai precis' $i mai clar', pentru
a putea fi transpus, n continuare, sub forma unui
program n#eles de calculator. Pentru reprezentarea
algoritmilor se folosesc diverse forme de descriere
caracteristice (denumite limbaje algoritmice), deoarece
limbajul natural nu permite o descriere suficient de
riguroas' a algoritmilor. n plus, pe m'sur' ce
complexitatea problemelor cre$te, cre$te $i complexitatea
descrierii acestora n limbaj natural.
n general, nota#ia folosit' pentru reprezentarea
algoritmilor trebuie s' satisfac' urm'toarele cerin#e:
s' fie u$or de nv'#at $i de folosit;
s' permit' exprimarea ct mai natural' a
ra#ionamentelor umane;
s' reflecte caracteristicile limbajelor de programare
pentru a u$ura codificarea algoritmilor.
Avnd n vedere scopurile propuse, se dovedesc
potrivite dou' forme de reprezentare a algoritmilor:
scheme logice $i limbajul pseudocod.
1.3.1. Scheme logice
O schem' logic' poate fi interpretat' ca o
reprezentare grafic' a algoritmului, format' din blocuri $i
s'ge#i. Blocurile marcheaz' opera#ii care trebuie
efectuate, iar s'ge#ile indic' ordinea acestora. n scheme
logice se folosesc urm'toarele tipuri de blocuri:
bloc de stare marcheaz' o etap' n timpul
execu#iei algoritmului a c'rui nume este specificat
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
17
ntr-o elips'. Dou' st'ri speciale sunt Start care
marcheaz' nceputul algoritmului, $i End (sau
Stop) care marcheaz' sfr$itul algoritmului.

End
Start

bloc de intrare: marcheaz' opera#ia de citire a
datelor de intrare. Lista de variabile a c'ror valori
trebuie citite este scris' ntr-un trapez cu baza
mare n sus sau ntr-un paralelogram n#epat n
partea stng' de o s'geat'. Pentru a reduce
complexitatea schemei, blocul de intrare poate s'
includ' un mesaj ce va fi afi$at utilizatorului:
lista de variabile


"Introducei lungimea"
GET lung

bloc de ie$ire marcheaz' opera#ia de generare a
rezultatelor. Lista de variabile sau mesajele ce
trebuie afi$ate fiind scrise ntr-un trapez cu baza
mare n jos sau ntr-un paralelogram din care
porne$te o s'geat' c'tre dreapta. Uneori, semnul
paragraf () se folose$te pentru a anun#a explicit
c' mesajele care vor urma dup' acest bloc de
ie$ire trebuie s' nceap' de pe o linie nou'.
lista de variabile


PUT "Acesta este un

bloc de ie!ire"

Algoritmi $i limbaje algoritmice
18
bloc de calcul marcheaz' opera#ia de prelucrare a
informa#iilor prin intermediul variabilelor n care
sunt stocate. Acesta permite efectuarea unor
calcule $i prelucr'ri de date, $i memorarea
rezultatului ob#inut ntr-o variabil' pentru a fi folosit
ulterior.

variabil$ ' expresie

bloc de decizie sau selec#ie marcheaz' alegerea
unei c'i de execu#ie n func#ie de context: se
verific' o condi#ie; n cazul n care condi#ia este
adev'rat', se urmeaz' ramura marcat' cu Da
(sau Yes), iar n caz contrar se urmeaz' ramura
marcata cu Nu (sau No). ntr-un final, cele dou'
ramuri de execu#ie vor ajunge ntr-un punct comun,
dar n timpul rul'rii, numai una dintre ele se
execut'.

condiie
No Yes

blocul de repetare marcheaz' o zon' de cod care
este rulat' de 0, 1 sau mai multe ori pn' cnd o
condi#ie logic' devine adev'rat'. Unii autori nu
consider' acest bloc ca fiind bloc fundamental al
schemelor logice deoarece el poate fi simulat
folosind celelalte blocuri definite anterior. Din acest
motiv, simbolul folosit pentru acesta nu este la fel
de bine definit ca n celelalte cazuri. n aceast'
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
19
carte vom folosi urm'torul simbol pentru a
reprezenta blocuri de repetare:

condiie
Yes
No
Loop

1.3.2. Limbajul pseudocod
Limbajul pseudocod permite specificarea
algoritmilor cu ajutorul a dou' tipuri de enun#uri: standard
$i nestandard. Enun#urile standard exprim' opera#ii cu
corespondent direct n limbajele de programare.
Enun#urile nestandard sunt fraze n limbaj natural care
pot fi utilizate de programator n schi#area formelor ini#iale
ale algoritmilor. n general, dezvoltarea unui algoritm se
realizeaz' iterativ, trecndu-l prin mai multe nivele de
detaliu, enun#urile nestandard fiind nlocuite treptat cu
enun#uri standard. De exemplu, pentru precizarea datelor
ini#iale se scrie: Cite$te a,b,c, iar pentru precizarea
rezultatelor: Scrie x1, x2 sau Scrie Ecua#ia nu are solu#ii
reale.
Algoritmi $i limbaje algoritmice
20
Att enun#urile standard, ct $i ce nestandard pot
fi ata$ate unor structuri de control. Cele mai utilizate
structuri de control sunt:
secven#a reprezint' o succesiune de comenzi
pentru prelucrarea datelor. De exemplu:
cite#te a, b
x = b + a
scrie x
decizia alegerea unei opera#ii sau a unei
secven#e dintre dou' alternative posibile:
dac% test atunci
secvena A
altfel
secvena B
sfr#it
n limbaj natural, execu#ia poate fi descris' astfel:
se evalueaz' condi#ia test; dac' rezultatul este valoarea
logic' adev'rat, atunci se execut' secven#a A, altfel
(daca rezultatul este fals), se execut' secven#a B.
Exprimat' cu o schem' logic', decizia arat' astfel:

test
secventa A secventa B
No
Yes

De asemenea, exist' $i decizia cu o cale vid',
exprimat' n pseudocod astfel (l's'm exprimarea n
schem' logic' ca exerci#iu pentru cititor):
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
21
dac% test atunci
secvena A
sfr#it

test
secventa A
No Yes

ciclul (sau itera#ia) cu test ini#ial asigur'
executarea unei secven#e n mod repetat, n
func#ie de o anumit' condi#ie testat' apriori.
ct timp test repet%
secvena
sfr#it
Exprimat cu o schem' logic', ciclul cu test ini#ial
arat' astfel:

test
secventa A
No
Yes
Loop
! test
secventa A
Yes
No
Loop

Algoritmi $i limbaje algoritmice
22
Execu#ia parcurge urm'toarele etape: se
evalueaz' expresia test; dac' rezultatul este adev'rat,
se execut' secven#a $i se repet' secven#a de ciclare,
altfel se termin' secven#a de ciclare $i se trece la
urm'toarea secven#'.
i Dac' valoarea testului e fals' de la nceput, ciclul
nu se execut' niciodat'.
i De remarcat c' n schema logic' din partea dreapt'
a figurii anterioare am folosit expresia !test care
reprezint' negarea valorii de adev'r a expresiei
test. Acest lucru este necesar pentru a exprima
dou' ac#iuni identice: n limbaj pseudocod, bucla se
execut' ct timp condi#ia este adev'rat'; n schema
logic', bucla se execut' pn' cnd condi#ia devine
fals'.
ciclul (sau itera#ia) cu test final asigur'
executarea unei secven#e n mod repetat, n
func#ie de o anumit' condi#ie testat' aposteriori.
repet%
secvena
ct timp test
Execu#ia parcurge urm'toarele etape: se execut'
secven#a, se evalueaz' expresia test; dac' rezultatul
este adev'rat, se repet' secven#a de ciclare, altfel se
termin' secven#a de ciclare $i se trece la urm'toarea
secven#'. Exprimat cu o schem' logic', ciclul cu test final
arat' astfel:
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
23

secventa A
! test
Yes
No
Loop
secventa A
test
No
Yes
Loop

i Ciclul se execut' m'car o dat', deoarece testarea
se realizeaz' la sfr$it.
Ciclul cu contor asigur' executarea unei
secven#e n mod repetat, pentru fiecare element al
unei mul#imi.
pentru contor=start la sfarsit pas pas repet%
secvena
sfr#it
Execu#ia parcurge urm'toarele etape: variabila
contor prime$te pe rnd valorile start, start+pas,
start+2*pas, , sfarsit, $i pentru fiecare din aceste
valori se execut' se secven#a specificat'. Ciclul cu contor
este un caz particular al ciclului cu test ini#ial (l's'm
cititorului ca exerci#iu exprimarea unui ciclu cu contor
folosind un ciclu cu test ini#ial $i structuri secven#iale).
Ciclul cu contor poate fi exprimat n schem' logic' a$a
cum se observ' n figura urm'toare.
Algoritmi $i limbaje algoritmice
24
i n mod similar cu exemple anterioare, partea din
dreapta a figurii are negat' expresia logic' (n
coresponden#' cu etichetele Yes/No ale ramurilor).
De aceast' dat' ns', n locul condi#iei
!(contor<=sfarsit) am folosit forma mai
tradi#ional' contor>sfarsit, ambele exprimnd
acela$i lucru.

contor ' start
contor>sfarsit
secventa

contor ' contor + 1
Yes
No
Loop
contor ' start
contor<=sfarsit
secventa

contor ' contor + 1
No
Yes
Loop

1.4. Exemple
1. Scrie#i un algoritm care s' primeasc' la intrare o
temperatur' n grade Celsius $i s' calculeze temperatura
corespunz'toare n grade Farenheit $i Kelvin.
Din enun#ul problemei extragem urm'toarele
cerin#e:
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
25
date de intrare: c num'r real
date de ie$ire: f, k numere reale
func#ionalitate: calculeaz' f = 32 + 9*c/5 $i k=c-
273,15.
Solu#ia, n pseudocod $i schem' logic' este
urm'toarea:
cite#te c
f = 32 + 9*5/c
k = c + 273,15
scrie f,k

2. Scrie#i un algoritm pentru rezolvarea ecua#iei
ax+b=0, unde a $i b sunt numere reale citite de la
tastatur'.
Algoritmi $i limbaje algoritmice
26
Din enun#ul problemei extragem urm'toarele
cerin#e:
date de intrare: a, b numere reale
date de ie$ire: x num'r real
func#ionalitate: dac' a=0 $i b=0, atunci afi$eaz'
mesajul Orice num'r real este solu#ie; dac' a=0
$i b0 atunci afi$eaz' mesajul Nu exist' solu#ii
reale; altfel afi$eaz' solu#ia ecua#iei de grad 1
(x=-b/a).
Solu#ia, n pseudocod $i schem' logic' este
urm'toarea:

cite#te a,b
dac% a=0 atunci
dac% b=0 atunci
scrie "Orice num%r real este soluie"
altfel
scrie "Nu exist% soluii reale"
sfr#it
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
27
altfel
x = -b/a
scrie x
sfr#it
3. Scrie#i un algoritm pentru rezolvarea ecua#iei
ax
2
+bx+c=0, unde a, b $i c sunt numere reale citite de la
tastatur'.
Din enun#ul problemei extragem urm'toarele
cerin#e:
date de intrare: a, b, c numere reale
date de ie$ire: x1, x2 numere reale
func#ionalitate: dac' a=0, atunci (pentru simplitate)
afi$eaz' mesajul "Ecua#ia nu este de gradul 2",
altfel calculeaz' d=b
2
-4ac; dac' d<0, atunci
afi$eaz' mesajul "Ecua#ia are solu#ii complexe",
altfel afi$eaz' solu#iile ecua#iei de grad 2 (x1=(-b-
sqrt(d))/(2a) $i x2=(-b+sqrt(d))/(2a), unde sqrt
reprezint' func#ia radical).
Solu#ia, n pseudocod $i schem' logic' este
urm'toarea:
cite#te a,b,c
dac% a=0 atunci
scrie "Ecuaia nu este de gradul 2"
altfel
d = b*b-4*a*c
dac% d<0 atunci
scrie "Ecuaia are soluii complexe"
altfel
x1=(-b-sqrt(d))/(2a)
x2=(-b+sqrt(d))/(2a)
scrie x1, x2
sfr#it
sfr#it
i n scheme logice $i pseudocod putem exprima
expresia matematic' x
y
prin expresia x**y sau x^y.
Algoritmi $i limbaje algoritmice
28
Astfel, valoarea variabilei d (delta) putea fi calculat'
$i cu expresiile b^24*a*c sau b**24*a*c.

4. Scrie#i un algoritm care determin' cel mai mare
divizor comun a dou' numere naturale.
Din enun#ul problemei extragem urm'toarele
cerin#e:
date de intrare: a, b numere naturale
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
29
date de ie$ire: c num'r natural
func#ionalitate: vom calcula cel mai mare divizor
comun folosind algoritmul lui Euclid. Pentru
aceasta, mai nti se determin' restul mp'r#irii lui
a la b (notat cu r=a%b); dac' restul este nenul,
variabile a $i b se modific' (devenind a=b $i b=r) $i
se repet' opera#ia anterioar'.
O solu#ie n pseudocod este urm'toarea.
cite#te a
cite#te b
repet%
r = a % b
a = b
b = r
ct timp r0
scrie b
O metod' alternativ' pentru determinarea celui
mai mare divizor comun (metoda original' propus' de
Euclid) const' n sc'deri repetate a variabilei cu valoarea
mai mic' din variabila cu valoarea mai mare, pn' cnd
valorile celor dou' variabile devin egale. Solu#ia n
pseudocod n acest caz este urm'toarea:
cite#te a
cite#te b
ct timp ab repet%
dac% a>b atunci
a = a b
altfel
b = b a
sfr#it
sfr#it
scrie b
Solu#iile n pseudocod sunt prezentate pentru
ambii algoritmi n figura urm'toarea.
Algoritmi $i limbaje algoritmice
30

A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
31

Algoritmi $i limbaje algoritmice
32
5. Scrie#i un algoritm care determin' dac' un num'r
este prim sau nu.
Din enun#ul problemei extragem urm'toarele
cerin#e:
date de intrare: a num'r natural
date de ie$ire: mesajul "prim" sau "compus"
func#ionalitate: Fie d num'rul de divizori ai lui a
(adic' numere naturale din intervalul [2, a/2] pentru
la care a se mparte f'r' rest). Dac' d este 0,
atunci num'rul este prim, altfel este compus.
Solu#ia, n pseudocod $i schem' logic' este
urm'toarea:
cite#te a
d = 0
pentru i=2 la a/2 pas 1 repet%
dac% a % i = 0 atunci
d = d + 1
sfr#it
sfr#it
dac% d = 0 atunci
scrie "prim"
altfel
scrie "compus"
sfr#it
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
33
Algoritmi $i limbaje algoritmice
34
6. Fie n un num'r natural $i a
1
,,a
n
, respectiv,
b
1
,,b
n
, doi vectori de n numere reale. Scrie#i un algoritm
care determin' produsul scalar al vectorilor a $i b.
Din enun#ul problemei extragem urm'toarele
cerin#e:
date de intrare: nnum'r natural, a
1
,,b
1
,
numere reale
date de ie$ire: p num'r real
func#ionalitate: determin' valoarea produsului
scalar p=<a,b>= a1* b1+a2*b2++ an*bn.
Solu#ia, n pseudocod $i schem' logic' este
urm'toarea:
cite#te n
pentru i = 1 la n repet%
cite#te a[i], b[i]
sfr#it
p = 0
pentru i = 1 la n repet%
p = p + a[i]*b[i]
sfr#it
scrie p
Valoarea produsului scalar putea fi calculat' n
acela$i timp cu citirea elementelor vectorului,
pseudocodul fiind:
cite#te n
p = 0
pentru i = 1 la n repet%
cite#te a[i], b[i]
p = p + a[i]*b[i]
sfr#it
scrie p
Schemele logice sunt prezentate n figurile
urm'toare.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
35
Algoritmi $i limbaje algoritmice
36
1.5. Exerci#ii
1. Scrie#i un algoritm care determin' perimetrul $i aria
unui dreptunghi cunoscnd lungimile laturilor.
2. Scrie#i un algoritm care determin' consumul de
combustibil la o sut' de kilometri al unui vehicul $tiind
consumul total pe parcursul unei anumite distan#e.
3. Scrie#i un algoritm care determin' maximul a trei
numere reale citite de la tastatur'.
4. Scrie#i un algoritm care, cunoscnd trei valori
naturale, determin' dac' acestea pot reprezenta laturile
unui triunghi. n caz afirmativ, s' se afi$eze dac'
triunghiul este oarecare, isoscel sau echilateral.
5. Scrie#i un algoritm pentru rezolvarea sistemului:
a*x + b*y = c
d*x + e*y = f
unde a, b, c, d, e, f sunt numere reale date.
6. Scrie#i un algoritm care determin' divizorii unui
num'r natural nenul.
7. Scrie#i un algoritm care determin' factorialul unui
num'r natural.
8. Scrie#i un algoritm care transform' un num'r din
baza 10 n baza 2.
9. Scrie#i un algoritm care transform' un num'r din
baza 2 n baza 10.
10. Fie n un num'r natural $i a
1
,,a
n
numere reale.
Scrie#i un algoritm care determin' media aritmetic' a
numerelor a
1
,, a
n
.
11. Fie n un num'r natural $i a1,,an numere reale.
Scrie#i un algoritm care determin' suma valorilor pozitive
din mul#imea a1,,an.
12. Fie n un num'r natural $i a
1
,,a
n
numere reale.
Scrie#i un algoritm care determin' valoarea minim' din
mul#imea a
1
,,a
n
.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
37
13. Fie n un num'r natural $i m, a
1
,,a
n
numere reale.
Scrie#i un algoritm care afi$eaz' toate valorile i pentru
care a
i
=m.
14. Fie n un num'r natural $i a
1
,, a
n
numere reale.
Scrie#i un algoritm care ordoneaz' cresc'tor numerele
a
1
,, a
n
.
39
2
22.
.. U
UUN
NNI
IIT
TT&
&&)
))I
II L
LLE
EEX
XXI
IIC
CCA
AAL
LLE
EE
Unit'#ile lexicale sunt atomii unui program C, a$a
cum un roman este format din fraze, iar acestea din
cuvinte. Scopul acestui capitol este s' v' prezinte aceste
no#iuni fundamentale. Orice program C este alc'tuit din
cel pu#in o func#ie (func#ia main). Orice func#ie con#ine
zero, una sau mai multe expresii. O expresie este
construit' din operanzi conecta#i prin operatori conform
anumitor reguli sintactice. n plus, textul programelor
poate con#ine comentarii care s' ajute la n#elegerea
acestuia.
2.1. Mul#imea caracterelor
Unit'#ile lexicale ale unui program C sunt
alc'tuite din caractere, fiecare caracter avnd un anume
n#eles pentru compilatorul C, folosirea incorect' a
acestora fiind semnalat' prin mesaje de eroare.
Mul#imea caracterelor ce pot fi folosite n
programe C este mp'r#it' n urm'toarele submul#imi:
caractere alfanumerice: literele mici $i mari din
alfabetul englez, $i cifrele;
Unit'#i lexicale
40
caractere speciale: caracterele prezentate n Tabel
2.1
caractere de spa#iere: caracterele prezentate n
Tabel 2.2
alte caractere: celelalte caractere tip'ribile din
setul de caractere ASCII (vezi Anexa 3 Setul de
caractere ASCII)
Tabel 2.1 Caractere speciale
Caracter Denumire Caracter Denumire
, virgul' . punct
: dou' puncte ; punct $i
virgul'
? semnul ntreb'rii ! semnul
exclam'rii
' apostrof " ghilimele
( parantez' rotund'
stnga
) parantez'
rotund'
dreapta
[ parantez' dreapt'
stnga
] parantez'
dreapt'
dreapta
{ acolad' stnga } acolad'
dreapta
< mai mic > mai mare
^ s'geat' sus = egal
+ plus - minus
* asterisc / slash
% procent \ backslash
| bar' vertical' ~ tild'
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
41
_ underscore # diez
& ampersand
Tabel 2.2 Caractere de spaiere
Cod
ASCII
Denumire Semnificaie
32 spa#iu un spa#iu
9 tab grup de spa#ii (tabulator
orizontal)
10 line feed trecere la linia urm'toare (new
line)
13 carriage
return
revenire la nceputul liniei
curente (folosit n special la
imprimante)
11 tab vertical tabulator vertical (folosit n
special la imprimante)
12 form feed trecere la pagina urm'toare
(folosit n special la imprimante)
2.2. Comentarii
Un comentariu este o por#iune de text care este
ignorat' de c'tre compilatorul C. Un comentariu pe o
singur' linie ncepe dup' o secven#' slash-slash // $i se
termin' la sfr$itul liniei curente. Un comentariu pe una
sau mai multe linii ncepe dup' o secven#' slash-star /*
$i se termin' la prima secven#' star-slash */. Pentru a
u$ura n#elegerea programelor se recomand' folosirea
comentariilor ct mai detaliate.
Unit'#i lexicale
42
De exemplu, o secven#' de program care
calculeaz' suma a dou' numere poate fi comentat'
astfel:
suma = a + b; // calculam suma lui a si b
sau
suma = a + b; /* calculam suma lui a si b */
i Comentariile nu pot fi imbricate (i.e. nu putem
introduce un comentariu n alt comentariu) $i nu pot
fi scrise n interiorul constantelor caracter sau $ir de
caractere.
2.3. Tipuri de date primare
Un tip de date este o informa#ie asociat' unei
expresii pe baza c'reia compilatorul limbajului C
determin' n ce context poate fi folosit' expresia
respectiv'. De exemplu, cu un num'r ntreg se pot
efectua opera#ii aritmetice. Orice expresie valid' n
limbajul C are asociat un tip de date. Limbajul C define$te
patru tipuri de date fundamentale: caracter (char), ntreg
(int), flotant (sau real) simplu (float) $i flotant dublu
(double), unele dintre acestea avnd mai multe variante
(denumite subtipuri).
n func#ie de compilator, tipurile char $i int
reprezint' valori cu sau f'r' semn, dar programatorul
poate s' foloseasc' modificatorii signed $i unsigned
pentru a selecta un anume subtip. De asemenea, implicit
tipul int poate fi scurt sau lung, dar programatorul poate
s' foloseasc' modificatorii short $i long pentru a
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
43
selecta subtipul dorit. n anumite situa#ii (foarte rare), tipul
flotant dublu (double) este echivalent cu flotant simplu
(float). Caracteristicile tipurilor $i subtipurilor de baz'
sunt prezentate n tabelul urm'tor.
Tabel 2.3 Tipuri $i subtipuri fundamentale de
date
Tip/subtip M*rime
(octei)
Domeniu de valori
unsigned char 1 0255
signed char 1 -128127
char 1 depinde (cu sau f'r' semn)
short signed int 2 -3276832767
short unsigned
int
2 065535
short int 2 depinde (cu sau f'r' semn)
long signed int 4 -21474836482147483647
long unsigned
int
4 0 4294967296
long int 4 depinde (cu sau f'r' semn)
signed int 2 sau 4 depinde (cu semn)
unsigned int 2 sau 4 depinde (f'r' semn)
int 2 sau 4 depinde (cu sau f'r' semn)
float 4 -3,4010
38
...3,410
38

double 8 -1,7910
308
...1,7910
308

2.4. Constante
Constantele reprezint' cel mai simplu tip de
operanzi, mai exact o valoare care nu poate fi modificat'
Unit'#i lexicale
44
$i care are asociat un tip (stabilit n func#ie de modul de
scriere al valorii constantei).
2.4.1. Constante de tip caracter
O constant' de tip caracter se scrie n program
ntre apostrofi (e.g. C, 0, ., !). Tipul
constantelor caracter este ntotdeauna char. Pentru a
scrie constantele caracter apostrof, backslash (\) sau un
caracter care nu apare pe tastatur' se folosesc secven#e
escape. O secven#' escape este compus' din caracterul
backslash (\) urmat de un caracter normal sau un num'r
(n baza 8 sau 16). n acest context, semnifica#ia
caracterului sau a num'rului de dup' backslash devine
una special'. Cele mai utile secven#e escape sunt
prezentate n Tabel 2.4. De exemplu, dac' vrem s'
scriem constanta caracter apostrof, atunci vom scrie
\.
Tabel 2.4 Secvene escape valide n limbajul C
Secven*
escape
Semnificaie
\a alert produce un sunt n difuzorul
calculatorului
\n new line trecerea la rndul urm'tor
\r carriage return revenirea la cap'tul rndului
\t horizontal tab deplasarea pe orizontal' cu
un tab
\v vertical tab deplasarea pe vertical' cu un
tab (la imprimant')
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
45
\f form feed trecerea la pagina urm'toare (la
imprimant')
\b backspace deplasarea napoi a cursorului
cu un caracter
\\ backslash caracterul backslash
\ single quote caracterul apostrof
\ double quote caracterul ghilimele
\ooo octal caracterul cu codul ASCII ooo (unde
ooo este un num'r n baza 8, vezi Anexa 3
Setul de caractere ASCII)
\xhh hexazecimal caracterul cu codul ASCII hh
(unde hh este un num'r n baza 16, vezi
Anexa 3 Setul de caractere ASCII)
2.4.2. Constante de tip $ir de caractere
O constant' de tip $ir de caractere este un grup
de caractere $i secven#e escape scrise ntre ghilimele
(e.g. acesta este un sir). Daca o constant' de tip
$ir de caractere este prea lung', ea poate fi scris' pe mai
multe linii n program fie prin terminarea fiec'rui rnd (cu
excep#ia ultimului) cu caracterul backslash, fie prin
scrierea fiec'rui rnd ntre ghilimele. De exemplu,
urm'toarele trei $iruri sunt identice:
Acesta este un sir
Acesta este \
un sir
Acesta este
un sir
Tipul constantelor $ir de caractere este char[],
adic' un vector de caractere. La sfr$itul fiec'rui $ir de
Unit'#i lexicale
46
caractere compilatorul adaug' automat caracterul NUL
(caracterul cu codul ASCII 0), ca marcator pentru sfr$itul
$irului.
Pentru a include caractere ghilimele ntr-un $ir de
caractere se folose$te secven#a escape \. Func#iile
pentru opera#ii cu caractere $i $iruri de caractere vor fi
discutate n detaliu n capitolul 8.
2.4.3. Constante de tip ntreg
O constant' de tip ntreg este un num'r ntreg
scris n baza 8, 10 sau 16. Dac' num'rul este scris n
baza 8, atunci trebuie s' fie prefixat de cifra zero. Dac'
num'rul este scris n baza 16, atunci trebuie s' fie
prefixat de zero urmat de litera x.
Subtipul constantei este ales astfel nct domeniu
acestuia s' con#in' valoarea constantei. Programatorul
poate scrie sufixele u (de la unsigned) $i/sau l (de la
long) pentru a specifica un subtip anume (vezi sec#iunea
2.3). Dac' valoarea constantei nu poate fi memorat' ca
subtip long signed int sau long unsigned int,
atunci constanta se consider' constant' de tip flotant.
De exemplu, constanta de tip ntreg 12 poate fi
scris': 014 (n baza 8), 12 (n baza 10) sau 0xC (n baza
16). Dac' scriem 12l, constanta are tot valoarea 12, dar
tipul este ntreg lung, iar dac' scriem 12ul, tipul ei este
ntreg lung f'r' semn.
i n limbajul C, codificarea valorilor de tip ntreg cu
semn se face folosind codul complementar fa#' de
2. n acest caz, bitul cel mai din stnga al num'rului
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
47
codific' semnul, iar restul bi#ilor valoarea. Bitul de
semn este 0 pentru numere pozitive $i 1 pentru
numere negative. n plus, valoarea n baza 10 a
numerelor negative se calculeaz' negnd bi#i de
valoare $i adunnd 1 la rezultat.
2.4.4. Constante de tip flotant
O constant' de tip flotant este un num'r real scris
n baza 10, cu sau f'r' zecimale, cu sau f'r' exponent.
Exponentul este alc'tuit din litera e urmat' de un num'r
ntreg n, cu semnifica#ia c' valoarea constantei este
num'rul dinaintea exponentului nmul#it cu 10
n
. Separator
pentru zecimale este punctul. Dac' num'rul nu are
zecimale sau exponent, atunci trebuie urmat de un punct
pentru a fi considerat real.
Tipul implicit al constantei este tipul double, dar
dac' aceasta este urmat' de litera f (de la float), tipul
implicit va fi float (vezi sec#iunea 2.3).
De exemplu, constanta cu valoarea -12,5 $i tip
double se poate scrie: -12.5 sau -1.25e1. Dac' scriem
-12.5f, atunci tipul este float.
2.5. Cuvinte cheie
Un cuvnt cheie este o secven#' caractere
alfanumerice, care are o semantic' predefinit' n limbajul
C. Cuvintele cheie ale limbajului C (standardul ANSI)
sunt: auto, break, case, char, const, continue,
default, do, double, else, enum, extern, float, for,
goto, if, int, long, register, return, short, signed,
Unit'#i lexicale
48
sizeof, static, struct, switch, typedef, union,
unsigned, void, volatile $i while.
2.6. Identificatori
Un identificator este un nume pe care
programatorul l d' unei entit'#i (aceasta poate fi o
variabil' vezi sec#iunea urm'toare, func#ie vezi
capitolul 7, sau tip de date vezi capitolul 6) pentru a
putea lucra mai u$or cu aceasta. Un identificator este o
secven#' de caractere alfanumerice $i underscore (_),
care ncepe cu o liter' sau underscore. Identificatorii
trebuie s' fie diferi#i de cuvintele cheie. De exemplu,
identificatorii varsta, greutate, total1980, _secret
sunt identificatori corec#i, dar 1980total, 1_secret nu
sunt.
2.6.1. Variabile
O variabil' este un identificator care are asociat
un tip, o adres' de memorie $i o valoare (i.e. informa#ia
din memorie de la adresa asociat' variabilei). nainte de a
fi folosit' n program, orice variabil' trebuie declarat',
adic' se specific' numele $i tipul variabilei. Tipul
variabilei determin' ce opera#ii se pot efectua cu valoarea
variabilei. Adresa de memorie unde va fi stocat' valoarea
variabilei se stabile$te automat. Valoarea variabilei poate
fi specificat' n faza de declarare (opera#ie denumit'
ini#ializare) sau ulterior (opera#ie denumit' atribuire).
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
49
De exemplu, pentru a defini o variabil' de tip
flotant dublu cu numele PI $i valoarea 3,1415926, $i
dou' variabile de tip ntreg f'r' semn cu numele varsta
$i greutate, din care varsta este ini#ializat' cu valoarea
26 vom scrie:
double PI = 3.1415926;
unsigned int varsta = 26, greutate;
2.6.2. Masive
Masivele (sau tablourile de date) sunt blocuri de
variabile de acela$i tip, grupate n memorie, accesibile
printr-un nume comun $i coordonatele lor n interiorul
grupului. Declararea unui masiv $i accesarea elementelor
acestuia se realizeaz' cu ajutorul caracterelor paranteze
p'trate (denumite n acest context operator de indexare).
Indexarea masivelor se face n limbajul C, pornind de la
0. Masivele $i propriet'#ile acestora sunt prezentate n
capitolul 6. Deocamdat' vom prezenta doar cteva
exemple:
float v[10]; // v este un masiv de 10 valori
reale
char c[65]; // c este un masiv de 65
caractere
int mat[5][5]; // mat este un masiv de 5x5
valori intregi
v[3]=0; // al 4-a valoare din v devine 0
i n limbajul C, o variabil' de tip $ir de caractere cu
maxim n caractere se declar' ca un vector de tip
char cu dimensiune n+1. *irurile de caractere sunt
discutate n capitolul 9.
Unit'#i lexicale
50
2.7. Exemple
7. Programul urm'tor exemplific' no#iunile discutate n
acest capitol. Instruc#iunea de preprocesare din prima
linie cere folosirea bibliotecii de func#ii stdio.h, care
con#ine func#ii standard de intrare/ie$ire (vezi capitolul 4)
precum printf. Urmeaz' defini#ia func#iei main, punctul
de pornire al oric'rui program C. n corpul func#iei main
(ntre cele dou' acolade), se declar' variabilele PI, raza
$i aria, prima fiind $i ini#ializat'. Func#ia printf afi$eaz'
pe ecran mesajul "Introduce#i raza", iar valoarea
introdus' de utilizator este memorat' n variabila raza cu
ajutorul func#iei scanf. Instruc#iunea urm'toare
calculeaz' aria unui cerc $i atribuie rezultatul variabilei
aria. n final, func#ia printf afi$eaz' rezultatul
calculelor. Codurile %g din mesajul func#iei vor fi nlocuite
cu valorile corespunz'toare parametrilor raza $i aria.
Instruc#iunea return din final este op#ional', dar scrierea
ei este o practic' bun', valoarea 0 simboliznd
terminarea f'r' erori a programului.
#include <stdio.h>
#include <conio.h>
int main()
{
float PI = 3.1415926, raza, aria;
printf("Introduceti raza:");
scanf("%f", &raza);
aria = PI * raza * raza;
printf("Aria unui cerc cu raza %g este
%g.\n", raza, aria);
getch();
return 0;
}
i Cnd este pornit din interfa#a grafic' din Windows,
fereastra programului dispare de pe ecran dup'
rulare. Pentru a suspenda execu#ia programului
pn' cnd utilizatorul apas' o tast' am folosit
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
51
instruc#iunea getch() din biblioteca conio.h
conform indica#iilor din sec#iunea 14.3.1.
i Pentru a compila $i rula acest program, consulta#i
Anexa 1 Mediul de programare Dev-C++.
Rezultatul rul'rii programului este urm'torul:
Introduceti raza:3.1
Aria unui cerc cu raza 3.1 este 30.1907.
8. Programul urm'tor afi$eaz' suma a dou' numere
ntregi.
#include <stdio.h>
#include <conio.h>
int main()
{
int a, b;
printf("Introduceti a si b");
scanf("%i %i", &a, &b);
printf("%i + %i = %i", a, b, a+b);
getch();
}
2.8. Exerci#ii
15. Determina#i tipul unit'#ilor lexicale din exemplele
anterioare.
16. Care dintre urm'toarele secven#e sunt constante de
tip caracter: 'a', a, "a", \a $i 'aa'?
17. Care dintre urm'toarele secven#e sunt constante de
tip $ir de caractere: 'a', a, "a", "a"a", "a\"a", "a\\"a" $i "aa"?
18. Care dintre urm'toarele secven#e sunt constante de
tip ntreg: a, 0xa, 0a, 10, 10.1, 10ul $i 10.?
19. Care dintre urm'toarele secven#e sunt constante de
tip flotant (simplu sau dublu): 10, 10.1, 10ul, 10.f $i 10.?
20. Care dintre urm'toarele secven#e pot fi folosite ca
identificator: test, test10, _test10, test_10, 10test, _10test
$i _10?
Unit'#i lexicale
52
21. Determina#i tipul, numele $i valoarea urm'toarelor
variabile:
int test=10, real=010, fictiv=0x10;
float greutate=1.3e2, densitate=3.2;
char cod='a', adresa[30]="Constanta";
22. Modifica#i exemplul 7 astfel nct s' calculeze
volumul unui cilindru.
23. Scrie#i un program C care afi$eaz' pe ecran
urm'torul desen folosind func#ia printf:
,-. _.---._
| `\.__.-'' ".
\ _ _ ,. \
,+++=.________________)_||______|_|_|| |
(_.ooo.==================||======|=|=|| |
~~' | ~' "~' o o /
\ /~'\ o o /
`~' `-.____.-'
24. Scrie#i un program C care afi$eaz' pe ecran
urm'torul desen folosind func#ia printf:
. | .
* | . . .
. /-\ :
|"""| . * |>~
/"""""\ . /\| _
__ ___|# # # #| ___ ___/<>\ |:
_|~~| |'''|# # # #||"""| __|"""|^^| |:
:|''|~~~~,|# # # #||"""|-|::|"""|''|_|
:|''|""""||# # # #||"""|t|::|"""|''|"""
|''|""""||# # # #||"""|||::|"""|''""""
53
3
33.
.. E
EEX
XXP
PPR
RRE
EES
SSI
III
II.
.. O
OOP
PPE
EER
RRA
AAN
NNZ
ZZI
II.
.. O
OOP
PPE
EER
RRA
AAT
TTO
OOR
RRI
II.
..
3.1. Expresii
O expresie este o secven#' de operanzi $i
operatori. Un operand poate fi o constant', o variabil'
sau o alt' expresie. O expresie este caracterizat' de o
valoare $i un tip. Valoarea $i tipul expresiei sunt
determinate de operatorii $i operanzii care formeaz'
expresia.
Regulile de asociativitate $i preceden#' a
operatorilor sunt n general acelea$i ca cele din
matematic' cu unele excep#ii, dar o expresie poate
con#ine paranteze rotunde pentru schimbarea priorit'#ii de
evaluare subexpresiilor sale. De exemplu, fie expresia:
a = (a*b-c/d)*(a-b);
n aceast' expresie a este primul operand al
operatorului de atribuire =, iar (a*b-c/d)*(a-b) este al
doilea operand. Al doilea operand (a*b-c/d)*(a-b),
este o expresie n care expresia (a*b-c/d) este primul
operand al operatorului de nmul#ire *, iar expresia (a-b)
este al doilea operand. Similar, expresia a*b este primul
Expresii. Operanzi. Operatori.
54
operand al operatorului de sc'dere -, iar expresia c/d
este al doilea operand, $.a.m.d.
Dac' variabilele a, b, c, d au valorile respectiv 2,
3, 6, 3, atunci expresia (a*b-c/d)*(a-b) are valoarea -
4. Astfel variabilei a i se atribuie valoarea -4. n plus, n
limbajul C, valoare unei expresii de atribuire este
valoarea variabilei destina#ie dup' atribuire, deci valoarea
ntregii expresii va fi -4.
Valoarea logic' de adev'r a expresiei a=(a*b-
c/d)*(a-b) este adev'rat, deoarece expresia are
valoare nenul'.
i n limbajul C, o expresie are valoarea logic' de
adev'r adev'rat dac' are valoare nenul' $i are
valoarea logic' de adev'r fals dac' are valoare
nul'.
3.2. Operanzi
Un operand poate fi: o constant', o constant'
simbolic', un identificator de variabil' simpl', un
identificator de tablou, un element de tablou, un
identificator de structur', un membru al unei structuri,
numele unei func#ii, un apel de func#ie sau o expresie.
3.3. Conversii implicite de tip
n unele situa#ii, n timpul evalu'rii unei expresii,
tipul unei subexpresii poate s' fie schimbat automat n alt
tip cu domeniul de valori mai mari. Aceast' opera#ie se
nume$te conversie implicit' de tip $i realizeaz' astfel:
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
55
orice operand de tipul char se converte$te la tipul
int;
orice operand de tipul short se converte$te la tipul
int.
n plus, unii operatori prelucreaz' informa#iile
stocate n doi operanzi. Dac' operanzii au acela$i tip,
atunci rezultatul operatorului are acela$i tip cu al
operanzilor. Altfel, unul dintre operanzi se converte$te la
tipul celuilalt, conform urm'toarelor reguli:
dac' un operand este de tipul double atunci $i
cel'lalt operand se converte$te la tipul double;
dac' un operand este de tipul float atunci $i
cel'lalt operand se converte$te la tipul float;
dac' un operand este de tipul unsigned long
atunci $i cel'lalt operand se converte$te la tipul
unsigned long;
dac' un operand este de tipul long atunci $i
cel'lalt operand se converte$te la tipul long.
3.4. Operatori
Limbajul C dispune de un set puternic de
operatori. Operatorii se pot clasifica dup' aritate, dup'
asociere sau dup' prioritatea la evaluare ntr-o expresie.
Din punct de vedere al arit'#ii (adic' num'rul de
operanzi), operatorii sunt unari, binari $i ternari. Operatorii
unari se scriu n general naintea operandului lor (de
exemplu: -5, !a, ~x, etc.). Excep#ie de la aceast' regul'
fac operatorii de incrementare $i decrementare postfixa#i
$i operatorul sizeof, a c'ror sintax' este x++, x-- $i
sizeof(expresie). Operatorii binari se scriu ntre
Expresii. Operanzi. Operatori.
56
operanzii lor (de exemplu: a+b, x<<3, etc.). Singurul
operator ternar al limbajului C este operatorul condi#ional.
Din punct de vedere al asociativit'#ii, operatorii
pot fi asociativi de la stnga la dreapta sau de la dreapta
la stnga. Cu excep#ia operatorilor de atribuire,
operatorului condi#ional $i operatorilor unari, restul
operatorilor au asociativitate de la stnga la dreapta.
n limbajul C, sunt definite 15 niveluri de
preceden#'; nivelul 1 este cel mai prioritar, iar nivelul 15
este cel mai pu#in prioritar. Operatorii afla#i pe un anumit
nivel de prioritate au aceea$i prioritate. Prezent'm n
ordine descresc'toare a preceden#ei to#i operatorii
limbajului C.
Tabel 3.1 Operatorii limbajului C
Ni-
vel
Categorie Opera-
tor
Aritate
(asociati-
vitate
1
)
Semnificaie
( ) Apel de
func#ie sau
schimbare
prioritate
[ ] 2 (SD) Operator de
indexare
. 2 (SD) Operator de
selec#ie
direct'
1 Operatori de
adresare
-> 2 (SD) Operator de

1
SD asociativitate de la stnga la dreapta, DS asociativitate de la
dreapta la stnga.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
57
selec#ie
indirect'
! 1 (DS) Negare logic'
~ 1 (DS) Negare la
nivel de bit
+ - 1 (DS) Operator de
semn
++ -- 1 (DS,
SD)
Incrementare,
decrementare
& 1 (DS) Operator
adres'
* 1 (DS) Operator de
adresare
indirect'
sizeof 1 (DS) Dimensiune n
octe#i a
operandului
2 Operatori
unari
(tip) 1 (DS) Conversie
explicit' de tip
(cast)
* 2 (SD) nmul#ire
/ 2 (SD) mp'r#ire
3 Operatori
multiplicativi
% 2 (SD) Modulo
+ 2 (SD) Adunare 4 Operatori
aditivi - 2 (SD) Sc'dere
<< 2 (SD) Deplasare la
stnga
5 Operatori de
deplasare
>> 2 (SD) Deplasare la
dreapta
Expresii. Operanzi. Operatori.
58
< 2 (SD) Mai mic
<= 2 (SD) Mai mic sau
egal
> 2 (SD) Mai mare
6 Operatori
rela#ionali
>= 2 (SD) Mai mare sau
egal
== 2 (SD) Egal 7 Operatori de
egalitate != 2 (SD) Diferit
8 & 2 (SD) *I pe bi#i
9 ^ 2 (SD) SAU exclusiv
pe bi#i
10
Operatori pe
bi#i
| 2 (SD) SAU pe bi#i
11 && 2 (SD) *I logic
12
Operatori
logici || 2 (SD) SAU logic
13 Operator
ternar
?: 3 (DS) Operatorul
condi#ional
= 2 (DS) Atribuire
simpl'
*= 2 (DS) nmul#ire $i
atribuire
/= 2 (DS) mp'r#ire $i
atribuire
%= 2 (DS) Modulo $i
atribuire
+= 2 (DS) Adunare $i
atribuire
-= 2 (DS) Sc'dere $i
atribuire
14 Operatori de
atribuire
&= 2 (DS) *I pe bi#i $i
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
59
atribuire
^= 2 (DS) SAU exclusiv
pe bi#i $i
atribuire
|= 2 (DS) SAU pe bi#i $i
atribuire
<<= 2 (DS) Deplasare la
stnga $i
atribuire
>>= 2 (DS) Deplasare la
dreapta $i
atribuire
15 Operator
secven#ial
, 2 (SD) Evaluare list'
expresii
3.4.1. Operatori de adresare
Operatorul de apelare ( ) este folosit ca
separator al listei de parametri a func#iilor sau ca
modificator de prioritate n evaluarea expresiilor.
Operatorul de indexare [ ] este folosit pentru accesarea
valorilor din tablouri de date $i va fi discutat n capitolul
dedicat tablourilor. Operatorii de selec#ie direct' . $i de
selec#ie indirect' -> se folosesc n gestiunea structurilor
$i uniunilor $i vor fi discuta#i n capitolul 6.
De exemplu, instruc#iunea
printf("Elementul 4 din vectorul v este %d",
v[3]);
Expresii. Operanzi. Operatori.
60
folose$te func#ia printf pentru a afi$a un mesaj. Parametrii
func#iei sunt scri$i n operatorul de apelare, unul dintre
ace$tia fiind al patrulea element din vectorul v.
3.4.2. Operatori unari
Operatorul de negare logic' are rezultatul 1 dac'
valoarea operandului este nul' $i 0 dac' valoarea
operandului este nenul'. Ca exemplu, fie secven#a:
int a = 21,b;
b=!a; // b este 0 deoarece a e diferit de 0
b=!b; // b devine 1 deoarece b este 0
Operatorul de negare la nivel de bit schimb' to#i
bi#ii operandului din 0 n 1 $i din 1 n 0. Ca exemplu, fie
secven#a:
short int a = 33,b;
b=~a;
S' determin'm valoarea lui b. Reprezentarea n
baza 2, pe 16 de bi#i a num'rului 33 este:
0000.0000.0010.0001. Dac' se schimb' to#i bi#ii 0 n 1 $i
to#i bi#ii 1 n 0 $i se ob#ine num'rul:
1111.1111.1101.1110. Deoarece aceast' valoare este
scris' n cod complementar fa#' de 2, valoarea n baza
10 a lui b este -34.
Operatorul de semn plus are ca rezultat valoarea
operandului, iar operatorul de semn minus are ca rezultat
valoarea cu semn schimbat a operandului. De exemplu,
int a = 33, b, c;
b = -a;
c = +b;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
61
Operatorii de adres' $i de adresare indirect',
avnd sintaxa &operand, respectiv, *operand, sunt
folosi#i pentru opera#ii cu adrese de memorie $i vor fi
detalia#i n capitolul 8.
Operatorii de incrementare $i decrementare au
fiecare dou' forme: prefixat' ++operand $i postfixat'
operand++, respectiv, operand $i operand--. n forma
prefixat' valoarea operandului se m're$te cu 1 (adic' se
incrementeaz'), respectiv se mic$oreaz' cu 1 (adic' se
decrementeaz'), iar rezultatul expresiei este noua
valoare. n forma postfixat', valoarea operandului se
incrementeaz', respectiv decrementeaz', iar rezultatul
expresiei este vechea valoare.
Operatorul sizeof are ca rezultat dimensiunea n
octe#i a operandului (adic' num'rul de octe#i necesari
pentru memorarea unei informa#ii de acest tip).
Operandul poate s' fie o expresie sau un tip de dat'.
Dac' operandul este o expresie, atunci se evalueaz'
expresia $i sizeof calculeaz' dimensiunea n octe#i pentru
tipul rezultatului. De exemplu,
long b;
char c;
b=sizeof(c); // b = 1 (un caracter ocupa 1
octet)
b=sizeof(-b);// b = 4 (un long int ocupa 4
octeti)
Operatorul de conversie explicit' (denumit
operator cast) este folosit atunci cnd este necesar'
conversia unei valori la un anumit tip. Sintaxa operatorului
este: (tip)expresie, unde tip este tipul spre care se
converte$te valoarea expresiei. De exemplu, operatorul
Expresii. Operanzi. Operatori.
62
de mp'r#ire aplicat la doi operanzi ntregi efectueaz'
mp'r#irea ntreag' (f'r' zecimale); pentru a calcula
valoarea real' unul dintre operanzi trebuie transformat n
tipul float sau double:
int a = 6, b = 10;
float f;
f=a/b; // f=6/10 = 0 (impartire intreaga)
f=(float)a/b;// f=6.0/10 = 0.6 (impartire
reala)
3.4.3. Operatori multiplicativi
Operatorul de nmul#ire are sintaxa
operand1*operand2 $i rezultatul este produsul valorilor
celor doi operanzi, cu eventuale conversii de tip.
Operatorul de mp'r#ire are sintaxa
operand1/operand2 $i rezultatul este ctul mp'r#irii
primului operand la cel de-al doilea operand, cu
eventuale conversii de tip. Dac' ambii operanzi sunt
ntregi, atunci operandul 2 trebuie s' fie nenul.
Operatorul modulo are sintaxa
operand1%operand2, se aplic' numai operanzilor de tip
ntreg $i rezultatul este restul mp'r#irii primului operand
la cel de-al doilea operand. Operandul 2 trebuie s' fie
nenul.
Pentru exemplificare consider'm secven#a
urm'toare:
int a = 3, b = 6;
double c = 8.1, d = 1.1;
printf("%d\n", a * b);// Valoarea 18 de tip
intreg
printf("%f\n", a * d);// Valoarea 6.6 de tip
real
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
63
printf("%f\n", c * d);// Valoarea 8.91 de tip
real
printf("%d\n", b / a);// Valoarea 2 de tip
intreg
printf("%d\n", a / b);// Valoarea 0 de tip
intreg
printf("%f\n", c / a);// Valoarea 2.7 de tip
real
printf("%f\n", c / d);// Valoarea 7.36 de tip
real
printf("%d\n", a % b);// Valoarea 3 de tip
intreg
printf("%d\n", b % a);// Valoarea 0 de tip
intreg
3.4.4. Operatori aditivi
Operatorul de adunare are sintaxa
operand1+operand2 $i rezultatul este suma valorilor
celor doi operanzi, cu eventuale conversii de tip.
Operatorul de sc'dere are sintaxa operand1operand2
$i rezultatul este diferen#a dintre valoarea primului $i a
celui de-al doilea operand, cu eventuale conversii de tip.
Pentru exemplificare consider'm secven#a
urm'toare:
int a = 3, b = 5;
double c = 8.12, d = 1.1;
printf("%d\n", a + b);// Valoarea 8 de tip
intreg
printf("%d\n", a b);// Valoarea -2 de tip
intreg
printf("%f\n", c b);// Valoarea 3.12 de tip
real
printf("%f\n", a + c);// Valoarea 11.12 de tip
real
printf("%f\n", c + d);// Valoarea 9.21 de tip
real
printf("%f\n", c d);// Valoarea 7.02 de tip
real
Expresii. Operanzi. Operatori.
64
3.4.5. Operatori pentru deplasare
Operatorii de deplasare se aplic' operanzilor de
tip ntreg, rezultatul fiind de tip ntreg. Operatorul de
deplasare stnga are sintaxa: operand1<<operand2 $i
rezultatul se ob#ine prin deplasarea la stnga a
configura#iei binare a primului operand, cu num'rul de bi#i
dat de valoarea celui de-al doilea operand. Pozi#iile
binare r'mase libere n dreapta se completeaz' cu
zerouri.
Operatorul de deplasare dreapta are sintaxa:
operand1>>operand2 $i rezultatul se ob#ine prin
deplasarea la dreapta a configura#iei binare a primului
operand, cu num'rul de bi#i dat de valoarea celui de-al
doilea operand. Pozi#iile binare r'mase libere n stnga
se completeaz' cu bitul de semn pentru subtipurile cu
semn (e.g. int, short, etc.), sau cu 0 pentru subtipurile f'r'
semn (e.g. unsigned int, unsigned short, etc.).
i Deplasarea la stnga cu n pozi#ii binare este
echivalent' cu nmul#irea cu 2
n
. Deplasarea la
dreapta cu n pozi#ii binare este echivalent' cu
mp'r#irea cu 2
n
. n ambele cazuri, valoarea final'
nu poate dep'$i domeniul de valori al tipului
rezultatului.
De exemplu, fie secven#a:
short int a = 20, b = 2, c;
c = a << b; // c este 80
d = a >> b; // d este 5
Pentru a calcula valoarea lui c, se reprezint'
valoarea lui a n baza 2 (0000.0000.0001.0100), se
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
65
deplaseaz' cu 2 pozi#ii la stnga (0000.0000.0101.0000)
$i se interpreteaz' rezultatul n baza 10. Deci 20<<2 este
80.
Pentru a calcula valoarea lui d, se reprezint'
valoarea lui a n baza 2 (0000.0000.0001.0100), se
deplaseaz' cu 2 pozi#ii la dreapta (0000.0000.0000.0101)
$i se interpreteaz' rezultatul n baza 10. Deci 20>>2 este
5.
3.4.6. Operatori relaionali
Operatorii rela#ionali sunt folosi#i pentru tipurile
aritmetice de date $i pentru datele de tip pointer, avnd
sintaxa operand1 operator operand2. Valoarea
expresiei se ob#ine astfel: se evalueaz' cei doi operanzi;
dac' valoarea primului operand este n rela#ia dat' de
operator, cu al doilea operand, rezultatul expresiei este 1;
altfel rezultatul expresiei este 0. De exemplu:
int a = 20, b = 13, c;
c = a<b; // c este 0
c = a<=b; // c este 0
c = a>b; // c este 1
c = a>=b; // c este 1
3.4.7. Operatori de egalitate
Operatorii rela#ionali sunt folosi#i pentru tipurile
aritmetice de date $i pentru datele de tip pointer, avnd
sintaxa operand1 operator operand2. Valoarea
expresiei se ob#ine astfel: se evalueaz' cei doi operanzi;
dac' valoarea primului operand este n rela#ia dat' de
Expresii. Operanzi. Operatori.
66
operator, cu al doilea operand, rezultatul expresiei este 1;
altfel rezultatul expresiei este 0.
De exemplu, fie secven#a:
int a = 20, b = 13, c;
c = a==b; // c este 0
c = a!=b; // c este 1
3.4.8. Operatori pe bii
Operatori pe bi#i binari folosesc operanzi de tip
ntreg, iar rezultatul este de tip ntreg, sintaxa general'
fiind operand1 operator operand2. Func#ia
operatorului se aplic' fiec'rei perechi de bi#i de acela$i
rang din reprezentarea binar' a operanzilor conform
tabelului urm'tor, iar rezultatul este dat de configura#ia de
bi#i care se ob#ine.
Tabel 3.2 Tabelul de adev*r al funciilor !I,
SAU exclusiv $i SAU
a b a&b a^b a|b
0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 0 1
De exemplu, fie secven#a:
short int a = 20, b = 13, c, d, e;
c = a & b; // c este 4
d = a ^ b; // d este 25
e = a | b; // e este 29
Pentru a calcula valoarea lui c, se reprezint' n
baza 2 valoarea lui a $i b (adic' 0000.0000.0001.0100,
respectiv 0000.0000.0000.1101); se aplic' operatorul *I
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
67
pentru fiecare pereche de bi#i $i se ob#ine:
0000.0000.0000.0100. Deci, 20 & 13 este 4.
Pentru a calcula valoarea lui d, se reprezint'
valoarea lui a $i b n baza 2 $i se aplic' operatorul SAU
exclusiv pentru fiecare pereche de bi#i $i se ob#ine:
0000.0000.0001.1001. Deci, 20 ^ 13 este 25.
Pentru a calcula valoarea lui e, se reprezint'
valoarea lui a $i b n baza 2 $i se aplic' operatorul SAU
pentru fiecare pereche de bi#i $i se ob#ine:
0000.0000.0001.1001. Deci, 20 | 13 este 29.
3.4.9. Operatori logici
Operatori logici binari se aplic' valorilor
operanzilor conform func#iei descrise n Tabel 3.2.
Evaluarea se realizeaz' prin scurt-circuit, adic' evaluarea
operanzilor se opre$te atunci cnd valoarea expresiei a
fost stabilit' $i nu mai poate fi schimbat' de restul
expresiei. De exemplu:
short int a = 20, b = 0, c, d;
c = a && b; // c este 0 (deoarece c este 0)
d = a || b; // d este 1 (deoarece a este 20)
3.4.10. Operatorul condiional
Operatorul condi#ional este singurul operator
ternar al limbajului C. Sintaxa sa este:
operand1?operand2:operand3. Valoarea expresiei se
ob#ine astfel: se evalueaz' expresia operand1; dac'
valoarea acesteia este nenul' rezultatul expresiei este
valoarea lui operand2, iar operand3 nu se mai
Expresii. Operanzi. Operatori.
68
evalueaz'; altfel, rezultatul expresiei este valoarea lui
operand3, iar operand2 nu se mai evalueaz'.
3.4.11. Operatori de atribuire
Operatorii de atribuire sunt de dou' tipuri: simplu
$i compu$i. Operatorul de atribuire simpl' are sintaxa
var=expr unde var este o variabil' sau un element dintr-
un tablou, iar expr este o expresie. Valoarea expresiei de
atribuire se calculeaz' astfel: se evalueaz' expresia
expr. Valoarea ob#inut' se atribuie variabilei var, cu
eventuale conversii de tip, iar valoarea opera#iei este
valoarea lui var. De exemplu, consider'm secven#a:
int a, b;
char c;
double d;
a = 5; // a este 5
d = 12.21; // c este 12.21
b = a + 3.5; // b este 8 (se face conversie la
int)
b = b+d; // b este 20 (se face conversie la
int)
c = 'x'; // d este caracterul x
Pentru atribuirea simpl' de forma:
variabila = variabila operator expresie;
unde operator poate fi oricare dintre operatorii binari, se
poate folosi operatorul compus operator=, astfel:
variabila operator=expresie;
De exemplu:
int a = 3, b = 5;
a += b; // Echivalent cu a = a+b, deci a = 8
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
69
Operatorii de atribuire se evalueaz' de la dreapta
c'tre stnga. n cazul unor atribuiri multiple, evaluarea
expresiei se face ncepnd din partea dreapt' $i la fiecare
pas se aplic' conversiile de tip necesare. De exemplu,
int a = 5, b = 8;
double d = 12.21;
a = b = b+d; // b este 20 (datorita
conversiei)
// deci a este 20
n acest caz, nti se evalueaz' expresia b+d,
rezultatul fiind 20.21. Ulterior se atribuie valoarea
variabilei b, nu nainte de a se realiza conversia de la tipul
double (tipul expresiei) la tipul int (tipul variabilei b), deci b
devine 20 $i valoarea expresiei b = b+d este tot 20. n
continuare, a cap't' valoarea 20 $i valoarea ntregii
expresii este 20.
3.4.12. Operatorul virgul*
Operatorul virgul' este folosit pentru scrierea
unei expresii format' dintr-o list' de expresii, avnd
sintaxa: operand1, operand2, ..., operandn.
Valoarea expresiei se calculeaz' astfel: se evalueaz'
succesiv valorile lui operand1, operand2, ..., operandn.
Tipul $i valoarea ntregii expresii este tipul $i valoarea
expresiei operandn. De exemplu,
int a, b, c;
a=2, b=5, c=b%2;
nti se atribuie variabilei a valoarea 2, apoi se
atribuie variabilei b valoarea 5 $i n final variabilei c restul
mp'r#irii valorii lui b la 2, adic' se atribuie variabilei c
Expresii. Operanzi. Operatori.
70
valoarea 1. Valoarea expresiei a=2,b=5,c=b%a este 1
(valoarea expresiei c=b%a), iar tipul ei este int (tipul
expresiei c=b%a).
3.5. Exemple
9. Programul urm'tor exemplific' func#ionarea
operatorilor unari !, ~, ++, , &, *.
#include <stdio.h>
#include <conio.h>
int main()
{
int val, temp, rez, *pint;
char oper;
printf("Testarea operatorilor unari.\n");
printf("Introduceti operandul:");
scanf("%d",&val);
printf("Introduceti operatorul:");
scanf(" %c",&oper);
switch(oper)
{
case '!': // Operatorul !
rez=!val;
printf("!%d = %d", val, rez);
break;
case '~': // Operatorul ~
rez=~val;
printf("~%d = %d", val, rez);
break;
case '+': // Operatorul ++
temp=val; // pastram valoarea initiala
rez=++val;
printf("++%d = %d\n", temp, rez);
val=temp; // refacem valoarea initiala
rez=val++;
printf("%d++ = %d", temp, rez);
break;
case '-': // Operatorul --
temp=val; // pastram valoarea initiala
rez=--val;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
71
printf("--%d = %d\n", temp, rez);
val=temp; // refacem valoarea initiala
rez=val--;
printf("%d-- = %d", temp, rez);
break;
case '&': // Operatorul &
case '*': // Operatorul *
pint=&val;
rez=*pint;
printf("Adresa variabilei este %p\n",
pint);
printf("Valoarea de la adresa %p este %d",
pint, *pint);
break;
default:
printf("Operator necunoscut");
}
getch();
}
Cteva dintre rezultatele produse de acest
program sunt:
Testarea operatorilor unari
Introduceti operandul: 21
Introduceti operatorul: !
!21 = 0

Testarea operatorilor unari
Introduceti operandul: 33
Introduceti operatorul: ~
~33 = -34

Testarea operatorilor unari
Introduceti operandul: 12
Introduceti operatorul: ++
++12 = 13
12++ = 13

Testarea operatorilor unari
Introduceti operatorul: &
Introduceti operandul: 3
Adresa variabilei este FFF4
Expresii. Operanzi. Operatori.
72
Continutul de la adresa FFF4 este 3
10. Programul urm'tor exemplific' func#ionarea
operatorilor binari pe bi#i.
#include <stdio.h>
#include <conio.h>
int main()
{
int op1,op2,rez;
char oper;
printf("Testarea operatorilor pe biti.\n");
printf("Introduceti operandul 1:");
scanf("%d",&op1);
printf("Introduceti operandul 2:");
scanf("%d",&op2);
printf("Introduceti operatorul:");
scanf(" %c",&oper);
switch(oper)
{
case '<':
rez = op1<<op2;
printf("%d<<%d = %d", op1, op2, rez);
break;
case '>':
rez = op1>>op2;
printf("%d>>%d = %d", op1, op2, rez);
break;
case '&':
rez = op1&op2;
printf("%d&%d = %d", op1, op2, rez);
break;
case '|':
rez = op1|op2;
printf("%d|%d = %d", op1, op2, rez);
break;
case '^':
rez = op1^op2;
printf("%d^%d = %d", op1, op2, rez);
break;
default:
printf("Operator necunoscut");
}
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
73
getch();
}
Cteva dintre rezultatele produse de acest
program sunt:
Testarea operatorilor pe bii.
Introduceti operandul 1: 20
Introduceti operandul 2: 2
Introduceti operatorul: <<
20<<2 = 80

Introduceti operandul 1: 21
Introduceti operandul 2: 7
Introduceti operatorul: &
21&7 = 5
11. Programul urm'tor prezint' func#ionarea
operatorului ternar.
#include <stdio.h>
#include <conio.h>
int main()
{
int a, b;
printf("Testarea operatorului
conditional.\n");
printf("Introduceti valoarea lui a:");
scanf("%d",&a);
printf("Introduceti valoarea lui b:");
scanf("%d",&b);
printf( a<b ? "%d e mai mic ca %d" : "%d e
mai mare ca %d", a, b);
getch();
}
Pentru a=3 $i b=5, deoarece expresia a<b este
adev'rat' (deci nenul'), formatul de afi$are al func#iei
printf este "%d e mai mic ca %d". n acest caz,
rezultatul programului este:
Testarea operatorului conditional.
Expresii. Operanzi. Operatori.
74
Introduceti valoarea lui a: 3
Introduceti valoarea lui b: 5
3 e mai mic ca 5
12. Programul urm'tor exemplific' func#ionarea
operatorilor de atribuire compu$i.
#include <stdio.h>
#include <conio.h>
int main()
{
int x = 5;
int n1 = 3, n2 = 2, n3 = 1, n4 = 4, n5 = 5;
printf("Initial, x = %d.\n", x);
printf("x+=%d este %d.\n", n1, x += n1);
printf("x-=%d este %d.\n", n2, x -= n2);
printf("x*=%d este %d.\n", n3, x *= n3);
printf("x /= %d este %d.\n", n4, x/=n4);
printf("x %%= %d este %d.\n", n5, x%=n5);
printf("In final, x este %d.\n", x);
getch();
}
Rezultatul execu#iei acestui program este:
Valoarea initiala a lui x este 5.
valoarea lui x += 3 este 8.
Valoarea lui x -= 2 este 6.
Valoarea lui x *= 1 este 6.
Valoarea lui x /= 4 este 1.
Valoarea lui x %= 5 este 1.
Valoarea finala a lui x este 1.
13. Programul urm'tor determin' maximul a patru
numere folosind operatorul condi#ional. Dup' citirea
datelor, primul num'r este ales ca maxim. n continuare,
valoarea variabilei max este actualizat' dac' se g'se$te
un num'r mai mare dect ea.
#include <conio.h>
#include <stdio.h>
int main()
{
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
75
float x, y, z, t, max;
printf("Introduceti numerele:");
scanf("%f%f%f%f", &x, &y, &z, &t);
max = x;
max = max > y ? max : y;
max = max > z ? max : z;
max = max > t ? max : t;
printf("Maximul este %f", max);
getch();
}
Rezultatul execu#iei acestui program este:
Introduceti numerele:2 3 5 1
Maximul este 5.000000
14. Program urm'tor calculeaz' num'rul total de
secunde care sunt egale cu h ore, m minute $i s secunde
(citite de la tastatur').
#include <conio.h>
#include <stdio.h>
int main()
{
int h, m, s, t;
printf("Introduceti timpul in format h:m:s:
");
scanf("%i:%i:%i", &h, &m, &s);
t = h * 3600 + m * 60 + s;
printf("Total secunde: %i", t);
getch();
}
i Formatul "%i:%i:%i" determin' func#ia scanf s'
citeasc' de la tastatur' valori ntregi separate prin
dou' puncte. Valorile vor sunt memorate n
variabilele h, m $i s, iar caracterele dou' puncte
sunt ignorate.
Rezultatul execu#iei acestui program este:
Introduceti timpul in format h:m:s: 1:3:10
Total secunde: 3790
Expresii. Operanzi. Operatori.
76
15. Sistemul RGB permite codificarea fiec'rei culori
printr-un triplet de numere naturale care reprezint'
intensit'#ile culorilor de baz' ro$u (Red), verde (Green) $i
albastru (Blue). Fiecare component' a tripletului poate
avea valori din mul#imea { } 255 , , 1 , 0 K . Tripletul poate fi
codificat ntr-un ntreg n baza 16, cu valori din mul#imea
{ } FFFFFF , , 1 , 0 K , primele dou' cifre hexazecimale
reprezentnd intensitatea culorii ro$u, urm'toarele dou'
cifre hexazecimale reprezentnd intensitatea culorii
verde, iar ultimele dou' pentru albastru. Programul
urm'tor cite$te de la tastatur' un ntreg n format
hexazecimal din mul#imea { } FFFFFF , , 1 , 0 K $i calculeaz'
$i afi$eaz' intensit'#ile culorilor de baz'.
// Codificare culori
#include "stdio.h"
#include "conio.h"
int main()
{
int cod,R,G,B;
printf(" Tastati codul de culoare in baza 16
");
scanf("%x",&cod);
if(cod>=0 && cod<=0xffffff)
{
printf(" Ati tastat codul %x \n",cod);
B=cod%256;
G=(cod>>8)%256;
R=(cod>>16);
printf(" R = %d \n",R);
printf(" G = %d \n",G);
printf(" B = %d \n",B);
} else
{
printf(" Cod invalid \n");
}
getch();
}
Rezultatul execu#iei este:
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
77
Tastati codul de culoare in baza 16 ABCDEF
Ati tastat codul abcdef
R = 171
G = 205
B = 239
3.6. Exerci#ii
25. Scrie#i un program C care cite$te de la tastatur' o
temperatur' n grade Celsius $i afi$eaz' pe ecran
temperatura n grade Farenheit $i Kelvin.
26. Scrie#i un program C care cite$te de la tastatur' un
num'r ntreg $i determin' dac' acesta este divizibil cu 2,
3, 5, 10 $i 100.
27. Scrie#i un program C care determin' perimetrul $i
aria unui dreptunghi cunoscnd lungimile laturilor.
28. Scrie#i un program C care determin' consumul de
combustibil la o sut' de kilometri al unui vehicul $tiind
consumul total pe parcursul unei anumite distan#e.
29. Scrie#i un program C care cite$te de la tastatur' un
num'r natural $i afi$eaz' cei mai pu#in semnificativi trei
bi#i din reprezentarea binar' a num'rului respectiv.
30. Scrie#i un program C care determin' minimul a opt
numere reale citite de la tastatur' (folosi#i ct mai pu#ine
compara#ii).
31. Scrie#i un program C care func#ioneaz' ca un
minicalculator: utilizatorul introduce o valoarea, un
operator aritmetic $i apoi o alt' valoare, iar programul
afi$eaz' rezultatul opera#iei aritmetice.
32. Scrie#i un program C care calculeaz' num'rul
maxim de ore, minute $i secunde care sunt egale cu un
num'r n de secunde (citit de la tastatur').
33. Scrie#i un program C care adun' dou' intervale de
timp exprimate n ore, minute $i secunde. Rezultatul
trebuie exprimat tot n ore, minute $i secunde. n plus,
Expresii. Operanzi. Operatori.
78
num'rul de secunde $i cel de minute trebuie s' fie
cuprinse ntre 0 $ i 59.
34. Scrie#i un program C care afi$eaz' valoarea func#iei
f(x,y)=2,5x
2
+ 3xy + 1,2y
2
, pentru valori x $i y citite de la
tastatur' cu ajutorul func#iei scanf.
35. Scrie#i un program C care calculeaz' media
ponderat' a trei numere naturale. Primul are pondere
20%, al doilea 30%, iar ultimul 50%.
79
4
44.
.. I
IIN
NNS
SST
TTR
RRU
UUC
CC)
))I
IIU
UUN
NNI
II
Instruc#iunile unui program C determin' opera#iile
pe care acesta le efectueaz'. O instruc#iune este format'
din cuvinte cheie, expresii $i/sau alte instruc#iuni. O
instruc#iune care apare n interiorul altei instruc#iuni
formeaz' corpul acesteia din urm'.
O instruc#iune compus' este un grup de zero sau
mai multe instruc#iuni incluse ntr-o pereche de acolade.
Efectul execu#iei acesteia este acela al execu#iei rnd pe
rnd a instruc#iunilor care o compun.
Cu excep#ia instruc#iunilor compuse, toate
instruc#iunile se termin' prin punct $i virgul'.
Instruc#iunea vid' este o instruc#iune care nu face nimic,
fiind reprezentat' de un singur caracter punct $i virgul'.
Ea se folose$te n locurile unde este necesar' o
instruc#iune, dar nu vrem s' se efectueze nici o opera#ie.
4.1. Instruc#iuni expresie
O instruc#iune expresie este o expresie compus'
din operanzi $i operatorii limbajului C (vezi capitolul 3).
Instruc#iuni
80
Efectul execu#iei acesteia este acela al evalu'rii expresiei
care o compune. Sintaxa instruc#iunii este urm'toare:
expresie;
4.2. Instruc#iuni de decizie
4.2.1. Instruciunea if
Instruc#iunea if permite condi#ionarea execu#iei
unei instruc#iuni de valoarea de adev'r a unei expresii.
Sintaxa instruc#iunii este urm'toare:
if (conditie)
instructiune1;
else
instructiune2;
Ramura else $i instruc#iune
2
pot fi omise,
ob#inndu-se varianta scurt' a instruc#iunii. Efectul
instruc#iunii este urm'torul: se evalueaz' expresia
conditie; dac' valoarea acesteia este diferit' de zero,
atunci se execut' instruciune1, altfel se execut'
instruciune2 (dac' exist' ramura else).
Instruc#iunile instruciune1 $i instruciune2
pot fi la rndul lor instruc#iuni if. n aceast' situa#ie,
compilatorul C asociaz' fiecare else cu cel mai recent if
care nu are asociat un else. Programatorul poate
modifica acest comportament prin folosirea acoladelor
(instruc#iunea if f'r' else devine astfel o instruc#iune
compus'). De exemplu, n secven#a:
if(i>=0)
if(i<=10)
j = 1;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
81
else
j = 2;
dac' i este ntre 0 $i 10, atunci valoarea variabilei j devine
1; dac' i este mai mare ca 10, atunci j devine 2; dac' i
este mai mic dect 0, j nu se modific'. n exemplul
urm'tor:
if(i>=0)
{
if(i<=10)
j = 1;
} else
j = 2;
dac' i este ntre 0 $i 10, atunci valoarea variabilei j devine
1; dac' i este mai mare dect 10, valoarea variabilei j nu
se modific'; dac' i este mai mic dect 0, j devine 2.
4.2.2. Instruciunea switch
La fel ca if, Instruc#iunea switch permite
condi#ionarea execu#iei unei instruc#iuni de valoarea unei
expresii, executnd automat testele de egalitate. Sintaxa
instruc#iunii este urm'toare:
switch(expresie)
{
case constanta1:
instructiune;
...
case constanta2:
instructiune;
...
...
default:
instructiune;
...
...
case constantan:
Instruc#iuni
82
instructiune;
...
}
Oricare variant' case poate s' nu con#in'
instruc#iuni. Varianta implicit' (default) $i instruc#iunile
aferente acesteia pot fi omise. Efectul instruc#iunii este
urm'torul: se evalueaz' instruc#iunea expresie o singur'
dat'. Valoarea acesteia se compar' pe rnd cu valorile
constanta1, constanta2, ..., constantan. Dac' exist' o
valoare egal' cu cea a expresiei, atunci se execut'
instruc#iunile ncepnd de la acel caz pn' la sfr$itul
instruc#iunii switch sau pn' la prima instruc#iune break.
Dac' nu exist' nici o valoare egal', $i exist' cazul implicit
se execut' instruc#iunile ncepnd de la acesta pn' la
sfr$itul instruc#iunii switch sau pn' la prima instruc#iune
break. Dac' nu exist' nici o valoare egal' $i nu exist'
cazul implicit, atunci nu se mai ntmpl' nimic.
De exemplu, n secven#a urm'toare:
switch(i)
{
case 0: j=1; break;
case 1:
case 2: j=2;
case 3: j=3; break;
default: j = 0;
}
dac' i are valoarea 0, atunci valoarea lui j devine 1; dac'
i are valoarea 1 sau 2, atunci valoarea lui j devine 2; dac'
i are valoarea 3, atunci valoarea lui j devine 3, iar pentru
alte valori ale lui i, valoarea lui j devine 0.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
83
4.3. Instruc#iuni de ciclare
4.3.1. Instruciunea do-while
Instruc#iunea do-while permite execu#ia repetat'
a unei instruc#iuni ct timp o expresie are valoare nenul'
(adic' adev'rat). Sintaxa instruc#iunii este:
do
instructiune;
while(conditie);
Efectul instruc#iunii este urm'torul: se execut'
corpul lui do-while (instruc#iunea instructiune) $i apoi
se evalueaz' expresia condiie. Dac' valoarea
acesteia este 0, atunci se trece la urm'toarea
instruc#iune, altfel se repet' instruc#iunea do-while
curent'. De remarcat c' testul se execut' la sfr$it, deci
instructiune se execut' m'car o dat'.
n exemplul urm'tor:
int i=3, j=1;
do
j=j+1;
while (i>j);
se executa instruc#iunea j=j+1 (deci j devine 2) $i
deoarece 3>2 (adic' i>j) este adev'rat' se repet'
instruc#iunea do-while; se executa instruc#iunea j=j+1
(deci j devine 3) $i deoarece 3>3 este fals', se termin'
instruc#iunea do-while.
Instruc#iuni
84
4.3.2. Instruciunea while
Instruc#iunea while permite execu#ia repetat' a
unei instruc#iuni ct timp o expresie are valoarea nenul'
(adic' adev'rat). Sintaxa instruc#iunii este:
while(conditie)
instructiune;
Efectul instruc#iunii este urm'torul: se evalueaz'
expresia condiie. Dac' valoarea acesteia este 0,
atunci se trece la urm'toarea instruc#iune de dup' while
(nu se execut' instruc#iunea din corpul lui while), altfel
se execut' corpul lui while (instruc#iunea instructiune)
$i se repet' instruc#iunea while curent'. De remarcat c'
testul se execut' la nceput, deci e posibil ca
instructiune s' nu se execute nici o dat'.
n exemplul urm'tor:
int i=3, j=1;
while (i>j)
j=j+1;
deoarece 3>1 (adic' i>j) este adev'rat', se executa
instruc#iunea j=j+1 (deci j devine 2) $i se repet'
instruc#iunea while; deoarece 3>2 (adic' i>j) este
adev'rat', se execut' instruc#iunea j=j+1 (deci j devine 3)
$i se repet' instruc#iunea while; deoarece 3>3 este fals',
se termin' instruc#iunea while.
4.3.3. Instruciunea for
Instruc#iunea for permite execu#ia repetat' a unei
instruc#iuni ct timp o expresie are valoarea nenul' (adic'
adev'rat). Sintaxa instruc#iunii este urm'toare:
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
85
for(initializare; conditie; actualizare)
instructiune;
Efectul instruc#iunii este urm'torul: se evalueaz'
expresia initializare o singur' dat'. Se evalueaz'
expresia condiie. Dac' valoarea acesteia este 0,
atunci se trece la urm'toarea instruc#iune de dup' for
(nu se execut' instruc#iunea din corpul lui for), altfel se
execut' corpul lui for (instruc#iunea instructiune), se
evalueaz' expresia actualizare $i se repet'
instruc#iunea for curent', dar f'r' expresia de
ini#ializare.
De remarcat c' expresia de ini#ializare se
execut' o singur' dat', iar apoi testul de repetare se
execut' la nceput, deci e posibil ca instructiune $i
actualizare s' nu se execute nici o dat'. Expresiile de
iniializare, condiie $i actualizare sunt
op#ionale, dar caracterele punct $i virgul' trebuie scrise.
Dac' lipse$te expresia conditie atunci valoarea ei se
consider' nenul'. O instruc#iune for poate fi rescris'
folosind instruc#iunea while astfel:
initializare;
while(conditie)
{
instructiune;
actualizare;
}
n exemplul urm'tor:
int i, j;
for(i = 1, j = 0; i <= 5; ++i)
j = j+i;
Instruc#iuni
86
instruc#iunea for produce execu#ia instruc#iunii j=j+i de
cinci ori, cu valori diferite pentru i. Astfel, in final valoare
lui j este 15 (adic' 1+2+3+4+5).
4.4. Instruc#iuni de salt
4.4.1. Instruciunea break
A$a cum s-a v'zut n sec#iunea 4.2.2,
instruc#iunea break poate fi folosit' pentru a for#a
terminarea unei instruc#iuni switch. De asemenea,
instruc#iunea break poate fi folosit' pentru a for#a
terminarea instruc#iunilor de ciclare for, while $i do-while.
n acest caz, execu#ia instruc#iunii break determin'
ntreruperea instruc#iunii de ciclare curente $i continuarea
execu#iei cu prima instruc#iune dup' aceasta.
n exemplul urm'tor:
int i, j=0;
for(i = 1; i <= 5; ++i)
{
if (i == 4)
break;
j = j+i;
}
instruc#iunea for produce (n mod normal) execu#ia
instruc#iunii j=j+i de cinci ori, cu valori diferite pentru i.
Totu$i, cnd i ajunge la valoarea 4, instruc#iunea if
determin' execu#ia instruc#iunii break, terminndu-se
astfel instruc#iunea for. Astfel, n final valoare lui j este 6
(adic' 1+2+3).
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
87
4.4.2. Instruciunea continue
Instruc#iunea continue poate fi folosit' pentru a
for#a terminarea execu#iei corpului instruc#iunii de ciclare.
Cu toate aceste, instruc#iunea de ciclare $i continu'
execu#ia prin evaluarea expresiei de actualizare (n cazul
lui for) $i a expresiei condi#ie. n exemplul urm'tor:
int i, j=0;
for(i = 1; i <= 5; ++i)
{
if (i == 4)
continue;
j = j+i;
}
instruc#iunea for produce (n mod normal) execu#ia
instruc#iunii j=j+i de cinci ori, cu valori diferite pentru i.
Totu$i, cnd i ajunge la valoarea 4, instruc#iunea if
determin' execu#ia instruc#iunii continue, terminndu-se
astfel corpul instruc#iunii for. Instruc#iunea for continu' cu
expresia de actualizare $i cu itera#ia urm'toare. Astfel, in
final valoare lui j este 11 (adic' 1+2+3+5).
4.4.3. Instruciunea goto
Instruc#iunea goto determin' transferul execu#iei
programului la o anumit' instruc#iune. Sintaxa instruc#iunii
este urm'toarea:
goto eticheta;
Efectul instruc#iunii este urm'torul: execu#ia
programului continu' cu prima instruc#iune dup' eticheta
eticheta. n general, se recomand' a se evita folosirea
instruc#iunii goto.
Instruc#iuni
88
O etichet' este un identificator unic (n interiorul
func#iei n care este declarat) asociat unei instruc#iuni $i
care are semnifica#ie doar pentru instruc#iunea goto. O
etichet' se scrie naintea instruc#iunii pe care o
denume$te $i este urmat' de caracterul dou' puncte. De
exemplu, n secven#a urm'toare:
int i=3, j=2;
if (i < j)
goto maimic;
j = i;
goto gata;
maimic: i = j; // aici este o eticheta
gata:; // aici este alta eticheta
dac' i este mai mic dect j, atunci execu#ia continu' de la
instruc#iunea cu eticheta maimic (adic' cu i=j), altfel se
execut' instruc#iunea j=i $i se sare la instruc#iunea
(vid') cu eticheta gata.
4.5. Exemple
16. Urm'torul program determin' solu#ia unei ecua#ii de
gradul 1 cu coeficien#i reali, de forma ax+b = 0.
#include <stdio.h>
#include <conio.h>
int main()
{
float a, b;
printf("Introduceti a: ");
scanf("%f", &a);
printf("Introduceti b: ");
scanf("%f", &b);
if(a == 0)
if(b == 0)
printf("Orice numar real e solutie");
else
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
89
printf("Nu exista solutii reale");
else
{
float x = -b/a;
printf("Solutie: %f", x);
}
getch();
}
Rezultatul rul'rii pentru ecua#ia 3x+8=0 este:
Introduceti a: 3
Introduceti b: 8
Solutie: -2.666667
17. Urm'torul program determin' solu#iile reale ale unei
ecua#ii de gradul 2 cu coeficien#i reali, de forma
ax
2
+bx+c=0. Dac' a este nul, rezolvarea ecua#iei se
reduce la rezolvarea unei ecua#ii de gradul 1. Pentru a
calcula r'd'cina p'trata a lui d vom folosi func#ia sqrt
din biblioteca math.h.
#include <stdio.h>
#include <math.h>
#include <conio.h>
int main()
{
float a, b, c;
printf("Introduceti a: ");
scanf("%f", &a);
printf("Introduceti b: ");
scanf("%f", &b);
printf("Introduceti c: ");
scanf("%f", &c);
if(a == 0)
{
if(b == 0)
if(c == 0)
printf("Orice numar real e solutie");
else
printf("Nu exista solutii reale");
else
{
Instruc#iuni
90
float x = -c/b;
printf("Solutie: %f", x);
}
} else
{
float d = b*b-4*a*c;
if(d < 0)
printf("Ecuatia nu are solutii reale");
else
{
float x1 = (-b-sqrt(d))/(2*a);
float x2 = (-b+sqrt(d))/(2*a);
printf("Solutii: %f si %f", x1, x2);
}
}
getch();
}
Rezultatul rul'rii pentru ecua#ia x
2
+3x+2=0 este:
Introduceti a: 1
Introduceti b: 3
Introduceti c: 2
Solutii: -2.000000 si -1.000000
18. Urm'torul program calculeaz' valoarea n! pentru n
num'r natural dup' formula n!=12...n.
#include <stdio.h>
#include <conio.h>
int main()
{
int i, n, nf;
printf("Valoarea lui n este : ");
scanf("%d",&n);
nf=1;
for(int i=1; i<=n; ++i)
nf *= i;
printf("%d! = %d\n",n, nf);
getch();
}
Rezultatul rul'rii pentru n=6 este:
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
91
Valoarea lui n este : 6
6! = 720
19. Fiind dat un num'r natural n nenul s' se determine
num'rul de zerouri cu care se termin' n!.
//Numrul ultimelor zerouri ale lui n!
#include<stdio.h>
#include<conio.h>
int main ()
{int n,i,k;
long nfact;
printf("n=");
scanf("%d", &n);
nfact=1;
for(i=1; i<=n; i++)
{
nfact=nfact*i;
}
printf(" %d! = %d se termina cu ",n,nfact);
k=0;
while(nfact%10==0)
{
k++;
nfact=nfact/10;
}
printf(" %d zerouri \n", k);
getch();
}
Un exemplu de rulare este urm'torul:
n=11
11! = 39916800 se termina cu 2 zerouri
20. Urm'torul program calculeaz' S(n)=1!+2!+...+n!,
pentru n un num'r natural. Prima variant', folose$te
directe formula lui S, ceea ce nseamn' c' fiecare termen
este calculat separat.
#include <stdio.h>
#include <conio.h>
int main()
{
Instruc#iuni
92
int s, i, j, n, nf;
printf("Valoarea lui n este : ");
scanf("%d",&n);
s=0;
for(int i=1; i<=n; ++i)
{
nf=1;
for(int j=1; j<=i; ++j)
nf *= j;
s = s + nf;
}
printf("S(%d) = %d\n", n, s);
getch();
}
21. O variant' mai eficient' pentru exemplu anterior
ob#inem dac' observ'm c' putem refolosi valorile
calculate la pasul anterior pentru a calcula valoarea
curent'.
#include <stdio.h>
#include <conio.h>
int main()
{
int s, i, n, nf;
printf("Valoarea lui n este : ");
scanf("%d",&n);
s=0;
nf=1;
for(int i=1; i<=n; ++i)
{
nf *= i;
s = s + nf;
}
printf("S(%d) = %d\n", n, s);
getch();
}
n ambele cazuri, rezultatul rul'rii pentru n=6
este:
Valoarea lui n este : 6
S(6) = 873
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
93
22. Programul urm'tor afi$eaz' primii n termeni ai
$irului lui Fibonacci, definit prin: : fib N N , ( ) 0 1 fib ,
( ) 1 1 fib , ( ) ( ) ( 1) 2 fib n fib n fib n + , ( ) 2 n . Pentru
a-i calcula, vom folosi urm'toarea metod': not'm cu ti
termenul la pasul i, cu t
i+1
termenul urm'tor $i cu t
i+2

termenul de dup' acesta. Astfel, pentru fiecare valoare a
lui i, afi$'m valoarea t
i
, calcul'm t
i+2
$i facem trecerea de
la i la i+1 (adic' ti=ti+1 $i ti+1=ti+2).
#include <stdio.h>
#include <conio.h>
int main()
{
int i, n, ti, ti_plus_1, ti_plus_2;
printf("Valoarea lui n este : ");
scanf("%d",&n);
ti=ti_plus_1=1;
for(int i=0; i<n; ++i)
{
printf("Fib(%i) = %i\n", i, ti);
ti_plus_2 = ti_plus_1 + ti;
ti = ti_plus_1;
ti_plus_1 = ti_plus_2;
}
getch();
}
Rezultatul rul'rii pentru n=7 este:
Valoarea lui n este : 7
Fib(0) = 1
Fib(1) = 1
Fib(2) = 2
Fib(3) = 3
Fib(4) = 5
Fib(5) = 8
Fib(6) = 13
23. Fiind dat un num'r natural n nenul, s' se determine
descompunerea lui n n sum' de termeni ai $irului lui
Fibonacci.
Instruc#iuni
94
#include "stdio.h"
#include "conio.h"
int main()
{
int n,x0,x1,xn,xn1,xn2,dif;
printf(" n = ");
scanf("%d",&n);
if(n>1)
{
x0=1;
x1=1;
dif=n;
while(dif>2)
{
xn=x0;
xn1=x1;
xn2=xn1+xn;
while(xn2<dif)
{
xn=xn1;
xn1=xn2;
xn2=xn1+xn;
}
printf(" %d ",xn1);
dif=dif-xn1;
}
if(dif==2)
printf(" %d ",x1+x0);
else
printf(" %d ",x0);
} else
printf(" Valoarea introdusa nu este in
domeniu \n");
getch();
}
Un exemplu de rulare a programului este:
n = 27
21 5 1
24. Este cunoscut faptul c' exist' numere naturale care
se pot reprezenta ca suma a trei cuburi distincte. De
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
95
exemplu
3 3 3
36 1 2 3 1 8 27 + + + + . Programul urm'tor
determin' toate numerele naturale din mul#imea
{ } 1, 2, , k K care au aceast' proprietate, k citit de la
tastatur'.
// Test suma de trei cuburi distincte
#include "stdio.h"
#include "conio.h"
int main()
{
int k,n,c1,c2,c3,i,dif;
printf(" k = ");
scanf("%d",&k);
for(n=1;n<=k;n++)
{
i=1;
while(i*i*i<n)
{
c3=i*i*i;
i++;
}
dif=n-c3;
i=1;
while(i*i*i<dif)
{
c2=i*i*i;
i++;
}
dif=dif-c2;
if(dif!=1)
{
i=1;
while(i*i*i<=dif)
{
c1=i*i*i;
i++;
}
}
else
c1=1;
if(n==c1+c2+c3 && c1!=c2 && c1!=c3 &&
c2!=c3)
Instruc#iuni
96
{
printf(" %d satisface proprietatea \n",n);
printf(" %d = %d + %d + %d
\n",n,c1,c2,c3);
}
}
getch();
}
Un exemplu de rulare este:
k = 100
36 satisface proprietatea
36 = 1 + 8 + 27
73 satisface proprietatea
73 = 1 + 8 + 64
92 satisface proprietatea
92 = 1 + 27 + 64
99 satisface proprietatea
99 = 8 + 27 + 64
25. Fie a $i b dou' numere naturale nenule.
Determinarea produsului celor dou' numere poate fi
f'cut' cu algoritmul rusesc de nmul#ire. Fie suma o
variabil' care, n final va memora valoarea produsului
* a b. Dac' a este impar se face atribuirea suma=suma+b.
Dac' a este par se mparte a la doi $i se nmul#e$te b cu
doi. Algoritmul continu' ct timp a>=1. n final variabila
suma are valoarea egal' cu cea a produsului * a b.
Programul urm'tor codific' algoritmul rusesc de nmul#ire.
// Produsul rusesc
#include "stdio.h"
#include "conio.h"
int main()
{
int a,b,sum,asalv,bsalv;
printf(" a = ");
scanf("%d",&a);
printf(" b = ");
scanf("%d",&b);
asalv=a;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
97
bsalv=b;
printf(" a b produs \n");
sum=0;
while(a>=1)
{
printf(" %d %d %d \n",a,b,sum);
while(a%2==0)
{
a=a/2;
b=b*2;
}
sum=sum+b;
printf(" %d %d %d \n",a,b,sum);
a=a/2;
b=b*2;
}
printf(" %d * %d = %d \n",asalv,bsalv,sum);
getch();
}
Rularea programului produce rezultatele:
a = 24
b = 25
a b produs
24 25 0
3 200 200
1 400 200
1 400 600
24 * 25 = 600

a = 93
b = 10
a b produs
93 10 0
93 10 10
46 20 10
23 40 50
11 80 50
11 80 130
5 160 130
5 160 290
2 320 290
1 640 930
Instruc#iuni
98
93 * 10 = 930
26. Urm'torul program aproximeaz' num'rul folosind
formula
2
1
1
6
n
n
i
i


. Valoarea aproximativ' este afi$at'
la fiecare 1000 de pa$i $i la ultimul pas.
#include <stdio.h>
#include <conio.h>
#include <math.h>
int main()
{
int n;
double s, p;
printf("Valoarea lui n este : ");
scanf("%d",&n);
s = 0;
for(int i=1; i<=n; ++i)
{
s += 1.0/(i*i);
if(i == n || i % 1000 == 1)
{
p = sqrt(6*s);
printf("pi(%i) = %f\n", i, p);
}
}
getch();
}
Rezultatul rul'rii pentru n=10000 este:
Valoarea lui n este : 10000
pi(1) = 2.449490
pi(1001) = 3.140639
pi(2001) = 3.141116
pi(3001) = 3.141274
pi(4001) = 3.141354
pi(5001) = 3.141402
pi(6001) = 3.141434
pi(7001) = 3.141456
pi(8001) = 3.141473
pi(9001) = 3.141487
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
99
pi(10000) = 3.141497
27. Urm'torul program calculeaz' suma cifrelor unui
num'r natural. Ct timp valoarea lui n este nenul',
programul folose$te operatorul % pentru a ob#ine ultima
cifr' $i operatorul / pentru a elimina aceast' cifr' din
num'r.
#include <stdio.h>
#include <conio.h>
int main()
{
int c, n, s;
printf("Valoarea lui n este : ");
scanf("%d",&n);
s=0;
while (n>0)
{
c = n%10; // restul impartirii
n = n/10; // catul impartirii
printf("Adun %d la suma. A mai ramas
%d\n", c, n);
s += c;
}
printf("Suma cifrelor este %d\n",s);
getch();
}
Pentru valoarea 12345 programul furnizeaz'
rezultatele:
Valoarea lui n este : 12345
Adun 5 la suma. A mai ramas 1234
Adun 4 la suma. A mai ramas 123
Adun 3 la suma. A mai ramas 12
Adun 2 la suma. A mai ramas 1
Adun 1 la suma. A mai ramas 0
Suma cifrelor este 15
28. Urm'torul program determin' r'sturnatul unui
num'r natural. n acest context, pentru
1 2
...
k
n a a a , se
Instruc#iuni
100
nume$te r'sturnatul lui n num'rul natural
1 1
...
k k
a a a

. De
exemplu, r'sturnatul num'rului 12345 este num'rul
54321.
#include <stdio.h>
#include <conio.h>
int main()
{
int c, n, nr;
printf("Valoarea lui n este : ");
scanf("%d",&n);
nr=0;
while (n>0)
{
c = n%10; // restul impartirii
n = n/10; // catul impartirii
printf("Adaug %d la numarul %d. A mai
ramas %d\n", c, nr, n);
nr = nr * 10 + c;
}
printf("Rasturnatul este %d\n", nr);
getch();
}
Pentru valoarea 12345 programul furnizeaz'
rezultatele:
Valoarea lui n este : 12345
Adaug 5 la numarul 0. A mai ramas 1234
Adaug 4 la numarul 5. A mai ramas 123
Adaug 3 la numarul 54. A mai ramas 12
Adaug 2 la numarul 543. A mai ramas 1
Adaug 1 la numarul 5432. A mai ramas 0
Rasturnatul este 54321
29. Un num'r natural p se nume$te palindrom dac'
este egal cu r'sturnatul s'u. Un num'r natural p se
nume$te superpalindrom dac' p $i p'tratul s'u sunt
palindroame. Programul urm'tor determin' $i afi$eaz'
primele n superpalindroame.
//Superpalindroame
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
101
#include<conio.h>
#include<stdio.h>
int main()
{
int n,k,ipatrat,inou, ipatratnou;
int isalv, ipsalv,ipal,ippal,i;
printf(" n =");
scanf( "%d", &n);
printf("Primele %d superpalindroame \n\n",
n);
k=0;
i=0;
while(k<n)
{
isalv=i;
inou=0;
while(i)
{
inou=inou+(i%10);
inou=inou*10;
i=i/10;
}
inou=inou/10;
if(isalv==inou)
ipal=1;
else
ipal=0;
ipatrat=isalv*isalv;
ipsalv=ipatrat;
ipatratnou=0;
while(ipatrat)
{
ipatratnou=ipatratnou+(ipatrat%10);
ipatratnou=ipatratnou*10;
ipatrat=ipatrat/10;
}
ipatratnou=ipatratnou/10;
if(ipsalv==ipatratnou)
ippal=1;
else
ippal=0;
if(ipal==1 && ippal==1)
{
Instruc#iuni
102
printf(" %d %d\n", isalv, ipsalv);
k++;
i=isalv+1;
}
else
i=isalv+1;
}
getch();
}
Un rezultat al rul'rii programului este:
n =11
Primele 11 superpalindroame

0 0
1 1
2 4
3 9
11 121
22 484
101 10201
111 12321
121 14641
202 40804
212 44944
30. Programul urm'tor cite$te un num'r ntreg n $i
folosind instruc#iunea if, dac' 1 7 n , atunci afi$eaz'
numele zilei corespunz'toare din s'pt'mn', altfel
afi$eaz' "Eroare".
#include <stdio.h>
#include <conio.h>
int main()
{
int n;
printf("Introduceti n:");
scanf("%i", &n);
if(n == 1) printf("Luni");
else if(n == 2) printf("Marti");
else if(n == 3) printf("Miercuri");
else if(n == 4) printf("Joi");
else if(n == 5) printf("Vineri");
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
103
else if(n == 6) printf("Sambata");
else if(n == 7) printf("Duminica");
else printf("Eroare");
getch();
}
31. Relu'm exemplul anterior, folosind instruc#iunea
switch.
#include <stdio.h>
#include <conio.h>
int main()
{
int n;
printf("Introduceti n:");
scanf("%i", &n);
switch(n)
{
case 1: printf("Luni"); break;
case 2: printf("Marti"); break;
case 3: printf("Miercuri"); break;
case 4: printf("Joi"); break;
case 5: printf("Vineri"); break;
case 6: printf("Sambata"); break;
case 7: printf("Duminica"); break;
default: printf("Eroare");
}
getch();
}
n ambele cazuri, programul furnizeaz' rezultatul:
Introduceti n:6
Sambata
i O variant' mai simpl' ($i mai elegant') este
prezentat' n capitolul 6. Aceasta folose$te un
vector de $iruri de caractere pentru a memora
numele zilelor.
32. Programul urm'tor calculeaz' cel mai mare divizor
comun a dou' numere folosind metoda cu sc'deri a lui
Euclid.
Instruc#iuni
104
#include <stdio.h>
#include <conio.h>
int main()
{
int m, n;
printf("Introduceti m si n:");
scanf("%i%i", &m, &n);
while(m != n)
if(m > n) m -= n;
else n-= m;
printf("cmmdc = %i", m);
getch();
}
Programul furnizeaz' urm'toarele rezultate:
Introduceti m si n:153 9
cmmdc = 9
4.6. Exerci#ii
36. Scrie#i un program C care calculeaz' produsul
cifrelor unui num'r natural.
37. Scrie#i un program C care determin' dac' un num'r
natural n este prim sau compus.
38. Scrie#i un program C care determin' divizorii unui
un num'r natural n.
39. Scrie#i un program C care cite$te un num'r natural n
$i dac' 1 12 n afi$eaz' numele lunii a n-a, altfel
afi$eaz' "Eroare".
40. Scrie#i un program C care calculeaz'
!
( )!
k
n
n
A
n k


pentru n $i k numere naturale.
41. Scrie#i un program C care calculeaz'
!
!( )!
k
n
n
C
k n k


pentru n $i k numere naturale.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
105
42. Scrie#i un program C care calculeaz'
k
n pentru n $i
k numere naturale.
43. Scrie#i un program C care aproximeaz' num'rul e
folosind formula
0
1
!
n
n
i
e
i

pentru un num'r natural n.


107
5
55.
.. F
FFU
UUN
NNC
CC)
))I
III
II S
SST
TTA
AAN
NND
DDA
AAR
RRD
DD D
DDE
EE I
IIN
NNT
TTR
RRA
AAR
RRE
EE/
//I
IIE
EE!
!!I
II R
RRE
EE
De$i limbajul C nu con#ine nici o instruc#iune
pentru citirea datelor (intrare) de la utilizator sau afi$area
rezultatelor (ie$ire) pe ecran, exist' un num'r mare de
func#ii standard pentru opera#ii de intrare/ie$ire. Aceste
func#ii se g'sesc n biblioteca stdio.h (stdio este un
acronim pentru standard input/output). Tot aici sunt
definite constantele EOF (End Of File) $i NULL. Aceste
valori sunt returnate de diverse func#ii cnd prelucrarea
datelor s-a finalizat (datorit' termin'rii datelor sau datorit'
unei erori).
5.1. Func#ii pentru caractere
Func#iile pentru caractere au o utilizare limitat',
fiind folosite pentru citirea $i afi$area informa#iei caracter
cu caracter, f'r' nici o prelucrare n prealabil.
Tabel 5.1 Funcii standard de intrare/ie$ire la
nivel de caracter
Prototip int putchar (int c)
Descriere Efect: afi$eaz' caracterul cu codul ASCII c
pe ecran.
Func#ii standard de intrare/ie$ire
108
Rezultat: valoarea c sau EOF n caz de
eroare
Prototip int getchar()
Descriere Efect: cite$te de la tastatur' un singur
caracter
Rezultat: codul ASCII al caracterului citit
sau EOF dac' s-au terminat datele sau a
ap'rut o eroare
i Func#ia getchar a$teapt' ap'sarea tastei Enter
nainte de a returna primul caracter introdus. La
urm'toarele apeluri, func#ia returneaz' restul
caracterelor tastate nainte de ap'sarea tastei
Enter.
De exemplu, secven#a urm'toare afi$eaz' pe
ecran primul caracter introdus de utilizator de la tastatur':
int c;
puts("Tastati un caracter si apasati Enter");
c = getchar();
putchar(c);
5.2. Func#ii pentru $iruri de caractere
Func#iile pentru $iruri de caractere permit citirea
$i afi$area informa#iei sub form' de $ir de caracter, f'r'
alte prelucr'ri.
Tabel 5.2 Funcii standard de intrare/ie$ire
pentru $iruri de caractere
Prototip int puts (char *s)
Descriere Efect: afi$eaz' pe ecran $irul din variabila s
$i trece pe linia urm'toare
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
109
Rezultat: un num'r nenegativ n caz de
succes sau EOF n caz de eroare
Prototip char* gets (char *s)
Descriere Efect: cite$te un $ir de caractere de la
tastatura pn' la ap'sarea tastei Enter $i l
pune n memorie la adresa s
Rezultat: adresa s a $irului citit sau NULL
daca s-au terminat datele sau a ap'rut o
eroare
De exemplu, secven#a urm'toare afi$eaz' pe
ecran un mesaj introdus de utilizator de la tastatur':
char sir[80];
puts("Tastati un text si apasati Enter");
gets(sir);
puts("Ati tastat:");
puts(sir);
5.3. Func#ii cu formatare
Func#iile cu formatare permit citirea $i afi$area
informa#iei dup' o prelucrare n prealabil a acesteia.
Prelucrarea se realizeaz' conform unor coduri de format
scri$i de programator ntr-un $ir de caractere.
Tabel 5.3 Funcii standard de intrare/ie$ire cu
formatare
Prototip int printf (char *fmt, ...);
Descriere Efect: scrie pe ecran $irul fmt n care
codurile de format sunt nlocuite cu valorile
expresiilor marcate prin trei puncte;
Rezultat: num'rul de caractere scrise sau
EOF n caz de eroare
Func#ii standard de intrare/ie$ire
110
Prototip int scanf (char *fmt, ...);
Descriere Efect: cite$te de la tastatur' date conform
$irului fmt $i le pune n memorie la adresele
marcate prin trei puncte;
Rezultat: num'rul de coduri de format
prelucrate corect sau EOF n caz de eroare
De exemplu, secven#a urm'toare preia de la
utilizator valoarea variabilei n $i afi$eaz' un mesaj ce
con#ine aceast' valoare.
int n;
printf("Introduceti n:");
scanf("%i", &n); // &n este adresa variabilei
n
printf("Valoarea lui n este %i\n", n);
5.3.1. Codurile de format ale funciei printf
Primul parametru al func#iei printf este un $ir de
caractere alc'tuit din caractere normale, secven#e escape
$i coduri de format. Caracterele normale (exceptnd %) $i
secven#ele escape vor fi afi$ate pe ecran exact a$a cum
apar n $ir. n schimb, fiecare cod de format va fi nlocuit
cu valoarea parametrului corespunz'tor lui: primul cod de
format folose$te valoarea celui de-al doilea parametru al
func#iei, al doilea cod de format folose$te valoarea celui
de-al treilea argument al func#iei, $.a.m.d. Un cod de
format este alc'tuit (n ordine de la stnga la dreapta) din:
caracterul %, care marcheaz' nceputul codului de
format (dac' vrem s' afi$'m un %, atunci trebuie
scris %%);
un caracter de umplere (op#ional) conform cu
Tabel 5.4;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
111
un caracter modificator (op#ional) pentru valori
numerice conform Tabel 5.5;
dimensiunea minim' a cmpului (op#ional);
un punct urmat de precizia de afi$are (op#ional);
un caracter pentru subtipul informa#iei (op#ional)
conform cu Tabel 5.6;
un caracter pentru tipul informa#iei conform cu
Tabel 5.7.
Dimensiunea minim' a cmpului determin'
num'rul minim de caractere care vor fi afi$ate (daca
informa#ia ocup' mai pu#ine caractere, atunci ea va fi
completat' conform caracterului de umplere).
Precizia determin' num'rul de zecimale afi$ate
n cazul valorilor numerice reale, respectiv num'rul
maxim de caractere afi$ate n cazul $irurilor de caractere.
Dimensiunea $i precizia pot fi numere zecimale
pozitive sau caracterul asterisc, caz n care acestea sunt
furnizate n lista parametrilor sub forma unui parametru
ntreg.
Tabel 5.4 Caractere de umplere
Caracter Descriere
spa#iu informa#ia este completat' n partea stng' cu
spa#ii (op#iunea implicit')
0 (zero) informa#ia este completat' n partea stng' cu
zerouri
- (minus) informa#ia este completat' n partea dreapt'
cu spa#ii
Func#ii standard de intrare/ie$ire
112
Tabel 5.5 Caractere modificatori pentru valori
numerice
Caracter Descriere
+ pentru formatele i, d, u, e, E, f, g $i G specific'
afi$area semnului valorilor numerice pozitive
(implicit, semnul este afi$at doar pentru
valorile negative)
# pentru formatul o specific' afi$area prefixului
0
# pentru formatele x $i X specific' afi$area
prefixului 0x, respectiv 0X
# pentru formatele e, E $i f specific' afi$area
punctului zecimal chiar $i pentru numere f'r'
zecimale
# pentru formatele g $i G specific' afi$area
zerourilor nesemnificative de la sfr$itul
num'rului
Tabel 5.6 Caractere pentru subtip folosite n
formatul funciei printf
Caracter Descriere
h pentru formatele d, i, o, x $i X specific'
subtipul short int
h pentru formatul u specific' subtipul short
unsigned int
l pentru formatele d, i, o, x $i X specific'
subtipul long int
l pentru formatul u specific' subtipul long
unsigned int
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
113
Tabel 5.7 Caractere pentru tip folosite n
formatul funciei printf
Caracter Tip
parametru
Format ie$ire
d int num'r ntreg scris n baza 10
i int num'r ntreg scris n baza 10
u unsigned
int
num'r ntreg scris n baza 10
o unsigned
int
num'r ntreg scris n baza 8
x unsigned
int
num'r ntreg scris n baza 16,
cu literele "abcdef"
X unsigned
int
num'r ntreg scris n baza 16,
cu literele "ABCDEF"
f double num'r real scris n baza 10
e double num'r real scris n baza 10 cu
exponent "e"
E double num'r real scris n baza 10 cu
exponent "E"
g double format e sau f (care este mai
scurt)
G double format E sau f (care este mai
scurt)
c int un caracter
s char * un $ir de caractere
p void * un pointer (i.e. o adres' de
memorie)
De exemplu, secven#a urm'toare:
char ch = 'h', *str = "test";
int in = 12;
Func#ii standard de intrare/ie$ire
114
double db = 2.15;
printf("|%d|%+d|%4d|\n",in, in, in);
printf("|%04d|%0*d|\n", in, 9, in);
printf("|%X|%x|%#x|\n", in, in, in);
printf("|%o|%#o|\n", in, in);
printf("|%c|\n", ch);
printf("|%s|%6s|%-6s|%.2s|\n", str, str, str,
str);
printf("|%f|%e|%g|\n", db, db, db);
printf("Adresa variabilei i este %p", &in);
produce urm'torul rezultat:
|12|+12| 12|
|0012|000000012|
|C|c|0xc|
|14|014|
|h|
|test| test|test |te|
|2.150000|2.150000e+000|2.15|
Adresa variabilei i este 0022FF6C
5.3.2. Codurile de format ale funciei scanf
Formatul func#iei scanf este alc'tuit din
caractere de spa#iere (vezi sec#iunea 2.1), caractere
normale $i coduri de format. Caracterele de spa#iere sunt
citite, dar nu sunt memorate, ele fiind interpretate ca
separatori ntre datele de intrare. Caracterele normale
(exceptnd %) vor fi citite, dar nu vor fi memorate. Dac'
se cite$te un caracter diferit de cel a$teptat atunci func#ia
se opre$te din cititul datelor. n locul fiec'rui cod, func#ia
cite$te o valoare de intrare $i o memoreaz' la o adres'
trimis' func#iei ca parametru: primul cod de format
folose$te adresa din al doilea argument al func#iei, al
doilea cod de format folose$te adresa din al treilea
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
115
argument al func#iei, $.a.m.d. Un cod de format este
alc'tuit (n ordine de la stnga la dreapta) din:
caracterul %, care marcheaz' nceputul codului de
format (dac' vrem s' citim un %, atunci trebuie
scris %%);
un caracter asterisc (op#ional) care specific' c'
informa#ia va fi citit', dar nu va fi memorat';
dimensiunea maxim' a cmpului (op#ional);
un caracter pentru subtipul informa#iei (op#ional)
conform cu Tabel 5.8;
un caracter pentru tipul informa#iei conform cu
Tabel 5.9.
Dimensiunea maxim' a cmpului define$te
num'rul maxim de caractere care vor fi citite (daca se
ntlne$te un caracter de spa#iere sau care intr' n
conflict cu formatul curent, atunci citirea opre$te).
n locul caracterului s (folosit pentru citirea unui
$ir de caractere) se poate specifica un $ir format numai
din anumite caractere scriind mul#imea caracterelor
permise ntre paranteze p'trate. Dac' primul caracter din
mul#ime este s'geata n sus (^), atunci va fi acceptat
orice caracter care nu apar#ine mul#imii.
Tabel 5.8 Caractere pentru subtip folosite n
formatul funciei scanf
Caracter Descriere
h pentru formatele d, i, n, o $i x specific'
subtipul short int
h pentru formatul u specific' subtipul short
unsigned int
l pentru formatele d, i, n, o $i x specific'
Func#ii standard de intrare/ie$ire
116
subtipul long int
l pentru formatul u specific' subtipul long
unsigned int
l pentru formatul f specific' tipul double (n loc
de float)
Tabel 5.9 Caractere pentru tip folosite n
formatul funciei scanf
Caracter Tip
parametru
Format intrare
d int* num'r ntreg scris n baza 10
D long int* num'r ntreg scris n baza 10
i int* num'r ntreg scris n baza 8,
10 sau 16
I long int* num'r ntreg scris n baza 8,
10 sau 16
u unsigned
int*
num'r ntreg f'r' semn scris
n baza 10
U unsigned
long*
num'r ntreg f'r' semn scris
n baza 10
o unsigned
int*
num'r ntreg scris n baza 8
O unsigned
long*
num'r ntreg scris n baza 8
x unsigned
int*
num'r ntreg scris n baza 16
X unsigned
long*
num'r ntreg scris n baza 16
f, e, E, g,
G
float* num'r real scris n baza 10
cu sau f'r' exponent
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
117
c char* un caracter (inclusiv
caractere de spa#iere)
s char* un $ir de caractere
n int* nimic (la adresa din
parametru va fi memorat
num'rul de caractere citite
pn' n prezent)
p void** un pointer (rar folosit)
De exemplu, secven#a urm'toare:
char ch, str[30];
int in;
float fl;
double db;
printf("Introduceti date: ");
scanf("%i%f%lf%s%c", &in, &fl, &db, str, &ch);
printf("Valori: %i %f %f %s %c",
in,fl,db,str,ch);
produce rezultatul de mai jos. De remarcat c' n cazul
variabilei str nu s-a folosit operatorul & (deoarece str
este un vector de caractere), iar codul %s a oprit citirea
datelor la primul spa#iu, urm'torul caracter fiind preluat de
codul %c.
Introduceti date: 5 4.23 3.2 test program
5 4.230000 3.200000 test p
5.4. Func#ii cu formatare pentru $iruri de
caractere
Func#ia sprintf func#ioneaz' similar cu func#ia
printf, cu excep#ia c' scrierea datelor se va face ntr-un
$ir de caractere $i nu pe ecran. n mod similar, func#ia
Func#ii standard de intrare/ie$ire
118
sscanf func#ioneaz' ca func#ia scanf, cu excep#ia c'
citirea datelor se va face dintr-un $ir de caractere $i nu de
la tastatur'.
Tabel 5.10 Funcii standard cu formatare
pentru $iruri de caractere
Prototip int sprintf (char* dest, char *fmt,
...);
Descriere Efect: scrie n $irul dest $irul fmt n care
codurile de format sunt nlocuite cu valorile
expresiilor marcate prin trei puncte;
Rezultat: num'rul de caractere scrise sau
EOF n caz de eroare
Prototip int sscanf (char* srs, char *fmt,
...);
Descriere Efect: cite$te din $irul srs date conform
$irului fmt $i le pune n memorie la adresele
marcate prin trei puncte;
Rezultat: num'rul de coduri de format
prelucrate corect sau EOF n caz de eroare
5.5. Exemple
33. Programul urm'tor cite$te de la tastatur' caracter
cu caracter $i afi$eaz' pe ecran doar literele. Programul
se opre$te la citirea primului caracter punct.
#include <stdio.h>
#include <conio.h>
int main()
{
int car;
puts("Introduceti textul:");
do
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
119
{
car = getchar();
if(car >= 'A' && car <= 'Z' ||
car >= 'a' && car <= 'z')
putchar(car);
} while(car != EOF && car != '.');
getch();
}
Introduceti textul:
Limbajul C are 32 de instructiuni. Asta e
bine.
LimbajulCaredeinstructiuni
34. Programul urm'tor cite$te de la tastatur' linie cu
linie $i afi$eaz' pe ecran liniile dup' ce majusculele au
fost transformate n minuscule (folosind func#ia strlwr,
descris' n capitolul 9). Programul se opre$te la citirea
primei linii care ncepe cu un punct.
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main()
{
char mesaj[150];
puts("Introduceti textul:");
while(gets(mesaj) && mesaj[0] != '.')
{
strlwr(mesaj);
puts(mesaj);
}
getch();
}
Introduceti textul:
Limbajul C are doar 32 de instructiuni.
limbajul c are doar 32 de instructiuni.
Asta e bine!
asta e bine!
.gata
35. Programul urm'tor afi$eaz' tabla nmul#irii.
Func#ii standard de intrare/ie$ire
120
#include <stdio.h>
#include <conio.h>
int main()
{
int l,c;
for(l = 1; l<= 10; ++l)
{
for(c = 1; c <= 10; ++ c)
printf("%5d", l*c);
printf("\n");
}
getch();
}
Rezultatul execu#iei este urm'torul:
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100
36. Programul urm'tor afi$eaz' tabela codurilor ASCII.
Programul listeaz' pe fiecare linie, n ordine cresc'toare
coduri ASCII n baza 10, 8 $i 16, $i caracterul asociat
acestora. Dup' 22 de linii, execu#ia se suspend' pn' la
ap'sarea unei tastei. Rezultatul execu#iei acestui
program este similar cu tabelul din Anexa 3 Setul de
caractere ASCII.
#include <stdio.h>
#include <conio.h>
int main()
{
int i;
puts("Cod 10\tCod 8\tCod 16\tCaracter");
for(i=0;i<=255;i++)
{
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
121
printf("%3i\t%#4o\t%#4X\t%c\n", i, i, i,
i);
if(i % 22 == 21)
{
getch();
puts("Cod 10\tCod 8\tCod 16\t
Caracter");
}
}
}
37. Programul urm'tor afi$eaz' o tabel' de
coresponden#' pentru temperaturi n grade Celsius,
Farenheit $i Kelvin.
#include <stdio.h>
#include <conio.h>
int main()
{
float c, k, f;
puts("Celsius\tKelvin\tFarenheit");
for(c=-30;c<=30;c+=10)
{
f = 32 + 9*c/5;
k = c - 273.15;
printf("%g\t%g\t%g\n", c, k, f);
}
getch();
}
Rezultatul programului este urm'torul:
Celsius Kelvin Farenheit
-30 -303.15 -22
-20 -293.15 -4
-10 -283.15 14
0 -273.15 32
10 -263.15 50
20 -253.15 68
30 -243.15 86
Func#ii standard de intrare/ie$ire
122
5.6. Exerci#ii
44. Scrie#i un program C care afi$eaz' valorile
polinomului
2
( ) 2,1 3, 5 8, 2 p x x x + + pentru toate valorile
[ , , 2 ,..., ] n n p n p m + + , unde n, p $i m sunt numere reale
citite de la tastatur'.
45. Scrie#i un program C care cite$te un ntreg zecimal
de cel mult 5 cifre de la tastatura $i l afi$eaz' ncadrat de
2 caractere % astfel: n octal, pe 10 pozi#ii, aliniat la
dreapta, $i n hexazecimal, pe 15 pozi#ii $i aliniat la
stnga.
46. Scrie#i un program C care cite$te dou' numere
hexazecimale separate prin virgul' $i afi$eaz' suma lor
n baza 8 $i 10, separate prin dou' puncte.
47. Scrie#i un program care cite$te de la tastatur' un
num'r natural n $i un $ir de caractere s $i afi$eaz' doar
primele n caractere din s.
48. Scrie#i un program C care cite$te un caracter de la
tastatur' folosind func#ia scanf $i afi$eaz' codul s'u
ASCII n baza 8 $i 10.
49. Scrie#i un program C care afi$eaz' reprezentarea n
baza 2 a unui num'r ntre n, citit de la tastatur'.
50. Scrie#i un program C care cite$te de la tastatur' un
num'r ntreg n ntre 2 $i 8 $i afi$eaz' pe ecran un desen
cu o linie de lungime n, astfel:
|T'T'T'T'T'T'T'T'T'T'T'T'T'T'T'T'T'T'T'T'|
|| ' | ' | ' | ' | ' |
|0 1 2 3 4 |
!________________________________________!
123
6
66.
.. T
TTI
II P
PPU
UUR
RRI
II D
DDE
EE D
DDA
AAT
TTE
EE C
CCO
OOM
MMP
PPU
UUS
SSE
EE
6.1. Masive
Masivele de date sunt tablouri de date de acela$i
tip, standard sau definit de utilizator, dispuse contiguu n
memorie. Un astfel de tablou poate avea mai multe
dimensiuni. Num'rul dimensiunilor tabloului este limitat
doar de memoria calculatorului pe care ruleaz' programul
care folose$te masive de date. Masivul care are o singur'
dimensiune se nume$te vector sau $ir. Masivul care are
dou' dimensiuni se nume$te matrice. Un masiv cu k
dimensiuni se declar' astfel:
tip nume[dim1][dim2][dimk]
unde: tip este tipul datelor din masiv, nume este numele
masivului, iar dim1, dim2, ..., dimk sunt expresii constante
a c'ror valori reprezint' num'rul de componente pentru
fiecare dimensiune.
De exemplu, urm'toarea secven#' de program
declar' vectorul v cu 20 de elemente de tip ntreg,
matricea mat cu 5x5 elemente de tip caracter $i masivul
tridimensional masiv cu 3x4x3 elemente de tip real.
int v[20];
Tipuri de date compuse
124
char mat[5][5];
float masiv[3][4][2];
Num'rul total de elemente ale unui masiv cu k
dimensiuni este egal cu dim
1
*dim
2
*...*dim
k
, iar pentru
memorarea unui masiv cu tipul tip $i k dimensiuni sunt
necesari sizeof(tip)*dim
1
*dim
2
*...*dim
k
octe#i. Accesarea
unui element al masivului se face cu construc#ia
nume[i
1
][i
2
][i
n
], unde i
1
, i
2
, , i
n
sunt coordonatele
elementului pe fiecare dintre dimensiuni (0 , ij < dimj,
1,j,k).
Masivele pot fi ini#ializate la declarare astfel:
tip nume[dim1][dim2]...[dimk]={v1, v2, ..., vn};
valorile v
1
, v
2
, ..., v
n
, fiind stocate n masiv n ordine de la
coordonatele mici (0,0,..., 0) la coordonatele mari (dim
1
-1,
dim
2
-1,..., dim
k
-1).
i Pentru a for#a completarea valorilor n anumite
loca#ii ale masivului, acestea trebuie grupate ntre
acolade astfel:
tip nume[dim1][dim2]...[dimk]={{v1,...,vp},
{vp+1,...}, {...,vn}};
i Dimensiunea cea mai important' (dim
1
) poate s'
lipseasc', ea fiind determinat' automat din num'rul
valorilor de ini#ializare, astfel:
tip nume[][dim2]...[dimk]= {v1, v2, ..., vn};
Dac' num'rul de valori folosite la ini#ializare
dep'$e$te num'rul de elemente din masiv atunci
compilatorul genereaz' un mesaj de eroare. Dac'
num'rul de valori folosite la ini#ializare este mai mic dect
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
125
num'rul de elemente din masiv, atunci restul valorilor
sunt ini#ializate cu 0.
De exemplu, prin declara#ia
int v[4]={-1,2,4,0};
sunt ini#ializate componentele vectorului cu identificatorul
vector cu valori ntregi astfel: v[0]=-1, v[1]=2, v[2]=4.
Echivalent, se poate folosi declara#ia:
int v[]={-1,2,4,0};
sau
int v[4]={-1,2,4};
6.2. Structuri
Spre deosebire de masive, care grupeaz' sub un
singur nume, date de acela$i tip, structura este un tip nou
de dat' care grupeaz' date de tipuri diferite. Un element
al unei structuri se nume$te membru sau cmp al
structurii. Un membru al unei structuri poate fi folosit fie
ca un singur tip de dat', fie ca o dat' individual'. Fiecare
membru al unei structuri are un tip predefinit sau definit
de utilizator, n particular putnd fi tot o structur'. O
structur' se declar' cu ajutorul cuvntului cheie struct,
astfel:
struct tipstructura
{
tip1 memebru1;
tip2 memebru2;
...
tipn memebrun;
};
Tipuri de date compuse
126
Prin aceast' declara#ie este definit un $ablon, un
tip nou de dat' cu numele tipstructura care are n
membri, fiecare membrui avnd tipul tipi. n particular,
tipi poate fi de o structur', caz n care se spune c'
structurile cu tipurile tipstructura $i tipi sunt
imbricate.
La compilare dup' o astfel de declara#ie nu se
rezerv' memorie deoarece este declarat un tip de dat'.
Declararea unor variabile de tipul tipstructura se
poate face ca pentru orice tip predefinit, astfel:
tipstructura variabila1, variabila2,,
variabilak;
Efectul ob#inut prin declara#iile de mai sus se
poate ob#ine cu declara#ia:
struct tipstructura
{
tip1 memebru1;
tip2 memebru2;
...
tipn memebrun;
} variabila1, variabila2,, variabilak;
Dac' tipstructura este absent, se spune c' a
fost definit' o structur' anonim'. n acest caz, cel pu#in o
variabil' trebuie s' fie prezent'.
Accesarea membrului membrui al variabilei
variabilap se face cu ajutorul operatorului de selec#ie
direct' . astfel:
variabilap.memebrui = valoare;
variabila = variabilap.memebrui;
De exemplu, declara#iile urm'toare:
struct student
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
127
{
char nume[20];
char prenume[20];
int nota;
};
declar' tipul de dat' student care are urm'torii membri:
vectorii de caractere nume $i prenume, $i variabila de tip
ntreg nota. Declara#ia:
student studenti[25];
declar' vectorul studenti cu 25 de elemente de tip
student. Expresia studenti[i].nota face referire la
membrul nota al componentei de rang i a vectorului
studenti.
Declara#iile urm'toare:
struct grupastudiu
{
char disciplina[50];
student studenti[25];
};
grupastudiu anstudiu[5];
definesc tipul structur' grupastudiu $i vectorul
anstudiu cu 5 de componente de tipul grupastudiu.
Expresia:
anstudiu[2].studenti[3].nota = 10;
atribuie valoarea 10 notei celui de-al patrulea student din
a treia grupa din anul de studiu.
Structurile se pot ini#ializa la declarare
asem'n'tor cu ini#ializarea masivelor. De exemplu,
instruc#iunea urm'toare:
student std={Ionescu,Dan,9};
Tipuri de date compuse
128
declar' $i ini#ializeaz' variabila std corespunz'toare
studentului Ionescu Dan, care are nota 9.
La asignarea unei variabile de tip structur', se
realizeaz' o copie a structurii surs' n variabila destina#ie.
De asemenea, structurile pot fi folosite ca parametri
pentru func#ii. n cazul n care tipul unui parametru este o
structur', la apelul func#iei se creeaz' o copie a structurii
care va fi folosit' de func#ie. Dac' parametrul este un
pointer la o structur', func#ia are acces direct la zona de
memorie a structurii folosind operatorul ->.
De exemplu, func#ia afiseaza prime$te ca
parametru un pointer la o structur' student $i afi$eaz'
informa#ii despre studentul respectiv:
void afiseaza(struct student *p)
{
printf("%s %s %d\n", p->nume, p->prenume, p-
>nota);
}
n acest caz, referirea la cmpurile structurii se
realizeaz' cu ajutorul operatorului de selec#ie indirect' -
> prin construc#ia p->nota, sau cu construc#ia
(*p).nota. Apelul func#iei se realizeaz' astfel:
f(&std);
f(&anstudiu[2].studenti[3]);
6.3. Uniuni
Uniunile ofer' utilizatorului posibilitatea refolosirii
aceleia$i zone de memorie pentru a memora date de
tipuri diferite la momente diferite de timp. Astfel, o zon'
de memorie poate memora date de tip int, pentru ca
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
129
ulterior aceea$i zon' s' memoreze date de tip float,
ceea ce nu are loc n cazul structurilor. Scopul acestor
reutiliz'ri ale memoriei este economisirea acesteia.
Uniunile se declar' $i se folosesc la fel ca
structurile, deosebirea constnd n nlocuirea cuvntului
cheie struct cu cuvntul cheie union. n cazul
structurilor se rezerv' pentru fiecare membru cte o zon'
de memorie de dimensiune corespunz'toare. n cazul
uniunilor se rezerv' o singur' zon' de memorie, de
dimensiune egal' cu valoarea maxim' a dimensiunilor
necesare membrilor s'i. n cazul uniunilor utilizatorul
trebuie s' monitorizeze tipurile de date aflate n memorie,
n fiecare moment al execu#iei programului.
n declara#ia:
union anstudiu
{
char cod;
int numar;
} an;
este declarat tipul de dat' anstudiu de tip uniune $i
variabila an de acest tip.
6.4. Cmpuri
Un cmp este un $ir de bi#i definit ca membru al
unei structuri. Un cmp se declar' ca un membru de tip
unsigned, numele fiind urmat de un ntreg care
precizeaz' dimensiunea n bi#i a cmpului respectiv. n
memorie cmpurile sunt grupate, n ordinea declar'rii lor,
de la dreapta spre stnga. Forma general' de declarare a
unor cmpuri este:
Tipuri de date compuse
130
struct tipstructura
{
...
unsigned camp1:dim1;
unsigned camp2:dim2;
...
} identificator;

n care campi este numele cmpului i care ocup' dimi
bi#i. Nici un cmp nu poate avea o dimensiune mai mare
dect lungimea unui cuvnt calculator (32 bi#i). Nu se pot
defini masive de cmpuri. Operatorul unar adres' & nu
poate avea ca operand un cmp.
Prin declara#ia:
struct
{
unsigned bitii01:2;
unsigned bitii25:4;
unsigned bitii68:3;
} campuri;
este definit' structura cmpuri cu cmpurile de bi#i
bitii01 (2 bi#i), bitii25 (4 bi#i) $i bitii68 (3 bi#i).
6.5. Exemple
38. Programul urm'tor cite$te un num'r ntreg n $i dac'
1 7 n , atunci afi$eaz' numele zilei corespunz'toare
din s'pt'mn', altfel afi$eaz' "Eroare".
#include <stdio.h>
#include <conio.h>
int main()
{
int n;
char *zile[] = {"Eroare", "Luni", "Marti",
"Miercuri", "Joi", "Vineri", "Sambata",
"Duminica"};
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
131
printf("Introduceti n:");
scanf("%i", &n);
if(n>=1 && n<=7)
printf(zile[n]);
else
printf(zile[0]);
getch();
}
39. Urm'torul program determin' valoarea minim' $i
pozi#ia sa ntr-un vector de numere reale:
#include <stdio.h>
#include <conio.h>
int main()
{
int i,n,pmin;
float v[100];
printf("Introduceti numarul de termeni:");
scanf("%d",&n);
printf("Introduceti componentele:\n");
for(i=0; i<n; i++)
{
printf("v[%d]=", i);
scanf("%f",&v[i]);
}
for(pmin=0,i=1; i<n; i++)
if(v[pmin]>v[i])
pmin = i;
printf("Minimul este v[%d]=%f\n", pmin,
v[pmin]);
getch();
}
Rularea programului genereaz' urm'toarele
rezultate:
Introduceti numarul de termeni: 5
Introduceti componentele:
v[0]= 23.1
v[1]= -2.3
v[2]= 4.5
v[3]= -11.2
v[4]= 9.8
Tipuri de date compuse
132
Minimul este v[3] = -11.200000
40. Urm'torul program determin' suma componentelor
unui vector de numere ntregi:
#include <stdio.h>
#include <conio.h>
int main()
{
int i,n,suma;
int v[100];
printf("Introduceti numarul de termeni:");
scanf("%d",&n);
printf("Introduceti componentele:\n");
for(i=0; i<n; i++)
{
printf("v[%d]=", i);
scanf("%d",&v[i]);
}
for(suma=0, i=0; i<n; i++)
suma += v[i];
printf("Suma este %d\n", suma);
getch();
}
Rularea programului genereaz' urm'toarele
rezultate:
Introduceti numarul de termeni: 5
Introduceti componentele:
v[0]= 23
v[1]= -20
v[2]= 4
v[3]= -11
v[4]= 9
Suma este 5
41. n programul urm'tor se cite$te un num'r natural
*
, 99 n N n $i vectorii ( )
0 1 1
, , ,
n
a a a a

K ,
( )
0 1 1
, , ,
n
b b b b

K , fiecare cu n componente numere reale
$i se genereaz' vectorul ( )
1 2 0 0 1 1
, , , , , , ,
n n n
c b b b a a a

K K .
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
133
// Generare vector
#include "stdio.h"
#include "conio.h"
int main()
{
float a[100],b[100],c[100];
int i,j,n;
printf(" Numar componente ");
scanf("%d",&n);
if(n>0 && n<=99)
{
printf(" Componentele vectorului a \n");
for(i=0;i<n;i++)
{
printf(" a[%d] = ",i);
scanf("%f",&a[i]);
}
printf(" Componentele vectorului b \n");
for(i=0;i<n;i++)
{
printf(" b[%d] = ",i);
scanf("%f",&b[i]);
}
for(i=n-1;i>=0;i--)
c[n-i-1]=b[i];
for(i=0;i<n;i++)
c[n+i]=a[i];
printf(" Vectorul c = ( ");
for(i=0;i<2*n;i++)
printf(" %f ",c[i]);
printf(" )\n");
}
else
printf(" %d nu este in domeniu \n",n);
getch();
}
Un exemplu de rulare este:
Numar componente 2
Componentele vectorului a
a[0] = 1
a[1] = 2
Componentele vectorului b
Tipuri de date compuse
134
b[0] = 3
b[1] = 4
Vectorul c = ( 4.000000 3.000000 1.000000
2.000000 )
42. Programul urm'tor cite$te un caracter, un $ir de
caractere $i determin' num'rul de apari#ii (dac' exist')
ale caracterului citit n $ir.
#include "stdio.h"
#include "conio.h"
int main()
{
int n=0,i=0;
char s[50],c;
puts(" Sirul ");
gets(s);
puts(" Caracterul ");
scanf("%c",&c);
while(s[i]!='\0')
{
if(s[i]==c)
n++;
i++;
}
if(n==0)
printf("Sirul %s nu contine caracterul %c
\n",s,c);
else
printf(" Numarul de caractere %c din sirul
%s este egal cu %d \n",c,s,n);
getch();
}
Un exemplu de rulare este:
Sirul
frecventa caracter in sir
Caracterul
#
Sirul frecventa caracter in sir nu contine
caracterul #

Sirul
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
135
frecventa caracter in sir
Caracterul
e
Numarul de caractere e din sirul frecventa
caracter in sir este egal cu 3
43. Urm'torul program determin' num'rul de cuvinte
dintr-un $ir de caractere. Un cuvnt este $irul de
caractere cuprins ntre unul din urm'torii separatori:
spa#iu, virgul', punct virgul'.
#include "stdio.h"
#include "conio.h"
int main()
{
char sir[100];
int nc,i;
puts(" Sirul :");
gets(sir);
i=0;
if(sir[i]==' ' || sir[i]==',' ||
sir[i]==';')
nc=-1;
else nc=0;
while(sir[i]!='\0')
{
if(sir[i]==' '||sir[i]==','||sir[i]==';')
{
nc++;
i++;
while(sir[i]==' ' || sir[i]==',' ||
sir[i]==';')
i++;
}
i++;
}
nc++;
printf(" Numar cuvinte %d \n",nc);
getch();
}
Un exemplu de rulare este:
Tipuri de date compuse
136
Sirul :
numar; de , cuvinte;;; din , sir
Numar cuvinte 5
44. Urm'torul program determin' $i sorteaz'
descresc'tor frecven#ele de apari#ie ale tuturor
caracterelor dintr-un $ir de caractere.
// Frecventele sortate descrescator ale
caracterelor
#include "stdio.h"
#include "conio.h"
int main()
{
char sir[100],c[100],smartor[100],auxc;
int nap[100],i,j,k,ncardist,auxi;
puts(" Sirul : ");
gets(sir);
for(i=0;sir[i]!='\0';i++)
smartor[i]=sir[i];
i=0;
while(sir[i]!='\0')
{
nap[i]=1;
c[i]=sir[i];
j=i+1;
while(sir[j]!='\0')
{
if(sir[i]==sir[j])
{
for(k=j;sir[k]!='\0';k++)
sir[k]=sir[k+1];
sir[k]='\0';
nap[i]++;
}
else
j++;
}
i++;
}
ncardist=i;
printf(" Frecventele nesortate ale
caracterelor\n\n In sirul %s \n",smartor);
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
137
for(k=0;k<ncardist;k++)
printf(" Caracterul %c apare de %d ori\n",
c[k],nap[k]);
getch();
printf(" Frecventele sortate descrescator
ale caracterelor\n\n In sirul %s \n",smartor);
for(i=0;i<ncardist;i++)
for(j=i+1;j<ncardist;j++)
if(nap[i]<=nap[j])
{
auxc=c[i];
c[i]=c[j];
c[j]=auxc;
auxi=nap[i];
nap[i]=nap[j];
nap[j]=auxi;
}
for(k=0;k<ncardist;k++)
printf(" Caracterul %c apare de %d ori\n",
c[k],nap[k]);
getch();
}
Un exemplu de rulare este:
Sirul :
determinarea frecventelor
Frecventele nesortate ale caracterelor

In sirul determinarea frecventelor
Caracterul d apare de 1 ori
Caracterul e apare de 6 ori
Caracterul t apare de 2 ori
Caracterul r apare de 4 ori
Caracterul m apare de 1 ori
Caracterul i apare de 1 ori
Caracterul n apare de 2 ori
Caracterul a apare de 2 ori
Caracterul apare de 1 ori
Caracterul f apare de 1 ori
Caracterul c apare de 1 ori
Caracterul v apare de 1 ori
Caracterul l apare de 1 ori
Caracterul o apare de 1 ori
Tipuri de date compuse
138
Frecventele sortate descrescator ale
caracterelor

In sirul determinarea frecventelor
Caracterul e apare de 6 ori
Caracterul r apare de 4 ori
Caracterul a apare de 2 ori
Caracterul n apare de 2 ori
Caracterul t apare de 2 ori
Caracterul o apare de 1 ori
Caracterul l apare de 1 ori
Caracterul v apare de 1 ori
Caracterul c apare de 1 ori
Caracterul f apare de 1 ori
Caracterul apare de 1 ori
Caracterul i apare de 1 ori
Caracterul m apare de 1 ori
Caracterul d apare de 1 ori
45. Urm'torul program determin' r'd'cinile ntregi ale
polinoamelor cu coeficien#i ntregi. Fie [ ] P Z X ,
*
gradP n N , ( )
1
1 1 0
n n
n n
P X a X a X a X a

+ + + + L ,
i
a Z , ( ) 0,1,..., i n , 0
n
a . Este cunoscut faptul c'
r'd'cinile ntregi ale polinomului, dac' exist', se g'sesc
printre divizorii termenului liber
0
a . Programul are ca date
de intrare gradul n $i coeficien#ii
0 1
, ,...,
n
a a a ai polinomului
$i ca date de ie$ire r'd'cinile sale ntregi. Se determin'
to#i divizorii termenului liber $i pentru fiecare din ei se
calculeaz' valoarea polinomului. Dac' aceast' valoare
este nul', atunci divizorul respectiv este r'd'cin'
ntreag' a polinomului.
#include <stdio.h>
#include <conio.h>
int main()
{
int coef[10], i, j, n, m;
printf("Gradul polinomului:");
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
139
scanf("%d", &n);
for (i=0; i<=n; ++i)
{
printf("Coeficientul %d: ", i);
scanf("%d", &coef[i]);
}
m = coef[0]<0 ? -coef[0] : coef[0];
for (i=-m; i<=m; ++i)
if(i==0 || m%i == 0)
{
long valoare = 0, putere = 1;
for(j = 0; j<=n; ++j)
{
valoare += coef[j] * putere;
putere *= i;
}
if(valoare == 0)
printf("%d este radacina\n", i);
}
getch();
}
Pentru ( )
3 2
6 11 6 P X X X X + , care are
r'd'cinile ntregi
1
1 x ,
2
2 x $i
3
3 x , programul
furnizeaz' rezultatele:
Gradul polinomului:3
Coeficientul 0: -6
Coeficientul 1: 11
Coeficientul 2: -6
Coeficientul 3: 1
1 este radacina
2 este radacina
3 este radacina
Pentru ( )
3 2
2 2 P X X X X + , care are
r'd'cinile ntregi
1
1 x ,
2
1 x $i
3
2 x , programul
furnizeaz' rezultatele:
Gradul polinomului:3
Coeficientul 0: 2
Tipuri de date compuse
140
Coeficientul 1: -1
Coeficientul 2: -2
Coeficientul 3: 1
-1 este radacina
1 este radacina
2 este radacina
46. Urm'torul program sorteaz' cresc'tor
componentele unui vector de numere reale prin metoda
bulelor:
#include <stdio.h>
#include <conio.h>
int main()
{
int i,j,n,pmin;
float v[100], aux;
printf("Introduceti numarul de termeni:");
scanf("%d",&n);
printf("Introduceti componentele:\n");
for(i=0; i<n; i++)
{
printf("v[%d]=",i);
scanf("%f",&v[i]);
}
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
if(v[i]>v[j])
{
aux=v[i];
v[i]=v[j];
v[j]=aux;
}
printf("Vectorul sortat crescator este:\n");
for(i=0;i<n;i++)
printf("a[%d] = %f\n",i,v[i]);
getch();
}
Rularea programului genereaz' urm'toarele
rezultate:
Introduceti numarul de termeni: 5
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
141
Introduceti componentele:
v[0]= 23.1
v[1]= -2.3
v[2]= 4.5
v[3]= -11.2
v[4]= 9.8
Sirul sortat crescator este :
v[0] = -11.200000
v[1] = -2.300000
v[2] = 4.500000
v[3] = 9.800000
v[4] = 23.100000
47. Urm'torul program calculeaz' produsul a dou'
matrice de numere reale:
#include <stdio.h>
#include <conio.h>
int main()
{
float a[20][20],b[20][20],c[20][20];
int m,n,p,q,i,j,k;
printf("Numarul de linii al matricei A:");
scanf("%d",&m);
printf("Numarul de coloane al matricei A:");
scanf("%d",&n);
printf("Numarul de linii al matricei B:");
scanf("%d",&p);
printf("Numarul de coloane al matricei B:");
scanf("%d",&q);
if(n==p)
{
printf("Se calculeaza produsul A*B\n");
for(i=0;i<m;i++)
for(j=0;j<n;j++)
{
printf("a[%d][%d]=",i,j);
scanf("%f",&a[i][j]);
}
for(i=0;i<p;i++)
for(j=0;j<q;j++)
{
printf("b[%d][%d]=",i,j);
Tipuri de date compuse
142
scanf("%f",&b[i][j]);
}
for(i=0;i<m;i++)
for(j=0;j<q;j++)
{
c[i][j]=0;
for(k=0;k<n;k++)
c[i][j] += a[i][k]*b[k][j];
printf("c[%d][%d]=%f\n",i,j,c[i][j]);
}
} else
{
printf("Produsul A*B nu este definit\n");
}
getch();
}
De exemplu, fie matricele
1 2
3 4
A
_


,
$i
1 1 2
2 0 1
B
_

,
. Produsul este
1 2
3 4
A B
_


,
1 1 2 5 1 4
2 0 1 11 3 10
_ _



, ,
.
Numarul de linii a matricei A: 2
Numarul de coloane a matricei A: 2
Numarul de linii a matricei B: 2
Numarul de coloane a matricei B: 3
Se calculeaza produsul A*B
a[0][0] = 1
a[0][1] = 2
a[1][0] = 3
a[1][1] = 4
b[0][0] = -1
b[0][1] = 1
b[0][2] = 2
b[1][0] = -2
b[1][1] = 0
b[1][2] = 1
c[0][0]= -5.000000
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
143
c[0][1]= 1.000000
c[0][2]= 4.000000
c[1][0]= -11.000000
c[1][1]= 3.000000
c[1][2]= 10.000000
48. Urm'torul program reprezint' un dic#ionar romn-
englez-francez "de juc'rie". Programul folose$te func#ii
pentru $iruri de caractere descrise n capitolul 9.
#include <stdio.h>
#include <string.h>
#include <conio.h>
char* cuvinte[][3] = {
"masa", "table", "table",
"scaun", "chair", "chaise",
"mancare", "food", "nourriture",
"apa", "water", "eau",
"om", "human", "humain",
NULL, NULL, NULL
};

int main(void)
{
char cuv_rom[80];
int i;

printf("Introduceti cuvantul romana:");
gets(cuv_rom);
/* cautam cuvantul in dictionar */
for(i = 0; cuvinte[i][0] != NULL; ++i)
if(!strcmp(cuv_rom, cuvinte[i][0]))
{
printf("Engleza: %s\nFranceza: %s\n",
cuvinte[i][1], cuvinte[i][2]);
break;
}
if(cuvinte[i][0] == NULL)
printf("Cuvant necunoscut.\n");
getch();
}
Tipuri de date compuse
144
49. Relu'm exemplul dic#ionarului, dar de aceast' dat'
cuvintele sunt memorate n variabile de tip structur'.
#include <stdio.h>
#include <string.h>
#include <conio.h>
struct cuvant
{
char *romana, *engleza, *franceza;
} cuvinte[] =
{
{"masa", "table", "table"},
{"scaun", "chair", "chaise"},
{"mancare", "food", "nourriture"},
{"apa", "water", "eau"},
{"om", "human", "humain"},
NULL, NULL, NULL
};

int main(void)
{
char cuv_rom[80];
int i;

printf("Introduceti cuvantul romana:");
gets(cuv_rom);
/* cautam cuvantul in dictionar */
for(i = 0; cuvinte[i].romana != NULL; ++i)
if(!strcmp(cuv_rom, cuvinte[i].romana))
{
printf("Engleza: %s\nFranceza: %s\n",
cuvinte[i].engleza, cuvinte[i].franceza);
break;
}
if(cuvinte[i].romana == NULL)
printf("Cuvant necunoscut.\n");
getch();
}
50. Exemplu urm'tor cite$te informa#iile unei grupe de
studen#i, le sorteaz' descresc'tor dup' not' $i afi$eaz'
rezultatele.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
145
#include <stdio.h>
#include <conio.h>
int main()
{
struct student
{
char nume[20];
char prenume[20];
int nota;
} student[25], aux;
int i,j,n;
printf("Numar studenti:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("Nume si prenume student %d:",
i+1);
scanf("%s%s",student[i].nume,
student[i].prenume);
printf("Nota studentului %s %s:",
student[i].nume, student[i].prenume);
scanf("%d",&student[i].nota);
}

for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
if(student[i].nota < student[j].nota)
{
aux=student[i];
student[i]=student[j];
student[j]=aux;
}

printf("Rezultatele grupei:\n");
for(i=0;i<n;i++)
printf("%s %s\t%d\n", student[i].nume,
student[i].prenume, student[i].nota);
getch();
}
Rularea programului furnizeaz' urm'toarele
rezultate:
Tipuri de date compuse
146
Numar studenti 5
Nume si prenume student 1 Ion Dan
Nota studentului Ion Dan 8
Nume si prenume student 2 Ilie Victor
Nota studentului Ilie Victor 7
Nume si prenume student 3 Ionescu Vlad
Nota studentului Ionescu Vlad 6
Nume si prenume student 4 Popescu Ion
Nota studentului Popescu Ion 9
Nume si prenume student 5 Dima Florin
Nota studentului Dima Florin 10
Rezultatele grupei:
Ionescu Vlad 6
Ilie Victor 7
Ion Dan 8
Popescu Ion 9
Dima Florin 10
51. Presupunem c' dorim s' prelucr'm o mul#ime de
puncte din plan. Despre fiecare punct ne intereseaz'
numele $i coordonatele acestuia. n final afi$'m distan#ele
dintre oricare dou' puncte. Vom defini o structur' de date
care reprezint' informa#iile despre un punct din plan.
#include <stdio.h>
#include <math.h>
#include <conio.h>
struct Punct
{
float x; // coordonata x
float y; // coordonata y
char nume[20]; // numele
};
int main()
{
struct Punct pt[10];// maxim 10 de puncte
int i, j, n; // numarul real de puncte
printf("Numarul de puncte: ");
scanf("%d", &n);
for(i = 0; i<n; ++i)
{
printf("Punctul %d.\n", i);
printf("\tNume: ");
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
147
scanf("%s", pt[i].nume);
printf("\tCoordonata pe axa Ox: ");
scanf("%d", &pt[i].x);
printf("\tCoordonata pe axa Oy: ");
scanf("%d", &pt[i].y);
}
for(i=0; i<n; ++i)
for(j=0; j<n; ++j)
printf("Distanta de la %s la %s este
%f.\n", pt[i].nume, pt[j].nume,
sqrt(pt[i].x*pt[j].x + pt[i].y*pt[j].y));
getch();
}
6.6. Exerci#ii
51. Scrie#i un program C care afi$eaz' suma
elementelor pare $i produsul elementelor impare dintr-un
vector de numere reale.
52. Scrie#i un program C care afi$eaz' pozi#ia primei
apari#ii a unui num'r m ntr-un vector de numere reale.
53. Scrie#i un program C care afi$eaz' produsul scalar
a doi vectori de numere reale.
54. Scrie#i un program C care afi$eaz' suma a doi
vectori de numere reale.
55. Scrie#i un program C care afi$eaz' suma a dou'
matrice de numere reale.
56. Scrie#i un program C care cite$te un num'r natural
*
, 99 n N n $i vectorii ( )
0 1 1
, , ,
n
a a a a

K ,
( )
0 1 1
, , ,
n
b b b b

K , fiecare cu n componente numere reale
$i se genereaz' vectorul ( )
0 1 1 0 1 1
, , , , , , ,
n n
c b b b a a a

K K .
57. Scrie#i un program C care cite$te un num'r natural
*
, 99 n N n $i vectorii ( )
0 1 1
, , ,
n
a a a a

K ,
Tipuri de date compuse
148
( )
0 1 1
, , ,
n
b b b b

K , fiecare cu n componente numere reale
$i se genereaz' vectorul ( )
0 0 1 1 1 1
, , , , , ,
n n
c b a b a b a

K .
58. Scrie#i un program C care simuleaz' evolu#ia unei
popula#ii de viru$i. Ace$ti se afl' n anumite noduri ale
unei re#ele cu dimensiune n x n. Un virus tr'ie$te dac'
are 2 sau 3 vecini, altfel moare (sufocat sau de
singur'tate). ntr-un nod liber cu 2 sau 3 vecini, se na$te
un virus.
59. Scrie#i un program C care gestioneaz' un vector cu
informa#ii despre un angajat. Informa#iile trebuie
memorate ntr-o structur'. Programul trebuie s' permit'
ad'ugarea $i $tergerea de elemente din vector.
149
7
77.
.. F
FFU
UUN
NNC
CC)
))I
III
II
Pentru scrierea unor programe de complexitate
cel pu#in medie, exist' posibilitatea organiz'rii unor date
$i a unor ac#iuni asupra lor, ntr-o entitate independent',
numit' func#ie. Limbajul C pune la dispozi#ia utilizatorului
diverse func#ii predefinite, numite func#ii standard.
Utilizatorul poate s' defineasc' $i s' utilizeze propriile
sale func#ii, numite func#ii utilizator.
Exist' o func#ie standard, principal', func#ia
main(), apelat' de sistemul de operare la nceputul
execu#iei oric'rui program. Func#iile apelate pot comunica
cu func#iile apelante prin intermediul parametrilor.
7.1. Declararea $i definirea func#iilor
Pentru a fi utilizat' ntr-un program C, o func#ie
trebuie nti declarat' ($i ulterior definit'). O func#ie se
declar' pentru ca tipul ei, precum $i tipul $i num'rul
argumentelor sale s' fie cunoscute n vederea utiliz'rii ei
viitoare de c'tre alte func#ii. O func#ie se define$te
specificnd tipul $i numele ei, tipul $i numele
Func#ii
150
argumentelor sale, precum $i corpul func#iei (compus din
declara#ii $i instruc#iuni).
i Argumentele unei func#ii precizate la definirea ei se
numesc parametri formali, n timp ce argumentele
precizate la apelul ei se numesc parametri actuali.
Sintaxa declara#iei unei func#ii este:
tip identificator(lista parametri formali)
{
declaraii #i instruciuni
}
unde
tip identificator(lista parametri formali)
se nume$te antet al func#iei, iar restul reprezint' corpul
func#iei. Elementul tip reprezint' tipul valorii ntoarse
prin apelul func#iei, iar identificator este numele
func#iei. Pentru func#iile care nu returneaz' nici o valoare,
tipul func#iei este void. Pentru fiecare parametru din
lista parametri formali trebuie specificat tipul $i
numele. Lista parametrilor formali poate s' fie $i vid', caz
n care poate fi nlocuit' cu cuvntul void.
Corpul func#iei se execut' pn' la executarea
ultimei instruc#iuni sau pn' la executarea instruc#iunii
return. Dac' func#ia returneaz' o valoare atunci se
folose$te forma
return expresie;
a instruc#iunii return. Prin executarea acestei instruc#iuni
se evalueaz' expresia, se atribuie func#iei valoarea
expresiei $i se ncheie execu#ia func#iei. Tipul expresiei
din instruc#iunea return trebuie s' fie compatibil cu tipul
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
151
func#iei. Dac' func#ia nu returneaz' valori, instruc#iunea
return poate s' lipseasc' sau se folose$te forma
return;
i n limbajul C nu este admis' definirea unei func#ii n
cadrul altei func#ii $i nu snt permise salturi cu
instruc#iunea goto n afara func#iei.
Dac' un parametru formal este un masiv, acesta
poate fi declarat f'r' a indica valoarea maxim' a primei
dimensiuni. Valorile maxime ale celorlalte dimensiuni
trebuie scrise. Urm'toarele prototipuri con#in parametrul
formal vector care este un masiv unidimensional (vector):
int f(int vector[]);
int f(int vector[50]);
Prototipuri de mai jos con#in parametrul formal
masiv care este un masiv tridimensional:
int f(int masiv[][50][50]);
int f(int masiv[50][50][50]);
7.1.1. Prototipul funciilor
O func#ie poate fi folosit' nainte de a fi definit'
dac' ea a fost declarat'. Declararea se realizeaz' prin
scrierea antetului func#iei urmat de caracterul ';'
(construc#ie denumit' prototip), astfel:
tip identificator(lista parametri formali);
Prototipul unei func#ii informeaz' compilatorul
despre tipul valorii pe care o va returna func#ia $i despre
tipurile tuturor parametrilor. Numele parametrilor pot lipsi,
fiind suficient' specificarea tipurilor lor. Prototipul trebuie
Func#ii
152
inserat n program naintea primului apel al func#iei. De
exemplu, urm'toarele prototipuri sunt identice $i corecte:
int functie(int param1, float param2, char
param3);
int functie(int, float, char);
7.1.2. Transferul parametrilor
Parametrii func#iilor se pot transmite prin valoare,
prin referin#' $i prin intermediul variabilelor globale. La
transmiterea parametrilor prin valoare, valorile din func#ia
apelant' sunt copiate n parametrii actuali ai func#iei, $i
nu pot fi modificate de c'tre func#ia apelat' deoarece
aceasta lucreaz' cu copii ale lor.
n cazul transmiterii parametrilor prin referin#'
(sau prin pointeri) func#ia apelant' furnizeaz' func#iei
apelate adresa zonei de memorie unde sunt p'strate
datele. Func#ia apelat' poate modifica aceste date
accesnd direct zona respectiv' de memorie.
O alt' metode de transfer al parametrilor este
transmiterea acestora prin variabile globale. Aceast'
metod' se bazeaz' pe faptul c' variabilele globale sunt
accesibile din orice func#ie.
7.2. Apelul func#iilor
Apelul unei func#ii se face prin scrierea numelui
acesteia urmat de parametrii actuali ai func#iei scri$i ntre
paranteze rotunde $i separa#i prin virgule. Parametrii
actuali trebuie s' corespund' cu cei formali prin ordine,
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
153
tip $i num'r. O func#ie se poate apela recursiv din alt'
func#ie sau direct, chiar din interiorul ei.
Dac' func#ia nu are parametri, ntre paranteze nu
se scrie nimic. Valoarea ntoars' de func#ie particip' la
evaluarea valorii finale a expresiei n care apare.
Utilizarea unei func#ii din bibliotec' impune
includerea fi$ierului asociat, cu directiva #include:
#include numebiblioteca.h
sau
#include <numebiblioteca.h>
De exemplu, secven#a:
int f(int x)
{
return x-1;
}
declar' o func#ie care are identificatorul f, un parametru
formal de tip ntreg x, $i care returneaz' o valoare de tip
ntreg. Instruc#iunea return x-1; ntoarce ca valoare a
func#iei valoarea lui x minus 1, deci apelul f(5) va
returna valoarea 4. Transmiterea parametrului este f'cut'
prin valoare. De exemplu:
#include <stdio.h>
#include <conio.h>
int f(int x)
{
return x-1;
}

int main()
{
int x;
printf("Valoarea lui x = ");
scanf("%d",&x);
Func#ii
154
printf("f (%d) = %d \n",x,f(x));
getch();
}
Rularea programului conduce la rezultatele:
Valoarea lui x = 5
f (5) = 4
7.3. Transmiterea parametrilor
n limbajul C exist' dou' posibilit'#i de transfer a
datelor ntre func#ia apelant' $i cea apelat': prin
parametri $i prin variabile globale. Prin utilizarea
variabilelor globale nu se face un transfer propriu-zis, ci
se folosesc n comun anumite zone de memorie partajat'
ntre toate func#iile din program.
7.3.1. Transferul prin parametri
n limbajul C transferul prin parametri se poate
realiza prin valoare $i prin referin#'. n acest transferului
prin valoare, valoarea parametrului este copiat', iar
func#ia apelat' lucreaz' cu aceast' copie. Deci opera#iile
efectuate asupra unui parametru formal transmis prin
valoare (adic' orice parametru care are tip fundamental),
nu modific', la ie$irea din func#ie, parametrul actual
corespunz'tor. n plus, transferul valorii este nso#it de
eventuale conversii de tip, realizate pe baza informa#iilor
despre func#ie de care dispune compilatorul. n concluzie,
parametrii transmi$i prin valoare se pot modifica n corpul
func#iei, dar dup' terminarea apelului func#iei apelate n
func#ia apelant' ace$tia au acelea$i valori pe care le-au
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
155
avut naintea apelului. Din acest motiv, transferul prin
valoare este folosit pentru transmiterea datelor de intrare.
Exemplu urm'tor prezint' o func#ie de calcul a
sumei primelor n numere naturale. Parametrul n este
transmis prin valoare. Func#ia suma are un singur
parametru, k, de tip int, care este parametru de
intrare. Func#ia returneaz' valoarea sumei prin numele
s'u.
#include <stdio.h>
#include <conio.h>
int suma(int k) // parametrul transmis prin
valoare
{
int s = 0,i;
for(i=1;i<=k;i++)
s+=i;
return s;
}

int main()
{
int n;
printf(" Valoarea lui n = ");
scanf("%d",&n);
printf("Suma primelor %d numere naturale
este %d\n", n, suma(n));
getch();
}
Pentru n=10 programul furnizeaz' valoarea 55.
Valoarea lui n = 10
Suma primelor 10 numere naturale este 55
Folosind transferul prin valoare se pot transmite
func#iei numai parametri de intrare. Pentru a transmite
parametri de ie$ire se folose$te transferul prin referin#'
(adic' prin pointeri), adic' se transmit func#iei adrese de
Func#ii
156
variabile. Pointerii sunt subiectul capitolului 8, dar, pe
scurt, antetul unei func#ii care folose$te transferul de
parametri de tip referin#' este (observa#i folosirea
caracterului asterisc nainte de numele variabilei):
tip identificator(, tip *variabila,)
Parametrii transmi$i prin referin#' se pot modifica
n corpul func#iei, iar dup' terminarea apelului func#iei
ace$tia au valorile primite n timpul execu#iei func#iei
apelate. n acest caz, func#ia prime$te ca parametru
adresa zonei de memorie unde se g'sesc datele $i poate
s' le actualizeaz' pe acestea modificnd con#inutul zonei
de memorie.
Relu'm exemplul anterior. Acum, func#ia suma
are un parametru formal de intrare k $i un parametru
formal de ie$ire s, care este un pointer la tipul int.
#include <stdio.h>
#include <conio.h>
// Parametrul n se transmite prin valoare
// Parametrul s se transmite prin adresa
int suma(int k,int *s)
{
int sum = 0,i;
for(i=1;i<=k;i++)
sum+=i;
*s=sum;
}

int main()
{
int n,sum;
printf("Valoarea lui n = ");
scanf("%d",&n);
// Apelul functiei
suma(n,&sum); // &sum inseamna adresa lui
sum
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
157
printf("Suma primelor %d numere naturale
este %d\n", n, sum);
getch();
}
Programul urm'tor cite$te valorile unor variabile a
$i b $i apeleaz' func#ia tipar. Aceasta prime$te prin
referin#' variabilele a $i b, modific' valorile de la
adresele lor $i tip're$te noile valori. Dup' apelul func#iei
tipar, n func#ia main se tip'resc din nou valorile celor
dou' variabile.
#include <stdio.h>
#include <conio.h>
void tipar(int *a, int *b)
{
*a=*a+3;
*b=*b+4;
printf("In tipar:\n");
printf("a = %d \n b = %d \n",*a,*b);
}

int main()
{
int a,b;
printf("Valoarea lui a : ");
scanf("%d",&a);
printf("Valoarea lui b : ");
scanf("%d",&b);
tipar(&a,&b);
printf("Valorile dupa apelul functiei
sunt:\n");
printf("a = %d \n b = %d \n",a,b);
getch();
}
Ce anume se ntmpl' la execu#ia programului
pentru a=5 $i b=7? Func#ia main apeleaz' func#ia tipar
avnd ca parametri actuali adresele variabilelor a $i b. La
adresa variabilei a este memorat' valoarea 5, iar la
Func#ii
158
adresa variabilei b este memorat' valoarea 7. Func#ia
tipar adun' valoarea 3 la con#inutul de la adresa lui a $i
valoarea 4 la con#inutul de la adresa lui b, astfel nct
noile valori ale lui a $i b sunt respectiv 8 $i 11. Aceste
valori se p'streaz' dup' apelul func#iei tipar.
Valoarea lui a : 5
Valoarea lui b : 7
In tipar:
a = 8
b = 11
Valorile dupa apelul functiei sunt:
a = 8
b = 11
Pentru parametrii de tip masiv de date, transferul
prin referin#' se face n mod implicit, deoarece numele
masivului este pointer c'tre zona de memorie unde este
stocat masivul. Astfel urm'toarele prototipuri snt
echivalente:
tip identificator1(int masiv[]);
tip identificator2(int *masiv);
Urm'torul exemplu prezint' o func#ie pentru
calculul sumei componentelor unui vector. Func#ia suma
are doi parametri de intrare. Citirea vectorului se
realizeaz' cu func#ia citvector. Parametrul vector este
transferat prin referin#' deoarece este un masiv de
ntregi.
#include <stdio.h>
#include <conio.h>
void citvector(int k,int vector[])
{
int i;
for(i=0;i<k;i++)
{
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
159
printf("v [ %d ] = ",i);
scanf("%d",&vector[i]);
}
}

int suma(int k,int vector[])
{
int s = 0,i;
for(i=0; i<k; i++)
s+=vector[i];
return s;
}

int main()
{
int n,v[100],i;
printf("Numar de componente n = ");
scanf("%d",&n);
citvector(n, v);
printf("Suma componentelor este: %d\n",
suma(n,v));
getch();
}
Rezultatul execu#iei programului este:
Numar de componente n = 3
v [ 0 ] = 11
v [ 1 ] = 22
v [ 2 ] = 33
Suma componentelor este: 66
7.3.2. Transferul prin variabile globale
Variabilele globale se declar' n afara func#iilor,
inclusiv n afara func#iei main() $i pot fi referite din orice
alte func#ii, inclusiv din func#ia main(). Astfel, transferul
de parametri ntre func#ia apelant' $i cea apelat' se
poate face $i prin variabile globale.
Func#ii
160
Pentru exemplificare, relu'm unul dintre
exemplele anterioare. Parametrii de intrare ai func#iei
suma sunt declara#i ca variabile globale. Func#ia suma are
lista parametrilor formali vid'.
#include <stdio.h>
#include <conio.h>
int n, vector[100]; // variabile globale
void citvector()
{
int i;
for(i=0;i<n;i++)
{
printf(" v [ %d ] = ",i);
scanf("%d", &vector[i]);
}
}

int suma()
{
int s = 0,i;
for(i=0;i<n;i++)
s+=vector[i];
return s;
}

int main()
{
int i;
printf(" Numar de componente n = ");
scanf("%d",&n);
citvector();
printf("Suma componentelor este:
%d\n",suma());
getch();
}
Cele dou' metode de transmitere a parametrilor
(prin variabile globale $i prin parametri) pot fi folosite
mpreun'. De exemplu, declar'm numai vectorul vector
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
161
variabil' global'. Func#ia suma are un singur parametru
formal k.
#include <stdio.h>
#include <conio.h>
// Declararea variabilei globale vector
int vector[100];
void citvector(int k)
{
int i;
for(i=0;i<k;i++)
{
printf(" v [ %d ] = ",i);
scanf("%d", &vector[i]);
}
}

int suma(int k)
{
int s = 0,i;
for(i=0;i<k;i++)
s+=vector[i];
return s;
}
int main()
{
int n;
printf(" Numar de componente n = ");
scanf("%d",&n);
citvector(n);
printf("Suma componentelor: %d\n", suma(n));
getch();
}
7.4. Recursivitate
Recursivitatea este o tehnic' de programare
frecvent utilizat' n implementarea func#iilor. Tehnica
recursivit'#ii const' n autoapelul func#iei (de c'tre ea
ns'$i), n mod direct sau indirect. Tehnica poate fi
Func#ii
162
folosit' n cazul problemelor cu natur' recursiv' $i
simplific' scrierea programelor prin scrierea direct' a
formulelor recursive.
Defini#ia unui proces recursiv trebuie s' satisfac'
condi#ia de consisten#', adic' s' se termine ntr-un
num'r finit de pa$i.
Un exemplu de func#ie inconsistent' este
urm'torul: fie func#ia : f N N N ,
( )
( )
1 0
1
n
f n
n f n altfel

'
+

, ( ) n N . De
exemplu, ( ) ( ) ( ) 2 2 3 2 3 4 ... f f f L , ceea ce arat' c'
acest proces recursiv nu este finit.
Un exemplu de func#ie consistent' este
urm'torul: fie func#ia : f N N ,
( )
( )
1 0
1
n
f n
n f n altfel

'

, ( ) n N . Evident:
( ) ( ) ( ) (3) 3 2 3 2 1 3 2 1 0 3 2 1 1 3! 6 f f f f ,
ceea ce arat' c' acest proces recursiv este finit.
La baza recursivit'#ii st' o zon' de memorie
organizat' ca o stiv'. La fiecare apel al func#iei se
salveaz' automat n stiv' valorile variabilelor din func#ie
$i adresele de revenire (adresa urm'toarei instruc#iuni
care urmeaz' a fi executat' dup' apelul). Acest lucru
simplific' programarea, dar implic' un consum
suplimentar de timp $i memorie datorit' opera#iilor cu
stiva.
Recursivitatea este de dou' tipuri: direct' $i
indirect'. O func#ie recursiv' se nume$te direct recursiv',
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
163
dac' n defini#ia ei exist' cel pu#in un autoapel al ei. O
func#ie recursiv' se nume$te indirect recursiv' dac', se
autoapeleaz' prin intermediul unei alte func#ii, care $i ea
se autoapeleaz' prin intermediul primei func#ii.
n cazul recursivit'#ii indirecte, func#iile care se
autoapeleaz' indirect trebuie f'cute cunoscute
compilatorului prin prototipurile lor, scrise naintea
defini#iilor lor. Urm'toarele programe ilustreaz' cele dou'
tipuri de recursivitate.
De exemplu, func#ia factorial recursiv' prezentat'
anterior, poate fi implementat' n limbajul C astfel:
long factorial (unsigned int n)
{
if(n==0)
return 1;
else
return n*factorial(n-1);
}
7.5. Exemple
52. Programul urm'tor prezint' o func#ie pentru
determinarea celui mai mare divizor comun a dou'
numere naturale cu algoritmul lui Euclid $i un program
care testeaz' aceast' func#ie. n program se define$te
func#ia euclid de tip ntreg care are parametrii formali p
$i q de tip ntreg. Func#ia returneaz' valoarea
cmmdc(p,q). Apelul func#iei cu parametrii actuali m $i n,
euclid(m,n) determin' calculul cmmdc(m,n).
#include <stdio.h>
#include <conio.h>
int euclid(int p, int q)
{
int r;
Func#ii
164
while(r=p%q)
{
p=q;
q=r;
}
return q;
}
int main()
{
int m,n;
printf("Valoarea lui m = ");
scanf("%d",&m);
printf("Valoarea lui n = ");
scanf("%d",&n);
printf("cmmdc(%d,%d) = %d \n", m, n,
euclid(m,n));
getch();
}
Pentru m=48 $i n=18 programul afi$eaz':
Valoarea lui m = 48
Valoarea lui n = 18
cmmdc(48,18) = 6
53. Exemplul urm'tor prezint' folosirea prototipului
func#iei euclid pentru declararea acesteia nainte de a fi
definit'. n program este scris mai nti prototipul func#iei
euclid, iar func#ia este definit' abia dup' defini#ia
func#iei main().
#include <stdio.h>
#include <conio.h>
int euclid(int, int); // Prototipul functiei
int main()
{
int m,n;
printf("Valoarea lui m = ");
scanf("%d",&m);
printf("Valoarea lui n = ");
scanf("%d",&n);
printf("cmmdc(%d,%d) = %d \n", m, n,
euclid(m,n));
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
165
getch();
}
int euclid(int p, int q) // Definitia functiei
{
int r;
while(r=p%q)
{
p=q;
q=r;
}
return q;
}

54. Fie n un num'r natural. Conform criteriului de
divizibilitate cu 3, num'rul n este divizibil cu 3 dac' suma
cifrelor num'rului n este un num'r divizibil cu 3. n
programul urm'tor este definit' o func#ie care
implementeaz' criteriul de divizibilitate cu 3.
// Test divizibilitate cu 3
#include "stdio.h"
#include "conio.h"
int test3(int n)
{
int s,uc,nsalv;
nsalv=n;
s=0;
while(n!=0)
{
uc=n%10;
s+=uc;
n/=10;
}
printf(" Suma cifrelor numarului %d este %d
\n", nsalv,s);
if(s%3)
return 0;
else
return 1;
}
int main()
{
Func#ii
166
int n;
printf(" n = ");
scanf("%d",&n);
if(test3(n))
printf("Numarul %d este divizibil cu 3\n",
n);
else
printf("Numarul %d nu este divizibil cu
3\n", n);
getch();
}
Un exemplu de rulare este:
n = 123456789
Suma cifrelor numarului 123456789 este 45
Numarul 123456789 este divizibil cu 3

n = 1234
Suma cifrelor numarului 1234 este 10
Numarul 1234 nu este divizibil cu 3
55. Fie n un num'r natural. Conform criteriului de
divizibilitate cu 9, num'rul n este divizibil cu 9 dac' suma
cifrelor num'rului n este un num'r divizibil cu 9. n
programul urm'tor este definit' o func#ie care
implementeaz' criteriul de divizibilitate cu 9.
// Test divizibilitate cu 9
#include "stdio.h"
#include "conio.h"
int test9(int n)
{
int s,uc,nsalv;
nsalv=n;
s=0;
while(n!=0)
{
uc=n%10;
s+=uc;
n/=10;
}
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
167
printf(" Suma cifrelor numarului %d este
%d\n", nsalv,s);
if(s%9)
return 0;
else
return 1;
}
int main()
{
int n;
printf(" n = ");
scanf("%d",&n);
if(test9(n))
printf(" Numarul %d este divizibil cu 9
\n",n);
else
printf(" Numarul %d nu este divizibil cu 9
\n",n);
getch();
}
Un exemplu de rulare este:
n = 123456789
Suma cifrelor numarului 123456789 este 45
Numarul 123456789 este divizibil cu 9

n = 1234
Suma cifrelor numarului 1234 este 10
Numarul 1234 nu este divizibil cu 9
56. Fie n un num'r natural. Conform criteriului de
divizibilitate cu 4, num'rul n este divizibil cu 4 dac'
num'rul format cu ultimele dou' cifre ale num'rului n
este un num'r divizibil cu 4. n programul urm'tor este
definit' o func#ie care implementeaz' criteriul de
divizibilitate cu 4.
// Test divizibilitate cu 4
#include "stdio.h"
#include "conio.h"
int test4(int n)
{
Func#ii
168
int udc,uc,k,nsalv;
nsalv=n;
udc=n%10;
n/=10;
k=1;
while(n!=0 && k<=1)
{
uc=n%10;
uc*=10;
udc+=uc;
k++;
n/=10;
}
printf(" Numarul format cu ultimele doua
cifre\n");
printf(" ale numarului %d este egal cu %d
\n",nsalv,udc);
if(udc%4==0)
return 1;
else
return 0;
}
int main()
{
int n;
printf(" n = ");
scanf("%d",&n);
if(test4(n))
printf(" Numarul %d este divizibil cu 4
\n",n);
else
printf(" Numarul %d nu este divizibil cu 4
\n",n);
getch();
}
Un exemplu de rulare este:
n = 123456
Numarul format cu ultimele doua cifre
ale numarului 123456 este egal cu 56
Numarul 123456 este divizibil cu 4

n = 123
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
169
Numarul format cu ultimele doua cifre
ale numarului 123 este egal cu 23
Numarul 123 nu este divizibil cu 4
57. Fie n un num'r natural cu trei cifre. Conform
criteriului de divizibilitate cu 11, num'rul n este divizibil
cu 11 dac' suma dintre prima $i ultima sa cifr' este egal'
cu a doua cifr'. n programul urm'tor este definit' o
func#ie care implementeaz' criteriul de divizibilitate cu 11.
// Test divizibilitate cu 11
#include "stdio.h"
#include "conio.h"
int test11(int n)
{
int uc,nsalv,i,cif[3];
nsalv=n;
i=0;
while(n!=0)
{
uc=n%10;
cif[i]=uc;
i++;
n/=10;
}
if(cif[0]+cif[2]==cif[1])
return 1;
else
return 0;
}
int main()
{
int n;
printf(" n = ");
scanf("%d",&n);
if(test11(n))
printf(" Numarul %d este divizibil cu 11
\n",n);
else
printf(" Numarul %d nu este divizibil cu 11
\n",n);
getch();
}
Func#ii
170
Un exemplu de rulare este:
n = 154
Numarul 154 este divizibil cu 11

n = 432
Numarul 432 nu este divizibil cu 11
58. Programul urm'tor define$te o func#ie pentru
determinarea sumei elementelor de pe coloana k a unei
matrici p'trate, k citit de la tastatur'.
// Suma elementelor de pe coloana k
// a unei matrici patrate cu elemente numere
intregi
#include "stdio.h"
#include "conio.h"
int sum(int a[][20], int n,int k)
{
int i,j,s;
s=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(j==k) s+=a[i][j];
return s;
}
int main()
{
int n,i,j,a[20][20],k;
printf(" Dimensiunea: ");
scanf("%d",&n);
printf(" Elementele matricei \n");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf(" a [ %d ][ %d ] = ",i,j);
scanf("%d",&a[i][j]);
}
printf("Coloana pe care se calculeaza
suma:");
scanf("%d",&k);
if(k>=0 && k<=n-1)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
171
printf(" Suma elementelor de pe coloana %d
este %d \n",k,sum(a,n,k));
else
printf(" Coloana %d inexistenta \n",k);
getch();
}
Un exemplu de rulare este:
Dimensiunea: 3
Elementele matricei
a [ 0 ][ 0 ] = 1
a [ 0 ][ 1 ] = 2
a [ 0 ][ 2 ] = 3
a [ 1 ][ 0 ] = 4
a [ 1 ][ 1 ] = 5
a [ 1 ][ 2 ] = 6
a [ 2 ][ 0 ] = 7
a [ 2 ][ 1 ] = 8
a [ 2 ][ 2 ] = 9
Coloana pe care se calculeaza suma: 2
Suma elementelor de pe coloana 2 este 18
59. Programul urm'tor define$te o func#ie pentru
determinarea sumei elementelor de pe linia k a unei
matrice p'trate, k citit de la tastatur'.
// Suma elementelor de pe linia k
// a unei matrici patrate cu elemente numere
intregi
#include "stdio.h"
#include "conio.h"
int sum(int a[][20], int n,int k)
{
int i,j,s;
s=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(i==k) s+=a[i][j];
return s;
}
int main()
{
int n,i,j,a[20][20],k;
Func#ii
172
printf(" Dimensiunea: ");
scanf("%d",&n);
printf(" Elementele matricei \n");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf(" a [ %d ][ %d ] = ",i,j);
scanf("%d",&a[i][j]);
}
printf(" Linia pe care se calculeaza suma:
");
scanf("%d",&k);
if(k>=0 && k<=n-1)
printf(" Suma elementelor de pe linia %d
este %d \n",k,sum(a,n,k));
else
printf(" Linia %d inexistenta \n",k);
getch();
}
Un exemplu de rulare este:
Dimensiunea: 3
Elementele matricei
a [ 0 ][ 0 ] = 1
a [ 0 ][ 1 ] = 2
a [ 0 ][ 2 ] = 3
a [ 1 ][ 0 ] = 4
a [ 1 ][ 1 ] = 5
a [ 1 ][ 2 ] = 6
a [ 2 ][ 0 ] = 7
a [ 2 ][ 1 ] = 8
a [ 2 ][ 2 ] = 9
Linia pe care se calculeaza suma: 1
Suma elementelor de pe linia 1 este 15
60. Programul urm'tor define$te o func#ie pentru
determinarea sumei elementelor de pe diagonala
principal' a unei matrice p'trate. Facem observa#ia c'
elementul
ij
a este pe diagonala principal' dac' i j .
// Suma elementelor de pe diagonala principala
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
173
// a unei matrici patrate cu elemente numere
intregi
#include "stdio.h"
#include "conio.h"
int sdp(int a[][20], int n)
{
int i,j,s;
s=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(i==j) s+=a[i][j];
return s;
}
int main()
{
int n,i,j,a[20][20];
printf(" Dimensiunea: ");
scanf("%d",&n);
printf(" Elementele matricei \n");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf(" a [ %d ][ %d ] = ",i,j);
scanf("%d",&a[i][j]);
}
printf(" Suma elementelor de pe diagonala
principala este %d \n",sdp(a,n));
getch();
}
Un exemplu de rulare este:
Dimensiunea: 3
Elementele matricei
a [ 0 ][ 0 ] = 1
a [ 0 ][ 1 ] = 2
a [ 0 ][ 2 ] = 3
a [ 1 ][ 0 ] = 4
a [ 1 ][ 1 ] = 5
a [ 1 ][ 2 ] = 6
a [ 2 ][ 0 ] = 7
a [ 2 ][ 1 ] = 8
a [ 2 ][ 2 ] = 9
Func#ii
174
Suma elementelor de pe diagonala principala
este 15
61. Programul urm'tor define$te o func#ie pentru
determinarea sumei elementelor de pe diagonala
secundar' a unei matrice p'trate cu n linii $i n coloane.
Facem observa#ia c' elementul
ij
a este pe diagonala
secundar' dac' 1 i j n + + .
// Suma elementelor de pe diagonala secundara
// a unei matrici patrate cu elemente numere
intregi
#include "stdio.h"
#include "conio.h"
int sum(int a[][20], int n)
{
int i,j,s;
s=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if((i+j)==n-1) s+=a[i][j];
return s;
}
int main()
{
int n,i,j,a[20][20];
printf(" Dimensiunea: ");
scanf("%d",&n);
printf(" Elementele matricei \n");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf(" a [ %d ][ %d ] = ",i,j);
scanf("%d",&a[i][j]);
}
printf(" Suma elementelor de pe diagonala
secundara este %d \n",sum(a,n));
getch();
}
Un exemplu de rulare este:
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
175
Dimensiunea: 3
Elementele matricei
a [ 0 ][ 0 ] = 1
a [ 0 ][ 1 ] = 2
a [ 0 ][ 2 ] = 3
a [ 1 ][ 0 ] = 4
a [ 1 ][ 1 ] = 5
a [ 1 ][ 2 ] = 6
a [ 2 ][ 0 ] = 7
a [ 2 ][ 1 ] = 8
a [ 2 ][ 2 ] = 9
Suma elementelor de pe diagonala secundara
este 15
62. Programul urm'tor define$te o func#ie pentru
determinarea sumei elementelor aflate sub diagonala
principal' (subdiagonale) a unei matrice p'trate cu n linii
$i n coloane. Facem observa#ia c' elementul
ij
a este
subdiagonal dac' i j > .
// Suma elementelor subdiagonale
// ale unei matrici patrate cu elemente numere
intregi
#include "stdio.h"
#include "conio.h"
int sum(int a[][20], int n)
{
int i,j,s;
s=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(i>j) s+=a[i][j];
return s;
}
int main()
{
int n,i,j,a[20][20];
printf(" Dimensiunea: ");
scanf("%d",&n);
printf(" Elementele matricei \n");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
Func#ii
176
{
printf(" a [ %d ][ %d ] = ",i,j);
scanf("%d",&a[i][j]);
}
printf(" Suma elementelor subdiagonale este
%d \n",sum(a,n));
getch();
}
Un exemplu de rulare este:
Dimensiunea: 3
Elementele matricei
a [ 0 ][ 0 ] = 1
a [ 0 ][ 1 ] = 2
a [ 0 ][ 2 ] = 3
a [ 1 ][ 0 ] = 4
a [ 1 ][ 1 ] = 5
a [ 1 ][ 2 ] = 6
a [ 2 ][ 0 ] = 7
a [ 2 ][ 1 ] = 8
a [ 2 ][ 2 ] = 9
Suma elementelor subdiagonale este 19
63. Programul urm'tor define$te o func#ie pentru
determinarea sumei elementelor aflate deasupra
diagonalei principale (supradiagonale) a unei matrice
p'trate cu n linii $i n coloane. Facem observa#ia c'
elementul
ij
a este supradiagonal dac' i j < .
// Suma elementelor supradiagonale
// ale unei matrici patrate cu elemente numere
intregi
#include "stdio.h"
#include "conio.h"
int sum(int a[][20], int n)
{
int i,j,s;
s=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(i<j) s+=a[i][j];
return s;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
177
}
int main()
{
int n,i,j,a[20][20];
printf(" Dimensiunea: ");
scanf("%d",&n);
printf(" Elementele matricei \n");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf(" a [ %d ][ %d ] = ",i,j);
scanf("%d",&a[i][j]);
}
printf(" Suma elementelor supradiagonale
este %d \n", sum(a,n));
getch();
}
Un exemplu de rulare este:
Dimensiunea: 3
Elementele matricei
a [ 0 ][ 0 ] = 1
a [ 0 ][ 1 ] = 2
a [ 0 ][ 2 ] = 3
a [ 1 ][ 0 ] = 4
a [ 1 ][ 1 ] = 5
a [ 1 ][ 2 ] = 6
a [ 2 ][ 0 ] = 7
a [ 2 ][ 1 ] = 8
a [ 2 ][ 2 ] = 9
Suma elementelor supradiagonale este 11
64. Un num'r natural n nenul se nume$te perfect dac'
este egal cu suma divizorilor s'i diferi#i de n . Programul
urm'tor cite$te un num'r natural k $i determin' toate
numerele perfecte din mul#imea { } 1, 2, , k K . Testul de
num'r perfect este f'cut de func#ia perfect. Func#ia
are ca parametru de intrare ntregul n $i returneaz' prin
numele s'u valoarea 1 dac' n este num'r perfect sau
valoarea zero dac' n nu este num'r perfect.
Func#ii
178
// Numerele perfecte din multimea {1,2,...,k}
#include "stdio.h"
#include "conio.h"
int perfect(int n)
{
int i,sum_div;
for(sum_div=0,i=1;i<=n/2;i++)
if(n%i==0)
sum_div+=i;
if(n==sum_div)
return 1;
else
return 0;
}
int main()
{
int k,n;
printf(" k = ");
scanf("%d",&k);
for(n=1;n<=k;n++)
if(perfect(n))
printf(" %d este numar perfect \n",n);
getch();
}
Un exemplu de rulare este:
k = 10000
6 este numar perfect
28 este numar perfect
496 este numar perfect
8128 este numar perfect
65. Programul din exemplul anterior poate fi modificat
astfel nct s' determine primele k numere perfecte. O
variant' este urm'toarea:
// Primele k numere perfecte
#include "stdio.h"
#include "conio.h"
int perfect(int n)
{
int i,sum_div;
for(sum_div=0,i=1;i<=n/2;i++)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
179
if(n%i==0)
sum_div+=i;
if(n==sum_div)
return 1;
else
return 0;
}
int main()
{
int i,k,n;
printf(" k = ");
scanf("%d",&k);
printf(" Primele %d numere perfecte sunt
\n",k);
i=1;
n=1;
while(n<=k)
{
if(perfect(i))
{
printf(" %d este numar perfect \n",i);
i++;
n++;
} else
i++;
}
getch();
}
Un exemplu de execu#ie este:
k = 4
Primele 4 numere perfecte sunt
6 este numar perfect
28 este numar perfect
496 este numar perfect
8128 este numar perfect
66. Dou' numere naturale n $i m se numesc numere
prietene dac' suma divizorilor lui m (f'r' num'rul m)
este egal' cu n $i suma divizorilor lui n (f'r' num'rul n )
este egal' cu m. De exemplu numerele 220 $i 284 sunt
prietene. Programul urm'tor testeaz' dac' dou' numere
Func#ii
180
naturale sunt sau nu numere prietene. n program sunt
definite dou' func#ii: sum_div pentru determinarea sumei
divizorilor parametrului de intrare $i prietene care
testeaz' dac' parametrii de intrare sunt numere prietene.
Se poate observa c' dac' un num'r este perfect atunci el
este num'r prieten cu el nsu$i.
// Test numere prietene
#include "stdio.h"
#include "conio.h"
int sum_div(int n)
{
int i,sd;
for(i=1,sd=0;i<=n/2;i++)
if(n%i==0)
sd+=i;
return sd;
}
int prietene(int n, int m)
{
if(n==sum_div(m) && m==sum_div(n))
return 1;
else return 0;
}
int main()
{
int n,m;
printf(" n = ");
scanf("%d",&n);
printf(" m = ");
scanf("%d",&m);
if(prietene(n,m))
printf(" Numerele %d si %d sunt prietene
\n",n,m);
else
printf(" Numerele %d si %d nu sunt prietene
\n",n,m);
getch();
}
Un exemplu de rulare este:
n = 220
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
181
m = 284
Numerele 220 si 284 sunt prietene

n = 28
m = 28
Numerele 28 si 28 sunt prietene

n = 220
m = 264
Numerele 220 si 264 nu sunt prietene
67. Programul din exemplul anterior poate fi modificat
astfel nct s' determine toate perechile de numere
prietene distincte, mai mici sau egale cu o valoare dat'
p .
// Perechile de numere prietene distincte mai
mici decat p
#include "stdio.h"
#include "conio.h"
int sum_div(int n)
{
int i,sd;
for(i=1,sd=0;i<=n/2;i++)
if(n%i==0)
sd+=i;
return sd;
}
int prietene(int n, int m)
{
if(n==sum_div(m) && m==sum_div(n))
return 1;
else return 0;
}
int main()
{
int k,i,j,n,p;
printf(" p = ");
scanf("%d",&p);
n=1;
for(i=1;i<=p;i++)
for(j=i+1;j<=p;j++)
if(prietene(i,j))
Func#ii
182
{
printf("%d Numerele %d si %d sunt prietene
\n",n,i,j);
n++;
}
getch();
}
Un exemplu de rulare este:
p = 2000
1 Numerele 220 si 284 sunt prietene
2 Numerele 1184 si 1210 sunt prietene
68. Este cunoscut faptul c' orice num'r natural par se
poate reprezenta ca suma adou' numere prime
(descompunerea Goldbach). Programul urm'tor
descompune num'rul natural par n suma a dou' numere
prime. Pentru testul de num'r prim am folosit func#ia
prim.
//Proprietatea Goldbach
#include "stdio.h"
#include "conio.h"
int prim(int n)
{
int i,p;
p=1;
for(i=2;i<=n/2;i++)
if(n%i==0)
p=0;
return p;
}
int main()
{
int n,i,dif,p;
printf(" n = ");
scanf("%d",&n);
if(n%2==0)
{
i=2;
while(i<n-1)
{
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
183
if(prim(i))
{
p=i;
i++;
}
else
i++;
}
dif=n-p;
printf(" %d = %d + %d \n",n,dif,p);
}
else
printf(" %d nu este numar par \n",n);
getch();
}
Rularea programului conduce la rezultatele:
n = 12
12 = 5 + 7

n = 13
13 nu este numar par
69. Programul urm'tor determin' $i afi$eaz'
descompunerea Goldbach pentru toate numerele pare
din mul#imea { } 4, 5, , k K , k citit de la tastatur'.
//Proprietatea Goldbach pe multimea
// {3,4,...,k}
#include "stdio.h"
#include "conio.h"
int prim(int n)
{
int i,p;
p=1;
for(i=2;i<=n/2;i++)
if(n%i==0)
p=0;
return p;
}
int main()
{
Func#ii
184
int k,n,i,dif,p;
printf(" k = ");
scanf("%d",&k);
for(n=4;n<=k;n++)
{
if(n%2==0)
{
i=2;
while(i<n-1)
{
if(prim(i))
{
p=i;
i++;
}
else
i++;
}
dif=n-p;
printf(" %d = %d + %d \n",n,dif,p);
}
}
getch();
}
O rulare a programului produce rezultatele:
k = 30
4 = 2 + 2
6 = 3 + 3
8 = 3 + 5
10 = 3 + 7
12 = 5 + 7
14 = 3 + 11
16 = 3 + 13
18 = 5 + 13
20 = 3 + 17
22 = 3 + 19
24 = 5 + 19
26 = 3 + 23
28 = 5 + 23
30 = 7 + 23
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
185
70. Este cunoscut faptul c' produsul a oric'ror dou'
numere naturale consecutive este un num'r natural
cuprins ntre dou' numere impare dintre care cel pu#in
unul este num'r prim. Programul urm'tor verific' acest
rezultat pentru fiecare num'r natural din mul#imea
{ } 2, 3, , n K , n citit de la tastatur'. Testul de num'r prim
este f'cut de func#ia prim.
//Produs numere consecutive
#include "stdio.h"
#include "conio.h"
int prim(int n)
{
int i,p;
p=1;
for(i=2;i<=n/2;i++)
if(n%i==0)
p=0;
return p;
}
int main()
{
int k,n,produs;
printf(" n = ");
scanf("%d",&n);
for(k=2;k<=n;k++)
{
produs=k*(k+1);
printf(" %d < %d * %d = %d < %d
\n",produs-1,k,k+1,produs,produs+1);
if(prim(produs-1))
printf(" %d este numar prim \n",produs-1);
if(prim(produs+1))
printf(" %d este numar prim \n",produs+1);
}
getch();
}
Rezultatele unei rul'ri sunt:
n = 5
5 < 2 * 3 = 6 < 7
Func#ii
186
5 este numar prim
7 este numar prim
11 < 3 * 4 = 12 < 13
11 este numar prim
13 este numar prim
19 < 4 * 5 = 20 < 21
19 este numar prim
29 < 5 * 6 = 30 < 31
29 este numar prim
31 este numar prim
71. Program pentru determinarea tuturor numerelor de
cinci cifre, din intervalul [ ] , li ls , li numar cu cinci cifre,
care au urm'toarele propriet'#i:
1. ultima cifr' este egal' cu 7;
2. printre primele patru cifre, cifra 1 apare o singur' dat';
3. suma tuturor cifrelor este un num'r impar;
4. primele patru cifre sunt distincte.
n program sunt definite trei func#ii utilizator pentru
determinarea ultimei cifre, sumei cifrelor, num'rului de
cifre $i dou' func#ii care testeaz' dac' primele patru cifre
sunt distincte $i respectiv dac' printre primele patru cifre,
cifra 1 apare o singur' dat'. Programul este prezentat n
continuare:
// Determinarea tuturor numerelor cu 5 cifre
cu proprietatile
// 1. Ultima cifra este 7
// 2. Printre primele patru cifre, cifra 1
apare exact o singura data
// 3. Suma tuturor cifrelor este un numar
impar
// 4. Primele patru cifre sunt distincte
#include "stdio.h"
#include "conio.h"

int v[4];

// Prototipurile functiilor utilizator
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
187

int uc(int);
int sc(int);
int nc(int);
int dis(void);
int c1(void);

// Functia care determina ultima cifra
int uc(int n)
{
int u;
u=n%10;
return u;
}

// Functia care determina suma cifrelor si
care
// construieste vectorul format cu primele
patru cifre
int sc(int n)
{
int sc, uc, i;
sc=0;
i=0;
uc=n%10;
sc=sc+uc;
while(n)
{
n=n/10;
uc=n%10;
sc=sc+uc;
v[i]=uc;
i++;
}
return sc;
}

// Functia care determina numarul de cifre ale
numarului n
int nc(int n)
{
int s;
s=0;
Func#ii
188
while(n)
{
n=n/10;
s++;
}
return s;
}

// Functia care testeaza daca primele patru
cifre sunt distincte
int dis(void)
{
int i,j,ok;
ok=1;
for(i=0;i<4;i++)
for(j=i+1;j<4;j++)
if(v[i]==v[j])
ok=0;
return ok;
}

// Functia care testeaza daca printre primele
patru cifre
// exista cifra 1
int c1(void)
{
int i, ok;
ok=0;
for(i=0;i<3;i++)
if(v[i]==1)
ok=1;
return ok;
}

// Functia principala
int main()
{
int li,ls,i,nt;
nt=0;
printf(" li = ");
scanf("%d",&li);
printf(" ls = ");
scanf("%d",&ls);
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
189
if(li <= ls && nc(li)==5)
{
for(i=li;i<=ls;i++)
{
if(sc(i)%2==1)
{
if(dis() && c1() && uc(i)==7)
{
nt++;
printf(" %d. i = %d \n",nt,i);
}
}
}
printf(" Numar total de numere %d \n",nt);
}
else
printf(" Numarul %d nu are 5 cifre sau %d
> %d \n",li,li,ls);
getch();
}
Un exemplu de rulare este:
li = 20000
ls = 21000
1. i = 20137
2. i = 20157
3. i = 20177
4. i = 20197
5. i = 20317
6. i = 20517
7. i = 20717
8. i = 20917
Numar total de numere 8
72. Func#ie pentru determinarea lungimii unui $ir de
caractere.
// Functie pentru determinarea lungimii unui
sir de caractere
#include "stdio.h"
#include "conio.h"
void strlen(char *s,int &n)
{
Func#ii
190
int i;
for(i=0;*(s+i)!='\0';i++);
n=i;
}
int main()
{
char s[100];
int lung;
puts(" Sirul ");
gets(s);
strlen(s,lung);
printf(" Sirul %s are %d caractere
\n",s,lung);
getch();
}
Un exemplu de rulare este urm'torul:
Sirul
Determinarea lungimii
Sirul Determinarea lungimii are 21 caractere
73. Func#ie pentru copierea unui $ir de caractere.
//Functie pentru copierea unui sir de
caractere
#include "stdio.h"
#include "conio.h"
char * strcpy(char *sd, char *ss)
{
int i;
for(i=0;*(ss+i)!='\0';*(sd+i)=*(ss+i),i++);
*(sd+i)='\0';
return sd;
}
int main()
{
char sirs[20],sird[100],*sd;
puts(" Sir sursa ");
gets(sirs);
sd=strcpy(sird,sirs);
puts(" Sirul sursa ");
printf(" %s \n",sirs);
puts(" Sirul destinatie ");
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
191
printf(" %s \n",sird);
printf(" Adresa sir destinatie returnata de
functie este %x \n",sd);
printf(" Adresa sir destinatie din functia
main este %x \n",sird);
getch();
}
Sir sursa
functie pentru copiere sir de caractere
Sirul sursa
functie pentru copiere sir de caractere
Sirul destinatie
functie pentru copiere sir de caractere
Adresa sir destinatie returnata de functie
este 22fec0
Adresa sir destinatie din functia main este
22fec0
74. Func#ie pentru concatenarea a dou' $iruri de
caractere.
//Functie pentru concatenarea a doua siruri
#include "stdio.h"
#include "conio.h"
char * strcat(char *sd, char *ss)
{
int i,ld;
for(i=0;*(sd+i)!='\0';i++);
ld=i;
i=0;
while(*(ss+i)!='\0')
{
*(sd+ld+i)=*(ss+i);
i++;
}
*(sd+ld+i)='\0';
return sd;
}
int main()
{
char sirs[20],sird[100],*sd;
puts(" Sir sursa ");
gets(sirs);
Func#ii
192
puts(" Sir destinatie ");
gets(sird);
sd=strcat(sird,sirs);
puts(" Sirul concatenat ");
printf(" %s \n",sird);
printf(" Adresa sir destinatie returnata de
functie este %x \n",sd);
printf(" Adresa sir destinatie din functia
main este %x \n",sird);
getch();
}
Sir sursa
concatenare
Sir destinatie
functie pentru
Sirul concatenat
functie pentru concatenare
Adresa sir destinatie returnata de functie
este 22fec0
Adresa sir destinatie din functia main este
22fec0
75. Func#ie pentru determinarea primei apari#ii a unui
caracter ntr-un $ir de caractere.
//Functie de cautare a unui caracter intr-un
sir
//Functia returneaza adresa primei aparitii a
caracterului sau NULL
#include "stdio.h"
#include "conio.h"
char * strchr(char *s, char c)
{
int i,gasit=0;
char *adr;
i=0;
while(*(s+i)!='\0')
{
if(*(s+i)==c)
{
adr=s+i;
gasit=1;
break;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
193
}
else
i++;
}
if(gasit)
return adr;
else
return NULL;
}
int main()
{
char sir[20],c,*s;
int n;
puts(" Sirul ");
gets(sir);
puts(" Caracterul ");
scanf("%c",&c);
s=strchr(sir,c);
if(s)
{
n=s-sir;
printf(" Caracterul %c are prima aparitie
in sirul %s pe pozitia %d \n",c,sir,n);
}
else
printf(" Caracterul %c nu apare in sirul
%s \n",c,sir);
getch();
}
Un exemplu de rulare este:
Sirul
abecedar
Caracterul
c
Caracterul c are prima aparitie in sirul
abecedar pe pozitia 3

Sirul
abecedar
Caracterul
#
Caracterul # nu apare in sirul abecedar
Func#ii
194
76. Variant' recursiv' a algoritmului lui Euclid.
Determinarea celui mai mare divizor comun cu algoritmul
lui Euclid poate fi f'cut' recursive, folosind rela#ia de
recuren#':
( ) ( )

'

0 % , ,
0
) , (
n daca n m n cmmdc m cmmdc
n daca m
n m cmmdc .
Programnd aceast' rela#ie de recuren#' se ob#ine
urm'torul cod:
// Varianta recursiva a algoritmului lui
Euclid
#include "stdio.h"
#include "conio.h"
int cmmdc(int m, int n)
{
if(n==0)
return m;
else
return cmmdc(n,m%n);
}
int main()
{
int m,n;
printf(" m = ");
scanf("%d",&m);
printf(" n = ");
scanf("%d",&n);
if(cmmdc(m,n)==1)
printf(" Numerele %d si %d sunt prime
intre ele \n",m,n);
else
printf(" Numerele %d si %d nu sunt prime
intre ele \n",m,n);
printf(" cmmdc( %d , %d ) = %d
\n",m,n,cmmdc(m,n));
getch();
}
Se ob#in rezultatele:
m = 124
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
195
n = 24
Numerele 124 si 24 nu sunt prime intre ele
cmmdc( 124 , 24 ) = 4
77. Program urm'tor afi$eaz' primii n termeni ai $irului
lui Fibonacci, definit prin: : fib N N , ( ) 0 1 fib ,
( ) 1 1 fib , ( ) ( ) ( 1) 2 fib n fib n fib n + , ( ) 2 n .
#include <stdio.h>
#include <conio.h>
int fib(int n)
{
if (n==0 || n==1)
return 1;
else
return fib(n-1)+fib(n-2);
}
int main()
{
int n,i;
printf("Generarea recursiva a termenilor
sirului lui Fibonacci \n");
printf("Rangul maxim n = ");
scanf("%d",&n);
printf("Primii %d termeni din sirul
Fibonacci:\n", n);
for(i=0;i<n;i++)
printf("Termenul de rang %d in sirul
Fibonacci este %d \n",i,fib(i));
getch();
}
Generarea recursiva a termenilor sirului lui
Fibonacci
Rangul maxim n = 5
Primii 6 termeni ai sirului Fibonacci sunt:
Termenul de rang 0 in sirul Fibonacci este 1
Termenul de rang 1 in sirul Fibonacci este 1
Termenul de rang 2 in sirul Fibonacci este 2
Termenul de rang 3 in sirul Fibonacci este 3
Termenul de rang 4 in sirul Fibonacci este 5
Func#ii
196
78. Programul afi$eaz' primii n termeni din $irurile
aritmetic-geometric-armonic ale lui Gauss, definite de
rela#iile de recuren#':
0
0 a p > ,
0
0 b q > ,
0
0 c r > ,
1 1 1
3
n n n
n
a b c
a

+ +
,
3
1 1 1 n n n n
b a b c

,
1 1 1
3
1 1 1
n
n n n
c
a b c

+ +
, ( )
*
n N .
#include <stdio.h>
#include <conio.h>
#include <math.h>
double p,q,r;
double a(int);
double b(int);
double c(int);
double a(int n)
{
if (n==0)
return p;
else
return (a(n-1)+b(n-1)+c(n-1))/3;
}
double b(int n)
{
if (n==0)
return q;
else
return pow(a(n-1)*b(n-1)*c(n-1), 1./3);
}
double c(int n)
{
if (n==0)
return r;
else
return 3/(1/a(n-1)+1/b(n-1)+1/c(n-1));
}
int main()
{
int n,i;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
197
printf("Sirurile aritmetic-geometric-armonic
ale lui Gauss\n");
printf("a( 0 ) = p = ");
scanf("%lf", &p);
printf("b( 0 ) = q = ");
scanf("%lf", &q);
printf("c( 0 ) = r = ");
scanf("%lf", &r);
printf(" Rangul maxim al termenilor n = ");
scanf("%i", &n);
for(i=0;i<n;i++)
printf("a( %d ) = %.4f\tb( %d ) = %.4f\tc(
%d ) = %.4f\n", i, a(i), i, b(i), i, c(i));
getch();
}
Sirurile aritmetic-geometric-armonic ale lui
Gauss
a( 0 ) = p = 1
b( 0 ) = q = 2
c( 0 ) = r = 3
Rangul maxim al termenilor n = 4
a( 0 ) = 1.0000 b( 0 ) = 2.0000 c( 0 ) =
3.0000
a( 1 ) = 2.0000 b( 1 ) = 1.8171 c( 1 ) =
1.6363
a( 2 ) = 1.8178 b( 2 ) = 1.8117 c( 2 ) =
1.8056
a( 3 ) = 1.8117 b( 3 ) = 1.8117 c( 3 ) =
1.8117
79. Programul urm'tor afi$eaz' pentru orice pereche
( ) , m n N N , pentru 0,1,..., i m , 0,1,..., j n , valorile
func#iei lui Ackerman definit' astfel: : Ack N N N ,
( ) ( )
( ) ( )
1, 0
, 1,1 , 0
1, , 1 ,
n m
Ack m n Ack m n
Ack m Ack m n altfel
+


'

,
( )( ) , m n N N .
Func#ii
198
i Pentru m>3, func#ia lui Ackerman este puternic
recursiv' $i determinarea valorilor ei poate s'
dureze foarte mult.
#include <stdio.h>
#include <conio.h>
int ack(int m,int n)
{
if (m==0)
return n+1;
else if (n==0)
return ack(m-1,1);
else
return ack(m-1,ack(m,n-1));
}
int main()
{
int n,m,i,j;
printf(" Functia lui Ackerman \n");
printf(" Tastati valoarea lui m = ");
scanf("%d",&m);
printf(" Tastati valoarea lui n = ");
scanf("%d",&n);
for(i=0;i<=m;i++)
for(j=0;j<=n;j++)
printf("Ackerman ( %d , %d ) = %d\n",
i, j, ack(i,j));
getch();
}
Functia lui Ackerman
Tastati valoarea lui m = 3
Tastati valoarea lui n = 2
Ackerman ( 0 , 0 ) = 1
Ackerman ( 0 , 1 ) = 2
Ackerman ( 0 , 2 ) = 3
Ackerman ( 1 , 0 ) = 2
Ackerman ( 1 , 1 ) = 3
Ackerman ( 1 , 2 ) = 4
Ackerman ( 2 , 0 ) = 3
Ackerman ( 2 , 1 ) = 5
Ackerman ( 2 , 2 ) = 7
Ackerman ( 3 , 0 ) = 5
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
199
Ackerman ( 3 , 1 ) = 13
Ackerman ( 3 , 2 ) = 29
80. Programul afi$eaz' pentru orice interval [ ] , a b R ,
$i pentru orice
*
n N , toate valorile
b a
f a i
n
_
+

,
,
0,1,..., i n , ale func#iei Manna-Pnueli definit' prin:
: f R R ,
( ) ( )
1, 12
( )
2 ,
x x
f x
f f x altfel

'
+

, ( ) x R .
#include <stdio.h>
#include <conio.h>
double f(double x)
{
if (x>=12)
return x-1;
else
return f(f(x+2));
}
int main()
{
float x,a,b,h;
int n,i;
printf(" Intervalul [a,b] \n");
printf("a = ");
scanf("%lf", &a);
printf("b = ");
scanf("%lf", &b);
printf(" Numarul de puncte n = ");
scanf("%i", &n);
h=(b-a)/n;
for(i=0;i<=n;i++)
{
x=a+i*h;
printf("MP( %g ) = %g\n", x, f(x));
}
getch();
}
Intervalul [a,b]
Func#ii
200
a = 11.5
b = 13.5
Numarul de puncte n = 10
MP( 11.5 ) = 11.5
MP( 11.7 ) = 11.7
MP( 11.9 ) = 11.9
MP( 12.1 ) = 11.1
MP( 12.3 ) = 11.3
MP( 12.5 ) = 11.5
MP( 12.7 ) = 11.7
MP( 12.9 ) = 11.9
MP( 13.1 ) = 12.1
MP( 13.3 ) = 12.3
MP( 13.5 ) = 12.5
81. Problema turnurilor din Hanoi. Se dau trei tije notate
A, B, C, a$ezate n pozi#ie vertical'. Pe tija A se g'sesc n
discuri care au razele r
1
>r
2
>...>r
n
, a$ezate n ordine
descresc'toare a razelor ncepnd de la baza tijei.
Problema const' n determinarea mut'rilor necesare
transferului celor n discuri de pe tija A pe tija B, n final
discurile fiind a$ezate pe tija B n aceea$i ordine ca pe tija
A. O mutare const' n a$ezarea unui singur disc pe o tij'
goal', sau peste un disc cu raza mai mare, pe oricare
dintre tije. Nu se poate a$eza un disc cu raz' mai mare
peste un disc cu raza mai mic'. . Rezolvarea problemei
se poate face astfel: dac' 1 n se mut' discul de pe tija
surs' pe tija destina#ie, problema fiind astfel rezolvat'.
Dac' 1 n se mut' primele 1 n discuri de pe tija s pe
tija m folosind ca tij' de manevr' d , apoi se mut' discul
r'mas pe tija s pe tija d , $i n final se mut' cele 1 n
discuri de pe tija m pe tija d , folosind ca tij' de manevr'
tija s . Not'm cu ( ) m d s n h , , , $irul mut'rilor necesare
rezolv'rii problemei $i cu b a mutarea primului disc de
pe tija a pe tija b . Se ob#ine rela#ia de recuren#' a $irului
de mut'ri din problema turnurilor din Hanoi:
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
201
( )
( ) ( )

'

>

1 , , , 1 , , , 1
1
, , ,
n daca s d m n h d s d m s n h
n daca d s
m d s n h
. Rezolvarea const' n programarea rela#ii de recuren#' a
$irului de mut'ri din problema turnurilor din Hanoi.
Programul afi$eaz' pentru orice
*
n N dat, mut'rile care
conduc la solu#ia problemei.
#include <stdio.h>
#include <conio.h>
void hanoi(int n, char a, char b, char c)
{
if (n==1)
{
printf("Se muta discul %d de pe %c pe
%c\n", n, a, b);
} else
{
hanoi(n-1,a,c,b);
printf("Se muta discul %d de pe %c pe
%c\n", n, a, b);
hanoi(n-1,c,b,a);
}
}
int main()
{
int n;
printf("Problema turnurilor din Hanoi\n");
printf("Numarul de discuri n = ");
scanf("%d",&n);
hanoi(n,'A','B','C');
getch();
}
Problema turnurilor din Hanoi
Numarul de discuri n = 3
Se muta discul 1 de pe A pe B
Se muta discul 2 de pe A pe C
Se muta discul 1 de pe B pe C
Se muta discul 3 de pe A pe B
Se muta discul 1 de pe C pe A
Se muta discul 2 de pe C pe B
Func#ii
202
Se muta discul 1 de pe A pe B
7.6. Exerci#ii
60. S' se scrie func#ia void citirevector(int v[],
int n) care cite$te de la tastatur' n numere ntregi $i le
memoreaz' n vectorul v.
61. S' se scrie func#ia void afi#arevector(int
v[], int n) care afi$eaz' pe ecran primele n numere
ntregi din vectorul v.
62. Scrie#i un program C care s' testeze cele dou'
func#ii (adic' cite$te un vector de la tastatur' $i l afi$eaz'
pe ecran).
63. Scrie#i o func#ie care afi$eaz' suma elementelor
pare $i produsul elementelor impare dintr-un vector $i un
program C care s' o testeze.
64. Scrie#i o func#ie care afi$eaz' elementele maxim $i
minim dintr-un vector $i un program C care s' o testeze.
65. Scrie#i o func#ie care ntoarce pozi#ia primei apari#ii a
unui num'r m ntr-un vector $i un program C care s' o
testeze.
66. Scrie#i o func#ie care adun' doi vectori $i pune
rezultatul n al treilea vector, $i un program C care s' o
testeze.
67. Scrie#i o func#ie care sorteaz' valorile unui vector de
numere reale $i un program care s' o testeze.
68. Scrie#i o func#ie nerecursiv' care returneaz'
valoarea n! (n este parametrul func#iei) $i un program C
care s' o testeze (Indica#ie: folosi#i formula n! = 1 * 2 * ...
* n).
69. Scrie#i o func#ie recursiv' care returneaz' valoarea
n! (n este parametrul func#iei) $i un program C care s' o
testeze (Indica#ie: folosi#i formula recursiv' n! = n * (n-1)!
pentru n>1 $i n!=1 pentru n=0 sau 1).
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
203
70. Scrie#i o func#ie nerecursiv' care returneaz' al n-lea
termen din $irul lui Fibonacci (n este parametrul func#iei)
$i un program C care s' o testeze (Indica#ie: folosi#i
formula t
1
=1, t
2
=1, t
i+2
=t
i
+t
i+1
pentru i>1).
71. Scrie#i o func#ie recursiv' care returneaz' al n-lea
termen din $irul lui Fibonacci (n este parametrul func#iei)
$i un program C care s' o testeze (Indica#ie: folosi#i
formula recursiv' t
i
=t
i-1
+t
i-2
pentru n>2 $i t
i
=1 altfel).
72. Scrie#i o func#ie nerecursiv' care returneaz'
valoarea cmmdc(m,n) (m $i n sunt parametrii func#iei) $i
un program C care s' o testeze (Indica#ie: ct timp m
este diferit de n, se scade din variabila mai mare valoarea
variabilei mai mici; cnd m=n atunci m e cmmdc).
73. Scrie#i o func#ie nerecursiv' care returneaz'
valoarea cmmdc(m,n) (m $i n sunt parametrii func#iei) $i
un program C care s' o testeze (Indica#ie: folosi#i formula
recursiv' cmmdc(a,b) = a, daca b=0; cmmdc(a,b) =
cmmdc(b, a%b), daca a>b; cmmdc(a,b) = cmmdc(a,
b%a), daca a<=b;).
205
8
88.
.. P
PPO
OOI
IIN
NNT
TTE
EER
RRI
II !
!!I
II G
GGE
EES
SST
TTI
IIU
UUN
NNE
EEA
AA D
DDI
IIN
NNA
AAM
MMI
II C
CC&
&& A
AA
M
MME
EEM
MMO
OOR
RRI
IIE
EEI
II
8.1. Pointeri
Un pointer este o variabil' a c'rei valoare este o
adres' din memoria calculatorului. Prin intermediul
pointerului, programatorul poate accesa $i modifica
informa#ia stocat' n memorie la adresa indicat' de
acesta. Pentru a accesa ntr-un mod coerent informa#ia
stocat' n memorie, fiecare pointer are un tip de baz'
care determin' tipul informa#iei aflate n memorie.
Pentru a declara o variabil' de tip pointer se
folose$te sintaxa:
tip *nume;
unde tip reprezint' tipul de baz' al pointerului, iar nume
reprezint' numele variabilei pointer. Tipul informa#iei
referite de c'tre un pointer poate fi: un tip fundamental,
tipul void, o structur', o uniune, un tablou, o func#ie sau
alt pointer. Un pointer cu tipul de baz' void este un
pointer c'tre o informa#ie al c'rei tip nu se cunoa$te
exact.
De exemplu, declara#iile urm'toare
Pointeri $i gestiunea dinamic' a memoriei
206
int *varsta;
char *nume;
declar' pointerul varsta care va con#ine adresa unui
num'r ntreg $i pointerul nume care va con#ine adresa
unui caracter.
8.2. Operatorii &, * $i ->
Operatorul unar & (denumit n acest context
operatorul de referen#iere) se poate folosi pentru a ob#ine
adresa unei variabile. Aceast' adres' poate fi memorat'
ntr-un pointer. n sens invers, informa#ia din memorie de
la o anumit' adres' (memorat' ntr-un pointer) poate fi
accesat' folosind operatorul unar * (denumit n acest
context operatorul de dereferen#iere).
De exemplu, n urma execu#iei secven#ei de
program
int x = 3, *px;
px = &x;
*px = 5;
variabila x cap't' valoarea 5, deoarece pointerul px
con#ine adresa variabilei x, deci instruc#iunea *px = 5
este echivalent' cu x = 5.
Dac' p este un pointer c'tre o structur' sau o
uniune, rezultatul expresiei *p este structura (sau
uniunea) a c'rei adres' este memorat' n p. Pentru a
accesa membrii acesteia folosind operatorul punct (care
are o prioritate mai mare dect operatorul *), expresia *p
trebuie scris' ntre paranteze rotunde astfel:
(*p).membru. Pentru a evita aceast' construc#ie, putem
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
207
folosi operatorul -> (caracterul minus urmat de caracterul
mai mare) astfel: p->membru.
i Operatorii * $i -> nu se pot aplica pointerilor de tip
void.
i Indiferent de tipul pointerului, acestuia i se poate
atribui valoarea 0, cu semnifica#ia "pointer
neini#ializat".
i n biblioteca stdio.h, este definit' constanta
simbolic' NULL cu valoarea 0, a c'rei folosire este
recomandat' n locul valorii 0 n cazul pointerilor.
8.3. Aritmetica pointerilor
n afar' de operatorul &, un pointer poate fi folosit
n diverse expresii cu operatorii de adunare, sc'dere $i
indexare, astfel: adunarea/scaderea unui pointer $i ntreg,
sc'derea a doi pointeri $i indexarea unui pointer cu un
ntreg. n fiecare dintre aceste opera#ii se #ine cont de
tipul informa#iei pe care o adreseaz' pointerul, deci ele nu
pot fi aplicate pointerilor de tip void.
Dac' p este un pointer cu tipul de baz' t $i n est
un num'r ntreg, atunci expresiile p+n $i p-n sunt corecte,
rezultatul lor fiind adrese de tipul t. Astfel, dac' privim
memoria calculatorului ca un vector cu elemente de tipul
t, atunci rezultatul expresiei p+n este adresa elementului
aflat la n elemente distan#' dup' p, iar rezultatul expresiei
p-n este adresa elementului aflat la n elemente distan#'
naintea lui p.
Dac' p $i q sunt pointeri cu tipul de baz' t, atunci
expresiile p-q $i q-p sunt corecte, rezultatul lor fiind un
Pointeri $i gestiunea dinamic' a memoriei
208
num'r ntreg. Astfel, dac' privim memoria calculatorului
ca un vector cu elemente de tipul t, atunci rezultatul
expresiei p-q este num'rul de elemente de la p la q, iar
rezultatul expresiei q-p este num'rul de elemente de la q
la p,

Dac' p este un pointer cu tipul de baz' t $i n un
num'r ntreg, atunci expresia p[n] este corect', rezultatul
ei fiind o valoare de tipul t. Astfel, dac' privim memoria
calculatorului ca un vector cu elemente de tipul t, atunci
rezultatul expresiei p[n] este valoarea elementului aflat la
n elemente distan#' dup' lui p. Practic, expresia p[n] este
echivalent' cu expresia *(p+n).
De exemplu, n urma execu#iei instruc#iunilor
urm'toare:
int vec[10]; // un vector cu 10 elemente
intregi
int *p = &vec[2]; // p este pointer la al 3-
lea element din vec
int *q = &vec[4]; // q este pointer la al 5-
lea element din vec
p+2 este egal cu q, p-q este egal cu 2, q-2 este egal cu p,
iar p[2], q[0], *q $i vec[4] reprezint' aceea$i informa#ie.
p+3 p p-3
q-p=4
q
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
209
8.4. Legtura ntre tablouri $i pointeri
A$a cum s-a observat n sec#iunea anterioar', un
pointer poate fi folosit pentru a accesa elementele unui
masiv. Acest lucru este posibil deoarece numele unui
masiv este un pointer c'tre zona de memorie unde sunt
stocate elementele acestuia. Totu$i, valoarea acestui
pointer nu poate fi modificat' (deci este un pointer
constant).
Din acest motiv, un $ir de caractere (care este de
fapt un vector cu elemente de tip char $i ultimul caracter
NUL) poate fi privit ca un pointer la informa#ii de tip char
(vezi capitolul 8).
Aceast' rela#ie se poate generaliza $i pentru
masive multidimensionale. De exemplu, pentru
urm'toarele instruc#iuni:
int tab[10][20][30];
int *pt = &tab[0][0][0];
elementul tab[m][n][p] poate fi accesat $i prin
construc#iile (echivalente)
*(pt+(m*30+n)*20+p)
(pt+((m*30+n)*20)[p]
(pt+m*30*20)[n*20 + p]
pt[(m*30+n)*20 + p]
8.5. Gestiunea dinamic a memoriei
n limbajul C, dimensiunea fiec'rei variabile
trebuie cunoscut' n momentul compil'rii programului;
pentru variabilele cu tip fundamental, dimensiunea este
furnizat' implicit de tipul acestor; pentru masive,
Pointeri $i gestiunea dinamic' a memoriei
210
dimensiunea este furnizat' explicit prin dimensiunile
acestora ($i tipul elementelor), etc.
Pentru a lucra cu informa#ii ale c'ror dimensiuni
nu sunt cunoscute la momentul compil'rii programului
exist' dou' alternative: declararea la compilare a unor
dimensiuni care acoper' n mod sigur necesarul de
memorie sau alocarea memoriei necesare n timpul
execu#iei programului.
Func#iile standard pentru gestiunea dinamic' a
memoriei se g'sesc n biblioteca malloc.h. Pentru a fi
generale, aceste func#ii lucreaz' cu pointeri de tip void,
deci este necesar ca programatorul s' execute conversii
explicite de tip.
Tabel 8.1 Funcii standard pentru gestiunea
dinamic* a memoriei
Prototip void* calloc (unsigned cnt,
unsigned size)
Descriere Efect: aloc' o zon' de memorie de
dimensiune cnt*size octe#i $i completeaz'
cu valoarea 0 con#inutul acesteia.
Rezultat: adresa zonei de memorie alocate
sau NULL n caz de eroare
Prototip void* malloc (unsigned size)
Descriere Efect: aloc' o zon' de memorie de
dimensiune size octe#i
Rezultat: adresa zonei de memorie alocate
sau NULL n caz de eroare
Prototip void* realloc(void * ptr, unsigned
size)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
211
Descriere Efect: realoc' zona de memorie indicat' de
pointerul ptr astfel nct s' aib'
dimensiunea size octe#i
Rezultat: adresa zonei de memorie
realocate sau NULL n caz de eroare
Prototip void free (void *ptr)
Descriere Efect: elibereaz' zona de memorie indicat'
de pointerul ptr
Algoritmul general de lucru n cazul folosirii
dinamice a memoriei const' n alocarea memorie,
folosirea ei $i, n final, eliberarea acesteia.
De exemplu, dac' vrem s' citim de la tastatur'
un num'r variabil de valori ntregi putem folosi
urm'toarea secven#':
int i, nrvalori, *valori;
printf(Introduceti numarul de valori: );
scanf(%d, &nrvalori); // citim numarul de
valori
valori = (int *) calloc(nrvalori,
sizeof(int));
if(valori == NULL)
{
printf(Memorie insuficienta\n);
} else
{
for (i = 0; i < nrvalori; ++i)
{
printf(Introduceti valoarea a %d-a: ,
i+1);
scanf(%d, &valori[i]);
}
// alte operatii...
free(valori);
}
Pointeri $i gestiunea dinamic' a memoriei
212
8.6. Func#ii pentru opera#ii cu blocuri de
memorie
Aceste func#ii permit prelucrarea simpl'
informa#iei din memorie la nivel de octe#i, dar cu o vitez'
ridicat'. Func#iile standard pentru manipularea blocurilor
de memorie se g'sesc n biblioteca string.h. n
prototipurile acestor func#ii, parametrul c de tip int
reprezint' de fapt un octet (sau un caracter). Ele pot fi
folosite att pentru zone de memorie alocate dinamic, ct
$i pentru zone de memorie declarate static.
Tabel 8.2 Funcii standard pentru manipularea
blocurilor de memorie
Prototip void* memcpy (void *dest, void
*src, unsigned cnt)
Descriere Efect: copiaz' cnt octe#i din zona de
memorie src n dest (src $i dest trebuie s'
fie disjuncte)
Rezultat: adresa destina#ie dest
Prototip void* memccpy (void *dest, void
*src, int c, unsigned cnt)
Descriere Efect: copiaz' cnt octe#i din zona de
memorie src n dest sau pn' la apari#ia
primului octet c.
Rezultat: adresa din destina#ie a octetului
care urmeaz' dup' c sau NULL dac' c nu
apare n destina#ie ($i s-au copiat cnt octe#i)
Prototip void* memmove (void *dest, void
*src, unsigned cnt)
Descriere Efect: copiaz' cnt octe#i din zona de
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
213
memorie src n dest (nu neap'rat disjuncte).
Rezultat: adresa surs' src.
Prototip void* memchr (void *src, int c,
unsigned cnt)
Descriere Efect: caut' valoarea c n primii cnt octe#i
din zona de memorie src
Rezultat: adresa octetului c sau NULL dac'
c nu a fost g'sit
Prototip void* memset (void *dest, int c,
unsigned cnt)
Descriere Efect: scrie valoarea c n primii cnt octe#i din
zona de memorie dest
Rezultat: adresa destina#ie dest
Prototip int memcmp (void *src1, void *src2,
unsigned cnt)
Descriere Efect: compar' n ordine cel mult cnt octe#i
din zonele de memorie src1 $i src2
Rezultat: valoarea 0 dac' informa#ia din
src1 este identic' cu cea din src2; o valoare
negativ' dac' primul octet diferit din src1
este mai mic dect octetul corespunz'tor
din src2; o valoare pozitiv' dac' primul
octet diferit din src1 este mai mare dect
octetul corespunz'tor din src2
Prototip int memicmp (void *src1, void
*src2, unsigned cnt)
Descriere Efect: compar' n ordine cel mult cnt octe#i
din zonele de memorie src1 $i src2, f'r' a
face distinc#ie ntre literele mari $i mici.
Pointeri $i gestiunea dinamic' a memoriei
214
Rezultat: valoarea 0 dac' informa#ia din
src1 este la fel cu cea din src2; o valoare
negativ' dac' primul octet diferit din src1
este mai mic dect octetul corespunz'tor
din src2; o valoare pozitiv' dac' primul
octet diferit din src1 este mai mare dect
octetul corespunz'tor din src2
De exemplu, pentru a copia con#inutul unui vector
de numere ntregi cu 20 de elemente n alt vector putem
folosi urm'toare secven#' de program:
int src[20], dest[20];
...
memcpy(dest, src, sizeof(src));
8.7. Exemple
82. Programul urm'tor cite$te un vector de dimensiune
n (n citit de la tastatura) $i l afi$eaz' n ordine invers'.
Dimensiunea maxim' a vectorului depinde doar de
memoria calculatorului, nefiind fixat' la compilare.
Accesul la elementele vectorului se face prin pointeri $i
operatorul de dereferen#iere.
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
int main()
{
int n, i;
int *vector;
printf("Dimensiunea vectorului n:");
scanf("%i", &n);
vector = (int*) malloc(sizeof(int) * n);
for(i=0; i<n; ++i)
{
printf("Introduceti v[%d]:", i);
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
215
scanf("%i", vector + i);
}
for(i=n - 1; i>=0; --i)
printf("v[%i] = %i\n", i, *(vector + i));

free(vector);
getch();
}
Rezultatul execu#iei programului este:
Dimensiunea vectorului n:6
Introduceti v[0]:1
Introduceti v[1]:2
Introduceti v[2]:3
Introduceti v[3]:4
Introduceti v[4]:5
Introduceti v[5]:6
v[5] = 6
v[4] = 5
v[3] = 4
v[2] = 3
v[1] = 2
v[0] = 1
83. Urm'torul program cite$te un vector de n numere $i
verific' dac' este palindrom. Dimensiunea maxim' a
vectorului depinde doar de memoria calculatorului, nefiind
fixat' la compilare. Accesul la elementele vectorului se
face prin pointeri $i operatorul de indexare.
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
int main()
{
int n, i, pal=1;
int *vector;
printf("Dimensiunea vectorului n:");
scanf("%i", &n);
vector = (int*) malloc(sizeof(int) * n);
for(i=0; i<n; ++i)
{
Pointeri $i gestiunea dinamic' a memoriei
216
printf("Introduceti v[%d]:", i);
scanf("%i", &vector[i]);
}
for(i=0; i<n/2 && pal == 1; ++i)
if(vector[i] != vector[n-i-1])
pal = 0;
if(pal == 1)
printf("Vectorul este palindrom.\n");
else
printf("Vectorul nu este palindrom.\n");
free(vector);
getch();
}
Rezultatul execu#iei programului este:
Dimensiunea vectorului n:5
Introduceti v[0]:1
Introduceti v[1]:5
Introduceti v[2]:3
Introduceti v[3]:5
Introduceti v[4]:1
Vectorul este palindrom.
84. Urm'torul program determin' ordinea valorilor x $i y
ntr-un vector de ntregi, folosind pointeri c'tre tipul ntreg.
// Ordinea aparitiei valorilor x si y intr-un
vector de intregi
#include "stdio.h"
#include "conio.h"
int main()
{
int *p,*q,a[50],x,y,i,n;
p=a;
q=a;
printf(" n = ");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf(" a[%d]= ",i);
scanf("%d",a+i);
}
printf(" x = ");
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
217
scanf("%d",&x);
printf(" y = ");
scanf("%d",&y);
if(x!=y)
{
while( *p!=x && p<=a+n )
p++;
while( *q!=y && q<=a+n )
q++;
if(p==a+n+1 || q==a+n+1)
printf(" %d sau %d nu este componenta a
sirului \n",x,y);
else if(p>q)
printf(" y = %d precede x = %d
\n",y,x);
else
printf(" x = %d precede y = %d
\n",x,y);
}
else
printf(" x = y \n");
printf(" Sfarsit \n");
getch();
}
Un exemplu de rulare este urm'torul:
n = 5
a[0]= -12
a[1]= 3
a[2]= 21
a[3]= 54
a[4]= -2
x = 54
y = 3
y = 3 precede x = 54
85. Algoritmul de sortare prin numarare count_sort.
Presupunem c' dorim s' sort'm n numere naturale din
intervalul [1, m]. Algoritmul const' n construirea unui
vector v al frecventelor de apari#ie, n care v[i] este egal
cu num'rul apari#iilor num'rului i. Cele n numere pot fi
ordonate folosind frecventele lor de apari#ie. De exemplu
Pointeri $i gestiunea dinamic' a memoriei
218
(n=7 $i m=7) s' presupunem c' dorim s' sort'm
elementele din mul#imea {7, 2, 2, 2, 3, 4, 4}. Se
construie$te vectorul frecventelor v[1]=0 (1 nu este n
mul#ime), v[2]=3 (2 apare de trei ori), v[3]=1, v[4]=2,
v[5]=0, v[6]=0, v[7]=1. Pentru fiecare i cu proprietatea
v[i]!=0, se afi$eaz' i de v[i] ori. Vectorul sortat va fi 2, 2, 2,
3, 4, 4, 7.
//Sortare crescatoare prin metoda de numarare
count_sort
#include <stdio.h>
#include <conio.h>
#include <malloc.h>

// Prototipurile functiilor folosite in
program

void citeste_numere(int *, int, int); //
citirea celor n numere naturale cuprinse intre
1 si 100

void init_v(int *, int); // initializarea
vectorului frecventelor

void count_sort(int *, int *, int,int);
//functia pentru sortare prin numarare

void afis_sortc(int *, int); //functia de
afisare crescatoare a celor n numere sortate

void afis_sortd(int *, int); //functia de
afisare descrescatoare a celor n numere
sortate

// Functia pentru citirea vectorului
void citeste_numere(int x[],int n, int m)
{
int i;
for(i=0;i<n;i++)
{
printf(" Numarul %d = ",i+1);
scanf("%d",x+i);
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
219
if(x[i] <= 0 || x[i] > m)
{
printf(" Numarul %d nu este in domeniu
\n",x[i]);
break;
}
}
}

// Functia de initializare a vectorului
frecventelor
void init_v(int v[], int m)
{
int i;
for(i=1;i<=m;v[i]=0,i++);
}

// Functia count de sortare
void count_sort(int x[], int v[], int n, int
m)
{
int i,f,k;
printf(" Sortare \n");
for( k= 1 ; k <= m ; k++ )
{
f=0;
for(i = 0;i < n;i++)
if(x[i]==k)
f++;
v[k]=f;
}
}

// Functia pentru afisarea crescatoare a
numerelor
void afis_sortc(int v[], int m)
{
int i,k;
printf(" Afisare crescatoare \n");
for(i=1;i <= m;i++)
{
if(v[i]!=0)
for(k=1;k<=v[i];k++)
Pointeri $i gestiunea dinamic' a memoriei
220
printf("%d ",i);
}
printf("\n");
}

// Functia pentru afisarea descrescatoare a
numerelor
void afis_sortd(int v[], int m)
{
int i,k;
printf(" Afisare descrescatoare \n");
for(i=m;i >= 1 ;i--)
{
if(v[i]!=0)
for(k=1;k<=v[i];k++)
printf("%d ",i);
}
printf("\n");
}
// Vectorul numere (alocat dinamic) contine
numerele citite
// Vectorul v este vectorul (alocat dinamic)
// frecventelor numerelor in vectorul numere
// n numarul de numere citite
// nmax si m limitele lui n respectiv a
valorilor numerelor citite

int main()
{
long int nmax = 1000000;
int n, m = 100, *numere, *v;
char c;// variabila folosita in evitarea
utilizarii functiei getch()
printf(" n = ");
scanf("%d",&n);
//testul valorii lui n
if(n > 0 && n < nmax)
{
//alocare memorie pentru vectorul de numere
care se va citi
if(numere=(int *)malloc(n*sizeof(int)))
{
// citire numere
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
221
citeste_numere(numere,n,m);
//alocare memorie pentru vectorul
frecventelor
if(v=(int *)malloc(m*sizeof(int)))
{
//initializare vector frecvente
init_v(v,m);
//sortarea prin numarare
count_sort(numere,v,n,m);
//afisarea crescatoare a vectorului sortat
afis_sortc(v,m);
//afisarea descrescatoare a vectorului
sortat
afis_sortd(v,m);
//eliberarea zonelor de memorie alocate
free(numere);
free(v);
}
else printf(" Alocare esuata \n");
}
else printf(" Alocare esuata \n");}
else printf(" Numarul %d nu este in domeniu
\n",n);
getch();
}
Un exemplu de rulare a programului este:
n = 7
Numarul 1 = 7
Numarul 2 = 2
Numarul 3 = 2
Numarul 4 = 2
Numarul 5 = 3
Numarul 6 = 4
Numarul 7 = 4
Sortare
Afisare crescatoare
2 2 2 3 4 4 7
Afisare descrescatoare
7 4 4 3 2 2 2
Pointeri $i gestiunea dinamic' a memoriei
222
86. Urm'torul program cite$te un vector de n numere
ntregi (n citit de la tastatur') $i calculeaz' valoarea SAU
exclusiv ntre toate elementele vectorului.
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
int main()
{
int n, i, r = 0;
int *vector;
printf("Dimensiunea vectorului n:");
scanf("%i", &n);
vector = (int*) malloc(sizeof(int) * n);
for(i=0; i<n; ++i)
{
printf("Introduceti v[%d]:", i);
scanf("%i", vector + i);
}
for(i=0; i<n; ++i)
r ^= *(vector + i);

printf("Rezultat: %d", r);
free(vector);
getch();
}
Rezultatul execu#iei programului este:
Dimensiunea vectorului n:5
Introduceti v[0]:1
Introduceti v[1]:2
Introduceti v[2]:3
Introduceti v[3]:7
Introduceti v[4]:2
Rezultat: 5
8.8. Exerci#ii
74. Scrie#i o func#ie care prime$te ca parametri dou'
numere naturale m $i n $i cite$te de la tastatur' o matrice
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
223
de numere reale de dimensiune m x n. Memoria necesar'
pentru stocarea matricei trebuie alocat' dinamic de c'tre
func#ie. Scrie#i un program C care testeaz' func#ia.
75. Scrie#i o func#ie care permite adunarea a dou'
matrice $i un program C care testeaz' func#ia. Memoria
necesar' pentru stocarea rezultatului trebuie alocat'
dinamic de c'tre func#ie.
76. Scrie#i o func#ie care permite nmul#irea a dou'
matrice $i un program C care testeaz' func#ia. Memoria
necesar' pentru stocarea rezultatului trebuie alocat'
dinamic de c'tre func#ie.
77. Scrie#i o func#ie care prime$te ca parametru un
pointer la caractere $i returneaz' num'rul de caractere
de la acea loca#ie pn' la primul caracter NUL (cu codul
ASCII 0).
78. Scrie#i o func#ie care prime$te ca parametru doi
pointeri la caractere $i copiaz' caracter cu caracter,
con#inutul zonei de memorie indicate de primul pointer n
zona de memorie indicat' de al doilea pointer. Copierea
se opre$te dup' primul caracter NUL (cu codul ASCII 0).
225
9
99.
.. F
FFU
UUN
NNC
CC)
))I
III
II P
PPE
EEN
NNT
TTR
RRU
UU !
!!I
IIR
RRU
UUR
RRI
II D
DDE
EE C
CCA
AAR
RRA
AAC
CCT
TTE
EER
RRE
EE
9.1. 'iruri de caractere
n limbajul C, un $ir de caractere este de fapt un
vector de caractere, ultimul caracter fiind caracterul NUL,
care are codul ASCII 0. n general, $irurile de caractere
se scriu ntre ghilimele sub form' de secven#e de
caractere normale $i secven#e escape (e.g. "acesta este
un sir"). Tipul $irurilor de caractere este char[], adic'
vector de caractere, dar avnd n vedere rela#ia ntre
tablouri $i pointer, putem scrie char*, adic' pointer la
date de tip caracter. De exemplu, conform tabelului cu
codurile ASCII din Anexa 3 Setul de caractere ASCII,
$irul de caractere "Limbajul C" este stocat n memoria
calculatorului astfel:
76 105 109 98 97 106 117 108 32 67 0
Acest lucru poate fi verificat u$or cu urm'torul program:
#include <stdio.h>
#include <conio.h>
int main()
{
int i;
char sir[] = "Limbajul C";
for(i=0; i<=10; ++i)
Func#ii pentru $iruri de caractere
226
printf("%d ", sir[i]);
getch();
}
9.2. Func#ii pentru $iruri de caractere
Dac' dorim ca $irurile de caractere pe care le
afi$'m s' fie create dinamic, n func#ie de anumite
condi#ii, sau s' fie preluate de la utilizator, sau s'
efectu'm anumite opera#ii cu ele, atunci trebuie s'
folosim func#ii specializate pentru aceste lucruri.
Func#iile standard pentru prelucrarea $irurilor de
caractere se g'sesc n biblioteca string.h. n
prototipurile acestor func#ii, parametrul c de tip int
reprezint' de fapt un caracter (sau un octet).
Tabel 9.1 Funcii standard pentru $iruri de
caractere
Prototip unsigned strlen (char *sir)
Descriere Efect: calculeaz' lungimea $irului de
caractere sir
Rezultat: lungimea $irului de caractere sir
Prototip char* strlwr (char *sir)
Descriere Efect: transform' majusculele din $irul sir n
minuscule
Rezultat: adresa $irului modificat (adic' sir)
Prototip char* strupr (char *sir)
Descriere Efect: transform' minusculele din $irul sir n
majuscule
Rezultat: adresa $irului modificat (adic' sir)
Prototip char* strcat (char *dest, char
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
227
*src)
Descriere Efect: adaug' $irul src la sfr$itul $irului
dest
Rezultat: adresa $irului modificat (adic'
dest)
Prototip char* strncat (char *dest, char
*src, unsigned cnt)
Descriere Efect: adaug' cel mult cnt caractere din
$irul src la sfr$itul $irului dest
Rezultat: adresa $irului modificat (adic'
dest)
Prototip char* strchr (char *src, int c)
Descriere Efect: caut' prima apari#ie n $irul src a
caracterului c.
Rezultat: adresa caracterului c sau NULL
dac' c nu a fost g'sit
Prototip char* strrchr (char *src, int c)
Descriere Efect: caut' ultima apari#ie n $irul src a
caracterului c.
Rezultat: adresa caracterului c sau NULL
dac' c nu a fost g'sit
Prototip char* strstr (char *src, char *sub)
Descriere Efect: caut' prima apari#ie n $irul src a
sub$irului sub.
Rezultat: adresa $irului sub n src sau NULL
dac' sub nu a fost g'sit
Prototip char* strrev (char *sir)
Descriere Efect: inverseaz' $irul (va fi scris de la
coada la cap)
Func#ii pentru $iruri de caractere
228
Rezultat: adresa $irului modificat (adic' sir)
Prototip char* strcpy (char *dest, char
*src)
Descriere Efect: copiaz' $irul src n $irul dest
Rezultat: adresa $irului modificat (adic'
dest)
Prototip char* strncpy (char *dest, char
*src, unsigned cnt)
Descriere Efect: copiaz' cel mult cnt caractere din
$irul src n $irul dest (num'rul de caractere
copiate este minimul dintre cnt $i lungimea
$irului src).
Rezultat: adresa $irului modificat (adic'
dest)
Prototip char* strdup (char *src)
Descriere Efect: copiaz' $irul src ntr-o zon' de
memorie alocat' cu malloc; programatorul
trebuie s' elibereze cu func#ia free zona de
memorie cnd nu o mai folose$te.
Rezultat: adresa zonei de memorie alocat'
Prototip char* strset (char *dest, int c)
Descriere Efect: scrie caracterul c n fiecare pozi#ie din
$irul dest.
Rezultat: adresa $irului modificat (adic'
dest)
Prototip char* strnset (char *dest, int c,
unsigned cnt)
Descriere Efect: scrie caracterul c n primele cnt pozi#ii
din $irul dest.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
229
Rezultat: adresa $irului modificat (adic'
dest)
Prototip char* strcmp (char *src1, char
*src2)
Descriere Efect: compar' caracterele din $irurile src1
$i src2
Rezultat: valoarea 0 dac' $irurile src1 $i
src2 sunt identice; o valoare negativ' dac'
primul caracter diferit din src1 este mai mic
dect caracterul corespunz'tor din src2; o
valoare pozitiv' dac' primul caractere diferit
din src1 este mai mare dect caracterul
corespunz'tor din src2.
Prototip char* stricmp (char *src1, char
*src2)
Descriere Efect: compar' caracterele din $irurile src1
$i src2, f'r' a face distinc#ie ntre literele
mari $i mici.
Rezultat: valoarea 0 dac' $irurile src1 $i
src2 sunt la fel; o valoare negativ' dac'
primul caracter diferit din src1 este mai mic
dect caracterul corespunz'tor din src2; o
valoare pozitiv' dac' primul caractere diferit
din src1 este mai mare dect caracterul
corespunz'tor din src2.
Prototip char* strncmp (char *src1, char
*src2, unsigned cnt)
Descriere Efect: compar' cel mult cnt caractere din
$irurile src1 $i src2
Func#ii pentru $iruri de caractere
230
Rezultat: valoarea 0 dac' $irurile src1 $i
src2 sunt identice n zona comparat'; o
valoare negativ' dac' primul caracter diferit
din src1 este mai mic dect caracterul
corespunz'tor din src2; o valoare pozitiv'
dac' primul caractere diferit din src1 este
mai mare dect caracterul corespunz'tor
din src2.
Prototip char* strnicmp (char *src1, char
*src2, unsigned cnt)
Descriere Efect: compar' cel mult cnt caractere din
$irurile src1 $i src2, f'r' a face distinc#ie
ntre literele mari $i mici.
Rezultat: valoarea 0 dac' $irurile src1 $i
src2 sunt la fel n zona comparat'; o
valoare negativ' dac' primul caracter diferit
din src1 este mai mic dect caracterul
corespunz'tor din src2; o valoare pozitiv'
dac' primul caractere diferit din src1 este
mai mare dect caracterul corespunz'tor
din src2.
Secven#a urm'toare de program exemplific'
utilizarea func#iilor pentru $iruri de caractere prezentate
anterior:
char s1[] = "Limba", s2="Limbajul C", *s3;
int n;
n = strlen(s1); // n este 5
n = strcmp(s1, s2); // n este -1
strlwr(s1); // s1 este "limba"
n = strcmp(s1, s2); // n este 1
strupr(s1); // s1 este "LIMBA"
n = strnicmp(s1, s2, 5); // n este 0
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
231
s3 = strstr(s2, " "); // s3 este subsirul " C"
din s2
strcat(s1, s3); // s1 este "LIMBA C"
strnset(s1, '#'); // s1 este "#######"
strcpy(s3, s1); // s3 este "#######", deci
// s2 este "Limbajul#######"
9.3. Func#ii pentru clasificarea caracterelor
n afar' de func#iile pentru $iruri de caractere,
biblioteca standard ctype.h ofer' diverse func#ii pentru
testarea categoriei unui caracter (dac' e majuscul',
minuscul', cifr', etc.) $i eventual transformarea acestuia
(din majuscule n minuscule $i invers). Aceste func#ii
primesc ca unic parametru caracterul care trebuie testat
sau modificat.
Tabel 9.2 Funcii standard pentru clasificarea
caracterelor
Prototip int isalpha (int c)
Descriere Efect: testeaz' dac' c este o liter'
Rezultat: 1 dac' c este liter', 0 altfel
Prototip int islower (int c)
Descriere Efect: testeaz' dac' c este o minuscul'
Rezultat: 1 dac' c este minuscul', 0 altfel
Prototip int isupper (int c)
Descriere Efect: testeaz' dac' c este o majuscul'
Rezultat: 1 dac' c este majuscul', 0 altfel
Prototip int isdigit (int c)
Descriere Efect: testeaz' dac' c este o cifr'
Rezultat: 1 dac' c este cifr', 0 altfel
Prototip int isxdigit (int c)
Func#ii pentru $iruri de caractere
232
Descriere Efect: testeaz' dac' c este o cifr'
hexazecimal'
Rezultat: 1 dac' c este hexazecimal', 0
altfel
Prototip int isalnum (int c)
Descriere Efect: testeaz' dac' c este liter' sau cifr'
(echivalent cu expresia isalpha(c) ||
isdigit(c))
Rezultat: 1 dac' c este liter' sau cifr', 0
altfel
Prototip int isblank (int c)
Descriere Efect: testeaz' dac' c este caracter gol
(spa#iu sau tab)
Rezultat: 1 dac' c este caracter gol, 0 altfel
Prototip int isspace (int c)
Descriere Efect: testeaz' dac' c este caracter de
spa#iere (spa#iu, tab, new line, vertical tab,
form feed sau carriage return)
Rezultat: 1 dac' c este caracter de
spa#iere, 0 altfel
Prototip int iscntrl (int c)
Descriere Efect: testeaz' dac' c este caracter de
control (adic' are codul ASCII ntre 0 $i 31)
Rezultat: 1 dac' c este caracter de control,
0 altfel
Prototip int ispunct (int c)
Descriere Efect: testeaz' dac' c este caracter de
punctua#ie
Rezultat: 1 dac' c este caracter de
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
233
punctua#ie, 0 altfel
Prototip int isgraph (int c)
Descriere Efect: testeaz' dac' c are o reprezentare
grafic' (adic' este caracter tip'ribil vizibil).
Rezultat: 1 dac' c are reprezentare grafic',
0 altfel
Prototip int isprint (int c)
Descriere Efect: testeaz' dac' c este un caracter
afi$abil
Rezultat: 1 dac' c este caracter afi$abil, 0
altfel
Prototip int tolower (int c)
Descriere Efect: testeaz' dac' c este majuscul' $i
returneaz' minuscula corespunz'toare
Rezultat: minuscula corespunz'toare lui c,
dac' c este majuscul', sau valoarea lui c,
altfel
Prototip int toupper (int c)
Descriere Efect: testeaz' dac' c este minuscul' $i
returneaz' majuscula corespunz'toare
Rezultat: majuscula corespunz'toare lui c,
dac' c este minuscul', sau valoarea lui c,
altfel
9.4. Exemple
87. Programul urm'tor cite$te un mesaj de la tastatur'
$i afi$eaz' un extras din acesta. Extrasul este specificat
prin pozi#ia de nceput $i lungimea maxim' admis'.
#include <stdio.h>
Func#ii pentru $iruri de caractere
234
#include <string.h>
#include <conio.h>
int main()
{
char mesaj[256], extras[256];
int i, n, l;
printf("Introduceti un text:\n");
gets(mesaj);
printf("Pozitie de start: ");
scanf("%i", &n);
printf("Lungime: ");
scanf("%i", &l);
i = 0;
do
{
extras[i] = mesaj[i+n];
++i;
} while(extras[i-1] != 0 && i<l);
printf("Extras: %s", extras);
getch();
}
Introduceti un text:
Limbajul C are doar 32 de instructiuni!
Pozitie de start: 9
Lungime: 10
Extras: C are doar
88. Programul urm'tor cite$te un mesaj de la tastatur'
$i afi$eaz' mesajul n oglind' (de la dreapta la stnga).
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main()
{
char mesaj[256];
int i, len;
printf("Introduceti un text:\n");
gets(mesaj);
len = strlen(mesaj);
for(i = 0; i<len/2; ++i)
{
char temp = mesaj[i];
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
235
mesaj[i] = mesaj[len - i - 1];
mesaj[len - i - 1] = temp;
}
printf("Rezultat:\n%s", mesaj);
getch();
}
Introduceti un text:
Limbajul C
Rezultat:
C lujabmiL
89. Programul urm'tor cite$te un mesaj de la tastatur'
$i un num'r ntreg n $i afi$eaz' mesajul codificat prin
nlocuirea fiec'rui caracter cu caracterul aflat la distan#' n
n tabela codurilor ASCII.
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main()
{
char mesaj[256];
int i, len, n;
printf("Introduceti un text:\n");
gets(mesaj);
printf("Introduceti n:");
scanf("%d", &n);
len = strlen(mesaj);
for(i = 0; i<len; ++i)
mesaj[i] += n;
printf("Rezultat:\n%s", mesaj);
getch();
}
Introduceti un text:
Limbajul C
Introduceti n:1
Rezultat:
Mjncbkvm!D
De remarcat, c' un mesaj codificat cu valoarea n
poate fi decodificat cu valoarea -n.
Func#ii pentru $iruri de caractere
236
Introduceti un text:
Mjncbkvm!D
Introduceti n:-1
Rezultat:
Limbajul C
90. Programul urm'tor verific' dac' un $ir este
palindrom (adic' citit de la dreapta la stnga $i de la
stnga la dreapta ob#inem acela$i cuvnt).
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main()
{
char mesaj[256];
int i, len, pal = 1;
printf("Introduceti un text:\n");
gets(mesaj);
len = strlen(mesaj);
for(i = 0; i<len/2; ++i)
if(mesaj[i] != mesaj[len - i - 1])
pal = 0;
if(pal == 1)
printf("Sirul este palindron.");
else
printf("Sirul nu este palindrom.");
getch();
}
Introduceti un text:
capac
Sirul este palindrom.
91. Programul urm'tor verific' dac' un $ir este
palindrom f'r' a face diferen#e ntre majuscule $i
minuscule, folosind func#iile bibliotecii string.h.
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main()
{
char mesaj[256], oglinda[256];
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
237
int i, len;
printf("Introduceti un text:\n");
gets(mesaj);
strcpy(oglinda, mesaj);
strrev(oglinda);
if(stricmp(oglinda, mesaj) == 0)
printf("Sirul este palindron.");
else
printf("Sirul nu este palindron.");
getch();
}
92. Programul urm'tor cite$te un mesaj de la tastatur'
$i elimin' din acesta prima apari#ie a unui sub$ir citit tot
de la tastatur'.
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main()
{
char mesaj[256], subsir[50], *inceput;
int i, len;
printf("Introduceti un text:\n");
gets(mesaj);
printf("Introduceti subsirul:\n");
gets(subsir);
inceput = strstr(mesaj, subsir);
if(inceput != NULL)
{
len = strlen(subsir);
strcpy(inceput, inceput+len);
}
printf("Rezultat:\n%s", mesaj);
getch();
}
Introduceti un text:
Limbajul C are doar 32 de instructiuni!
Introduceti subsirul:
doar 32 de
Rezultat:
Limbajul C are instructiuni!
Func#ii pentru $iruri de caractere
238
93. Programul urm'tor afi$eaz' cuvintelor dintr-un $ir
de caractere cte unul pe linie. n acest context, un
cuvnt este un $ir de caractere cuprins ntre doi
separatori. Prin separator se n#elege aici, orice caracter.
Programul prime$te la intrare un $ir de caractere, o list'
de separatori $i afi$eaz' cuvintele din $irul introdus.
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main()
{
char sir[100], sep[10], *pozitie;
printf("Introduceti textul");
gets(sir);
printf("Introduceti separatorii");
gets(sep);
printf(" Cuvintele din text sunt: \n");
pozitie=strtok(sir, sep);
while(pozitie)
{
printf("%s\n", pozitie);
pozitie=strtok(NULL,sep);
}
getch();
}
Un exemplu de rulare este:
Introduceti textul:
Limbajul C are doar 32 de instructiuni!
Introduceti separatorii:
a d
Cuvintele din text sunt:
Limb
jul
C
re
o
r
32
e
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
239
instructiuni!
94. Programul urm'tor cite$te un mesaj de la tastatur'
$i afi$eaz' statistici despre acesta (lungimea total',
num'rul de majuscule, minuscule, cifre, semne de
punctua#ie $i caractere de spa#iere):
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
int main()
{
char mesaj[256];
int i, len, maj, min, cif, pct, spa;
printf("Introduceti un text:\n");
gets(mesaj);
len = strlen(mesaj);
maj = min = cif = pct = spa = 0;
for(i = 0; i<len; ++i)
if(islower(mesaj[i])) ++maj;
else if(isupper(mesaj[i])) ++min;
else if(isdigit(mesaj[i])) ++cif;
else if(ispunct(mesaj[i])) ++pct;
else if(isspace(mesaj[i])) ++spa;
printf("Lungime: %d\n", len);
printf("Majuscule: %d\n", maj);
printf("Minuscule: %d\n", min);
printf("Cifre: %d\n", cif);
printf("Semne de punctuatie: %d\n", pct);
printf("Spatii: %d\n", spa);
getch();
}
Introduceti un text:
Limbajul C are doar 32 de instructiuni!
Lungime: 39
Majuscule: 28
Minuscule: 2
Cifre: 2
Semne de punctuatie: 1
Spatii: 6
Func#ii pentru $iruri de caractere
240
95. Programul urm'tor transform' un $ir de caractere
citit de la tastatur' astfel nct fiecare cuvnt s' nceap'
cu o majuscul' $i s' con#in' n rest doar minuscule.
Variabila cuvantnou este folosit' pentru afla dac'
prelucr'm caracterele din interiorul unui cuvnt, sau
urmeaz' s' ncep un cuvnt nou.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
int main()
{
char mesaj[256];
int i, len, cuvantnou = 1;
printf("Introduceti un text:\n");
gets(mesaj);
len = strlen(mesaj);
for(i = 0; i<len; ++i)
if(isalpha(mesaj[i]))
if(cuvantnou)
{
mesaj[i] = toupper(mesaj[i]);
cuvantnou = 0;
}else
{
mesaj[i] = tolower(mesaj[i]);
}
else
cuvantnou = 1;
printf("Rezultat:\n%s", mesaj);
getch();
}
Introduceti un text:
limbajul c are doar 32 de instructiuni!
Rezultat:
Limbajul C Are Doar 32 De Instructiuni!
96. Func#ie pentru nlocuirea unui caracter c dintr-un $ir
de caractere, cu un alt caracter. Func#ia nlocuie$te toate
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
241
apari#iile caracterului c n $ir. Dac' c nu a fost g'sit se
emite un mesaj.
/ Inlocuire caracter in sir de caractere
#include "stdio.h"
#include "conio.h"
#include "string.h"
int inlocuire(char *x, char cs, char cd)
{
int i,k,gasit;
i=0;
gasit=0;
for(i=0;i<strlen(x);i++)
{
if(*(x+i)==cs)
{
gasit=1;
*(x+i)=cd;
}
}
if(gasit)
return 1;
else
return 0;
}
int main()
{
char sir[200],cars,card;
puts(" Sirul ");
gets(sir);
puts(" Caracterul de inlocuit ");
cars=getche();
puts("\n Caracterul cu care inlocuiesc ");
card=getche();
if(inlocuire(sir,cars,card))
{
puts("\n Sirul modificat ");
puts(sir);
}
else
printf("\n Caracterul %c nu a fost gasit
in sirul %s \n",cars,sir);
getch();
Func#ii pentru $iruri de caractere
242
}
Un exemplu de rulare este urm'torul:
Sirul
inlocuire caracter
Caracterul de inlocuit
c
Caracterul cu care inlocuiesc
?
Sirul modificat
inlo?uire ?ara?ter

Sirul
abac
Caracterul de inlocuit
!
Caracterul cu care inlocuiesc
?
Caracterul ! nu a fost gasit in sirul abac
97. Func#ie pentru inserarea unui $ir surs' ntr-un $ir
destina#ie dup' caracterul aflat pe pozi#ia n n $irul
destina#ie. Dac' n=-1 se insereaz' $irul surs' n fa#a
$irului destina#ie. Dac' n este egal cu lungimea $irului
destina#ie minus 1 se ob#ine concatenarea celor dou'
$iruri.
//Inserare sir sursa in sir destinatie la
pozitia n
// Pentru n=-1 se insereaza in fata
destinatiei
// Pentru n=(lungimea destinatiei - 1) se
obtine concatenare
#include "stdio.h"
#include "conio.h"
void insert(char *d, char *s, int n)
{
int is,id,im;
char m[100];
im=0;
id=n+1;
while(*(d+id)!='\0')
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
243
{
m[im]=*(d+id);
id++;
im++;
}
id=n+1;
m[im]='\0';
is=0;
while(*(s+is)!='\0')
{
*(d+id)=*(s+is);
id++;
is++;
}
im=0;
while(*(m+im)!='\0')
{
*(d+id)=*(m+im);
id++;
im++;
}
*(d+id)='\0';
}
int main()
{
char sird[100],sirs[100];
int n;
puts(" Sirul sursa ");
gets(sirs);
puts(" Sirul destinatie ");
gets(sird);
puts(" Pozitia de inceput a inserarii ");
scanf("%d",&n);
insert(sird,sirs,n);
puts(sird);
getch();
}
Un exemplu de rulare este:
Sirul sursa
sir sursa
Sirul destinatie
sir destinatie
Func#ii pentru $iruri de caractere
244
Pozitia de inceput a inserarii
-1
sir sursa sir destinatie

Sirul sursa
sir sursa
Sirul destinatie
sir destinatie
Pozitia de inceput a inserarii
3
sir sir sursa destinatie

Sirul sursa
sir sursa
Sirul destinatie
sir destinatie
Pozitia de inceput a inserarii
14
sir destinatie sir sursa
98. Func#ie pentru $tergerea tuturor apari#iilor unui
caracter dintr-un $ir de caractere. Dac' $irul nu con#ine
caracterul respectiv se emite un mesaj corespunz'tor.
// Stergere caracter
#include "stdio.h"
#include "conio.h"
#include "string.h"
int sterg(char *x, char c)
{
int i,k,j,este;
i=0;este=0;
while(i<strlen(x))
{
j=i;
while(*(x+j)==c)
{
este=1;
for(k=j;*(x+k)!='\0';k++)
*(x+k)=*(x+k+1);
*(x+k+1)='\0';
}
i++;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
245
}
return este;
}
int main()
{
char sir[200],sirm[200],car;
puts(" Sirul ");
gets(sir);
strcpy(sirm,sir);
puts(" Caracterul care va fi sters ");
scanf("%c",&car);
if(sterg(sir,car))
{
printf("Caracterul %c a fost garsit in
sirul %s \n", car,sirm);
puts(" Sirul modificat ");
puts(sir);
}
else
printf(" Caracterul %c nu a fost gasit in
sirul %s \n",car,sir);
getch();
}
Un exemplu de rulare este:
Sirul
stergere caracter
Caracterul care va fi sters
c
Caracterul c a fost garsit in sirul stergere
caracter
Sirul modificat
stergere arater

Sirul
stergere caracter
Caracterul care va fi sters
#
Caracterul # nu a fost gasit in sirul
stergere caracter
Func#ii pentru $iruri de caractere
246
99. Programul urm'tor transform' toate minusculele
unui $ir de caractere n majuscule $i apoi, toate
majusculele n minuscule.
// Minuscule majuscule
#include "stdio.h"
#include "conio.h"
#include "ctype.h"
void schimb_m_M(char x[])// minuscule in
majuscule
{
int i;
i=0;
while(x[i]!='\0')
{
x[i]=toupper(x[i]);
i++;
}
}
void schimb_M_m(char x[])// majuscule in
minuscule
{
int i;
i=0;
while(x[i]!='\0')
{
x[i]=tolower(x[i]);
i++;
}
}
int main()
{
char s[100];
puts(" Tastati un sir de caractere ");
gets(s);
schimb_m_M(s);
printf(" Transformarea tuturor minusculelor
in majuscule\n");
puts(" Sirul modificat este ");
puts(s);
getch();
schimb_M_m(s);
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
247
printf(" Transformarea tuturor majusculelor
in minuscule\n");
puts(" Sirul modificat este ");
puts(s);
getch();
}
Un exemplu de rulare este:
Tastati un sir de caractere
TransFormare minuscule - MAJUSCULE
Transformarea tuturor minusculelor in
majuscule
Sirul modificat este
TRANSFORMARE MINUSCULE - MAJUSCULE
Transformarea tuturor majusculelor in
minuscule
Sirul modificat este
transformare minuscule - majuscule
100. Programul urm'tor transform' un $ir de caractere
citit de la tastatur' astfel nct primul cuvnt din fiecare
fraz' s' nceap' cu majuscul', restul literelor fiind
minuscule. Variabila frazanoua este folosit' pentru afla
dac' prelucr'm caracterele din interiorul unei fraze, sau
urmeaz' s' ncepem o fraz' nou'.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
int main()
{
char mesaj[256];
int i, len, frazanoua = 1;
printf("Introduceti un text:\n");
gets(mesaj);
len = strlen(mesaj);
for(i = 0; i<len; ++i)
if(isalpha(mesaj[i]))
if(frazanoua)
{
mesaj[i] = toupper(mesaj[i]);
Func#ii pentru $iruri de caractere
248
frazanoua = 0;
}else
{
mesaj[i] = tolower(mesaj[i]);
}
else if(ispunct(mesaj[i]))
frazanoua = 1;
printf("Rezultat:\n%s", mesaj);
getch();
}
Introduceti un text:
limbajul c are putine instructiuni. asta e
bine.
Rezultat:
Limbajul c are putine instructiuni. Asta e
bine.
9.5. Exerci#ii
79. Scrie#i un program C care cite$te de la tastatur' un
$ir de caractere A $i un caracter B, $i afi$eaz' num'rul de
apari#ii ale caracterului B n $irul A.
80. Scrie#i un program C care cite$te de la tastatur'
dou' $iruri de caractere A $i B, $i afi$eaz' num'rul de
apari#ii ale $irului B n $irul A.
81. Scrie#i un program C care cite$te de la tastatur'
dou' $iruri de caractere A $i B, $i un num'r natural n, $i
afi$eaz' pe ecran $irul A n care a fost inserat $irul B la
pozi#ia n.
82. Scrie#i un program C care cite$te de la tastatur'
$iruri de caractere $i afi$eaz' pe ecran lungimea $i $irul
respectiv. Citirea se opre$te la introducerea $irului vid (cu
lungime 0) de c'tre utilizator.
83. Scrie#i un program C care cite$te de la tastatur'
$iruri de caractere $i le afi$eaz' pe ecran nlocuind
majusculele cu minuscule. Citirea se opre$te la
introducerea $irului vid (cu lungime 0) de c'tre utilizator.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
249
84. Scrie#i un program C care cite$te o succesiune de
cuvinte. Citirea se opre$te la introducerea $irului vid (cu
lungime 0) de c'tre utilizator. Programul afi$eaz' apoi
cuvntul cel mai lung.
85. Scrie#i un program C care cite$te o succesiune de
cuvinte. Citirea se opre$te la introducerea $irului vid (cu
lungime 0) de c'tre utilizator. Programul afi$eaz' apoi
cuvntul cel mai mare din punct de vedere lexicografic
(de exemplu, "casa" este mai mare din punct de vedere
lexicografic dect "dar").
86. Scrie#i un program C care cite$te o succesiune de
cuvinte, le sorteaz' n ordine cresc'toare $i apoi le
afi$eaz' n aceast' ordine.
251
1
110
00.
.. F
FFU
UUN
NNC
CC)
))I
III
II M
MMA
AAT
TTE
EEM
MMA
AAT
TTI
IIC
CCE
EE
Biblioteca limbajului C pune la dispozi#ia
utilizatorului un num'r de func#ii matematice. Aceste
func#ii au prototipurile n fi$ierul antet math.h, stdlib.h
$i/sau complex.h. Orice program care folose$te astfel de
func#ii trebuie s' con#in' directivele compilator:
#include <math.h>
#include <stdlib.h>
#include <complex.h>
mpreun' cu aceste func#ii, sunt disponibile
valorile unor constante remarcabile din matematic',
definite prin constante simbolice. Vom prezenta n
continuare constantele simbolice $i cele mai utilizate
dintre aceste func#ii.
Tabel 10.1 Constante simbolice
Nume Valoare Descriere
M_E 2.7182818284590452354 e
M_LOG2E 1.4426950408889634074
2
log e
M_LOG10E 0.43429448190325182765
lge
M_LN2 0.69314718055994530942 ln 2
M_LN10 2.30258509299404568402 ln10
Func#ii matematice
252
M_PI 3.14159265358979323846
M_PI_2 1.57079632679489661923
2


M_PI_4 0.78539816339744830962
4


M_1_PI 0.31830988618379067154
1


M_2_PI 0.63661977236758134308
2


M_2_SQRTPI 1.12837916709551257390
2


M_SQRT2 1.41421356237309504880 2
M_SQRT1_2 0.70710678118654752440
1
2

Tabel 10.2 Funcii trigonometrice
Prototip double sin (double x)
Descriere Returneaz' ( ) sin x n [ ] 1,1
Prototip double cos (double x)
Descriere Returneaz' ( ) cos x n [ ] 1,1
Prototip double asin (double x)
Descriere
Returneaz' ( ) arcsin x n ,
2 2
_


,
.
Argumentul [ ] 1,1 x
Prototip double acos (double x)
Descriere Returneaz' ( ) arccos x n ( ) 0, . Argumentul
[ ] 1,1 x
Prototip double tan (double x)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
253
Descriere
Returneaz' ( ) tg x n R , ( ) 2 1
2
x k

+ ,
( ) k Z
Prototip double atan (double x)
Descriere
Returneaz' ( ) arctg x n ,
2 2
_


,

Prototip double atan2 (double x, double y)
Descriere
Returneaz'
x
arctg
y
_

,
n ,
2 2
_


,

Tabel 10.3 Funcii putere $i radical
Prototip double pow (double x, double y)
Descriere Returneaz'
y
x , 0 x >
Prototip double sqrt (double x)
Descriere Returneaz' x , 0 x
Tabel 10.4 Funcii exponeniale, logaritmice,
hiperbolice
Prototip double exp (double x)
Descriere Returneaz'
x
e
Prototip double log (double x)
Descriere Returneaz' ln x , 0 x >
Prototip double log10 (double x)
Descriere
Returneaz' lg x , 0 x >
Prototip double log2 (double x)
Descriere Returneaz'
2
l g o x , 0 x >
Prototip double sinh (double x)
Descriere
Returneaz' sh( )
2
x x
e e
x


Func#ii matematice
254
Prototip double cosh (double x)
Descriere
Returneaz' ch( )
2
x x
e e
x

+

Prototip double tanh (double x)
Descriere
Returneaz'
( )
th( )
( )
sh x
x
ch x

Prototip double sinh (double x)
Descriere
Returneaz' inversa func#iei sh( )
2
x x
e e
x


Prototip double cosh (double x)
Descriere
Returneaz' inversa func#iei ch( )
2
x x
e e
x

+

Prototip double tanh (double x)
Descriere
Returneaz' inversa func#iei
( )
th( )
( )
sh x
x
ch x

Tabel 10.5 Funcii de conversie
Prototip int atoi (const char* c)
Descriere Conversie $ir de caractere n ntreg
Prototip double atof (const char* c)
Descriere Conversie $ir de caractere n double
Prototip long atoll (const char* c)
Descriere Conversie $ir de caractere n ntreg lung
Tabel 10.6 Funcii de rotunjire, trunchiere,
modul
Prototip double floor (double x)
Descriere Returneaz' cel mai mare ntreg mai mic
dect x , x 1
]

Prototip double ceil (double x)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
255
Descriere Returneaz' cel mai mic ntreg mai mare
dect x , x 1
1

Prototip double round (double x)
Descriere Func#ie de rotunjire a lui x
Prototip double trunc (double x)
Descriere Returneaz' trunchierea lui x
Prototip int abs (int x)
Descriere Returneaz' x , x Z
Prototip double fabs (double x)
Descriere Returneaz' x , x R
Tabel 10.7 Funcii pentru generare numere
aleatoare
Prototip int rand ()
Descriere Returneaz' la fiecare apel un num'r natural
aleatoriu
Prototip void srand (unsigned s)
Descriere Ini#ializeaz' valoarea de start a secven#ei
de numere aleatoare produse cu rand.
10.1. Exemple
101. Programul urm'tor calculeaz' valorile unei func#ii
reale de o singur' variabil' real', ntr-un interval dat. Fie
func#ia : f R R , definit' astfel:
( )
( )
( ) [ ]
( ) ( ) ( )
2
1
2 3
, , 1
1ln 1 1,1
sin * 1,
x
xe x
f x x x x
x sh x x

+ +
'


Func#ii matematice
256
Vom scrie programul care calculeaz' valorile
func#iei f n 2 n + puncte din intervalul [ ] , a b . Folosind
expresia analitic' a func#iei f definim func#ia f n
limbajul C astfel:
double f(double x)
{
if(x<-1)
return x*exp(1-pow(x,2));
if(x>=-1 && x<=1)
return pow(x+1,1.0/3)* log(1+pow(x,2));
if(x>1)
return sin(x)*sinh(x);
}
Datele de intrare sunt extremit'#ile intervalului
[ ] , a b $i num'rul n de puncte din intervalul ( ) , a b n care
se calculeaz' valorile func#iei. Pentru lucrul cu o alt'
func#ie se modific' n mod corespunz'tor defini#ia func#iei
f.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <conio.h>
double f(double x)
{
if(x<-1)
return x*exp(1-pow(x,2));
if(x>=-1 && x<=1)
return pow(x+1,1.0/3)* log(1+pow(x,2));
if(x>1)
return sin(x)*sinh(x);
}
int main()
{
double a,b,h,x;
int n,k;
printf("Extremitatile intervalului [a,b]
\n");
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
257
printf(" a = ");
scanf(%lf, &a);
printf(" b = ");
scanf(%lf, &b);
printf("Numarul de puncte din intervalul
(%f, %f) in care se calculeaza f(x)=", a, b);
scanf("%d",&n);
h=(b-a)/n;
for(k=0,x=a; k<=n+1; x=a+k*h,k++)
printf("%d. f ( %f ) = %f \n",k+1,x,f(x));
getch();
}
Ca exemplu am folosit intervalul [ ] 2, 2 $i 10 n .
Extremitatile intervalului [a,b]
a = -2
b = 2
Numarul de puncte din intervalul (-2.000000,
2.000000) in care se calculeaza f(x) = 10
1. f ( -2.000000 ) = -0.099574
2. f ( -2.000000 ) = -0.099574
3. f ( -1.600000 ) = -0.336218
4. f ( -1.200000 ) = -0.772844
5. f ( -0.800000 ) = 0.289300
6. f ( -0.400000 ) = 0.125182
7. f ( 0.000000 ) = 0.000000
8. f ( 0.400000 ) = 0.166036
9. f ( 0.800000 ) = 0.601769
10. f ( 1.200000 ) = 1.406877
11. f ( 1.600000 ) = 2.374555
12. f ( 2.000000 ) = 3.297895
102. Program urm'tor calculeaz' valorile unei func#ii
reale de dou' variabile reale, ntr-un domeniu dat. Fie
func#ia
2
: f R R , ( ) ( ) , f x y arctg x y + , ( )
2
, x y R .
Vom scrie programul care calculeaz' valorile func#iei f
n domeniul [ ] [ ]
2
, , a b c d R . Folosind expresia analitic'
a func#iei f definim func#ia f n limbajul C astfel:
double f(double x, double y)
Func#ii matematice
258
{
return atan(x+y);
}
Datele de intrare sunt extremit'#ile a,b,c,d ale
domeniului, num'rul n de puncte din intervalul ( ) , a b $i
num'rul m de puncte din intervalul ( ) , c d n care se
calculeaz' valorile func#iei. Pentru lucrul cu o alt' func#ie
se modific' n mod corespunz'tor defini#ia func#iei f.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <conio.h>
double f(double x, double y)
{
return atan(x+y);
}
int main()
{
double x,y,a,b,c,d,hx,hy;
int n,m,k,p,nrp;
printf("Extremitatile intervalului [a,b]
\n");
printf("a = ");
scanf(%lf, &a);
printf("b = ");
scanf(%lf, &b);
printf("Extremitatile intervalului [c,d]
\n");
printf("c = ");
scanf(%lf, &c);
printf("d = ");
scanf(%lf, &d);
printf("Numarul de puncte din intervalul
(%f, %f) in care se calculeaza f(x,y) =
",a,b);
scanf("%d",&n);
printf("Numarul de puncte din intervalul
(%f, %f) in care se calculeaza f(x,y) =
",c,d);
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
259
scanf("%d",&m);
hx=(b-a)/n;
hy=(d-c)/m;
for(k=0,x=a,nrp=1;k<=n;k++,x=a+k*hx)
for(p=0,y=c;p<=m;p++,y=c+p*hy,nrp++)
printf("%d. f ( %f, %f ) = %f\n", nrp,
x, y, f(x,y));
getch();
}
Ca exemplu am folosit domeniul [ ] [ ] 2,1 3, 4 ,
2 n $i 2 m .
Extremitatile intervalului [a,b]
a = -2
b = 1
Extremitatile intervalului [c,d]
c = -3
d = 4
Numarul de puncte din intervalul (-2.000000,
1.000000) in care se calculeaza f(x) = 2
Numarul de puncte din intervalul (-3.000000,
4.000000) in care se calculeaza f(x) = 2
1. f ( -2.000000, -3.000000 ) = -1.373401
2. f ( -2.000000, 0.500000 ) = -0.982794
3. f ( -2.000000, 4.000000 ) = 1.107149
4. f ( -0.500000, -3.000000 ) = -1.292497
5. f ( -0.500000, 0.500000 ) = 0.000000
6. f ( -0.500000, 4.000000 ) = 1.292497
7. f ( 1.000000, -3.000000 ) = -1.107149
8. f ( 1.000000, 0.500000 ) = 0.982794
9. f ( 1.000000, 4.000000 ) = 1.373401
103. Urm'torul program prezint' aproximarea solu#iilor
ecua#iilor neliniare cu metoda lui Newton. Fie
[ ] : , f a b R , [ ] ( )
2
, f C a b , ( ) 0 f x , ( ) ( ) , x a b $i
ecua#ia ( ) 0 f x , care are o singur' r'd'cin' n
intervalul [ ] , a b . Metoda lui Newton (a tangentei) const'
n construirea $irului de aproxima#ii ($irul lui Newton):
Func#ii matematice
260
[ ]
0
, x a b , care satisface condi#ia Fourier,
( ) ( )
0 0
0 f x f x > ,
( )
( )
1
n
n n
n
f x
x x
f x
+

, ( ) n N . Acest $ir
este convergent $i tinde la solu#ia exact' a ecua#iei
( ) 0 f x . Dac' este pragul de eroare, generarea
termenilor $irului de aproxima#ii se termin' cnd
1 n n
x x
+
< . Ca exemplu am considerat func#ia
[ ] : 0,1 f R , ( )
3
3 1 f x x x + $i ecua#ia ( ) 0 f x , care
are n intervalul [ ] 0,1 o singur' solu#ie. Func#iile f, fd,
fd2 codific' func#iile ( ) ( ) , f x f x $i respectiv ( ) f x .
Func#ia recursiv' x calculeaz' termenii $irului
aproxima#iilor.
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <stdlib.h>
double f(double x)
{
return pow(x,3)-3*x+1;
}
double fd(double x)
{
return 3*pow(x,2)-3;
}
double fd2(double x)
{
return 6*x;
}
double x(int n, double p)
{
if(n==0)
return p;
else
return x(n-1,p)-f(x(n-1,p))/fd(x(n-1,p));
}
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
261
int main()
{
double p, e, eps, a, b;
int n;
printf("Intervalul [a,b]\n");
printf("a = ");
scanf("%lf",&a);
printf("b = ");
scanf("%lf",&b);
if(f(a)*fd2(a)>0) p=a;
if(f(b)*fd2(b)>0) p=b;
printf("Eroarea de aproximare eps : ");
scanf("%d",&eps);
e=eps+1;
n=0;
while(e>eps)
{
printf("x ( %d ) = %f\n",n,x(n,p));
e=fabs(x(n+1,p)-x(n,p));
n++;
}
printf("Numar total de iteratii = %d \n",n-
1);
printf("Solutia ecuatiei cu eroarea %f este
%f\n", eps, x(n,p));
getch();
}
Rezultatele rul'rii programului sunt urm'toarele:
Intervalul [a,b]
a = 0
b = 1
Eroarea de aproximare eps : 0.00001
x ( 0 ) = 0.000000
x ( 1 ) = 0.333333
x ( 2 ) = 0.347222
x ( 3 ) = 0.347296
Numar total de iteratii = 3
Solutia ecuatiei cu eroarea 0.000010 este
0.347296
Func#ii matematice
262
104. Urm'torul program prezint' o metod' pentru
aproximarea integralei ( )
b
a
f x dx

cu metoda Simpson
1/3. Fie [ ] : , f a b R , continu' pe [ ] , a b ,
[ ]
{ }
0 1 2 ,
, , ,
n a b
x x x L o diviziune echidistant' a intervalului
[ ] , a b ,
0 1 2
...
n
a x x x b < < < ,
2
b a
h
n

,
0 i
x x ih + ,
1, 2,..., 2 i n . n aceste condi#ii, se poate demonstra c'
are loc aproximarea
( ) ( ) ( ) ( ) ( )
1
2 2 1
1 1
~ 2 4
3
b
n n
k k
k k
a
h
f x dx f a f b f x f x


_
+ + +

,

,
cunoscut' ca fiind formula lui Simpson 1/3, care poate fi
u$or programat'. Datele de intrare sunt , a b $i n .
Programul furnizeaz' valoarea aproximativ' a integralei
( )
b
a
f x dx

. Ca exemplu vom aproxima


1
2
0
1
1
dx
x +

, care are
valoarea exact' M_PI_4, adic'
0.78539816339744830962. Modificnd n program
defini#ia func#iei f, programul poate fi folosit pentru
aproximarea oric'rei integrale.
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <stdlib.h>
double f(double x)
{
return 1/(x*x+1);
}
int main()
{
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
263
double a,b,h,xi,yi,sp,si,valint;
int n, i;
printf("Intervalul de integrare \n");
printf(" a = ");
scanf(%lf, &a);
printf(" b = ");
scanf(%lf, &b);
printf("Numarul nodurilor n = ");
scanf(%i, &n);
h=(b-a)/(2*n);
for(i=0,xi=a,sp=0,si=0;i<=2*n;i++) {
if(i%2==0)
si=si+f(xi);
else
sp=sp+f(xi);
xi=xi+h;
}
valint=(f(a)+f(b)+4*si+2*sp)*h/3;
printf("Valoarea integralei este
%f\n",valint);
getch();
}
Rezultatul rul'rii programului este:
Intervalul de integrare
a = 0
b = 1
Numarul nodurilor n = 1000000
Valoarea integralei este 0.785399
105. Programul urm'tor prezint' aproximarea valorilor
solu#iei ecua#iei diferen#iale ( ) ( ) ( ) , y x f x y x , [ ] , x a b ,
cu condi#ia ini#ial' ( )
0
y a y , cu metoda Euler. Fie ecua#ia
diferen#ial' ( ) ( ) ( ) , y x f x y x , [ ] , x a b , cu condi#ia
ini#ial' ( )
0
y a y . Fie
[ ]
{ }
0 1 ,
, , ...,
n a b
x x x o diviziune
echidistant' a intervalului [ ] , a b ,
0 1
...
n
a x x x b < < < ,
Func#ii matematice
264
b a
h
n

,
0 i
x x ih + , ( )
i i
y y x 1, 2,..., i n . n aceste
condi#ii, se poate demonstra c' valorile func#iei
necunoscute y , n punctele diviziunii
[ ] , a b
, sunt date de
termenii $irului lui Euler: ( )
0
y y a , ( )
1
,
i i i i
y y hf x y
+
+ ,
1, 2,..., i n . Valorile aproximative sunt cu att mai
apropiate de valorile exacte cu cat n este mai mare. Ca
exemplu am considerat ecua#ia diferen#ial'
( ) ( ) 2 , 0 1 y x xy y . n acest exemplu ( ) , 2 f x y xy .
Aceast' ecua#ie are solu#ia exact' ( )
2
x
y x e . Programul
listeaz', pentru compara#ie, valorile exacte ale solu#iei $i
pe cele aproximative. Pentru calculul valorilor func#iei
( ) , 2 f x y xy , am definit n program func#ia f. Modificnd
corespunz'tor func#ia f, programul poate aproxima
solu#ia oric'rei ecua#ii diferen#iale de acest tip.
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <stdlib.h>
double f(double x,double y)
{
return 2*x*y;
}
int main()
{
double y0,a,b,h,xi,yi,ye;
int n, i;
printf(" Intervalul [a,b] \n");
printf(" a = ");
scanf("%lf", &a);
printf(" b = ");
scanf("%lf", &b);
printf(" Numarul de puncte n = ");
scanf("%i", &n);
printf(" Conditia initiala y0 = ");
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
265
scanf("%lf", &y0);
h=(b-a)/n;
printf("Valoare aproximativa\tValoare
exacta\n");
for(i=0,xi=a,yi=y0;i<=n;i++)
{
yi=yi+h*f(xi,yi);
ye=exp(pow(xi,2.));
printf("y(%f) = %f\ty(%f) = %f \n", xi,
yi, xi, ye);
xi=xi+h;
}
getch();
}
Rezultatul rul'rii programului este:
Intervalul [a,b]
a = 0
b = 1
Numarul de puncte n = 10
Conditia initiala y0 = 1
Valoare aproximativa Valoare exacta
y(0.000000) = 1.000000 y(0.000000) =
1.000000
y(0.100000) = 1.020000 y(0.100000) =
1.010050
y(0.200000) = 1.060800 y(0.200000) =
1.040811
y(0.300000) = 1.124448 y(0.300000) =
1.094174
y(0.400000) = 1.214404 y(0.400000) =
1.173511
y(0.500000) = 1.335844 y(0.500000) =
1.284025
y(0.600000) = 1.496146 y(0.600000) =
1.433329
y(0.700000) = 1.705606 y(0.700000) =
1.632316
y(0.800000) = 1.978503 y(0.800000) =
1.896481
y(0.900000) = 2.334633 y(0.900000) =
2.247908
Func#ii matematice
266
y(1.000000) = 2.801560 y(1.000000) =
2.718282
i Deoarece am introdus pentru n o valoare mic',
aproxima#ia este destul de slab'. Invit'm cititorul s'
compare rezultatele pentru n>1000.
106. Scrie#i un program C care aproximeaz' num'rul e
folosind formula
0
1
!
n
n
i
e
i

pentru un num'r natural n.


#include <stdio.h>
#include <math.h>
#include <conio.h>
int main()
{
int i;
double s = 1, ifact= 1, err;
printf("Introduceti eroarea minima: ");
scanf("%lf", &err);
printf("Calculat Corect Eroare\n");
for(i=1; fabs(s-M_E) > err; ++i)
{
ifact*= i;
s += 1/ifact;
printf("%f %f %f\n", s, M_E, fabs(s-
M_E));
}
printf("Minim de pasi: %d", i);
getch();
}
Introduceti eroarea minima: 0.00001
Calculat Corect Eroare
2.000000 2.718282 0.718282
2.500000 2.718282 0.218282
2.666667 2.718282 0.051615
2.708333 2.718282 0.009948
2.716667 2.718282 0.001615
2.718056 2.718282 0.000226
2.718254 2.718282 0.000028
2.718279 2.718282 0.000003
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
267
Minim de pasi: 9
10.2. Exerci#ii
87. Scrie#i un program C care determin' perimetrul $i
aria unui triunghi cunoscnd lungimile laturilor.
88. Scrie#i un program C care cite$te un unghi n grade
sexagesimale $i calculeaz' valoarea func#iei sinus,
cosinus $i tangent'.
89. Scrie#i un program C care determin' valoarea
minim' a num'rului natural n astfel nct eroarea
num'rului aproximat cu formula
2
1
1
6
n
n
i
i


s' scad'
sub un anumit prag specificat de utilizator.
90. Scrie#i un program C care afi$eaz' valoarea func#iei
1
( ) sin( ) cos( )
n
i
f n i i

, pentru un num'r n citit de la


tastatur'.
91. Scrie#i un program C care afi$eaz' valoarea func#iei
1
( )
n
i
i
f n e i

, pentru un num'r n citit de la tastatur'.


92. Scrie#i un program C care afi$eaz' valoarea func#iei
1
sin( ) cos( )
( )
n
i
i
i i
f n
i

, pentru un num'r n citit de la


tastatur'.
93. Scrie#i un program C care afi$eaz' valoarea func#iei
1 1
( ) ( 1)
n i
j j
i j
f n j

, pentru un num'r n citit de la


tastatur'.
94. Scrie#i un program C care determin' dac' un num'r
natural n citit de la tastatur' este num'r narcisist. Un
Func#ii matematice
268
num'r
2 1
...
k
n a a a este narcisist dac'
1
k
k
i
i
n a

(de
exemplu, 7, 153, 1634, 54748).
95. Scrie#i un program C care alege aleator un num'r
ntre 0 $i 9. Utilizatorul are trei ncerc'ri s' ghiceasc'
acest num'r. La fiecare tentativ', programul l anun#'
dac' valoarea aleas' este corect', prea mic' sau prea
mare.
269
1
111
11.
.. F
FFU
UUN
NNC
CC)
))I
II I
II P
PPE
EEN
NNT
TTR
RRU
UU G
GGE
EES
SST
TTI
II U
UUN
NNE
EEA
AA F
FFI
II!
!!I
IIE
EER
RRE
EEL
LLO
OOR
RR
Limbajul C nu are instruc#iuni definite special
pentru opera#ii de intrare/ie$ire, dar pentru astfel de
opera#ii, exist' o gam' complet' de func#ii oferite de
biblioteca standard C. Limbajul C ofer' dou' clase de
func#ii pentru lucrul cu fi$iere, denumite generic func#ii de
nivel nalt $i func#ii de nivel sc'zut. Totu$i, dintre acestea
doar nivelul nalt este standardizat, fiind similar pe toate
platformele. Func#iile de nivel nalt pentru lucru cu fi$iere
sunt declarate n biblioteca standard stdio.h, o parte
dintre ele fiind similare cu cele prezentate n capitolul 4).
11.1. Structura FILE
Majoritatea func#iilor standard pentru opera#ii cu
fi$iere necesit' un parametru de tip pointer la o structur'
FILE. Tipul structur' FILE este definit de asemenea n
biblioteca standard stdio.h. Structura propriu-zis'
con#ine informa#ii despre pozi#ia curent' de la care se
citesc sau la care se scriu date n fi$ier, identificatorul
fi$ierului, modul de acces, etc. Ea este creat' automat la
Func#ii pentru gestiunea fi$ierelor
270
deschiderea fi$ierului $i este distrus' automat la
nchiderea acestuia.
Algoritmul general de lucru cu fi$iere const' n
deschiderea sau crearea fi$ierului, citirea sau scrierea
datelor $i, n final, nchiderea acestuia.
11.2. Fi$iere standard de intrare/ie$ire
Cnd un program este pornit se deschid automat
trei fi$iere (adic' se creeaz' structurile FILE
corespunz'toare lor). Aceste fi$iere sunt intrarea
standard, ie$irea standard $i ie$irea standard pentru erori.
Variabilele pointeri c'tre structurile FILE ale acestor
fi$iere se numesc stdin, stdout $i stderr (definite in
stdio.h).
11.3. Deschiderea $i nchiderea fi$ierelor
nainte de a se citi sau scrie date ntr-un fi$ier,
acesta trebuie deschis cu func#ia fopen. n func#ie de
modul de acces stabilit la deschidere, asupra fi$ierului se
pot efectua doar opera#ii de citire, doar opera#ii se scriere,
sau opera#ii de citire $i scriere. Dup' ncheierea
opera#iilor de citire $i/sau scriere a datelor, fi$ierul trebuie
nchis cu func#ia fclose.
Tabel 11.1 Funcii standard pentru gestiunea
dinamic* a memoriei
Prototip FILE* fopen (char *name, char
*mode)
Descriere Efect: deschide fi$ierul name n modul de
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
271
accesare mode.
Rezultat: returneaz' un pointer la o
structura FILE sau NULL n caz de eroare
Prototip int fclose ( FILE *fptr)
Descriere Efect: nchide fi$ierul corespunz'tor lui
fptr.
Rezultat: 0 n caz de succes $i diferit de 0
altfel
Al doilea argument al func#ie fopen este un $ir de
caractere care determin' modul de acces. Acesta indic'
cum va fi utilizat fi$ierul: citire ("r"), scriere("w") sau
ad'ugare ("a"). n plus, exist' $i modurile extinse: citire
cu posibilitatea de scriere ("r+"), scriere cu posibilitatea
de citire ("w+") sau ad'ugare cu posibilitatea de citire
("a+").
Dac' se deschide un fi$ier care nu exist' pentru
scriere ("w") sau ad'ugare ("a"), el este creat. Dac' se
deschide un fi$ier existent pentru scriere ("w"), con#inutul
s'u este $ters. ncercarea de a deschide pentru citire un
fi$ier care nu exist' produce o eroare.
11.4. Func#ii pentru caractere
Func#iile pentru caractere au o utilizare limitat',
fiind folosite pentru citirea $i scrierea informa#iei caracter
cu caracter, f'r' nici o prelucrare n prealabil.
Tabel 11.2 Funcii standard de intrare/ie$ire la
nivel de caracter
Prototip int fputc (int c, FILE * fptr)
Func#ii pentru gestiunea fi$ierelor
272
Descriere Efect: scrie caracterul cu codul ASCII c n
fi$ierul fptr
Rezultat: valoarea c sau EOF n caz de
eroare
Prototip int fgetc (FILE * fptr)
Descriere Efect: cite$te din fi$ierul fptr un singur
caracter
Rezultat: codul ASCII al caracterului citit
sau EOF dac' s-au terminat datele sau a
ap'rut o eroare
De exemplu:
FILE *fp = fopen("test.txt", "w");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
}else
{
int c = 'A';
fputc(c, fp);
fclose(fp);
}
Un alt exemplu:
FILE *fp = fopen("test.txt", "r");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
} else
{
int c=fgetc(fp);
if(c==EOF)
printf("Fisierul este gol.\n");
else
printf("Am citit caracterul %c", c);
fclose(fp);
}
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
273
11.5. Func#ii pentru $iruri de caractere
Func#iile pentru $iruri de caractere permit citirea
$i scrierea informa#iei sub form' de $ir de caracter, f'r'
alte prelucr'ri.
Tabel 11.3 Funcii standard de intrare/ie$ire
pentru $iruri de caractere
Prototip int fputs (char *s, FILE *fptr)
Descriere Efect: scrie $irul s n fi$ierul fptr
Rezultat: un num'r nenegativ n caz de
succes sau EOF n caz de eroare
Prototip char* fgets (char *s, int cnt, FILE
*fptr)
Descriere Efect: cite$te un $ir de maximum cnt-1
caractere din fi$ierul fptr $i l pune n
memorie la adresa s
Rezultat: adresa $irului sau NULL daca s-au
terminat datele sau a ap'rut o eroare
Exemplul urm'tor scrie un mesaj n fi$ierul
test.txt.
FILE *fp = fopen("test.txt", "w");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
} else
{
char linie="Aceasta este o linie de text".;
fputs(linie, fp);
fclose(fp);
}
Exemplul urm'tor cite$te un mesaj din fi$ierul
test.txt.
Func#ii pentru gestiunea fi$ierelor
274
FILE *fp = fopen("test.txt", "r");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
} else
{
char linie[100];
fgets(linie, 100, fp);
printf("Am citit linia: %s.\n", linie);
fclose(fp);
}
11.6. Func#ii cu formatare
Func#iile cu formatare permit citirea $i scrierea
informa#iei dup' o prelucrare n prealabil a acesteia.
Prelucrarea se realizeaz' conform codurilor de format
descrise n sec#iunea 5.3.
Tabel 11.4 Funcii standard de intrare/ie$ire cu
formatare
Prototip int fprintf (FILE *fptr, char *fmt,
...);
Descriere Efect: scrie n fi$ierul fptr $irul fmt n care
codurile de format sunt nlocuite cu valorile
expresiilor marcate prin trei puncte;
Rezultat: num'rul de caractere scrise sau
EOF n caz de eroare
Prototip int scanf (FILE *fptr, char *fmt,
...);
Descriere Efect: cite$te din fi$ierul fptr date conform
$irului fmt $i le pune n memorie la adresele
marcate prin trei puncte;
Rezultat: num'rul de coduri de format
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
275
prelucrate corect sau EOF n caz de eroare
De exemplu:
FILE *fp = fopen("test.txt", "w");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
} else
{
fprintf(fp, "%d|%c|%f|%s", 3, 'A', 3.14,
"Test");
fclose(fp);
}
De exemplu:
FILE *fp = fopen("test.txt", "r");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
} else
{
char cuvant[100];
fscanf(fp, "%s", cuvant);
printf("Am citit %s.\n", cuvant);
fclose(fp);
}
11.7. Func#ii pentru blocuri de date
Func#iile fread $i fwrite permit citirea $i scrierea
informa#iilor binare (adic' non-textuale) dintr-un fi$ier. n
acest caz, parametrul mod de acces al func#iei fopen
trebuie s' con#in' sufixul "b". Dac' sufixul lipse$te sau se
folose$te sufixul "t", modul implicit de lucru este cel
textual (adic' non-binar), caz n care informa#ia poate fi
transformat' ntr-un mod nedorit n timpul opera#iilor de
citire/scriere.
Func#ii pentru gestiunea fi$ierelor
276
Tabel 11.5 Funcii standard de intrare/ie$ire cu
blocuri de date
Prototip unsigned fread (void *dest,
unsigned size, unsigned cnt, FILE
*fptr)
Descriere Efect: cite$te maxim cnt elemente de
dimensiune size din fi$ierul fptr n zona de
memorie dest.
Rezultat: num'rul de elemente citite
complet
Prototip unsigned fwrite (void *src,
unsigned size, unsigned cnt, FILE
*fptr)
Descriere Efect: scrie maxim cnt elemente de
dimensiune size n fi$ierul fptr din zona de
memorie src.
Rezultat: num'rul de elemente scrise
complet
De exemplu:
FILE *fp = fopen("test.txt", "wb");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
} else
{
int valori[] = {1, 2, 3, 5};
fwrite(valori, sizeof(int), 4, fp);
fclose(fp);
}
De exemplu:
FILE *fp = fopen("test.txt", "rb");
if(fp == NULL)
{
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
277
printf("Eroare la deschiderea fisierului");
} else
{
int valori[20];
int citite = fread(valori, sizeof(int), 20,
fp);
printf("Am citit %d intregi.\n", citite);
fclose(fp);
}
11.8. Func#ii pentru acces aleator n fi$iere
n momentul deschiderii unui fi$ier n modul de
citire sau scriere, pozi#ia curent' la care se scriu date sau
de la care se citesc date este nceputul fi$ierului. Pentru
fi$ierele deschise n modul de ad'ugare pozi#ia curent' la
care se scriu date n fi$ier este sfr$itul fi$ierului. Ulterior,
n urma opera#iilor de citire/ scriere, pozi#ia curent'
avanseaz' automat cu num'rul de octe#i corespunz'tor.
Tabel 11.6 Funcii standard de intrare/ie$ire cu
blocuri de date
Prototip long ftell ( FILE *fptr)
Descriere Rezultat: pozi#ia curent' n fi$ier sau EOF n
caz de eroare
Prototip int fseek (FILE *fptr, long offset,
int origin)
Descriere Efect: mut' pozi#ia curent' pentru fi$ierul
fptr cu offset octe#i relativ la pozi#ia
specificata de parametrul origin.
Rezultat: num'rul de elemente scrise
complet
Func#ii pentru gestiunea fi$ierelor
278
Parametrul origin al func#iei fseek poate fi una
din constantele SEEK_CUR (denot' pozi#ia curent'),
SEEK_END (denot' sfr$itul fi$ierului), SEEK_SET (denot'
nceputul fi$ierului).
De exemplu:
FILE *fp = fopen("test.txt", "wb");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
} else
{
fseek(fp, 0, SEEK_END); // la sfarsitul
fisierului
printf("Fisierul are %li octeti.\n",
ftell(fp));
fseek(fp, 0, SEEK_SET); // la inceputul
fisierului
fclose(fp);
}
11.9. Alte func#ii pentru fi$iere $i directoare
Folosirea acestor func#ii ntr-un program necesit'
includerea bibliotecii direct.h.
Tabel 11.7 Funcii standard de intrare/ie$ire cu
blocuri de date
Prototip int remove (char *nume)
Descriere Efect: $terge fi$ierul nume
Rezultat: 0 n caz de succes sau diferit de
zero altfel
Prototip int rename (char *vechi, char *nou)
Descriere Efect: redenume$te fi$ierul vechi n nou
Rezultat: 0 n caz de succes sau diferit de
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
279
zero altfel
Prototip int chdir (char *nume)
Descriere Efect: face nume directorul curent de lucru
Rezultat: 0 n caz de succes sau diferit de
zero altfel
Prototip char* getcwd (char *dest, int cnt)
Descriere Efect: copiaz' n zona de memorie dest (cu
dimensiune maxim' de cnt octe#i) calea
directorului curent.
Rezultat: dest n caz de succes $i NULL
altfel
Prototip int mkdir (char *nume)
Descriere Efect: creeaz' directorul nume
Rezultat: 0 n caz de succes sau diferit de
zero altfel
Prototip int rmdir (char *nume)
Descriere Efect: $terge directorul nume
Rezultat: 0 n caz de succes sau diferit de
zero altfel
11.10. Exemple
107. Programul urm'tor copiaz' con#inutul unui fi$ier n
alt fi$ier folosind func#iile pentru blocuri de date. Numele
fi$ierelor sunt citite de la tastatur'.
#include <stdio.h>
#include <conio.h>
int main()
{
char sursa[256], destinatie[256];
printf("Fisierul sursa: ");
gets(sursa);
Func#ii pentru gestiunea fi$ierelor
280
printf("Fisierul destinatie: ");
gets(destinatie);

FILE *fpin = fopen(sursa, "rb");
FILE *fpout = fopen(destinatie, "wb");
if (fpin==NULL || fpout==NULL)
{
printf("Eroare la deschiderea
fisierelor");
} else
{
char data[80];
int cnt;
do
{
cnt=fread(data, sizeof(char), 80,
fpin);
fwrite(data, sizeof(char), cnt, fpout);
} while(cnt > 0);
}
fclose(fpin);
fclose(fpout);
getch();
}
108. Programul urm'tor redenume$te un fi$ier sau un
director al c'rui nume a fost citit de la tastatur'.
#include <stdio.h>
#include <conio.h>
int main()
{
char numeVechi[256], numeNou[256];
printf("Numele vechi: ");
gets(numeVechi);
printf("Numele nou: ");
gets(numeNou);

if(rename(numeVechi, numeNou) != 0)
printf("Redenumirea nu s-a efectuat");
else
printf("Redenumirea s-a efectuat");
getch();
}
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
281
109. Programul urm'tor $terge un fi$ier al c'rui nume a
fost citit de la tastatur'.
#include <stdio.h>
#include <conio.h>
int main()
{
char nume[256];
printf("Numele: ");
gets(nume);

if(remove(nume) != 0)
printf("Stergerea nu s-a efectuat");
else
printf("Stergerea s-a efectuat");
getch();
}
110. Programul urm'tor afi$eaz' con#inutul unui fi$ier al
c'rui nume este citit de la tastatur' folosind func#ii pentru
blocuri de date.
#include <stdio.h>
#include <conio.h>
int main()
{
char nume[50];
printf("Nume fisier:");
gets(nume);
FILE *fp = fopen(nume, "r");
if(fp == NULL)
{
printf("Eroare la deschiderea
fisierului");
} else
{
char data[80];
int cnt;
do
{
cnt=fread(data, sizeof(char), 80, fp);
fwrite(data, sizeof(char), cnt,
stdout);
Func#ii pentru gestiunea fi$ierelor
282
} while(cnt > 0);
fclose(fp);
}
getch();
}
111. Programul urm'tor exemplific' folosirea func#iilor
pentru opera#ii cu foldere. Programul afi$eaz' folderul n
care este pornit, schimb' folderul cu unul specificat de
utilizator $i creeaz' n acesta un fi$ier cu numele
"test.txt".
#include <stdio.h>
#include <direct.h>
#include <conio.h>
int main()
{
char buffer[256];
getcwd(buffer, 256);
printf("Folderul curent %s\n", buffer);

printf("Noul folder: ");
gets(buffer);
chdir(buffer);
getcwd(buffer, 256);
printf("Acum suntem in folderul %s\n",
buffer);
fclose(fopen("test.txt", "w"));
getch();
}
112. Programul urm'tor creeaz' un folder nou al c'rui
nume este introdus de utilizator.
#include <stdio.h>
#include <direct.h>
#include <conio.h>
int main()
{
printf("Folder nou: ");
char nume[256];
gets(nume);
if(mkdir(nume) != 0)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
283
printf("Directorul nu a fost creat.");
else
printf("Directorul a fost creat.");
getch();
}
113. Programul urm'tor $terge un folder al c'rui nume
este introdus de utilizator. Folderul trebuie s' fie gol,
adic' s' nu con#in' fi$iere sau alte foldere.
#include <stdio.h>
#include <direct.h>
#include <conio.h>
int main()
{
printf("Folder: ");
char nume[256];
gets(nume);
if(rmdir(nume) != 0)
printf("Directorul nu a fost sters.");
else
printf("Directorul a fost sters.");
getch();
}
114. Programul urm'tor gestioneaz' o agend' telefonic'
simpl'. Programul ofer' func#ii pentru creare, listare,
c'utare, ad'ugare, $tergere, sortare, salvare $i nc'rcare
din fi$ier.
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>

struct contact
{
char nume[50];
char adresa[100];
char telefon[15];
} agenda[100];
int intrari;
char * numefisier = "agenda.dat";
Func#ii pentru gestiunea fi$ierelor
284

void incarcare(void)
{
puts("Incarcare agenda");
FILE *f = fopen(numefisier,"rb");
if(f == NULL)
{
printf("Fisierul %s lipseste. Incep o
agenda noua.\n", numefisier);
intrari = 0;
} else
{
intrari = fread(agenda, sizeof(contact),
100, f);
fclose(f);
}
}

void salvare(void)
{
puts("Salvare agenda");
FILE *f = fopen(numefisier, "wb");
if(f == NULL)
{
printf("Fisierul %s nu poate fi
modificat.\n", numefisier);
} else
{
int i = fwrite(agenda, sizeof(contact),
intrari, f);
if(i != intrari)
printf("Doar %d contacte din %d au fost
salvate.", i, intrari);
fclose(f);
}
}

void afisarecontact(struct contact c)
{
printf("Nume: %s\n", c.nume);
printf("Adresa: %s\n", c.adresa);
printf("Telefon: %s\n", c.telefon);
}
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
285

void citirecontact(struct contact *c)
{
fflush(stdin);
printf("Nume: ");
gets(c->nume);
printf("Adresa: ");
gets(c->adresa);
printf("Telefon: ");
gets(c->telefon);
}

void cautarenume(void)
{
int i, gasite = 0;
char date[50];
fflush(stdin);
printf("Nume: ");
gets(date);
for(i = 0; i<intrari; ++i)
if(stricmp(date, agenda[i].nume)==0)
{
printf("Intrarea %d:\n", i);
afisarecontact(agenda[i]);
++gasite;
}
printf("Au fost gasite %d contacte.\n",
gasite);
}

void cautareadresa(void)
{
int i, gasite = 0;
char date[100];
fflush(stdin);
printf("Adresa partiala: ");
gets(date);
for(i = 0; i<intrari; ++i)
if(strstr(agenda[i].adresa, date)!=NULL)
{
printf("Intrarea %d:\n", i);
afisarecontact(agenda[i]);
++gasite;
Func#ii pentru gestiunea fi$ierelor
286
}
printf("Au fost gasite %d contacte.\n",
gasite);
}

void cautaretelefon(void)
{
int i, gasite = 0;
char date[100];
fflush(stdin);
printf("Telefon cautat: ");
gets(date);
for(i = 0; i<intrari; ++i)
if(strcmp(date, agenda[i].telefon)==0) {
printf("Intrarea %d:\n", i);
afisarecontact(agenda[i]);
++gasite;
}
printf("Au fost gasite %d contacte.\n",
gasite);
}

void adaugare(void)
{
char corect;
struct contact c;
puts("Introduceti datele:");
citirecontact(&c);
puts("Ati introdus:");
afisarecontact(c);
do
{
printf("Sigur doriti sa adaugati?
(d/n)\n");
corect = toupper(getchar());
} while(corect !='D' && corect !='N');
if(corect == 'D')
agenda[intrari++] = c;
}

void stergere(void)
{
char corect;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
287
int i;
struct contact c;
puts("Introduceti numarul contactului:");
scanf("%i", &i);
if(i < 0 || i>= intrari)
{
puts("Valoare incorecta");
return;
}
puts("Ati selectat:");
afisarecontact(agenda[i]);
do
{
printf("Sigur doriti sa stergeti?
(d/n)\n");
corect = toupper(getchar());
}while(corect !='D' && corect !='N');
if(corect == 'D')
{
--intrari;
for(; i<intrari; ++i)
agenda[i] = agenda[i+1];
}
}

void listare(void)
{
int i;
for(i = 0; i<intrari; ++i)
{
printf("Intrarea %d:\n", i);
afisarecontact(agenda[i]);
}
printf("Au fost gasite %d contacte.\n",
intrari);
}

void sortare(void)
{
int i, j;
struct contact c;
for(i=0;i < intrari; ++i)
for(j=i+1; j < intrari; ++j)
Func#ii pentru gestiunea fi$ierelor
288
if(stricmp(agenda[i].nume,
agenda[j].nume)>0)
{
c = agenda[i];
agenda[i] = agenda[j];
agenda[j] = c;
}
}

int main()
{
int optiune;
incarcare();
do
{
puts("Functia dorita:");
puts("\t[1] Cautare in agenda dupa nume");
puts("\t[2] Cautare in agenda dupa
numar");
puts("\t[3] Cautare in agenda dupa
adresa");
puts("\t[4] Adaugare in agenda");
puts("\t[5] Listare agenda");
puts("\t[6] Stergere din agenda");
puts("\t[7] Sortare agenda");
puts("\t[0] Terminare");
scanf("%d", &optiune);
switch(optiune)
{
case 0: break;
case 1: cautarenume(); break;
case 2: cautaretelefon(); break;
case 3: cautareadresa(); break;
case 4: adaugare(); break;
case 5: listare(); break;
case 6: stergere(); break;
case 7: sortare(); break;
default: puts(" Functie necunoscuta");
}
}while(optiune!=0);
salvare();
getch();
}
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
289
La prima rulare programul afi$eaz' mesajele
corespunz'toare cre'rii unei noi agende.
Incarcare agenda
Fisierul agenda.dat lipseste. Incep o agenda
noua.
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
5
Au fost gasite 0 contacte.
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
4
Introduceti datele:
Nume: Andrei Bautu
Adresa: Constanta
Telefon: 123456
Ati introdus:
Nume: Andrei Bautu
Adresa: Constanta
Telefon: 123456
Sigur doriti sa adaugati? (d/n)
d
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
Func#ii pentru gestiunea fi$ierelor
290
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
4
Introduceti datele:
Nume: Paul Vasiliu
Adresa: Constanta
Telefon: 654321
Ati introdus:
Nume: Paul Vasiliu
Adresa: Constanta
Telefon: 654321
Sigur doriti sa adaugati? (d/n)
d
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
0
Salvare agenda
La rul'ri succesive, programul ncarc' datele
salvate la ultima rulare.
Incarcare agenda
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
5
Intrarea 0:
Nume: Andrei Bautu
Adresa: Constanta
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
291
Telefon: 123456
Intrarea 1:
Nume: Paul Vasiliu
Adresa: Constanta
Telefon: 654321
Au fost gasite 2 contacte.
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
4
Introduceti datele:
Nume: Elena Bautu
Adresa: Constanta
Telefon: 123654
Ati introdus:
Nume: Elena Bautu
Adresa: Constanta
Telefon: 123654
Sigur doriti sa adaugati? (d/n)
d
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
5
Intrarea 0:
Nume: Andrei Bautu
Adresa: Constanta
Telefon: 123456
Intrarea 1:
Nume: Paul Vasiliu
Adresa: Constanta
Func#ii pentru gestiunea fi$ierelor
292
Telefon: 654321
Intrarea 2:
Nume: Elena Bautu
Adresa: Constanta
Telefon: 123654
Au fost gasite 3 contacte.
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
0
Salvare agenda
La urm'toarea rulare, agenda con#ine deja 3
contacte.
Incarcare agenda
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
5
Intrarea 0:
Nume: Andrei Bautu
Adresa: Constanta
Telefon: 123456
Intrarea 1:
Nume: Paul Vasiliu
Adresa: Constanta
Telefon: 654321
Intrarea 2:
Nume: Elena Bautu
Adresa: Constanta
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
293
Telefon: 123654
Au fost gasite 3 contacte.
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
0
Salvare agenda
11.11. Exerci#ii
96. Scrie#i un program C care afi$eaz' pe ecran doar
literele $i spa#iile din con#inutul unui fi$ier al c'rui nume a
fost citit de la tastatur'.
97. Scrie#i un program C care copiaz' con#inutul unui
fi$ier n alt fi$ier caracter cu caracter (folosind func#iile
fgetc $i fputc), exceptnd semnele de punctua#ie care
sunt nlocuite cu spa#iu.
98. Scrie#i un program C care copiaz' con#inutul unui
fi$ier n alt fi$ier linie cu linie (folosind func#iile fgets $i
fputs), transformnd majusculele n minuscule.
99. Scrie#i un program C care scrie ntr-un fi$ier $iruri de
caractere citite de la tastatur'. Citirea se opre$te la citirea
$irului de caractere vid (cu lungime 0).
100. Scrie#i un program C care afi$eaz' statistici despre
con#inutul unui fi$ier (num'r total de caractere, majuscule,
minuscule, cifre, semne de punctua#ie, caractere de
spa#iere).
101. Scrie#i un program C care afi$eaz' media numerelor
citite dintr-un fi$ier.
102. Scrie#i un program C care gestioneaz' catalogul
unei discipline. Programul trebuie s' permit' ad'ugarea,
Func#ii pentru gestiunea fi$ierelor
294
$tergerea, afi$area $i c'utarea studen#ilor, ad'ugarea $i
afi$area notelor, salvarea $i nc'rcarea datelor n fi$iere
diferite).
295
1
112
22.
.. M
MME
EET
TTO
OOD
DDE
EE D
DDE
EE P
PPR
RRO
OOG
GGR
RRA
AAM
MMA
AAR
RRE
EE
12.1. Metoda Divide et Impera
Metoda const' n descompunerea problemei de
rezolvat n dou' sau mai multe subprobleme care, la
rndul lor se descompun n dou' sau mai multe
subprobleme, pn' cnd se ob#in subprobleme a c'ror
rezolvare este direct' $i nu mai necesit' alte
descompuneri. Solu#ia problemei ini#iale se ob#ine prin
combinarea solu#iilor problemelor cu rezovare direct' n
care a fost descompus'.
S' presupunem c' urmeaz' procesarea $irului
1
, , ,
k k p
s s s
+
K $i exist' m cu proprietatea k m p . *irul
1
, , ,
k k p
s s s
+
K se descompune n sub$irurile
1
, , ,
k k m
s s s
+
K $i
1 2
, , ,
m m p
s s s
+ +
K . Se proceseaz' cele dou' sub$iruri, cu
eventuala lor descompunere, $i apoi se combin'
rezultatele proces'rii tuturor sub$irurilor pentru a ob#ine
rezultatul proces'rii $irului
1
, , ,
k k p
s s s
+
K . Astfel, func#ia
care proceseaz' $irul
1
, , ,
k k p
s s s
+
K are parametrii de
intrare k $i p $i genereaz' rezultatul proces'rii $irului
1
, , ,
k k p
s s s
+
K .
Metode de programare
296
12.2. Exemple

115. Program pentru calculul sumei primelor n numere
naturale
Fie suma ( )
1 2
1,
n
S n a a a + + + L $i
( )
1
,
k k p
k
a a a k p
S k p
a k p
+
+ + +

'

L
. Evident se poate defini
rela#ia de recuren#':
( ) ,
, 1,
2 2
k
a k p
S k p
k p k p
S k S p k p

_ _ + + ' 1 1
+ +
1 1
] ] , ,
,
rela#ie care este o descompunere a lui ( ) 1, S n . Astfel,
pentru 5 n se ob#ine:
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) 1, 5 1,3 4, 5 1, 2 3, 3 4, 4 5, 5 S S S S S S S + + + +
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
1 2 3 4 5 1 2 3 4 5
1,1 2, 2 3, 3 4, 4 5,5 S S S S S a a a a a a a a a a + + + + + + + + + + + +

Problema propus' este cazul particular n care
k
a k . Fie ( ) 1, 1 2 S n n + + + L suma primelor n numere
naturale $i ( )
( ) 1
,
k k p k p
S k p
k k p
+ + + +

'

L
. Evident se
poate defini rela#ia de recuren#':
( ) ,
, 1,
2 2
k k p
S k p k p k p
S k S p k p

_ _ + + ' 1 1
+ +
1 1
] ] , ,
.
Astfel, pentru 5 n se ob#ine:
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) 1, 5 1,3 4, 5 1, 2 3, 3 4, 4 5, 5 S S S S S S S + + + +
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) 1,1 2, 2 3,3 4, 4 5, 5 1 2 3 4 5 1 2 3 4 5 15 S S S S S + + + + + + + + + + + +

A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
297
Programul afi$eaz' solu#iile subproblemelor $i
solu#ia problemei.
// Suma primelor n numere naturale cu metoda
"Divide et Impera"
#include "stdio.h"
#include "conio.h"
int n;
int s(int k,int p)
{
if(k==p)
return k;
else
return s(k,(k+p)/2)+s((k+p)/2+1,p);
}
void afis(int k,int p)
{
if(k==p)
printf(" S(%d,%d)=%d \n",k,k,s(k,k));
else
{
afis(k,(k+p)/2);
afis((k+p)/2+1,p);
printf(" S(%d,%d)=%d\n",k,(k+p)/2,
s(k,(k+p)/2));
printf("S(%d,%d)=%d \n",(k+p)/2+1,p,
s((k+p)/2+1,p));
}
}
int main()
{
int k,p;
printf(" n = ");
scanf("%d",&n);
afis(1,n);
printf(" S = %d ",s(1,n));
getch();
}
n = 5
S(1,1)=1
S(2,2)=2
S(1,1)=1
Metode de programare
298
S(2,2)=2
S(3,3)=3
S(1,2)=3
S(3,3)=3
S(4,4)=4
S(5,5)=5
S(4,4)=4
S(5,5)=5
S(1,3)=6
S(4,5)=9
S = 15
116. Program pentru calculul lui ! n . Fie produsul
( )
1 2
1,
n
P n a a a L $i ( )
1
,
k k p
k
a a a k p
P k p
a k p
+

'

L
.
Evident se poate defini rela#ia de recuren#':
( ) ,
, 1,
2 2
k
a k p
P k p
k p k p
P k P p k p

_ _ + + ' 1 1
+
1 1
] ] , ,
,
rela#ie care este o descompunere a lui ( ) 1, P n . Astfel,
pentru 5 n se ob#ine:
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) 1,5 1, 3 4,5 1, 2 3,3 4, 4 5, 5 P P P P P P P
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
1 2 3 4 5 1 2 3 4 5
1,1 2, 2 3,3 4, 4 5,5 P P P P P a a a a a a a a a a

Problema propus' este cazul particular n care
k
a k . Fie ( ) 1, 1 2 P n n L suma primelor n numere
naturale $i ( )
( ) 1
,
k k p k p
P k p
k k p
+

'

L
. Evident se
poate defini rela#ia de recuren#':
( ) ,
, 1,
2 2
k k p
P k p
k p k p
P k P p k p

_ _ + + ' 1 1
+
1 1
] ] , ,
.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
299
Astfel, pentru 5 n se ob#ine:
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) 1,5 1, 3 4,5 1, 2 3,3 4, 4 5, 5 P P P P P P P
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) 1,1 2, 2 3,3 4, 4 5,5 1 2 3 4 5 1 2 3 4 5 P P P P P

1,1 2, 2 3,3 4, 4 5,5 1 2 3 4 5 1 2 3 4 5
Programul afi$eaz' solu#iile subproblemelor $i
solu#ia problemei.
// Calculul lui n! cu metoda "Divide et
Impera"
#include "stdio.h"
#include "conio.h"
int n;
int fact(int k,int p)
{
if(k==p)
return k;
else
return fact(k,(k+p)/2)*fact((k+p)/2+1,p);
}
void afis(int k,int p)
{
if(k==p)
printf("fact(%d,%d)=%d \n",k,k,fact(k,k));
else
{
afis(k,(k+p)/2);
afis((k+p)/2+1,p);
printf("fact(%d,%d)=%d \n",k,(k+p)/2,
fact(k,(k+p)/2));
printf(" fact(%d,%d)=%d \n", (k+p)/2+1, p,
fact((k+p)/2+1,p));
}
}
int main()
{
int k,p;
printf(" n = ");
scanf("%d",&n);
Metode de programare
300
afis(1,n);
printf(" S = %d ",fact(1,n));
getch();
}
n = 5
fact(1,1)=1
fact(2,2)=2
fact(1,1)=1
fact(2,2)=2
fact(3,3)=3
fact(1,2)=2
fact(3,3)=3
fact(4,4)=4
fact(5,5)=5
fact(4,4)=4
fact(5,5)=5
fact(1,3)=6
fact(4,5)=20
S = 120
117. Program pentru determinarea maximului dintr-un
$ir de numere reale.
Programul determin' maximul dintre termenii
$irului
1
, , ,
k k p
x x x
+
K folosind rela#ia de recuren#':
{ }
1
1 2
1 2 2 2
max max , , , , max , , ,
max , , ,
k k p k p k p k p
k k p
k
x x x x x x k p
x x x
x k p
+ + + + 1 1 1
+ +
1 1 1
+
] ] ]

' ' ; ' ;;

'

K K
K
// Determinarea maximului dintr-un sir de
numere reale cu metoda "Divide et Impera"
#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
int n;
typedef float sir[100];
sir x;
float max(sir x,int k,int p)
{
float m1,m2;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
301
if(k==p)
return x[k];
else
{
m1=max(x,k,(k+p)/2);
m2=max(x,(k+p)/2+1,p);
if(m1>=m2)
return m1;
else
return m2;
}
}
int main()
{
int k,p,i;
char c[10];
printf(" Numarul de termeni din sir n = ");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
printf(" Termenul %d = ",i);
scanf("%f",&x[i]);
}
printf(" Maximul din sir este %4f
\n",max(x,1,n));
getch();
}
Numarul de termeni din sir n = 5
Termenul 1 = 23
Termenul 2 = 21
Termenul 3 = 44
Termenul 4 = 55
Termenul 5 = 32
Maximul din sir este 55.000000
12.3. Metoda Backtracking
Metoda Backtracking este o metod' general' de
elaborare a algoritmilor. Pentru rezolvarea anumitor
probleme este necesar' desf'$urarea unui proces de
Metode de programare
302
c'utare a solu#iei aflate ntr-o anumit' mul#ime, numit'
spa#iul st'rilor. Pentru fiecare element din spa#iul st'rilor
este definit' o mul#ime de ac#iuni sau alternative.
Momentul ini#ial n rezolvarea problemei corespunde unei
st'ri, numit' ini#ial', iar solu#iile corespund drumurilor n
spa#iul st'rilor, de la cea ini#ial' pn' la una final'.
Procesul de rezolvare a problemei poate fi imaginat ca o
secven#' de ac#iuni care asigur' deplasarea, prin
intermediul unei secven#e de st'ri, n spa#iul st'rilor, din
starea ini#ial' la cea final'. n cazul anumitor probleme se
dore$te ob#inerea unei singure solu#ii, altele solicit'
determinarea tuturor solu#iilor sau determinarea unei
solu#ii optime, dintr-un anumit punct de vedere, numit'
solu#ie optimal'.
Consider'm un labirint avnd una sau mai multe
ie$iri. Starea ini#ial' poate fi considerat' orice camer' a
labirintului, problema revenind la g'sirea unui drum din
camera respectiv' c'tre una dintre ie$iri. Desf'$urarea
procesului de c'utare a unei st'ri finale presupune, la
fiecare etap', alegerea op#iunii pentru o alternativ'
posibil' a st'rii curente $i detectarea acelor st'ri capcan'
din care nu mai este posibil' continuarea procesului, sau
deja se cunoa$te excluderea atingerii unei st'ri finale.
Detectarea st'rii capcan' trebuie s' determine revenirea
la starea din care s-a ajuns la ea $i selectarea unei noi
op#iuni de continuare. n cazul n care nu mai exist'
alternative care s' nu fi fost selectate anterior, o astfel de
stare devine la rndul ei capcan' $i pentru ea se aplic'
acela$i tratament.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
303
Prin solu#ie a problemei se n#elege o secven#'
de ac#iuni care determin' tranzi#ia din starea ini#ial' ntr-o
stare final', fiecare component' a unui drum solu#ie
reprezentnd o alternativ' din mul#imea de variante
posibile. Cu alte cuvinte,
1
x este alternativa aleas' pentru
starea ini#ial',
2
x este alternativa selectat' pentru starea
n care s-a ajuns pe baza op#iunii
1
x ,
3
x este alternativa
selectat' pentru starea n care s-a ajuns pe baza op#iunii
2
x ,,
n
x este alternativa selectat' pentru starea n care
s-a ajuns pe baza op#iunii
1 n
x

. Dup' efectuarea ac#iunii
corespunz'toare alegerii alternativei
n
x rezult' o stare
final'.
Procesul de c'utare a unui drum solu#ie revine la
tentativa de extindere a por#iunii de drum construit,
alegnd prima alternativ' disponibil' pentru starea
curent' atins'. Continuarea drumului poate fi realizat'
pn' la atingerea unei st'ri finale sau pn' la ntlnirea
unei st'ri capcan' (mul#imea vid' de alternative). Dac'
este atins' o stare capcan', atunci este necesar'
revenirea la starea anterioar' $i selectarea urm'toarei
alternative disponibile acestei st'ri. Dac' nu mai exist'
alternative disponibile, atunci se ini#iaz' o nou' revenire
$i a$a mai departe. n cazul n care exist' cel pu#in nc' o
alternativ' disponibil', atunci se reia procesul de
extindere a drumului rezultat. n condi#iile n care
revenirea poate conduce la atingerea st'rii ini#iale $i
pentru ea nu mai exist' alternative disponibile, se
consider' c' problema nu are solu#ie.
Metode de programare
304
Pentru implementarea c'ut'rii este necesar'
re#inerea alternativei selectate pentru fiecare stare atins'
pn' la cea curent', astfel nct, n cazul unei reveniri s'
fie posibil' alegerea alternativei urm'toare. Cu alte
cuvinte, procesul de c'utare revine la tentativa de
extindere a drumului curent (pasul de continuare), cu
eventuala revenire n cazul atingerii unei st'ri capcan'
(pasul de revenire - back), memornd alternativele
selectate pentru fiecare stare intermediar' atins' (track).
De aici $i are geneza numele metodei backtracking.
Pentru determinarea unei singure solu#ii, metoda
presupune parcurgerea urm'torilor pa$i:
Pasul 1: starea ini#ial' a problemei este prima alternativ'
posibil' pentru starea curent' ; fie aceasta
1 1
x S ;
Pasul 2: dac' starea curent' rezultat' prin alternativa
1
x
este final', atunci vectorul x are o singur' component',
( )
1
x x , este vectorul solu#ie $i stop;
Pasul 3: altfel, este selectat' prima alternativ' din
mul#imea de ac#iuni posibile pentru starea curent',
2 2
x S ;
Pasul 4: dac' secven#a de alternative care a condus la
starea curent' este ( )
1 2
, , ,
k
x x x x K , atunci:
Pasul 5: dac' starea curent' este final', solu#ia este
vectorul ( )
1 2
, , ,
k
x x x x K $i stop;
Pasul 6: dac' starea curent' nu este starea final' atunci:
Pasul 7: dac' pentru starea curent' exist' alternative
disponibile, atunci se alege prima dintre ele $i se
continu';
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
305
Pasul 8: altfel, se revine la starea anterioar' celei
curente, solu#ia par#ial construit' devine ( )
1 2 1
, , ,
k
x x x x

K
$i se face salt la Pasul 7.
Pasul 9: dac', n urma unui pas de revenire, s-a ajuns la
starea ini#ial' $i nu mai sunt alternative disponibile, atunci
problema nu are solu#ie $i stop.
n cazul n care trebuie determinate toate solu#iile
problemei, c'utarea continu' dup' determinarea fiec'rei
solu#ii prin efectuarea de reveniri succesive.Terminarea
c'ut'rii este decis' n momentul n care s-a revenit la
starea ini#ial' $i nu mai exist' alternative disponibile.
Dac' se dore$te ob#inerea numai a solu#iilor care
optimizeaz' o func#ie
criteriu, atunci metoda se aplic' pentru
determinarea tuturor solu#iilor problemei,
fiecare nou' solu#ie rezultat' fiind comparat' cu
cea mai bun' solu#ie determinat' anterior. Pentru
aceasta este necesar' re#inerea celei mai bune solu#ii
calculate la fiecare moment.
Astfel, metoda se aplic' problemelor a c'ror
solu#ie se poate reprezenta sub forma unui vector solu#ie
( )
1 2
, , ,
m
X x x x K , care apar#ine spa#iului solu#iilor posibile
sau alternativelor
1 2 m
S S S S L ,
k k
x S , $i
( ) , 1, 2, ,
k k
card S n k m K . Pentru fiecare problem', se
dau anumite condi#ii interne pe care trebuie s' le
satisfac' componentele vectorului solu#ie. O solu#ie care
satisface condi#iile interne se nume$te solu#ie rezultat.
Metoda Backtracking genereaz' toate solu#iile rezultat,
f'r' generarea tuturor solu#iilor posibile. Se atribuie pe
Metode de programare
306
rnd valori componentelor vectorului X astfel: se atribuie
o valoare din mul#imea
k
S componentei
k
x numai dac'
au fost atribuite valori componentelor
1 2 1
, , ,
k
x x x

K ; dac'
s-a atribuit o valoare componentei
k
x , se verific' dac'
componentele
1 2
, , ,
k
x x x K satisfac condi#iile interne de
continuare; dac' condi#iile interne de continuare sunt
satisf'cute se atribuie valoare componentei
1 k
x
+
; dac'
condi#iile interne de continuare nu sunt satisf'cute se
atribuie o alt' valoare componentei
k
x sau dac' mul#imea
k
S a fost epuizat', se decrementeaz' k .
12.4. Backtracking nerecursiv
Pentru implementarea metodei definim
urm'toarele func#ii. Func#ia succesor testeaz' dac'
mul#imea
k
S mai are elemente $i care atribuie variabilei
as (am succesor) valoarea 1 dac' mul#imea
k
S mai are
elemente sau valoarea 0 n caz contrar.
void succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
} else
as=0;
}
Func#ia validare verific' dac' sunt satisf'cute
condi#iile interne specifice problemei $i care atribuie
variabilei ev (este valid) valoarea 1 dac' sunt satisf'cute
condi#iile interne sau valoarea 0 n caz contrar.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
307
Implementarea acestei func#ii difer' de la o problem' la
alta, n func#ie de condi#iile de continuare.
void validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(!conditie)
ev=0;
}
Func#ia afi#are care afi$eaz' o solu#ie rezultat:
void afisare(sir x, int k)
{
int i;
printf(" ( ");
for(i=1;i<=k-1;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}
Aceste func#ii sunt gestionate de secven#a
Backtracking care codific' mecanismul de generare a
solu#iilor rezultat.
k=1;
x[k]=0;
while(k>0)
{
do
{
succesor(x,k,as);
if(as)
validare(x,k,ev);
}while(as && !ev);
if(as)
if(k==n) afisare(x,k);
else
{
k=k+1;
x[k]=0;
}
Metode de programare
308
else k=k-1;
}
12.5. Exemple
Prezent'm n continuare cteva exemple clasice
de aplicare a metodei backtracking. Pentru fiecare
exemplu este furnizat codul surs' $i un exemplu de
execu#ie a programului.
118. Program pentru generarea permut'rilor unei mul#imi
de n obiecte
// Generare permutari de n obiecte si a
numarului lor nf
#include "stdio.h"
#include "conio.h"
typedef int sir[100];
sir a,x;
int i,k,n,as,ev,nf;
void succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else as=0;
}

void validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(!(x[k]!=x[i]))
ev=0;
}

void afisare(sir x, int k)
{
int i;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
309
printf(" %d ( ",nf);
for(i=1;i<=k-1;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}

int main()
{
printf("Generarea permutarilor de n obiecte
\n");
nf=0;
printf(" Numarul de obiecte n = ");
scanf("%d",&n);
printf(" Tastati obiectele \n");
for(i=1;i<=n;i++)
{
printf(" a [ %d ] = ",i);
scanf("%d",&a[i]);
}
k=1;x[k]=0;
while(k>0)
{
do
{
succesor(x,k,as);
if(as) validare(x,k,ev);
} while(as && !ev);
if(as)
if(k==n)
{
nf++;
afisare(x,k);
} else
{
k=k+1;
x[k]=0;
}
else k=k-1;
}
printf(" Numarul permutarilor de %d obiecte
este egal cu %d \n",n,nf);
getch();
}
Metode de programare
310
Pentru un num'r de trei obiecte programul
furnizeaz' rezultatele:
Generarea permutarilor de n obiecte
Numarul de obiecte n = 3
Tastati obiectele
a [ 1 ] = 22
a [ 2 ] = 11
a [ 3 ] = 33
1 ( 22, 11, 33 )
2 ( 22, 33, 11 )
3 ( 11, 22, 33 )
4 ( 11, 33, 22 )
5 ( 33, 22, 11 )
6 ( 33, 11, 22 )
Numarul permutarilor de 3 obiecte este egal
cu 6
119. Program pentru generarea combin'rilor de n
obiecte luate cte p $i a num'rului lor
// Generare combinari de n luate cate p si a
numarului lor // cnp
#include "stdio.h"
#include "conio.h"
typedef int sir[100];
sir a,x;
int p,i,k,n,as,ev,cnp;
void succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else
as=0;
}

void validare(sir x,int k, int &ev)
{
ev=1;
if((k>=2) && !(a[x[k]]>a[x[k-1]]))
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
311
ev=0;
}

void afisare(sir x, int k)
{
int i;
printf(" %d ( ",cnp);
for(i=1;i<=k-1;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}

int main()
{
printf(" Generarea combinarilor de n luate
cate p \n");
cnp=0;
printf(" Numarul de obiecte n = ");
scanf("%d",&n);
printf(" Tastati obiectele \n");
for(i=1;i<=n;i++)
{
printf(" a [ %d ] = ",i);
scanf("%d",&a[i]);
}
printf(" Combinari luate cate p = ");
scanf("%d",&p);
if(p<=n)
{
k=1;
x[k]=0;
while(k>0)
{
do
{
succesor(x,k,as);
if(as)
validare(x,k,ev);
}while(as && !ev);
if(as)
if(k==p) {
cnp++;
afisare(x,k);
Metode de programare
312
} else
{
k=k+1;
x[k]=0;
} else
k=k-1;
}
printf(" Numarul combinarilor de %d obiecte
luate cate %d este egal cu %d \n",n,p,cnp);
getch();
}
else
printf(" Eroare in date: p>n \n");
getch();
}
Generarea combinarilor de n luate cate p
Numarul de obiecte n = 4
Tastati obiectele
a [ 1 ] = 11
a [ 2 ] = 22
a [ 3 ] = 33
a [ 4 ] = 44
Combinari luate cate p = 3
1 ( 11, 22, 33 )
2 ( 11, 22, 44 )
3 ( 11, 33, 44 )
4 ( 22, 33, 44 )
Numarul combinarilor de 4 obiecte luate cate
3 este egal cu 4
120. Program pentru generarea aranjamentelor de n
obiecte luate cte p $i a num'rului lor
// Generare aranjamente de n luate cate p si a
numarului // lor anp
#include "stdio.h"
#include "conio.h"
typedef int sir[100];
sir a,x;
int p,i,k,n,as,ev,anp;
void succesor(sir x,int k,int &as)
{
if(x[k]<n)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
313
{
as=1;
x[k]=x[k]+1;
}
else as=0;
}

void validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(x[k]==x[i])
ev=0;
}

void afisare(sir x, int k)
{
int i;
printf("%d ( ",anp);
for(i=1;i<=k-1;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}

int main()
{
printf(" Generarea aranjamentelor de n luate
cate p \n");
anp=0;
printf(" Numar de obiecte n = ");
scanf("%d",&n);
printf(" Tastati obiectele \n");
for(i=1;i<=n;i++)
{
printf(" a [ %d ] = ",i);
scanf("%d",&a[i]);
}
printf(" Aranjamente luate cate p = ");
scanf("%d",&p);
if(p<=n)
{
k=1;
x[k]=0;
Metode de programare
314
while(k>0)
{
do
{
succesor(x,k,as);
if(as)
validare(x,k,ev);
} while(as && !ev);
if(as)
if(k==p)
{
anp++;
afisare(x,k);
}
else
{
k=k+1;
x[k]=0;
}
else k=k-1;
}
printf(" Numarul de aranjamente de %d luate
cate %d este egal cu %d\n",n,p,anp);
getch();
}
else
printf(" Eroare in date: p>n \n");
getch();
}
Generarea aranjamentelor de n luate cate p
Numar de obiecte n = 4
Tastati obiectele
a [ 1 ] = 11
a [ 2 ] = 32
a [ 3 ] = 21
a [ 4 ] = 43
Aranjamente luate cate p = 2
1 ( 11, 32 )
2 ( 11, 21 )
3 ( 11, 43 )
4 ( 32, 11 )
5 ( 32, 21 )
6 ( 32, 43 )
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
315
7 ( 21, 11 )
8 ( 21, 32 )
9 ( 21, 43 )
10 ( 43, 11 )
11 ( 43, 32 )
12 ( 43, 21 )
Numarul de aranjamente de 4 luate cate 2 este
egal cu 12
121. Program pentru generarea produsului cartezian a m
mul#imi
// Produsul cartezian a m multimi finite
#include "stdio.h"
#include "conio.h"
typedef int sir[100];
sir x,n;
int a[50][50],k,as,ev,i,j,m,nel;
void succesor(sir x,int k,int &as)
{
if(x[k]<n[k])
{
as=1;
x[k]=x[k]+1;
}
else
as=0;
}

void validare(int &ev)
{
ev=1;
}

void afisare(sir x,int k)
{
printf(" %d (",nel);
for(i=1;i<=k;i++)
printf(" %d ",a[i][x[i]]);
printf(")\n");
}

int main()
Metode de programare
316
{
int i;
nel=0;
printf(" Produs cartezian \n");
printf(" Numarul de multimi m = ");
scanf("%d",&m);
printf(" Tastati elementele multimilor \n");
for(i=1;i<=m;i++)
{
printf(" Numarul de elemente ale multimii
%d n[%d] = ",i,i);
scanf("%d",&n[i]);
printf(" Tastati elementele multimii %d
\n",i);
for(j=1;j<=n[i];j++)
{
printf(" a%d[%d] =",i,j);
scanf("%d",&a[i][j]);
}
}
printf(" Produsul cartezian a celor %d
multimi are elementele :\n",m);
k=1;
x[k]=0;
while(k>0)
{
do
{
succesor(x,k,as);
if(as)
validare(ev);
} while(as&&!ev);
if(as)
if(k==m)
{
nel++;
afisare(x,k);
} else
{
k=k+1;
x[k]=0;
}
else
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
317
k=k-1;
}
printf(" Numarul total de elemete este egal
cu %d \n",nel);
getch();
}
Ca exemplu de control am considerat cazul a trei
mul#imi cu cte dou', trei $i respectiv patru elemente.
Dup' rulare se ob#in rezultatele:
Produs cartezian
Numarul de multimi m = 3
Tastati elementele multimilor
Numarul de elemente ale multimii 1 n[1] = 2
Tastati elementele multimii 1
a1[1] =1
a1[2] =2
Numarul de elemente ale multimii 2 n[2] = 3
Tastati elementele multimii 2
a2[1] =11
a2[2] =22
a2[3] =33
Numarul de elemente ale multimii 3 n[3] = 4
Tastati elementele multimii 3
a3[1] =66
a3[2] =77
a3[3] =88
a3[4] =99
Produsul cartezian a celor 3 multimi are
elementele
1 ( 1 11 66 )
2 ( 1 11 77 )
3 ( 1 11 88 )
4 ( 1 11 99 )
5 ( 1 22 66 )
6 ( 1 22 77 )
7 ( 1 22 88 )
8 ( 1 22 99 )
9 ( 1 33 66 )
10 ( 1 33 77 )
11 ( 1 33 88 )
12 ( 1 33 99 )
Metode de programare
318
13 ( 2 11 66 )
14 ( 2 11 77 )
15 ( 2 11 88 )
16 ( 2 11 99 )
17 ( 2 22 66 )
18 ( 2 22 77 )
19 ( 2 22 88 )
20 ( 2 22 99 )
21 ( 2 33 66 )
22 ( 2 33 77 )
23 ( 2 33 88 )
24 ( 2 33 99 )
Numarul total de elemete este egal cu 24
122. Program pentru rezolvarea problemei celor n dame
Pe o tabl' de $ah cu n linii $i coloane se g'sesc
n dame. Problema const' n determinarea pozi#iilor celor
n dame pe tabla de $ah astfel nct acestea s' nu se
atace, pe fiecare linie, coloan' $i diagonal' a tablei de
$ah s' existe o singur' dam'. Fie k $i
k
x , 1, 2, , k n K ,
linia $i respectiv coloana pe care se g'se$te dama k .
Evident dou' dame i $i k , i k , se g'sesc pe aceea$i
coloan' dac' $i numai dac'
k i
x x , pe aceea$i linie dac'
$i numai dac' k i (condi#ie fals' prin ipoteza i k ) $i pe
aceea$i diagonal' dac' $i numai dac'
k i
x x k i .
Astfel, condi#iile interne care sunt verificate de func#ia
validare sunt:
k i
x x (pe aceea$i coloan' s' nu
existe dou' dame) $i
k i
x x k i (pe aceea$i diagonal'
s' nu existe dou' dame), pentru fiecare 1, 2, , 1 i k K .
Programul genereaz' toate solu#iile rezultat $i num'rul
total de solu#ii.
// Problema celor n dame si numarul solutiilor
rezultat
#include "stdio.h"
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
319
#include "conio.h"
#include "math.h"
#include "stdlib.h"
typedef int sir[100];
sir x;
int i,n,k,as,ev;
void succesor(sir x,int k,int&as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else as=0;
}

void validare(sir x,int k,int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(x[k]==x[i] || (k-i==abs(x[k]-x[i])))
ev=0;
}

void afisare(sir x,int k)
{
for(i=1;i<=k;i++)
printf(" Dama %d este pe linia %d si coloana
%d \n",i,i,x[i]);
}

int main()
{
int nsol;
printf(" Problema celor n dame \n");
printf(" Numarul de dame n = ");
scanf("%d",&n);
k=1;x[k]=0;nsol=1;
while(k>0)
{
do
{
succesor(x,k,as);
Metode de programare
320
if(as) validare(x,k,ev);
} while(as&&!ev);
if(as)
if(k==n)
{
printf("Solutia %d\n",nsol);
nsol++;
afisare(x,k);
getch();
}
else
{
k++;
x[k]=0;
}
else k--;
}
printf(" Numarul total de solutii rezultat
este %d \n",nsol-1);
getch();
}
Problema celor n dame
Numarul de dame n = 4
Solutia 1
Dama 1 este pe linia 1 si coloana 2
Dama 2 este pe linia 2 si coloana 4
Dama 3 este pe linia 3 si coloana 1
Dama 4 este pe linia 4 si coloana 3
Solutia 2
Dama 1 este pe linia 1 si coloana 3
Dama 2 este pe linia 2 si coloana 1
Dama 3 este pe linia 3 si coloana 4
Dama 4 este pe linia 4 si coloana 2
Numarul total de solutii rezultat este 2
12.6. Backtracking recursiv
n variant' recursiv' se define$te func#ia
backtracking:
void back(int k)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
321
{
if(sol(k))
afisare(x,k);
else
{
init(k);
while(succesor(x,k,as))
if(validare(x,k,ev))
back(k+1);
}
}
Func#ia are un singur parametru de tip ntreg,
care este indice al vectorului solu#ie. Func#ia testeaz'
dac' s-a generat o solu#ie prin apelul func#iei sol.
Defini#ia func#iei sol este:
int sol(int k)
{
return k==n+1;
}
Dac' s-a ob#inut o solu#ie, aceasta este afi$at'
de func#ia afisare, cu aceea$i defini#ie ca n cazul
nerecursiv. Dac' nu s-a ob#inut o solu#ie, se ini#ializeaz'
nivelul k cu valoarea aflat' naintea tuturor valorilor
posibile. Ini#ializarea este f'cut' de func#ia init:
void init(int k)
{
x[k]=0;
}
Func#ia init efectueaz' ini#ializarea lui
k
x cu o
valoare prin care se indic' faptul c', pn' la acel
moment, nu a fost selectat' nici o alternativ' pentru
pozi#ia k a vectorului x ;
Metode de programare
322
Dup' ini#ializare, se genereaz' succesiv toate
valorile din mul#imea
k
S . Pentru generarea acestor valori
se folose$te func#ia succesor, modificat' fa#' de cazul
nerecursiv n sensul c' returneaz' valoarea variabilei de
tip ntreg as:
int succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else as=0;
return as;
}
Pentru fiecare valoare generat' se testeaz' cu
func#ia validare condi#iile de continuare. Func#ia
validare este modificat' fa#' de cazul nerecursiv prin
returnarea valorii de tip ntreg a variabilei ev:
int validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(!conditie)
ev=0;
return ev;
}
Dac' condi#iile de continuare sunt ndeplinite se
genereaz' urm'toarea valoare pentru componenta k prin
apelul recursiv al func#iei back.
n func#ia main() se apeleaz' func#ia back cu
parametrul 1 deoarece algoritmul pleac' de la
componenta de indice 1.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
323
12.7. Exemple
Relu'm exemplele din sec#iunea 12.3.2 pentru
care folosim metoda backtracking n variant' recursiv'.
123. Program pentru generarea permut'rilor unei mul#imi
de n obiecte. n acest caz, { }
1 2 1 2
, ,
n n
S S S a a a L K .
Alternativele posibile pentru starea ini#ial' corespund
alegerilor pentru prima pozi#ie dintr-un vector solu#ie.
Func#ia init(k) realizeaz' ini#ializarea
elementului
k
x cu valoarea 0, pentru a marca faptul c',
pn' la momentul curent, nu a fost selectat' nici o
alternativ' pentru
k
x . Func#ia succesor returneaz'
valoarea 1 a variabilei as dac' elementul
k
x are
succesor n mul#imea { }
1 2
, ,
n
a a a K , sau 0 dac' elementul
k
x nu are succesor n mul#imea { }
1 2
, ,
n
a a a K . Func#ia
validare returneaz' valoarea 1 a variabilei ev dac' $i
numai dac' vectorul ( )
1 2
, , ,
k
x x x x K calculat pn' la
momentul curent satisface condi#ia intern' a problemei,
adic' are componentele distincte.
// Generare permutari de n obiecte si a
numarului lor nf
#include "stdio.h"
#include "conio.h"
typedef int sir[100];
sir a,x;
int i,k,n,as,ev,nf;
void init(int k)
{
x[k]=0;
}
int sol(int k)
{
return k==n+1;
}
Metode de programare
324
int succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else as=0;
return as;
}
int validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(!(x[k]!=x[i]))
ev=0;
return ev;
}
void afisare(sir x, int k)
{
int i;
printf(" %d ( ",nf);
for(i=1;i<=k-2;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}
void back(int k)
{
if(sol(k))
{
nf++;
afisare(x,k);
} else
{
init(k);
while(succesor(x,k,as))
if(validare(x,k,ev))
back(k+1);
}
}
int main()
{
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
325
printf(" Generarea permutarilor de n obiecte
\n");
nf=0;
printf(" Numarul de obiecte n = ");
scanf("%d",&n);
printf(" Tastati obiectele \n");
for(i=1;i<=n;i++)
{
printf(" a [ %d ] = ",i);
scanf("%d",&a[i]);
}
back(1);
printf(" Numarul permutarilor de %d obiecte
este egal cu %d \n",n,nf);
getch();
}
Pentru trei obiecte programul furnizeaz'
rezultatele:
Generarea permutarilor de n obiecte
Numarul de obiecte n = 3
Tastati obiectele
a [ 1 ] = 1
a [ 2 ] = 2
a [ 3 ] = 3
1 ( 1, 2, 3 )
2 ( 1, 3, 2 )
3 ( 2, 1, 3 )
4 ( 2, 3, 1 )
5 ( 3, 1, 2 )
6 ( 3, 2, 1 )
Numarul permutarilor de 3 obiecte este egal
cu 6

124. Program pentru generarea combin'rilor de n obiecte
luate cte p $i a num'rului lor
// Generare combinari de n luate cate p si a
numarului lor // cnp
#include "stdio.h"
#include "conio.h"
Metode de programare
326
typedef int sir[100];
sir a,x;
int p,i,k,n,as,ev,cnp;
void init(int k)
{
x[k]=0;
}
int sol(int k)
{
return k==p+1;
}
int succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
} else
as=0;
return as;
}
int validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if((k>=2) && !(a[x[k]]>a[x[k-1]]))
ev=0;
return ev;
}
void afisare(sir x, int k)
{
int i;
printf(" %d ( ",cnp);
for(i=1;i<=k-2;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}
void back(int k)
{
if(sol(k)) {
cnp++;
afisare(x,k);
} else
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
327
{
init(k);
while(succesor(x,k,as))
if(validare(x,k,ev))
back(k+1);
}
}
int main()
{
printf(" Generarea combinarilor de n luate
cate p \n");
cnp=0;
printf(" Numarul de obiecte n = ");
scanf("%d",&n);
printf(" Tastati obiectele \n");
for(i=1;i<=n;i++)
{
printf(" a [ %d ] = ",i);
scanf("%d",&a[i]);
}
printf(" Combinari luate cate p = ");
scanf("%d",&p);
if(p<=n)
{
back(1);
printf(" Numarul combinarilor de %d
obiecte luate cate %d este egal cu %d
\n",n,p,cnp);
}
else
printf(" Eroare %d > %d \n ",p,n);
getch();
}
Pentru exemplificare am generat toate
combin'rile de patru obiecte luate cte dou'.
Generarea combinarilor de n luate cate p
Numarul de obiecte n = 4
Tastati obiectele
a [ 1 ] = 1
a [ 2 ] = 2
a [ 3 ] = 3
Metode de programare
328
a [ 4 ] = 4
Combinari luate cate p = 2
1 ( 1, 2 )
2 ( 1, 3 )
3 ( 1, 4 )
4 ( 2, 3 )
5 ( 2, 4 )
6 ( 3, 4 )
Numarul combinarilor de 4 obiecte luate cate
2 este egal cu 6
125. Program pentru generarea aranjamentelor de n
obiecte luate cte p $i a num'rului lor
// Generare aranjamente de n luate cate p si a
numarului // lor anp
#include "stdio.h"
#include "conio.h"
typedef int sir[100];
sir a,x;
int p,i,k,n,as,ev,anp;
void init(int k)
{
x[k]=0;
}
int sol(int k)
{
return k==p+1;
}
int succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else
as=0;
return as;
}
int validare(sir x,int k, int &ev)
{
ev=1;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
329
for(i=1;i<=k-1;i++)
if(x[k]==x[i])
ev=0;
return ev;
}
void afisare(sir x, int k)
{
int i;
printf(" %d ( ",anp);
for(i=1;i<=k-2;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}
void back(int k)
{
if(sol(k))
{
anp++;
afisare(x,k);
}
else
{
init(k);
while(succesor(x,k,as))
if(validare(x,k,ev))
back(k+1);
}
}
int main()
{
printf(" Generarea aranjamentelor de n luate
cate p \n");
anp=0;
printf(" Numarul de obiecte n = ");
scanf("%d",&n);
printf(" Tastati obiectele \n");
for(i=1;i<=n;i++)
{
printf(" a [ %d ] = ",i);
scanf("%d",&a[i]);
}
printf(" Aranjamente luate cate p = ");
scanf("%d",&p);
Metode de programare
330
if(p<=n)
{
back(1);
printf(" Numarul de aranjamente de %d
luate cate %d este egal cu %d\n",n,p,anp);
}
else
printf(" Eroare %d > %d \n ",p,n);
getch();
}
Pentru n=4 $i p=2 se obtin rezultatele:
Generarea aranjamentelor de n luate cate p
Numarul de obiecte n = 4
Tastati obiectele
a [ 1 ] = 1
a [ 2 ] = 2
a [ 3 ] = 3
a [ 4 ] = 4
Aranjamente luate cate p = 2
1 ( 1, 2 )
2 ( 1, 3 )
3 ( 1, 4 )
4 ( 2, 1 )
5 ( 2, 3 )
6 ( 2, 4 )
7 ( 3, 1 )
8 ( 3, 2 )
9 ( 3, 4 )
10 ( 4, 1 )
11 ( 4, 2 )
12 ( 4, 3 )
Numarul de aranjamente de 4 luate cate 2 este
egal cu 12
126. Program pentru generarea produsului cartezian a m
mul#imi
// Produsula cartezian a m multimi finite
#include "stdio.h"
#include "conio.h"
typedef int sir[100];
sir x,n;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
331
int a[50][50],k,as,ev,i,j,m,nel;
void init(int k)
{
x[k]=0;
}
int sol(int k)
{
return k==m+1;
}
int succesor(sir x,int k,int &as)
{
if(x[k]<n[k])
{
as=1;
x[k]=x[k]+1;
}
else
as=0;
return as;
}
int validare(int &ev)
{
ev=1;
return ev;
}
void afisare(sir x, int k)
{
printf(" %d (",nel);
for(i=1;i<=k-1;i++)
printf(" %d ",a[i][x[i]]);
printf(")\n");
}
void back(int k)
{
if(sol(k))
{
nel++;
afisare(x,k);
}
else
{
init(k);
while(succesor(x,k,as))
Metode de programare
332
if(validare(ev))
back(k+1);
}
}
int main()
{
int i;
nel=0;
printf(" Produs cartezian \n");
printf(" Numarul de multimi m = ");
scanf("%d",&m);
printf(" Tastati elementele multimilor \n");
for(i=1;i<=m;i++)
{
printf(" Numarul de elemente ale multimii
%d n[%d] = ",i,i);
scanf("%d",&n[i]);
printf(" Tastati elementele multimii %d
\n",i);
for(j=1;j<=n[i];j++)
{
printf(" a%d[%d] =",i,j);
scanf("%d",&a[i][j]);
}
}
printf(" Produsul cartezian a celor %d
multimi are elementele :\n",m);
back(1);
printf(" Numarul total de elemete este egal
cu %d \n",nel);
getch();
}
Ca exemplu de control am considerat cazul a trei
mul#imi cu cte dou', trei $i respectiv patru elemente.
Dup' rulare se ob#in rezultatele:
Produs cartezian
Numarul de multimi m = 3
Tastati elementele multimilor
Numarul de elemente ale multimii 1 n[1] = 2
Tastati elementele multimii 1
a1[1] =11
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
333
a1[2] =22
Numarul de elemente ale multimii 2 n[2] = 3
Tastati elementele multimii 2
a2[1] =1
a2[2] =2
a2[3] =3
Numarul de elemente ale multimii 3 n[3] = 4
Tastati elementele multimii 3
a3[1] =6
a3[2] =7
a3[3] =8
a3[4] =9
Produsul cartezian a celor 3 multimi are
elementele :
1 ( 11 1 6 )
2 ( 11 1 7 )
3 ( 11 1 8 )
4 ( 11 1 9 )
5 ( 11 2 6 )
6 ( 11 2 7 )
7 ( 11 2 8 )
8 ( 11 2 9 )
9 ( 11 3 6 )
10 ( 11 3 7 )
11 ( 11 3 8 )
12 ( 11 3 9 )
13 ( 22 1 6 )
14 ( 22 1 7 )
15 ( 22 1 8 )
16 ( 22 1 9 )
17 ( 22 2 6 )
18 ( 22 2 7 )
19 ( 22 2 8 )
20 ( 22 2 9 )
21 ( 22 3 6 )
22 ( 22 3 7 )
23 ( 22 3 8 )
24 ( 22 3 9 )
Numarul total de elemete este egal cu 24
127. Program pentru rezolvarea problemei celor n dame
// Problema celor n dame si numarul solutiilor
rezultat
Metode de programare
334
#include "stdio.h"
#include "conio.h"
// Problema celor n dame
#include "math.h"
#include "stdlib.h"
typedef int sir[100];
sir x;
int i,n,k,as,ev,nsol;
void init(int k)
{
x[k]=0;
}
int sol(int k)
{
return k==n+1;
}
int succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else
as=0;
return as;
}
int validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(x[k]==x[i] || (k-i==abs(x[k]-x[i])))
ev=0;
return ev;
}
void afisare(sir x, int k)
{
for(i=1;i<=k-1;i++)
printf(" Dama %d este pe linia %d si
coloana %d \n",i,i,x[i]);
}

void back(int k)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
335
{
if(sol(k))
{
printf("Solutia %d\n",nsol);
nsol++;
afisare(x,k);
} else
{
init(k);
while(succesor(x,k,as))
if(validare(x,k,ev))
back(k+1);
}
}

int main()
{
nsol=1;
printf(" Problema celor n dame \n");
printf(" Numarul de dame n = ");
scanf("%d",&n);
back(1);
printf(" Numarul total de solutii rezultat
este %d \n",nsol-1);
getch();
}
Solu#iile pentru cazul a patru dame sunt:
Problema celor n dame
Numarul de dame n = 4
Solutia 1
Dama 1 este pe linia 1 si coloana 2
Dama 2 este pe linia 2 si coloana 4
Dama 3 este pe linia 3 si coloana 1
Dama 4 este pe linia 4 si coloana 3
Solutia 2
Dama 1 este pe linia 1 si coloana 3
Dama 2 este pe linia 2 si coloana 1
Dama 3 este pe linia 3 si coloana 4
Dama 4 este pe linia 4 si coloana 2
Numarul total de solutii rezultat este 2
Metode de programare
336
12.8. Metoda Greedy
Algoritmii de tip greedy se caracterizeaz' prin
luarea unor decizii rapide care duc la g'sirea unei solu#ii
a problemei. Nu ntotdeauna asemenea decizii rapide duc
la o solu#ie optim', dar vom vedea c' exist' anumite
tipuri de probleme unde se pot ob#ine solu#ii optime sau
foarte apropiate de optim. n traducere din limba englez'
cuvntul greedy nseamn' lacom. Algoritmii de tip
greedy vor s' construiasc' ntr-un mod ct mai rapid
solu#ia problemei.
Algoritmii de tip Greedy se aplic' problemelor ale
c'ror date de intrare sunt organizate sub forma unei
mul#imi A $i pentru care se cere determinarea unei
submul#imi B A care s' ndeplineasc' anumite condi#ii
astfel nct submul#imea B s' fie acceptat' ca solu#ie
posibil'.
n general pot s' existe mai multe submul#imi
B A care s' reprezinte solu#ii posibile ale problemei.
Dintre toate aceste submul#imi B se pot selecta, conform
unui anumit criteriu, anumite submul#imi
*
B care
reprezint' solu#ii optime ale problemei. Scopul este de a
g'si, dac' este posibil, una din submul#imile
*
B . Dac'
acest lucru nu este posibil, atunci scopul este g'sirea
unei mul#imi B care s' fie ct mai aproape de
submul#imile
*
B , conform criteriului de optimalitate impus.
Construirea submul#imii B se face printr-un $ir de
decizii. Ini#ial se porne$te cu mul#imea vid', B .
Fiecare decizie const' n alegerea unui element din
mul#imea A, analiza lui $i eventual introducerea lui n
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
337
submul#imea B . n func#ie de modul n care se iau aceste
decizii, submul#imea B se va apropia mai mult sau mai
pu#in de solu#ia optim'
*
B . n cazul ideal vom avea
*
B B .
Algoritmii de tip greedy nu urm'resc s' determine
toate solu#iile posibile $i s' aleag' dintre ele, conform
criteriului de optimalitate impus, solu#iile optime. Dup'
cum spune $i numele, algoritmii de tip greedy sunt
caracteriza#i prin l'comie $i nu au r'bdarea s'
investigheze toate variantele posibile de alegere a
solu#iei. Ei ncep construirea unei solu#ii pornind de la
mul#imea vid'. La fiecare pas se ia cte o decizie $i se
extinde solu#ia cu cte un element. La fiecare pas se
analizeaz' cte un element din mul#imea A $i se decide
dac' s' fie sau nu inclus n submul#imea B care se
construie$te. Astfel se progreseaz' de la mul#imea vid'
cu un $ir de submul#imi intermediare
1 2
, , , , ,
k
B B B K K
cu proprietatea
1 2 k
B B B A L L , pn' cnd
se ob#ine o solu#ie final' B .
Nu exist' un standard de implementare a
metodei greedy, care s' fie general valabil pentru toate
problemele care pot fi rezolvate cu aceast' metod'.
Implementarea metodei difer' de la o problem' la alta.
Exist' dou' variante de principiu pentru implementarea
algoritmilor de tip greedy. Prima variant' folose$te
func#iile: sel, test, adaug $i afis. Func#ia sel este are
rolul de a selecta urm'torul element x din mul#imea A
care s' fie prelucrat. Func#ia test verific' dac' elementul
x poate fi ad'ugat solu#iei intermediare
i
B astfel nct
Metode de programare
338
noua solu#ie
1 i
B
+
care s-ar ob#ine s' fie o solu#ie valid'.
Func#ia adaug adaug' elementul testat x mul#imii
1 i
B
+
.
Func#ia afis listeaz' solu#ia optim', elementele mul#imii
*
B . Prezent'm n continuare pseudocodul pentru aceast'
variant' greedy. Se consider' c' num'rul de elemente al
mul#imii A este egal cu n.
( , )
0; ;
( )
( ( , ))
( , )
( )
greedy A B
B
pentru i i n i
repeta
x sel A
if test B x
adaug B x
afis B

< + +


Dificultatea n aceast' variant' const' n scrierea
func#iei sel. Dac' func#ia sel este bine conceput', atunci
putem fi siguri c' solu#ia B g'sit' este o solu#ie optim'.
Dac' func#ia sel nu este foarte bine conceput', atunci
solu#ia B va fi doar o solu#ie posibil' $i nu va fi optim'.
Ea se poate apropia ns' mai mult sau mai pu#in de
solu#ia optim'
*
B , n func#ie de criteriul de selec#ie
implementat.
n a doua variant' de implementare a algoritmului
greedy se face mai nti o prelucrare a mul#imii A de
func#ia prel. Practic se face o sortare a elementelor
mul#imii A, conform unui anumit criteriu. Dup' sortare,
elementele vor fi prelucrate direct n ordinea rezultat'.
Dac' prelucrarea mul#imii A este bine f'cut', atunci se
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
339
va ajunge n mod sigur la o solu#ie optim'. Altfel se va
ob#ine doar o solu#ie posibil', mai mult sau mai pu#in
apropiat' de optim. Prezent'm n continuare descrirea n
limbajul pseudocod pentru aceast' a doua variant' a
algoritmului greedy.
( )
( , )
0; ;
[ ]
( ( , ))
( , )
( )
greedy A B
B
prel A
pentru i i n i
repeta
x A i
if test B x
adaug B x
afis B

< + +


Func#iile test, adaug $i afis joac' acela$i rol ca n
prima variant' de implementare a metodei greedy.
Prezent'm n continuare exemple de probleme
rezolvate cu metoda greedy.
128. Fie A o mul#ime cu n elemente numere reale. S' se
determine mul#imea B cu num'r maxim de elemente a
c'ror sum' s' fie maxim'.
Este evident c' pentru ca num'rul elementelor
mul#imii B s' fie maxim $i suma lor s' fie maxim', trebuie
ca B s' con#in' numai elemente pozitive $i nule. Func#ia
alege selecteaz' elemetele mul#imii A. Func#ia posibil
returneaz' o valaore nenul' (1) dac' a fost selectat un
element pozitiv sau nul din mul#imea A, sau valoarea zero
n cazul selec#iei unei valori negative. Func#ia adauga
Metode de programare
340
construie$te mul#imea B cu elementele selectate din
mul#imea A care satisfac codi#ia de nenegativitate.
Func#ia afiseaza tipare$te elementele mul#imii B,
num'rul $i suma lor. Programul este un exemplu a primei
metode de implementare a algoritmului greedy.
12.9. Exemple
129. Program pentru determinarea sumei maxime.
// Problema sumei maxime
#include "stdio.h"
#include "conio.h"
int n,m,i;
float sel(float a[])
{
return a[i];
}
int test(float b[],float x)
{
if(x>=0)
return 1;
else
return 0;
}
void adaug(float b[],float x)
{
b[m]=x;
m++;
}
void afis(float b[])
{
float s;
if(m)
{
printf(" Multimea B are %d elemente
\n",m);
for(i=0,s=0;i<m;s+=b[i],i++)
printf(" B [ %d ]= %f \n",i,b[i]);
s+=b[i];
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
341
printf(" Suma elementelor multimii B este
%f \n",s);
}
else
printf(" Multimea B este vida \n");
}
void greedy(float a[],float b[])
{
float x;
for(i=0;i<n;i++)
{
x=sel(a);
if(test(b,x))
adaug(b,x);
}
afis(b);
}
int main()
{
float a[50],b[50];
printf(" Numarul de elemente ale multimii n
= ");
scanf("%d",&n);
printf(" Elementele multimii A : \n");
for(i=0;i<n;i++)
{
printf(" A [ %d ] = ",i);
scanf("%f",&a[i]);
}
greedy(a,b);
getch();
}
Un exemplu de rulare este:
Numarul de elemente ale multimii n = 5
Elementele multimii A :
A [ 0 ] = 2.
A [ 1 ] = 3.
A [ 2 ] = -9.
A [ 3 ] = -5.
A [ 4 ] = 7.
Multimea B are 3 elemente
B [ 0 ]= 2.000000
Metode de programare
342
B [ 1 ]= 3.000000
B [ 2 ]= 7.000000
Suma elementelor multimii B este 12.000000

Pentru cazul n care mul#imea A are numai
elemente negative, B este vid'.
Numarul de elemente ale multimii n = 3
Elementele multimii A :
A [ 0 ] = -9.
A [ 1 ] = -1.
A [ 2 ] = -2.
Multimea B este vida

130. Program pentru determinarea multiplilor de k dintr-o
mul#ime de numere naturale cu metoda greedy.
// Multipli de k dintr-o multime de numere
naturale
#include "stdio.h"
#include "conio.h"
int n,m,i;
float sel(int a[])
{
return a[i];
}
int test(int b[],int x, int k)
{
if(x%k==0)
return 1;
else
return 0;
}
void adaug(int b[],int x)
{
b[m]=x;
m++;
}
void afis(int b[],int k)
{
if(m)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
343
{
printf(" Multimea A are %d multipli de %d
\n",m,k);
for(i=0;i<m;i++)
printf(" B [ %d ]= %d \n",i,b[i]);
}
else
printf(" Submultimea multiplilor de %d
este vida \n",k);
}
void greedy(int a[],int b[], int k)
{
int x;
for(i=0;i<n;i++)
{
x=sel(a);
if(test(b,x,k))
adaug(b,x);
}
afis(b,k);
}
int main()
{
int a[50],b[50],k;
printf(" Numarul de elemente ale multimii n
= ");
scanf("%d",&n);
printf(" Elementele multimii A : \n");
for(i=0;i<n;i++)
{
printf(" A [ %d ] = ",i);
scanf("%d",&a[i]);
}
printf(" Divizorul comun k = ");
scanf("%d",&k);
greedy(a,b,k);
getch();
}
Pentru n=6 $i k=5 se ob#ine:
Numarul de elemente ale multimii n = 6
Elementele multimii A :
A [ 0 ] = 2
Metode de programare
344
A [ 1 ] = 0
A [ 2 ] = 1
A [ 3 ] = 5
A [ 4 ] = 4
A [ 5 ] = 15
Divizorul comun k = 5
Multimea A are 3 multipli de 5
B [ 0 ]= 0
B [ 1 ]= 5
B [ 2 ]= 15
Pentru o mul#ime f'r' multipli de k se ob#ine:
Numarul de elemente ale multimii n = 6
Elementele multimii A :
A [ 0 ] = 2
A [ 1 ] = 3
A [ 2 ] = 4
A [ 3 ] = 1
A [ 4 ] = 12
A [ 5 ] = 22
Divizorul comun k = 5
Submultimea multiplilor de 5 este vida
131. Problema continu' a rucsacului. Presupunem c'
avem la dispozi#ie un rucsac n care se poate transporta o
greutate maxim' fixat' G. Cu acest rucsac urmeaz' a fi
transportate n obiecte de greut'#i cunoscute. Pentru
fiecare obiect se cunoa$te beneficiul transport'rii lui la
destina#ie. Problema const' n determinarea obiectelor
care vor fi transportate la destina#ie astfel nct beneficiul
total al transportului s' fie maxim. Dac' un obiect nu
poate fi divizat, problema se nume$te continu'. Dac'
obiectele pot fi divizate problema se numeste discret'.
Rezolvarea problemei continue a rucsacului se
poate face cu un algoritm de tip greedy. Se calculeaz'
pentru fiecare obiect raportul dintre beneficiu $i greutatea
lui. Se sorteaz' descresc'tor vectorul acestor rapoarte.
Ct timp nu a fost completat' greutatea total' a
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
345
rucsacului $i mai exist' obiecte n afara lui se selecteaz'
obiectul cu raportul maxim dintre beneficiu $i greutate.
Dac' obiectul nu ncape n ntregime n rucsac se
determin' frac#iunea din obiect care se poate transporta.
Programul afiseaz' ordinea introducerii obiectelor n
rucsac, informa#iile referitoare la obiectele introduse si
beneficiul total al transportului. Programul este un
exemplu a celei de a doua metode de implementare a
algoritmului greedy.
// Problema continua a rucsacului
#include "stdio.h"
#include "conio.h"
int n,m,i,j;
float G,grcurent,dif,benef,f;
struct ob
{
int nr;
float g;
float benef;
float raport;
} obiect[50];
struct r
{
int nr;
float g;
float benef;
float raport;
float f;
} rucsac[50];
void prel(void)
{
int auxx;
float aux;
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
if(obiect[i].raport<=obiect[j].raport)
{
aux=obiect[j].raport;
obiect[j].raport=obiect[i].raport;
Metode de programare
346
obiect[i].raport=aux;
aux=obiect[j].benef;
obiect[j].benef=obiect[i].benef;
obiect[i].benef=aux;
aux=obiect[j].g;
obiect[j].g=obiect[i].g;
obiect[i].g=aux;
auxx=obiect[j].nr;
obiect[j].nr=obiect[i].nr;
obiect[i].nr=auxx;
}
}
int test()
{
dif=G-grcurent;
if(dif)
return 1;
else
return 0;
}
void adaug()
{
if(obiect[i].g<=dif)
{
rucsac[m].nr=obiect[i].nr;
rucsac[m].g=obiect[i].g;
rucsac[m].benef=obiect[i].benef;
rucsac[m].raport=obiect[i].raport;
grcurent+=rucsac[m].g;
benef+=rucsac[m].benef;
rucsac[m].f=1.;
m++;
} else
{
rucsac[m].nr=obiect[i].nr;
rucsac[m].g=dif;
rucsac[m].benef=(obiect[i].benef/
obiect[i].g)*dif;
rucsac[m].raport=rucsac[m].benef/
rucsac[m].g;
benef+=rucsac[m].benef;
rucsac[m].f=rucsac[m].g/obiect[i].g;
m++;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
347
}
}
void afis(void)
{
if(m)
{
printf(" Rucsacul contine %d obiecte
\n",m);
for(i=0;i<m;i++)
{
printf(" Obiectul %d \n",rucsac[i].nr);
printf("\t\t Greutate %f \n",rucsac[i].g);
printf("\t\t Fractiunea de greutate %f
\n",rucsac[i].f);
printf("\t\t Beneficiu %f
\n",rucsac[i].benef);
printf("\t\t Raport beneficiu/greutate %f
\n",rucsac[i].raport);
}
printf(" Beneficiul total este %f
\n",benef);
}
else
printf(" Rucsacul este gol \n");
}
void greedy(void)
{
prel();
for(i=0;i<n;i++)
{
if(test())
adaug();
}
afis();
}
int main()
{
printf(" Numarul de obiecte n = ");
scanf("%d",&n);
printf(" Greutatea si beneficiul: \n");
for(i=0;i<n;i++)
{
printf(" Greutatea obiectului %d = ",i);
Metode de programare
348
scanf("%f",&obiect[i].g);
printf(" Beneficiul adus de obiectul %d
= ",i);
scanf("%f",&obiect[i].benef);
obiect[i].raport=obiect[i].benef/
obiect[i].g;
obiect[i].nr=i;
}
printf(" Greutatea maxima admisa : ");
scanf("%f",&G);
greedy();
getch();
}
Pentru exemplul de mai jos suma tuturor
greut'#ilor obiectelor este mai mic' dect capacitatea
rucsacului.
Numarul de obiecte n = 3
Greutatea si beneficiul:
Greutatea obiectului 0 = 4
Beneficiul adus de obiectul 0 = 8
Greutatea obiectului 1 = 2
Beneficiul adus de obiectul 1 = 6
Greutatea obiectului 2 = 5
Beneficiul adus de obiectul 2 = 20
Greutatea maxima admisa : 100
Rucsacul contine 3 obiecte
Obiectul 2
Greutate 5.000000
Fractiunea de greutate
1.000000
Beneficiu 20.000000
Raport beneficiu/greutate
4.000000
Obiectul 1
Greutate 2.000000
Fractiunea de greutate
1.000000
Beneficiu 6.000000
Raport beneficiu/greutate
3.000000
Obiectul 0
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
349
Greutate 4.000000
Fractiunea de greutate
1.000000
Beneficiu 8.000000
Raport beneficiu/greutate
2.000000
Beneficiul total este 34.000000

Beneficiul total este 34.000000
Pentru exemplul de mai jos suma tuturor
greut'#ilor obiectelor este mai mare dect capacitatea
rucsacului. Reparti#ia obiectelor n rucsac este:
Numarul de obiecte n = 3
Greutatea si beneficiul:
Greutatea obiectului 0 = 4
Beneficiul adus de obiectul 0 = 8
Greutatea obiectului 1 = 2
Beneficiul adus de obiectul 1 = 6
Greutatea obiectului 2 = 5
Beneficiul adus de obiectul 2 = 20
Greutatea maxima admisa : 8
Rucsacul contine 3 obiecte
Obiectul 2
Greutate 5.000000
Fractiunea de greutate
1.000000
Beneficiu 20.000000
Raport beneficiu/greutate
4.000000
Obiectul 1
Greutate 2.000000
Fractiunea de greutate
1.000000
Beneficiu 6.000000
Raport beneficiu/greutate
3.000000
Obiectul 0
Greutate 1.000000
Fractiunea de greutate
0.250000
Metode de programare
350
Beneficiu 2.000000
Raport beneficiu/greutate
2.000000
Beneficiul total este 28.000000
12.10. Metoda programrii dinamice
Metoda program'rii dinamice se utilizeaz' la
rezolvarea unor probleme de optimizare care se refer' la
un proces. Procesul parcurge st'rile
0 1
, , ,
n
s s s K ,
0
s este
starea ini#ial',
n
s este starea final'. La fiecare trecere din
starea
i
s n starea
1 i
s
+
se ia decizia
1 i
d
+
, 0,1, , 1 i n K
pentru a se realiza acest lucru. La fiecare pas i , decizia
1 i
d
+
poate fi aleas' din mai multe decizii posibile, cea
care se ia trebuie s' fie optim'. n general deciziile
i
d
care conduc la solu#ia problemei, trebuie s' fie optime
satisf'cnd principiul optimalit'#ii al lui R.Bellmann. Acest
principiu spune c', dac' st'rilor
0 1
, , ,
n
s s s K le corespund
deciziile
1 2
, , ,
n
d d d K optime, atunci, oricare ar fi i , la $irul
de st'ri
0 1
, , ,
i
s s s K le corespund acelea$i decizii optime
1 2
, , ,
i
d d d K iar la $irul de st'ri
1
, , ,
i i n
s s s
+
K corespund
acelea$i decizii optime
1 2
, , ,
i i n
d d d
+ +
K .
Dac' principiul optimalit'#ii este satisf'cut,
metoda program'rii dinamice presupune scrierea unei
rela#ii de recuren#' pentru decizia de la pasul i . n
general, rela#iile de recuren#' sunt de dou' tipuri:
( )
1 2 1
, , ,
i i
d f d d d

K cunoscut' sub numele de rela#ia
retrospectiv' sau metoda napoi, n care func#ia f
determin' decizia de la pasul 1 i #innd cont de deciziile
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
351
luate anterior; ( )
1 2
, , ,
i i i n
d f d d d
+ +
K cunoscut' sub
numele de rela#ia prospectiv' sau metoda nainte, n care
func#ia f determin' decizia de la pasul 1 i #innd cont
de viitorul procesului.
Nu exist' criterii pe baza c'rora s' se poat'
decide aplicarea metodei program'rii dinamice unei
probleme date. putem formula dou' propriet'#i care
sugereaz' o solu#ie prin programare dinamic'. Exist'
dou' propriet'#i ale problemei de rezolvat care
recomand' aplicarea metodei program'rii dinamice.
Problema de rezolvat se poate descompune n
subprobleme $i solu#ia optim' a problemei deriv' din
solu#iile optime ale subproblemelor sale. Aceast'
proprietate poate s' conduc' fie la metoda metoda Divide
et Impera, fie la metoda Greedy. A doua proprietate a
problemei de rezolvat const' n posibilitatea suprapunerii
subproblemelor, ceea ce elimin' ideea metodei Divide et
Impera datorit' cre$terii timpului de execu#ie al
programului, prin execu#ia repetat' a codului asociat unor
subprobleme. Prin metoda program'rii dinamice fiecare
subproblem' se rezolv' o singur' dat'.
Rezolvarea unei probleme cu metoda program'rii
dinamice presupune parcurgerea urm'toarelor etape:
- identificarea subproblemele problemei date;
- definirea unei structuri de date, care s' memoreze
solu#iile subproblemelor;
- definirea unei rela#ii de recuren#' care s' caracterizeze
substructura optimal' a problemei;
- implementarea rela#iei de recuren#'.
Metode de programare
352
12.11. Exemple
Vom exemplifica aplicarea metodei program'rii
dinamice unor probleme clasice.
132. Problema nmul#irii optime a matricilor.
Fie n matrici
0 1 1 2 1
, , ,
n n
p p p p p p
A A A


K . Deoarece
nmul#irea matricilor este asociativ', produsul
0 1 1 2 1 n n
p p p p p p
A A A


L poate fi calculat n mai multe moduri.
Se pune problema determin'rii acelei asocieri a factorilor
pentru care produsul celor n matrici se poate efectua cu
un num'r minim de nmul#iri elementare. Este cunoscut
faptul c' num'rul de nmu#iri necesare efect'rii
produsului a dou' matrice
p q q r
M M

este egal cu p q r .
De exemplu, pentru matricele
2 2 2 3 3 4
, , A A A

, produsul
2 2 2 3 3 4
A A A

se poate calcula folosind asocierea
( )
2 2 2 3 3 4
A A A

, care necesit' 2 2 3 2 3 4 36 + nmul#iri
elementare. Folosind asocierea ( )
2 2 2 3 3 4
A A A

sunt
necesare 2 3 4 2 2 4 40 + nmul#iri elementare.
Calculul produsului
0 1 1 2 1 n n
p p p p p p
A A A


L , se reduce la
calculul unui produs de forma
( ) ( )
0 1 1 2 1 1 1 2 1 k k k k k k n n
p p p p p p p p p p p p
A A A A A A
+ + +

L L , ceea ce
este adev'rat $i pentru produsele din cele dou'
paranteze. Astfel, rezolvarea problemei se reduce la
rezolvarea subproblemelor de forma
1 1 i i j j
p p p p
A A
+ +

L cu
1 i j n . Subproblemele nu sunt independente
deoarece produsele
1 1 i i j j
p p p p
A A
+ +

L $i
1 2 1 2 i i j j
p p p p
A A
+ + + +

L au
n comun produsul
1 2 1 i i j j
p p p p
A A
+ + +

L . Vom defini matricea
solu#ie sol , cu elementele [ ][ ], 1 sol i j i j n n care
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
353
[ ][ ] sol i j este num'rul minim de nmul#iri elementare
necesare calculului produsului
1 1 i i j j
p p p p
A A


L . Evident
[1][ ] sol n reprezint' num'rul minim de nmul#iri
elementare necesare calculului produsului
0 1 1 2 1
, , ,
n n
p p p p p p
A A A


K . Pentru ca asocierea factorilor
produsului
0 1 1 2 1 n n
p p p p p p
A A A


L s' fie optim' este necesar
ca asocierea factorilor produselor
( ) ( )
0 1 1 2 1 1 1 2 1 k k k k k k n n
p p p p p p p p p p p p
A A A A A A
+ + +

L L
0 1 1 2 1 k k
p p p p p p
A A A


L $i
1 1 2 1 k k k k n n
p p p p p p
A A A
+ + +

L s' fie
optim'. Pentru a determina num'rul minim de nmul#iri
elementare pentru calculul produsului
1 1 i i j j
p p p p
A A


L se
fixeaz' pozi#ia parantezei k n toate modurile, 1 i k j
$i se alege varianta care conduce la num'rul minim de
nmul#iri. Pentru k fixat, num'rul de nmul#iri este egal cu
num'rul de nmul#iri necesare efectu'rii produsului
1 1 i i k k
p p p p
A A


L , egal cu [ ][ ] sol i k , adunat cu num'rul de
nmul#iri necesare efectu'rii produsului
1 1 k k j j
p p p p
A A
+

L ,
egal cu [ 1][ ] sol k j + , la care trebuie adunat num'rul de
nmul#iri necesare efectu'rii produsului celor dou' matrice
rezultate, egal cu
1 i k j
p p p

. Rezult' c' elementele


matricei sol trebuie s' satisfac' rela#ia de recuren#':
{ } [ ][ ] min [ ][ ] [ 1][ ] [ 1]* [ ]* [ ]
i k j
sol i j sol i k sol k j p i p k p j
<
+ + +
$i ( ) [ ][ ] 0 1, 2, , sol i i i n K .
n program sunt definite func#iile prodopt care
rezolv' rela#ia de recuren#' $i func#ia afis care afi$eaz'
asocierea optim' a factorilor produsului
Metode de programare
354
1 2 2 3 1
, , ,
n n
p p p p p p
A A A
+

K . n func#ia main se tip're$te
num'rul minim de nmul#iri elementare. Programul
prime$te la intrare num'rul de matrici $i pentru fiecare
matrice num'rul de linii $i coloane. Dac' condi#ia de
nl'n#uire nu este satisf'cut' se semnaleaz' eroare.
Programul afi$eaz' asocierea optim' a factorilor
produsului $i num'rul minim de nmul#iri elementare.
// Inmultirea optima a unui sir de matrice
#include "stdio.h"
#include "conio.h"
#include "limits.h"
long int sol[100][100];
int n,p[100],lc;
void prodopt()
{
int nm, i, j, k, kminim;
long int min;
for (nm=2; nm<=n; nm++)
for (i=1; i<=n-nm+1; i++)
{
j=i+nm-1;
min=INT_MAX;
for (k=i; k<j; k++)
if (min>sol[i][k]+sol[k+1][j]+p[i-
1]*p[k]*p[j])
{
min=sol[i][k]+sol[k+1][j]+p[i-1]*p[k]*p[j];
kminim=k;
}
sol[i][j]=min;
sol[j][i]=kminim;
}
}
void afis(int i, int j)
{
if (i==sol[j][i])
printf("A%d * ",i);
else
{
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
355
printf("(");
afis(i,sol[j][i]);
printf(") * ");
}
getch();
if (j==sol[j][i]+1)
printf("A%d",j);
else
{
printf("(");
afis(sol[j][i]+1,j);
printf(")");
}
}
int main()
{
int m,sw;
int lin[100],col[100];
printf(" Numar de matrici : ");
scanf("%d",&n);
for(m=1;m<=n;m++)
{
sw=1;
while(sw)
{
printf(" Matricea %d \n\n",m);
printf(" Numrul de linii ale matricei %d :
",m);
scanf("%d",&lin[m]);
if(col[m-1]!=lin[m] && m>1)
printf(" Conditia de inlantuire nu este
satisfacuta \n");
else
{
sw=0;
printf(" Numrul de coloane ale matricei %d :
",m);
scanf("%d",&col[m]);
}}}
for(m=1,p[0]=lin[1];m<=n;p[m]=col[m],m++);
prodopt();
printf("\n\n Asocierea optima a factorilor
produsului este: \n\n");
Metode de programare
356
afis(1,n);
printf("\n\n Numarul minim de inmultiri este
egal cu %d \n",sol[1][n]);
getch();
}
Un prim exemplu de rulare este pentru exemplul
tratat mai sus: determinarea asocierii optime a factorilor
produsului
2 2 2 3 3 4
A A A

. Pentru asocierea
( )
2 2 2 3 3 4
A A A

am ob#inut num'rul minim de nmul#iri
elementare egal cu 36.
Numar de matrici : 3
Matricea 1

Numrul de linii ale matricei 1 : 2
Numrul de coloane ale matricei 1 : 2
Matricea 2

Numrul de linii ale matricei 2 : 2
Numrul de coloane ale matricei 2 : 3
Matricea 3

Numrul de linii ale matricei 3 : 5
Conditia de inlantuire nu este satisfacuta
Matricea 3

Numrul de linii ale matricei 3 : 3
Numrul de coloane ale matricei 3 : 4

Asocierea optima a factorilor produsului este:

(A1 * A2) * A3

Numarul minim de inmultiri este egal cu 36

Urm'torul exemplu de rulare este pentru
determinarea asocierii optime a factorilor produsului a 5
matrici
3 4 4 5 5 2 2 3 3 5
A A A A A

.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
357

Numar de matrici : 5
Matricea 1

Numrul de linii ale matricei 1 : 3
Numrul de coloane ale matricei 1 : 4
Matricea 2

Numrul de linii ale matricei 2 : 1
Conditia de inlantuire nu este satisfacuta
Matricea 2

Numrul de linii ale matricei 2 : 4
Numrul de coloane ale matricei 2 : 5
Matricea 3

Numrul de linii ale matricei 3 : 2
Conditia de inlantuire nu este satisfacuta
Matricea 3

Numrul de linii ale matricei 3 : 5
Numrul de coloane ale matricei 3 : 2
Matricea 4

Numrul de linii ale matricei 4 : 2
Numrul de coloane ale matricei 4 : 3
Matricea 5

Numrul de linii ale matricei 5 : 3
Numrul de coloane ale matricei 5 : 5


Asocierea optima a factorilor produsului
este:

(A1 * (A2 * A3)) * (A4 * A5)

Numarul minim de inmultiri este egal cu 124

133. Problema determin'rii celui mai lung sub$ir comun a
dou' $iruri.
Metode de programare
358
Un sub$ir al unui $ir dat se ob#ine din $irul dat
prin eliminarea unor termeni sau a nici unui termen. Fiind
dat $irul ( )
1 2
, , ,
n
X x x x K , $irul ( )
1 2
, , ,
k
Z z z z K este
sub$ir al $irului X dac' exist' un $ir strict cresc'tor de
indici din X , ( )
1 2
, , ,
k
i i i K , astfel nct, pentru orice
1, 2, , j k K , are loc egalitatea
j
i j
x z . Consider'm
$irurile de numere reale ( )
1
i
i n
X x

$i
( )
1
j
j m
Y y

.
Problema const' n determinarea celui mai lung sub$ir
comun al celor dou' $iruri. De exemplu pentru $irurile
( ) 1.1, 2.3, 2.5,8., 7., 3.2 X $i
( ) 9.8, 5.6,1.1, 2.3, 2.5, 8., 7., 3.2 Y exist' sub$irurile
comune ( ) 1.1, 2.3, 2.5 , ( ) 2.3, 2.5, 7., 3.2 ,
( ) 1.1, 2.3, 2.5, 7.,3.2 , ( ) 7.,3.2 . Cel mai lung sub$ir
comun este ( ) 1.1, 2.3, 2.5, 7.,3.2 $i are lungimea 5. Fie
( )
1 2
, , ,
k k
X x x x K sub$irul primilor k termeni al lui X ,
numit prefixul de ordin k al lui X , ( )
1 2
, , ,
p p
Y y y y K
prefixul de ordinul p al $irului Y . Determinarea
sub$irului comun de lungime maxim' al prefixelor
k
X $i
p
Y este o subproblem'. Fie ( ) ,
k p
l X Y lungimea maxim' a
sub$irurilor comune prefixelor
k
X $i
p
Y . Problema ini#ial'
se reduce la determinarea valorii ( ) ,
n m
l X Y $i a sub$irului
comun corespunz'tor. Evident are loc egalitatea:
( )
( )
( ) ( ) { }
1 1
1 1
,
,
max , , ,
k p k p
k p
k p k p k p
l X Y daca X Y
l X Y
l X Y l X Y daca X Y

'

.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
359
Definim matricea
( ) ( ) 1 1 n m
l
+ +
, n care [ ][ ] l k p este
lungimea celui mai lung sub$ir comun al prefixelor
k
X $i
p
Y . Elementele matricei l verific' rela#iile:
( ) [ ][0] 0 1, 2, , l k k n K , ( ) [0][ ] 0 1, 2, , l p p m K ,
{ }
1 [ 1][ 1] [ ] [ ]
[ ][ ]
max [ ][ 1], [ 1][ ] [ ] [ ]
l k p daca x k y p
l k p
l k p l k p daca x k y p
+

'

.
Programul prime$te la intrare dimensiunile $i
termenii celor dou' $iruri. Se afi$eaz', dac' exist',
lungimea $i termenii sub$irului comun maximal al celor
dou' $iruri. Func#ia sir implementeaz' rela#iile de
recuren#'.
// Cel mai lung subsir comun si lungimea lui
#include "stdio.h"
#include "conio.h"
float x[50],y[50],l[50][50],subsir[50];
int k,p;
void sir(int n,int m)
{
for(k=1;k<=n;l[k][0]=0,k++);
for(p=1;p<=m;l[0][p]=0,p++);
for (k=1; k<=n; k++)
for (p=1; p<=m; p++)
if (x[k]==y[p])
l[k][p]=1+l[k-1][p-1];
else
l[k][p]=(l[k-1][p]>l[k][p-1]) ? l[k-1][p] :
l[k][p-1];
}
int main()
{
int n,m,i;
printf(" Numarul de termeni ai sirului X : ");
scanf("%d",&n);
printf(" Termenii sirului X \n");
for(i=1;i<=n;i++)
{
Metode de programare
360
printf(" x [ %d ] = ",i);
scanf("%f",&x[i]);
}
printf(" Numarul de termeni ai sirului Y : ");
scanf("%d",&m);
printf(" Termenii sirului Y \n");
for(i=1;i<=m;i++)
{
printf(" y [ %d ] = ",i);
scanf("%f",&y[i]);
}
sir(n,m);
printf(" Lungimea subsirului comun maximal
este %d \n",(int)l[n][m]);
if(l[n][m])
{
printf(" Cel mai lung subsir comun este: \n");
for (i=0,k=n,p=m;l[k][p];)
if (x[k]==y[p])
{
subsir[i++]=x[k];
k--;
p--;
}
else
if (l[k][p]==l[k-1][p])
k--;
else
p--;
for (k=0;k<=i-1; k++)
printf(" %f ",subsir[k]);
}
else
printf(" Nu exista subsiruri comune \n");
getch();
}
Pentru $irurile ( ) 1.1, 2.3, 2.5,8., 7., 3.2 X $i
( ) 9.8, 5.6,1.1, 2.3, 2.5, 8., 7., 3.2 Y programul
furnizeaz':
Numarul de termeni ai sirului X : 6
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
361
Termenii sirului X
x [ 1 ] = 1.1
x [ 2 ] = -2.3
x [ 3 ] = 2.5
x [ 4 ] = 8.
x [ 5 ] = -7.
x [ 6 ] = 3.2
Numarul de termeni ai sirului Y : 8
Termenii sirului Y
y [ 1 ] = 9.8
y [ 2 ] = -5.6
y [ 3 ] = 1.1
y [ 4 ] = -2.3
y [ 5 ] = 2.5
y [ 6 ] = -8.
y [ 7 ] = -7.
y [ 8 ] = 3.2
Lungimea subsirului comun maximal este 5
Cel mai lung subsir comun este:
3.200000 -7.000000 2.500000 -2.300000
1.100000
Pentru dou' $iruri disjuncte, care nu au sub$iruri
comune, programul furnizeaz' rezultatele:
Numarul de termeni ai sirului X : 3
Termenii sirului X
x [ 1 ] = 1.
x [ 2 ] = 2.
x [ 3 ] = 3.
Numarul de termeni ai sirului Y : 4
Termenii sirului Y
y [ 1 ] = 5.
y [ 2 ] = 6.
y [ 3 ] = 7.
y [ 4 ] = 8.
Lungimea subsirului comun maximal este 0
Nu exista subsiruri comune

Metode de programare
362
134. Rezolv'm problema 94 pentru cazul $irurilor de
caractere. Cu mici modific'ri care se impun, referitoare la
lucrul cu caractere, programul este:
// Cel mai lung subsir comun si lungimea lui
#include "stdio.h"
#include "conio.h"
int l[50][50];
char x[50],y[50],subsir[50];
int k,p;
void sir(int n,int m)
{
for(k=1;k<=n;l[k][0]=0,k++);
for(p=1;p<=m;l[0][p]=0,p++);
for (k=1; k<=n; k++)
for (p=1; p<=m; p++)
if (x[k]==y[p])
l[k][p]=1+l[k-1][p-1];
else
l[k][p]=(l[k-1][p]>l[k][p-1]) ? l[k-1][p] :
l[k][p-1];
}
int main()
{
int n,m,i;
printf(" Numarul de termeni ai sirului X : ");
scanf("%d",&n);
printf(" Termenii sirului X \n");
for(i=1;i<=n;i++)
{
printf(" x [ %d ] = ",i);
x[i]=getche();
printf("\n");
}
printf(" Numarul de termeni ai sirului Y : ");
scanf("%d",&m);
printf(" Termenii sirului Y \n");
for(i=1;i<=m;i++)
{
printf(" y [ %d ] = ",i);
y[i]=getche();
printf("\n");
}
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
363
sir(n,m);
printf(" Lungimea subsirului comun maximal
este %d \n",(int)l[n][m]);
if(l[n][m])
{
printf(" Cel mai lung subsir comun este: \n");
for (i=0,k=n,p=m;l[k][p];)
if (x[k]==y[p])
{
subsir[i++]=x[k];
k--;
p--;
}
else
if (l[k][p]==l[k-1][p])
k--;
else
p--;
for (k=0;k<=i-1; k++)
printf(" %c ",subsir[k]);
}
else
printf(" Nu exista subsiruri comune \n");
getch();
}
Rezultatele pentru cazul n care ( ) , , , X a b c d $i
( ) , , , , Y w a s c d sunt:
Numarul de termeni ai sirului X : 4
Termenii sirului X
x [ 1 ] = a
x [ 2 ] = b
x [ 3 ] = c
x [ 4 ] = d
Numarul de termeni ai sirului Y : 5
Termenii sirului Y
y [ 1 ] = w
y [ 2 ] = a
y [ 3 ] = s
y [ 4 ] = c
y [ 5 ] = d
Metode de programare
364
Lungimea subsirului comun maximal este 3
Cel mai lung subsir comun este:
d c a
365
1
113
33.
..
N
NNT
TTR
RRE
EEB
BB&
&&R
RRI
II D
DDE
EE A
AAU
UUT
TTO
OOE
EEV
VVA
AAL
LLU
UUA
AAR
RRE
EE
13.1. Unit#i lexicale
1. Care comentariu nu este corect?
a. // un comentariu
b. /* un comentariu */
c. // un comentariu //
d. /* un comentariu
e. //* un comentariu
2. Care element nu este un tip de dat' primar n limbajul
C?
a. int
b. float
c. real
d. char
e. double
3. Care element nu este un cuvnt cheie al limbajului C?
a. while
b. for
c. if
d. main
e. short
ntreb'ri de autoevaluare
366
4. Care element nu poate fi identificator ntr-un program
C?
a. flota
b. Float
c. _float
d. float
e. float_
13.2. Expresii. Operanzi. Operatori
5. Indica#i valoarea lui x in urma instruc#iunilor:
short int a=10, x;
x = sizeof(25.-a);
a. 15 (adic' 25 -10)
b. 25 (adic' valoarea cea mai mare)
c. 4 sau 8 (depinde de implementarea tipului double)
d. 2 (adic' sizeof(a), a fiind singura variabila din expresie)
e. eroare (operatorul sizeof nu se aplica unei expresii)
6. Care este valoarea lui a dup' secven#a urm'toare?
int a = 4;
a==-5+2;
a. secven#a con#ine o eroare
b. a are valoarea 4
c. a are valoarea -3
d. a are valoarea 7
e. a are valoarea -7
7. Indica#i valoarea lui x in urma instruc#iunilor:
x=0; z=1;
x=x==(y=!z);
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
367
a. 0
b. eroare deoarece operatorul de inegalitate (!=) este
scris invers
c. 1
d. alta valoare
e. rezultatul depinde de valoarea lui y
8. Indica#i ce afi$eaz' urm'toarele instruc#iuni:
int a=3, b=5;
printf (a=b ? "egale" : "diferite");
a. diferite
b. egale
c. instruc#iunile con#in erori de sintaxa
d. true
e. false
9. Indica#i valoarea lui x in urma instruc#iunilor:
int x=0, y=1, z=0;
x=x||!y&&z;
a. expresie eronata neadmis' n limbaj
b. 0
c. 1
d. 2
e. nici una din variante
10. Indica#i valoarea lui x in urma instruc#iunilor:
int x=2, y=1, z;
x=x&&y||z;
a. depinde de valoarea ini#ial' a lui z
b. 1
c. 0
d. false
ntreb'ri de autoevaluare
368
e. alta valoare
11. Care este valoarea expresiei 6 & 8?
a. 4
b. 5
c. 1
d. 3
e. 0
12. Indica#i valorile lui t, x si y in urma instruc#iunilor:
int t, x=2, y=3;
t=++x<y++?++x:y++;
a. 1, 2, 2
b. 2, 2, 2
c. 1, 2, 3
d. 2, 2, 3
e. 4, 3, 5
13. Indica#i ce afi$eaz' urm'toarele instruc#iuni:
int a=3, b=7%4;
printf(a==b ? "egale" : "diferite");
a. instruc#iunile con#in erori de sintaxa
b. true
c. egale
d. diferite
e. false
13.3. Instruc#iuni
14. Ce afi$eaz' secven#a de cod urm'toare?
int i, j;
for(i=1,j=1;i<4; j=++i)
{
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
369
int k=1;
printf("%d%d%d", i, j, k);
k++;
}
a. 111222333
b. 111122133
c. 111221331
d. 111211311
e. 111111111
15. Ce afi$eaz' secven#a de cod urm'toare?
int i, j;
for(i=1,j=1;i<4; i++)
{
int k=1;
printf("%d%d%d", i, j, k);
j++;k++;
}
a. 111221331
b. 111222333
c. 111111111
d. 111211311
e. 111122133
16. Ce afi$eaz' secven#a de cod urm'toare?
int i=3;
while(--i);
printf("%d",i);
a. 2 1 0
b. 3 2 1
c. 0
3 2
2 1
ntreb'ri de autoevaluare
370
17. Ce afi$eaz' secven#a de cod urm'toare?
int i;
for(i=19;i>0;i%7)
printf("%d", i);
a. 191919191919... (19 la infinit)
b. 195
c. 197
d. 19
e. altceva
13.4. Func#ii standard de intrare/ie$ire
18. n ce bibliotec' se g'sesc func#iile standard de
intrare/ie$ire?
a. conio.h
b. stdlib.h
c. math.h
d. stdio.h
e. string.h
19. Ce afi$eaz' urm'toarea secven#' de program?
printf("%03c %#x %o %.0s", '9', 9, 9, "9");
a. 009 0x9 9
b. 009 0x9 11
c. 009 0x9 11 9
d. 009 0x9 9 9
e. 9 9 9 9
20. Ce afi$eaz' urm'toarea secven#' de program dac'
datele introduse de la tastatur' sunt Decembrie
2006:
int a; char x[10];
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
371
scanf("%s%2d", x, &a);
printf("%d, %.3s", a, x);
a. 20, Dec
b. 2006, Dec
c. 2006, Decembrie
d. 2006 Decembrie
e. nimic
13.5. Tipuri de date compuse
21. Care afirma#ie este corecta referitor la ini#ializarea:
char mesaj[]={'G', 'r', 'e', 's', 'i', 't',
0};
a. ini#ializarea este corecta
b. ini#ializarea nu este permisa in cazul vectorilor de
caractere
c. ini#ializarea este eronata (lipse$te dimensiunea
vectorului)
d. ini#ializarea este eronata (0 nu este scris intre
apostrofi)
e. ini#ializarea este eronata (trebuiau scrise ghilimele in
loc de apostrofi)
22. Cte elemente are vectorul declarat n secven#a
urm'toare:
double v[30] = {1, 5, 18};
a. 30 de elemente
b. 3 elemente
c. 4 elemente
d. 0 elemente
ntreb'ri de autoevaluare
372
e. secven#a nu este corect'
23. Care instruc#iunea afi$eaz' numele coloanei a 3-a din
linia a 6-lea?
struct
{
struct
{
char nume[20];
int latime;
} coloane[5];
} linii[10];
a. printf("Nume: %s", linii[5].coloane[2].nume);
b. printf("Nume: %s", linii[6].coloane[3].nume);
c. printf("Nume: %s", linii[5].coloane[3].nume);
d. printf("Nume: %s", linii[6].coloane[2].nume);
e. printf("Nume linii[6].coloane[3].nume");
13.6. Func#ii
24. Care este valoarea expresiei f(21)?
int f(int n)
{
if (n<3) return n;
else return f(n/2);
}
a. 1
b. 2
c. 3
d. 0
e. 5
25. Care este valoarea expresiei f(5)?:
int f(int n)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
373
{
if (n<2) return 1;
else return n * f(n-1);
}
a. 120
b. 5
c. 1
d. 6
e. 12345
26. Care este valoarea expresiei f(2,5)?
int f(int n, int m)
{
if (m<1) return 1;
else return n * f(n, m-1);
}
a. 2
b. 5
c. 32
d. 1
e. 0
27. Care este valoarea expresiei f(5)?
int f(int n)
{
if (n<2) return 1;
else return n / f(n-1);
}
a. 1
b. 5
c. 0
d. 1.2
e. 15
ntreb'ri de autoevaluare
374
28. Care este valoarea expresiei f(5,0)?
int f(int n, int m)
{
if (n<0) return f(n+1, m+n);
else if (n>0) return f(n-1, m+n);
else return m;
}
a.15
b. 5
c. 0
d. -5
e. 12345
29. Care este valoarea expresiei f(6)?
int f(int n)
{
if (n<2) return 1;
else return n / f(n-1);
}
a. 1
b. 5
c. 0
d. 1.2
e. 6
13.7. Pointeri $i gestiunea dinamic a
memoriei
30. n ce bibliotec' se g'se$te func#ia realloc?
a. conio.h
b. realloc.h
c. malloc.h
d. stdio.h
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
375
e. string.h
31. Care instruc#iune afi$eaz' numele coloanei a 3-a din
linia indicat' prin pointerul linie?
struct
{
struct
{
char nume[20];
int latime;
} coloane[5];
} *linie;
a. printf("Nume: %s", linie->coloane[2].nume);
b. printf("Nume: %s", linie.coloane[3].nume);
c. printf("Nume: %s", linie->coloane->nume);
d. printf("Nume: %s", linie.coloane->nume);
e. printf("Nume linie->coloane->nume");
32. Care sunt valorile din vectorul v dup' secven#a de
program:
int v[] = {3, 4, 5}, *p;
p = v+1; *p = 6;
*p++ = 2;
a. 3 6 2
b. 3 2 5
c. 6 5 5
d. 3 7 5
e. 3 7 2
13.8. Func#ii pentru $iruri de caractere
33. Preciza#i valoarea expresiei strlen(test) dac' variabila
test este declarata astfel:
char test[]="";
ntreb'ri de autoevaluare
376
a. 1, deoarece se num'r' caracterele $i terminatorul de
sir
b. 0, deoarece se num'r' caracterele f'r' terminatorul de
sir
c. -1, deoarece nu e precizata dimensiunea $irului de
caractere
d. 2 sau 4, deoarece variabila test este un pointer
e. alta valoare dect cele de la celelalte r'spunsuri
34. Ce afi$eaz' secven#a de program:
char s[] = "out.txt";
printf("%s", strrchr(s,'t'));
a. out.txt
b. txt
c. out.
d. t
e. fi$ierul este gol
35. Preciza#i valoarea expresiei strlen(test) dac' variabila
test este declarata astfel:
char test[100]="Examen";
a. 7, deoarece se num'r' caracterele $i terminatorul de
sir
b. 6, deoarece se num'r' caracterele f'r' terminatorul de
sir
c. 100, deoarece aceasta este dimensiunea vectorului
d. 2 sau 4, deoarece variabila test este un pointer
e. alta valoare dect cele de la celelalte r'spunsuri
36. Care afirma#ie este corect' referitor la secven#a de
program:
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
377
char s1[100]="daca", s2[50]="inveti",
s3[]="raspunzi";
strcat(s2, s3);
strcat(s1, s2);
puts(s1);
a. afi$eaz' daca nve#i r'spunzi
b. afi$eaz' r'spunzi daca nve#i
c. este gre$it' (prin concatenare se suprascriu zone de
memorie nealocate)
d. este gre$it' (vectorii de caractere nu pot fi folosi#i ca
$iruri de caractere)
e. afi$eaz' daca r'spunzi nve#i
37. Indica#i valoarea returnat' in urma apelului:
strcmp("ghicitoare", "ghici");
a. o valoare pozitiva
b. o valoare negativa
c. zero
d. apel eronat deoarece compara doua constante
e. apel eronat deoarece compara doua adrese
13.9. Func#ii matematice
38. Ce func#ie nu face parte din biblioteca math.h?
a. sin
b. fabs
c. strlen
d. pow
e. sqrt
39. Ce constant' predefinit' are valoarea num'rului ?
a. PI
ntreb'ri de autoevaluare
378
b. M_PI
c. pi
d. m_pi
e. Pi
13.10. Func#ii pentru gestiunea fi$ierelor
40. Ce con#ine fi$ierul out.txt dup' execu#ia secven#ei de
cod:
char s[] = "out.txt";
FILE *fout = fopen(s, "wt");
fprintf(fout, "", strlen(s));
fclose(fout);
a. 7
b. 5
c. 123
d. 0
e. fi$ierul este gol
41. Ce con#ine fi$ierul out.txt dup' execu#ia secven#ei de
cod:
char s[] = "out.txt";
FILE *fout = fopen(s, "wt");
fprintf(fout, "%d", strlen(s));
fclose(fout);
a. 7
b. 5
c. 123
d. 0
e. fi$ierul este gol
42. Ce con#ine fi$ierul out.txt dup' execu#ia secven#ei de
cod:
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
379
char s[] = "out.txt";
FILE *fout = fopen(s, "wt");
fprintf(fout, s);
fclose(fout);
a. out.txt
b. t.txt
c. txt.tuo
d. t
e. fi$ierul este gol
43. In ce biblioteca este declarata fprintf?
a. file.h
b. stdio.h
c. strlib.h
d. math.h
e. string.h
44. Care instruc#iune nchide fi$ierul asociat variabilei fis?
a. fclose(fis);
b. close(fis)
c. fclose fis;
d. close fis;
e. *fis = fclose;
Tabel 13.1 R*spunsuri la ntreb*ri
R R R R R
1 d 2 c 3 d 4 d 5 c
6 b 7 c 8 b 9 b 10 b
11 e 12 e 13 c 14 c 15 a
16 c 17 a 18 d 19 b 20 a
21 a 22 a 23 a 24 b 25 a
26 c 27 a 28 a 29 e 30 c
ntreb'ri de autoevaluare
380
31 a 32 b 33 b 34 d 35 b
36 a 37 a 38 c 39 b 40 e
41 a 42 a 43 b 44 a
381
1
114
44.
.. A
AAN
NNE
EEX
XXA
AA 1
11
M
MME
EED
DDI
II U
UUL
LL D
DDE
EE P
PPR
RRO
OOG
GGR
RRA
AAM
MMA
AAR
RRE
EE
D
DDE
EEV
VV-
--C
CC+
+++
++
Dev-C++, realizat de Bloodshed Software, este
un mediu integrat de dezvoltare pentru limbajul C/C++
pentru Windows, gratuit $i complet. Un mediu integrat de
dezvoltare este un pachet de programe care permit
editare, compilarea, executarea $i verificarea programelor
direct din programul principal.
Dev-C++ folose$te varianta Mingw a
compilatorului GCC (GNU Compiler Collection),
recunoscut pentru calit'#ile sale. Printre calit'#ile mediului
Dev-C++ se num'r':
func#ii avansate de editare, c'utare $i nlocuire,
tip'rire, CVS (Concurrent Versioning System), list'
To Do, etc;
interfa#' n diverse limbi (printre care $i limba
romn');
colorarea $i completarea codului;
depanator de programe integrat;
crearea rapid' a programelor Windows (cu sau
f'r' interfa#' grafic') $i a bibliotecilor (statice $i
dinamice);
Anexa 1 Mediul de programare Dev-C++
382
manager de instrumente (pentru integrarea altor
unelte de dezvoltare n mediul Dev-C++);
manager de proiecte (pentru gestionarea u$oar' a
proiectelor medii $i mari);
manager pe pachete (pentru instalarea u$oara a
unor module suplimentare).
14.1. Instalare
Programul de instalare poate fi desc'rcat gratuit
de pe situl Bloodshed (la adresa
http://www.bloodshed.net) sau de pe SourceForge (la
adresa http://sourceforge.net/projects/dev-cpp). V'
recomand'm s' desc'rca#i programul de instalare care
include compilatorul Mingw, instalarea fiind mai simpl'.
Dup' desc'rcare porni#i programul de instalare $i
urma#i pa$ii indica#i de acesta. Noi vom discuta etapele
necesare pentru Dev-C++ versiunea 4.9.9.2. La pornirea
programului de instalare, acesta v' cere s' dezinstala#i
eventuale versiuni mai vechi ale sale, dup' care v' cere
s' selecta#i limba n care se va desf'$ura procesul de
instalare. Selecta#i limba romn'.

Urm'toarea fereastr' v' afi$eaz' contractul de
licen#' GNU, care v' d' dreptul s' folosi#i $i s' distribui#i
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
383
gratis programul. Ap'sa#i butonul De acord. Urmeaz'
etapa de selectare a componentelor. Set'rile implicite
sunt corecte, a$a c' pute#i ap'sa pe butonul nainte >.
n continuare, trebuie s' selecta#i folderul unde va
fi instalat programul. n majoritatea cazurilor, valoarea
implicit' este bun', deci ap'sa#i butonul Instalare.
Urm'toarea fereastr' afi$eaz' opera#iile efectuate n
timpul instal'rii. Dac' apar erori, porni#i din nou instalarea
$i selecta#i un alt folder la pasul anterior. Dac' nu apar
erori, programul de instalare v' ntreab' dac' dori#i ca
programul s' fie accesibil tuturor utilizatorilor
calculatorului. R'spunsul depinde de dumneavoastr'.

Anexa 1 Mediul de programare Dev-C++
384
Ultima fereastr' v' informeaz' c' instalarea s-a
ncheiat cu succes $i v' ofer' posibilitatea de a porni
programul.
14.2. Configurare
14.2.1. Prima pornire
La prima pornire, programul trebuie configurat
pentru a satisface preferin#ele dumneavoastr'. Vom folosi
limba englez', deoarece op#iunile mediului Dev-C++
seam'n' cu op#iunile din alte medii de programare.
Valorile pentru restul op#iunilor depind de dumneavoastr'.
Ap'sa#i pe Next.

Urm'toarea fereastr' v' ofer' posibilitatea s'
activa#i func#ia de completare a codului. Aceast' func#ie
poate fi util' deoarece Dev-C++ afi$eaz' prototipul
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
385
func#iilor atunci cnd consider' necesar, dar consum'
memorie suplimentar' $i necesit' timp de nc'rcare
suplimentar. V' recomand'm s' nu o activa#i.

Ultima fereastr' v' anun#' c' Dev-C++ a fost
configurat corect $i este gata de lucru. Ap'sa#i pe butonul
Ok.
14.2.2. Editorul
n mod implicit, la pornire Dev-C++ afi$eaz'
fereastra Tip of the day cu sfaturi utile pentru utilizatorii
ncep'tori. Dac' observa#i c' v-a#i nsu$it aceste sfaturile,
pute#i bifa op#iunea Dont display tips at startup, nainte
de a nchide fereastra.
Pentru a configura editorul, selecta#i din meniul
Tools op#iunea Editor options. n sec#iunea General,
efectua#i urm'toarele verific'ri/modific'ri:
Anexa 1 Mediul de programare Dev-C++
386
bifa#i Auto indent, astfel programele vor fi mai
u$or de urm'rit, deoarece instruc#iunile vor fi
deplasate automat la stnga, n func#ie de context;
bifa#i Use Tab Character, astfel ap'sarea tastei
Tab introduce n fi$ier un caracter tab, n loc de
spa#ii; seta#i valoarea Tab size la 4;
debifa#i Smart tabs, altfel programele vor fi greu
de urm'rit, datorit' indent'rii inegale a liniilor;
debifa#i Keep Trailing Spaces, astfel fi$ierele nu
vor con#ine spa#ii inutile;
bifa#i Enhanced Home Key, astfel prima ap'sare
a tastei Home, deplaseaz' cursorul la primul
caracter afi$abil din rnd, iar a doua ap'sare la
nceputul rndului.
n sec#iunea Display, pute#i modifica tipul $i
m'rimea fontului n func#ie de preferin#ele
dumneavoastr'. Indiferent de m'rime, v' recomand'm
folosirea unui font propor#ional precum Courier New,
Lucida Console sau Terminal. De asemenea, bifa#i
op#iunea Line Numbers.
14.2.3. Tastele rapide
Pentru a configura tastele rapide, selecta#i din
meniul Tools op#iunea Configure Shortcuts. Selecta#i
comanda c'reia vre#i s'-i asocia#i o combina#ie de taste $i
ap'sa#i tastele respective. De exemplu, pentru comanda
Edit::Date/Time seta#i combina#ia de taste Ctrl+T. Astfel,
cnd ve#i edita un program, ap'snd Ctrl+T se va
introduce automat data $i ora curent'. Pentru a anula o
combina#ie de taste ap'sa#i tasta ESC.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
387

14.2.4. Alte instrumente
Dev-C++ con#ine un manager de instrumente
care permite integrarea altor programe n mediul Dev-
C++. Acesta este accesibil din meniul Tools op#iunea
Configure Tools. De exemplu, pentru a c'uta pe Google
informa#ii despre cuvnt din program pe care este plasat
cursorul, executa#i urm'torii pa$i:
ap'sa#i pe butonul Add;
introduce#i set'rile din imaginea urm'toare.
ap'sa#i pe butonul Ok, apoi pe butonul Close
n meniul Tools, apare op#iunea Cauta pe
Google.
Anexa 1 Mediul de programare Dev-C++
388

14.3. Utilizare
14.3.1. Scrierea unui program C
Realizarea unui program ncepe cu transcrierea
algoritmului acelui program n limbajul de programare
dorit (limbajul C n cazul nostru). n mediul Dev-C++,
aceast' activitate ncepe cu deschiderea unui fi$ier surs':
din meniul File, selecta#i op#iunea New, apoi op#iunea
Source File.
n zona de editare se deschide un fi$ier nou,
denumit Untitled1. n acest fi$ier trebuie scrise
instruc#iunile C care formeaz' programul nostru. Pentru
exemplificare, scrie#i urm'torul program:
#include <stdio.h>
#include <conio.h>
int main()
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
389
{
printf("Un mic exemplu");
getch();
}
i Func#ia getch, definit' n biblioteca conio.h,
suspend' execu#ia programului pn' cnd
utilizatorul apas' o tast'. Dac' aceast' instruc#iune
lipse$te, programul se termin' imediat dup'
execu#ia ultimei instruc#iuni, iar fereastra cu
rezultatele dispare.
i Instruc#iunea getch() poate fi nlocuit' cu
instruc#iunea system("pause"). n acest caz,
biblioteca conio.h trebuie nlocuit' cu biblioteca
stdlib.h.
14.3.2. Compilarea codului surs*
La fiecare modificare a programului, acesta
trebuie compilat. Compilarea se realizeaz' cu ajutorul
op#iunii Compile din meniul Execute. Pentru
programele noi, nainte de prima compilare, Dev-C++
cere utilizatorului s' salveze fi$ierul pe disc.
n faza de compilare, programul este verificat din
punct de vedere sintactic. Dac' sunt detectate erori,
atunci acestea sunt afi$ate n partea inferioar' a ferestrei.
n caz, contrar pe ecran este afi$at' o fereastr' cu
statistici despre program. Ap'sa#i butonul Close.
14.3.3. Rularea programului
Programul poate fi rulat cu ajutorul op#iunii Run
din meniul Execute. La pornire programul afi$eaz' pe
ecran o fereastr' (dac' fereastra apare $i dispare
Anexa 1 Mediul de programare Dev-C++
390
imediat, verifica#i existen#a instruc#iunii getch() sau
system("pause") la sfr$it). Mediul Dev-C++ nu permite
pornirea simultan' a dou' programe. Dac' op#iunile din
meniul Execute sunt dezactivate, nchide#i programul
care ruleaz' deja.
i Compilarea $i rularea programului se pot realiza
ntr-un singur pas folosind op#iunea Compile &
Run din meniul Execute.
14.3.4. Depanarea
Chiar dac' un program nu con#ine erori de
sintax' (deci a fost compilat cu succes), el poate s'
con#in' erori de programare. Acestea se manifest' prin
furnizarea de rezultate incorecte pentru toate sau doar
anumite cazuri de test. n aceast' situa#ie func#ia de
depanare (debugging) a mediului Dev-C++ faciliteaz'
detectarea $i eliminarea erorilor.
Pentru depanarea unui program se folosesc
op#iunile din meniul Debug dup' etapa de compilare.
Programatorul poate selecta op#iunea Run to cursor
pentru a executa programul pn' ajunge la linia unde
este cursorul editorului. Odat' ajuns pe aceast' linie,
execu#ia programului se suspend'. n acest moment,
op#iunea Next step execut' urm'toarea instruc#iune,
op#iunea Step into execut' prima instruc#iune din func#ia
care urmeaz', iar op#iunea Continue reia execu#ia
programului.
n timpul depan'rii, op#iunea Add Watch permite
monitorizarea $i modificarea valorilor variabilelor. Astfel
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
391
programatorul poate s' vad' unde apar nepotriviri ntre
program $i algoritm.
Op#iunea Toogle breakpoint permite ad'ugarea
$i anularea punctelor de oprire, adic' linii din program n
care execu#ia programului se suspend', controlul fiind
redat din nou programatorului.
n orice moment, depanarea poate fi oprit'
folosind op#iunea Stop debugging.
393
1
115
55.
.. A
AAN
NNE
EEX
XXA
AA 2
22
M
MME
EED
DDI
II U
UUL
LL D
DDE
EE P
PPR
RRO
OOG
GGR
RRA
AAM
MMA
AAR
RRE
EE
R
RRA
AAP
PPT
TTO
OOR
RR
Raptor este un acronim pentru Rapid Algorithmic
Prototyping Tool for Ordered Reasoning, adic' instrument
de prototipizare algoritmic' rapid' pentru o gndire
ordonat'.
Raptor este un mediu de programare pe baz' de
scheme logice, proiectat special pentru a ajuta studen#ii
s' vizualizeze algoritmi lor $i s'-i testeze nainte de a i
implementa ntr-un limbaj de programare textual.
Programele Raptor sunt create vizual $i se execut' vizual
prin parcurgerea st'rilor schemei logice. Sintaxa
necesar' pentru scrierea unui program n Raptor este
redus' la minimum.
Raptor a fost dezvoltat n cadrul Departamentului
de *tiin#' a Calculatoarelor de la Academia For#elor
Aeriene a Statelor Unite. El poate fi desc'rcat gratuit de
pe situl web al Academiei For#elor Aeriene:
www.usafa.af.mil/df/dfcs/bios/mcc_html/raptor.cfm sau de
pe pagina web personal' a principalului autor, Dr. Martin
Carlisle: www.martincarlisle.com.
Anexa 2 Mediul de programare Raptor
394
Instalarea mediului Raptor este un proces simplu
datorit' utilitarului de instalare $i nu necesit' set'ri
suplimentare. Pentru sistemele de operate Windows care
nu au instalat' platforma .Net, utilitarul de instalare va
desc'rca automat $i va instala aceast' platform'.
Dup' pornirea aplica#iei, aceasta va deschide n
mod automat dou' ferestre: fereastra principal' pentru
programare $i fereastra consol' pentru monitorizarea
ie$irilor programului. Fereastra principal' con#ine n parte
din stnga cele $ase blocuri de programare accesibile n
Raptor (majoritatea fiind descrise n primul capitol al
c'r#ii).

Zona principal' a ferestrei con#ine schema logic'
corespunz'toare programului folosit. Butoanele din bara
de instrumente din partea superioar' a ferestrei permit
efectuarea diferitelor opera#ii de editare (salvare $i
nc'rcare programe; copiere n/din clipboard; opera#ii de
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
395
anulare $i refacere a ultimelor opera#ii) $i opera#ii de
programare (pornirea continu' sau pas cu pas, oprirea $i
stoparea programului).
n timpul rul'rii schemei logice, starea activ' care
se execut' va fi marcat' printr-un contur cu linie verde
ngro$at'. Aceasta permite monitorizarea u$oar' a
execu#iei algoritmului. n plus fa#' de acest' op#iune,
Raptor afer' multe alte instrumente grafice care u$ureaz'
n#elegerea algoritmului executat $i g'sirea eventualelor
erori:
viteza de execu#ie a algoritmului poate fi controlat'
cu ajutorul reglabilului disponibil pe bara de
instrumente n partea dreapt';
butonul Step to next shape permite execu#ia
pas cu pas a schemei logice $i permite astfel un
studiu eficient al efectelor acestuia;
valorilor variabilelor sunt afi$ate permanent n
timpul execu#iei n partea din stnga jos a ferestrei
principale, iar variabilele ale c'ror valori au fost
modificate de algoritm n ultimul pas executat sunt
afi$ate cu culoarea ro$ie pentru a ie$i n eviden#';
din meniul contextual al fiec'rui bloc (afi$at prin
clic dreapta pe blocul respectiv) se pot ad'uga
comentarii care s' ofere explica#ii suplimentare
referitoare la acel bloc;
din meniul contextual al fiec'rui bloc se pot
ad'uga puncte de oprire ale execu#iei
(breakpoints) astfel nc't execu#ia schemei logice
s' fie oprit' momentan atunci cnd se ajunge la
acestea.
Nu n ultimul rnd, fereasta consol' este un ajutor
nepre#uit pentru a urm'ri mesajele tip'rite de algoritm
Anexa 2 Mediul de programare Raptor
396
prin intermediul blocurilor de ie$ire (blocuri cu tipul
output).

Toate aceste func#ii utile pentru programare sunt
suplimentate de o serie de instrumente $i op#iuni utile
pentru prezentarea schemelor logice realizate, cum sunt
instrumentul creion de marcare din meniul Ink sau
op#iunile de compactare a blocurilor de decizie $i repeti#ie
din meniul View.
397
1
116
66.
.. A
AAN
NNE
EEX
XXA
AA 3
33
S
SSE
EET
TTU
UUL
LL D
DDE
EE C
CCA
AAR
RRA
AAC
CCT
TTE
EER
RRE
EE A
AAS
SSC
CCI
III
II
i Caracterele din setul ASCII cu codurile ntre 0 $i 31,
$i codul 127 (n baza 10) nu au o reprezentare
grafic' pe calculator. Ele sun denumire caractere de
control, fiind folosite ini#ial pentru a controla
comunica#ia ntre calculator $i periferice, $i modul de
afi$are al informa#iei.
Tabel 16.1 Tabela codurilor ASCII
Cod n baza
10 8 16
Caracter (semnificaie)
0 000 0x00 NUL (Nul character)
1 001 0x01 SOH (Start of Header)
2 002 0x02 STX (Start of Text)
3 003 0x03 ETX (End of Text)
4 004 0x04 EOT (End of Transmission)
5 005 0x05 ENQ (Enquiry)
6 006 0x06 ACK (Acknowledgment)
7 007 0x07 BEL (Bell)
8 010 0x08 BS (Backspace)
9 011 0x09 HT (Horizontal Tab)
10 012 0x0A LF (Line Feed)
11 013 0x0B VT (Vertical Tab)
Anexa 3 Setul de caractere ASCII
398
Cod n baza
10 8 16
Caracter (semnificaie)
12 014 0x0C FF (Form Feed)
13 015 0x0D CR (Carriage Return)
14 016 0x0E SO (Shift Out)
15 017 0x0F SI (Shift In)
16 020 0x10 DLE (Data Link Escape)
17 021 0x11 DC1 (XON) (Device Control 1)
18 022 0x12 DC2 (Device Control 2)
19 023 0x13 DC3 (XOFF) (Device Control 3)
20 024 0x14 DC4 (Device Control 4)
21 025 0x15 NAK (Negative Acknowledgement)
22 026 0x16 SYN (Synchronous Idle)
23 027 0x17 ETB (End of Trans. Block)
24 030 0x18 CAN (Cancel)
25 031 0x19 EM (End of Medium)
26 032 0x1A SUB (Substitute)
27 033 0x1B ESC (Escape)
28 034 0x1C FS (File Separator)
29 035 0x1D GS (Group Separator)
30 036 0x1E RS (Request to Send) (Record
Separator)
31 037 0x1F US (Unit Separator)
32 040 0x20 SP (spa#iu)
33 041 0x21 !
34 042 0x22 "
35 043 0x23 # (diez)
36 044 0x24 $ (dollar)
37 045 0x25 % (procent)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
399
Cod n baza
10 8 16
Caracter (semnificaie)
38 046 0x26 & (ampersand)
39 047 0x27 ' (apostof)
40 050 0x28 (
41 051 0x29 )
42 052 0x2A * (asterisk)
43 053 0x2B +
44 054 0x2C ,
45 055 0x2D -
46 056 0x2E .
47 057 0x2F / (slash)
48 060 0x30 0
49 061 0x31 1
50 062 0x32 2
51 063 0x33 3
52 064 0x34 4
53 065 0x35 5
54 066 0x36 6
55 067 0x37 7
56 070 0x38 8
57 071 0x39 9
58 072 0x3A :
59 073 0x3B ;
60 074 0x3C <
61 075 0x3D =
62 076 0x3E >
63 077 0x3F ?
64 0100 0x40 @ (simbol AT)
Anexa 3 Setul de caractere ASCII
400
Cod n baza
10 8 16
Caracter (semnificaie)
65 0101 0x41 A
66 0102 0x42 B
67 0103 0x43 C
68 0104 0x44 D
69 0105 0x45 E
70 0106 0x46 F
71 0107 0x47 G
72 0110 0x48 H
73 0111 0x49 I
74 0112 0x4A J
75 0113 0x4B K
76 0114 0x4C L
77 0115 0x4D M
78 0116 0x4E N
79 0117 0x4F O
80 0120 0x50 P
81 0121 0x51 Q
82 0122 0x52 R
83 0123 0x53 S
84 0124 0x54 T
85 0125 0x55 U
86 0126 0x56 V
87 0127 0x57 W
88 0130 0x58 X
89 0131 0x59 Y
90 0132 0x5A Z
91 0133 0x5B [
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
401
Cod n baza
10 8 16
Caracter (semnificaie)
92 0134 0x5C \ (backslash)
93 0135 0x5D ]
94 0136 0x5E ^ (circumflex)
95 0137 0x5F _ (underscore)
96 0140 0x60 ` (apostrof invers)
97 0141 0x61 a
98 0142 0x62 b
99 0143 0x63 c
100 0144 0x64 d
101 0145 0x65 e
102 0146 0x66 f
103 0147 0x67 g
104 0150 0x68 h
105 0151 0x69 i
106 0152 0x6A j
107 0153 0x6B k
108 0154 0x6C l
109 0155 0x6D m
110 0156 0x6E n
111 0157 0x6F o
112 0160 0x70 p
113 0161 0x71 q
114 0162 0x72 r
115 0163 0x73 s
116 0164 0x74 t
117 0165 0x75 u
118 0166 0x76 v
Anexa 3 Setul de caractere ASCII
402
Cod n baza
10 8 16
Caracter (semnificaie)
119 0167 0x77 w
120 0170 0x78 x
121 0171 0x79 y
122 0172 0x7A z
123 0173 0x7B {
124 0174 0x7C | (bar' vertical')
125 0175 0x7D }
126 0176 0x7E ~ (tild')
127 0177 0x7F DEL (delete)
403
B
BBI
IIB
BBL
LLI
IIO
OOG
GGR
RRA
AAF
FFI
II E
EE
[1] Cormen T.H., Leiserson C.E., Rivest R.R..
Introducere n algoritmi, Editura Computer Libris
Agora, Cluj Napoca, 2000
[2] Cristea V. Limbajul C Standard, Editura Teora,
Bucure$ti, 1992
[3] Gheorghe M., Popoviciu I., Chiru C., Vasiliu P.,
Lupei T. Limbajul C. Programare prin exemple,
Editura Academia Naval' Mircea cel B'trn,
Constan#a, 2001
[4] Vasiliu P., B'utu A. Programarea calculatoarelor
n limbajul C, Editura Europolis, Constan#a, 2006.
[5] Kernigham B., Ritchie D. The C programming
language, Practice Hall, 1975
[6] Knuth D.E. Tratat de programarea calculatoarelor,
vol.I-II, Editura Tehnic', Bucure$ti,1974
[7] Livovschi L., Georgescu H. Sinteza $i analiza
algoritmilor, Editura *tiin#ific' $i Enciclopedic',
Bucure$ti, 1992
[8] Negrescu L. Limbajul Turbo C, Editura Libris, Cluj-
Napoca, 1992

404
[9] Negrescu L. Limbajele C $i C++ pentru ncep'tori,
Editura Albastr', Cluj-Napoca, 1998
[10] Schildt H. C++ manual complet, Editura Teora,
1997
[11] Vlada M. Informatic', Editura Ars Docendi,
Bucure$ti, 1999

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