Sunteți pe pagina 1din 140

1. Cum se scrie un program in C?

1.1. Un prim program


1.2. Variabile, expresii si asignari
1.3. Un exemplu de utilizare a variabilelor de tip float
1.4. nitializarea variabilelor
1.!. "olosirea directivei #define
1.$. "olosirea functiilor printf%& si scanf%&
1.'. nstructiunea ()*ile(
1.+. ,tilul de redactare al programelor
1.-. .rori de programare frecvente
1.1/. 0edirectarea intrarii si iesirii
1.11. .xercitii propuse spre implementare
11111111
Capitolul 1
11111111
1111111111111111111111111
Cum se scrie un program (in C) ?
1111111111111111111111111
2rogramele sunt scrise pentru a instrui masinile sa lucreze cu tas3uri specifice sau sa rezolve
probleme specifice. 4 procedura %descrisa pas cu pas& asociata unui tas3 se numeste algoritm.
2rogramarea este activitatea de comunicare %codificare& a algoritmilor in calculatoare. 2rocesul de
programare are %in general& patru pasi5
1. ,pecificarea tas36ului7
2. 8escoperirea unui algoritm pentru solutia sa7
3. Codificarea algoritmului in C7
4. 9estarea codului.
Un calculator este o masina electronica digitala compusa din trei componente5
1. procesor %central processing unit sau C2U&7
2. memorie7
3. dispozitive de intrare:iesire.
2rocesorul lucreaza cu instructiuni care sunt inregistrate in memorie. 2e langa aceste instructiuni, in
memorie sunt pastrate si date. 8ispozitivele de intrare:iesire iau informatii de la agenti externi catre
masina si produc informatii pentru acesti agenti.
8ispozitivele de intrare sunt %de obicei&5
1. tastatura7
2. disc*eta7
3. banda7
4. C8604;.
8ispozitivele de iesire sunt %de obicei&5
1. ecranul terminalului7
2. imprimanta7
3. disc*eta7
4. banda7
!. C8604;.
,istemul de operare consta intr6o colectie de programe speciale si are doua scopuri principale5
1. coordoneaza resursele %memoria, procesorul, imprimanta& masinii. 8e exemplu, daca un fisier
este creat pe disc sistemul de operare are gri<a de detaliile localizarii acestuia si memoreaza
numele, lungimea si data creearii7
2. produce instrumente necesare utilizatorilor, multe dintre ele sunt folositoare utilizatorilor C. 8e
exemplu, doua dintre acestea sunt un editor de texte si un compilator de C.
Un cod C se numeste cod sursa, iar un fisier ce contine un cod sursa se numeste fisier sursa. 8upa
ce a fost creat un fisier sursa, atunci se invoca un compilator de C. 8e exemplu, pentru sistemele
;,684, se poate da comanda5
bc ex1.c sau tcc ex1.c
iar pentru unele sisteme U=>5
cc ex1.c
8aca nu sunt erori in ex1.c, atunci aceasta comanda produce fisierul executabil asociat %ex1.exe&.
?cum acesta poate fi rulat %executat& cu numele sau %ex1 sau ex1.exe&.
n continuare, vom preciza trei dintre trasaturile procesului de compilare %mentionam ca asupra
acestor notiuni, vom reveni cu detalii interesante intr6un capitol viitor&5
1. invocarea preprocesorului7
2. invocarea compilatorului7
3. invocarea incarcatorului.
2reprocesorul modifica o copie a codului sursa prin includerea altor fisiere si facand alte sc*imbari.
Compilatorul traduce aceasta in cod obiect folosit de incarcator pentru producerea fisierului
executabil final. "isierul care contine codul obiect se numeste fisier obiect. "isierele obiect, spre
deosebire de fisierele sursa, nu se pot intelege asa usor. Cand spunem deci compilare, de fapt
invocam preprocesorul, compilatorul si apoi incarcatorul.
8upa ce scriem un program, acesta trebuie compilat si testat. 8aca sunt necesare modificari, atunci
codul sursa trebuie editat din nou. ?sadar, partea proceselor de programare consta din ciclul5
editare 666@ compilare 666@ executie
AA B B
B BCCCCCCCCCC B B
BCCCCCCCCCCCCCCCCCCCCCCCB
66666666666666666666666
Un prim program
66666666666666666666666
4 sa incepem cu un exemplu de program C necesar pentru tiparirea unui sir pe ecran.
#include Dstdio.*@
main%&
E
printf%(azi am inceput laboratoarele de CFn(&7
G
"olosind un editor de texte, presupunem ca am scris si salvat acest fisier numit (ex1.c(. Cand
programul este compilat si rulat atunci va apare pe ecran sirul5
azi am inceput laboratoarele de C
6666666666666
Explicatii:
6666666666666
1. #include Dstdio.*@
Hiniile care incep cu (#( se numesc directive de preprocesare %precompilare&. ?cestea comunica cu
preprocesorul. ?ceasta directiva (#include( determina preprocesorul sa includa o copie a fisierului
*eader (stdio.*( in acest punct al codului. 2arantezele ung*iulare din (Dstdio.*@( indica ca acest
fisier se gaseste in biblioteca C %pentru compilatorul Iorland 3.1 pentru ;,684,, acesta se gaseste
in subdirectorul IC31:=CHU8.&. ?m inclus acest fisier deoarece acesta contine informatii despre
functia (printf%&(.
2. main%&
"iecare program are o functie numita (main(, care se executa intai. 2arantezele ce urmeaza dupa
(main( indica compilatorului ca aceasta este o functie.
3. E
?colada stanga incepe corpul fiecarei functii. 4 acolada dreapta corespunzatoare trebuie sa fie la
sfarsitul functiei.
4. printf%&
,istemul C contine o biblioteca standard de functii care poate fi utilizata in programe. (printf%&( este
o functie din biblioteca care tipareste pe ecran. ?ceasta este o functie descrisa in biblioteca
(stdio.*( %care se numeste prototipul functiei (printf%&(&.
!. (azi am inceput laboratoarele de CFn(
Un sir constant in C consta dintr6un numar de caractere incadrate intre g*ilimele. ?cest sir este un
argument al functiei (printf%&(. Caracterele Fn de la sfarsitul sirului %se citesc (bac3slas* n(&
reprezinta, de fapt, un singur caracter numit (ne)line(.
4 forma ec*ivalenta a programului de mai sus5
#include Dstdio.*@
main%&
E
printf%(azi am inceput (&7
printf%(laboratoarele de CFn(&7
G
66666666666666
4bservatii5
66666666666666
1. 2rimul (printf( contine la sfarsit un spatiu.
66666666666666666666666666666666666666
Variabile, expresii si asignari
66666666666666666666666666666666666666
n urmatorul exemplu vom ilustra folosirea variabilelor pentru manipularea valorilor intregi.
Variabilele sunt folosite sa memoreze valori. 8in moment ce diferite tipuri de variabile sunt folosite
sa memoreze diferite tipuri de date, tipul fiecarei variabile trebuie specificat.
2entru a ilustra aceasta idee vom calcula cate ore si minute contin un anumit numar de zile.
?lgoritmul ar fi5
1. asigneaza un numar de zile unei variabile7
2. calculeaza numarul de ore si memoreaza6l intr6o variabila7
3. calculeaza numarul de minute si memoreaza6l intr6o variabila7
4. afiseaza numarul de zile, ore si minute pe ecran.
Urmatorul program scris in C reprezinta implementarea algoritmului precedent5
#include Dstdio.*@
main%&
E
int zile, ore, minute7
zile1'7
ore124Jzile7
minute1$/Jore7
printf%(4 saptamana are Kd ore, Kd minute.Fn(,ore, minute&7
G
Cand compilam si rulam acest program, pe ecran va apare mesa<ul5
4 saptamana are 1$+ ore, 1//+/ minute.
6666666666666
Explicatii:
6666666666666
1. Hinia
int zile, ore, minute7
reprezinta o declaratie de variabile. Variabilele zile, ore, minute sunt declarate de tip (int(, unul
dintre cele mai importante tipuri din C. 4 variabila de tip (int( poate lua o valoare intreaga intre
632$'+ si 32$''. 9oate variabilele dintr6un program trebuie declarate inainte de a fi utilizate.
8eclaratiile, la fel ca si instructiunile, au la sfarsit (7(.
2. Hinia
zile1'7
reprezinta o instructiune de atribuire %sau asignare&. ,emnul (1( este operatorul de asignare de baza
in C. Valoarea expresiei din partea dreapta a simbolului (1( este atribuita variabilei din partea
stanga.
3. nstructiunea
printf%(4 saptamana are Kd ore, Kd minute.Fn(,ore, minute&7
este similara celei prezentate in exemplul precedent, dar are trei argumente. 2rimul argument,
intotdeauna un sir de caractere, se numeste sir de control. ?ici, intalnim specificarea de conversie
%care se mai numeste format& (Kd(. "ormatele (Kd( determina tiparirea valorilor expresiilor
corespunzatoare %al doilea si al treilea argument& in formatul intregilor zecimali. ?sadar, primul
format (Kd( corespunde cu valoarea variabilei (ore(, iar cel de6al doilea format (Kd( cu valoarea
variabilei (minute(.
n C, toate variabilele trebuie declarate inainte de a fi utilizate in expresii si instructiuni. "orma
generala a unui program simplu este5
directive de precompilare
main%&
E
declaratii
instructiuni
G

Un nume de variabila, numit si identificator, consta dintr6o secventa de litere, cifre si (underscore(,
dar fara a incepe cu cifra. Cuvintele c*eie, numite si cuvinte rezervate, nu pot fi utilizate ca nume de
variabile. .xemple de cuvinte c*eie5 c*ar, int, float.
4peratorii binari
L 6 J : K
sunt folositi pentru adunare, scadere, inmultire, impartire sau modul.
.xemple5 ! K 2 1 1 si ' K 4 1 3.
.vident, in expresia a K b, b nu trebuie sa fie zero, din moment ce nu se poate face impartirea cu
zero.
6666666666666666666666666666666666666666666666666666666666666666
Un exemplu de utilizare a variabilelor de tip float
6666666666666666666666666666666666666666666666666666666666666666
#include Dstdio.*@
main%&
E
float x, M7

x 1 1./7
M 1 2./7
printf%(,uma dintre x si M este Kf.Fn(, xLM&7
G

2e ecran se va afisa
,uma dintre x si M este 3.//////.
66666666666666
Observatii:
66666666666666
1. Hinia
float x, M7
semnifica declararea variabilelor x si M de tip (float( %deci de tip real&. n realitate sunt numere
rationale din intervalul
N61/AE3/+G,61/AE63/+GO U N1/AE63/+G,1/AE3/+GO
2. Hinia
printf%(,uma dintre x si M este Kf.Fn(, xLM&7
are doua argumente si reprezinta o tiparire la ecran. 8e remarcat, ca spre deosebire de exemplele
precedente %unde foloseam formatul Kd&, aici folosim formatul pentru numere reale, care este (Kf(.
3. 2recizarea tipului variabilelor este esential. 8e exemplu, daca, sa zicem, ca x1'./ si M12./, sunt
declarati ca fiind de tip float, atunci x:M se evalueaza la 3.!. 8aca, insa x1' si M12, sunt declarati ca
fiind de tip int, atunci x:M se evalueaza la 3 %ramane doar partea intreaga&.
6666666666666666
Initializarea
6666666666666666
nitializarea variabilelor se poate face si cand se declara acestea. 8e exemplu, putem scrie5
c*ar c1P?P7
int i117
2utem astfel modifica programul precedent, inlocuind liniile
int zile, ore, minute7
zile1'7
cu
int zile1', ore, minute7
66666666666666
Observatii:
66666666666666
1. 8e obicei, pentru initializarea unei variabile se folosesc constante sau expresii constante. ,e pot
insa folosi si variabile care au de<a valoarea precizata. 8e exemplu, urmatoarea secventa de
program este corecta5
int zile1', ore1zile J 24, minute1ore J $/7
666666666666666666666666666666666666
Folosirea directivei #define
666666666666666666666666666666666666
0eamintim ca in procesul de compilare a programelor C, intai este invocat preprocesorul. 8e
exemplu, pot fi incluse fisiere, sau anumite siruri de caractere specificate pot fi modificate in alte
siruri. 8irectivele de preprocesare incep cu caracterul # %in C traditional, acesta trebuie pus pe
prima coloana, pe cand in ?=, C poate fi precedat de spatii&. ,e recomanda scrierea # pe prima
coloana, iar a directivelor de precompilare la inceputul programului. ata cateva exemple de folosire
a directivei (#define(5
#define H;9 1//
#define 2 3.141!-
66666666666666
Observatii:
66666666666666
1. 8aca aceste directive de preprocesare apar la inceputul fisierului, atunci in momentul compilarii
preprocesorul sc*imba toate aparitiile identificatorului H;9 la 1// si a lui 2 cu 3.141!-.
,ingurele care raman nesc*imbate sunt sirurile constante. 8e exemplu, preprocesorul va sc*imba
printf%(2 1 KfFn(, 2&7 in printf%(2 1 KfFn(, 3.141!-&7
8eoarece identificatorul 2 se va inlocui peste tot %cu exceptia sirurilor constante& in 3.141!-, atunci
acesta se va numi constanta simbolica.
2. 8irectiva #define poate aparea oriunde in program, dar ea afecteaza numai liniile care urmeaza
acesteia.
3. 2rin conventie, identificatorii care trebuie sc*imbati de preprocesor se scriu cu ma<uscule.
66666666666666666666666666666666666666666666666666
Avantae ale folosirii directivei #define
66666666666666666666666666666666666666666666666666
1. Hizibilitate marita. ,e refera la citirea si intelegerea rapida a fisierului sursa %2 stim ce inseamna
si ne amintim ca este 3.ceva, deci nu trebuie sa scriem de fiecare data valoarea sa&7
2. ,c*imbarile ulterioare ale unor valori constante se face foarte usor. 8e exemplu, vrem sa
modificam valoarea lui H;9 la 1////. n locul liniei
#define H;9 1//
scriem
#define H;9 1////
8aca nu am fi folosit acest mod de definire a constantei H;9, atunci ar fi trebuit sa modificam
peste tot in program 1// cu 1////.
66666666666666666666666666666666666666666666666
Folosirea functiilor printf!" si scanf!"
66666666666666666666666666666666666666666666666
"unctiile de tiparire, respectiv de citire, (printf%&( si (scanf%&( au urmatoarele argumente5
sirCdeCcontrol si celelalteCargumente
unde sirCdeCcontrol este un sir care poate contine specificatii de conversie, sau formate. 4
specificare de conversie incepe cu caracterul K si se termina cu caracterul de conversie. 8e
exemplu, in formatul Kd, litera (d( este caracterul de conversie.
666666666666666666666666666
Folosirea lui printf!"
666666666666666666666666666
0eamintim ca formatul Kd este folosit pentru scrierea valorii unei expresii ca un intreg zecimal. n
mod similar5
6 Kc este folosit pentru tiparirea unei expresii ca un caracter
6 Kf este folosit pentru tiparirea unei expresii reale
6 Ks este folosit pentru tiparirea unui sir de caractere
66666666666
Exemplu:: "ie instructiunea5
66666666666
printf%(;ultime de argumente5 Ks Kd Kf KcKcFn(,(one(,2,2.33,PQP,P4P&7

?rgumentele lui (printf%&( sunt separate de virgula, deci avem sase argumente. 2rimul argument
este sirul de control. 4btinem corespondenta5
Ks D666@ (one(
Kd D666@ 2
Kf D666@ 2.33
Kc D666@ PQP
Kc D666@ P4P

Cand se executa programul ce contine aceasta instructiune, obtinem5
;ultime de argumente5 one 2 2.33//// Q4
66666666666666
Observatii:
66666666666666
1. 8aca instructiunea (printf%&( contine prea multe caractere, atunci se poate scrie aceasta pe mai
multe linii, separate prin virgula. 8e exemplu, putem scrie5
printf%(KsKsFn(,
(?ceasta instructiune se va scrie (,
(pe o linie de text foarte lunga.Fn(&7
9abelul de mai <os descrie cum caracterele de conversie afecteaza argumentele corespunzatoare.
printf%&
B66666666666666666666666666666666666666666666666666666666666666666666666666666666B
B Caracter B B
B de B Cum este tiparit argumentul corespunzator ? B
B conversie B B
B66666666666666666666666666666666666666666666666666666666666666666666666666666666B
B c B ca un caracter B
B d B ca un intreg zecimal B
B e B ca un numar in virgula flotanta in notatia stiintifica B
B f B ca un numar in virgula flotanta B
B g B in format e sau f %alegand cel mai scurt dintre ele& B
B s B ca un sir B
B666666666666666666666666666666666666666666666666666666666666666666666666666666666B
Cand un argument este tiparit, locul unde este tiparit se numeste campul sau, iar numarul de
caractere ale acestui camp se numeste lungimea campului. ?ceasta lungime poate fi specificata intr6
un format ca un intreg plasat intre caracterul K si caracterul de conversie. 8e exemplu,
instructiunea
printf%(KcK3cK'cFn(, P?P, PIP, PCP&7
va tipari
? I C
2entru numerele in virgula flotanta, putem controla precizia %numarul de cifre zecimale&, la fel ca
lungimea campului. "orma generala a formatului este
Km.nf
si semnifica ca m este lungimea campului, iar n precizia. "ormatul Kmf specifica doar lungimea
campului, iar formatul K.nf numai precizia. 8e exemplu, instructiunile5
printf%(=umere15 K.1f K.2f K.3fFn(, 1./, 2./, 3./&7
printf%(=umere25 K'.1f K'.2f K'.3fFn(, 4./, !./, $./&7
vor avea ca efect afisarea5
=umere15 1./ 2.// 3.///
=umere25 4./ !.// $.///
66666666666666666666666666
Folosirea lui scanf!"
66666666666666666666666666
"unctia (scanf%&( este asemanatoare cu (printf%&(, dar este folosita pentru intrari in loc de iesiri.
2rimul sau argument este un sir de control care are formatele corespunzatoare cu variatele moduri
de interpretare a sirurilor de intrare. 8upa sirul de control urmeaza adresele variabilelor. ?dresa
unei variabile este locul din memorie unde este memorata variabila %vom reveni in capitolele
viitoare&. ,imbolul (R( reprezinta operatorul de adresa. 8e exemplu,
scanf%(Kd(, Rx&7
formatul Kd implica interpretarea caracterelor tiparite la intrare ca un intreg zecimal, si apoi
memorarea valorii variabilei la adresa lui x.
9abelul de mai <os descrie efectele caracterelor de conversie din formate folosite de functia scanf%&.
scanf%&
B6666666666666666666666666666666666666666666666666666666666666666666666666B
B Caracter B B
B de B Ha ce caractere se face convertirea ? B
B conversie B B
B6666666666666666666666666666666666666666666666666666666666666666666666666B
B c B la un caracter B
B d B la un intreg zecimal B
B f B la un numar in virgula flotanta %float& B
B lf B la un numar in virgula flotanta %double& B
B Hf B la un numar in virgula flotanta %long double& B
B s B la un sir B
B6666666666666666666666666666666666666666666666666666666666666666666666666B
66666666666
?tentie S "unctia (prinf%&( foloseste formatul Kf pentru tiparirea numerelor
66666666666 float si double, pe cand (scanf%&( foloseste formatul Kf pentru
citirea unui float si Klf pentru citirea unui double.
666666666666
Exemplu:: ?ria unui cerc.
666666666666
#include Dstdio.*@
#define 2 3.141!-2$!3!+-'-3
main%&
E
double raza7
printf%(FnKsFnFnKs(,
(?cest program calculeaza aria cercului(,
(8ati raza5(&7
scanf%(Klf(, Rraza&7
printf%(FnKsFnKsK.2fKsK.2fKsK.2fFnKsK.!fFnFn(,
(?ria 1 2 J raza J raza(,
( 1 (, 2, ( J (, raza, ( J (, raza,
( 1 (, 2 J raza J raza&7
G

2resupunem ca la executia programului introducem raza egala cu 2.333. ?tunci vor apare pe ecran5
?cest program calculeaza aria cercului

8ati raza5 2.333

?ria 1 2 J raza J raza
1 3.14 J 2.33 J 2.33
1 1'./--34

8aca am calcula separat %pe *artie&, am obtine ?ria 1 3.14 J 2.33 J 2.33 1 1'./4$'4$, numar care
nu coincide cu cel furnizat de calculator. Tustificarea este aceea ca 2 si raza sunt tiparite doar cu
doua zecimale, pe cand valorile lor sunt pastrate in memorie cu precizie mai mare.
66666666666666666666666666666
Instructiunea #$%ile#
66666666666666666666666666666
nstructiunea )*ile face parte din categoria actiunilor repetitive. 2entru a intelege aceasta
instructiune, vom face un exemplu de adunare a numerelor de la 1 la 1/.
6666666666666
Exemplu::
6666666666666
#include Dstdio.*@
main%&
E
int i11, suma1/7
)*ile %iD11/&
E
suma 1 suma L i7
i 1 i L 17
G
printf%(,uma primelor 1/ numere este KdFn(,suma&7
G
6666666666666
Explicatii:
6666666666666
1. Ha linia
int i11, suma1/7
se declara variabilele i si sum de tip int si sunt initializate cu 1 si /, respectiv.
2. Constructia
)*ile %iD11/&
E
suma 1 suma L i7
i 1 i L 17
G
reprezinta o instructiune )*ile %sau iteratie )*ile&. ;ai intai, se evalueaza expresia iD11/. Cum
valoarea initiala a lui i este egala cu 1, rezulta ca se vor executa instructiunile dintre acolade. ?stfel,
variabila suma va fi asignata cu vec*ea valoare a lui suma la care se adauga valoarea lui i. 8eci,
suma se evalueaza la 1. ?poi, variabila se evalueaza la suma dintre vec*ea valoare a lui i %i11& si
1, deci este egala cu 2. n acest moment, executia revine la inceput adica evaluam expresia iD11/.
Cum valoarea lui i este 2, rezulta ca se va executa iar corpul lui )*ile. Ha sfarsitul acestei iteratii,
suma este evaluata la 1L2, iar i la 3. ,e observa usor ca iD11/ este tot adevarata, deci se va executa
din nou corpul lui )*ile. Ha sfarsitul celei de6a treia iteratii, sum este evaluata la 1L2L3, iar i la 4.
2rocesul continua pana cand valoarea lui i este 11, care implica falsitatea expresiei iD11/. ?stfel se
iese din bucla )*ile.
3. nstructiunea
printf%(,uma primelor 1/ numere este KdFn(, suma&7
va afisa mesa<ul ,uma primelor 1/ numere este !!.
4. "ormatul general al instructiunii )*ile este
)*ile %expresie&
instructiune
unde instructiune poate fi o singura instructiune sau un grup de instructiuni delimitate prin E si G
%care se mai numeste si instructiune compusa&.
66666666666666666666666666666666666666666666666
&eneralizarea problemei precedente
66666666666666666666666666666666666666666666666
8orim sa citim mai multe numere %fara a sti aprioric numarul lor si care sunt acestea& si dorim sa
afisam suma lor.
Consideram urmatorul algoritm cu patru pasi5
1. nitializarea a doua variabile contor si suma7
2. ?fisarea unor mesa<e utile citirii numerelor7
3. Citirea repetata a numerelor, incrementarea variabilei contor si adunarea numarului citit la suma7
4. ?fisarea celor doua valori ale variabilelor.
nstructiunea )*ile este una din cele trei constructii existente in C menite sa descrie actiuni
repetitive. n solutia noastra, utilizam valoarea returnata de functia (scanf%&( pentru a controla
instructiunea )*ile. Consideram urmatorul cod C5
#include Dstdio.*@
main%&
E
int contor 1 /7
float suma 1 /./, x7
printf%(,uma urmatoarelor numere va fi calculataFn(&7
printf%(8ati numerele5Fn(&7
)*ile %scanf%(Kf(, Rx&111&
E
contor 1 contor L17
suma 1 suma Lx7
G
printf%(FnKsK!dFnKsK12fFnFn(,
(=umarul de numere5 (, contor,
(,uma lor5 (, suma&7
G
66666666666666
Explicatii:
66666666666666
1. scanf%(Kf(, Rx&111
,imbolul 11 reprezinta operatorul de egalitate. .xpresia a11b intoarce true daca valoarea lui a este
egala cu valoarea lui b. 8e exemplu, 1111 intoarce true, 2113 intoarce false. "unctia (scanf%&( are
rolul de a citi caractere scrise de utilizator, sa le converteasca la float, si sa plaseze aceasta valoare
la adresa lui x. 8aca totul se desfasoara cu succes, atunci scanf%& intoarce valoarea 1, adica true.
8aca din anumite motive, procesul de conversie esueaza, atunci se intoarce valoarea / %deci false&.
8aca nu mai introducem nici o data %ControlAz in ;8684,, C0 urmat de ControlAd in U=>&,
atunci scanf%& va intoarce valoarea 61 %deci tot false&.
2. )*ile %scanf%(Kf(, Rx&111&
E
contor 1 contor L17
suma 1 suma Lx7
G
8upa cum am vazut mai sus, bucla )*ile se executa atata timp cat scanf%(Kf(, Rx&111 se evalueaza
la true. teratia se inc*eie cand tastam ControlAz sau ceva ce nu se poate converti la float, de
exemplu PaP sau C0. Ha fiecare executie a buclei se incrementeza variabila contor, iar valoarea
variabilei suma creste cu valoarea lui x %citita de la tastatura&.
3. printf%(FnKsK!dFnKsK12fFnFn(,
(=umarul de numere5 (, contor,
(,uma lor5 (, suma&7
2resupunem ca executam acest program pentru numerele
1.1 2./2 3.//3 4.///4 !.////!
2e ecran va apare rezultatul5
=umarul de numere5 !
,uma lor5 1!.12344-
666666666666666
Observatii:
666666666666666
1. 8aca numaram spatiile, observam ca valoarea lui contor a fost tiparita pe un camp de ! caractere,
iar suma pe 12 caractere. ?ceasta este cauzata de formatele (K!d( si (K12f(. 0etineti ca tiparirea
zecimalelor pentru suma este gresita de la a treia zecimala.
666666666666666666666666666666666666666666666
'tilul de redactare al programelor
666666666666666666666666666666666666666666666
Un stil bun de scriere a codului este esential pentru arta programarii. ?ceasta faciliteaza citirea,
scrierea si intretinerea programelor. Un stil bun foloseste5
1. spatii goale si comentarii, astfel incat codul este usor de citit si de inteles7
2. utilizarea indentarii este cruciala, care indica cu precizie structurile de control. 8e exemplu,
in constructia
)*ile %expresie&
instructiune
indentarea instructiunii indica ca executia acesteia este sub controlul iteratiei )*ile7
3. alegerea de nume sugestive pentru variabile7
4. corespondenta dintre acolade. 8e exemplu, urmatorul program este scris in stilul (Iell Habs
industrial programming stMle( %#,E,G,m pe prima coloana&.
#include Dstdio.*@
#include Dstdlib.*@
#define Q4 (,tart(
main%&
E
G
666666666666666
Observatii:
666666666666666
1. 2rogramatorii incepatori uneori cred ca vor (sparge( piata cu stilul lor propriu de redactare a
programelor. ?tentie S Utilizati strategia care este de<a in uz.
66666666666666666666666666666666666666666
Erori de programare frecvente
66666666666666666666666666666666666666666
;ai ales la inceputul invatarii programarii pe calculator, se fac multe erori simple, cum ar fi5
1. neinc*iderea sirului cu g*ilimele drepte. Cand compilatorul intalneste g*ilimeaua stanga, atunci
incepe sa colecteze toate caracterele care urmeaza spre a forma un sir de caractere, pana intalneste
g*ilimeaua dreapta. 8aca aceasta nu exista, atunci compilatorul da mesa<ul de eroare, de tipul5
Unterminated string or c*aracter constant
2. scrierea gresita a numelui variabilelor7
3. nedeclararea lor.
n general, compilatorul da un mesa< de eroare potrivit, alteori din cauza interpretarii separate, nu.
8e exemplu, scriem gresit (prinf%&( in loc de (printf%&(. ?tunci compilatorul va da un mesa< prin
care ne informeaza ca nu gaseste functia (prinf%&(. 8eci, el nu isi da seama de omiterea unei litere,
ci o interpreteaza in mod diferit.
4. daca dorim sa citim o variabila de tip double, atunci in functia (scanf%&( trebuie sa specificam
formatul (Klf(7
!. faptul ca uneori uitam ca in formatul (Km.nf( pentru afisarea cu virgula mobila, m semnifica
lungimea campului. 8e exemplu, pentru a specifica doua zecimale la dreapta si trei la stanga, nu
trebuie sa scriem K2.3f, ci K$.3f deoarece se numara si punctul zecimal7
$. poate cea mai frecventa greseala cand se foloseste scanf%& este uitarea operatorului de adresa.
8aca, de exemplu, scriem
scanf%(KdKd(, a, b& in loc de scanf%(KdKd(, Ra, Rb&
atunci compilatorul nu se va (prinde( de eroare. Iineinteles, ca vom obtine rezultate eronate %run6
time error& care sunt ceva mai greu de corectat.
666666666666666666666666666666666666666
(edirectarea intrarii si iesirii
666666666666666666666666666666666666666
2utem citi valorile variabilelor dintr6un fisier, nu neaparat de la tastatura. 8e exemplu, fisierul
nostru executabil se numeste (ex1.exe(. 2entru a extrage datele din fisierul de intrare (in.dat(, dam
comanda
ex1.exe D in.dat
2utem, de asemenea, sa scriem valorile unor variabile intr6un fisier extern, sa zicem (out.dat(.
?stfel dam comanda
ex1.exe @ out.dat
.vident, daca se doreste atat citirea unor variabile din fisier, cat si scrierea rezultatelor in alt fisier,
atunci se va da comanda
ex1.exe D in.dat @ out.dat
6666666666666
Exemplu::
6666666666666
#include Dstdio.*@
main%&
E
c*ar c*7

)*ile %scanf%(Kc(, Rc*& 111&
E
printf%(Kc(, c*&7
printf%(Kc(, c*&7
G
G
66666666666666666666666666666666666666666666666
Exercitii propuse spre implementare
66666666666666666666666666666666666666666666666
1. 2resupunem ca dispunem de rezultatele din anul curent relative la cursul de sc*imb valutar dintre
leu, dolar, marca si franc. ,a se scrie un program C care deseneaza %cu caractere ?,C& graficul
evolutiei raportului leu:valuta, unde valuta1Edolar, marca, francG. ?poi, desenati graficul raportului
dolar:marca si marca:franc.
2. ,crieti un program C care primeste la intrare un numar de secunde, si intoarce numar maxim de
ore, de minute, de secunde care este ec*ivalent ca timp. 8e exemplu, '3+4 secunde este ec*ivalent
cu 2 ore, 3 minute si 4 secunde.
3. "olosind o bucla )*ile, scrieti un program C care calculeaza al n6lea termen din sirul din
"ibonacci. 0eamintim ca sirul lui "ibonacci este dat de recurenta liniara de ordin 25
aC11aC2117
aCEnL2G1aCEnL1GLaCn, n@11
?tomi lexicali, operatori, sistemul C
2.1. Caractere si atomi lexicali
2.2. ?vanta<ele folosirii comentariilor
2.3. Cuvinte rezervate
2.4. dentificatori
2.!. Constante
2.$. ,iruri constante
2.'. 4peratori si semne de punctuatie
2.+. 4peratorii de precedenta si asociativitate
2.-. 4peratorii de incrementare si decrementare
2.1/. 4peratori de asignare
2.11. ,istemul C
2.12. .xercitii propuse spre implementare

111111111
Capitolul 2
111111111
111111111111111111111111111
?tomi lexicali, operatori, sistemul C
111111111111111111111111111
Ca si alte limba<e, C are un alfabet si reguli pentru scrierea programelor corecte folosind semne de
punctuatie. ?ceste reguli formeaza sintaxa limba<ului C. Compilatorul C are rolul de a testa daca un
program C este corect. 8aca sunt erori, atunci va afisa o lista de mesa<e de eroare si se va opri. 8aca
nu sunt erori, atunci compilatorul va (traduce( acest program in cod obiect, folosit de incarcator
pentru producerea codului executabil.
;ai intai compilatorul imparte multimea caracterelor %programul sursa& in atomi lexicali, care
reprezinta vocabularul de baza al limba<ului. n ?=, C %?=, 1 ?merican =ational ,tandards
nstitute& sunt sase tipuri de atomi lexicali %care se mai numesc si elemente lexicale sau unitati
lexicale&5
1. cuvinte rezervate %sau c*eie&7
2. identificatori7
3. constante7
4. siruri constante7
!. operatori7
$. semne de punctuatie.
6666666666666666666666666666666666
Caractere si atomi lexicali
6666666666666666666666666666666666
n fapt, un program C este o secventa de caractere. Caracterele permise in programele C sunt5
1. litere mici 5 a b ... z
2. litere mari 5 ? I ... U
3. cifre 5 / 1 ... -
4. alte caractere5 d f J : 1 % & E G N O D @ P (
S V # W K R C B A X F . , 7 5 ?
!. spatii 5 blan3, ne)line si tab
666666666666666
Comentarii
666666666666666
Comentariile sunt siruri de caractere cuprinse intre :J si J:. Comentariile nu reprezinta atomi
lexicali. Compilatorul va traduce comentariile intr6un singur caracter spatiu, de aceea comentariile
nu fac parte din codul executabil.
66666666666
?tentie S 2entru a verifica aceasta, puteti citi lungimea unui cod executabil %fara comentarii& si
66666666666 apoi sa comparati lungimea codului executabil obtinut dupa o noua compilare %cu
comentarii&.
6666666666666666666666666666666
.xemple5 de comentarii5
6666666666666666666666666666666
1. :J un comentariu J:
2. :JJ al doilea comentariu JJ:
3. :JJJJJ:
4. :J
J ?l patrulea
J comentariu
J:
!. :JJJJJJJJJJJJJJ
J ?l cincilea J
J comentariu J
JJJJJJJJJJJJJJ:
66666666666666666666666666666666666666666666
?vanta<ele folosirii comentariilor5
66666666666666666666666666666666666666666666
1. 2rincipalul scop este usurarea documentarii ulterioare. ,copul documentarii este explicarea clara
a folosirii programelor7
2. Uneori un comentariu poate contine informatii ce argumenteaza demonstratia corectitudinii
acelui algoritm7
3. ,fat S "olositi comentariile in timpul introducerii textului programului.
66666666666666666666666
Cuvinte rezervate
66666666666666666666666
Cuvintele rezervate %c*eie& au un inteles strict insemnand un atom individual. .le nu pot fi
redefinite sau utilizate in alte contexte. ata lista lor5

auto do goto signed unsigned
brea3 double if sizeof void
case else int static volatile
c*ar enum long struct )*ile
const extern register s)itc*
continue float return tMpedef
default for s*ort union

?numite implementari pot contine si alte cuvinte rezervate5
asm cdecl far *uge interrupt near pascal
Comparativ cu alte limba<e de programare, C are un numar mic de cuvinte rezervate. ?da, de
exemplu, are $2 cuvinte rezervate. ?ceasta este o caracteristica a limba<ului C de a avea doar cateva
simboluri speciale si cuvinte rezervate.
66666666666666666
dentificatori
66666666666666666
Un identificator este un atom lexical compus din secventa de litere, cifre sau underscore %(C(& cu
restrictia ca primul caracter este o litera sau underscore. n multe implementari C, se face distinctie
dintre litere mici si mari. n general, se obisnuieste ca identificatorii sa fie scrisi cu nume sugestive
care sa usureze citirea si documentarea programului.
666666666666
.xemple55
666666666666
1. 3, Cid, contor, unCidentificator sunt identificatori7
2. gresit#unu, 1//CgresitCdoi, 6plus nu sunt identificatori.
dentificatorii sunt creati pentru a da nume unice pentru diverse obiecte dintr6un program.
Cuvintele rezervate pot fi privite ca fiind identificatori. dentificatori precum (printf%&( sau (scanf%&(
sunt de<a cunoscuti sistemului C ca fiind functii de intrare:iesire.
4 diferenta ma<ora dintre sistemele de operare si sistemele C o reprezinta lungimea admisa pentru
numele identificatorilor. ?stfel, pentru unele sisteme vec*i, este acceptat un identificator al carui
nume are mai mult de + caractere, dar numai primele + sunt semnificative. 8e exemplu,
identificatorul C234!$'+1 este privit la fel ca C234!$'+2.
n ?=, C, primele 31 de caractere sunt luate in considerare.
666666666
?tentie S
666666666
dentificatorii care incep cu underscore pot fi confundati cu numele variabilelor sistem. 8e
exemplu, identificatorul Ciob declarat in biblioteca Dstdio.*@ este folosit pentru numele unui vector
de structuri. 8aca un programator foloseste un identificator cu acelasi nume, dar pentru alte scopuri,
atunci ori se va semnala o eroare aparent necunoscuta, ori %si mai rau& compilatorul se va comporta
ciudat. 0ecomandarea este5 =u folositi identificatori care incep cu underscore.
6666666666666
Constante
6666666666666
C manipuleaza diferite tipuri de valori. =umere precum / si 1' sunt exemple de constante intregi,
iar numere precum 1./ si 3.141!- sunt exemple de constante numere zecimale. Ca si multe alte
limba<e, C trateaza constantele (int( si (float( in mod diferit. Constantele caracter sunt foarte
apropiate de tipul (int( %vom reveni&. Un caracter special l6am si intalnit de<a. .ste vorba de PFnP,
care se mai c*eama (secventa escape(. n traducere libera, ar insemna (evadare a lui n din intelesul
uzual(. n fapt, el este folosit pentru a trece cursorul curent la linie noua %ne)line&.
Constantele de intregi, reali, caractere si enumerare sunt toate colectate de compilator ca fiind
atomi lexicali. 8in cauza limitelor impuse de memoria masinilor, unele constante care pot fi
exprimate sintactic nu pot fi disponibile pe o masina anume. 8e exemplu, numarul
1234!$'+-//////////// nu poate fi memorat ca fiind un intreg.
666666666666666666666
,iruri constante
666666666666666666666
4 secventa de caractere incadrate intre g*ilimele, de exemplu (abc(, este un sir constant. .ste
inteles de compilator ca fiind un singur atom lexical. n capitolele ulterioare, vom vedea ca de fapt
sirurile constante se memoreaza ca siruri de caractere. ,irurile constante sunt tratate mereu diferit
fata de constantele de tip caracter. 8e exemplu, (a( nu este totuna cu PaP.
8e mentionat ca g*ilimeaua ( reprezinta un singur caracter, nu doua. 8e aceea, daca dorim sa apara
intr6un sir constant, atunci ea trebuie precedata de F %bac3slas*&. 8aca dorim ca intr6un sir sa apara F,
atunci trebuie sa6l precedam tot cu F %devenind astfel FF&.
666666666666
.xemple55
666666666666
1. (sir text(
2. (( :J sirul vid J:
3. ( ( :J sir de spatii J:
4. ( a 1 b L c ( :J nu se executa nimic J:
!. ( :J acesta nu este un comantariu J: (
$. ( un sir ce contine g*ilimea F( (
'. ( un sir ce contine bac3slas* FF (
+. :J (gresit( J: :J nu este un sir J:
-. (gresit
doi( :J nici asta nu este sir J:
8oua siruri constante care sunt separate doar printr6un spatiu vor fi concatenate de compilator intr6
unul singur. 8e exemplu,
(abc( (def( este ec*ivalent cu (abcdef(
?ceasta este o trasatura a limba<ului ?=, C, nefiind disponibil in C traditional. ,irurile constante
sunt tratate de compilator ca atomi lexicali. Ca si alte constante, compilatorul va rezerva spatiu in
memorie pentru pastrarea sirurilor constante.
6666666666666666666666666666666666666666666
4peratori si semne de punctuatie
6666666666666666666666666666666666666666666
n C, exista multe caractere speciale cu inteles specific. 8e exemplu, operatorii aritmetici
L 6 J : K
reprezinta adunarea, scaderea, inmultirea, impartirea, modulul, respectiv. 0eamintim %pentru
bubulici& ca a K b inseamna restul impartirii intregi a lui a la b %notatie matematica5 a mod b7 a nu
se confunda modul cu valoarea absoluta&. 8e exemplu, ! K 3 are valoarea 2. ?tentie la numere
intregi negative %Vezi .xercitiul 1&.
?numite simboluri au intelesuri dependente de context. Consideram simbolul K din instructiunile
printf%(Kd(, a&7 si a 1 b K '7
2rimul simbol K este un format de scriere, pe cand al doilea reprezinta operatorul modul.
n exemplul de mai <os, parantezele %,& se folosesc atat pentru a preciza ca %& este un operator
%(main( reprezinta numele unei functii&, cat si ca semne de punctuatie.
main%&
E
int a, b 1 2, c 1 37
a 1 1' J %b L c&7
...
G
?numite caractere speciale sunt folosite in multe contexte. "ie espresiile
a L b LLa a L1 b
.le folosesc caracterul L, dar LL este un singur operator, la fel ca si L1.
666666666666666666666666666666666666666666666666666666
4peratorii de precedenta si asociativitate
666666666666666666666666666666666666666666666666666666
4peratorii au reguli de precedenta si asociativitate care implica evaluarea expresiilor. 8in moment
ce expresiile din interiorul parantezelor se evalueaza mai intai, este clar ca parantezele sunt folosite
pentru a preciza care operatii se fac mai intai. Consideram expresia
1 L 2 J 3
n C, operatorul J are prioritate %precedenta& mai mare decat L, deci se va face intai inmultirea apoi
adunarea. 8eci valoarea expresiei este '. 4 expresie ec*ivalenta este
1 L %2 J 3&
2e de alta parte, expresia %1 L 2& J3 este diferita7 ea are valoarea -.
Consideram acum expresia 1 L 2 6 3 L 4 6 !. 4peratorii L si 6 au aceeasi precedenta, deci se va
folosi regula de asociativitate la stanga. ?stfel %%%1 L 2& 6 3& L 4& 6! este o expresie ec*ivalenta.
n continuare vom prezenta un tabel in care precizam regulile de precedenta si asociativitate pentru
cativa operatori din C.
B6666666666666666666666666666666666666666666666B6666666666666666666666666666B
B 4peratori B ?sociativitate B
B6666666666666666666666666666666666666666666666B6666666666666666666666666666B
B %& LL %postfix& 66 %postfix& B de la stanga la dreapta B
B6666666666666666666666666666666666666666666666B6666666666666666666666666666B
B L%unar& 6%unar& LL%prefix& 66%prefix& B de la dreapta la stanga B
B6666666666666666666666666666666666666666666666B6666666666666666666666666666B
B J : K B de la stanga la dreapta B
B6666666666666666666666666666666666666666666666B6666666666666666666666666666B
B L 6 B de la stanga la dreapta B
B6666666666666666666666666666666666666666666666B6666666666666666666666666666B
B 1 L1 61 J1 :1 etc. B de la dreapta la stanga B
B6666666666666666666666666666666666666666666666B6666666666666666666666666666B
9oti operatorii de pe o linie %de exemplu, J, :, K& au aceeasi prioritate intre ei, dar au prioritate mai
mare decat cei ce apar in liniile de mai <os.
4peratorii L si 6 pot fi si binari si unari. 8e remarcat ca cel unar are prioritate mai mare. 8e
exemplu, in expresia
6 a J b 6 c
primul operator 6 este unar, pe cand al doilea binar. "olosind regulile de precedenta, se vede ca
aceasta este ec*ivalenta cu
%%6 a& J b& 6 c
6666666666666666666666666666666666666666666666666666666666
4peratorii de incrementare si decrementare
666666666666666666666666666666666666666666666666666666666
4peratorii de incrementare si de decrementare %LL, 66& au o prioritate foarte mare %dupa cum se
poate vedea in tabelul de mai sus& si se pot asocia atat de la dreapta la stanga, cat se de la stanga la
dreapta. 4peratorii LL si 66 se pot aplica variabilelor, dar nu si constantelor. ;ai mult, ei pot apare
ca notatie prefixata, cat si postfixata. 8e exemplu, putem avea LLi si contorLL, dar nu putem avea
1$'LL sau LL%a J b 6 1&.
"iecare din expresiile LLi si iLL au o valoare7 mai mult fiecare cauzeaza incrementarea valorii
variabilei i cu o unitate. 8iferenta este5
1. expresia LLi va implica intai incrementarea lui i, dupa care
expresia va fi evaluata la noua valoare a lui i7
2. expresia iLL va implica evaluarea sa la valoarea lui i, dupa
care se va incrementa i.
666666666666
.xemplu55
666666666666
int a, b, c 1 /7
a 1 LLc7
b 1 cLL7
printf%(a1Kd b1Kd c1Kd LLc1KdFn(, a, b, c, LLc&7

ntrebare5 Ce se va tipari la ecran ?
ntr6un mod similar, 66i va implica decrementarea valorii lui i cu 1, dupa care expresia 66i va avea
noua valoare a lui i, pe cand i66 se va evalua la valoarea lui i, dupa care i se va decrementa cu 1.
0etineti deci ca, spre deosebire de L si 6, operatorii LL si 66 vor determina sc*imbarea valorii
variabilei i din memorie. ,e mai spune ca operatorii LL si 66 au efect lateral %side effect&.
8aca nu folosim valoarea lui LLi sau a lui iLL, atunci acestea sunt ec*ivalente. ;ai precis,
LLi7 si iLL7
sunt ec*ivalente cu
i 1 i L 17

666666666666
.xemple55
666666666666
2resupunem ca avem declaratiile
int a 1 1, b 1 2, c 1 3, d 1 47
?tunci avem5
.xpresie .xpresie ec*ivalenta parantetizata Valoare

a J b : c %a J b& : c /
a J b K c L 1 %%a J b& K c& L 1 3
LL a J b 6 c 66 %%LL a& J b& 6 %c 66& 1
' 6 6 b J LL d ' 6 %%6 b& J %LL d&& 1'
66666666666666666666666666666
4peratori de asignare
6666666666666666666666666666
2entru sc*imbarea valorii unei variabile, am utilizat de<a instructiunea de asignare %atribuire&, cum
ar fi
a 1 b L c7
,pre deosebire de celelalte limba<e, C trateaza 1 ca un operator. 2recedenta sa este cea mai mica
dintre toti operatorii si asociativitatea sa este de la dreapta la stanga. 4 expresie de asignare simpla
are forma5
variabila 1 parteCdreapta
unde (parteCdreapta( este o expresie. 8aca punem 7 la sfarsitul expresiei de asignare, atunci vom
obtine instructiune de asignare. 4peratorul 1 are doua argumente, (variabila( si (parteCdreapta(.
Valoarea expresiei (parteCdreapta( este asignata pentru (variabila( si aceasta valoare se returneaza
de catre expresia de asignare %ca un tot unitar&.
666666666666
.xemplu55 Consideram instructiunile
666666666666
b 1 27
c 1 37
a 1 b L c7
unde toate variabilele sunt de tipul int. "olosind faptul ca 1 este un operator, putem condensa
aceasta la
a 1 %b 1 2& L %c 1 3&7
.xplicatia este ca expresia de asignare b 1 2 atribuie valoarea 2 atat variabilei b, cat si instructiunii
intregi.
8aca exemplul de mai sus pare artificial, atunci o situatie frecvent intalnita este asignarea multipla.
8e exemplu, instructiunea
a 1 b 1 c 1 /7
este ec*ivalenta cu %folosind asociativitatea de la dreapta la stanga&
a 1 %b 1 %c 1 /&&7
0elativ la 1, mai exista inca doi operatori. .ste vorba de L1 si 61. .xpresia
3 1 3 L 2
va aduna 2 la vec*ea valoare a lui 3 si va asigna rezultatul lui 3 si intregii expresii. .xpresia
3 L1 2
face acelasi lucru.
6666666666666666666666666666666666666666
Hista operatorilor de asignare5 1 L1 61 J1 :1 K1 @@1 DD1 R1 A1 B1
6666666666666666666666666666666666666666
9oti acesti operatori au aceeasi precedenta si se asociaza de la dreapta la stanga. ,emantica lor este
specificata de
variabila op1 expresie
care este ec*ivalent cu
variabila 1 variabila op %expresie&
cu exceptia faptului ca variabila sa nu fie o expresie.
666666666666
.xemplu55
666666666666
.xpresia de asignare
< J1 3 L 3
este ec*ivalenta cu
< 1 < J %3 L 3&
si nu cu
< 1 < J 3 L 3
"ie declaratia
int i 1 1, < 1 2, 3 1 3, m 1 47
Consideram urmatoarele exemple de evaluari ale expresiilor
.xpresie .xpresie ec*ivalenta .xpresie ec*ivalenta Valoare
i L1 < L 3 i L1 %< L 3& i 1 %i L %< L 3&& $
< J1 3 1 m L ! < J1 %3 1 %m L !&& < 1 %< J %3 1 %m L !&&& 1+
666666666666
.xemple55 Calculul puterilor lui 2
66666666666
#include Dstdio.*@

main%&
E
int i 1 /, po)er 1 17

)*ile %LLi D1 1/&
printf%(K$d(, po)er J12&7
printf%(Fn(&7
G
esirea acestui program va fi5
2 4 + 1$ 32 $4 12+ 2!$ !12 1/24
666666666666666
,istemul C
666666666666666
n capitolele precedente am prezentat directiva de preprocesare #include si #define. 8irectiva
#include avea forma generala5
#include DnumeCfisier@
si insemna includerea in acest loc a fisierului *eader specificat din directoarele specifice C %;,6
84, FbcFinclude sau FtcFinclude, U=> :usr:include&. 4 alta forma este
#include (numeCfisier(
ce are drept scop inlocuirea acestei linii cu o copie a fisierului (numeCfisier( din directorul curent.
8eci, atunci cand utilizam o functie C, trebuie sa specificam prototipul ei %scanf%& si printf%& au
prototipul Dstdio.*@, rand%& are prototipul Dstdlib.*@&.
666666666666
.xemplu55
666666666666
#include Dstdio.*@
#include Dstdlib.*@

main%&
E
int i, n7

printf%(FnKsFnKs(,
(Vom afisa niste intregi aleatori.(,
(Cati doriti sa vedeti ? (&7
scanf%(Kd(, Rn&7
for %i 1 /7 i D n7 LLi&
E
if %i K $ 11 /&
printf%(Fn(&7
printf%(K12d(, rand%&&7
G
printf%(Fn(&7
G
8aca de exemplu, tastam numarul 11, atunci pe ecran vor apare 11 numere intregi aleatoare.
66666666666666
4bservatii5
66666666666666
1. ?tentie S LLi D n este diferit de iLL D n7
2. 4peratorul 11 este operatorul de egalitate %test&, adica a 11 b va fi evaluata la true daca si numai
daca valoarea lui a este egala cu valoarea lui b %in caz contrar va fi evaluata la false&.
3. "unctia rand%& intoarce un intreg cuprins intre / si n, unde n este dependent de sistem. n ?=,
C, n este dat de constanta 0?=8C;?>.
66666666666666666666666666666666666666666666666
.xercitii propuse spre implementare
66666666666666666666666666666666666666666666666
1. nvestigati comportarea operatorilor : si K pentru numere intregi negative. ;entionam ca in
unele sisteme C, ':62 da rezultatul 63, in altele 64. Verificati daca se pastreaza identitatea din
matematica %prevazuta a fi adevarata de ?=,&5
%a : b& J b L a K b 1 a
,ugestie5 ,crieti un program C care sa contina liniile de cod
int a, b7
printf%(dati doi intregi nenuli5 (&7
scanf%(KdKd(, Ra, Rb&7
printf%(KsK4dFnKsK4dFnKsK4dFnKsK4dFnKsK4dFn(,
( a 1(,a,
( b 1(,b,
( a : b 1(, a : b,
( a K b 1(, a K b,
(Verif. ?=,1(, %a : b& J b L a K b 6 a&7
2. ,crieti un program C care sa calculeze cel mai mare divizor comun dintre a si b, unde a, b sunt
numere intregi, folosind algoritmul lui .uclid.
3. 8in moment ce L si LL sunt operatori, rezulta ca expresia aLLLb poate fi interpretata fie ca
aLL L b fie a L LLb
depinzand de modul de grupare semnului L. ,crieti un program scurt pentru a vedea ce interpretare
face compilatorul C.
4. nlocuiti LLi cu iLL in programul de calcul a puterilor lui 2.
!. Un patrat magic %de latura n& are proprietatea ca include in locatiile sale toate numerele intregi
din intervalul 1, ..., nA2 si sumele numerelor de pe fiecare linie, fiecare coloana sau fiecare
diagonala sunt egale. 8e exemplu5
$ 1 +
' ! 3
2 - 4
este un patrat magic de dimensiune 3. ,a se scrie un program C care testeaza daca un patrat este
magic sau nu. 8e asemenea, incercati sa generati toate patratele magice de ordin n.
$. ,a se scrie un program C care sa calculeze nS, unde n@/ este un numar natural %iar nS 1 1 J 2 J
... J n&.
3. Controlul instructiunilor
3.1. 4peratori relationali, de egalitate si logici
3.2. 4peratori si expresii relationale
3.3. 4peratori si expresii de egalitate
3.4. 4peratori logici si expresii logice
3.!. .valuare rapida %s*ort6circuit&
3.$. nstructiunea compusa
3.'. nstructiunea vida
3.+. nstructiunile (if( si (if6else(
3.-. nstructiunea ()*ile(
3.1/. nstructiunea (for(
3.11. 4peratorul (,(
3.12. nstructiunea (do(
3.13. nstructiunea (goto(
3.14. nstructiunile (brea3( si (continue(
3.1!. nstructiunea (s)itc*(
3.1$. 4peratorul conditional
3.1'. .xercitii propuse spre implementare
11111111
Capitolul 3
11111111
111111111111111111
Controlul instructiunilor
111111111111111111
666666666666666666666666666666666666666666666666666666
4peratori relationali, de egalitate si logici
666666666666666666666666666666666666666666666666666666
4peratori relationali 5 D, @, D1, @1
4peratori de egalitate5 11, S1
4peratori logici 5 S, RR, BB
Ca si ceilalti operatori, acesti operatori au reguli de precedenta si asociativitate care determina
precis modul de evaluare a acestor
expresii.
66666666666666666666666666666666666666666666666666666666666666666666666666666666
B 4peratori B ?sociativitate B
66666666666666666666666666666666666666666666666666666666666666666666666666666666
%& LL %postfix& 66 %postfix& B de la stanga la dreapta B
L %unar& 6 %unar& LL %prefix& 66 %prefix& B de la dreapta la stanga B
J : K B de la stanga la dreapta B
L 6 B de la stanga la dreapta B
D D1 @ @1 B de la stanga la dreapta B
11 S1 B de la stanga la dreapta B
RR B de la stanga la dreapta B
BB B de la stanga la dreapta B
?5 B de la dreapta la stanga B
1 L1 61 J1 :1 etc B de la dreapta la stanga B
, %operatorul virgula& B de la stanga la dreapta B
6666666666666666666666666666666666666666666666666666666666666666666666666666666
4peratorul S este unar, spre deosebire de toti operatori %relationali, de egalitate si logici& care sunt
binari. 9oti operatorii vor fi prezenti in expresii ce pot lua valoarea intreaga 1 sau /. ;otivul este ca
C reprezinta (false( orice expresie egala cu zero, si (true( orice expresie diferita de zero.
666666666666
Exemple: n continuare, dam o lista de expresii ce se evaluaza la false
666666666666
1. 4 expresie de tip int ce are valoarea /7
2. 4 expresie de tip float ce are valoarea /./7
3. Caracterul null PF/P7
4. 2ointerul =UHH.
66666666666666666666666666666666666666666
4peratori si expresii relationale
66666666666666666666666666666666666666666
?m vazut ca operatorii D, @, D1, @1 sunt toti binari. .xpresiile ce contin acesti operatori pot lua
valoarea / sau 1.
66666666666
.xemple. 2rimele patru exemple sunt corecte, restul sunt gresite5
66666666666
1. a D 3
2. a @ b
3. 61.1 @1 %2.2 J x L 3.3&
4. a D b D c %corecta, dar confuza&
!. a 1D b
$. a D 1 b
'. a @@ b
"ie expresia relationala (a D b(. 8aca valoarea lui a este mai mica decat valoarea lui b, atunci
expresia va avea valoarea 1, pe care o gandim ca fiind (true(. 8aca valoarea lui a este mai mare
decat valoarea lui b, atunci expresia va avea valoarea /, pe care o gandim ca fiind (false(.
4bservam ca valoarea lui (a D b( este aceeasi cu valoarea lui (a 6 b D /(. "olosind precedenta
operatorilor aritmetici, aceasta este deci ec*ivalenta cu (%a 6 b& D /(. 8e altfel, pe multe masini,
expresii cum sunt (a D b( sunt implementate ca fiind (a 6 b D /(.
66666666666
Exemple: Vom considera urmatorul tabel cu declaratii si initializari.
66666666666
2resupunem ca avem declaratiile5
int i 1 1, < 1 2, 3 1 37
double x 1 !.!, M 1 '.'7
6666666666666666666666666666666666666666666666666666666666666666666666
B .xpresie B .xpresie ec*ivalenta B Valoare B
6666666666666666666666666666666666666666666666666666666666666666666666
i D < 6 3 i D %< 6 3& /
6 i L ! J < @1 3 L 1 %%6 i& L %! J <&& @1 %3 L 1& 1
x 6 M D1 < 6 3 61 %x 6 M& D1 %%< 6 3& 6 1& 1
x L 3 L ' D M : 3 %%x L 3& L '& D %M : 3& /
B6666666666666666666666B666666666666666666666666666666666B6666666666666B
666666666666666666666666666666666666666666
4peratori si expresii de egalitate
66666666666666666666666666666666666666666
.xpresiile pot contine si operatorii de egalitate 11 si S1. .xpresiile ce le contin au valoarea / sau 1.
66666666666
.xemple. 2rimele trei exemple sunt corecte, restul sunt gresite5
66666666666
1. c 11 P?P
2. 3 S1 62
3. x L M 11 2 J x 6 !
4. a 1 b
!. a 1 1 b 6 1
$. %x L M& 1S 44
ntuitiv, o expresie de egalitate cum ar fi a 11 b este sau (true( sau (false(. ;ai precis, daca a este
egal cu b, atunci a 11 b intoarce valoarea 1 %true&7 altfel, aceasta intoarce valoarea / %false&. 4
expresie ec*ivalenta este a 6 b 11 / %aceasta este ceea ce se implementeaza la nivel masina&.
.xpresia (a S1 b( ilustreaza folosirea operatorului (diferit de( %sau (nu este egal cu(&.
66666666666
Exemple: Vom considera urmatorul tabel cu declaratii si initializari.
66666666666
2resupunem ca avem declaratiile5
int i 1 1, < 1 2, 3 1 37
6666666666666666666666666666666666666666666666666666666666666666666666666
B .xpresie B .xpresie ec*ivalenta B Valoare B
6666666666666666666666666666666666666666666666666666666666666666666666666
i 11 < < 11 i /
i S1 < < S1 i 1
i L < L 3 11 6 2 J 6 3 %%i L <& L 3& 11 %%62& J %6 3&& 1
6666666666666666666666666B666666666666666666666666666666666666B6666666666B
666666666666666666666666666666666666666666
4peratori logici si expresii logice
666666666666666666666666666666666666666666
4peratorul logic S este unar, iar RR si BB sunt binari. .xpresiile ce contin acesti operatori intorc
valoarea / sau 1. =egarea logica poate fi aplicata unei expresii aritmetice sau unui tip pointer. 8aca
o expresie are valoarea /, atunci expresia negata are valoarea 1. 8aca expresia are o valoare diferita
de /, atunci expresia negata intoarce valoarea 1.
66666666666
.xemple. 2rimele trei exemple sunt corecte, restul sunt gresite5
66666666666
1. Sa
2. S%x L '.'&
3. S%a D b BB c D d&
4. aS
!. a S1 b %este corecta, dar se refera la operatorul (diferit(&
Unele identitati logice %din matematica& nu se (transmit( in C. 8e exemplu, se stie ca (not %not s&
1s(, in timp ce valoarea lui (SS!( nu este !, ci 1. ;otivul este ca operatorul (S( se asociaza de la
dreapta la stanga, si deci (SS!( este ec*ivalent cu (S%S!&(, care ec*ivalent cu (S%/&(, ce intoarce
valoarea 1.
666666666666
Exemple: Vom considera urmatorul tabel cu declaratii si initializari.
666666666666
2resupunem ca avem declaratiile5
int i 1 ', < 1 '7
double x 1 /./, M 1 ---.-7
66666666666666666666666666666666666666666666666666666666666666666666
B .xpresie B .xpresie ec*ivalenta B Valoare B
66666666666666666666666666666666666666666666666666666666666666666666
S %i 6 <& L 1 %S %i 6 <&& L 1 2
S i 6 < L 1 %%S i& 6 <& L 1 6$
S S %x L 3.3& S %S %x L 3.3&& 1
S x J S S M %S x& J %S %S M&& 1
6666666666666666666666B666666666666666666666666666666B6666666666666B
4peratorii logici binari RR si BB pot fi folositi in expresii care intorc / sau 1.
66666666666
.xemple. 2rimele patru exemple sunt corecte, restul sunt gresite5
66666666666
1. a RR b
2. a BB b
3. S%a D b& RR c
4. 3 RR %62 J a L '&
!. a RR
$. a B B b
'. a R b %corecta, dar se refera la operatii peste biti&
+. Rb %corecta, dar se refera la adresa lui b&66666666666
Exemple: Vom considera urmatorul tabel cu declaratii si initializari.
66666666666
2resupunem ca avem declaratiile5
int i 1 3, < 1 3, 3 1 37
double x 1 /./, M 1 2.37
66666666666666666666666666666666666666666666666666666666666666666666
B .xpresie B .xpresie ec*ivalenta B Valoare B
66666666666666666666666666666666666666666666666666666666666666666666
i RR < RR 3 %i RR <& RR 3 1
x BB i RR < 6 3 x BB %i RR %< 6 3&& /
i D < RR x D M %i D <& RR %x D M& /
i D < BB x D M %i D <& BB %x D M& 1
B6666666666666666666666B666666666666666666666666666666666B666666666666B
66666666666666666666666666666666666666
.valuare rapida %s*ort6circuit&
66666666666666666666666666666666666666
2entru expresiile ce contin RR sau BB, evaluarea are loc cand s6a stabilit de<a valoarea expresiei,
eventual fara parcurgerea intregii
expresii. ?stfel, presupunem ca (expr1( se evalueaza la / %false&. ?tunci expresia
expr1 RR expr2
se va evalua la /, fara a se mai face evaluarea expresiei (expr2(.
?lt exemplu, daca (expr1( se evalueaza la 1 %true&, atunci expresia
expr1 BB expr2
se va evalua la true fara a se mai evalua expresia (expr2(.
Uneori se mai spune ca operatorii RR si BB sunt lazM %adica le este lene sa mai evalueze toti
operanzii din expresie&.
66666666666666666666666666666
nstructiunea compusa
66666666666666666666666666666
4 instructiune compusa este un sir de declaratii si instructiuni delimitate de acolade. Ceea ce
acoladele delimiteaza se numeste (bloc(. 4 instructiune compusa este ea insasi o instructiune.
66666666666
Exemplu:
66666666666
E
a 1 17
E
b 1 27
c 1 37
G
G
6666666666666666666666666
nstructiunea vida
6666666666666666666666666
nstructiunea vida se reprezinta cu semnul 7 %punct si virgula&. .a se foloseste cand se doreste
folosirea ei sintactica, si nu neaparat folosire semantica. 8upa cum vom vedea, aceasta se foloseste
in constructii (if6else( si (for(. 4 expresie urmata de 7 se numeste (instructiune expresie(.
66666666666
Exemplu:
66666666666
a 1 b7
a L b L c7
7
printf%(KdFn(, a&7
66666666666666666666666666666666666666
nstructiunile (if( si (if6else(
66666666666666666666666666666666666666
"orma generala a instructiunii (if( este
if %expresie&
instructiune
,emantica intuitiva este simpla. ?stfel, daca valoarea expresiei este true %diferita de zero&, atunci se
executa instructiunea, altfel nu.
66666666666
Exemplu:
66666666666
nstructiunea (if( de mai <os va testa daca se poate face impartirea cu M %ce trebuie sa fie diferit de
/&5
if %M S1 /./&
x :1 M7
Urmatoarele doua instructiuni
if %< D 3&
min 1 <7
if %< D 3&
printf%(< este mai mic decat 3Fn(&7
se pot scrie intr6una singura
if %< D 3&
E
min 1 <7
printf%(< este mai mic decat 3Fn(&7
G
nstructiunea (if6else( de mai <os este foarte apropiata de instructiunea (if(. ?ceasta are forma
generala
if %expresie&
instructiune1
else
instructiune2
,emantica intuitiva este de asemenea clara. 8aca valoarea expresiei este diferita de zero, atunci se
executa instructiune1 si (se sare( peste instructiune2. 8aca valoarea expresiei este zero, atunci (se
sare( instructiune1, si se executa instructiune2.
666666666666
Exemplu:
666666666666
Urmatorul subprogram C de mai <os calculeaza si afiseaza minimul dintre x si M.
if %x D M&
min 1 x7
else
min 1 M7
printf%(Valoarea minima 1 KdFn(, min&7
66666666666666666666666666666
nstructiunea ()*ile(
66666666666666666666666666666
(Y*ile(, (for( si (do( sunt cele trei instructiuni repetitive din limba<ul C. Consideram urmatorul
format general al instructiunii ()*ile( %iteratia sau bucla ()*ile(&.
)*ile %expresie&
instructiune
instructiuneCurmatoare
;ai intai se evalueaza expresie. 8aca aceasta nu este zero %deci este (true(&, atunci se executa
instructiunea, si control trece la inceputul buclei ()*ile(. ?stfel, corpul buclei se executa de cate ori
expresie se evalueaza la (true(. 9erminarea buclei are loc cand expresie ia valoarea zero %adica
(false(&. n acest punct, controlul se paseaza catre (instructiuneCurmatoare(.
66666666666
Exemplu:66666666666
)*ile %i D1 1/&
E
suma L1 i7
LLi7
G
66666666666666666666666666
nstructiunea (for(
6666666666666666666666666
Ca si instructiunea ()*ile(, instructiunea (for( se foloseste pentru descrierea structurilor iterative
%repetitive&. ?stfel constructia
for %expresie17 expresie27 expresie3&
instructiune
instructiuneCurmatoare
este semantic ec*ivalenta cu
expresie17
)*ile %expresie2&
E
instructiune7
expresie37
G
instructiuneCurmatoare7
8eci, se va evalua expresie1. 8e obicei, aceasta se foloseste pentru initializarea buclei. ?poi, se
evalueaza expresie2. 8aca aceasta nu este zero %(true(&, atunci se executa instructiune, se evalueaza
expresie3, si controlul buclei se (paseaza( la inceputul buclei %cu deosebirea ca nu se mai evalueaza
expresie1&. 8e obicei, expresie2 este o expresie logica care controleaza bucla. ?cest proces
continua pana cand expresie2 este / %false&, punct in care se plaseaza controlul catre
instructiuneCurmatoare.
666666666666
Exemplu: .xemplul de mai <os calculeaza factorialul numarului n.
666666666666
factorial117
for %i 1 17 i D1 n7 iLL&
factorial J1 i7
4rice sau toate expresiile dintr6o instructiune (for( pot lipsi, dar nu poate lipsi 7.
66666666666
Exemple:
66666666666
.xemplul de mai <os calculeaza suma numerelor intregi de la 1 la 1/.
i 1 17
suma 1 /7
for % 7 i D1 1/7 LLi&
suma L1 i7
?cesta se poate scrie ec*ivalent5
i 1 17
suma 1 /7
for % 7 i D1 1/7 &
suma L1 iLL7
8aca, in sc*imb, lipseste expresie2, atunci obtinem o bucla infinita.
666666666666666666666
4peratorul (,(
666666666666666666666
4peratorul (,( are cea mai mica prioritate dintre toti operatorii din C. .ste un operator binar ce are
ca operanzi drept expresii si se
asociaza de la stanga la dreapta. ntr6o expresie de forma
expresie1 , expresie2
se evalueaza mai intai expresie1, apoi expresie2. .xpresia (,( intoarce valoarea si tipul operandului
din dreapta.
66666666666
Exemplu: 2resupunem ca a, b sunt de tip int. ?tunci expresia (,(
666666666666
a 1 /, b 1 1
intoarce valoarea 1 de tipul int.
4peratorul (,( este deseori folosit in instructiunea (for(.
6666666666
Exemplu: .xemplul de mai <os calculeaza factorialul numarului n %reluare&.
66666666666
for %factorial 1 1, i 1 17 i D1 n7 iLL&
factorial J1 i7
666666666666
Exemplu: 0evenim asupra unui exemplu precedent %suma primelor = numere naturale&
666666666666
for %suma 1 /, i 1 17 i D1 n7 LLi&
suma L1 i7
se poate scrie, ec*ivalent, in
for %suma 1 /, i 1 17 i D1 n7 suma L1 i, LLi&7
6666666666666
ntrebare5 Ce se intampla cu valoarea lui suma daca intervertim instructiunile
666666666666
suma L1 i cu LLi
66666666666
Exemplu:
66666666666
for %i1/, p 1 *ead7 p S1 =UHH7 p1p 6@ next &
.....
666666666666666666666666
nstructiunea (do(
66666666666666666666666
nstructiunea (do( poate fi considerata o varianta a instructiunii ()*ile(. 8eosebirea consta in faptul
ca pentru instructiunea ()*ile( testul se face la inceputul ciclului, iar pentru (do( la sfarsit.
Consideram constructia de forma
do
instructiune
)*ile %expresie&7
instructiuneCurmatoare
Ha inceput se executa instructiune, apoi se evalueaza expresie. 8aca valoarea lui expresie este
diferita de / %(true(&, atunci controlul se paseaza la inceputul instructiunii (do(, si procesul se
repeta. 8aca expresie se evalueaza la / %false&, atunci controlul se paseaza la
instructiuneCurmatoare.
66666666666
Exemplu: ,uma unor numere intregi diferite de /
66666666666
suma 1 i 1 /7
do
E
suma L1 i7
scanf%(Kd(, Ri&7
G
)*ile %i @ /&7
66666666666666666666666666
nstructiunea (goto(
6666666666666666666666666
nstructiunea (goto( %salt neconditionat& este considerata opusa programarii structurate. ,fatul
general valabil este evitarea acestei instructiuni. 9otusi, in unele cazuri se poate folosi %cand
simplifica controlul, cand face codul mai eficient&. 4 instructiune de etic*etare are forma5
etic*eta 5 instructiune
unde etic*eta este un identificator.
666666666666
Exemple:
666666666666
bMe5 exit%1&7
etic*eta15 a 1 b L c7
3335 a 1 b L c7 %exemplu gresit, de ce ?&
Controlul programului poate fi transferat neconditionat catre o instructiune de etic*etare astfel
goto etic*eta7
6666666666666666666666666666666666666666666666
nstructiunile (brea3( si (continue(
6666666666666666666666666666666666666666666666
Cele doua instructiuni
brea37 si continue7
intrerup controlul normal al programelor. nstructiunea (brea3( va cauza iesirea din bucla in care se
afla sau din instructiunea (s)itc*(. nstructiunea (continue( se poate afla numai in instructiuni
(for(, ()*ile( si (do(. .a are rolul de a trasmite controlul catre sfarsitul buclei respective.
66666666666
Exemple:
66666666666
)*ile %1&
E
scanf%(Klf(, Rx&7
if %x D /./&
brea37 :J iesim cand x este negativ J:
printf%(KlfFn(, sZrt%x&&7
G
)*ile %contor D n&
E
scanf%(Klf(, Rx&7
if %x @ 6/./1 RR x D 1/./1&
continue7 :J valorile mici nu se iau in considerare J:
LLcontor7
suma L1 x7
G
666666666666666666666666666666
nstructiunea (s)itc*(
66666666666666666666666666666
(s)itc*( este o instructiune conditionala ce generalizeaza o instructiune (if6else(.
66666666666
Exemplu:
66666666666
s)itc* %val&
E
case 15
LLcontorCa7
brea37
case 25
case 35
LLcontorCb7
brea37
default5
LLcontorCc7
G
Corpul unei instructiuni (s)itc*( este un exemplu de instructiune compusa. .xpresia de control
dintre paranteze %ce urmeaza cuvantului s)itc*& trebuie sa fie de tip integral %vom reveni intr6un alt
capitol&. 8upa evaluarea lui val, controlul sare la etic*eta corespunzatoare valorii lui val. 8e obicei,
ultima instructiune dintr6un (case( este de obicei (brea3(. 8aca nu exista (brea3(, atunci se vor
executa si instructiunile din urmatoarele (case(6uri.
?tentie S 4miterea scrierii lui (brea3( este foarte frecventa SS
2oate apare cel mult un (default( %in general pe ultima pozitie&. Cuvintele rezervate (case( si
(default( pot apare numai in interiorul
unui (s)itc*(.
666666666666666666666666666666
4peratorul conditional
666666666666666666666666666666
4peratorul (?5( este mai putin obisnuit deoarece este ternar %cu trei argumente&. "orma generala este
expresie1 ? expresie2 5 expresie3
;ai intai, se evalueaza expresie1. 8aca aceasta este diferita de / %true&, atunci se evalueaza
expresie2, si aceasta va fi valoarea returnata de intreaga expresie conditionala. 8aca expresie1 este
/ %false&, atunci se evalueaza expresie3, si aceasta va fi valoarea intregii expresii conditionale.
666666666666
Exemplu: nstructiunea
66666666666
if %M D z&
x 1 M7
else
x 1 z7
este ec*ivalenta cu
x 1 %M D z& ? M 5 z7
4peratorul ?5 are aceeasi prioritate cu operatorul de asignare si se asociaza de la dreapta la stanga.
66666666666666666666666666666666666666666666666
.xercitii propuse spre implementare
66666666666666666666666666666666666666666666666
1. ,a se scrie un program care sa calculeze minimul a trei numere %folosind o instructiune (if6t*en(
si una (if( sau doua (if6t*en( %fara variabila suplimentara&&. Qeneralizare5 ,a se gaseasca primele
doua numere %cele mai mici& dintr6un vector de n elemente %cu numar minim de comparatii&.
2. Cititi n numere de la tastatura si afisati maximul lor. ncercati sa cititi un numar arbitrar de
numere %deci fara a citi acest n&.
3. "olosind structura for, scrieti un program care calculeaza urmatoarele formule logice %sub forma
unei tabele de adevar&5
b1 BB b3 BB b! si b1 RR b2 BB b4 RR b!
4. "ie functia lui Collatz5
E n:2 daca n este par
f%n& 1
E 3JnL1 daca n este impar
,a se scrie un program C care determina 3 natural minim astfel incat
%f o f o ... o f&%n&11.
de 3 ori
!. ,crieti un program C care calculeaza suma divizorilor naturali ai unui numar natural n. Un numar
este perfect daca este egal cu suma divizorilor proprii pozitivi %ex5 2+ 1 1 L 2 L 4 L ' L 14&. ,a se
genereze primele 3 numere perfecte %3 D ! S&.
$. 4peratia matematica min%x,M& se poate reprezenta ca o expresie conditionala5
%x D M& ? x 5 M
ntr6un mod similar, descrieti operatiile aritmetice
min%x, M, z& si max%x, M, z, t&
'. ,e stie ca un procedeu de intersc*imbare a valorii a doua variabile %a si b& se poate face folosind
o variabila auxiliara %se foloseste in metodele de sortare, arbori, sisteme de ecuatii, etc&5
aux 1 a 7
a 1 b 7
b 1 aux7
,a se arate ca in limba<ul C se poate face acest lucru in mod ec*ivalent fara utilizarea explicita a
unei variabile suplimentare. ?sadar intervertirea valorilor a si b se poate face si astfel5
a 1 b L a 6 %b 1 a&7
?ratati ca aceasta instructiune este ec*ivalenta cu5
aux 1 b L a 7
b 1 a 7
a 1 aux 6 a7 %sau a 1 aux 6 b7&
.c*ivalent, fara variabile suplimentare, se pot considera instructiunile5
a 1 a L b7
b 1 a 6 b7
a 1 a 6 b7
"unctii si programare structurata
4.1. ?pelul functiilor
4.2. nstructiunea (return(
4.3. 2rototipurile functiilor
4.4. 8escriere (top6do)n(
4.!. nvocare si apel prin valoare
4.$. 8eosebirea dintre (return( si (exit(
4.'. .xercitii propuse spre implementare

11111111
Capitolul 4
11111111
1111111111111111111111111
"unctii si programare structurata
1111111111111111111111111
2rogramarea structurata este o problema ce rezolva strategia si metodologia programarii si are
urmatoarele principii5
1. ,tructurile de control trebuie sa fie cat se poate de simple7
2. Constructia unui program trebuie sa fie descrisa top6do)n.
8escrierea top6do)n se refera la descompunerea problemei noastre in subprobleme. 8e obicei,
aceste subprobleme sunt usor de descris.
666666666666666666666
?pelul functiilor
666666666666666666666
Un program este compus din una sau mai multe functii, printre care si (main%&(. ntotdeauna
executia unui program incepe cu (main%&(. Cand o functie este apelata %sau invocata& atunci
controlul programului este pasat functiei apelate. 8upa ce aceasta isi termina executia, atunci se
paseaza inapoi controlul catre program.
Codul C care descrie ce face o functie se numeste (definitia functiei(. ?ceasta are urmatoarea
forma generala5
tip numeCfunctie %listaCparametri&
E
declaratii
instructiuni
G
2rimul rand se numeste (*eader6ul( %antetul& functiei, iar ceea ce este inclus intre acolade se
numeste corpul functiei. 8aca in antet
nu precizam parametri, atunci se va scrie (void( %cuvant rezervat pentru lista vida&. 8aca functia nu
intoarce nici o valoare, atunci se va scrie ca tip intors tot (void(. 9ipul intors de functie este cel
precizat in (return( %ce va fi indata explicat&. 2arametrii din antetul functiei sunt dati printr6o lista
cu argumente separate prin virgula. ?ceste argumente sunt date de tipul argumentului urmat de un
identificator ce apartine acelui tip. ,e mai spune ca acel identificator este (parametru formal(.
66666666666
.xemplu5
66666666666
#include Dstdio.*@
void tiparesteCmesa<%int 3&
E
int i7
printf%(ti urez5Fn(&7
for %i 1 /7 i D 37 LLi&
printf%( 4 zi buna S Fn(&7
G

main%&
E
int n7
printf%(8ati un numar natural mic5 (&7
scanf%(Kd(, Rn&7
tiparesteCmesa<%n&7
G
666666666666666666666666666666
nstructiunea (return(
666666666666666666666666666666
nstructiunea (return( este folosita pentru doua scopuri. Cand se executa o instructiune (return(,
controlul programului este pasat inapoi programului apelant. n plus, daca exista o expresie dupa
acest (return(, atunci se va returna valoarea acestei expresii. nstructiunea (return( poate avea
formele5
return7
sau
return expresie7
66666666666
.xemplu5 ;inimul a doi intregi.
66666666666
#include Dstdio.*@
int min%int x, int M&
E
if %x D M&
return x7
else
return M
G

main%&
E
int <, 3, m7

printf%(8ati doi intregi5 (&7
scanf%(KdKd(, R<, R3&7
m 1 min%<, 3&7
printf%(FnKd este minimul dintre Kd si Kd.Fn(, m, <, 3&7
G
666666666666666666666666666666
2rototipurile functiilor
666666666666666666666666666666
n C, apelul unei functii poate apare inaintea declararii ei. "unctia poate fi definita mai tarziu in
acelasi fisier, sau in alt fisier sau dintr6o biblioteca standard. n ?=, C, prototipul functiei
remediaza problema punand la dispozitie numarul si tipul argumentelor functiei. 2rototipul
specifica, de asemenea, si tipul returnat de functie. ,intaxa prototipului unei functii este5
tip numeCfunctie %listaCtipuriCparametri&7
n lista de parametri putem specifica c*iar si parametrul, dar asta este optional. 8aca functia nu are
parametri, atunci se foloseste (void(.
66666666666
.xemplu5 0eluam un exemplu precedent.
66666666666
#include Dstdio.*@
main%&
E
int n7
void tiparesteCmesa<%int&7

printf%(8ati un numar natural mic5 (&7
scanf%(Kd(, Rn&7
tiparesteCmesa<%n&7
G

void tiparesteCmesa<%3&
E
int i7

printf%(ti urez5Fn(&7
for %i 1 /7 i D 37 LLi&
printf%( 4 zi buna S Fn(&7
G
2rototipul unei functii poate fi plasat in corpul altei functii, sau de regula, se scriu la inceputul
programelor dupa directivele #include si #define.
6666666666666666666666666666
8escriere (top6do)n(
6666666666666666666666666666
2resupunem ca avem de citit cativa intregi si trebuie sa6i afisam in ordine pe coloane %in capatul de
sus al coloanelor trebuie sa scriem numele campului&, sa le afisam suma lor partiala, minimul si
maximul lor. 2entru scrierea unui program C ce face acest lucru, vom utiliza proiectarea
%descrierea& (top6do)n(.
?stfel, descompunem problema in urmatoarele subprobleme5
1. Un antet pentru problema data7
2. ,crierea campurilor7
3. Citirea si scrierea lor pe coloane.
9oti acesti trei pasi vor fi descrisi in cate o functie ce se apeleaza din (main%&(. 4btinem, un prim
cod5
#include Dstdio.*@

main%&
E
void tiparesteCantet%void&7
void scrieCcampurile%void&7
void citesteCscrieCcoloanele%void&7

tiparesteCantet%&7
scrieCcampurile%&7
citesteCscrieCcoloanele%&7
G

?ceasta reprezinta intr6un mod foarte simplu descrierea (top6do)n(. 8aca o problema este prea
grea, atunci o descompunem in subprobleme, si apoi le rezolvam pe acestea. Ieneficiul suplimentar
al acestei metode este claritatea sa.
void tiparesteCantet%void&
E
printf%(FnKsKsKsFn(,
(JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFn(,
(J Calculul sumelor, minimului si maximului JFn(,
(JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJFn(&7
G

"unctia ce foloseste la scrierea campurilor este la fel usor de scris5
void scrieCcampurile%void&
E
printf%(K!sK12sK12sK12sK12sFnFn(,
(=umar(, (?rticol(, (,uma(, (;inimul(, (;aximul(&7
G
Urmeaza apoi functia ce serveste la scrierea inregistrarilor referitoare la campurile discutate mai
sus5
void citesteCscrieCcoloanele%void&
E
int contor 1 /, articol, suma, minim, maxim7
int min%int, int&, max%int, int&7

if %scanf%(Kd(, Rarticol& 11 1&
E
LLcontor7
suma 1 minim 1 maxim 1 articol7
printf%(K!dK12dK12dK12dK12dFnFn(,
contor, articol, suma, minim, maxim&7
)*ile %scanf%(Kd(, Rarticol& 11 1&
E
LLcontor7
suma L1 articol7
minim 1 min%articol, minim&7
maxim 1 max%articol, maxim&7
printf%(K!dK12dK12dK12dK12dFnFn(,
contor, articol, suma, minim, maxim&7
G
G
else
printf%(=ici o data nu a fost citita.FnFn(&7
G
8aca datele se introduc de la tastatura, atunci tabelul se va afisa (intrerupt( de citirile ce au loc de la
tastatura. ?stfel, se prefera citirea dintr6un fisier extern. 2resupunem ca fisierul nostru executabil
%asociat fisierului sursa scris in C& se numeste (numere.exe( si am creat un fisier numit (fisier.int(
ce contine urmatoarele numere5
1- 23 6' 2- 611 1'
8and comanda
numere D fisier.int
vom obtine un tabel ce contine toate datele dorite.
6666666666666666666666666666666666666
nvocare si apel prin valoare
6666666666666666666666666666666666666
4 functie este invocata prin scrierea numelui sau impreuna cu lista sa de argumente intre paranteze.
8e obicei, numarul si tipul acestor argumente se (potriveste( cu parametrii din lista de parametri
prezenti in definitia functiei. 9oate argumentele sunt apelate prin valoare %(call6bM6value(&. ?sta
inseamna ca fiecare argument este evaluat si valoarea sa este folosita ca valoare pentru parametrul
formal corespunzator. 8e aceea, daca o variabila %argument& este folosita la transmiterea unei
valori, atunci valoarea ei nu se sc*imba.
66666666666
.xemplu5
66666666666
#include Dstdio.*@
main%&
E
int n13, suma, calculeazaCsuma%int&7

printf%(KdFn(, n&7 :J se va scrie 3 J:
suma 1 calculeazaCsuma%n&7
printf%(KdFn(, n&7 :J se va scrie 3 J:
printf%(KdFn(, suma&7 :J se va scrie $ J:
G

int calculeazaCsuma%int n& :J suma numerelor de la 1 la n J:
E
int suma 1 /7
for % 7 n @ /7 66n& :J n se sc*imba aici, dar nu si in main%& J:
sum L1 n7
printf%(KdFn(, n&7 :J se va scrie / J:
return suma7
G
C*iar daca n este trimis ca argument in functia (calculeazaCsuma%&( si valoarea lui n se modifica in
aceasta functie, valoarea sa din
mediul apelant ramane nesc*imbata. Vom vedea mai tarziu cum se poate simula apelul prin adresa
%(call6bM6reference(&.
6666666666666666666666666666666666666666666666
8eosebirea dintre (return( si (exit(
6666666666666666666666666666666666666666666666
.xista doua procedee de a returna o valoare.
return expresie si exit%expresie&
8aca se folosesc in (main%&(, atunci acestea sunt ec*ivalente, dar in orice alta functie efectul lor
este diferit %in ?=, C, functia (main%&( intoarce o valoare de tip int&. Un apel al lui exit%& in orice
alta functie va implica terminarea executiei programului si returnarea valorii catre mediul apelant
%sistemul de operare sau mediul de programare C&. Valoarea returnata se numeste stare de iesire
%(exit status(&. 2rin conventie, starea de iesire zero indica terminare cu succes, pe cand iesire cu un
numar diferit de zero indica o situatie anormala.
66666666666666666666666666666666666666666666666
.xercitii propuse spre implementare
66666666666666666666666666666666666666666666666
1. "olosind functiile (rand%&(, (min%,&( si (max%,&(, sa se genereze n numere naturale si sa se
afiseze minimul si maximul dintre acestea.
2. %Tocul cap6pa<ura, simulare ;onte6Carlo&
2resupunem ca dispunem de o moneda ideala %nemasluita&. 8oi <ucatori arunca cu moneda dupa
urmatoarele reguli5
1.a. ,e fac un numar total de n aruncari7
1.b. 2rimul <ucator arunca moneda si celalalt spune (cap( sau (pa<ura(7
1.c. 8aca acesta (g*iceste( ce va pica moneda, atunci se inverseaza <ucatorii %adica arunca al
doilea si primul incearca sa g*iceasca&7
1.d. Ha sfarsit, trebuie afisat scorul %si procentul de castig al fiecaruia&.
3. %Con<ectura lui Qoldbac*&
4rice numar par mai mare decat 2 se poate scrie ca suma a doua numere prime. ,crieti un
program C care verifica aceasta con<ectura pentru numere situate intre m si n. 8e exemplu, daca
m1'// si n111//, atunci afisati5
'// 1 1' L $+3
'/2 1 11 L $-1
'/4 1 3 L '/1
...
1/-+ 1 ! L 1/-3
11// 1 3 L 1/-'
Qeneralizare5 ,crieti toate combinatiile posibile de adunare a doua numere prime egal cu un numar
dat.
2rocesarea caracterelor
!.1. 9ipul de data (c*ar(
!.2. Utilizarea lui (getc*ar%&( si (putc*ar%&(
!.3. Iiblioteca DctMpe.*@
!.4. Un exemplu util5 =umararea cuvintelor
!.!. .xercitii propuse spre implementare


11111111
Capitolul !
11111111
111111111111111111
2rocesarea caracterelor
111111111111111111
666666666666666666666666666
9ipul de data (c*ar(
666666666666666666666666666
.ste unul dintre tipurile fundamentale din limba<ul C. Constantele si variabilele de acest tip sunt
folosite pentru reprezentarea caracterelor. "iecare caracter este memorat pe 1 bMte %octet&, care %in
general& este compus din + biti. Un octet compus din + biti poate pastra 2A+12!$ valori distincte.
Cand memoram un caracter intr6un octet, continutul acestuia poate fi gandit ca un caracter sau un
intreg mic %intre / si 2!!&. 8esi putem memora 2!$ valori distincte, doar o parte din ele sunt
tiparibile %litere mici, mari, cifre, semne de punctuatie, spatiu, tab, caractere speciale L, J, K&.
.xemple de caractere netiparibile5 ne)line, bell.
4 constanta caracter se scrie intre apostroafe, cum ar fi5 PaP, PbP. 4 declaratie obisnuita a unei
variabile de tip caracter este5
c*ar c7
Variabilele caracter se pot initializa astfel5
c*ar c1 1 P?P, c2 1 PJP7
Un caracter este pastrat in memorie pe un octet dupa o codificare specifica. ;ulte masini folosesc
codurile de caractere ?,C sau
.IC8C. =e vom referi numai la codul ?,C. ?stfel, vom preciza constanta caracter si valoarea
corespunzatoare a sa5
de la 2A!L2A4 pana la !', in ordine5 P/P, P1P, ..., P-P
de la 2A$L2A/ pana la -/, in ordine5 P?P, PIP, ..., PUP
de la 2A$L2A!L2A/ pana la 112, in ordine5 PaP, PbP, ..., PzP
8e exemplu, se observa ca pentru a obtine litere mici din cele mari, sc*imbam doar un bit. ?stfel,
caracterul P?P are codul $! care
inseamna numarul /1/////1 in baza 2, iar caracterul PaP are codul /11////1. ,e observa ca difera
doar bitul cu numarul 3.

66666666666
.xemple5
66666666666
n functiile (printf%&( si (scanf%&(, pentru formatul caracter se foloseste Kc.
printf%(Kc(, PaP&7 va tipari a
printf%(KcKcKc(, P?P, PIP, PCP&7 va tipari ?IC
printf%(Kd(, PaP&7 va tipari -'
printf%(Kc(, -'&7 va tipari a
?numite caractere netiparibile necesita (secvente escape( %F reprezinta caracterul escape&. n acest
sens, dam un tabel
=umele caracterului ;odul de scriere Valoarea intreaga
alert Fa '
bac3slas* FF -2
bac3space Fb +
carriage return Fr 13
g*ilimea F( 34
formfeed Ff 12
tab orizontal Ft -
ne)line Fn 1/
caracterul nul F/ /
apostrof FP 3-
tab vertical Fv 11

66666666666
.xemple5 Ce va fi afisat in cazul urmatoarelor instructiuni ?
66666666666
1. printf%(F(?ICF((&7
2. printf%(P?ICP(&7
Un alt mod de a scrie o constanta caracter este folosind una, doua sau trei cifre octale ca secvente
escape, cum ar fi PF//'P. ?cest
PF//'P este de fapt caracterul (alert( %sau clopotel&. .l mai poate fi scris PF/'P sau PF'P sau Fa.

6666666666666666666666666666666666666666666666666666
Utilizarea lui (getc*ar%&( si (putc*ar%&(
6666666666666666666666666666666666666666666666666666
?ceste functii sunt folosite pentru citirea si scrierea caracterelor si sunt definite in Dstdio.*@. ?stfel
pentru citirea unui caracter de
la tastatura se foloseste (getc*ar%&(, iar pentru scrierea unui caracter pe ecran (putc*ar%&(.
Iineinteles ca daca dorim sa afisam un sir de caractere mai mare, este mai elegant cu functia
(printf%&(.

66666666666
.xemplu5
66666666666
Urmatorul program citeste un caracter din intrare %tastatura& si il atribuie unei varibile de tip c*ar,
apoi il afiseaza pe ecran.
#include Dstdio.*@
main%&
E
c*ar c7

)*ile %1&
E
c1getc*ar%&7
putc*ar%c&7
G
G

,ingurul mod de a opri acest program este sa apasam C90HAC. 2utem reface acest program
folosind constanta .4".
#include Dstdio.*@
main%&
E
int c7

)*ile %%c 1 getc*ar%&& S1 .4"&
E
putc*ar%c&7
G
G

66666666666666
Comentarii5
66666666666666
1. n biblioteca Dstdio.*@, exista o linie in care se declara
#define .4" %61&
8enumirea lui .4" provine de la (end6of6file(.
2. Variabila c trebuie sa fie declarata de tip int si nu de tip c*ar. ?m vazut ca sfarsitul unui fisier
este codificat cu 61, si nu cu un
caracter.
3. ,ubexpresia
c1getc*ar%&
citeste o valoare de la tastatura si o asigneaza variabilei c.

66666666666666666666666666
Iiblioteca DctMpe.*@
66666666666666666666666666
,istemul C pune la dispozitie fisierul *eader DctMpe.*@ care contine o multime de macro6uri
%definitii& folosite pentru testarea
caracterelor si o multime de prototipuri de functii ce sunt folosite pentru conversia caracterelor.
n tabelul de mai <os prezentam o lista de macro6uri folosite la testarea caracterelor. ?ceste macro6
uri iau ca argument o variabila
de tip int si returneaza o valoare de tip int %zero1false, diferit de zero1true&.
66666666666666666666666666666666666666666666666666666666666666666666666
B ;acro B ,e returneaza true %diferit de zero& daca B
66666666666666666666666666666666666666666666666666666666666666666666666
isalp*a%c& c este litera
isupper%c& c este litera ma<uscula
islo)er%c& c este litera mica
isdigit%c& c este cifra
isalnum%c& c este litera sau cifra
isxdigit%c& c este cifra *exazecimala
isspace%c& c este caracter spatiu
ispunct%c& c este semn de punctuatie
isprint%c& c este caracter tiparibil
isgrap*%c& c este tiparibil, dar diferit de spatiu
iscntrl%c& c este caracter de control
isascii%c& c este cod ?,C
6666666666666666666666666666666666666666666666666666666666666666666
n tabelul urmator, vom scrie functiile (toupper%&( si (tolo)er%&(, care sunt din biblioteca standard
si macro6ul (toascii%&(. ;acro6ul
si prototipurile pentru cele doua functii sunt in DctMpe.*@. ?cestea au ca argument o variabila de tip
int si returneaza tipul int.
toupper%c& sc*imba c din litera mica in ma<uscula
tolo)er%c& sc*imba c din ma<uscula in litera mica
toascii%c& sc*imba c cu codul ?,C

6666666666666666
Un exemplu %util&5 =umararea cuvintelor
6666666666666666
Vrem sa numaram cate cuvinte sunt introduse de la tastatura. .le sunt separate prin spatiu. 2entru
scrierea programului vom utiliza tot strategia (top6do)n(.

#include Dstdio.*@
#include DctMpe.*@
main%&
E
int numarCcuvinte 1 /7
int gasesteCurmatorulCcuvant%void&7

)*ile %gasesteCurmatorulCcuvant%& 11 1&
LL numarCcuvinte7
printf%(=umarul de cuvinte 1 KdFnFn(, numarCcuvinte&7
G

int gasesteCurmatorulCcuvant%void&
E
int c7

)*ile %isspace%c 1 getc*ar%&&&
7 :J sarim peste spatii J:
if %c S1 .4"&
E
)*ile %%c 1 getc*ar%&& S1 .4" RR Sisspace%c&&
7 :J sarim peste orice diferit de .4" si spatii J:
if %c S1 .4"& return 17
else return /7
G
return /7
G

66666666666666666666666666666666666666666666666
.xercitii propuse spre implementare
66666666666666666666666666666666666666666666666
1. "olosind functiile (getc*ar%&( si (putc*ar%&(, sa se scrie un program C care transforma literele
mici in litere mari. ncercati si o varianta de program care foloseste functiile (islo)er%&( si
(toupper%&(.
2. Utilizand functiile (getc*ar%&( si (putc*ar%&( creati un program C care sa copie un fisier in alt
fisier %comanda voastra proprie de
copiere&. Utilizati redirectarea S 8e asemeni, precizati si cazul cand dorim sa copiem un fisier la
sfarsitul unui fisier existent.
3. ,crieti in C un analizor lexical care sa recunoasca cat mai multi atomi lexicali din C. 8e
exemplu, cuvintele rezervate %)*ile, do, for, ...&, identificatori, operatori %relationali, logici,
artimetici, ...& si eventual alte structuri. ?poi, tipariti acelasi fisier de intrare cu exceptia spatiilor
multiple si a comentariilor.
4. ,crieti un program C care citeste caractere de la tastatura si le scrie la ecran. ,crieti toate
vocalele cu litere ma<uscule si consoanele cu litere mici. ?poi, scrieti un program C care citeste
caractere de la tastatura si sterge vocalele din ele %afisand doar consoanele&. %?cest mod de scriere
era folosit in scrisul *ieroglific al Qreciei ?ntice&.
!. %(2rettM printing(&
,crieti un program C care are la intrare un fisier sursa C si il transforma intr6un program C scris
frumos %eventual in stilul Iell Haboratoires&.
9ipuri fundamentale de date
$.1. 8eclaratii si expresii
$.2. 9ipuri fundamentale de date
$.3. Caractere si tipul (c*ar(
$.4. 9ipul de date (int(
$.!. 9ipurile integrale (s*ort(, (long( si (unsigned(
$.$. 9ipuri reale
$.'. 4peratorul (sizeof%&(
$.+. "unctii matematice
$.-. Conversii implicite si explicite
$.1/. Conversia la intreg
$.11. Conversiile aritmetice uzuale
$.12. Conversii explicite
$.13. .rori de programare frecvente
$.14. .xercitii propuse spre implementare


11111111
Capitolul $
11111111
111111111111111111111
9ipuri fundamentale de date
111111111111111111111

666666666666666666666666666
8eclaratii si expresii
666666666666666666666666666
Variabilele si constantele sunt obiecte cu care se lucreaza intr6un program. n C, toate variabilele
trebuie declarate inainte de a fi
folosite. 8eclaratiile au doua scopuri5
1. spun compilatorului cat spatiu de memorie trebuie rezervat pentru memorarea acelor variabile7
2. permit compilatorului sa instruiasca masina pentru a face operatiile specifice corect.
8e exemplu, in expresia a L b, operatorul L este aplicat pentru doua variabile. ;asina executa in
mod diferit adunarea pentru variabile de tip (int( si pentru variabile de tip (float(. Iineinteles,
pentru programator aceste conventii sunt transparente %se mai spune ca (L( este operator de
supraincarcare&. .xpresiile sunt combinatii %cu inteles& de constante, variabile si apeluri de functii.
;a<oritatea expresiilor %cum ar fi, de exemplu, variabilele& au si valoare si tip. n multe situatii,
valoarea returnata depinde in principal de tipul expresiei.

66666666666666666666666666666666666666
9ipuri fundamentale de date
66666666666666666666666666666666666666
?vem urmatoarele tipuri fundamentale de date %scriere intreaga 6 lunga&5
c*ar signed c*ar unsigned c*ar
signed s*ort int signed int signed long int
unsigned s*ort int unsigned int unsigned long int
float double long double
9oate acestea sunt cuvinte rezervate, deci nu se pot folosi ca nume de variabile. ?lte tipuri de date,
cum ar fi vectorii si pointerii,
sunt derivate din tipurile fundamentale.
8e obicei, cuvantul rezervat (signed( nu se mai scrie. 8e exemplu, (signed int( este ec*ivalent cu
(int(. 8e asemenea, cuvintele (s*ort int(, (long int( si (unsigned int( pot fi prescurtate, de obicei, ca
(s*ort(, (long( si (unsigned(. Cu aceste conventii, tabelul de mai sus se mai poate scrie5
c*ar signed c*ar unsigned c*ar
s*ort int long
unsigned s*ort unsigned unsigned long
float double long double
9ipurile fundamentale se pot grupa dupa functionalitate5
1. tipurile integrale sunt cele care sunt folosite pentru reprezentarea valorilor intregi7
2. tipurile reale sunt cele care sunt folosite pentru reprezentarea valorilor reale7
3. tipurile aritmetice sunt tipuri integrale sau reale.
?cestea sunt5
9ipuri integrale5
c*ar signed c*ar unsigned c*ar
s*ort int long
unsigned s*ort unsigned unsigned long
9ipuri reale5
float double long double

666666666666666666666666666666666
Caractere si tipul (c*ar(
666666666666666666666666666666666
n C, variabilele de orice tip integral pot fi folosite pentru reprezentarea caracterelor. n particular,
variabilele de tip (c*ar( si (int( se folosesc pentru acest scop. ?m vazut in capitolul precedent ca
atunci cand dorim sa comparam o variabila cu .4", atunci trebuie sa declaram acea variabila de tip
(int(, si nu de tip (c*ar(. Constante cum ar fi PaP, PLP pe care le gandim ca fiind caractere
sunt de tip (int(, si nu de tip (c*ar(. 0etineti ca nu exista constante de tip (c*ar( SSS
0eamintim ca toate caracterele sunt tratate ca (intregi mici(, si reciproc, intregii mici sunt tratati ca
niste caractere. n particular, orice expresie integrala poate fi afisata in format intreg sau caracter.

66666666666
.xemplu5 2resupunem ca avem o (bucata( de cod C5
66666666666
c*ar c 1 PaP7 :J PaP are codul ?,C -' J:
int i 1 $!7 :J $! este codul ?,C pentru P?P J:

printf%(Kc(, c L 1&7 :J este afisat b J:
printf%(Kd(, c L 2&7 :J este afisat -- J:
printf%(Kc(, i L 3&7 :J este afisat 8 J:
n C, fiecare caracter este memorat pe un octet de memorie. 2e aproape toate masinile, un octet este
compus din + biti. "ie declaratia
c*ar c 1 PaP7
2utem gandi ca (c( este memorat pe un octet astfel
666666666666666666666666666666
B / B 1 B 1 B / B / B / B / B 1 B
666666666666666666666666666666
' $ ! 4 3 2 1 /
"iecare celula reprezinta un bit si fiecare bit este numerotat %incepand cu cel mai putin
semnificativ&. Iitii care formeaza un octet sunt fie (on(, fie (off(, aceste stari fiind reprezentate prin
1 si / respectiv. ?cesta ne conduce sa gandim fiecare octet din memorie ca un sir de + cifre binare
%se mai numesc siruri de biti&.
?stfel variabila (c( poate fi gandita ca sirul de biti
/11////1
;ai general, fiecare cuvant masina poate fi gandit ca un sir de cifre binare grupate in octeti.
Un sir de cifre binare poate fi deci gandit ca un numar binar %adica in baza 2&. "ara a intra in detalii
matematice %teorema bazei de numeratie& vom face doar un exemplu5

66666666666
.xemplu5
66666666666
Valoarea lui (c( este numarul /11////1 %in baza 2&
1 x 2A$ L 1 x 2A! L / x 2A4 L / x 2A3 L / x 2A2 L / x 2A1 L 1 x 2A/
care inseamna $4 L 32 L 1 1 -' in notatia zecimala %in baza 1/&.
?=, C pune la dispozitie trei tipuri referitoare la caractere5
c*ar signed c*ar unsigned c*ar
8e obicei, tipul (c*ar( este ec*ivalent cu (signed c*ar( sau (unsigned c*ar(, depinzand de
compilator. "iecare din aceste trei tipuri se memoreaza pe un octet %deci poate (tine( 2!$ valori
distincte&. 2entru (signed c*ar(, valorile sunt intre 612+ si 12', iar pentru (unsigned c*ar( intre / si
2!!.

6666666666666666666666666
9ipul de date (int(
6666666666666666666666666
9ipul de date (int( este cel mai folosit tip din limba<ul C. ?cest tip, impreuna cu alte tipuri
integrale %cum ar fi5 (c*ar(, (s*ort( si (long(& este desemnat pentru lucrul cu valori intregi
reprezentabile pe o masina.
n matematica, numerele naturale sunt /, 1, 2, 3, ..., care impreuna cu cele negative
%corespunzatoare& formeaza numerele intregi. 2e o masina, se pot reprezenta %folosind un tip
integral& numai o submultime finita a acestor numere.
8e obicei, un cuvant se memoreaza pe un cuvant masina. ?numite calculatoare folosesc cuvante de
2 octeti %11$ biti&, altele 4 octeti %132 biti&.

66666666666
.xemple5
66666666666
1. ;asini ce folosesc cuvinte memorate pe 2 octeti5 2C
2. ;asini ce folosesc cuvinte memorate pe 4 octeti5 ?pollo, [e)lett62ac3ard, =ext, ,ilicon
Qrap*ics, ,un, etc.

2resupunem ca lucram pe un calculator care lucreaza pe 4 octeti. ?ceasta implica ca un cuvant are
32 biti, deci poate (tine( 2AE32G
valori distincte. Tumatate sunt folosite pentru reprezentarea numerelor negative si cealalta <umatate
pentru pozitive5
6 2AE31G, 62AE31GL1,..., 62, 61, /, 1, 2, ..., 2AE31G61
8aca lucram pe un calculator unde memorarea unui cuvant se face pe 2 octeti, atunci putem
memora 2AE1$G valori distincte.
Valoarea cea mai mare, a tipului (int( este data de constanta ;?>=9. .vident cea mai mica
valoare va fi 6;?>=961.
8aca se incearca, de exemplu, adunarea a doua numere %si se depaseste aceasta valoare&, atunci se
va primi un mesa< (integer overflo)(.

6666666666666666666666666666666666666666666666666666666666666
9ipurile integrale (s*ort(, (long( si (unsigned(
6666666666666666666666666666666666666666666666666666666666666
8e obicei, tipul (s*ort( se memoreaza pe doi octeti si tipul (long( pe patru octeti. ?stfel, pe
masinile in care cuvintele au patru octeti, lungimea tipului (int( este aceeasi cu lungimea tipului
(long(, iar pe masinile in care cuvintele au doi octeti, lungimea tipului (int( este egala cu lungimea
tipului (s*ort(. Constantele predefinite ;?>,[409 si ;?>H4=Q %in unele implementari
H4=QC;?>& caracterizeaza lungimea acestor tipuri. 8e obicei, ;?>,[40912AE1!G si
;?>H4=Q12AE31G. ?stfel, daca (s( este o variabila de tip (s*ort(, atunci
6 ;?>,[409 D1 s D1 ;?>,[40961
8aca (l( este o variabila de tip (long(, atunci
6 ;?>H4=Q D1 s D1 ;?>H4=Q61
n ceea ce priveste tipul (unsigned(, acesta este memorat pe acelasi numar de octeti ca si tipul (int(.
8aca (u( este o variabila de tip
(unsigned(, atunci
/ D1 u D1 2J;?>=961

6666666666666666
9ipuri reale
6666666666666666
?=, C contine trei tipuri reale5 (float(, (double( si (long double(. Variabilele de acest tip vor
putea tine valori reale, cum ar fi5
/.//1 2./ 3.141!-
?ceasta notatie se numeste notatie zecimala, deoarece contine punctul zecimal. ;ai exista si
notatia exponentiala. 8e exemplu,
1.234!$'e! corespunde cu 1.234!$' x 1/A!11234!$.'
2e ma<oritatea masinilor, tipul (float( se memoreaza pe 4 octeti, iar tipul (double( pe + octeti. ?sta
inseamna ca o variabila de tipul
(float( poate avea $ zecimale, iar o variabila de tipul (double( poate avea 1! zecimale. ?stfel, o
variabila de tipul (float( are forma
/,dC1 dC2 dC3 dC4 dC! dC$ x 1/AEnG
unde 63+ D1 n D1 3+.
?semanator, o variabila de tipul (double( are forma
/,dC1 dC2 ... dCE1!G x 1/AEnG
unde 63/+ D1 n D1 3/+.
?stfel, instructiunea
x 1 123.4!1234!1234!1234!7 :J 2/ cifre semnificative J:
va implica atribuirea lui x a valorii
/.1234!1234!1234! x 1/A3 %1! cifre semnificative&
n ?=, C, pentru varibilele de tip (long double( se aloca mai multa memorie. nsa sunt
compilatoare care trateaza acest exact tip exact ca si (double(.

6666666666666666666666666666
4peratorul (sizeof%&(
6666666666666666666666666666
C pune la dispozitie operatorul (sizeof%&( pentru determinarea numarului de octeti necesari
memorarii unui obiect. ?cesta are aceeasi prioritate si asociativitate ca si ceilalti operatori unari. 4
expresie de forma
sizeof%obiect&
returneaza un intreg car reprezinta numarul de octeti necesari pentru memorarea obiectului in
memorie. Un obiect poate fi un tip, cum ar fi (int( sau (float(, sau poate fi o expresie, cum ar fi a L
b, sau poate fi un sir sau o structura.

66666666666
.xemplu5 Calculul numarului de octeti pentru cateva tipuri
66666666666
#include Dstdio.*@
main%&
E
printf%(Hungimea catorva tipuri fundamentale.FnFn(&7
printf%( c*ar5K3d octeti Fn(, sizeof%c*ar&&7
printf%( s*ort5K3d octeti Fn(, sizeof%s*ort&&7
printf%( int5K3d octeti Fn(, sizeof%int&&7
printf%( long5K3d octeti Fn(, sizeof%long&&7
printf%( unsigned5K3d octeti Fn(, sizeof%unsigned&&7
printf%( float5K3d octeti Fn(, sizeof%float&&7
printf%( double5K3d octeti Fn(, sizeof%double&&7
printf%(long double5K3d octeti Fn(, sizeof%long double&&7
G
8in moment ce limba<ul C este flexibil in ceea ce priveste necesarul de memorie pentru tipurile
fundamentale, situatiile pot sa difere de la o masina la alta. 9otusi, aceasta garanteaza ca5
sizeof%c*ar& 1 1
sizeof%s*ort& D1 sizeof%int& D1 sizeof%long&
sizeof%signed& D1 sizeof%unsigned& D1 sizeof%int&
sizeof%float& D1 sizeof%double& D1 sizeof%long double&
(sizeof%&( nu este o functie %c*iar daca contine paranteze atunci cand ne referim la tipuri&, ci este un
operator. 8e exemplu5
sizeof%a L b L '.'& este ec*ivalent cu sizeof a L b L '.'

6666666666666666666666666
"unctii matematice
6666666666666666666666666
=u exista functii matematice implicite %in compilatorul C&, ci acestea sunt descrise in biblioteci. 8e
exemplu, functiile
sZrt%& po)%& exp%& log%& sin%& cos%& tan%&
sunt definite in biblioteca Dmat*.*@. 9oate aceste functii, cu exceptia lui (po)er%&( au un argument
de tip (double( si returneaza o
valoare de tip (double(. "unctia (po)er%&( are doua argumente de tip (double( si returneaza o
valoare de tip (double(.

666666666666666666666666666666666666666
Conversii implicite si explicite
666666666666666666666666666666666666666
4 expresie aritmetica, cum ar fi (x L M(, are si valoare si tip. 8e exemplu, daca (x( si (M( au tipul
(int(, atunci expresia (x L M( are
tipul (int(. 8ar, daca (x( si (M( au ambele tipul (s*ort(, atunci (x L M( este de tip (int(, si nu
(s*ort(. ?ceasta se intampla deoarece
in orice expresie, (s*ort( se converteste la (int(.

6666666666666666666666666
Conversia la intreg
666666666666666666666666
Un (c*ar( sau (s*ort(, ori (signed( sau (unsigned(, ori un tip enumerare %vom reveni& poate fi
folosit in orice expresie unde poate fi folosit (int( sau (unsigned int(. 8aca toate valorile tipului
original pot fi reprezentate de un (int(, atunci valoarea acesteia se va converti la (int(7 altfel se va
converti la (unsigned int(. ?ceasta se numeste (conversie la intreg(.
66666666666
.xemplu5
66666666666
c*ar c 1 P?P7
printf%(KcFn(, c&7
Variabila (c( apare ca argument al functiei (printf%&(. Cu toate acestea, deoarece are loc conversia
la intreg, tipul expresiei (c( este (int(, si nu (c*ar(.

66666666666666666666666666666666666666
Conversiile aritmetice uzuale
66666666666666666666666666666666666666
Conversiile aritmetice pot apare cand sunt evaluati operanzii unui operator binar.
666666666666
.xemplu5
666666666666
2resupunem ca (i( este (int( si (f( este un (float(. n expresia (i L f(, operandul (i( se converteste
la (float( si deci expresia (i L f(
va intoarce tipul (float(.
?ceste reguli se numesc (conversii aritmetice uzuale(. ata urmatorul (algoritm(5
daca un operand este de tip (long double( atunci
si celalalt operand va fi convertit la tipul (long double(
altfel
daca un operand este de tip (double( atunci
si celalalt operand va fi convertit la tipul (double(
altfel
daca un operand este de tip (float( atunci
si celalalt operand va fi convertit la tipul (float(
altfel
:JJJJJ au loc conversiile la intreg JJJJJ:
daca un operand este de tip (unsigned long( atunci
si celalalt operand va fi convertit la tipul (unsigned long(
altfel
daca un operand are tipul (long( si celalalt (unsigned( atunci
6 daca un (long( poate reprezenta toate valorile (unsigned( atunci
operandul de tip (unsigned( se va converti la (long(
6 daca un (long( nu poate reprezenta toate valorile (unsigned( atunci
ambii operanzi se vor converti la (unsigned long(
altfel
daca un operand are tipul (long( atunci
celalalt operand se converteste la (long(
altfel
daca un operator are tipul (unsigned( atunci
celalalt operand va fi convertit la (unsigned(
altfel
ambii operanzi vor avea tipul (int(

66666666666
.xemplu5 2resupunem ca avem declaratiile5
66666666666
c*ar c7
s*ort s7
int i7
unsigned u7
unsigned long ul7
float f7
double d7
long double ld7
?tunci avem urmatoarele valori pentru tipurile expresiilor de mai <os5
66666666666666666666666666666666666666666666666666666666666666666666666
B .xpresie 9ip B .xpresie 9ip B
66666666666666666666666666666666666666666666666666666666666666666666666
B c 6 s : i int u J ' 6 i unsigned B
B u J 2./ 6 i double f J ' 6 i float B
B c L 3 int ' J s J ul unsigned long B
B c L !./ double ld L c long double B
B d L s double u 6 ul unsigned long B
B 2 J i : l long u 6 l dependent de sistem B
66666666666666666666666666666666666666666666666666666666666666666666666

666666666666666666666666
Conversii explicite
666666666666666666666666
8aca (i( este de tip (int(, atunci
%double& i
va converti valoarea lui (i( astfel incat expresia sa aiba tipul (double(. Variabila (i( ramane
nesc*imbata. Conversiile se pot aplica
si expresiilor.
66666666666
.xemple5
66666666666
%long& %P?P L 1./&
x 1 %float& %%int& M L 1&
%double& %x 1 ''&
4peratorul de conversie de tip %cast& este un operator unar care are aceeasi prioritate si
asociativitate %de la dreapta la stanga& ca
alti operatori unari.

666666666666
.xemplu5
666666666666
.xpresia
%float& i L 3 este ec*ivalenta cu %%float& i& L 3
pentru ca operatorul (cast( are prioritate mai mare decat (L(.

666666666666666666666666666666666666666
.rori de programare frecvente
666666666666666666666666666666666666666
2resupunem ca suntem pe o masina care lucreaza folosind cuvinte memorate pe doi octeti.
Consideram urmatorul exemplu5
66666666666
.xemplu5
66666666666
int a 1 1, b 1 1''$, c 1 32///7
printf%(KdFn(, a L b L c&7 :J eroare5 va fi afisat 631'!- J:
Un mod de a repara aceasta greseala este inlocuirea instructiunii (printf%&( cu5
printf%(KdFn(, %long& a L b L c&7 :J va fi afisat 33''' J:

66666666666666666666666666666666666666666666666
.xercitii propuse spre implementare
66666666666666666666666666666666666666666666666
1. 2resupunem ca depunem o suma %depozit la termen& intr6o banca care ofera o dobanda de 3+ K
%de exemplu& pe an. ,a se calculeze suma finala dupa un anumit numar de ani %se va tine cont de
(dobanda la dobanda(&.
2. ,crieti o functie C utilizator care sa simuleze functia (po)er%m, n&( pentru m intreg si n natural.
Cate inmultiri are functia ?
3. ,a se verifice care din urmatoarele numere este mai mare5
piAe sau eAEpiG
unde (pi(13.141!-2$!3!+-'-324 si (e(12.'1+2+1+2+4!-/4!24.
4. ,a se scrie un program C care aproximeaza (pi( si (e( cu un anumit numar de zecimale.
dei5 2entru calculul lui (e(, puteti folosi convergenta sirului
1LFsum 1:nS 6@ e
2entru calculul lui (pi(, puteti folosi convergenta sirului
Fsum 1:3A2 6@ piA2:$
9ipurile enumerare, (tMpedef(, si operatori pentru biti
'.1. 9ipurile enumerare
'.2. "olosirea lui (tMpedef(
'.3. .xpresii si operatori pe biti
'.4. Complement pe bit
'.!. Complement fata de doi
'.$. 4peratori logici binari pe biti
'.'. 4peratori de deplasare stanga si dreapta
'.+. ;asti
'.-. Un program de impac*etare si despac*etare a cuvintelor
'.1/. Hitere mari 6@ litere mici
'.11. 0ecapitulare
'.12. .xercitii propuse spre implementare



11111111
Capitolul '

11111111
11111111111111111111111111111111111111111
9ipurile enumerare, (tMpedef(, si operatori pentru biti
11111111111111111111111111111111111111111

66666666666666666666666666
9ipurile enumerare
6666666666666666666666666

2entru declararea tipurilor enumerare se foloseste cuvantul rezervat (enum(. ?cesta va implica
denumirea multimii, enumerarea elementelor %numite enumeratori&, ca elemente ale multimii.

66666666666
.xemplu5
66666666666
enum zile Eluni, marti, miercuri, <oi, vineri, sambata, duminicaG7
?ceasta declaratie creeaza tipul utilizator (enum zile(. Cuvantul rezervat (enum( este urmat de
identificatorul (zile(. .numeratorii
sunt identificatorii luni, marti, ... . ?cestea sunt constante de tip (int(. 2rin conventie, primul este /,
si apoi restul sunt incrementati. 8eclararea variabilelor de tip (enum zile( se face astfel5
enum zile zi1, zi27
Variabilele (zi1( si (zi2( pot lua ca valori elemente ale acestui tip. 8e exemplu,
zi1 1 miercuri7
va asigna variabilei (zi1( valoarea miercuri. nstructiunea
if %zi1 11 zi2&
E
...
G
va testa daca valoarea variabilei (zi1( este egala cu valoarea variabilei (zi2(.
.numeratorii pot fi initializati. 8e asemeni, putem declara variabilele in timpul definirii tipului
(enum(.

66666666666
.xemplu5
66666666666
enum carti Etrefla 1 1, caro, frunza, inimaG a, b, c7
8in moment ce (trefla( este initializata cu 1, rezulta ca (caro(, (frunza( si (inima( sunt initializate
cu 2, 3, respectiv 4
.
66666666666
.xemplu5
66666666666
enum fructe Emere 1 ', pere, portocale 1 3, lamaiG nrCfrct7
.ste clar ca (pere( va fi initializat cu +, iar (lamai( cu 4.
=umele tipului enumerare poate lipsi, insa atunci nu mai putem declara alte variabile de acel tip.

66666666666
.xemplu5
66666666666
enum Eplop, molid, bradG copaci7
,ingura variabila de tip (enum Eplop, molid, bradG( este copaci %nu se mai poate declara alta&.

66666666666666666666666666666
"olosirea lui (tMpedef(
66666666666666666666666666666
C pune la dispozitie facilitatea (tMpedef( pentru redenumirea tipurilor de<a existente.
66666666666
.xemplu5 tMpedef int culoare7
66666666666 culoare rosu, verde, albastru7
?cesta defineste tipul (culoare( ca fiind un sinonim al lui (int(. ?poi declaram trei variabile de
tipul (culoare(.

66666666666
.xemplu5
66666666666
Vom ilustra folosirea lui (tMpedef( pentru un tip enumerare %creand o functie ce returneaza ziua
urmatoare&.

enum zile Eduminica, luni, marti, miercuri, <oi, vineri, sambataG7
tMpedef enum zile zi7

zi gasesteCziuaCurmatoare%zi z&
E
zi ziuaCurmatoare7

s)itc*%z&
E
case duminica5
ziuaCurmatoare 1 luni7
brea37
case luni5
ziuaCurmatoare 1 marti7
brea37
...
case sambata5
ziuaCurmatoare 1 duminica7
brea37
G
return ziuaCurmatoare7
G

4 alta versiune %mai succinta& folosind (cast( este5

enum zile Eduminica, luni, marti, miercuri, <oi, vineri, sambataG7
tMpedef enum zile zi7

zi gasesteCurmatoareaCzi%zi z&
E
return %%zi&%%%int& z L 1& K '&&7
G

66666666666666666666666666666666666
.xpresii si operatori pe biti
66666666666666666666666666666666666
4peratorii pe biti lucreaza cu expresii integrale reprezentate ca siruri de cifre binare. ?cesti
operatori sunt dependenti de sistem.
4peratorii pe biti sunt5
4peratori logici
66666666666666666666
1. Complement pe bit %unar&5 X
2. ,i pe bit 5 R
3. ,au exclusiv pe bit 5 A
4. ,au inclusiv pe bit 5 B
4peratori de deplasare
6666666666666666666666666666
1. 8eplasare stanga 5 DD
2. 8eplasare dreapta 5 @@
Ca si ceilalti operatori, operatorii pe biti au reguli de precedenta si asociativitate care determina
precis cum se evalueaza expresiile ce contin astfel de operatori. 4peratorul X este unar, restul
operatorilor sunt binari si lucreaza cu tipuri integrale.

6666666666666666666666666
Complement pe bit
6666666666666666666666666
4peratorul X se numeste operator de complement %sau operator de complement pe bit&. ?cesta
inverseaza reprezentarea sirului pe biti, adica / devine 1 si 1 devine /.
66666666666
.xemplu5 "ie declaratia
66666666666
int a 1 !1'17
0eprezentarea binara a lui a este5
///1/1// //11//11
.xpresia Xa este5
111/1/11 11//11//
?ceasta are valoarea intreaga
6 !1'2

6666666666666666666666666666666
Complement fata de doi
6666666666666666666666666666666
0eprezentarea complementului fata de doi a unui numar natural este un sir de biti obtinut prin
complementarierea scrierii lui n in baza 2. Considerand complementul pe biti al lui n la care
adunam 1, obtinem reprezentarea complementului fata de doi a lui 6n.
4 masina care utilizeaza reprezentarea complementului fata de doi ca reprezentare binara in
memorie pentru valori integrale se numeste masina complement fata de doi. 0eprezentarile
complement fata de doi ale lui / si 61 sunt speciale. ?stfel valoarea / are toti bitii (off(, pe cand
valoarea 61 are toti bitii (on(. =umerele negative sunt caracterizate prin aceea ca au bitul cel mai
semnificativ 1. 2e masinile care utilizeaza complementul fata de doi, *ard6ul permite implementarea
scaderii ca o adunare si un complement pe biti. 4peratia a 6 b este aceeasi cu a L %6b&, unde 6b se
obtine considerand complementul pe biti al lui b la care adunam 1.

666666666666666666666666666666666666666
4peratori logici binari pe biti
66666666666666666666666666666666666666
Cei trei operatori R %si&, A %sau exclusiv& si B %sau inclusiv& sunt binari si au operanzi integrali.
4peranzii sunt operati bit cu bit. 9abelul de mai <os contine semantica lor5
a b a R b a A b a B b
66666666666666666666666666666666666666666666
/ / / / /
1 / / 1 1
/ 1 / 1 1
1 1 1 / 1

66666666666
.xemplu5 2resupunem ca avem declaratiile si initializarile
66666666666
int a 1 3333, b 1 ''''7
.xpresie 0eprezentare Valoare
66666666666666666666666666666666666666666666666666666666666
a ////11/1 /////1/1 3333
b ///1111/ /11////1 ''''
a R b ////11// ///////1 3/'3
a A b ///1//11 /11//1// 4-$4
a B b ///11111 /11//1/1 +/3'
X%a B b& 111///// 1//11/1/ 6+/3+
%Xa R Xb& 111///// 1//11/1/ 6+/3+
6666666666666666666666666666666666666666666666666666666666

6666666666666666666666666666666666666666666666666666
4peratori de deplasare stanga si dreapta
6666666666666666666666666666666666666666666666666666
Cei doi operanzi ai unui operator de deplasare trebuie sa fie expresii integrale. 9ipul returnat de
expresie este dat de operandul
din stanga. 4 expresie de forma
expresie1 DD expresie2
implica reprezentarea pe bit a lui (expresie1( sa fie deplasata catre stanga cu un numar de pozitii
specificat de (expresie2(. n capatul din dreapta, vor fi adaugate /6uri.

66666666666
.xemplu5 c*ar c 1 PUP7
66666666666
666666666666666666666666666666666666666666666666666666666666666666666666
.xpresie 0eprezentare ?ctiune
666666666666666666666666666666666666666666666666666666666666666666666666
c /1/11/1/ nedeplasat
c DD 1 1/11/1// deplasare la stanga cu 1
c DD 4 1/1///// deplasare la stanga cu 4
c DD 1! //////// deplasare la stanga cu 1!
666666666666666666666666666666666666666666666666666666666666666666666666
C*iar daca valoarea lui (c( se memoreaza pe un octet, intr6o expresie aceasta ia tipul (int(. 8eci
valoarea expresiilor (c DD 1(, (c DD 4( si (c DD 1!( se memoreaza pe doi octeti.
4peratorul de deplasare la dreapta (@@( nu este c*iar simetric cu (DD(. 2entru expresiile integrale
fara semn, din stanga se va deplasa /, iar pentru cele cu semn 1.

66666666666
.xemplu5
66666666666
2resupunem ca avem declaratiile5
int a 1 1 DD 1!7
unsigned b 1 1 DD 1!7
666666666666666666666666666666666666666666666666666666666666666666666666666
.xpresie 0eprezentare ?ctiune
666666666666666666666666666666666666666666666666666666666666666666666666666
a 1/////// //////// nedeplasat
a @@ 3 1111//// //////// deplasare la dreapta cu 3
b 1/////// //////// nedeplasat
b @@ 3 ///1//// //////// deplasare la dreapta cu 3
66666666666666666666666666666666666666666666666666666666666666666666666666
Ca valoare intreaga, a @@ 3 este 64/-$, iar b @@ 3 este 4/-$, lucru care este in concordanta cu
notiunea de numar negativ si pozitiv din matematica.
8aca operandul din dreapta a operatorului de deplasare este negativ sau are o valoare care este
egala sau depaseste numarul de biti folositi pentru reprezentarea operandului din stanga, atunci
comportarea este nedefinita.
9abelul de mai <os ilustreaza regulile de precedenta %L este mai prioritar& si asociativitate %de la
stanga la dreapta& referitoare la operatorii de deplasare.

66666666666
.xemplu5 2resupunem ca avem5 unsigned a 1 1, b 1 27
66666666666
666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
.xpresie .xpresie ec*ivalenta 0eprezentare Valoare
666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
a DD b @@ 1 %a DD b& @@ 1 //////// //////1/ 2
a DD 1 L 2 DD 3 %a DD %1 L 2&& DD 3 //////// /1////// $4
a L b DD 12 J a @@ b %%a L b&DD%12 J a&&@@b ////11// //////// 3/'2
666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666

66666666
;asti
66666666
4 (masca( este o constanta sau variabila folosita pentru extragerea bitilor doriti dintr6o alta
variabila sau expresie. 8in moment ce constanta (int( 1 are reprezentarea pe biti5
//////// ///////1
aceasta poate fi folosita pentru determinarea bitului cel mai nesemnificativ dintr6o expresie (int(.
Codul de mai <os foloseste aceasta masca si tipareste o secventa alternativa de / si 15
int i, masca 1 17
for %i 1 /7 i D 1/7 LL i&
printf%(Kd(, i R masca&7
8aca dorim sa gasim valoarea unui anume bit dintr6o expresie, putem folosi o masca care este 1 in
acea pozitie si / in rest.

66666666666
.xemplu5
66666666666
2utem folosi expresia 1 DD 2 pentru a vedea al treilea bit %numarand de la dreapta&. .xpresia
%v R %1 DD 2&& ? 1 5 /
are valoarea 1 sau / dupa cum este al treilea bit din (v(.
?lt exemplu de masca este valoarea constanta 2!! %adica 2A+ 61&. .a are reprezentarea
//////// 11111111
8eoarece doar octetul din dreapta este plasat pe (on(, atunci expresia
v R 2!!
va intoarce o valoare ce are reprezentare pe biti cu toti bitii din octetul din stanga (off( si cel din
dreapta identic cu octetul din dreapta a lui (v(. ,punem ca 2!! este o masca pentru octetul din
dreapta.

6666666666666666666666666666666666666666666666666666666666666666666666666
Un program de impac*etare si despac*etare a cuvintelor
6666666666666666666666666666666666666666666666666666666666666666666666666
,tim ca un caracter se memoreaza pe un octet, pe cand un intreg pe doi octeti. "olosind operatorii
de deplasare, putem comprima doua caractere intr6un intreg.

#include Dlimits.*@
#include Dstdio.*@
#include Dconio.*@

void bitCprint%int a&
E
int i7
int n 1 sizeof%int& J C[?0CI97
int masca 1 1 DD %n61&7

for %i 1 17 i D1 n7 LLi&
E
putc*ar%%%a R masca& 11 /& ? P/P 5 P1P&7
a DD1 17
if %i K C[?0CI9 11 / RR i D n&
putc*ar%P P&7
G
G

int pac3%c*ar a, c*ar b&
E
int p 1 a7
p 1 %p DD C[?0CI9& B b7
return p7
G

c*ar unpac3%int p, int 3& :J 3 1 /, 1 J:
E
int n 1 3 J C[?0CI97 :J n 1 /, + J:
unsigned masca 1 2!!7

masca DD1 n7
return%%p R masca& @@ n&7
G

void main%&
E
clrscr%&7
bitCprint%$!&7
printf%(Fnab 1 (&7
bitCprint%pac3%PaP, PbP&&7
putc*ar%PFnP&7
getc*%&7
printf%(=umarul 24-3/ este impac*etarea caracterelor Kc si Kc(,
unpac3%24-3/,1&, unpac3%24-3/,/&&7
getc*%&7
G

66666666666666666666666666666666
Hitere mari 6@ litere mici
66666666666666666666666666666666
0eluam un exemplu dintr6un capitol precedent si anume transformarea literelor mari in mici
folosind operatori de deplasare.

#include Dstdio.*@
#include Dconio.*@
#include DctMpe.*@

void main%&
E
clrscr%&7
int c7
)*ile %%c 1 getc*ar%&& S1 .4"&
E
if %isupper%c&& :: sau %c@1P?P RR cD1PUP&
putc*ar%c B %1 DD !&&7
else
putc*ar%c&7
G
G

66666666666666666
0ecapitulare
66666666666666666
n cele ce urmeaza, vom preciza cum se calculeaza valoarea unui numar pozitiv, respectiv negativ
%in memoria calculatorului&.
"ie declaratia
int a7
Consideram reprezentarea sa in baza 2
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCCCCCCCCCCC
BCCCCCCBCCCCCCBCCCCCCCCCCCCCCBCCCB BCCCBCCCBCCCCCCCCCCCCCCCCCBCCCB
bCE1$G bCE1!G . . . . . . . bC- bC+ bC' . . . . . . . bC1
8aca bCE1$G 1 / atunci
a 1 sumaCE<11GAE1!G bC<J2A<
altfel
consideram reprezentarea in baza 2 a complementului lui a %Xa&
CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCC
BCCCCCCCBCCCCCCBCCCCCCCCCCCCBCCCCB BCCCCBCCCCBCCCCCCCCCCCCCCCBCCCCB
bPCE1$G bPCE1!G . . . . . bPC- bPC+ bPC' . . . . . . bPC1
unde bPC< 1 1 6 bC<7
Xa 1 sumaCE<11GAE1!G bPC<J2A<7
6a 1 Xa L 17
a 1 6%Xa L 1&7
sfarsit.

66666666666666666666666666666666666666666666666
.xercitii propuse spre implementare
66666666666666666666666666666666666666666666666
1. %Tocul *artie, pumn, farfece&
2resupunem ca avem doi <ucatori care folosesc mana dreapta pentru reprezentarea a trei obiecte5
*artie 1 palma intinsa
pumn 1 mana stransa sub forma de pumn
foarfece 1 doua degete departate %semnul Victoriei&
.i isi arata simultan mana dreapta in una din aceste configuratii %de mai multe ori&. 8aca ei arata
acelasi lucru, este remiza %nu castiga nimeni&. 8aca nu se aplica una din urmatoarele trei reguli5
a& [artia acopera pumnul. %deci palma intinsa castiga fata de pumn&
b& 2umnul sparge foarfecele.
c& "oarfecele taie *artia.
,a se simuleze acest <oc, facand un numar arbitrar de evenimente precizand scorul final. ,e cere sa
se <oace persoana6calculator, si
varianta a doua calculator6calculator.
2. 4 ruleta este o masina care selecteaza la intamplare un numar intre / si 3! la intamplare.
Tucatorul poate paria pe un numar par:impar sau poate paria pe un numar oarecare. Castigul unui
pariu par:impar se premiaza cu 2:1 dolari, cu exceptia celor in care ruleta alege /. 8aca <ucatorul
(prinde( numarul selectat de ruleta, atunci este platit cu 3! ... 1 dolari.
ntrebare5 Considerand ca <ucam pariuri de 1 dolar, cate parieri trebuie sa facem astfel incat sa
pierdem 1/ dolari ?
3. "olosind functia (bitCprint( construiti un tabel %cu trei coloane& care sa contina n, reprezentarea
binara a lui 2An, reprezentarea binara a lui 2An61, pentru n 1 /, 1, 2, ..., 32. ?poi, afisati un tabel %tot
cu trei coloane& care sa contina n, 1/An si 1/An61 pentru n 1 /, 1, 2, ..., ' %in baza zece&. Ce
asemanare observati ?
4. Uilele secolului 2/ pot fi notate folosind intregi in forma (zi:luna:an(. 8e exemplu, 1:':-3
inseamna 1 iulie 1--3. ,crieti o functie care memoreaza ziua, luna si anul compact, astfel5
a& pentru zile %maxim 31& sunt suficienti ! biti7
b& pentru luna %12& sunt suficienti 4 biti7
c& pentru ani %1//& sunt suficienti ' biti7
"unctia trebuie sa aiba la intrare ziua, luna si anul ca intregi si trebuie sa returneze data
(impac*etata( pe un (intreg( pe 1$ biti. ,crieti inca o functie care face (despac*etarea(.
!. "olosind operatori pe biti, scrieti programe C care5
a& testeaza daca un numar de tip (int( sau (long( este divizibil cu +. Qeneralizare %divizibilitate cu
2An&7
b& testeaza daca un numar este pozitiv sau negativ7
c& calculeaza pentru un n dat, multiplii de 2, 4, ... Qeneralizare7
d& calculeaza pentru un n dat, Nn:2O, Nn:4O, ... Qeneralizare7
e& calculeaza mAn, folosind reprezentarea in baza 2 a lui n si metoda (divide et impera( %vezi
exercitiul 2 din capitolul $&.
$. ,a se calculeze suma cifrelor unui numar cu n cifre.
"unctii, pointeri si clase de memorare
+.1. 8eclararea si atribuirea pointerilor
+.2. ?dresare si indirectare
+.3. 2ointeri catre (void(
+.4. ?pel prin adresa %referinta&
+.!. 0eguli pentru stabilirea domeniului
+.$. Clase de memorare
+.'. Clasa de memorare (auto(
+.+. Clasa de memorare (extern(
+.-. Clasa de memorare (register(
+.1/. Clasa de memorare (static(
+.11. Variabile externe statice
+.12. nitializari implicite
+.13. 8efinitii si declaratii de functii
+.14. Calificatorii de tip (const( si (volatile(
+.1!. .xercitii propuse spre implementare

11111111
Capitolul +
11111111
1111111111111111111111111111
"unctii, pointeri si clase de memorare
1111111111111111111111111111
Va amintiti ca daca o expresie este transmisa ca argument pentru o functie, atunci se creeaza o
copie a valorii expresiei care se transmite. ?cest mecanism este cunoscut sub numele de apel prin
valoare %(call6bM6value(& si se foloseste in limba<ul C. 2resupunem ca avem o variabila v si o
functie f%&. 8aca scriem
v 1 f%v&7
atunci valoarea returnata de functia f va sc*imba valoarea lui v, altfel nu. n interiorul functiei f, nu
se modifica valoarea lui v. ?ceasta se datoreaza faptului ca se transmite doar o copie a lui v catre f.
n alte limba<e de programare, un apel de functie poate sc*imba valoarea lui v din memorie. ?cest
mecanism se mai numeste apel prin referinta %(call6bM6reference(&. =oi vom simula apelul prin
referinta transmitand adresele variabilelor ca argumente in apelul functiei.

6666666666666666666666666666666666666666666666
8eclararea si atribuirea pointerilor
666666666666666666666666666666666666666666666
2ointerii sunt folositi in programe pentru accesarea memoriei si manipularea adreselor. 8e<a ne6am
intalnit cu adresele variabilelor
ca argumente ale functiei (scanf%&(. 8e .xemplu, putem avea5
scanf%(KdFn(, Rn&7
8aca v este o variabila, atunci Rv este o adresa %sau locatie& din memorie. 4peratorul de adresa R
este unar si are aceeasi precedenta si asociativitate de la dreapta la stanga ca si ceilalti operatori
unari. Variabilele pointer pot fi declarate in programe si apoi folosite pentru a lua valori adrese din
memorie.

66666666666
.xemplu5 8eclaratia
66666666666
int i, Jp7
defineste i de tip (int( si p (pointer catre int(. 8omeniul legal de valori pentru orice pointer
cuprinde adresa speciala / si o multime de numere naturale care sunt interpretate ca fiind adrese
masina ale sistemului C. 8e obicei, constanta simbolica =UHH este / %definita in Dstdio.*@&.

66666666666
.xemple5
66666666666
1. p 1 Ri7 :J valoarea lui p este adresa lui i J:
2. p 1 /7 :J valoarea lui p este adresa speciala / J:
3. p 1 =UHH7 :J ec*ivalent cu p 1 /7 J:
4. p 1 %int J& 13/'7 :J o adresa absoluta din memorie J:

666666666666666666666666666666
?dresare si indirectare
666666666666666666666666666666
?m vazut ca operatorul de adresa R se aplica unei variabile si intoarce valoarea adresei sale din
memorie. 4peratorul de indirectare %sau de dereferentiere& se aplica unui pointer si returneaza
valoarea scrisa in memorie la adresa data de pointer. ntr6un anumit sens, acesti doi operatori sunt
inversi unul altuia. 2entru a intelege mai bine aceste notiuni, sa vedem pe un exemplu ce se
intampla in memorie5
66666666666
.xemplu5
66666666666
2resupunem ca avem declaratiile5

int i 1 ''', Jp 1 Ri7

?tunci, in memorie avem5
=ume 9ip Valoare ?dresa
666666666666666666666666666666666666666
B i B int B ''' B 3?3+5/"". B
666666666666666666666666666666666666666
:F B
B B
%Jp 11 i& J B 66666666 %p 1 Ri&
B B R
B F:
666666666666666666666666666666666666666666666666
B p B int J B 3?3+5/"". B 3?3+5/""? B
666666666666666666666666666666666666666666666666
=ume 9ip Valoare ?dresa

;entionam ca adresa unei variabile este dependenta de sistem %C aloca memorie acolo unde poate&.

66666666666
.xemplu5
66666666666
float x, M, Jp7
p 1 Rx7
M 1 Jp7
;ai intai (p( se asigneaza cu adresa lui (x(. ?poi, (M( se asigneaza cu valoarea unui obiect la care
pointeaza p %adica Jp&. ?ceste doua instructiuni de asignare se pot scrie
M 1 JRx7
care este ec*ivalent cu
M 1 x7
?m vazut mai sus ca un pointer se poate initializa in timpul declararii sale. 9rebuie sa avem totusi
gri<a ca variabilele din membrul drept sa fie de<a declarate.

6666666666
.xemplu5 Unde este greseala ? int Jp 1 Ra, a7
6666666666
9abelul de mai <os ilustreaza modul de evaluare a expresiilor cu pointeri.

6666666666
.xemplu5
6666666666
2resupunem ca avem declaratiile5
int i 1 3, < 1 !, Jp 1 Ri, JZ 1 R<, Jr7
double x7
666666666666666666666666666666666666666666666666666666666666666666666
B .xpresie B .xpresie ec*ivalenta B Valoare B
666666666666666666666666666666666666666666666666666666666666666666666
p 11 R i p 11 %R i& 1
p 1 i L ' p 1 %i L '& gresit
J J R p J %J %R p&& 3
r 1 R x r 1 %R x& gresit
' J J p : J Z L ' %%%' J %J p&&& : %J Z&& L ' 11
J %r 1 R <& J1 J p %J %r 1 %R <&&& J1 %J p& 1!
66666666666666666666666666666666666666666666666666666666666666666666
,pre deosebire de C traditional, in ?=, C, singura valoare intreaga care poate fi asignata unui
pointer este / %sau constanta =UHH&. 2entru asignarea oricarei alte valori, trebuie facuta o conversie
explicita %cast&.
n cele ce urmeaza, vom scrie un program care ilustreaza legatura dintre valoarea unui pointer si
adresa lui.

66666666666
.xemplu5
66666666666
#include Dstdio.*@
#include Dconio.*@

void main%&
E
int i 1 ''', Jp 1 Ri7
clrscr%&7

printf%(Valoarea lui i5 KdFn(, Jp&7
printf%(?dresa lui i5 Klu sau KpFn(, Ri, Ri&7
printf%(?dresa lui i5 Klu sau KpFn(, p, p&7
printf%(Valoarea lui p5 Klu sau KpFn(, p, p&7
printf%(?dresa lui p5 Klu sau KpFn(, Rp, Rp&7
getc*%&7
G

Hocatia curenta a unei variabile din memorie este dependenta de sistem. 4peratorul J %din expresia
Jp& va afisa valoarea scrisa la adresa care este egala cu valoarea lui p. ?dresa lui i %valoarea lui p&
va fi afisata ca fiind ceva de genul
3?3+5/"".
care reprezinta un numar scris in baza 1$ %in care cifrele sunt /, 1, ..., -, ?, I, C, 8, ., "& si are
valoarea
3J1$A'L1/J1$A$L3J1$A!L+J1$A4L 1!J1$A2L1!J1$L14 1 -'$'!2$3+
8e observat ca un pointer se memoreaza intotdeauna pe patru octeti indiferent de tipul variabilei
catre care se face referirea. .xplicati de ce ?

666666666666666666666666666
2ointeri catre (void(
666666666666666666666666666
n C traditional, pointerii de tipuri diferite sunt considerati compatibili ca asignare. n ?=, C,
totusi, un pointer poate fi asignat altuia doar daca au acelasi tip, sau cand unul dintre ei este de tipul
(void(. 8e aceea, putem gandi (void J( ca un tip pointer generic.

6666666666
.xemple5 2resupunem ca avem declaratiile
6666666666
int Jp7
float JZ7
void Jv7
6666666666666666666666666666666666666666666666666666666666
B ?signari legale B ?signari ilegale B
6666666666666666666666666666666666666666666666666666666666
B p 1 /7 p 1 17 B
B p 1 %int J& 17 v 1 17 B
B p 1 v 1 Z7 p 1 Z7 B
B p 1 %int J& Z7 B
666666666666666666666666666666666666666666666666666666666
Vom discuta in capitolele ulterioare despre functiile (calloc%&( si (malloc%&(, care produc alocare
dinamica a memoriei pentru vectori si structuri. .le returneaza un pointer catre (void(, de aceea
putem scrie5
int Ja7
a 1 calloc%...&7
n C traditional, trebuie sa facem conversie explicita5
a 1 %int J& calloc%...&7

66666666666666666666666666666666666
?pel prin adresa %referinta&
66666666666666666666666666666666666
?m vazut ca C foloseste mecanismul apelului prin valoare %(call6bM6value(& in cazul apelurilor
functiilor si anume se fac copii ale parametrilor actuali care se transmit functiilor. n cele ce
urmeaza, vom descrie mecanismul apelului prin adresa si astfel se va asigura modificarea valorii
variabilei transmise. 2entru aceasta, vom utiliza pointeri.
66666666666
.xemplu5
66666666666
#include Dstdio.*@

void intersc*imba%int J, int J&7

void main%&
E
int a 1 3, b 1 '7

printf%(Kd KdFn(, a, b&7
intersc*imba%Ra, Rb&7
printf%(Kd KdFn(, a, b&7
G

void intersc*imba%int Jp, int JZ&
E
int tmp7

tmp 1 Jp7
Jp 1 JZ7
JZ 1 tmp7
G
.fectul apelului prin adresa este realizat prin5
1. 8eclararea parametrului functiei ca fiind un pointer7
2. "olosirea unui pointer de indirectare in corpul functiei7
3. 9ransmiterea adresei unui argument cand functia este apelata.

6666666666666666666666666666666666666666666666
0eguli pentru stabilirea domeniului
6666666666666666666666666666666666666666666666
8omeniul unui identificator este partea din textul unui program unde identificatorul este cunoscut
sau accesibil. ?ceasta idee depinde de notiunea de (bloc(, care este o instructiune compusa cu
declaratii.
0egula de baza in stabilirea domeniului este aceea ca identificatorii sunt accesibili numai in blocul
unde sunt declarati si necunoscuti in afara granitelor blocului. Unii programatori folosesc acelasi
nume de identificatori prezenti in anumite blocuri.
66666666666
.xemplu5
66666666666
E
int a 1 27
printf%(KdFn(, a&7
E
int a 1 '7
printf%(KdFn(, a&7
G
printf%(KdFn(, LLa&7
G
Un program ec*ivalent ar fi5
E
int aCafara 1 27
printf%(KdFn(, aCafara&7
E
int aCinauntru 1 '7
printf%(KdFn(, aCinauntru&7
G
printf%(KdFn(, LLaCafara&7
G

6666666666666666666666666
Clase de memorare
6666666666666666666666666
4rice variabila si functie are doua atribute5
tipul si clasa de memorare
.xista patru clase de memorare in C, automata, externa, registru si statica si sunt date de
urmatoarele cuvinte rezervate5
auto extern register static
Cea mai cunoscuta clasa de memorare este (auto(.

6666666666666666666666666666666666
Clasa de memorare (auto(
6666666666666666666666666666666666
Variabilele declarate in interiorul functiilor sunt implicit automate. 8e aceea, clasa (auto( este cea
mai cunoscuta dintre toate. 8aca o instructiune compusa %bloc& incepe cu declararea unor variabile,
atunci aceste variabile sunt in domeniu in timpul acestei instructiuni compuse %pana la intalnirea
semnului G&.

66666666666
.xemplu5
66666666666
auto int a, b, c7
auto float f7
8eclaratiile variabilelor in blocuri sunt implicit automate.
Ha executie, cand se intra intr6un bloc, se aloca memorie pentru variabilele automate. Variabilele
sunt considerate locale acestui bloc. Cand se iese din acest bloc, sistemul elibereaza zona de
memorie ocupata de acestea si deci valorile acestor variabile se pierd. 8aca intram din nou in acest
bloc, atunci se aloca din nou memorie pentru aceste variabile, dar vec*ile valori sunt necunoscute.

6666666666666666666666666666666666666
Clasa de memorare (extern(
6666666666666666666666666666666666666
4 metoda de transmitere a informatiei in blocuri si functii este folosirea variabilelor externe. 8aca
o variabila este declarata inafara functiei, atunci acesteia i se aloca permanent memorie si spunem
ca ea apartine clasei de memorare (extern(. 4 variabila externa este considerata globala tuturor
functiilor declarate dupa ea, si c*iar dupa iesirea din blocuri sau functii, ea ramane permanent in
memorie.
66666666666
.xemplu5
66666666666
#include Dstdio.*@

int a 1 1, b 1 2, c 1 37
int f%void&7

void main%&
E
printf%(K3dFn(, f%&&7
printf%(K3dK3dK3dFn(, a, b, c&7
G

int f%void&
E
int b, c7 :J b si c sunt locale, deci b, c globale sunt
mascate J:

a 1 b 1 c 1 47 :J valoarea lui a se modifica J:
return%a L b Lc&7
G

.xplicatia este foarte simpla. Ha inceput se memoreaza cate 2 octeti pentru (a(, (b(, (c(. Cand
a<ungem la functia (f%&(, memoram inca cate doi octeti pentru (b( si (c( %notate la fel din
intamplare&. Ha intoarcerea in functia apelanta, aceste (b( si (c( noi nu mai exista pentru ca erau
locale functiei (f%&(. ,a vedem mai exact ce se intampla in memorie5
nainte de apelul functiei (f%&(5
=ume 9ip Valoare ?dresa
666666666666666666666666666666666666666
B a B int B 1 B 3?3+5/"". B
6666666666666666666666666666666666666666
6666666666666666666666666666666666666666
B b B int B 2 B 3?3+5/""C B
6666666666666666666666666666666666666666
6666666666666666666666666666666666666666
B c B int B 3 B 3?3+5/""? B
6666666666666666666666666666666666666666
n timpul executiei functiei (f%&( %dupa a 1 b 1 c 1 4&5
=ume 9ip Valoare ?dresa
666666666666666666666666666666666666666
B a B int B 4 B 3?3+5/"". B
666666666666666666666666666666666666666
666666666666666666666666666666666666666
B b B int B 2 B 3?3+5/""C B
666666666666666666666666666666666666666
666666666666666666666666666666666666666
B c B int B 3 B 3?3+5/""? B
666666666666666666666666666666666666666
66666666666666666666666666666666666666
B b B int B 4 B 3?3+5/""+ B
66666666666666666666666666666666666666
66666666666666666666666666666666666666
B c B int B 4 B 3?3+5/""$ B
66666666666666666666666666666666666666
Ha intoarcerea in functia (main%&(5
=ume 9ip Valoare ?dresa
666666666666666666666666666666666666666
B a B int B 4 B 3?3+5/"". B
666666666666666666666666666666666666666
666666666666666666666666666666666666666
B b B int B 2 B 3?3+5/""C B
666666666666666666666666666666666666666
666666666666666666666666666666666666666
B c B int B 3 B 3?3+5/""? B
66666666666666666666666666666666666666
8eci, cuvantul rezervat (extern( spune compilatorului (cauta peste tot, c*iar si in alte fisiere S(.
?stfel, programul precedent se poate rescrie5
in fisierul (fisier1.c(5

#include Dstdio.*@

int a 1 1, b 1 2, c 1 37 :J variabile externe J:
int f%void&7

void main%&
E
printf%(K3dFn(, f%&&7
printf%(K3dK3dK3dFn(, a, b, c&7
G
in fisierul (fisier2.c(5

int f%void&
E
extern int a7 :J cauta6l peste tot J:
int b, c7

a 1 b 1 c 1 47 :J valoarea lui a se modifica J:
return%a L b Lc&7
G

8eci, putem conc*ide ca informatiile se pot transmite prin variabile globale %declarate cu extern&
sau folosind transmiterea parametrilor. 8e obicei se prefera al doilea procedeu.
9oate functiile au clasa de memorare externa. 8e .xemplu,
extern double sin%double&7
este un prototip de functie valid pentru functia (sin%&(, iar pentru definitia functiei, putem scrie5
extern double sin%double x&
E
..
G

66666666666666666666666666666666666666
Clasa de memorare (register(
66666666666666666666666666666666666666
Clasa de memorare (register( spune compilatorului ca variabilele asociate trebuie sa fie memorate
in registri de memorie de viteza mare, cu conditia ca aceasta este fizic si semantic posibil. 8aca
limitarile resurselor si restrictiile semantice %cateodata& fac aceasta imposibila, clasa de memorare
register va fi inlocuita cu clasa de memorare implicita (auto(. 8e obicei, compilatorul are doar
cativa astfel de registri disponibili. ;ulti sunt folositi de sistem si deci nu pot fi alocati.
"olosirea clasei de memorare (register( este o incercare de a mari viteza de executie a programelor.
8e regula, variabilele dintr6o
bucla sau parametrii functiilor se declara de tip (register(.
66666666666
.xemplu5
66666666666
E
register int i7
for %i 1 /7 i D H;97 LLi&
E
. . . . .
G
G :J la iesirea din bloc, se va elibera registrul i J:
8eclaratia
register i7
este ec*ivalenta cu
register int i7
8aca lipseste tipul variabilei declarata intr6o clasa de memorare de tip (register(, atunci tipul se
considera implicit (int(.

66666666666666666666666666666666666
Clasa de memorare (static(
66666666666666666666666666666666666
8eclaratiile (static( au doua utilizari distincte si importante5
a& permite unei variabile locale sa retina vec*ea valoare cand se reintra in bloc %sau functie&
%caracteristica ce este in contrast cu variabilele (auto( obisnuite&7
b& folosita in declaratii externe are alta comportare %vom discuta in sectiunea urmatoare&7
2entru a ilustra a&, consideram .xemplul5
66666666666
.xemplu5
66666666666
void f%void&
E
static int contor 1 /7

LLcontor7
if %contor K 2 11 /&
. . . . .
else
. . . . .
G

2rima data cand functia este apelata, (contor( se initializeaza cu /. Cand se paraseste functia,
valoarea lui (contor( se pastreaza in memorie. Cand se va apela din nou functia (f%&(, (contor( nu se
va mai initializa, ba mai mult, va avea valoarea care s6a pastrat in memorie la precedentul apel.
8eclararea lui (contor( ca un (static int( in functia (f%&( il pastreaza privat in (f%&( %adica numai aici
i se poate modifica valoarea&. 8aca ar fi fost declarat in afara acestei functii, atunci si alte il puteau
accesa.

6666666666666666666666666666666
Variabile externe statice
6666666666666666666666666666666
=e vom referi acum la folosirea lui (static( ca declaratie externa. ?ceasta pune la dispozitie un
mecanism de (izolare( foarte important pentru modularitatea programelor. 2rin (izolare( intelegem
vizibilitatea sau restrictiile de domeniu.
8eosebirea dintre variabile externe si cele externe static este ca acestea din urma sunt variabile
externe cu restrictii de domeniu. 8omeniul este fisierul sursa in care ele sunt declarate. ?stfel,
acestea sunt inaccesibile pentru functiile definite anterior in fisier sau definite in alte fisiere, c*iar
daca functiile folosesc clasa de memorare (extern(.
66666666666
.xemplu5
66666666666
void f%void&
E
. . . . . :J v nu este accesibil aici J:
G

static int v7 :J variabila externa statica J:

void g%void&
E
. . . . . :J v poate fi folosit aici J:
G
Vom mai prezenta un .xemplu de generare a numerelor aleatoare bazata pe metode de congruente
liniara %\nut*, 8., ..5 (9*e ?rt of Computer 2rogramming(, 2nd ed., vol. 2, (,eminumerical
?lgorit*ms(, 0eading ;ass. ?ddison6YesleM, 1-+1&.

66666666666
.xemplu5
66666666666
#define =9?HC,..8 1' :J ,..8 6 samanta J:
#define ;UH92H.0 2!2'3
#define =C0.;.=9 13+4-
#define ;48UHU, $!!3$
#define "H4?9=QC;48UHU, $!!3$./

static unsigned seed 1 =9?HC,..87 :J externa, dar locala acestui fisier J:
unsigned random%void&
E
seed 1 %;UH92H.0 J seed L =C0.;.=9& K ;48UHU,7
return seed7
G

double probabilitM%void&
E
seed 1 %;UH92H.0 J seed L =C0.;.=9& K ;48UHU,7
return %seed : "H4?9=QC;48UHU,&7
G

"unctia (random%&( produce o secventa aleatoare %aparenta& de numere intregi situate intre / si
;48UHU,. "unctia (probabilitM%&( produce o secventa aleatoare %aparenta& de valori reale intre /
si 1.
4bservam ca un apel al functiei (random%&( sau (probabilitM%&( produce o noua valoare a variabilei
(seed( care depinde de cea vec*e. 8in moment ce (seed( este o variabila externa statica, aceasta
este locala acestui fisier si valoarea sa se pastreaza de la un apel la altul. 2utem acum crea functii in
alte fisiere care apeleaza aceste numere aleatoare fara sa avem gri<a efectelor laterale.
2rezentam, in continuare, un ultim .xemplu de utilizare a lui (static( ca specificator de clasa de
memorare pentru functii. "unctiile declarate (static( sunt vizibile doar in fisierul unde au fost
declarate.
66666666666
.xemplu5
66666666666
void f%int a&
E
. . . . . :J g%& este disponibil aici, dar nu si in alte fisiere J:
G

static int g%void&
E
. . . . .
G

66666666666666666666666666
nitializari implicite
66666666666666666666666666
n C, variabilele externe si statice care nu sunt explicit initializate de catre programator, sunt
initializate de catre sistem cu /. ?ceasta include siruri, siruri de caractere, pointeri, structuri si
inregistrari %union&. 2entru siruri %de caractere&, aceasta inseamna ca fiecare element se initializeaza
cu /, iar pentru structuri si (union( fiecare membru se initializeaza tot cu /. n contrast cu aceasta,
variabilele (registru( si (auto( nu se initializeaza de catre sistem, ci pornesc cu valori (garbage(
%adica cu ce se gaseste la momentul executiei la acea adresa&.

66666666666
.xemplu5 2rocesarea caracterelor
66666666666
4 functie care utilizeaza (return( poate returna o singura valoare. 8aca dorim sa trasmitem mai
multe valori pentru mediul apelant, atunci trebuie sa transmitem adresele unor variabile. Vrem sa
procesam un sir de caractere %in stilul (top6do)n(& astfel5
6 citeste caractere de la intrare pana cand avem .4"7
6 sc*imba litere mici in litere mari7
6 scrie pe fiecare linie trei cuvinte separate de un singur spatiu7
6 numara caracterele si literele de la intrare.

#include Dstdio.*@
#include DctMpe.*@

#define =0CCUV=9. 3
int procesare%int J, int J, int J&7

void main%&
E
int c, numarCcaractere 1 /, numarClitere 1 /7

)*ile %%c 1 getc*ar%&& S1 .4"&
if %procesare%Rc, RnumarCcaractere, RnumarClitere& 11 1&
putc*ar%c&7
printf%(FnKsK!dFnKsK!dFnFn(,
(=umar de caractere5(, numarCcaractere,
(=umar de litere5 (, numarClitere&7
G

int procesare%int Jp, int JnCcCp, int JnClCp&
E
static int contor 1 /, ultimCcaracter 1 P P7

if %isspace%ultimCcaracter& RR isspace%Jp&&
return /7
if %isalp*a%Jp&&
E
LLJnClCp7
if %islo)er%Jp&&
Jp 1 toupper%Jp&7
G
else
if %isspace%Jp&&
if %LLcontor K =0CCUV=9. 11 /&
Jp 1 PFnP7
else
Jp 1 P P7
LLJnCcCp7
ultimCcaracter 1 Jp7
return 17
G

6666666666666666666666666666666666666666
8efinitii si declaratii de functii
666666666666666666666666666666666666666
2entru compilator, declaratiile functiilor sunt date in multe moduri5
6 apelul functiei
6 definitia functiei
6 prototipuri si declaratii explicite
8aca un apel de functie cum ar fi f%x& apare inainte de a fi declarata atunci compilatorul presupune
declaratia implicita
int f%&7
n stilul C traditional, declararea functiilor se face astfel5
int f%x&
double x7
E
. . . . .
G
.ste responsabilitatea programatorului de a transmite o variabila de tip (double(. n stilul ?=, C,
aceasta s6ar scrie5
int f%double x&
E
. . . . .
G
n acest caz, compilatorul stie tipul argumentelor din functia (f%&(. 8e .xemplu, daca un (int( este
transmis ca parametru, atunci el va fi convertit automat la (double(.
.xista cateva limitari pentru definitiile si prototipurile functiilor. Clasa de memorare a functiei,
daca este prezenta, poate fi (extern( sau (static(, dar nu ambele7 (auto( si (register( nu se pot folosi.
,ingura clasa care se poate folosi in lista de tipuri a parametrilor este (register(. 2arametrii nu se pot
initializa.

66666666666666666666666666666666666666666666666666
Calificatorii de tip (const( si (volatile(
66666666666666666666666666666666666666666666666666
Comitetul ?=, a adaugat cuvintele rezervate (const( si (volatile( pentru limba<ul C %acestea nu
sunt disponibile in limba<ul C traditional&. 8e obicei, (const( este plasat intre clasa de memorare si
tipul variabilei.
66666666666
.xemplu5 static const int 3 1 37
66666666666
Citim aceasta (3 este o constanta de tip int cu clasa de memorare static(. 8eoarece (3( are tipul
(const(, atunci putem initializa (3(, dar nu mai poate fi reasignat %incrementat sau decrementat&.
C*iar daca variabila este calificata ca fiind (const(, aceasta nu se poate folosi pentru precizarea
lungimii unui sir.
66666666666
.xemplu5
66666666666
const int n 1 37
int vNnO7 :J gresit J:
8eci o variabila calificata (const( nu este ec*ivalenta cu o constanta simbolica.
Un pointer necalificat nu poate fi asignat cu adresa unei variabile calificata (const(.

6666666666
.xemplu5
66666666666
const int a 1 '7
int Jp 1 Ra7 :J gresit J:
;otivul este ca (p( este un pointer obisnuit catre (int( si l6am putea folosi mai tarziu in expresii de
genul (LLJp(. 9otusi, utilizand pointeri, putem sc*imba valoarea lui a %ceea ce contravine
conceptului de constanta&.

66666666666
.xemplu5
66666666666
const int a 1 '7
const int Jp 1 Ra7
=u vom putea modifica valoarea lui (a(, utilizand (Jp(. 2ointerul (p( nu este constant %putem face
pLL&.
2resupunem ca vrem ca (p( sa fie constant, si nu (a(. Consideram declaratiile5
int a7
int J const p 1 Ra7
Ultima declaratie spune ca (p este un pointer constant catre int, si valoarea sa initiala este adresa lui
a(. ?poi, nu mai putem asigna o valoare lui p, dar putem da valori lui (Jp(.
Consideram acum un .xemplu si mai interesant5

666666666666
.xemplu5
666666666666
const int a 1 '7
const int J const p 1 Ra7
Ultima declaratie spune ca p este un pointer constant catre o constanta intreaga. =ici (p(, nici (Jp(,
nu mai pot fi reasignate. n contrast cu (const(, calificatorul (volatile( este rar folosit. Un obiect
(volatile( este unul ce poate fi modificat intr6un mod nespecificat de catre *ard.

66666666666
.xemplu5 Consideram declaratia
66666666666
extern const volatile int realCtimeCcloc37
Clasa de memorare (extern( inseamna (cauta6l oriunde, in acest fisier sau in alte fisiere(.
Calificatorul (volatile( presupune ca obiectul poate fi modificat de *ard. 8in moment ce apare si
calificatorul (const(, inseamna ca obiectul nu poate fi modificat din program.

66666666666666666666666666666666666666666666666
.xercitii propuse spre implementare
66666666666666666666666666666666666666666666666
1. 8aca (i( si (<( sunt de tip (int(, iar (p( si (Z( sunt pointeri catre (int(, precizati care dintre
urmatoarele asignari sunt corecte5
p 1 Ri7 p 1 RJRi7 i 1 %int& p7 Z 1 Rp7
JZ 1 R<7 i 1 %JR&<7 i 1 JRJR<7 i 1 %Jp&LL L JZ7
2. ,crieti o functie C care sa faca o permutare circulara a cinci variabile. %1,2,3,4,!& 6@ %2,3,4,!,1&.
3. "ie codul C
int v 1 ', Jp 1 Rv, JJZ 1 Rp7
printf%(KpFnKdFnKpFnKpFnKdFnKpFnKpFnKpFnKdFn(,
Rv, JRv, Rp, JRp, JJRp, RZ, JRZ, JJRZ, JJJRZ&7
.xplicati de ce anumite numere se repeta S 4bservati ca am folosit combinatia (JR(, si nu (RJ(.
.xplicati daca exista situatii unde (RJ( este corect semantic.
4. ,crieti un program C care arata pe cati octeti sunt memorati pointerii catre tipurile fundamentale
de date. Ce observati ?
,iruri si pointeri
-.1. ,iruri uni6dimensionale
-.2. nitializarea sirurilor
-.3. ndexul unui sir
-.4. 0elatia dintre vectori si pointeri
-.!. 2ointeri aritmetici si lungimea elementelor
-.$. 9rimiterea sirurilor ca argumente pentru functii
-.'. ,iruri multidimensionale
-.+. Vectori 26dimensionali
-.-. Vectori 36dimensionali
-.1/. nitializarea vectorilor
-.11. ?locarea dinamica a memoriei
-.12. .xercitii propuse spre implementare



111111111
Capitolul -
111111111
1111111111111
,iruri si pointeri
1111111111111
Un sir %se mai spune si vector& este o secventa de date ce contine articole de acelasi tip, indexate si
memorate contiguu. 8e obicei, sirurile se folosesc pentru reprezentarea unui numar mare de valori
omogene %in capitolul urmator vom studia sirurile de caractere&. 4 declaratie obisnuita de sir aloca
memorie incepand de la adresa de baza. =umele sirului este un pointer constant la aceasta adresa de
baza.
4 alta notiune pe care o vom explica este transmiterea sirurilor ca argumente in functii.

6666666666666666666666666666666
,iruri uni6dimensionale
6666666666666666666666666666666
666666666666
.xemplu5
666666666666
2resupunem ca vrem sa lucram cu trei intregi5
int a1, a2, a37
9otusi, daca avem mai multe numere este anevoios sa declaram numerele in acest fel. ,olutia
consta in utilizarea unui sir %de lungime trei& de intregi.
int aN3O7
.lementele acestui sir vor fi accesate astfel5 aN/O aN1O aN2O
8eci numarul 3 reprezinta lungimea sirului, elementele sale fiind indexate incepand cu numarul /.
?ceasta este o trasatura a limba<ului C.
4 declaratie de sir uni6dimensional este un tip urmat de un identificator urmat la randul lui de
paranteze patrate ce cuprind o expresie integrala constanta. Valoarea expresiei constante, care
trebuie sa fie pozitiva, se numeste lungimea sirului si ea specifica numarul de elemente ale sirului.
2entru memorarea elementelor intr6un sir, compilatorul rezerva un spatiu de memorie
corespunzator, pornind de la adresa de baza. 8imensiunea spatiului de memorie este egala cu
numarul de elemente ale sirului inmultit cu numarul de octeti necesari memorarii unui element al
sirului.

666666666666
.xemplu5
666666666666
Vom scrie un mic program care initializeaza un sir, tipareste valorile sale si insumeaza elementele
sirului.

#include Dstdio.*@
#define = !

void main%&
E
int aN=O7 :J aloca spatiu de memorie pentru aN/O, aN1O, aN2O, aN3O si aN4O J:
int i, suma 1 /7

for %i 1 /7 i D =7 LLi& :J initializeaza sirul J:
aNiO 1 ' L i J i7
for %i 1 /7 i D =7 LLi& :J tipareste sirul J:
printf%(aNKdO 1 Kd (, i, aNiO&7
for %i 1 /7 i D =7 LLi& :J insumeaza elementele sirului J:
suma L1 aNiO7
printf%(Fnsuma 1 KdFn(, suma&7 :J tipareste suma lor J:
G

,a vedem ce se intampla in memorie ?
=ume 9ip Valoare ?dresa
666666666666666666666666666666666666666
B aN4O B int B 23 B 3?3+5/"". B
666666666666666666666666666666666666666
666666666666666666666666666666666666666
B aN3O B int B 1$ B 3?3+5/""C B
666666666666666666666666666666666666666
666666666666666666666666666666666666666
B aN2O B int B 11 B 3?3+5/""? B
666666666666666666666666666666666666666
6666666666666666666666666666666666666
B aN1O B int B + B 3?3+5/""+ B
6666666666666666666666666666666666666
6666666666666666666666666666666666666
B aN/O B int B ' B 3?3+5/""$ B
6666666666666666666666666666666666666

8eci vectorul %sirul& (a( se va memora incepand de la adresa 3?3+5/""$. 8eci (a 1 RaN/O(.
,e recomanda definirea lungimii unui sir ca o constanta simbolica %folosind directiva (#define(&.

666666666666666666666666666
nitializarea sirurilor
666666666666666666666666666
,irurile pot apartine claselor de memorare (auto(, (extern(, (static( sau (constant(, dar nu pot fi
(register(. Ca si variabilele simple,
sirurile pot fi initializate in timpul declararii lor. nitializarea sirurilor se face folosind acolade si
virgule.
666666666666
.xemplu5
666666666666
float xN'O 1 E61.1, /.2, 33./, 4.4, !./!, /./, '.'G7
?sta inseamna, ec*ivalent5
xN/O 1 61.17
xN1O 1 /.27
. . . . .
xN$O 1 '.'7
8aca lista de valori de initializare este mai mica decat numarul de elemente ale sirului, atunci
elementele ramase se initializeaza cu /. 8aca un sir declarat (extern( sau (static( nu este initializat,
atunci sistemul initializeaza toate elementele cu /. Vectorii declarati constanti sau automatic %cei
impliciti& sunt initializati cu valori (garbage( %adica cu valorile existente in momentul executiei in
memorie la acele adrese&. C traditional permite doar initializarea vectorilor declarati (extern( sau
(static(, pe cand ?=, C permite initializarea sirurilor automate si constante.
8aca un sir este declarat fara precizarea lungimii si initializat cu o serie de valori, atunci lungimea
sa se considera implicit numarul
de valori initiale.

666666666666
.xemplu5
666666666666
8eclaratiile
int aNO 1 E3, 4, !, $G7 si int aN4O 1 E3, 4, !, $G7
sunt ec*ivalente.

666666666666666666666
ndexul unui sir
66666666666666666666
2resupunem ca avem declaratia
int i, aNlungimeO7
2entru accesarea unui element din sir, vom scrie (aNiO(, sau mai general (aNexpresieO(, unde
(expresie( este o expresie integrala. (i( de mai sus se numeste index al sirului (a( si poate avea
valori intre / si (lungime61(. 8aca indexul depaseste acest domeniu, compilatorul va da eroare in
timpul executiei programului.

66666666666
.xemplu5
66666666666
#include Dstdio.*@
#include DctMpe.*@

void main%&
E
int c, i, literaN2$O7

for %i 1 /7 i D 2$7 LLi& :J initializarea vectorului cu / J:
literaNiO 1 /7
)*ile %%c 1 getc*ar%&& S1 .4"& :J numararea literelor J:
if %isupper%c&&
LLliteraNc 6 P?PO7
for %i 1 /7 i D 2$7 LLi& :J tiparirea rezultatelor J:
E
if %i K $ 11 /&
printf%(Fn(&7
printf%(K!c5K4d(, P?P L i, literaNiO&7
G
printf%(FnFn(&7
G
?cest program citeste de la tastatura sau dintr6un fisier %folosind indirectarea& un sir de caractere si
numara in vectorul (litera( fiecare aparitie %in parte& a literelor.

66666666666666666666666666666666666666666
0elatia dintre vectori si pointeri
66666666666666666666666666666666666666666
?m vazut ca numele unui sir %de exemplu (a(& este o adresa, deci poate fi privit ca valoare a unui
pointer. 8eci sirurile si pointerii pot fi priviti oarecum la fel in ceea ce priveste modul cum sunt
folositi pentru accesarea memoriei. Cu toate acestea, sunt cateva diferente %subtile si importante&.
Cum numele unui sir este o adresa fixa %particulara&, atunci aceasta o putem gandi ca un pointer
constant. Cand este declarat un sir, compilatorul trebuie sa aloce o adresa de baza si un spatiu
suficient de memorie care trebuie sa contina toate elementele sirului. ?dresa de baza a unui sir este
locatia initiala din memorie unde sirul este memorat7 aceasta coincide cu adresa primului element
%de index /& al sirului.

666666666666
.xemplu5 2resupunem ca avem declaratiile5
666666666666

#define = 1//
int aN=O, Jp7
?tunci sistemul va rezerva octetii %sa zicem& numerotati 3//, 3/2, ..., 4-+ ca fiind adresele
elementelor aN/O, aN1O, ..., aN--O
nstructiunile
p 1 a7 si p 1 RaN/O7
sunt ec*ivalente si vor asigna lui (p( valoarea 3// %ca adresa de memorie&. ?ritmetica pointerilor
pune la dispozitie o alternativa pentru indexarea sirurilor.
nstructiunile p 1 a L 17 si p 1 RaN1O7 sunt ec*ivalente si va asigna lui (p( valoarea 3/2 %adresa,
bineinteles&.

666666666666
.xemplu5 2resupunem ca avem un sir ale carui elemente au de<a valori. 2entru a face suma
elementelor, putem folosi pointeri.
666666666666
suma 1 /7
for %p 1 a7 p D RaN=O7 LLp&
suma L1 Jp7

6666666666666666666666666666666666666666666666666666666
2ointeri aritmetici si lungimea elementelor
6666666666666666666666666666666666666666666666666666666
2ointerii aritmetici reprezinta una din trasaturile puternice ale limba<ului C. 8aca variabila (p( este
pointer catre un tip particular, atunci expresia (p L 1( reprezinta adresa masina pentru memorarea
sau accesarea urmatoarei variabile de acest tip. n mod similar, expresiile
p L i LLp p L1 i
au sens. 8aca (p( si (Z( sunt pointeri catre elemente de tip vector, atunci (p 6 Z( intoarce valoarea
(int( si reprezinta numarul de elemente dintre (p( si (Z(. C*iar daca expresiile pointer si expresiile
aritmetice seamana, exista diferente mari intre cele doua tipuri de expresii.

66666666666
.xemplu5
66666666666
void main%&
E
double aN2O, Jp, JZ7
p 1 RaN/O7 :J pointeaza catre baza sirului J:
Z 1 p L 17 :J ec*ivalent cu Z 1 RaN1O7 J:
printf%(KdFn(, Z 6 p&7 :J se va tipari 1 J:
printf%(KdFn(, %int& Z 6 %int& p&&7 :J se va tipari + J:
G

66666666666666666666666666666666666666666666666666666666666666
9rimiterea sirurilor ca argumente pentru functii
66666666666666666666666666666666666666666666666666666666666666
ntr6o definitie de functie, un parametru formal care este declarat ca un sir este de fapt un pointer.
Cand este trimis un sir, atunci se
trimite de fapt adresa de baza %evident prin (call6bM6value(&. .lementele vectorului nu sunt copiate.
Ca o conventie de notatie, compilatorul permite folosirea parantezelor patrate %N,O& in declararea
pointerilor ca parametri.
66666666666
.xemplu5 ,uma elementelor unui sir de tip vector
66666666666
int suma%int aNO, int n& :J n dimensiunea sirului J:
E
int i, s 1 /7
for %i 1 /7 i D n7 LLi&
s L1 aNiO7
return s7
G
n antetul functiei precedente, declaratia5
int aNO7 este ec*ivalenta cu int Ja7
2e de alta parte, declaratiile de mai sus nu sunt ec*ivalente daca se utilizeaza in alta parte5
6 prima se refera la creearea unui pointer constant %fara spatiu de memorie&7
6 a doua va crea o variabila pointer.
2resupunem ca (v( este declarat ca fiind un sir de 1// de elemente de tip (int(. 8upa ce am atribuit
valori elementelor sale, putem utiliza functia (suma%&( pentru a aduna anumite valori ale lui (v(.
6666666666666666666666666666666666666666666666666666666666666666
B ?pel B Ce se calculeaza si se returneaza ? B
6666666666666666666666666666666666666666666666666666666666666666
suma%v, 1//& vN/O L vN1O L ... L vN--O
suma%v, ++& vN/O L vN1O L ... L vN+'O
suma%RvN'O, 36'& vN'O L vN+O L ... L vN3 6 1O
suma%v L ', 2 J 3& vN'O L vN+O L ... L vN2 J 3 L $O
6666666666666666666666666666666666666666666666666666666666666666

66666666666
.xemplu5 ,ortare cu bule 6 (Iubble sort(
66666666666
?lgoritmii eficienti de sortare au, de obicei, 4%nJlog n& operatii. ;etoda sortarii cu bule este
ineficienta din acest punct de vedere
deoarece are 4%nA2& operatii. 9otusi, pentru siruri de lungime mica, numarul de operatii este
acceptabil. Un cod (elegant( ar fi5
void intersc*imba%int J, int J&7

void bubble%int aNO, int n& :J n este lungimea lui aNO J:
E
int i, <7

for %i 1 /7 i D n 6 17 LLi&
for %< 1 n 6 17 i D <7 66<&
if %aN< 6 1O @ aN<O&
intersc*imba%RaN< 6 1O, RaN<O&7
G

66666666666666666666666666666666
,iruri multidimensionale
66666666666666666666666666666666
Himba<ul C permite siruri de orice tip, inclusiv siruri de siruri. 2utem obtine siruri de dimensiune 2,
3, ... .
66666666666
.xemple5
66666666666
int aN1//O7 D6 sir de dimensiune 1
int bN2ON'O7 D6 sir de dimensiune 2
int cN!ON3ON2O7 D6 sir de dimensiune 3
2ornind de la adresa de baza, toate elementele sirului sunt memorate contiguu in memorie. 2rin
definitie un tablou bidimensional este de fapt un tablou unidimensional ale carei elemente sunt
fiecare in parte cite un tablou. 2rin urmare, indicii se scriu astfel aNiON<O in loc de aNi, <O ca in
ma<oritatea limba<elor. n plus un tablou bidimensional poate fi tratat in mai multe moduri decat in
alte limba<e. .lementele sunt memorate pe linii, ceea ce inseamna ca indicele din dreapta variaza
primul in asa fel incit elementele sunt accesate in ordinea memoriei.

666666666666666666666666666666
Vectori 26dimensionali
66666666666666666666666666666
2resupunem ca avem un vector 26dimensional cu elemente intregi.
int aN3ON!O7
ncepand cu adresa de baza, compilatorul va aloca spatiu contiguu pentru 1! intregi. ?tunci putem
gandi acest vector ca o matrice,
astfel5
col1 col2 col3 col4 col!
lin1 aN/ON/O aN/ON1O aN/ON2O aN/ON3O aN/ON4O
lin2 aN1ON/O aN1ON1O aN1ON2O aN1ON3O aN1ON4O
lin3 aN2ON/O aN2ON1O aN2ON2O aN2ON3O aN2ON4O
2entru aNiON<O avem expresiile, de exemplu, ec*ivalente5
J%aNiO L <&
%J%a L i&&N<O
J%%J%a L i&& L <&
J%RaN/ON/O L !Ji L <&
2utem gandi (aNiO( ca a (i(6a coloana a lui (a( %numarand de la /&, si (aNiON<O( ca elementul din linia
(i(, coloana (<( a sirului %numarand de la /&. =umele sirului %(a(& este tot una cu (RaN/O(7 acesta
este un pointer catre un sir de ! intregi. ?dresa de baza este (RaN/ON/O(, si nu (a(. Ultimul exemplu
de mai sus reflecta functia de corespondenta in memorie dintre valoarea pointerului si indicele
sirului.
Cand un vector multidimensional este un parametru formal in definitia unei functii, toate
dimensiunile, exceptand prima trebuie specificate.

66666666666
.xemplu5
66666666666
2resupunem ca sunt date elementele vectorului (a(. "unctia de mai <os se poate folosi pentru suma
elementelor unui sir. ?tentie S 9rebuie specificat numarul de coloane.
int suma%int aNON!O&
E
int i, <, suma 1 /7

for %i 1 /7 i D 37 LLi&
for %< 1 /7 < D !7 LL<&
suma L1 aNiON<O7
return suma7
G
n antetul functiei, urmatoarele declaratii sunt ec*ivalente5
int aNON!O int %Ja&N!O int aN3ON!O
Constanta 3 actioneaza ca o reminiscenta a omului, dar compilatorul nu tine cont de ea.
=ou venitii in C sunt uneori confuzi in legatura cu deosebirea dintre un tablou bidimensional si un
tablou de pointeri cum ar fi (a( din exemplul de mai sus. "iind date declaratiile
int aN1/ON1/O7
int JbN1/O7
utilizarile lui (a( si (b( pot fi similare, in sensul ca aN!ON!O si bN!ON!O sunt ambele referinte legale
ale aceluiasi (int(.
?vanta<e pentru utilizarea vectorilor %dezavanta<e pentru pointeri&5
6 (a( este un tablou in toata regula5 toate cele 1// celule de memorie trebuie alocate, iar pentru
gasirea fiecarui element
se face calculul obisnuit al indicelui7
6 pentru (b(, oricum prin declararea sa se aloca 1/ pointeri7 fiecare trebuie facut sa pointeze un
tablou de intregi.
2resupunind ca fiecare pointeaza cate 1/ elemente din tablou, atunci vom obtine 1// celule de
memorie rezervate, plus cele 1/
celule pentru pointeri. ?stfel tabloul de pointeri utilizeaza sensibil mai mult spatiu si poate
cere un procedeu explicit de
initializare.
?vanta<e pentru utilizarea pointerilor %dezavanta<e pentru vectori&5
6 accesarea unui element se face indirect prin intermediul unui pointer, in loc sa se faca prin
inmultire si adunare7
6 liniile tabloului pot fi de lungimi diferite. ?ceasta inseamna ca nu orice element al lui b este
constrins sa pointeze pe un vector
de 1/ elemente, unii pot pointa pe cate 2 elemente, altii pe cate 2/ si altii pe niciunul.

66666666666666666666666666666
Vectori 36dimensionali
66666666666666666666666666666
Vectorii de dimensiune mai mare decat 3 lucreaza intr6un mod similar. 8aca avem declaratia
int aN'ON-ON2O7
atunci compilatorul va aloca spatiu pentru 'J-J2 intregi. ?dresa de baza a sirului este
(RaN/ON/ON/O(, iar functia de corespondenta in memorie este specificata de
aNiON<ON3O care este ec*ivalent cu J%RaN/ON/ON/O L -J2Ji L 2J< L 3&

66666666666666666666666666666
nitializarea vectorilor
66666666666666666666666666666
.xista mai multe moduri de a initializa un vector multidimensional.
666666666666
.xemplu5 Urmatoarele declaratii sunt ec*ivalente5
666666666666
int aN2ON3O 1 E1, 2, 3, 4, !, $G7
int aN2ON3O 1 EE1, 2, 3G, E4, !, $GG7
int aNON3O 1 EE1, 2, 3G, E4, !, $GG7
ndexarea se face dupa linii. 8aca nu sunt suficiente elemente care sa initializeze vectorul, atunci
restul elementelor sunt initializate cu /. 8aca prima componenta lipseste, atunci compilatorul
extrage lungimea din numarul de perec*i de acolade interioare.
666666666666
.xemplu5 Consideram initializarea5
666666666666
int aN2ON2ON3O 1 E
EE1, 1, /G, E2, /, /GG,
EE3, /, /G, E4, 4, /GG
G7
4 initializare ec*ivalenta poate fi data si astfel5
int aNON2ON3O 1 EEE1, 1G, E2GG, EE3G, E4, 4GGG7
8e obicei, daca un sir declarat (auto( nu este explicit initializat, atunci elementele sirului vor
contine valori (garbage(.
,irurile (static( si (external( sunt initializate implicit cu /. ata un mod simplu de a initializa toate
valorile unui vector cu /5
int aN2ON2ON3O 1 E/G7

666666666666666666666666666666666666666
?locarea dinamica a memoriei
666666666666666666666666666666666666666
C pune la dispozitie pentru alocarea memoriei functiile (calloc%&( si (malloc%&( din biblioteca
standard. ?ceste functii au prototipul
declarat in Dstdlib.*@. ?cest lucru va permite rezervarea memoriei pentru un vector %de exemplu&
in care ii aflam dimensiunea abia la rularea in executie %pana acum declararam dimensiunea unui
vector cu #define&. Un apel de tipul
calloc%n, dimensiuneCtip&
va returna un pointer catre un spatiu din memorie necesar pentru memorarea a (n( obiecte, fiecare
pe (dimensiuneCtip( octeti. 8aca
sistemul nu poate aloca spatiul cerut, atunci acesta va returna valoarea =UHH.
n ?=, C, tipul (sizeCt( este dat ca (tMpedef( in Dstdlib.*@. 8e obicei, tipul este (unsigned(.
8efinitia tipului este folosita in
prototipurile functiilor (calloc%&( si (malloc%&(5
void Jcalloc%sizeCt, sizeCt&7
void Jmalloc%sizeCt&7
8eoarece pointerul returnat de aceste functii are tipul (void(, acesta poate fi asignat altor pointeri
fara conversie explicita %cast&. 9otusi unele sisteme nu accepta aceasta conversie, deci ea trebuie
facuta explicit. 4ctetii rezervati de (calloc%&( sunt automat initializati cu /, pe cand cei rezervati cu
(malloc%&( nu sunt initializati %deci vor avea valori (garbage(&. =umele (calloc(, respectiv (malloc(,
provine de la (contiguous allocation(, respectiv (memorM allocation(.

66666666666
.xemplu5 2rogram care citeste dimensiunea unui sir interactiv
66666666666
#include Dstdio.*@
#include Dstdlib.*@

void main%&
E
int Ja, i, n, suma 1 /7

printf%(FnKs(, (Citirea dimensiunii unui sir interactiv.FnFn8ati numarul de elemente a sirului5 (&7
scanf%(Kd(, Rn&7
a 1 calloc%n, sizeof%int&&7 :J aloca spatiu pentru n intregi J:
:J daca da eroare de conversie de tip, atunci adaugati dupa semnul 1,
conversia %int J& J:
for %i 1 /7 i D n7 LLi&
scanf%(Kd(, RaNiO&7
for %i 1 /7 i D n7 LLi&
suma L1 aNiO7
free%a&7 :J eliberarea spatiului J:
printf%(FnKsK'dFnKsK'dFnFn(, (=umarul de elemente5 (, n, (,uma elementelor 5 (, suma&7
G
2rototipul functiei (free%&( se gaseste in Dstdlib.*@ si este
void free%void Jptr&7
,patiul alocat de (calloc%&( si (malloc%&( ramane ocupat pana cand este eliberat de catre
programator. ?cesta nu se elibereaza cand se iese dintr6o functie %in care s6a facut rezervarea de
memorie&.
n programul de mai sus, instructiunea
a 1 calloc%n, sizeof%int&&7
este ec*ivalenta cu
a 1 malloc%n J sizeof%int&&7
,ingura diferenta este deci initializarea cu / in cazul functiei (calloc%&(.

666666666666
.xemplu5 .xemplu de citire interactiva a dimensiunii si a elementelor unei matrice de intregi

void main%&
E
int =7
int JJ a, Jptr7

printf%(ntroduceti dimensiunea matricii5(&7
scanf%(Kd(, R=&7
a 1 %int JJ& calloc%= J =, sizeof%int&&7

ptr1RaN/ON/O7
printf%(FnFnntroduceti elementele matricii5Fn(&7

for %i 1 /7i D =7 LLi&
for %< 1 /7< D =7 LL<&
E
printf%(aNKdONKdO1(, i, <&7
scanf%(Kd(, ptrLL&7
G
G

66666666666666666666666666666666666666666666666
.xercitii propuse spre implementare
66666666666666666666666666666666666666666666666
1. ,crieti o functie care insumeaza elementele de rang %index& impar, respectiv par, ale unui vector
cu elemente de tip (double(.
,ugestie5 functia poate incepe cam asa
void suma%double aNO,
int n, :J n 6 lungimea sirului a J:
double Jimpar,
double Jpar&
E
. . . . .
2. ;odificati programul de sortare cu bule astfel incat terminarea iteratiilor sa aiba loc cand nu se
mai fac intersc*imbari de
elemente.
3. Calculati valoarea unui determinant asociat unei matrice patratice. n cazul in care determinantul
este nenul, calculati
inversa matricei.
4. Calculati inversa unei permutari cu un numar constant de variabile suplimentare
,iruri de caractere si pointeri
1/.1. ;arcatorul (sfarsit de sir de caractere( F/
1/.2. "olosirea pointerilor pentru procesarea unui sir
1/.3. 9rimiterea argumentelor catre (main%&(
1/.4. Hucrul cu sirurile din biblioteca standard
1/.!. Unde este eroarea ?
1/.$. .xercitii propuse spre implementare

111111111
Capitolul 1/
111111111
1111111111111111111111
,iruri de caractere si pointeri
1111111111111111111111
Un caracter dintr6un sir de caractere (a( poate fi accesat folosind indexul sirului %aNiO, de exemplu&
sau folosind pointeri la caracter.

666666666666666666666666666666666666666666666666666666
;arcatorul (sfarsit de sir de caractere( F/
666666666666666666666666666666666666666666666666666666
2rin conventie, un sir de caractere se termina prin marcatorul %santinela, delimitator& F/, sau
caracterul nul. 8e exemplu, sirul (abc( este memorat pe 4 caractere, ultimul fiind F/. 8eci numarul
de elemente al sirului este 3, iar dimensiunea 4.
66666666666
.xemplu5
66666666666
#define ;?>Y408 1//
void main%&
E
c*ar )N;?>Y408O7
. . . . .
G
nitializarea %citirea& unui sir se poate face in mai multe moduri5
1. nitializarea fiecarui element cu cate un caracter5
)N/O 1 P?P7
)N1O 1 PIP7
)N2O 1 PCP7
)N3O 1 PF/P7
2. "olosind functia (scanf%&(5
scanf%(Ks(, )&7

"ormatul (Ks( este folosit pentru citirea unui sir de caractere. 8istingem trei pasi5
6 pozitionare pe primul caracter al sirului7
6 se citesc toate caracterele diferite de D.nter@ si se introduc in ()(7
6 citirea se face pana cand intalnim .4"7 acum se plaseaza la sfarsitul sirului PF/P.
8in moment ce numele unui sir este un pointer la adresa de baza a sirului, expresia ()( este
ec*ivalenta cu (R)N/O(.
8aca sirul citit are mai multe caractere decat cele rezervate, atunci se va obtine o eroare.
?tentie S PaP si (a( sunt diferite. 2rima este o constanta caracter, iar a doua este o constanta
sir de caractere.
66666 666666
(a( 1 B PaP B PF/P B
66666 666666
3. ,irurile se pot initializa la fel ca si caracterele
c*ar sNO 1 (abc(7
sau ec*ivalent
c*ar sNO 1 EPaP, PbP, PcP, PF/PG7
4. 2utem folosi si un pointer catre un sir constant, dar interpretarea este diferita5
c*ar Jp 1 (abc(7
Va reamintim ca numele unui sir poate fi tratat ca un pointer catre adresa de baza a sirului
din memorie.
Constanta (abc( este memorata de catre compilator. n acelasi timp, aceasta este (un nume
de sir(.
?sadar, diferenta dintre un sir initializat cu o constanta sir si un pointer initializat tot cu o constanta
sir este ca sirul contine caractere individuale urmate de caracterul (F/(, in timp ce pointerul este
asignat cu adresa sirului constant din memorie.

66666666666
.xemplu5 Utilizarea sirurilor de caractere %ca vectori&.
66666666666 Citim o linie de caractere dintr6un sir, le tiparim in ordine inversa si adunam literele din
sir.

#include Dstdio.*@
#include DctMpe.*@
#define ;?>,90=Q 1//

main%&
E
c*ar c, nameN;?>,90=QO7
int i, sum 1 /7

printf%(Fn,alutS Care este numele tau? (&7
for %i 1 /7 %c 1 getc*ar%&& S1 PFnP7 LLi&
E
nameNiO 1 c7
if %isalp*a%c&&
sum L1 c7
G
nameNiO 1 PF/P7
printf%(FnKsKsKsFnKs(,
(;a bucur ca te6am intalnit (,name,(.(,
(=umele tau scris invers este (&7
for %66i7 i @1 /7 66i&
putc*ar%nameNiO&7
printf%(FnKsKdKsFnFnKsFn(,
(si numele tau are (, sum,( litere .(,
(Ha revedere. (&7
G

666666666666666666666666666666666666666666666666666666666666
"olosirea pointerilor pentru procesarea unui sir
666666666666666666666666666666666666666666666666666666666666
Vom discuta despre folosirea pointerilor pentru procesarea unui sir si cum se pot folosi acestea
pentru a fi transmise ca parametri unei functii. Vom scrie un exemplu de program interactiv care
citeste intr6un sir o linie de caractere introdusa de utilizator. 2rogramul va crea un nou sir si6l va
tipari.
666666666666
.xemplu5
666666666666
#include Dstdio.*@
#define ;?>H=. 1//

void main%&
E
c*ar linieN;?>H=.O, Jsc*imba%c*ar J&7
void citesteCin%c*ar J&7

printf%(Fn8ati un sir5(&7
citesteCin%linie&7
printf%(FnKsFnFnKsFnFn(,
(?sa arata sirul dupa sc*imbare5(, sc*imba%linie&&7
G

void citesteCin%c*ar sNO&
E
int c, i 1 /7

)*ile %%c 1 getc*ar%&& S1 .4" RR c S1 PFnP&
sNiLLO 1 c7
sNiO 1 PF/P7
G

c*ar Jsc*imba%c*ar Js&
E
static c*ar sirCnouN;?>H=.O7
c*ar Jp 1 sirCnou7

JpLL 1 PFtP7
for % 7 Js S1 PF/P7 LLs&
if %Js 11 PeP&
JpLL 1 P.P7
else
if %Js 11 P P&
E
JpLL 1 PFnP7
JpLL 1 PFtP7
G
else
JpLL 1 Js7
Jp 1 PF/P7
return sirCnou7
G
66666666666
ntrebare5 8e ce vectorul (sirCnou( a fost declarat static ?
66666666666
8eoarece numele (sirCnou( este tratat ca un pointer catre adresa de baza a sirului. "iind declarat
(static(, acesta se pastreaza in memorie si dupa ce se iese din functia (sc*imba%&(. ?cest lucru nu s6
ar fi intamplat si daca, de exemplu, sirul ar fi fost declarat (auto(.
66666666666
.xemplu5 "unctie C pentru numararea cuvintelor unui sir de caractere
66666666666
#include DctMpe.*@

int numarareCcuvinte%c*ar Js&
E
int contor 1 /7

)*ile %Js S1 PF/P&
E
)*ile %isspace%Js&& :J sarim spatiile goale J:
LLs7
if %Js S1 PF/P& :J gasim un cuvant J:
E
LLcontor7
)*ile %Sisspace%Js& RR Js S1 PF/P& :J sarim peste cuvant J:
LLs7
G
G
return contor7
G

6666666666666666666666666666666666666666666666666666
9rimiterea argumentelor catre (main%&(
6666666666666666666666666666666666666666666666666666
C pune la dispozitie siruri de orice tip, inclusiv siruri de pointeri. 2entru scrierea de programe care
folosesc argumente in linia de comanda, trebuie sa folosim siruri de pointeri catre caractere. 2entru
aceasta, functia (main%&( foloseste doua argumente, numite generic (argc( si (argv(.
66666666666
.xemplu5
66666666666
#include Dstdio.*@

void main%int argc, c*ar JargvNO&
E
int i7

printf%(argc 1 KdFn(, argc&7
for %i 1 /7 i D argc7 LLi&
printf%(argvNKdO 1 KsFn(, i, argvNiO&7
G

Variabila (argc( precizeaza numarul de argumente din linia de comanda. ,irul (argv( este un sir de
pointeri catre caracter si poate fi gandit ca vector de siruri de caractere. 8eoarece elementul
(argvN/O( contine intotdeauna numele comenzii, rezulta ca valoarea lui (argc( va fi mai mare sau
egala cu 1.
Compilam programul de mai sus si obtinem executabilul (prog1.exe(. 8aca dam comanda
prog1
atunci pe ecran se va afisa
argc 1 1
argvN/O 1 prog1
8aca dam comanda
prog1 fisier1 fisier2
atunci pe ecran se va afisa
argc 1 3
argvN/O 1 prog1
argvN1O 1 fisier1
argvN2O 1 fisier2
2arametrul (argv( s6ar fi putut declara si astfel
c*ar JJargv7
?cesta este un pointer catre pointer catre (c*ar( si acesta poate fi gandit ca un sir de pointeri catre
(c*ar(, care la randul lor pot fi ganditi ca vector de siruri de caractere. 4bservati ca nu alocam
spatiu in memorie pentru sirurile din linia de comanda. ?cest lucru este facut de insusi sistemul C
cand atribuie valori pentru argumentele (argc( si (argv(.

66666666666666666666666666666666666666666666666666666
Hucrul cu sirurile din biblioteca standard
66666666666666666666666666666666666666666666666666666
Iiblioteca standard Dstring.*@ contine multe functii utile pentru lucrul cu siruri de caractere.
,irurile ce sunt argumente trebuie terminate cu PF/P si toate returneaza un intreg sau o valoare a unui
pointer catre (c*ar(.
Cateva functii utile pentru lucrul cu siruri de caractere
666666666666666666666666666666666666666666666666666666666666666666
6 c*ar Jstrcat%c*ar Js1, const c*ar Js2&7
"unctia primeste doua argumente, le concateneaza si pune rezultatul in (s1(. 2rogramatorul
trebuie sa verifice daca (s1( are suficient spatiu pentru pastrarea rezultatului. ,e returneaza sirul
(s1(.
6 int strcmp%const c*ar Js1, const c*ar Js2&7
,unt trimise doua siruri de caractere si se returneaza un intreg care este mai mic strict, egal
sau mai mare strict
decat / dupa cum (s1( este mai mic, egal sau mai mare lexicografic decat (s2(.
6 c*ar JstrcpM%c*ar Js1, const c*ar Js2&7
,irul (s2( este copiat in (s1( pana cand se intalneste PF/P. Ceea ce se gaseste in (s1( se
suprascrie. ,e presupune ca (s1(
are suficient spatiu pentru pastrarea rezultatului. ,e returneaza valoarea lui (s1(.
6 unsigned strlen%const c*ar Js&7
2astreaza numarul de caractere inaintea lui PF/P.
6666666666666666666666666666666666666666666666666666666666666666
?ceste functii sunt scrise in C si sunt foarte scurte. Variabilele din ele sunt de obicei declarate
(register( pentru a face executia
mai rapida.

6666666666
.xemplu5 "unctia (strlen%&( %o varianta&.
6666666666
unsigned strlen%const c*ar Js&
E
register int n 1 /7

for % 7 Js S1 PF/P7 LLs&
LLn7
return n7
G
66666666666666666666666666666666666666666666666666666666666
B 8eclaratii si initializari B
66666666666666666666666666666666666666666666666666666666666
B c*ar s1NO 1 (tara noastra frumoasa si bogata(, B
B s2NO 1 (facultatea de informatica(7 B
66666666666666666666666666666666666666666666666666666666666
B .xpresie B Valoare B
66666666666666666666666666666666666666666666666666666666666
B strlen%s1& B 31 B
B strlen%s2 L +& B 1' B
B strcmp%s1, s2& B numar pozitiv B
66666666666666666666666666666666666666666666666666666666666
B nstructiune B Ce se va tipari ? B
66666666666666666666666666666666666666666666666666666666666
B printf%(Ks(, s1 L 13&7 B frumoasa si bogata B
B strcpM%s2 L 11, s1 L 2!&7B B
B strcat%s2, (Fn(&7 B B
B printf%(Ks(, s2&7 B facultatea bogata B
66666666666666666666666666666666666666666666666666666666666

6666666666666666666666666
Unde este eroarea ?
6666666666666666666666666
1. c*ar sN14O7
strcpM%s, (Ce mai faci ?Fn(&7
2. c*ar sN14O7
scanf%(Ks(, Rs&7

66666666666666666666666666666666666666666666666
.xercitii propuse spre implementare
66666666666666666666666666666666666666666666666
1. "olosind (argc( si (argv( %si eventual optiunea 6c& tipariti cu litere ma<uscule argumentele din
(argv(.
2. ,crieti o functie proprie (strncmp%&( %extrageti din [elp definitia si prototipul&.
3. 2resupunem ca avem declaratia si initializarea5
c*ar JpN2ON3O 1 E
(abc(, (defg(, (*i(, (<3lmno(, (pZrstuv)(, (xMz(
G7
Completati urmatorul tabel %incercati intai sa nu rulati programul C&.
66666666666666666666666666666666666666666666666666666666666666666
B .xpresie B .xpresie ec*ivalenta B Valoare B
6666666666666666666666666666666666666666666666666666666666666666
B JJJp B pN/ON/ON/O B PaP B
B JJpN1O B B B
B JJ%pN1O L 2& B B B
BJ%J%p L 1& L 1&N'O B B eroare B
B%J%J%p L 1& L 1&&N'OB B B
B J%pN1ON2O L 2& B B B
66666666666666666666666666666666666666666666666666666666666666666
4. "olosind (scanf%&( cititi ' siruri de caractere, dupa care folosind (strcmp%&( sortati6le alfabetic
%eventual cu (bubble sort(&.
!. %J& ,crieti un program similar cu exercitiul 4 care sorteaza si afiseaza argumentele din linia de
comanda.
8irective preprocesor si metodologie de programare
11.1. "olosirea lui #include
11.2. "olosirea lui #define
11.3. ,intaxa (dulce(
11.4. ;acrouri cu argumente
11.!. Unde este greseala ?
11.$. 8efinitii de tipuri si macrouri din Dstddef.*@
11.'. ,ortare folosind (Zsort%&(
11.+. Un exemplu de utilizare a macrourilor cu argumente
11.-. Compilare conditionala
11.1/. ;acrouri predefinite
11.11. 4peratorii # si ##
11.12. ;acroul (assert%&(
11.13. "olosirea lui #error si #pragma
11.14. =umerele liniilor unui program
11.1!. .xercitii propuse spre implementare

111111111
Capitolul 11
111111111

111111111111111111111111111111111111111
8irective preprocesor si metodologie de programare
111111111111111111111111111111111111111
666666666666666666666666666
"olosirea lui #include
666666666666666666666666666
?m discutat de<a folosirea directivelor de preprocesare
#include Dstdio.*@
#include Dstdlib.*@
4 alta forma pentru #include este
#include (numeCfisier(
2reprocesorul va inlocui aceasta linie cu o copie a fisierului precizat. ;ai intai cautarea se face in
directorul curent, apoi
in alte locuri dependente de sistem. 8aca directiva este de forma
#include DnumeCfisier@
atunci preprocesorul va cauta in alte locuri %deci nu in directorul curent&. 8e exemplu, sub U=>,
fisierele *eader standard %cum ar fi (stdio.*(, (stdlib.*(& se gasesc de obicei in directorul
:usr:include
,ub ;,684,, aceste fisiere se gasesc in directorul
:include

66666666666666666666666666
"olosirea lui #define
66666666666666666666666666
8irectivele de preprocesare declarate cu (#define( au doua forme5
6 #define identificator sirCatomi
6 #define identificator%id,...,id& sirCatomi
4 definitie lunga %care nu dorim sa o scriem pe aceeasi linie poate fi continuata pe linia urmatoare
punand un F %bac3slas*& la sfarsitul liniei curente&. n primul caz, compilatorul va inlocui fiecare
aparitie a (identificatorului( prin (sirCatomi( in restul fisierului %de la pozitia curenta in <os& cu
exceptia celor care sunt incadrate intre g*ilimele sau apostroafe.
66666666666
.xemple5
66666666666
#define =0C,.CC2.CU %$/ J $/ J 24&
#define 2 3.141!-2$!3
#define C 2--'-2.4!+ :J viteza luminii in 3m:sec J:
#define .4" %61& :J valoarea uzuala pt sfarsit de fisier J:
#define ;?>=9 214'4+3$4' :J numarul intreg maxim pe 4 octeti J:
#define 8;.=, 2!/ :J dimensiunea unui sir J:
#define .2,H4= 1./e6- :J limita numerica J:
8eci, folosirea lui (#define( mareste claritatea si portabilitatea unui program.

66666666666666666666
,intaxa (dulce(
66666666666666666666
,e foloseste pentru evitarea unor greseli frecvente sau ca un moft.
666666666666
.xemplu5 #define .] 11
666666666666
?ceasta declaratie a<uta programatorul sa nu mai confunde 1 cu 11.
666666666666
.xemplu5 #define do :J spatiu J:
666666666666
8e exemplu, acum putem simula instructiunea ()*ile( din C ca un ()*ile do( din 2ascal sau
?lgol.
8e exemplu, daca avem definitiile de sintaxa (dulce( de mai sus, putem spune ca instructiunile
)*ile %i .] 1& do
E
. . . . .
G
si
)*ile %i 11 1&
E
. . . . .
G
sunt ec*ivalente.

666666666666666666666666666666
;acrouri cu argumente
666666666666666666666666666666
0evenim la forma a doua a macrourilor cu argumente5
#define identificator%id,...,id& sirCatomi
666666666666
.xemplu5 #define ,]%x& %%x& J %x&&
666666666666
dentificatorul x din #define este un parametru care va fi substituit in textul ce urmeaza. ,ubstitutia
se face fara considerarea
corectitudinii sintactice. 8e exemplu,
,]%' L )& este ec*ivalent cu %%' L )& J %' L )&&
ntr6o maniera similara,
,]%,]%Jp&& este ec*ivalent cu %%%%Jp& J %Jp&&& J %%%Jp& J %Jp&&&&
4bservati deci ca folosirea parantezelor %de exemplu, %x&& are o importanta deosebita, altfel nu s6ar
respecta ordinea de evaluare.

6666666666666666666666666
Unde este greseala ? #define ,]%x& %%x& J %x&&7
6666666666666666666666666
;acrourile sunt folosite de obicei pentru a inlocui apelurile functiilor cu cod liniar %scurte si fara
variabile suplimentare&.
66666666666
.xemplu5 ;acroul de mai <os defineste minimul a doua valori5
66666666666
#define min%x, M& %%%x& D %M&& ? %x& 5 %M&&
8upa aceasta definitie, o expresie de forma
m 1 min%u, v&
se poate expanda de catre preprocesor la
m 1 %%%u& D %v&& ? %u& 5 %v&&
"olosind aceasta definitie, putem defini minimul a patru valori, astfel
#define min4%a, b, c, d& min%min%a,b&, min%c, d&&
4 macro6definitie poate folosi functii si macrouri in corpul lor.

66666666666
.xemple5
66666666666
#define ,]%x& %%x& J %x&&
#define CUI%x& %,]%x& J %x&&
#define "C24Y%x& sZrt%sZrt%CUI%x&&&
4 directiva de preprocesare de forma
#undef identificator
va anula definitia precedenta a identificatorului.

666666666666666666666666666666666666666666666666666666666
8efinitii de tipuri si macrouri din Dstddef.*@
666666666666666666666666666666666666666666666666666666666
C pune la dispozitie facilitatea (tMpedef( pentru a asocia %redenumi& un tip cu unul specific.
66666666666
.xemplu5 tMpedef c*ar uppercase7
66666666666
8eclaratia de mai sus face tipul (uppercase( sinonim cu (c*ar(. 8e exemplu, declaratiile de mai <os
sunt valide5
uppercase c, uN1//O7
"isierul *eader Dstddef.*@ contine cateva definitii de tip5
tMpedef int ptrdiffCt7 :J tip intors de diferenta pointerilor J:
tMpedef s*ort )c*arCt7 :J tip caracter mare J:
tMpedef unsigned sizeCt7 :J tipul sizeof J:
9ipul (ptrdiffCt( spune care este tipul returnat de o expresie implicata in diferenta a doi pointeri. n
;,684,, acesta depinde de modelul de memorie ales %tinM, s*ort, large, far, *uge&, pe cand in
U=>, tipul folosit este (int(.
9ipul ()c*arCt( se foloseste pentru acele caractere care nu se pot reprezenta pe un octet %c*ar 6@
int&.
0eamintim ca operatorul (sizeof( este folosit pentru determinarea lungimii unui tip sau a unei
expresii. 8e exemplu, (sizeof%double& 1 +(. 9ipul (sizeCt( este returnat de operatorul (sizeof(.
Un macrou definit in Dstddef.*@ este
#define =UHH /

666666666666666666666666666666666
,ortare folosind (Zsort%&(
666666666666666666666666666666666
8aca avem o multime relativ mica de elemente, atunci putem sa folosim sortare cu bule sau metoda
sortarii prin selectie directa %care sunt de ordinul 4%nA2&&. 8aca insa avem multe elemente, atunci
este convenabil sa folosim metoda sortarii rapide %(Zuic3 sort(&. 2rototipul functiei (Zsort%&( se
gaseste in Dstdlib.*@. ?cesta este
void Zsort%void JarraM, sizeCt nCels, sizeCt elCsize, int compare%const void J, const void J&&7
?rgumentele acestei functii au rolul5
arraM 6 sirul care va fi sortat7
nCels 6 numarul de elemente ale sirului7
elCsize 6 numarul de octeti necesar memorarii unui element7
compare 6 functia de comparare, ce se declara ca fiind int compare%const void J, const void
J&
"unctia de comparare are ca argumente doi pointeri catre void. ?ceasta returneaza un intreg care
este mai mic, egal sau mai mare
decat zero dupa cum primul argument este mai mic, egal sau mai mare decat al doilea argument.

66666666666
.xemplu5
66666666666
Vom scrie un program ce foloseste (Zsort%&(. nitializam un vector, il tiparim, il sortam cu
(Zsort%&(, apoi il tiparim din nou.

#include Dstdio.*@
#include Dstdlib.*@
#include Dtime.*@
#define = 11 :J dimensiunea sirului J:

int cmp%const void Jvp, const void JvZ&7 :J functia de comparare J:
void init%double Ja, int n&7
void tiparesteCsir%double Ja, int n&7
void main%&
E
double aN=O7
init%a, =&7
tiparesteCsir%a, =&7
Zsort%a, =, sizeof%double&, cmp&7
tiparesteCsir%a, =&7
G
int cmp%const void Jvp, const void JvZ&
E
const double Jp 1 %const double J&vp7
const double JZ 1 %const double J&vZ7
double diff 1 Jp 6 JZ7
return %%diff @1 /./& ? %%diff @ /./& ? 61 5 /& 5 L1&7
G
void init%double Ja, int n&
E
int i7
srand%time%=UHH&&7 :J vezi rand%& J:
for %i 1 /7 i D n7 LLi&
aNiO 1 %rand%& K 1//1& : 1/./7
G
void tiparesteCsir%double Ja, int n&
E
int i7
for %i 1 /7 i D n7 LLi&
E
if %i K $ 11 /&
putc*ar%PFnP&7
printf%(K12.1f(, aNiO&7
G
putc*ar%PFnP&7
G
6666666666
ntrebari5 1. Ce trebuie sa modificati pentru a obtine ordinea crescatoare a sirului ?
6666666666 2. Ce rol are (const( din declaratia lui (cmp%&( ?

6666666666666666666666666666666666666666666666666666666666666666666
Un exemplu de utilizare a macrourilor cu argumente
6666666666666666666666666666666666666666666666666666666666666666666
Vom relua problema de mai sus, dar vom folosi macrouri cu argumente. Vom scrie programul in
doua fisiere, un fisier *eader (sort.*( si un fisier (sort.c(. "isierul *eader va contine directive de
precompilare %#include, #define&, precum si prototipuri pentru functiile noastre. "isierul (sort.*(
este5

#include Dstdio.*@
#include Dstdlib.*@
#include Dstring.*@
#include Dtime.*@
#define ; 32
#define = 11
#define parteCfractionara%x& %x 6 %int& x&
#define caracterCaleator%& %rand%& K 2$ L PaP&
#define realCaleator%& %rand%& K 1// : 1/./&
#define =9%arraM, sz, tMpe& F
if %strcmp%tMpe, (c*ar(& 11 /& F
for %i 1 /7 i D sz7 LLi& F
arraMNiO 1 caracterCaleator%&7 F
else F
for %i 1 /7 i D sz7 LLi& F
arraMNiO 1 realCaleator%&7

#define 20=9%arraM, sz, sirCcontrol& F
for %i 1 /7 i D sz7 LLi& F
printf%sirCcontrol, arraMNiO&7 F
putc*ar%PFnP&

int comparaCparteaCfractionara%const void J, const void J&7
int lexico%const void J, const void J&7

?cum, vom scrie restul codului pentru programul nostru, si anume fisierul (sort.c(.
#include (sort.*(

void main%&
E
c*ar aN;O7
float bN=O7
int i7
srand%time%=UHH&&7
=9%a, ;, (c*ar(&7
20=9%a, ;, (K62c(&7
Zsort%a, ;, sizeof%c*ar&, lexico&7
20=9%a, ;, (K62c(&7
printf%(666Fn(&7
=9%b, =, (float(&7
20=9%b, =, (K6$.1f(&7
Zsort%b, =, sizeof%float&, comparaCparteaCfractionara&7
20=9%b, =, (K6$.1f(&7
G

int comparaCparteaCfractionara%const void Jvp, const void JvZ&
E
const float Jp 1 %const float J&vp, JZ 1 %const float J&vZ7
float x7
x 1 parteCfractionara%Jp& 6 parteCfractionara%JZ&7
return%%x D /./& ? 61 5 %x 11 /./& ? / 5 L1&7
G

int lexico%const void Jvp, const void JvZ&
E
const c*ar Jp 1 %const c*ar J&vp, JZ 1 %const c*ar J&vZ7
return%Jp 6 JZ&7
G

666666666666666666666666666666
Compilare conditionata
666666666666666666666666666666
2reprocesorul are directive pentru compilare conditionata. ?cestea pot fi folosite pentru
dezvoltarea programelor si pentru scrierea
codului mai portabil de la o masina la alta. "iecare directiva de forma
#if expresieCintegralaCconstanta
#ifdef identificator
#ifndef identificator
implica compilarea conditionata a codului care urmeaza pana la directiva de precompilare
#endif
2entru compilarea codului de mai sus, in cazul lui #if trebuie ca expresia constanta sa fie diferita de
zero %true&, in cazul lui
#ifdef sau #ifdefined numele identificatorului trebuie sa fie definit anterior intr6o linie #define, fara
interventia directivei
#undef identificator
n cazul lui #ifndef, numele identificatorului trebuie sa nu fie curent definit.
.xpresia constanta integrala folosita intr6o directiva de precompilare nu poate contine operatorul
(sizeof( sau un cast. 2oate
insa, folosi operatorul de precompilare (defined( %valabil in ?=, C, dar nu si C traditional&.
.xpresia
defined identificator
este ec*ivalenta cu
defined%identificator&
?cesta se evalueaza la 1 daca identificatorul este definit, si / in caz contrar.

666666666666
.xemplu5
666666666666
#if defined%[2-///& BB defined%,U=4& RR Sdefined%V?>&
. . . . . :J cod dependent de masina J:
#endif

Uneori (printf%&( este utila in scopuri de depanare. 2resupunem ca la inceputul unui fisier am scris
#define 8.IUQ 1
si in unele zone ale programului am scris
#if 8.IUQ
printf%(debug5 a 1 KdFn(, a&7
#endif
8aca dupa ce ne6am convins ca este bine ce se intampla si vrem sa nu mai vizualizam valoarea lui
(a( in acest moment, atunci sc*imbam 8.IUQ in / %de exemplu&.
4 alta varianta ar fi sa nu initializam 8.IUQ. ,criem deci la inceputul fisierului
#define 8.IUQ
2utem folosi #ifdef si #if si scriem5
#ifdef 8.IUQ
. . . . .
#endif

666666666666666666666666666
;acrouri predefinite
666666666666666666666666666
n ?=, C sunt ! macrouri predefinite. =u pot fi redefinite de catre programator. .le au la inceput
si sfarsit cate doua simboluri
(underscore(.
;acro predefinit Valoare
6666666666666666666666666666666666666666666666666666666666666666
CC8?9.CC Un sir ce contine data curenta
CC"H.CC Un sir ce contine numele fisierului
CCH=.CC Un intreg reprezentand numarul liniei curente
CC,98CCC 8aca implementarea1?=, C, atunci acesta
reprezinta un numar diferit de zero
CC9;.CC Un sir ce contine timpul curent
6666666666666666666666666666666666666666666666666666666666666666

6666666666666666666666
4peratorii # si ##
6666666666666666666666
4peratorii de preprocesare # si ## sunt valabili in ?=, C, dar nu si in C traditional. 4peratorul
unar # cauzeaza transformarea in sir a unui parametru formal dintr6o macro6definitie.
#define mesa<Cpentru%a, b& F
printf%#a ( si ( #b (5 9e iubim SFn(&
void main%& E mesa<Cpentru%Carolina, =icoleta&7 G

Ha apelul acestui macrou, fiecare parametru al acestuia este inlocuit cu argumentul corespunzator,
iar # cauzeaza ca argumentele sa fie puse intre g*ilimele. ?ltfel spus, dupa preprocesare, in
memorie se obtine5
void main%& E printf%(Carolina( ( si ( (=icoleta( (5 9e iubim SFn(&7 G
8eoarece sirurile constante separate prin spatiu se concateneaza, instructiunea de mai sus este
ec*ivalenta cu5
void main%& E printf%(Carolina si =icoleta5 9e iubim SFn(&7 G
4peratorul binar ## este folosit la impartirea in to3enuri lexicale.

666666666666
.xemplu5
666666666666 #define >%i& x ## i
>%1& 1 >%2& 1 >%3&7
va deveni dupa preprocesare
x1 1 x2 1 x37

6666666666666666666666666
;acroul (assert%&(
666666666666666666666666
?=, C pune la dispozitie macroul (assert%&( din biblioteca standard (assert.*(. ?cest macrou
poate fi folosit cand vrem sa ne asiguram ca o expresie are o anumita valoare. Vrem sa scriem o
functie ale carei argumente satisfaca niste conditii.
66666666666
.xemplu5
66666666666
#include Dassert.*@
void f%c*ar Jp, int n&
E
. . . . .
assert%2 S1 =UHH&7
assert%n @ / RR n D !&7
. . . . .
G

8aca vreo asertiune esueaza, atunci sistemul va tipari un mesa< si va opri executia programului.
ata o implementare posibila a lui
(assert%&(.
#if defined%=8.IUQ&
#define assert%ignore& %%void& /& :J ignorare J:
#else
#define assert%expr&
if %S%expr&& F
E F
printf%(FnKsKsFnKsKsFnKsKdFnFn, F
(?ssertion failed5 (, #expr, F
(in file (, CC"H.CC, F
(al line (, CCH=.CC&7 F
G
#endif
8e remarcat ca daca =8.IUQ este definit, atunci sunt ignorate toate asertiunile. ?ceasta permite
programatorului in timpul scrierii programului sa verifice pas cu pas executia programului. "unctia
(abort%&( se gaseste in biblioteca standard.

6666666666666666666666666666666666666666
"olosirea lui #error si #pragma
6666666666666666666666666666666666666666
?=, C contine si directivele de preprocesare #error si #pragma.
666666666666
.xemplu5
666666666666
#if ?C,U. D IC,U.
#error (tipuri incompatibile(
#endif
8aca in timpul compilarii va apare o eroare prezenta intr6o directiva #error, atunci se va afisa
mesa<ul respectiv.
8irectiva #pragma se foloseste pentru folosire specifica implementarii. .a are forma generala5
#pragma atomiClexicali
?ceasta cauzeaza o comportare ce depinde de fiecare compilator C in parte.

6666666666666666666666666666666666666666
=umerele liniilor unui program
6666666666666666666666666666666666666666
4 directiva de preprocesare de forma
#line constantaCintegrala (numeCfisier(
va determina compilatorul sa renumeroteze liniile textului sursa astfel incat urmatoarea linie sa aiba
valoarea specificata si numele
fisierului sursa curent este (numeCfisier(. 8aca nu se precizeaza (numeCfisier(, atunci se va face
doar numerotarea liniilor. Iineinteles, numerele asociate liniilor sunt ascunse pentru programator si
apar numai la mesa<e de eroare sau avertismente.

66666666666666666666666666666666666666666666666
.xercitii propuse spre implementare
6666666666666666666666666666666666666666666666
1. ,crieti propria voastra functie (Zuic3sort%&( care sa fie ec*ivalenta cu (Zsort%&( pus la dispozitie
de sistemul C.
2. 8efiniti o macro6definitie pentru >40%&, numita (sau exclusiv(. Un apel >40%a,b&1true D1@ a
este true si b false, sau a false si b true. ,crieti si o macro6definitie >40%a,b,c& si una >40%a,b,c,d&.
3. ,crieti un program C in care sa afisati valorile celor ! macrouri predefinite.
0ecursie
12.1. ;anipularea sirurilor folosind recursia
12.2. ;etodologia (divide6et6impera(
12.3. .xercitii propuse spre implementare


111111111111
Capitolul 12
111111111111

11111111
0ecursie
11111111
4 functie este recursiva daca se autoapeleaza, direct sau indirect. n C toate functiile se pot defini
recursiv.
6666666666
.xemplu5
6666666666
#include Dstdio.*@
void numara%int n&7

void main%&
E
numara%1/&7
G

void numara%int n&
E
if %n&
E
printf%(Kd S (, n&7
numara%n 6 1&7
G
else
printf%(Qata SFn(&7
G

8upa executia acestui program, pe ecran se va tipari
1/ S - S + S ' S $ S ! S 4 S 3 S 2 S 1 S
Qata S
?cest program s6ar fi putut realiza si iterativ %folosind o instructiune de tip )*ile&.

66666666666
.xemplu5 ,uma primelor n numere naturale.
66666666666
int suma%int n&
E
if %n D1 1&
return n7
else
return %n L suma%n 6 1&&7
G

8e obicei, functiile recursive urmeaza un (pattern( standard5
6 exista un caz de baza %sau mai multe&7
6 caz recursiv general %in care, in general, un intreg este trimis ca argument al apelului recursiv&7

0ecursia este un procedeu foarte puternic de rezolvare a problemelor. ,ecretul este identificarea
cazului general.
2entru exemplul precedent, cand se trimite n catre functia (suma%&(, recursia activeaza n copii ale
functiei inaintea intoarcerii pas cu pas catre primul apel recursiv %se mai spune ca in momentul
apelului recursiv, variabilele locale (ing*eata(, ele (dezg*etandu6se( la intoarcerea din recursie&.
;ulte functii recursive se pot scrie intr6o forma iterativa %folosind structuri de tip ()*ile(, se mai
spune (derecursivare(&. 0ecursia se recomanda cand problema se poate rezolva foarte usor folosind
recursie si cand nu se cere o eficienta sporita in timpul executiei programului. Uneori, se recomanda
recursia finala %adica dupa apelul recursiv nu mai sunt alte instructiuni si nu exista variabile locale&.

66666666666
.xemplu5 Citeste o linie si o afiseaza in ordine inversa, apoi lasa
66666666666 doua randuri goale.

#include Dstdio.*@
void tipareste%void&7

void main%&
E
printf%(ntroduceti o linie5 (&7
tipareste%&7
printf%(FnFn(&7
G

void tipareste%void&
E
c*ar c7
if %%c 1 getc*ar%&& S1 PFnP&
tipareste%&7
putc*ar%c&7
G

ata o rulare in executie5
ntroduceti o linie5 iepurasu usa rupei

iepur asu usarupei
4bservati in exemplul precedent ca la fiecare apel recursiv, se memoreaza in stiva caracterul (c(
legat la o valoare, care se va afisa la intoarcerea din recursie. 8eci practic, sunt (n( copii ale lui (c(,
unde (n( reprezinta lungimea liniei.

66666666666
.xemplu5
66666666666
2utem complica putin exemplul precedent, in sensul ca afisam aceleasi cuvinte, dar in ordine
inversa.
#include DctMpe.*@
#include Dstdio.*@

#define ;?>Y408 1//

void tiparesteCcuvinte%void&7
void citesteCcuvant%c*ar J&7

void main%&
E
printf%(ntroduceti o linie5 (&7
tiparesteCcuvinte%&7
printf%(FnFn(&7
G

void tiparesteCcuvinte%void&
E
c*ar )N;?>Y408O7

citesteCcuvant%)&7
if %)N/O S1 PFnP&
tiparesteCcuvant%&7
printf%(Ks (, )&7
G

void citesteCcuvant%c*ar Js&
E
static c*ar c 1 PF/P7

if %c 11 PFnP&
JsLL 1 c7
else
)*ile %Sisspace%c 1 getc*ar%&&&
JsLL 1 c7
Js 1 PF/P7
G

8aca, la executie, utilizatorul scrie5
ntroduceti o linie5 noi invatam C
atunci pe ecran, va apare5
C invatam noi
Variabila (c( avand clasa de memorare (static(, rezulta ca valoarea ei se pastreaza de la un apel la
altul. 8e altfel, initializarea lui (c( se face o singura data %cand se intra prima data in aceasta
functie&. 8aca (c( ar fi fost de tip (auto(, atunci c*iar daca aveam la sfarsitul sirului PFnP, la
urmatorul apel, acesta nu ar fi fost cunoscut, deci practic nu mai aveam conditie de oprire.

66666666666
.xemplu5
66666666666
n acest exemplu, vom desena (pattern6uri( pe ecran folosind functii recursive.
#include Dstdio.*@
#define ,^;I4H PJP
#define 4"",.9 /
#define H.=Q9[ 1-

void displaM%c*ar, int, int&7
void dra)%c*ar, int&7

void main%&
E
displaM%,^;I4H, 4"",.9, H.=Q9[&7
G

void displaM%c*ar c, int m, int n&
E
if %n @ /&
E
dra)%P P, m&7
dra)%c, n&7
putc*ar%PFnP&7
displaM%c, m L 2, n 6 4&7
G
G

void dra)%c*ar c, int 3&
E
if %3 @ /&
E
putc*ar%c&7
dra)%c, 3 6 1&7
G
G

"unctia (main%&( contine apelul functiei (displaM%&(, care apeleaza (dra)%&(, care la randul ei
apeleaza (displaM%&(. 8eci functia
(displaM%&( este recursiva. "unctia (dra)%&( tipareste 3 copii ale caracterului (c(. 2e ecran se va
afisa5
J J J J J J J J J J J J J J J J J J J
J J J J J J J J J J J J J J J
J J J J J J J J J J J
J J J J J J J
J J J

6666666666666666666666666666666666666666666666666666
;anipularea sirurilor folosind recursia
6666666666666666666666666666666666666666666666666666
Un sir consta dintr6un numar de caractere consecutive, terminate prin caracterul PF/P. 8e fapt, putem
gandi un sir ca fiind sirul nul %care consta doar din caracterul PF/P& sau un caracter urmat de un sir.
?ceasta definitie a sirului este o structura de date recursiva.
66666666666
.xemplu5 4 definitie recursiva a lungimii unui sir.
66666666666
int rCstrlen%c*ar Js&
E
if %Js 11 PF/P&
return /7
else
return %1 L rCstrlen%s L 1&&7
G
.leganta acestei formulari recursive este (platita( de o pierdere in timpul executiei. 8aca sirul are
lungimea 3, calcularea lungimii sale necesita 3 L 1 apeluri recursive %un compilator optimizat poate
evita aceasta pierdere&.

666666666666666666666666666666666666666666
;etodologia (divide6et6impera(
66666666666666666666666666666666666666666
0ecursia se foloseste in foarte multe cazuri pentru codificarea algoritmilor (divide6et6impera(. Un
astfel de algoritm imparte problema in subprobleme, rezolvand fiecare subproblema prin recursie,
apoi recombina solutiile partiale pentru a obtine intreaga solutie.
Vom considera un exemplu cunoscut, si anume, determinarea minimului si maximului elementelor
unui sir de intregi %publicat pentru prima data de catre ra 2o*l, (? ,orting 2roblem and ts
ComplexitM(, Communications of t*e ?C;, 1!, nr. $, 1-'2& considerat cel mai bun algoritm pentru
aceasta problema. Criteriul pentru (cel mai bun( a fost numarul de comparatii necesare. 2rezentam
mai <os o functie C care rezolva aceasta problema %considerand dimensiunea sirului putere a lui 2&.
void minmax%int aNO, int n, int JminCptr, int JmaxCptr&
E
int min1, max1, min2, max27

if %n 11 2&
if %aN/O D aN1O&
E
JminCptr 1 aN/O7
JmaxCptr 1 aN1O7
G
else
E
JminCptr 1 aN1O7
JmaxCptr 1 aN/O7
G
else
E
minmax%a, n:2, Rmin1, Rmax1&7
minmax%a L n:2, n:2, Rmin2, Rmax2&7
if %min1 D min2&
JminCptr 1 min17
else
JminCptr 1 min27
if %max1 D max2&
JmaxCptr 1 max27
else
JmaxCptr 1 max17
G
G

66666666666666666666666666666666666666666666666
.xercitii propuse spre implementare
66666666666666666666666666666666666666666666666
1. ,crieti o functie C recursiva ec*ivalenta cu (strncmp%&(.
2. ,crieti o functie C recursiva care calculeaza media aritmetica a unui sir de numere reale.
3. ,crieti o functie C recursiva care calculeaza nS, unde n este un numar natural.
4. %;utarea calului& 8ata o tabla de sa* %+ x +&, sa se scrie o functie C recursiva care descrie
mutarile calului astfel incat orice pozitie sa fie parcursa o singura data.
,tructuri si liste inlantuite
13.1. 8eclararea structurilor
13.2. ?ccesarea unui membru
13.3. ?sociativitatea si precedenta operatorilor %tabelul complet&
13.4. ,tructuri, functii si asignari
13.!. nitializarea structurilor
13.$. "olosirea lui (tMpedef(
13.'. ,tructuri recursive %self6referential&
13.+. Histe liniar inlantuite
13.-. 4peratii pentru liste
13.1/. Crearea unei liste
13.11. =umarare si cautare
13.12. nserare si stergere
13.13. .xercitii propuse spre implementare


111111111
Capitolul 13
111111111

11111111111111111111
,tructuri si liste inlantuite
11111111111111111111
9ipul structura permite programatorului sa imbine mai multe componente intr6o singura variabila.
Componentele structurii au nume distincte si se numesc membrii. ;embrii unei structuri pot avea
tipuri diferite. 8eci, ca si pointerii si sirurile, structurile sunt considerate un tip derivat. ?ccesarea
membrilor unei structuri se face cu (.( sau cu (6@( care au cea mai inalta prioritate %ca si %& si NO&.

666666666666666666666666666666
8eclararea structurilor
666666666666666666666666666666
,e face folosind cuvantul rezervat (struct(. ata un exemplu de declarare a cartilor de <oc5
66666666666
.xemplu5 8eclaratia de mai <os creaza tipul de data (carteCdeC<oc(5
66666666666
struct carteCdeC<oc
E
int numar7
c*ar culoare7
G7
?stfel cartea 3 de trefla va avea (numar13( si (culoare1PtP(. Celelalte caractere pentru culorile
cartilor sunt %frunza 6 PfP, caro 6 PcP, inima 6 PiP&. =umele structurii poate fi folosit acum pentru
declararea variabilelor de acest tip. ?bia in acest moment se rezerva loc in memorie pentru aceste
variabile5
struct carteCdeC<oc c1, c27
2entru accesarea membrilor lui c1 si c2, folosim operatorul (.(.
666666666666
.xemplu5
666666666666
c1.numar 1 37
c1.culoare 1 PtP7
c2.numar 1 127
c2.culoare 1 PcP7
4 constructie de forma
variabilaCstructura . numeCmembru
este folosita ca o variabila in acelasi mod ca o simpla variabila sau ca un element al unui sir.
=umele unui membru trebuie sa fie unic intr6o structura specificata. 8in moment ce membrii
trebuie intotdeauna prefixati de un identificator de variabila de structura
unic, atunci nu vor fi confuzii %ambiguitati& intre doi membri cu acelasi nume, dar din structuri
diferite.
666666666666
.xemplu5
666666666666
struct fruct
E
c*ar numeN1!O7
int calorii7
G

struct leguma
E
c*ar numeN1!O7
int calorii7
G

struct fruct a7
struct leguma b7

2utem accesa (a.calorii(, respectiv (b.calorii( fara ambiguitate. 2utem declara variabile de un tip
structurat in timpul declararii acestuia.

666666666666
.xemplu5
666666666666
struct carteCdeC<oc
E
int numar7
c*ar culoare7
G c1, c2, c3N!2O7
dentificatorul (carteCdeC<oc( este numele structurii. dentificatorii (c1( si (c2( se declara ca fiind
variabile de tip (struct carteCdeC<oc(, iar identificatorul (c3( ca fiind un sir de tip (struct
carteCdeC<oc(. 8aca insa lipseste numele structurii, atunci singura data cand se pot declara variabile
de tip structura este in momentul declararii acesteia.

666666666666
.xemplu5
666666666666
struct
E
c*ar Jnume7
int nrCstudent7
float medie7
G s1, s2, s37
n aceasta structura se declara trei variabile de tip structura, insa lipsind numele structurii inseamna
ca nu se mai pot declara si alte
variabile de acest tip. 8aca, de exemplu, scriem
struct student
E
c*ar Jnume7
int nrCstudent7
float medie7
G7
atunci (student( este numele structurii si nu sunt variabile declarate in acest moment. ?cum putem
scrie
struct student temp, clasaN1//O7
si declaram (temp( si (clasa( de tip (struct student(.

6666666666666666666666666666666
?ccesarea unui membru
6666666666666666666666666666666
n cele ce urmeaza, prezentam un exemplu de folosire a operatorului de membru (.(.
666666666666
.xemplu5 n fisierul (clCinfo.*( scriem5
666666666666
#define =0C,9U8.=9 1//
struct student
E
c*ar Jnume7
int nrCstudent7
float medie7
G7
n alt fisier, scriem
#include (clCinfo.*(
void main%&
E
struct student temp, clasaN=0C,9U8.=9O7
. . . . .
G
2utem avea instructiuni de asignare cum ar fi5
temp.medie 1 4.//7
temp.nume 1 (onescu(7
temp.nrCstudent 1 1/237
n continuare, scriem o functie care numara studentii cu media 4.//5
int esec%struct student clasaNO&
E
int i, contor 1 /7

for %i 1 /7 i D =0C,9U8.=97 LLi&
contor L1 clasaNiO.medie 11 4.//7
return contor7
G
C pune la dispozitie operatorul pointer catre structura 6@ pentru accesarea membrilor unei structuri
relativ la un pointer %,imbolul 6@ este format din caracterul 6 %minus& si @ %mai mare&&. 8aca o
variabila pointer este asignata cu adresa unei structuri, atunci un membru al structurii poate fi
accesat printr6o constructie de forma5
pointerCcatreCstructura 6@ numeCmembru
Iineinteles, o constructie ec*ivalenta este5
%JpointerCcatreCstructura&.numeCmembru
2arantezele sunt necesare deoarece operatorii (.( si (6@( au prioritate mare si se asociaza de la
stanga la dreapta. ?stfel, parantezele sunt obligatorii, deoarece in caz contrar, daca in expresia de
mai sus nu ar fi fost paranteze, atunci aceasta ar fi ec*ivalenta cu
J%pointerCcatreCstructura.numeCmembru&

666666666666
.xemplu5 "ie urmatoarele declaratii si asignari5
666666666666
struct student temp, Jp 1 Rtemp7
temp.medie 1 1/.//7
temp.nume 1 (onescu(7
temp.nrCstudent 1 12/47
?tunci obtinem urmatorul tabel5
6666666666666666666666666666666666666666666666666666666666666666666666666666
B .xpresie B .xpresie ec*ivalenta B Valoare conceptuala B
6666666666666666666666666666666666666666666666666666666666666666666666666666
B temp.medie B p 6@ medie B 1/.// B
B temp.nume B p 6@ nume B onescu B
B temp.nrCstudent B p 6@ nrCstudent B 12/4 B
B %Jp&.nrCstudent B p 6@ nrCstudent B 12/4 B
6666666666666666666666666666666666666666666666666666666666666666666666666666

666666666666666666666666666666666666666666666666666666666666666666666666666
?sociativitatea si precedenta operatorilor %tabelul complet&
666666666666666666666666666666666666666666666666666666666666666666666666666
66666666666666666666666666666666666666666666666666666666666666666666666666666
B 4peratori B ?sociativitate B
66666666666666666666666666666666666666666666666666666666666666666666666666666
%& NO . 6@ LL %postfix& 66 %postfix& B de la stanga la dreapta B
66666666666666666666666666666666666666666666666666666666666666666666666666666
LL %prefix& 66 %prefix& S X sizeof %tip& B de la dreapta B
L %unar& 6 %unar& R %adresa& J %dereferentiere& B la stanga B
666666666666666666666666666666666666666666666666666666666666666666666666666666
J : K B de la stanga la dreapta B
666666666666666666666666666666666666666666666666666666666666666666666666666666
L 6 B de la stanga la dreapta B
666666666666666666666666666666666666666666666666666666666666666666666666666666
DD @@ B de la stanga la dreapta B
666666666666666666666666666666666666666666666666666666666666666666666666666666
D D1 @ @1 B de la stanga la dreapta B
666666666666666666666666666666666666666666666666666666666666666666666666666666
11 S1 B de la stanga la dreapta B
666666666666666666666666666666666666666666666666666666666666666666666666666666
R B de la stanga la dreapta B
666666666666666666666666666666666666666666666666666666666666666666666666666666
A B de la stanga la dreapta B
666666666666666666666666666666666666666666666666666666666666666666666666666666
B B de la stanga la dreapta B
666666666666666666666666666666666666666666666666666666666666666666666666666666
RR B de la stanga la dreapta B
666666666666666666666666666666666666666666666666666666666666666666666666666666
BB B de la stanga la dreapta B
666666666666666666666666666666666666666666666666666666666666666666666666666666
?5 B de la dreapta la stanga B
666666666666666666666666666666666666666666666666666666666666666666666666666666
1 L1 61 J1 :1 K1 @@1 DD1 R1 A1 B1 B de la dreapta la stanga B
666666666666666666666666666666666666666666666666666666666666666666666666666666
, %operatorul virgula& B de la stanga la dreapta B
666666666666666666666666666666666666666666666666666666666666666666666666666666
4peratorul (,( are cea mai mica prioritate dintre toti operatorii C. Virgula folosita in declaratii si in
lista de argumente ale functiilor nu este operator.
666666666666
.xemple5 .xpresia a 1 1, b 1 2 este o expresie virgula. ntai se evalueaza (a 1 1(, apoi (b 1 2(,
iar valoarea si tipul returnat de expresia virgula sunt cele returnate de (b 1 2(, adica valoarea (2( si
tipul (int(.

Un exemplu frecvent unde apare operatorul virgula este (for(. 8e exemplu,
for %i 1 /, < 1 17 i D H;97 i L1 2, < L12&
. . . . .
Va amintiti ca operatorul unar (sizeof( poate fi folosit pentru determinarea numarului de octeti
necesar memorarii sale. 8e exemplu, expresia sizeof%struct carteCdeC<oc& va intoarce numarul de
octeti necesari sistemului pentru memorarea unei variabile de tip (struct carteCdeC<oc(. 2e cele mai
multe sisteme tipul returnat de expresie este (unsigned(.

66666666666666666666666666666666666
,tructuri, functii si asignari
66666666666666666666666666666666666
C traditional permite unui pointer catre un tip structura sa fie transmis ca argument al unei functii si
returnat ca o valoare. ?=, C
permite c*iar unei structuri sa fie trimisa ca argument pentru functii si returnata ca valoare. 8e
exemplu, daca (a( si (b( sunt structuri, atunci expresia de asignare (a 1 b( este valida. ?ceasta
implica ca fiecare valoare a unui membru din structura (a( devine
egala cu valoarea membrului corespunzator din structura (b(.
n C, structurile, pointerii si vectorii pot fi combinati pentru crearea unor structuri de date
complicate.
66666666666
.xemplu5 Iaza de date cu studenti
66666666666
n fisierul (student.*(5

#define =0C,9U8.=9 !/
#define =0CCU0,U0 1/

struct student
E
c*ar Jnume7
int nrCstudent7
float medie7
G7

struct data
E
s*ort zi7
c*ar lunaN1/O7
s*ort an7
G7

struct persoana
E
c*ar numeN2/O7
struct data ziCnastere7
G7

struct dateCstudent
E
struct persoana p7
int nrCstudent7
float medieN=0CCU0,U0O7
G7
4bservati ca (struct dateCstudent( este construita cu structuri imbricate. 8e exemplu, daca avem
declaratia5
struct dateCstudent temp7
atunci expresia5
temp.p.ziCnastere.lunaN/O
are ca valoare prima litera a lunii datei de nastere a studentului asociat lui (temp(.
n continuare, vom scrie o functie (citesteCdate%&( pentru a introduce date in variabile de tip (struct
date(. Ha apelul functiei, trebuie trimisa adresa variabilei ca argument.
66666666666
.xemplu5
66666666666
#include (student.*(

void citesteCdate%struct data Jz&
E
printf%(8ati ziua%int& luna%string& an%int&5 (&7
scanf%(K*dKsK*d(, Rz 6@ zi, z 6@ luna, Rz 6@ an&7
G

"ormatul K*d este folosit pentru conversia caracterelor de la tastatura la o valoare de tip (s*ort(.

6666666666666
ntrebare5 8e ce (z 6@ luna( nu contine operatorul de adresa ?
6666666666666
"unctia (citesteCdate%&( poate fi folosita pentru citirea informatiei intr6o variabila de tip (struct
dateCstudent( astfel5

struct dateCstudent temp7

citesteCdate%Rtemp.p.ziCnastere&7


66666666666666666666666666666666
nitializarea structurilor
66666666666666666666666666666666
9oate variabilele externe si statice, inclusiv variabilele de structura, care nu sunt explicit
initializate, sunt automat initializate de catre sistem cu zero. n C traditional, structurile statice si
externe pot fi initializate de catre programator. n ?=, C, putem initializa si structuri definite
(auto(. ,intaxa este similara celei folosite la siruri. 4 variabila structura poate fi urmata de semnul
(1( si o lista de constante cuprinse intre acolade. 8aca nu sunt suficiente valori pentru asignarea lor,
atunci membrii ramasi sunt asignati cu zero implicit.
66666666666
.xemple5 struct carteCdeC<oc c 1 E12, PtPG7
66666666666 struct complex
E
double real7
double imaginar7
G mN3ON3O 1
E
EE1./, 6/.!G, E2.!, 1./G, E/.', /.'GG,
EE'./, 6$.!G, E6/.!,1.!G,E4!.',+./GG,
G7
,e observa imediat ca linia (mN2ONO( este initializata cu /.

666666666666666666666666666666
"olosirea lui (tMpedef(
666666666666666666666666666666
"acilitatea (tMpedef( este deseori folosita pentru redenumirea unui tip structura.
66666666666
.xemple5
66666666666
tMpedef c*ar J string7
tMpedef int lungime7
tMpedef float vectorN1/O7
tMpedef double %J2"8&%double&7
8upa aceste redenumiri, putem face declaratiile5
lungime l1, l27
string s1 1 (abc(, s2 1 (xMz(7
vector x7
?ceste declaratii sunt ec*ivalente cu5
int l1, l27
c*ar J s1 1 (abc(, s2 1 (xMz(7
float xN1/O7 :J ?tentie S ,e inlocuieste vector cu x J:
Ha fel, declaratia
2"8 f7
este ec*ivalenta cu
double %Jf&%double&7
.ste vorba mai sus de un pointer la o functie ce returneaza tipul (double(.

6666666666666666666666666666666666666666666666
,tructuri recursive %self6referential&
6666666666666666666666666666666666666666666666
4 structura este recursiva daca un membru pointer se refera la tipul structurii initiale %recursie de
ordinul 1, exista si ordine mai
mari&. 8e obicei, structurile recursive necesita rutine explicite pentru rezervarea si eliberarea de
memorie.
666666666666
.xemplu5
666666666666
struct lista
E
int data7
struct lista Jurmator7
G
"iecare variabila de tip (struct lista( are doi membri, (data( si (urmator(. 2ictural, asta arata cam
asa %in memorie&5
66666666666666
B B 6666B66@
66666666666666
data urmator
Variabila pointer (urmator( contine o adresa a unei locatii de memorie a unui element succesor
(struct lista( sau valoarea speciala
=UHH, definita in Dstdio.*@ ca avand valoarea constanta /. Valoarea =UHH este folosita pentru
notarea sfarsitului listei.
2resupunem ca avem declaratiile
struct lista a, b, c7
Vrem sa creeam o lista inlantuita formata din aceste trei variabile. ;ai intai, facem asignarile5
a.data 1 17
b.data 1 27
c.data 1 37
a.urmator 1 b.urmator 1 c.urmator 1 =UHH7
8upa aceste instructiuni, obtinem in memorie5
a b c
6666666666666666 6666666666666666 6666666666666666
B 1 B =UHH B B 2 B =UHH B B 3 B =UHH B
6666666666666666 6666666666666666 6666666666666666
data urmator data urmator data urmator

?cum putem (lega( cele trei structuri, astfel5
a.urmator 1 Rb7
b.urmator 1 Rc7

4btinem5
a b c
66666666666666 66666666666666 6666666666666666
B 1 B 666B6666@B 2 B 666B6666@B 3 B =UHH B
66666666666666 66666666666666 6666666666666666
data urmator data urmator data urmator

6666666666666666666666666666
Histe liniar inlantuite
6666666666666666666666666666
4 lista liniar inlantuita este o structura de date ce are elementele legate secvential. .xista un pointer
catre primul element al listei,
fiecare element al listei pointeaza catre urmatorul element al listei, avand ultimul element pointand
catre =UHH. 8e obicei, o lista
inlantuita se creaza dinamic.
,criem in fisierul (*eader( intitulat (list.*( urmatoarele declaratii5
#include Dstdio.*@
tMpedef c*ar 8?9?7

struct listaCinlantuita
E
8?9? d7
struct listaCinlantuita Jnext7
G7

tMpedef struct listaCinlantuita .H.;.=97
tMpedef .H.;.=9 J H,9?7

0elativ la alocarea dinamica, va reamintim ca functia (malloc%&( are un singur argument de tip
(sizeCt( si intoarce un pointer catre
(void( care pointeaza catre adresa de baza a spatiului de memorie alocat %evident, cauta spatiu
suficient pentru un obiect&. ?stfel,
daca (*ead( este o variabila de tip (H,9?(, atunci
*ead 1 %H,9?& malloc%sizeof%.H.;.=9&&7
va produce o bucata din memorie menita sa memoreze un .H.;.=9 asignand adresa de baza
pointerului (*ead(.

666666666666
.xemplu5
666666666666
2resupunem ca vrem sa creeam dinamic o lista liniar inlantuita pentru memorarea a trei caractere
PnP, PeP si P)P. Considerand
*ead 1 %H,9?& malloc%sizeof%.H.;.=9&&7
*ead 6@ d 1 PnP7
*ead 6@ next 1 =UHH7
obtinem un memorie ceva de genul5
6666666666666666
*ead 666@B PnP B =UHH B
666666666666666
d next

?l doilea element este adaugat de instructiunile5
*ead 6@ next 1 %H,9?& malloc%sizeof%.H.;.=9&&7
*ead 6@ next 6@ d 1 PeP7
*ead 6@ next 6@ next 1 =UHH7
n memorie avem5
666666666666 666666666666666
*ead666@B PnP B 666B666@B PeP B =UHH B
666666666666 666666666666666
d next d next

n sfarsit, adaugam si al treilea element5
*ead 6@ next 6@ next 1 malloc%sizeof%.H.;.=9&&7
*ead 6@ next 6@ next 6@ d 1 P)P7
*ead 6@ next 6@ next 6@ next 1 =UHH7
n memorie avem5
66666666666666 66666666666666 6666666666666666
*ead666@B PnP B 666B666@B PeP B 666B666@B P)P B =UHH B
66666666666666 66666666666666 6666666666666666
d next d next d next


66666666666666666666666666
4peratii pentru liste
66666666666666666666666666
4peratiile de baza pentru liste liniar inlantuite includ urmatoarele5
1. Crearea unei liste
2. =umararea elementelor unei liste
3. Cautarea unui element
4. nserarea unui element
!. ,tergerea unui element
66666666666666666666666
Crearea unei liste
66666666666666666666666
Vom prezenta o varianta recursiva a acestei operatii, si anume vom crea o lista pornind de la un
string. "unctia va returna un pointer catre primul element al listei.
#include (list.*(

H,9? creare%c*ar sNO&
E
H,9? *ead7

if %sN/O 11 PF/P&
return =UHH7
else
E
*ead 1 %H,9?& malloc%sizeof%.H.;.=9&&7
*ead 6@ d 1 sN/O7
*ead 6@ next 1 creare%s L 1&7
return *ead7
G
G


66666666666666666666666666
=umarare si cautare
66666666666666666666666666
"unctia recursiva (numara%&( numara elementele unei liste parcurgand fiecare element pana
intalneste pointerul =UHH. 8aca lista este vida, atunci se intoarce /, altfel numarul de elemente al
listei.
#include (list.*(

int numara%H,9? *ead&
E
if %*ead 11 =UHH&
return /
else
return %1 L numara%*ead 6@ next&&7
G
"unctia recursiva (cauta%&( cauta intr6o lista un element. 8aca este gasit acel element, atunci se
intoarce un pointer catre acesta,
altfel se intoarce pointerul =UHH.
#include (list.*(

H,9? cauta%8?9? c, H,9? *ead&
E
if %*ead 11 =UHH&
return =UHH7
else
if %c 11 *ead 6@ d&
return *ead7
else
return %cauta%c, *ead 6@ next&&7
G

6666666666666666666666666
nserare si stergere
6666666666666666666666666
2ictural, asta ar arata cam asa %inainte de inserare&5

p1 66B p266B
B B
V V
66666666666666 66666666666666
... 666@B ? B 666B666@B C B 666B666@ ...
66666666666666 66666666666666
66666666666666666
Z 666@B I B =UHH B
66666666666666666
8upa inserare, obtinem5
66666666666666 66666666666666
... 666@B ? B B B B C B 666B666@ ...
6666666666B666 66666666666666
B A
6@6666666666B6666
Z 666@B I B B B
666666666666666
"unctia care face acest lucru este5
#include (list.*(
void insert%H,9? p1, H,9? p2, H,9? Z&
E
p1 6@ next 1 Z7
Z 6@ next 1 p27
G
,tergerea unui element intr6o lista liniar inlantuita este foarte simpla. 2ictural, avem5
p66B
B
V
66666666666666 66666666666666 66666666666666
... 666@B ? B 666B666@B I B 666B666@B C B 666B66@ ...
66666666666666 66666666666666 66666666666666
nstructiunea
Z 1 p 6@ next7
va implica pointarea lui Z catre obiectul care trebuie sters. 4btinem5
p66B Z66B
B B
V V
66666666666666 66666666666666 66666666666666
... 666@B ? B 666B666@B I B 666B666@B C B 666B66@ ...
66666666666666 66666666666666 66666666666666
Considerand instructiunea
p 6@ next 1 Z 6@ next7
se obtine in memorie
p66B Z66B
B B
V V
66666666666666 66666666666666 66666666666666
... 666@B ? B B B B I B 666B666@B C B 666B66@ ...
666666666B6666 666666666666666 66666666666666
B A
B B
6666666666666666666666666666666
,e observa ca elementul I este inaccesibil %adica nu mai apartine listei&, deci nu mai este folosit.
?cesta se mai numeste (garbage( %gunoi&. .vident ca ar fi bine pentru sistem daca s6ar putea elibera
aceasta locatie de memorie pentru a putea fi refolosita. .liberarea zonei de memorie se face cu
functia (free%&( din biblioteca standard. 8eci, (free%Z&( face disponibila pentru sistem locatia de
memorie catre care pointeaza (Z( care a fost alocata mai inainte cu (malloc%&( %sau (calloc%&(&. Cum
(free%&( are ca argument de tip pointer catre (void(, rezulta ca (Z( poate fi de orice tip.

n continuare, vom scrie o functie care sterge si elibereaza toate elementele unei liste.
#include (list.*(
void stergeClista%H,9? *ead&
E
if %*ead S1 =UHH&
E
stergeClista%*ead 6@ next&7
free%*ead&7
G
G

66666666666666666666666666666666666666666666666
.xercitii propuse spre implementare
66666666666666666666666666666666666666666666666
1. ,crieti un program C pentru simularea unui <oc de carti. ,a se faca o amestecare si o impartire a
cartilor la cei n <ucatori.
2. "olosind (tMpedef(, sa se scrie trei functii C care sa calculeze suma a doi vectori, produsul scalar
a doi vectori si inmultirea
matricelor.
3. %4peratii cu liste&
a& Concatenarea a doua liste7
b& 8eterminarea unei subliste ce contine primele 3 elemente dintr6o lista, cu eliberarea zonelor de
memorie ale restului elementelor.
4. ,a se oglindeasca o lista liniara inlantuita cu numar constant de variabile suplimentare fara a
folosi recursie.
!. ,a se sorteze n numere folosind liste liniar inlantuite si metoda interclasarii.
$. ,crieti un program C in care sa descrieti urmatoarele operatii pentru arbori binari5 creare,
numarare, cautare, stergere, inserare, parcurgere %preordine, inordine, postordine&.
'. ,crieti un program C in care sa descrieti aceleasi operatii de mai sus, dar pentru arbori generali
%idee5 folositi legaturi de tip fiu6frate&.
ntrari:iesiri si fisiere
14.1. "unctia de iesire (printf%&(
14.2. "unctia de intrare (scanf%&(
14.3. "unctiile (sprintf%&( si (sscanf%&(
14.4. "unctiile (fprintf%&( si (fscanf%&(
14.!. ?ccesarea fisierelor
14.$. ?ccesarea aleatoare a unui fisier
14.'. ,til de programare
14.+. .xercitii propuse spre implementare

1111111111
Capitolul 14
1111111111
1111111111111111
ntrari:iesiri si fisiere
1111111111111111
n acest capitol vom explica folosirea unor functii de intrare:iesire %printre care si (printf%&( si
(scanf%&(&. 8e asemenea vom arata modurile de desc*idere a fisierelor %pentru procesarea lor& si
cum se foloseste un pointer catre fisier.
66666666666666666666666666666666666
"unctia de iesire (printf%&(
66666666666666666666666666666666666
?re doua proprietati importante care permit o folosire flexibila la un nivel inalt5
6 poate fi tiparita o lista de argumente de lungime arbitrara7
6 afisarea este controlata de specificari de conversie simple %sau formate&.
"unctia (printf%&( primeste sirul de caractere din fisierul standard de iesire %stdout&, care este
normal conectat la ecran. Hista de
argumente a lui (printf%&( are doua parti5
sirulCdeCcontrol si celelalteCargumente
66666666666
.xemplu5 n cazul apelului5
66666666666
printf%(2rodusul Kd Ks WKfFn(, 2, (costa(, 3.''&7
avem
sirulCdeCcontrol5 (2rodusul Kd Ks WKfFn(
celelalteCargumente5 2, (costa(, 3.''

.xpresiile din PcelelalteCargumenteP sunt evaluate si convertite conform cu formatele din sirul de
control si apoi plasate in sirul de iesire. Caracterele din sirul de control care nu fac parte dintr6un
format sunt plasate direct in sirul de iesire. ,imbolul K introduce o
specificare de conversie sau format. 4 specificare de conversie este un sir care incepe cu K si se
termina cu un caracter de conversie.
9abelul de mai <os reprezinta caracterele de conversie %si modul lor de afisare& pentru functia
(printf%&(5
666666666666666666666666666666666666666666666666666666666666666666666
Caracter Cum sunt afisate
de argumentele corespunzatoare ?
conversie
666666666666666666666666666666666666666666666666666666666666666666666
c ca un caracter
d, i ca un intreg zecimal
u ca un intreg zecimal fara semn
o ca un intreg octal fara semn
x, > ca un intreg *exazecimal fara semn
e ca un numar in virgula mobila7 %ex5 '.123///eL//&
. ca un numar in virgula mobila7 %ex5 '.123///.L//&
f ca un numar in virgula mobila7 %ex5 '.123///&
g in formatul cel mai scurt dintre (e( sau (f(
Q in formatul cel mai scurt dintre (.( sau (f(
s ca un sir
p argumentul corespunzator este un pointer catre void7 valoarea sa se va tipari ca un
intreg *exazecimal
n argumentul corespunzator este un pointer catre un intreg7 argumentul nu este convertit
K cu formatul KK se va afisa un singur K catre sirul de iesire7 nu avem argumente ce
trebuie convertite
666666666666666666666666666666666666666666666666666666666666666666666
66666666666
.xemplu5 ata un exemplu de folosire a formatului (Kn(5
66666666666
#include Dstdio.*@
void main%&
E
int J pi7
printf%(;ai multe caractere Kn.Fn(, pi&7
printf%(=r.caractere 1 Kd(, Jpi&7
G
2e ecran se va afisa numarul de caractere afisate pana la aparitia formatului (Kn( %in cadrul
instructiunii de afisare (printf%&( curente&, adica 2/. "unctia (printf%&( intoarce un (int( ce
reprezinta numarul de caractere tiparite dupa inlocuirea corespunzatoare a specificatorilor de
conversie.

66666666666
.xemplu5
66666666666
#include Dstdio.*@
void main%&
E
int J pi7
int a 1 printf%(;ai mult de Kd caractere Kn.Fn(, 1/, pi&7
printf%(=umarul de caractere intors de functia printf%& este KdFn(, a&7
printf%(=r.caractere 1 Kd(, Jpi&7
G

n specificarile de conversie pot fi incluse informatii de formatare explicite. 8aca ele nu apar,
atunci sunt folosite cele implicite. 8e exemplu, formatul Kf cu argumentul 3.'' va afisa 3.''////.
=umarul este afisat pe $ caractere la dreapta punctului zecimal %implicit&. ntre K %care specifica
inceputul unei specificari de conversie& si caracterul de conversie de la sfarsit, pot apare in ordine5
6 zero sau mai multe caractere %flag& care modifica intelesul specificarii de conversie7
6 un intreg pozitiv optional care specifica minimul lungimii campului a argumentului convertit.
Hocul unde un argument este tiparit se numeste (campul sau(, iar numarul de spatii folosit pentru
afisarea sa se numeste (lungimea campului(. 8aca argumentul convertit are mai putine caractere
decat lungimea campului specificat, atunci acesta se va completa cu spatii %la stanga sau dreapta&.
8aca argumentul convertit are mai multe caractere decat lungimea campului specificat, atunci
lungimea campului se va mari cu cat este necesar. 8aca intregul care defineste lungimea campului
incepe cu zero si argumentul ce se tipareste este a<ustat dreapta in campul sau, atunci pentru
umplerea sa se vor folosi zerouri in loc de spatii7
6 o (precizie( optionala, care este specificata de un punct urmat de un intreg nenegativ. 2entru
conversii d, i, o, u, x si > aceasta specifica numarul minim de cifre ce trebuie afisate. 2entru
conversii e, . si f aceasta specifica numarul de cifre de la dreapta punctului zecimal. 2entru
conversii g si Q aceasta specifica numarul maxim de cifre semnificative. 2entru conversie cu s,
aceasta specifica numarul maxim de caractere ce trebuie tiparite dintr6un sir7
6 un * sau l optional, care este un modificator (s*ort( sau (long(, respectiv. 8aca * este urmat de
un d, i, o, u, x sau >, atunci aceasta este o specificare de conversie relativ la (s*ort int( sau
(unsigned s*ort int(. 8aca un * este urmat de n, atunci argumentul corespunzator este un pointer
catre (s*ort int( sau (unsigned s*ort int(. 8aca l este urmat de d, i, o, u, x sau >, atunci specificarea
de conversie se aplica unui argument (long int( sau (unsigned long int(. 8aca l este urmat de
caracterul n, atunci argumentul corespunzator este un pointer catre (long int( sau (unsigned long
int(7
6 H optional, care este un modificator (lung(. 8aca H este urmat de e, ., f, g sau Q, specificarea
de conversie se aplica unui argument (long double(.

Caracterele (flag( sunt5
6 semnul (6( va implica alinierea spre stanga a argumentului convertit in campul sau. 8aca nu
gasim nici un semn (6(, atunci alinierea argumentului convertit se face la dreapta campului.
6 semnul (L( va implica afisarea semnului (L( in cazul numerelor pozitive %functioneaza pentru
d, i, e, ., f, g si Q&. 9oate numerele negative incep cu semnul minus.
6 un spatiu, care semnifica ca un numar pozitiv %ce provine dintr6o conversie unsigned& are la
inceput un spatiu7
6 un (#(, care semnifica ca rezultatul trebuie convertit la o forma alternativa ce depinde de
caracterul de conversie. 8aca caracterul de conversie este (o(, atunci (#( cauzeaza afisarea unui
zero in fata numarului octal. ntr6o conversie x sau >, (#( cauzeaza /x, respectiv />, in fata
numarului *exazecimal. n conversiile g si Q, acesta cauzeaza tiparirea unor zerouri la coada %pana
la un anumit numar de zecimale, de obicei !&. n conversiile e, ., f, g sau Q, aceasta cauzeaza
tiparirea punctului zecimal, c*iar si cu precizia /. 2entru alte conversii, comportarea lui (#( este
nedefinita.
6 un (/( %zero&, care inseamna ca in loc de spatii sunt folosite zerouri. Cu caracterele de conversie
d, i, o, u, x, >, e, ., f, g si Q, aceasta poate produce zerouri nesemnificative %in fata numarului&.

ntr6un format, lungimea campului sau precizia %sau ambele&, pot fi specificate folosind J, in loc de
un intreg, lucru care indica ca o
valoare se obtine dintr6o lista de argumente.
66666666666
.xemplu5
66666666666
int m, n7
double x 1 333.'''''''7
. . . . . . . . . . .
:J citeste m si n %sau le calculam cumva& J:
. . . . . . . . . . .
printf%(x 1 KJ.JfFn(, m, n, x&7

8aca argumentul corespunzator lungimii campului are lungime negativa, atunci se considera (6( ca
fiind un (flag( urmat de o valoare pozitiva. 8aca argumentul corespunzator preciziei are valoare
negativa, atunci acesta se considera ca lipseste.
9abelul de mai <os contine formate de caractere si siruri %folosim g*ilimele pentru delimitarea
vizuala a campului, ele nefiind afisate&.

66666666666666666666666666666666666666666666666666666666666666666666666666666666666
8eclaratii si initializari
66666666666666666666666666666666666666666666666666666666666666666666666666666666666
c*ar c 1 P?P, sNO 1 (Huna rosieS(7
66666666666666666666666666666666666666666666666666666666666666666666666666666666666
"ormat ?rgumentul Cum este afisat 4bservatii
corespunzator in campul sau ?
6666666666666666666666666666666666666666666666666666666666666666666666666666666666
Kc c (?( Hungimea campului 1 implicit
K2c c ( ?( Hungimea campului 2, aliniat dreapta
K63c c (? ( Hungimea campului 3, aliniat stanga
Ks s (Huna rosieS( Hungimea campului 11 implicit
K3s s (Huna rosieS( ,patii suplimentare
K.$s s (Huna r( 2recizia $
K611.+s s (Huna ros ( 2recizie +, aliniere stanga
6666666666666666666666666666666666666666666666666666666666666666666666666666666666
n tabelul de mai <os vom da exemple de folosire a altor formate %avand aceeasi conventie de
afisare cu g*ilimele&.


66666666666666666666666666666666666666666666666666666666666666666666666666666666666
8eclaratii si initializari
66666666666666666666666666666666666666666666666666666666666666666666666666666666666
int i 1 1237
double x 1 /.1234!$'+-7
6666666666666666666666666666666666666666666666666666666666666666666666666666666666
"ormat ?rgumentul Cum este afisat 4bservatii
corespunzator in campul sau ?
6666666666666666666666666666666666666666666666666666666666666666666666666666666666
Kd i (123( Hungimea campului 3 implicit
K/!d i (//123( ?daugat /6uri nesemnificative
K'o i ( 1'3( ?liniere dreapta, octal
K6-x i ('b ( ?liniere stanga, *exazecimal
K6#-x i (/x'b ( ?liniere stanga, *exazecimal
K1/.!f x ( /.1234$( Hungimea campului 1/, precizie !
K612.!e x (1.234!'e6/1 ( ?liniere stanga, format 6e
6666666666666666666666666666666666666666666666666666666666666666666666666666666666

666666666666666666666666666666666666
"unctia de intrare (scanf%&(
666666666666666666666666666666666666
?re doua proprietati importante care permit o folosire flexibila la un nivel inalt5
6 poate citi o lista de argumente de lungime arbitrara7
6 intrarea este controlata de specificari de conversie simple %sau formate&.
"unctia (scanf%&( citeste caractere din fisierul standard (stdin(. Hista de argumente a functiei
(scanf%&( are doua parti5
sirCdeCcontrol si celelalteCargumente

66666666666
.xemplu5 "ie declaratiile si apelul functiei (scanf%&(5
66666666666
c*ar a, b, c, sN1//O7
int n7
double x7
scanf%(KcKcKcKdKsKlf(, Ra, Rb, Rc, Rn, s, Rx&7
?vem5
sirCdeCcontrol5 (KcKcKcKdKsKlf(
celelalteCargumente5 Ra, Rb, Rc, Rn, s, Rx
Celelalte argumente urmate de un sir de control consta dintr6o lista separata prin virgule de expresii
pointer sau adrese %reamintim ca (s( este insusi o adresa&.

666666666666666666666666666666666666
8irective in sirul de control
666666666666666666666666666666666666
,irul de control din (scanf%&( este compus din trei tipuri de (directive(5
6 caractere ordinare
6 spatii goale
6 specificari de conversie

6666666666666666666666666
Caractere ordinare
6666666666666666666666666
Caracterele din sirul de control %diferite de spatiile goale si caracterele din specificarile de
conversie& sunt numite (caractere ordinare(. Caracterele ordinare trebuie sa se regaseasca
%potriveasca& cu cele din sirul de la intrare.

66666666666
.xemplu5 float suma7
66666666666 scanf%(WKf(, Rsuma&7

Caracterul W este ordinar. 8eci trebuie sa intalnim W in sirul de la intrare. 8aca are loc o potrivire cu
succes, atunci spatiile goale %daca exista& se vor sari, si caracterele care urmeaza se vor potrivi la o
valoare %in virgula mobila&. Valoarea convertita va fi plasata
in memorie la adresa variabilei (suma(.

66666666666666666666666666666666
Caractere (spatii goale(
66666666666666666666666666666666
Caracterele spatii goale din sirul de control care nu fac parte dintr6o specificare de conversie se
potrivesc cu orice spatiu liber din sirul de intrare.
66666666666
.xemplu5 c*ar c1, c2, c37
66666666666 scanf%( Kc Kc Kc(, Rc1, Rc2, Rc3&7
8aca sirul de la intrare contine literele (a(, (b(, si (c(, atunci (c1(, (c2( si (c3( vor avea valorile
(a(, (b(, (c( %a nu se citi g*ilimelele&. 4 directiva spatiu liber implica ca spatiile goale %daca exista&
sa fie ignorate din sirul de intrare.
66666666666
.xemplu5 Urmatoarele instructiuni sunt ec*ivalente5
66666666666
scanf%( Kc Kc Kc(, Rc1, Rc2, Rc3&7
scanf%(FtKc Ft KcFnKc(, Rc1, Rc2, Rc3&7

6666666666666666666666666666666
,pecificari de conversie
6666666666666666666666666666666
ntr6un sir de control pentru (scanf%&(, o directiva de specificare de conversie incepe cu un (K( si
se termina cu un caracter de conversie. ?ceasta determina modurile de potrivire si de convertire a
caracterelor din sirul de intrare %cele doua tabele de mai <os contin explicatii pentru functia
(scanf%&(&5
66666666666666666666666666666666666666666666666666666666666666666666666666666666
Caracter de Caracterele din sirul de 9ipul
conversie intrare cu care se potrivesc argumentului
nemodificabil corespunzator
66666666666666666666666666666666666666666666666666666666666666666666666666666666
c orice caracter, inclusiv spatiu liber c*ar J
d un intreg zecimal %optional cu semn& int J
i zecimal, octal, *exazecimal int J
%'', /'', /x'', optional cu semn&
u un intreg zecimal %optional cu semn& unsigned J
o un intreg octal %optional cu semn& unsigned J
cifra / nu mai este necesara
x, > un intreg *exazecimal %optional cu semn& unsigned J
/x sau /> nu mai sunt necesare
e, ., f, g, Q numar in virgula mobila %optional cu semn& float J
s o secventa de caractere diferite de spatiu c*ar J
p ceea ce produce Kp in (printf%&( void J J
%de obicei intreg *exazecimal fara semn&
n, K, N . . .O %vezi urmatorul tabel&
6666666666666666666666666666666666666666666666666666666666666666666666666666666
4bservatie. Uecimal inseamna numar intreg scris in baza 1/ %nu numar cu zecimale&.


66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
6666666666666666666666
Caracter de 4bservatii
conversie
nemodificabil
66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
6666666666666666666666
n =u se potriveste nici un caracter din sirul de intrare. ?rgumentul corespunzator este un
pointer catre (int(,
in care se memoreaza numarul de caractere citite in acel (scanf%&(
K Conversia de specificare KK va implica potrivirea cu un caracter K din sirul de intrare.
=u are argumente
corespunzatoare.
N . . . O ;ultimea caracterelor dintre paranteze se numeste multime de scanare. ?ceasta
determina ce se potriveste
si face citirile respective. ?rgumentul corespunzator este un pointer catre baza sirului de
caractere ce este
suficient de mare pentru a pastra caracterele cu care s6a potrivit, apoi va adauga automat
terminatorul PF/P.
66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
6666666666666666666666

ntre K si caracterul de conversie poate fi5
6 caracterul J optional, care indica o suprascriere, urmata de un intreg optional care defineste
lungimea maxima a sirului de intrare
%care va fi deci ignorat&, urmat optional de *, l, H care modifica caracterul de conversie7
6 modificatorul *, care poate precede caracterele de conversie d, i, o, u, x sau >. ?cesta precizeaza
ca valoarea convertita trebuie
memorata ca un (s*ort int( sau (unsigned s*ort int(7
6 modificatorul l, care poate precede caracterele de conversie d, i, o, u, x, > sau e, ., f, g, Q. n
primul caz, acesta precizeaza ca
valoarea trebuie memorata ca un (long int( sau (unsigned long int(.
n cel de6al doilea caz, acesta precizeaza ca valoarea convertita trebuie memorata ca un (double(7
6 modificatorul H, care poate precede caracterele de conversie e, ., f,g sau Q. ?cesta precizeaza
ca valoarea convertita trebuie
memorata ca un (long double(.
Caracterele din sirul de intrare sunt convertite la valori in concordanta cu specificarile de conversie
din sirul de control si plasate la adresa data prin expresia pointer corespunzatoare din lista de
argumente. Cu exceptia unei intrari caracter, un camp de scanare consta dintr6un numar contiguu de
caractere diferite de spatiu %conforme cu conversia specificata&. Campul de scanare se termina cand
se gaseste un caracter neadecvat, sau s6a depasit lungimea scanarii %daca ea este precizata&, sau s6a
a<uns la .4" %depinde care vine primul&.
,pecificarea Ks sare spatiile goale si apoi citeste caractere diferite de spatiu pana cand se gaseste
spatiu sau .4" %depinde care vine primul&. n sc*imb, specificarea K!s sare spatiile goale, apoi
citeste caracterele diferite de spatiu, dar cel mult ! caractere sau pana la .4" %depinde care vine
primul&. Cand se citeste un sir de caractere, se presupune ca in memorie este de<a rezervat suficient
spatiu pentru memorarea sa %cu tot cu santinela F/&.
"ormatul Knc %unde (n( este o constanta intreaga& foloseste la citirea urmatoarelor n caractere,
inclusiv spatii goale %se presupune
ca s6a rezervat suficient spatiu in memorie pentru pastrarea lor, iar caracterul F/ nu se mai adauga&.


6666666666666666666666666666666666666666666666666666666666
=umere in virgula mobila din sirul de intrare
6666666666666666666666666666666666666666666666666666666666
=umerele in virgula mobila din sirul de intrare sunt formatate cu un semn optional %L sau 6& urmat
de un sir de cifre cu un punct zecimal optional, urmat de parte exponentiala optionala. 2artea
exponentiala consta din e sau ., urmate de un semn optional %L sau 6&, urmat de un sir de cifre.
66666666666
.xemple5
66666666666
''
L'.'e1
''/./.61
L/.//3
666666666666
=u uitati5 ,irul de intrare nu este cod C %se aplica reguli diferite&.
66666666666

66666666666666666666666666666666666666
"olosirea multimii de scanare
66666666666666666666666666666666666666
4 specificare de conversie de forma KNsirO indica ca un sir special poate fi citit. ;ultimea de
caractere dintre parantezele patrate se
numeste (multime de scanare(. 8aca primul caracter din multimea de scanare nu este caracterul
circumflex (A(, atunci sirul trebuie sa fie construit numai din caractere ce apartin multimii de
scanare.
66666666666
.xemple5 1. "ormatul KNabcO va citi orice sir care contine literele (a(, (b( si (c( si se va opri daca
orice alt caracter va
66666666666 apare in sirul de intrare, inclusiv un spatiu %ex. scanf%(KNabcO(, m&&.
2. n contrast, formatul KNAabcO va citi orice ce se va termina cu (a(, (b( sau (c(, dar nu si
spatiu.
3. "ie codul
c*ar mN3/O7
scanf%(K2-N?I FtFnO(, m&7
?ceasta va produce citirea in vectorul de caractere (m( a unui sir de cel mult 2-
caractere. ,irul consta din literele ?, I,
spatiu, tab, ne)line. Ha sfarsit, se va scrie F/.
4. 2rogramatorii de obicei gandesc o linie ca un sir de caractere, inclusiv spatii si taburi,
care se termina cu un ne)line.
Un mod %elegant& de a citi o linie in memorie este folosirea unei multimi de scanare
potrivita5
c*ar linieN2!$O7
)*ile %scanf%( KNAFnO(, linie& 11 1&
printf%(KsFn(, linie&7

66666666666666666666666666666666666666666
Valoarea returnata de (scanf%&(
66666666666666666666666666666666666666666
Cand (scanf%&( este apelata, poate apare o greseala la citire. 8e exemplu, daca nu sunt caractere in
sirul de intrare, atunci (scanf%&( va intoarce 61 %.4"&. 8aca apare o nepotrivire intre formatele din
(scanf%&( si sirul de la intrare, atunci (scanf%&( va intoarce numarul de conversii cu succes pana in
acel moment. =umarul este zero daca nu apar conversii. 8aca (scanf%&( reuseste cu succes, atunci
este returnat numarul de conversii cu succes. Ha fel, acest numar poate fi zero.
66666666666
.xemplu5
66666666666
c*ar c, JsirCcontrol, sN'O, mN1+O7
int a, contor7
sirCcontrol 1 (Kd , KJs KK Kc KNabcO KJs K!s Ks(7
contor 1 scanf%sirCcontrol, Ra, Rc, s, m, RmN!O&7
Consideram ca avem la intrare sirul5
23 , ignora K C abacus citesteCaceastaJJ
?tunci5
(23( este plasat in memorie la adresa lui (a(
(,( se potriveste
(ignora( este un sir ignorat
(K( se potriveste
(C( este plasat in memorie la adresa lui (c(
(abac( este plasat in sN/O,...,sN4O1PF/P
(us( este un sir ignorat
(cites( este plasat in mN/O,...,mN!O1PF/P
(teCaceastaJJ( este plasat in mN!O,...,mN1+O1PF/P
8in moment ce au avut loc ! conversii cu succes, rezulta ca functia (scanf%&( va intoarce valoarea
!.

66666666666
.xemplu5 9abelul de mai <os contine mai multe exemple de directive de control pentru functia
(scanf%&(5
66666666666
666666666666666666666666666666666666666666666666666666666666666666666
8irective 9ipul argumentului Continutul 4bservatii
in sirul corespunzator sirului de
de control intrare
666666666666666666666666666666666666666666666666666666666666666666666
abK2c c*ar J abacus ab se potriveste
ac se converteste
666666666666666666666666666666666666666666666666666666666666666666666
K3*d s*ort J 6''33 6'' se converteste
666666666666666666666666666666666666666666666666666666666666666666666
K41i long J L/x$$ L/x$ se converteste
666666666666666666666666666666666666666666666666666666666666666666666
6K2u unsigned J 6123 6 se potriveste
12 se converteste
666666666666666666666666666666666666666666666666666666666666666666666
L Klu unsigned long J L6123 L se potriveste
6123 se converteste
666666666666666666666666666666666666666666666666666666666666666666666
L Klu unsigned long J L 6123 L se potriveste
6123 se converteste
666666666666666666666666666666666666666666666666666666666666666666666
L Klu unsigned long J L6 123 L se potriveste
eroare, %6 nu se converteste&
666666666666666666666666666666666666666666666666666666666666666666666
K3e float J L'e62 L'e se converteste
666666666666666666666666666666666666666666666666666666666666666666666
K4f float J 'eL22 'eL22 se converteste
666666666666666666666666666666666666666666666666666666666666666666666
K!1f double J 61.234! 61.23 se converteste
666666666666666666666666666666666666666666666666666666666666666666666
K4Hf long double J 1234! 1234 se converteste
666666666666666666666666666666666666666666666666666666666666666666666
Kp void J J dependent poate citi ceea ce printf%&
de sistem cu Kp scrie la iesire
666666666666666666666666666666666666666666666666666666666666666666666


6666666666666666666666666666666666666666666
"unctiile (sprintf%&( si (sscanf%&(
6666666666666666666666666666666666666666666
"unctiile (sprintf%&( si (sscanf%&( sunt versiuni ce folosesc siruri ale functiei (printf%&( si (scanf%&(,
respectiv. 2rototipurile lor,
care se gasesc in (stdio.*(, sunt5
int sprintf%c*ar Js, const c*ar Jformat, ...&7
int sscanf%const c*ar Js, const c*ar Jformat, ...&7
2unctele ... indica compilatorului faptul ca functia poate avea un numar variabil de argumente. 4
instructiune de forma5
sprintf%sir, sirCdeCcontrol, alteCargumente&7
scrie rezultatul in sirul de caractere (sir(. ntr6o maniera similara, o instructiune de forma5
sscanf%sir, sirCdeCcontrol, alteCargumente&7
citeste rezultatul din sirul de caractere (sir(.

66666666666
.xemplu5
66666666666
c*ar J sirCintrare 1 (1 2 3 ab(7
c*ar sirCiesireN1//O, tempN1//O7
int a, b, c7
sscanf%sirCintrare, (KdKdKdKs(, Ra, Rb, Rc, Rtemp&7
sprintf%sirCiesire, (Ks Ks KdKdKdFn(, temp, temp, a, b, c&7
printf%(Ks(, sirCiesire&7
?tunci se va afisa la ecran5
ab ab 123
?tentie S .ste responsabilitatea programatorului sa rezerve spatiu suficient pentru memorarea lui
(sirCiesire( din (sprintf%&(.

666666666666666666666666666666666666666666
"unctiile (fprintf%&( si (fscanf%&(
666666666666666666666666666666666666666666
"unctiile (fprintf%&( si (fscanf%&( sunt versiunile pentru fisiere a functiilor (printf%&( si (scanf%&(.
"isierul (stdio.*( contine un numar de constructii referitoare la fisiere. n acest fisier exista si tipul
structura "H. a caror membrii descriu starea curenta a unui fisier. 9ot in acest fisier, sunt definiti
trei pointeri la fisier. .ste vorba despre (stdin(, (stdout( si (stderr(.
666666666666666666666666666666666666666666666666666666666666666666666666
8enumirea in C =umele complet 4bservatii
666666666666666666666666666666666666666666666666666666666666666666666666
stdin standard input file conectat la tastatura
stdout standard output file conectat la ecran
stderr standard error file conectat la ecran
666666666666666666666666666666666666666666666666666666666666666666666666
n fisierul (stdio.*( exista prototipurile pentru functiile (fprintf%&( si (fscanf%&(5
int fprintf%"H. Jofp, const c*ar Jformat, ...&7
int fscanf%"H. Jifp, const c*ar Jformat, ...&7
%(ofp( 6 outfile pointer, iar (ifp( 6 infile pointer&
2unctele ... spun compilatorului ca functia ia un numar variabil de argumente. 4 instructiune de
forma5
fprintf%pointerCcatreCfisier, sirCdeCcontrol, alteCargumente&7
va scrie in fisierul spre care pointeaza (pointerCcatreCfisier(. n particular,
fprintf%stdout, ...&7 este ec*ivalent cu printf%...&7
ntr6o maniera similara, o instructiune de forma5
fscanf%pointerCcatreCfisier, sirCdeCcontrol, alteCargumente&7
va citi din fisierul spre care pointeaza (pointerCcatreCfisier(. n particular,
fscanf%stdin, ...&7 este ec*ivalent cu scanf%...&7

6666666666666666666666666
?ccesarea fisierelor
6666666666666666666666666
"isierele au cateva proprietati importante5
6 au un nume
6 trebuie inc*ise si desc*ise
6 poate fi scris in ele sau citit din ele sau adaugat la ele
6 cand sunt desc*ise avem acces la ele de la inceput la sfarsitul lor
?bstract, un fisier poate fi gandit ca un sir de caractere. 8upa ce un fisier a fost desc*is, sirul poate
fi accesat folosind functii din
biblioteca standard.
66666666666
.xemplu5
66666666666
#include Dstdio.*@
void main%&
E
int suma 1 /, val7
"H. Jifp, Jofp7
ifp 1 fopen%(fisCin(, (r(&7 :J desc*is pentru citire J:
ofp 1 fopen%(fisCout(, ()(&7 :J desc*is pentru scriere J:
. . . . . .
G
n acest exemplu, am desc*is fisierul (fisCin( pentru citire si (fisCout( pentru scriere. 8in
momentul desc*iderii fisierului, pointerul catre fisier poate fi folosit exclusiv pentru referirea la
intregul fisier. 8aca, de exemplu, presupunem ca fisierul (fisCin( are numere intregi, atunci iata o
modalitate de a face suma lor5
)*ile %fscanf%ifp, (Kd(, Rval& 11 1&
sum L1 val7
fprintf%ofp, (,uma lor este Kd.Fn(, suma&7
Ca si (scanf%&(, functia (fscanf%&( intoarce numarul de conversii cu succes. 8upa ce terminam de
exploatat fisierele, putem sa le
inc*idem5
fclose%ifp&7
fclose%ofp&7
Un apel de functie de forma (fopen%numeCfisier, mod&( desc*ide fisierul respectiv intr6un mod
particular si returneaza un pointer
catre fisier. ,unt mai multe posibilitati pentru modul de accesare a fisierului5

666666666666666666666666666666666666666666666666666666666666
;od de acces ,emnificatie
666666666666666666666666666666666666666666666666666666666666
(r( desc*ide fisier text pentru citire
()( desc*ide fisier text pentru scriere
(a( desc*ide fisier text pentru adaugare
(rb( desc*ide fisier binar pentru citire
()b( desc*ide fisier binar pentru scriere
(ab( desc*ide fisier binar pentru adaugare
6666666666666666666666666666666666666666666666666666666666666
"iecare dintre aceste moduri se poate termina cu (aL(. ?sta inseamna ca fisierul poate fi desc*is si
pentru citire si pentru scriere.
666666666666666666666666666666666666666666666666666666666666666
;od de acces ,emnificatie
666666666666666666666666666666666666666666666666666666666666666
(rL( desc*ide fisier text pentru citire si scriere
()L( desc*ide fisier text pentru scriere si citire
. . . . .
666666666666666666666666666666666666666666666666666666666666666
8esc*iderea pentru citire a unui fisier care nu exista, sau care nu poate fi citit, va esua si functia
(fopen%&( va intoarce pointerul =UHH. 8esc*iderea unui fisier pentru scriere va avea ca efect
crearea unui fisier %daca acesta nu exista& sau se va suprascrie peste unul existent. 8esc*iderea unui
fisier pentru adaugare va avea ca efect crearea unui fisier %daca acesta nu exista& sau se va scrie la
sfarsitul sau %daca acesta exista&.
8aca scriem modul (rL( sau ()L( atunci fisierul se considera ca a fost desc*is pentru citire si
scriere. Cu toate acestea citirile nu
pot fi urmate de scrieri decat daca s6a a<uns la .4" sau au intervenit apeluri ale functiilor (fsee3%&(,
(fsetpos%&( sau (re)ind%&(. 8e asemeni, scrierile nu pot fi urmate de citiri decat daca s6a a<uns la
.4" sau au intervenit apeluri ale functiilor (fflus*%&(, (fsee3%&(, (fsetpos%&( sau (re)ind%&(.

666666666666666666666666666666666666666666
?ccesarea aleatoare a unui fisier
666666666666666666666666666666666666666666
n plus fata de accesarea unui caracter unul dupa altul intr6un fisier %acces secvential&, noi putem
accesa caractere in locuri diferite %acces aleator&. n biblioteca C, functiile (fsee3%&( si (ftell%&( sunt
folosite pentru accesarea aleatoare a unui fisier. 4 expresie de forma
ftell%pointerCcatreCfisier&
returneaza valoarea curenta a indicatorului de pozitie in fisier. Valoarea reprezinta numarul de
octeti pornind de la inceputul fisierului, numarand de la /. Cand un caracter este citit dintr6un fisier,
sistemul incrementeaza indicatorul de pozitie cu 1. 9e*nic vorbind, indicatorul de pozitie in fisier
este un membru a structurii catre care pointeaza (pointerCcatreCfisier(. 2ointerul catre fisier
nu pointeaza catre caractere individuale din fisier %aceasta este o eroare de conceptie pe care o fac
programatorii incepatori&.
"unctia (fsee3%&( are trei argumente5
6 pointer catre fisier
6 offset %intreg&
6 un intreg care arata locul fata de care se calculeaza offset6ul

4 instructiune de forma
fsee3%pointerCcatreCfisier, offset, mod&7
seteaza indicatorul de pozitie la o valoare care reprezinta (offset( octeti pornind de la (mod(.
Valoarea lui (mod( poate fi /, 1 sau 2, insemnand ca ne referim la inceputul fisierului, pozitia
curenta sau sfarsitul fisierului, respectiv.
?tentie S "unctiile (fsee3%&( si (ftell%&( sunt garantate sa lucreze numai pentru fisiere binare. n ;,6
84,, daca dorim sa lucram cu
aceste functii, trebuie sa desc*idem acest fisier in acces binar. n U=>, din moment ce exista doar
un singur mecanism de lucru cu
fisierele, orice mod de desc*idere pentru fisier este bun.

666666666666666666666666
,til de programare
666666666666666666666666
Un stil bun de programare va verifica daca functia (fopen%&( lucreaza asa cum ne asteptam %in orice
program serios, acest lucru trebuie facut&. ata cum ar trebui sa se faca desc*iderea fisierului (fis1(
in acces de citire5
if %%ifp 1 fopen%(fis1(, (r(&& 11 =UHH&
E
printf%(Fn=u putem desc*ide fisierul fis1. 2aSFnFn(&7
exit%1&7
G

66666666666666666666666666666666666666666666666
.xercitii propuse spre implementare
66666666666666666666666666666666666666666666666
1. "olosind (argc( si (argv( ca argumente ale functiei (main%&(, scrieti un program care copie
(fisier1( in (fisier2( dubland liniile %cu exceptia lui DC0@&.
2. ,crieti un program C care citeste in variabile C dintr6un fisier text numarul de linii, respectiv
coloane, si elementele unei matrice, apoi afisati matricea citita din fisier.
1!. nstrumente soft
1!.1. .xecutarea comenzilor dintr6un program C
1!.2. Variabile de mediu
1!.3. Compilatorul C
1!.4. Crearea unei biblioteci
1!.!. "olosirea lui (prof(
1!.$. Cronometrarea executiei codului C
1!.'. 2rograme de depanare
1!.+. Utilitarul (ma3e(
1!.-. Utilitarul (touc*(
1!.1/. ?lte instrumente soft utile
1!.11. .xercitii propuse spre implementare

1111111111
Capitolul 1!
1111111111
111111111111
nstrumente soft
111111111111
.xista doua tipuri de instrumente soft5
6 facilitati generale puse la dispozitie de catre sistemul de operare7
6 facilitati specifice desemnate explicit pentru a a<uta programatorul.
8in moment ce comenzile sistemului de operare pot fi executate dintr6un program C, atunci
programatorul poate folosi aceste comenzi ca instrumente de soft pentru indeplinirea anumitor
sarcini. Cateva instrumente sunt disponibile intr6un sistem de operare, dar nu si in altul. 8e
exemplu, (ma3e( exista in U=>, iar in ;,684, este o trasatura ce se poate instala. nstrumentele
de soft variaza cu timpul. ,istemele de depanare par a fi cele mai disponibile. Compilatorul C insusi
poate fi considerat un instrument soft.
n acest capitol vom discuta cum executam o comanda din sistemul de operare dintr6un program C.
?poi vom discuta cateva instrumente soft importante, cum ar fi5
6 compilatorul C
6 (ma3e(
6 (touc*(
6 (grep(
6 instrumente de depanare

66666666666666666666666666666666666666666666666666666666
.xecutarea comenzilor dintr6un program C
66666666666666666666666666666666666666666666666666666666
"unctia (sMstem%&( %din biblioteca C& pune la dispozitie accesarea comenzilor sistemului de
operare. ?stfel, comenzile existente in sistemul de operare pot fi apelate si din programe C.
66666666666
.xemplu5 ?tat in ;,684,, cat si in U=>, exista comanda (date(. 8aca intr6un program C,
scriem comanda
66666666666
sMstem%(date(&7
atunci va fi tiparita la ecran data curenta a sistemului.
,irul trimis ca argument al functiei (sMstem%&( este tratat ca o comanda a sistemului de operare.
Cand se executa instructiunea, controlul este trimis catre sistemul de operare, se executa comanda si
apoi controlul este trimis inapoi catre program.

66666666666
.xemplu5 n U=>, (vi( este o comanda folosita pentru editare. 2resupunem ca suntem intr6un
program si vrem sa editam un fisier al carui nume se citeste de la tastatura. 2utem scrie5
c*ar comandaN;?>,90=QO7
sprintf%comanda, (vi Ks(, argvN1O&7
printf%(8am comanda vi, desc*izand fisierul KsFn(, argvN1O&7
sMstem%comanda&7
Un exemplu similar poate functiona si in ;,684, inlocuind (vi( cu alt editor de texte.
66666666666
.xemplu5 Consideram ca vrem sa dam comanda ;,684, (dir( si dorim afisarea doar cu litere
mici. ?tunci putem scrie programul5
66666666666
#include DctMpe.*@
#include Dstdio.*@
#include Dstdlib.*@
#define ;?>,90=Q 1//

void main%&
E
c*ar comandaN;?>,90=QO, JnumeCfisCtemp7
int c7
"H. Jifp7
numeCfisCtemp 1 tmpnam%=UHH&7
sprintf%comanda, (dir @ Ks(, numeCfisCtemp&7
sMstem%comanda&7
ifp 1 fopen%numeCfisCtemp, (r(&7
)*ile %%c 1 getc%ifp&& S1 .4"&
putc*ar%tolo)er%c&&7
remove%numeCfisCtemp&7
G
4 varianta ceva mai (prote<ata( este5
#include DctMpe.*@
#include Dstdio.*@
#include Dstdlib.*@
#define ;?>,90=Q 1//

void main%&
E
c*ar comandaN;?>,90=QO, JnumeCfisCtemp7
int c7
"H. Jifp7
numeCfisCtemp 1 tmpnam%=UHH&7
sprintf%comanda, (dir @ Ks(, numeCfisCtemp&7
if %sMstem%(dir J.J(& 11 /&
E
sMstem%comanda&7
if %%ifp 1 fopen%numeCfisCtemp, (r(&& S1 =UHH&
)*ile %%c 1 getc%ifp&& S1 .4"&
putc*ar%tolo)er%c&&7
remove%numeCfisCtemp&7
G
G
?tentie S ,e creeaza intai executabilul si apoi se ruleaza dupa ce s6a iesit din compilatorul C.
6666666666666
4bservatii5 2entru programele de mai sus, facem precizarile5
6666666666666
6 folosim functia (tmpnam%&( pentru creearea unui nume de fisier temporar %de obicei
(tmp1.WWW(&7 daca exista de<a fisierul (tmp1.WWW( in directorul curent, atunci se creeaza fisierul
(tmp2.WWW(, s.a.m.d.&7
6 apelam functia (sistem%&( pentru redirectarea iesirii comenzii (dir( in acel fisier temporar7
6 apoi tiparim continutul fisierului la ecran sc*imband literele mari in mici7
6 in final, stergem din memorie fisierul temporar folosind functia (remove%&(.

6666666666666666666666666
Variabile de mediu
6666666666666666666666666
Variabilele de mediu sunt disponibile atat in U=>, cat si in ;,684,. ?fisarea lor la ecran se
poate face cu urmatorul program5
#include Dstdio.*@

void main%int argc, c*ar JargvNO, c*ar JenvNO&
E
int i7
for %i 1 /7 envNiO S1 =UHH7 LLi&
printf%(KsFn(, envNiO&7
G
?mbii parametri %argv si env& sunt de tip pointer catre pointer catre (c*ar(. 8eci, putem sa6i
gandim ca siruri de pointeri catre (c*ar( sau (vectori de siruri de caractere(. ,istemul memoreaza
spatiu pentru ele. Ultimul element din fiecare astfel de sir este pointerul =UHH. .vident programul
de mai sus foloseste doar vectorul (env(.
2e sistemele U=>, programul va afisa5
2?9[1:usr:local:bin5:bin5:usr:bin5:usr:>110$:bin5:*ome:stefan:bin
[4;.1:*ome:stefan
,[.HH1:bin:bas*
9.0;1vt22/
U,.01stefan
. . . . .
Ha stanga semnului (1( sunt deci variabilele de mediu, iar la dreapta valorile lor, care trebuie
gandite ca siruri de caractere.
2e sistemele ;,684,, programul va afisa5
204;291W2WQ
2?9[1U5.7^5.7>5.7Y5.7V5.7U5.795.7,5.705.7]5.725.
C4;,2.C1^5C4;;?=8.C4;
. . . . .
?mbele sisteme %U=> si ;,684,& pun la dispozitie comenzi pentru afisarea variabilelor de
mediu. n U=>, se pot folosi comenzile (env( sau (printenv( %pe unele sisteme si comanda (set(&,
iar in ;,684, comanda (set(.
2rin conventie, variabilele de mediu sunt de obicei scrise cu litere mari. ntr6un program C, putem
accesa variabilele de mediu prin al treilea argument al functiei (main%&( sau putem folosi functia
(getenv%&( din biblioteca standard. 2rototipul sau, care se gaseste in Dstdlib.*@, este dat prin5
c*ar Jgetenv%const c*ar Jname&7
8aca sirul trimis ca argument este o variabila de mediu, atunci functia intoarce sirul %pointer catre
(c*ar(& pus la dispozitie de catre sistem ca valoare a variabilei. 8aca sirul trimis ca argument nu
este variabila de mediu, atunci se returneaza =UHH.
666666666666
.xemplu5
666666666666
printf%(KsKsFnKsKsFnKsKsFnKsKsFnKsKsFn(,
(=ume utilizator5 (, getenv%(U,.0(&,
(=ume login5 (, getenv%(H4Q=?;.(&,
(,*ell5 (, getenv%(,[.HH(&,
(.nv5 (, getenv%(.=V(&,
(8irector [ome5 (, getenv%([4;.(&&7
n U=>, anumite variabile de mediu, cum ar fi H4Q=?;., ,[.HH, [4;., sunt puse la
dispozitie de catre sistem %adica sunt nemodificabile&. 2entru a initializa altele, scriem
setenv =?;. (?bcd efg*(
in fisierul nostru (.login(.

66666666666666666666
Compilatorul C
66666666666666666666
.xista multe compilatoare de C si un sistem de operare poate pune la dispozitie un numar mare de
astfel de compilatoare. ata cateva posibilitati5
666666666666666666666666666666666666666666666666666666666666666666666666666666666
Comanda Compilator C apelat
666666666666666666666666666666666666666666666666666666666666666666666666666666666
cc Compilator C creat de Iell Haboratories
cc Compilator C creat de CraM 0esearc* %U=C4,&
cc Compilator C creat de [e)lett62ac3ard %[26U>&
cc Compilator C creat de ,ilicon Qrap*ics %0>&
acc Compilator C creat de ,un ;icrosMstems %,un4,&
gcc Compilator Q=U C creat de "ree ,oft)are "oundation
*c Compilator [ig* C creat de ;eta)are
occ Compilator 4regon C creat de 4regon ,of)are
Zc Compilator ]uic3 C creat de ;icrosoft
tc Compilator 9urbo C, sistem integrat, creat de Iorland
tcc Compilator 9urbo C, versiune linie comanda, Iorland
66666666666666666666666666666666666666666666666666666666666666666666666666666666
n cele ce urmeaza, vom preciza modul de apel si optiunile acestora in U=>. ;ulte dintre ele sunt
valabile si in ;,684,.
8aca avem un program complet intr6un singur fisier, sa zicem (pgm.c(, atunci comanda5
cc pgm.c
va traduce codul C din (pgm.c( in cod obiect executabil si6l va scrie in fisierul (a.out( %n ;,6
84,, fisierul executabil se numeste (pgm.exe(&. Comanda (a.out( executa programul. Consideram
acum comanda5
cc 6o pgm pgm.c

?ceasta cauzeaza scrierea codului executabil direct in fisierul (pgm(, suprascriind6ul in cazul in
care acesta exista de<a %n ;,684, optiunea similara este 6e&. Comanda (cc( lucreaza de fapt in trei
faze5
6 apelul preprocesorului
6 apelul compilatorului
6 apelul incarcatorului %editorului de legaturi&

0olul incarcatorului este de a pune %lega& impreuna bucatile furnizate de compilator pentru a face
fisierul executabil final. 4ptiunea 6c se foloseste numai pentru compilare %pentru apelul
preprocesorului si compilatorului&, nu si a incarcatorului. ?ceasta optiune este utila daca avem un
program scris in mai multe fisiere. Consideram comanda
cc 6c main.c fis1.c fis2.c
8aca nu sunt erori, fisierele obiect corespunzatoare vor fi create si vor avea extensia (.o( %n ;,6
84,, ele au extensia (.ob<(&. 2entru creearea unui fisier executabil, putem compila anumite fisiere
cu extensia (.c( si (.o( %combinate&. 2resupunem ca avem o eroare in (main.c(. 8upa corectarea ei,
putem da comanda5
cc 6o pgm main.c fis1.o fis2.o
"olosirea fisierului cu extensia (.o( in locul celui cu extensia (.c( reduce timpul de compilare. n
plus fata de extensia (.c( si (.o(, putem folosi fisiere cu extesia (.s( care sunt create de asamblor sau
de compilator cu optiunea (6,( %cand folosim biblioteci create de ar*ivator&. Iibliotecile, de obicei,
au extensia (.a( %n ;,684, ele au extensia (.lib(&.

66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
666
Cateva optiuni folositoare pentru compilatorul C
66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
666
6c 8oar compilare, genereaza fisiere cu extensia (.o(
6g Qenereaza cod pentru depanator
6o nume 2une codul executabil in fisierul (nume(
6p Qenereaza cod pentru profiler
68 nume1def 2une la inceputul fiecarui fisier cu extensia (.c( linia #define nume def
6. ?peleaza preprocesorul, dar nu si compilatorul
6 dir %i mare& Cauta fisierele (#include( din directorul (dir(
6; Creaza un (ma3efile(
6;; Creaza un (ma3efile(, dar nu include toate dependentele din fisierele *eader standard
64 Qenereaza cod optimizat
6, Qenereaza cod de asamblare in fisiere cu extensia (.s(
66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
66


6666666666666666666666666666666
Crearea unei biblioteci
6666666666666666666666666666666
;ulte sisteme de operare pun la dispozitie facilitati de creare si gestionare a bibliotecilor. n U=>,
acest lucru se face cu ar*ivatorul si se apeleaza cu comanda (ar(. n ;,684,, acest lucru se
realizeaza cu bibliotecarul si este o aplicatie ce se poate instala. Iibliotecarul ;icrosoft este (lib(,
in timp ce bibliotecarul 9urbo C Iorland este (tlib(. 2rin conventie, numele fisierelor din biblioteci
au extensia (.a( in U=> si (.lib( in ;,684,. n cele ce urmeaza vom discuta situatia din U=>,
dar ideea generala se poate aplica oricarui bibliotecar.
n U=>, ar*ivatorul (ar( poate fi folosit pentru combinarea unui grup de fisiere intr6unul singur
numit (biblioteca(. Iiblioteca C standard este un exemplu in acest sens. 2e multe sisteme U=>,
aceasta este fisierul (:lib:libc.a( sau poate exista in mai multe fisiere. ncercati comanda5
ar t :lib:libc.a
C*eia (t( este folosita pentru tiparirea numelor %sau titlurilor& fisierelor din biblioteca. 8aca dorim
numararea acestor titluri %pentru ca sunt foarte multe& putem da comanda5
ar t :lib:libc.a B )c
6666666666666
4bservatie5 2e unele sisteme U=>, biblioteca C nu este intitulata astfel. 8e exemplu, pe (fenrir(,
puteti incerca alt
6666666666666 exemplu de biblioteca5
ar t :lib:libp)db.a B )c

66666666666666666666666666
"olosirea lui (prof(
66666666666666666666666666
n U=>, daca folosim optiunea (6p( pentru compilator, atunci se produce cod suplimentar, care
poate lua locul in fisiere obiect sau fisiere executabile produse de compilator. Cand programul este
apelat, codul suplimentar produce informatii care pot fi folosite pentru generarea (profilului( unei
executii. nformatiile pentru (profile( sunt scrise automat in fisierul (mon.out(. ?cest fisier nu poate
fi citit de utilizatori. 2entru a obtine informatiile din (mon.out(, programatorul trebuie sa dea
comanda
prof pgm
unde (pgm( este numele programului.

666666666666666666666666666666666666666666666
Cronometrarea executiei codului C
666666666666666666666666666666666666666666666
;ulte sisteme de operare pun la dispozitie functii pentru folosirea ceasului intern. ?ccesul la ceasul
masinii este posibil in ?=, C printr6un numar de functii a caror prototipuri sunt descrise in
Dtime.*@. "isierul *eader contine de asemenea un numar de alte constructii, printre care si
definitiile lui (cloc3Ct( si (timeCt(. 8e obicei, aceste definitii de tipuri sunt date prin5
tMpedef long cloc3Ct7
tMpedef long timeCt7
si aceste tipuri sunt folosite in prototipurile functiilor. ata trei functii utile pentru cronometrarea
timpului5
cloc3Ct cloc3%void&7
timeCt time%timeCt Jp&7
double difftime%timeCt time1, timeCt time/&7
Cand un program este executat, sistemul de operare tine minte timpul procesorului ce este folosit.
Cand este apelata functia (cloc3%&(, valoarea returnata de sistem este cea mai buna aproximare a
timpului folosit de program pana in acel punct. Unitatile %de masura& ceasului pot varia de la o
masina la alta. ;acro6ul
#define CH4C\,C2.0C,.C $/ :J dependent de masina J:
este pus la dispozitie in *eader6ul Dtime.*@D:>;2@
Dp@D>;2@. ?cesta poate fi folosit pentru conversia valorii returnate de (cloc3%&(
catre secunde. "unctia (time%&( intoarce numarul de secunde care au trecut de
la 1 ianuarie 1-'/ %sunt posibile si alte unitati, aceasta fiind una din ele&.
4 folosire uzuala a acestei functii este5 srand%time%=UHH&&7 ?pelul se refera
la generatorul de numere aleatoare. 8aca trimitem doua valori produse de (time%&(
catre functia (difftime%&(, atunci va fi returnata diferenta exprimata in secunde
de tip (double(.

666666666666666666666666666666
2rograme de depanare
666666666666666666666666666666

Un program de depanare permite programatorului sa urmareasca linie cu linie
executia codului si de a verifica valorile unor variabile sau expresii. ?cest
lucru este extrem de folositor %mai ales cand un program nu functioneaza conform
asteptarilor&. Humea programarii este plina de programe de depanare. 8e exemplu,
in U=> exista programul (dbx( %care insa nu este asa grozav&. 2rogramul C (fis.c(
trebuie compilat cu optiunea (6g( %debugging&, dupa care se lanseaza comanda
(dbx fis.c(. 2ana la comanda (Zuit(, toate comenzile sunt interne lui (dbx(.
Vizualizarea lor se poate face cu (dbx *elp(. n lumea ;,684,, programele de
depanare sunt in general incorporate. 8e exemplu, firmele ;icrosoft si Iorland
produc programe de depanare excelente.

66666666666666666666666
Utilitarul (ma3e(
66666666666666666666666

?tat pentru programator, cat si pentru masina, este ineficient si costisitor sa pastram un program
C mare intr6un singur fisier care necesita compilari repetate. 4 strategie mult mai buna este
scrierea programului in mai multe fisiere cu extensia (.c( si compilarea lor separata. Utilitarul
(ma3e( poate fi folosit pentru a pastra (urmele( fisierelor sursa si de a produce acces usor la
biblioteci si la fisierele *eader asociate. ?ceasta facilitate este prezenta in U=>, iar in ;,684,
este o proprietate ce se poate instala.

66666666666666666666666
Utilitarul (touc*(
66666666666666666666666
Utilitarul (touc*( este disponibil intotdeauna in U=> si uneori disponibila sub ;,684, %de
obicei, este disponibila acolo unde este instalat (ma3e(&. Utilitarul (touc*( este folosit pentru a
actualiza data unui fisier. ?cesta este util cand folosim (ma3e( cand se compara timpurile
fisierelor care trebuie compilate.

66666666666
.xemplu5 8aca punem data curenta la un fisier (aaa.*( folosind comanda5

touc* aaa.* atunci fisierul (aaa.*( are data cea mai recenta decat toate fisierele
(.*(, (.c(, (.o(. ?cum, dand comanda (ma3e( toate fisierele cu extensia (.c(
vor fi recompilate si fisierele obiect lin3editate pentru a crea noul fisier
executabil.

6666666666666666666666666666666666
?lte instrumente soft utile
666666666666666666666666666666666

,istemul de operare pune la dispozitie multe instrumente soft pentru programatori.
ata o lista cu cateva instrumente soft ce se gasesc in U=> %unele c*iar si
in ;,684,&5
66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
Comanda 4bservatii
66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
cb "olosit pentru transformarea codului C in (prettM print(
diff 9ipareste liniile care difera in doua fisiere grep Cauta un (pattern( intr6unul sau mai
multe
fisiere
indent ?lt (prettM printer( cu mai multe optiuni
)c =umara liniiile, cuvintele si caracterele dintr6un fisier %sau mai multe&
66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
Utilitarul (cb( citeste din (stdin( si scrie in (stdout(. Utilitarul (indent(
este mai puternic. 2oate fi gasit pe versiunile U=> Ier3eleM si ,un.

66666666666
.xemplu5 cb D pgm.c
Utilitarele (diff(, (grep( si ()c( pot fi folosite
de oricine, nu numai de programatori. Cu toate ca sunt utilitare U=>, ele sunt
de obicei disponibile si in ;,684, %in special (grep(, foarte folositor programatorilor&.
n final, sa mentionam ca C poate fi folosit in con<unctie si cu alte instrumente
de nivel inalt %unele dintre ele limba<e (adevarate(&5
66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
Utilitar 4bservatii
66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
a)3 Himba< de procesare si scanare a pattern6urilor cs* ?cest (s*ell( %ca si
(s*(, (3s*(& este programabil
lex Qenereaza cod C pentru analiza lexicala
sed .ditor de texte care preia comenzile sale dintr6un fisier
Macc (^et anot*er compiler6compiler(, folosit la generarea de cod C
66666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
4 importanta deosebita o au (lex( si (Macc( %cu versiunile (pclex( si (pcMacc(
pentru ;,684,&. Versiuni mai recente, cum ar fi, (flex( sau (bison(, sunt disponibile
de la "ree ,oft)are "oundation, nc. .le lucreaza atat sub U=>, cat si sub
;,684,.

66666666666666666666666666666666666666666666666
.xercitii propuse spre implementare
66666666666666666666666666666666666666666666666
1. ,crieti un program C care implementeaza strategiile (bubble sort(, respectiv (Zuic3sort(, si
folosind
functii (de timp( comparati timpii de executie ale celor doua metode.
2. "olosind comanda (sMstem%&( scrieti un program C care apeleaza un editor de texte %salvati
fisierul (fis.txt(&, apoi listati fisierul (fis.txt( la imprimanta

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