Sunteți pe pagina 1din 147

MANUAL LIMBAJ C

Theory without practice is useless; practice without theory is blind


Roger Bacon
Acest manual este structurat astfel nct elementele limbajului C s fie prezentate ntr-
o manier unitar. Primul capitol face o scurt introucere !i prezint !ase programe C.
"rmtoarele cinci capitole escriu elementele primare ale limbajului C# tipurile
funamentale e ate$ efini%ii e constante !i &ariabile$ instruc%iuni$ func%ii. Capitolul
!apte escrie strategii e organizare a acti&it%ii e programare pentru elaborarea
programelor mari$ compuse in mai multe moule. 'ot n acest capitol snt prezentate !i
irecti&ele e compilare cele mai folosite. Capitolele opt !i nou escriu elemente
a&ansate ale limbajului C# pointeri !i structuri.
Capitolele zece !i unsprezece trec n re&ist func%iile cele mai es utilizate efinite n
biblioteca stanar$ mpreun cu cte&a programe emonstrati&e. Am selectat oar
func%iile efinite e mai multe stanare (n primul rn A)*+ C,$ pentru a garanta o
portabilitate ct mai mare.
Acest manual a fost conceput pentru a ser&i ca ocument care s poat fi consultat e
programatori n elaborarea proiectelor$ !i nu pentru a fi memorat. -anualul nu este o
prezentare e./austi& a limbajului C; am selectat strictul necesar care s permit unui
programator s elaboreze programe eficiente !i u!or e ntre%inut.
0eoarece a&em con&ingerea c cea mai bun e.plica%ie este un program func%ional$
e.emplele in acest manual pot fi rulate pe orice meiu e programare C !i sub orice
sistem e operare.
Ca o ultim obser&a%ie amintim recomanarea fcut e n!i!i creatorii limbajului# cea
mai bun meto e n&%are este practica.
Dac constructorii ar fi construit cldiri aa cum scriu programatorii programe, atunci
prima ciocnitoare care ar fi venit ar fi distrus civilizaia
(in 1egile lui -urp/2,
33333333333333333333333333333333333333333333
4
1. Generaliti asupra limbajului C
1.1. Introducere
1imbajul C a fost creat la nceputul anilor 567 e ctre Brian 8 9ernig/am !i
0ennis - Ritc/ie e la Bell 1aboratories )e: ;erse2$ fiin ini%ial estinat scrierii
unei pr%i in sistemul e operare "ni.. 1ucrarea '/e C Programming
1anguage a celor oi autori$ aprut n mai multe &ersiuni$ a rmas cartea e
referin% n omeniu$ impunn un stanar minimal pentru orice implementare.
Caracteristicile istincti&e ale limbajului au fost clar efinite e la nceput$ ele
pstrnu-se n toate ez&oltrile ulterioare#
< portabilitate ma.im;
< structurare;
< posibilitatea efecturii opera%iilor la ni&elul ma!inii cu pstrarea caracteristicilor
unui limbaj e&oluat.
1imbajul C este un limbaj e programare uni&ersal$ caracterizat printr-o
e.primare concis$ un control moern al flu.ului e.ecu%iei$ structuri e ate$ !i un
bogat set e operatori.
1imbajul C nu este un limbaj e ni&el foarte nalt !i nu este specializat
pentru un anumit omeniu e aplica%ii. Absen%a restric%iilor !i generalitatea sa l
fac un limbaj mai con&enabil !i mai eficient ect multe alte limbaje mai
puternice.
1imbajul C permite scrierea e programe bine structurate$ atorit
construc%iilor sale e control al flu.ului# grupri e instruc%iuni$ luri e ecizii
(if,$ cicluri cu testul e terminare naintea ciclului (while$ for, sau up ciclu
(do, !i selec%ia unui caz intr-o mul%ime e cazuri (switch,.
1imbajul C permite lucrul cu pointeri !i are o aritmetic e arese puternic.
Permite e asemenea efinirea e ctre programator a unor tipuri structurate e
ate$ care pot fi orict e comple.e.
1imbajul C nu are opera%ii care prelucreaz irect obiectele compuse cum snt
!irurile e caractere$ mul%imile$ listele sau masi&ele$ consierate fiecare ca o
entitate. 1imbajul C nu prezint facilit%i e alocare a memoriei altele ect
efini%ia static sau isciplina e sti& relati& la &ariabilele locale ale func%iilor.
=n sfr!it$ limbajul C nu are facilit%i e intrare > ie!ire !i nici metoe irecte e
acces la fi!iere. 'oate aceste mecanisme e ni&el nalt snt realizate prin func%ii
e.plicite.
0e!i limbajul C este$ a!aar$ un limbaj e ni&el relati& sczut$ el este un
limbaj agreabil$ e.presi& !i elastic$ care se preteaz la o gam larg e programe.
33333333333333333333333333333333333333333333
?
C este un limbaj restrns !i se n&a% relati& u!or$ iar subtilit%ile se re%in pe msur
ce cre!te e.perien%a n programare.
1.. !epre"entarea #alorilor numerice
@ &aloare ntreag se reprezint n baza oi#
47A
(47,
= 74474774
(?,
B?6A7
(47,
= 7444444444474447
(?,
@ &aloare ntreag negati& se reprezint n complement fa% e oi astfel#
ac pentru reprezentare se folosesc w bi%i$ <a (7<a<?
w<4
, se reprezint ca !i
&aloarea ?
w
<a$ in care se pstreaz cele mai pu%in semnificati&e w pozi%ii. Astfel
opera%iile e aunare (cele mai frec&ente opera%ii elementare, se efectueaz ntr-un
timp foarte scurt$ fr a fi ne&oie e alte opera%ii au.iliare.
<47A
(47,
= 47747444
(?,
B?6A7
(47,
= 4777777777747747
(?,
Coificarea A*C++ a caracterelor folose!te C bi%i (un octet,#
< coul caracterului spa%iu este B?;
< courile cifrelor snt &alori ntre DC !i A6;
< courile literelor mari snt &alori ntre EA !i F7;
< courile literelor mici snt &alori ntre F6 !i 4??.
G.ist ou con&en%ii e memorare a &alorilor ntregi care necesit mai mul%i
octe%i#
< Big Gnian$ octe%ii apar n orinea cifrelor semnificati&e# &aloarea
4?6ACDA7
(4E,
se memoreaz astfel# 4?$ 6A$ CD$ A7;
< 1ittle Gnian$ octe%ii apar n orine in&ers# &aloarea 4?6ACDA7
(4E,
se
memoreaz astfel# A7$ CD$ 6A$ 4?.
Calculatoarele bazate pe procesoare +ntel folosesc a oua con&en%ie e
reprezentare. 0etalii espre acest subiect se afl la#
/ttp#>>:::.cs.umass.eu>H&erts>csB?>enian./tml
@ &aloare real nenul se reprezint normalizat n &irgul mobil$
escompus n ou elemente# o parte subunitar n inter&alul I7.A$4, !i o putere a
bazei oi. Pentru semn se folose!te o pozi%ie istinct (7 poziti&$ 4 negati&,.
Exemplu$ D.E?A = 477.474
(?,
= 7.477474
(?,
?
B
)umrul e pozi%ii rezer&ate pentru partea frac%ionar$ respecti& pentru
e.ponent epin e precizia aleas$ care poate fi simpl$ ubl sau e.tins.
1.%. &rimele pro'rame
=n aceast sec%iune snt prezentate !i e.plicate !ase programe cu scopul e a
asigura un suport e baz pentru prezentrile in capitolele urmtoare.
33333333333333333333333333333333333333333333
B
Prin trai%ie primul program C este un mic e.emplu in lucrarea e&enit
clasic < The C programming language$ e Brian 8 9ernig/am !i 0ennis -
Ritc/ie.
#include <stdio.h>
int main() {
printf("Hello, world\n");
return 0;

Acest program afi!eaz un mesaj e salut.


Prima linie inic faptul c se folosesc func%ii e intrare > ie!ire$ !i escrierea
moului e utilizare (numele$ tipul argumentelor$ tipul &alorii returnate etc, a
acestora se afl n fi!ierul cu numele stdio.h .
A oua linie efine!te func%ia main care &a con%ine instruc%iunile
programului. =n acest caz singura instruc%iune este un apel al func%iei printf
care afi!eaz un mesaj la terminal. -esajul este at ntre g/ilimele !i se termin
cu un caracter special ne:-line (\n,.
+nstruc%iunea return pre controlul sistemului e operare la terminarea
programului !i comunic acestuia coul 7 pentru terminare. Prin con&en%ie aceast
&aloare semnific terminarea normal a programului < aic nu au aprut erori n
prelucrarea atelor.
Corpul func%iei main apare ntre acolae. @rice program C trebuie s aib o
func%ie main.
Al oilea program a!teapt e la terminal introucerea unor numere ntregi
nenule !i etermin suma lor. =n momentul n care se introuce o &aloare zero$
programul afi!eaz suma calculat.
#include <stdio.h>
int main() {
int s,n;
s ! 0;
do {
scanf(""d",#n);
s $! n;
while (n%!0);
printf(""d\n",s);
return 0;

=n carul func%iei main se efinesc ou &ariabile s !i n care &or memora


&alori ntregi. Jariabila s (care &a pstra suma numerelor introuse, este
ini%ializat cu &aloarea 7.
33333333333333333333333333333333333333333333
D
=n continuare se repet (do, o sec&en% e ou instruc%iuni$ prima fiin o
opera%ie e intrare !i a oua o aunare.
Primul argument al func%iei scanf < formatul e introucere ""d" < inic
faptul c se a!teapt introucerea unei &alori ntregi n format zecimal e la
terminal (consol,. Al oilea argument inic unde se &a epune n memorie
&aloarea citit; e aceea este necesar s se precizeze adresa &ariabilei n (cu
ajutorul operatorului #,.
=n a oua instruc%iune la &aloarea &ariabilei s se aun &aloarea &ariabilei n.
@peratorul $! are semnifica%ia adun la.
Aceast sec&en% se repet (do, ct timp (while, &aloarea introus (n, este
nenul. @peratorul != are semnifica%ia diferit de.
=n final func%ia printf afi!eaz pe terminal valoarea &ariabilei s n format
zecimal.
Al treilea program a!teapt e la terminal introucerea unei &alori naturale n$
up care mai a!teapt introucerea a n &alori reale (ubl precizie,# a
0
$ a
&
$ ...$
a
n&
. =n continuare se afi!eaz meia aritmetic a acestor &alori$ calculat n
carul unei func%ii care se efine!te n acest scop.
#include <stdio.h>
dou'le media(dou'le ()*, int n) {
dou'le s;
int i;
for (s!i!0; i<n; i$$)
s $! ()i*;
return s+n;

int main() {
int n,i;
dou'le a)&00*;
scanf(""d",#n);
for (i!0; i<n; i$$)
scanf(""lf",#a)i*);
printf("".,lf\n", media(a,n));
return 0;

=n carul func%iei main se efinesc ou &ariabile n !i i care &or memora


&alori ntregi. Jariabila n pstreaz numrul actual e &alori in masi&ul a. *e
efinesc e asemenea un masi& uniimensional a care &a putea memora 477 e
&alori e tip real (ubl precizie,.
*e cite!te e la terminal o &aloare n. =n continuare se introuc &alorile reale
a
i
(i = 0$ &$ ...$ n&,; se obser& moul e referire la fiecare element in masi&#
33333333333333333333333333333333333333333333
A
a)i*. Kormatul e introucere ""lf" inic faptul c se a!teapt introucerea
unei &alori n ubl precizie e la terminal$ care &a fi epus la loca%ia e memorie
asociat &ariabilei a
i
. =n locul construc%iei #a)i* se poate folosi forma
ec/i&alent a$i.
Pentru a introuce toate &alorile a
i
se efectueaz un ciclu for$ n carul
cruia &ariabila i (care controleaz ciclul, ia toate &alorile ntre 0 (inclusi&, !i n
(e.clusi&, cu pasul &. 'recerea la urmtoarea &aloare a &ariabilei i se face cu
ajutorul operatorului $$.
-eia aritmetic a acestor &alori$ calculat cu ajutorul func%iei media$ este
afi!at cu o precizie e trei cifre up punctul zecimal$ conform formatului e
afi!are ".,lf".
* analizm acum efini%ia func%iei media. Aceasta calculeaz o &aloare e
tip dou'le$ opern asupra unui masi& ( care are elemente e tip dou'le. Cte
elemente are masi&ul$ aflm in al oilea parametru al func%iei# n.
0eclara%ia dou'le ()*
nu efine!te un masi&# n momentul apelului in main$ argumentul ( &a inica
spre masi&ul a cu care este pus n coresponen%.
0eclara%ia int n
efine!te o &ariabil local n$ care n momentul apelului in main &a primi
&aloarea argumentului n.
'rebuie s subliniem faptul c cele ou &ariabile$ e!i au acela!i nume$ snt
istincte# fiecare este local func%iei n care este efinit. Aceea!i obser&a%ie este
&alabil !i pentru &ariabilele i.
Ciclul for ini%ializeaz &ariabilele s !i i cu zero. Jariabila s (e asemenea
local, &a memora suma &alorilor in masi&ul (. Cu ajutorul &ariabilei i se
parcurge masi&ul ($ !i &aloarea fiecrui element este cumulat n s. =n final
instruc%iunea return comunic func%iei principale &aloarea s+n.
Acela!i program poate fi scris !i altfel$ efinin o parte in &ariabile n afara
celor ou func%ii.
#include <stdio.h>
int n;
dou'le a)&00*;
dou'le media() {
dou'le s;
int i;
for (s!i!0; i<n; i$$) s $! a)i*;
return s+n;

int main() {
int i;
33333333333333333333333333333333333333333333
E
scanf(""d",#n);
for (i!0; i<n; i$$) scanf(""lf",#a)i*);
printf("".,lf\n",produs());
return 0;

=n acest caz ambele func%ii se refer la acela!i masi& a !i la aceea!i &ariabil


n; spunem c &ariabilele a !i n snt globale. Kunc%ia media efine!te ou
&ariabile locale# s !i i$ func%ia main efine!te o &ariabil local# i.
G.ist o iferen% important ntre cele ou func%ii media in cele ou
programe. Prima efini%ie este mai general$ eoarece poate opera pe orice masi&
e elemente e tip dou'le$ a&n oricte elemente. 0ac$ e e.emplu$ n func%ia
principal am a&ea nc un masi& ' cu m elemente$ apelul ar fi# media(',m).
A oua efini%ie nu permite acest lucru. Kunc%ia principal ar trebui s copieze
mai nti toate elementele masi&ului ' n masi&ul a$ !i &aloarea m n &ariabila n.
Abia up aceea ar putea fi apelat func%ia media. 0ar astfel am istruge &ec/ile
&alori in a !i n.
Al oilea stil e programare trebuie e&itat$ eoarece utilizarea func%iilor este
foarte greoaie pentru argumente istincte la apeluri istincte ale acestora. G.ist o
singur justificare pentru acest stil# cn !tim cu certituine c o func%ie pe care o
efinim &a opera ntoteauna cu argumente memorate tot timpul n acelea!i
&ariabile.
Al cincilea program este o ilustrare a unor probleme legate e capacitatea
reprezentrilor &alorilor e tip ntreg !i &irgul mobil.
#include <stdio.h>
int main() {
short -,i;
float a,',c,u,(,w;
i ! ./0; - ! i 0 i;
printf(""hd\n",-);
a ! 10.&; - ! a 0 &00;
printf(""hd\n",-);
a ! &.,/2134; ' ! &.,/2135;
c ! a 0 a 6 ' 0 ';
u ! a 0 a; ( ! ' 0 '; w ! u 7 (;
printf(""f "f\n",c,w);
if (c!!w) return 0;
else return &;

Jariabila -$ care ar trebui s memoreze &aloarea A6E77$ are tipul ntreg scurt
(short,$ pentru care omeniul e &alori este restrns la <B?6EC B?6E6. Astfel
33333333333333333333333333333333333333333333
6
c &aloarea 4447777477777777
(?,
(n zecimal A6E77,$ n reprezentare ntreag cu
semn este e fapt <6FBE.
=n continuare &ariabila a prime!te &aloarea E7.4$ care nu poate fi reprezentat
exact n virgul mobil. 0e aceea &ariabila - prime!te &aloarea E77F atorit
erorilor e apro.imare.
Al treilea set e opera%ii necesit o analiz mai atent; e.plica%iile snt &alabile
pentru programe care ruleaz pe ar/itecturi +ntel. Jariabila c$ care ar trebui s
memoreze &aloarea ?DEF4BA6 (rezultatul corect,$ &a a&ea &aloarea ?DEF4BAE$
eoarece tipul float are rezer&ate pentru mantis oar ?D e cifre binare.
Rezultatul este foarte apropiat e cel corect eoarece rezultatele intermeiare se
pstreaz n regi!trii coprocesorului matematic cu precizie ma.im. Abia la
memorare se efectueaz trunc/ierea$ e une rezult &aloarea afi!at.
Cu totul altfel stau lucrurile n cazul celui e al patrulea set e opera%ii. Aici
rezultatele intermeiare snt memorate e fiecare at cu trunc/iere n &ariabile e
tip float. =n final se calculeaz !i iferen%a intre cele ou &alori trunc/iate$ e
une rezult &aloarea 4E666?4E.
=nainte e terminare se &erific ac &alorile c !i w snt egale. =n caz afirmati&
se comunic sistemului e operare un co 7 (terminare normal,. =n caz contrar se
comunic un co 4 (terminare anormal,.
Rula%i acest program pe iferite sisteme e calcul !i obser&a%i care este
rezultatul.
"ltimul program cite!te cte o linie e la intrarea stanar !i o afi!eaz la
ie!irea stanar.
#include <stdio.h>
char lin)50*;
int main() {
while (8ets(lin)) puts(lin);
return 0;

1inia citit cu ajutorul func%iei e bibliotec 8ets este memorat n masi&ul


lin$ ultimul caracter &ali al liniei fiin urmat e o &aloare zero$ care marc/eaz
astfel sfr!itul !irului. Citirea se nc/eie atunci cn intrarea stanar nu mai
furnizeaz nimic. Kunc%ia 8ets returneaz o &aloare care are semnifica%ia True
ac intrarea stanar a furnizat o linie$ sau !alse ac nu s-a mai furnizat nimic.
0ac linia se termin cu ne:-line$ acest caracter este preluat e la intrarea
stanar$ ar nu este memorat n !irul lin.
Am presupus c fiecare linie introus are mai pu%in e C7 e caractere$ altfel
programul nu &a func%iona corect. 0e altfel func%ia 8ets este folosit n aceast
lucrare oar n scop iactic$ pentru simplificarea e.punerilor.
33333333333333333333333333333333333333333333
C
Kiecare linie citit e la intrarea stanar este afi!at cu ajutorul func%iei
puts. Aceasta afi!eaz automat la sfr!it caracterul ne:-line.
0ac programul este rulat n mo obi!nuit nu se ntmpl nimic spectaculos#
fiecare linie introus e la terminal &a fi reafi!at. Programul poate fi totu!i
folosit pentru a afi!a con%inutul unui fi!ier te.t$ pentru a crea un fi!ier te.t$ sau
pentru a copia un fi!ier te.t. =n acest scop programul este rulat n mo linie e
coman astfel#
"rog <!iier#intrare (!iier#ieire
"rog este numele programului e.ecutabil$ ob%inut n urma compilrii
programului surs. !iier#intrare este numele fi!ierului al crui con%inut orim s-
l afi!m sau s-l copiem. !iier#ieire este numele fi!ierului pe care orim s-l
crem.
@ricare in cele ou argumente poate lipsi. 0ac primul argument este
prezent$ programul &a citi atele in fi!ierul e intrare specificat$ altfel &a a!tepta
introucerea atelor e la terminal. =n al oilea caz trebuie marcat ntr-un mo
special terminarea introucerii$ !i acest mo epine e sistemul e operare sub
care se lucreaz. 0ac al oilea argument este prezent$ programul &a scrie atele
n fi!ierul e ie!ire specificat$ care &a fi creat n acest scop. 0ac ie!irea nu este
specificat$ atele &or fi afi!ate la terminal.
Observaie general. =n cazul fiecrui program$ fiecare variabil sau funcie
este definit nainte de utilizare$ pentru ca n momentul utilizrii s e.iste toate
informa%iile espre conte.tul n care poate fi utilizat ientificatorul respecti&.
33333333333333333333333333333333333333333333
F
. Unitile le)icale ale limbajului C
*etul e caractere al limbajului C este un subset al setului e caractere A*C++$
format in#
< ?E litere mici
a b c e f g / i j L l m n o p M r s t u & : . 2 z
< ?E litere mari
A B C 0 G K N O + ; 9 1 - ) @ P P R * ' " J 8 Q R S
< 47 cifre
7 4 ? B D A E 6 C F
< B7 simboluri speciale
Blanc T U V W X 5 ( , Y + $ . > # ; < = > Z I [ \ ] 3 H ^ _ `
< E simboluri negrafice
[n$ [t$ [b$ [r$ [f$ [a
=n limbajul C e.ist !ase tipuri e unit%i le.icale# ientificatori$ cu&inte-c/eie$
constante$ !iruri$ operatori !i separatori.
.1. Identi*icatori+ cu#inte c,eie
"n ientificator este o succesiune e litere !i cifre intre care primul caracter
este n mo obligatoriu o liter. *e amit !i litere mari !i litere mici ar ele se
consier caractere istincte. 1iniu%a e subliniere 3 este consierat ca fiin
liter.
Cu&intele c/eie snt ientificatori rezer&a%i limbajului. Gi au o semnifica%ie
bine eterminat !i nu pot fi utiliza%i ect a!a cum cere sinta.a limbajului.
Cu&intele c/eie se scriu obligatoriu cu litere mici. Cu&intele c/eie efinite e
stanarul A)*+ snt#
auto do 8oto si8ned unsi8ned
'rea- dou'le if si9eof (oid
case else int static (olatile
char enum lon8 struct while
const e:tern re8ister switch
continue float return t;pedef
default for short union
.. Constante
=n limbajul C e.ist urmtoarele tipuri e constante# ntreg (zecimal$ octal$
/e.azecimal,$ ntreg lung e.plicit$ flotant$ caracter$ simbolic.
33333333333333333333333333333333333333333333
47
Constante -ntre'i
@ constant ntreag const intr-o succesiune e cifre.
@ constant octal este o constant ntreag care ncepe cu 0 (cifra zero,$ !i
este format cu cifre e la 0 la 3.
@ constant /e.azecimal este o constant ntreag preceat e 0: sau 0<
(cifra 0 !i litera :,. Cifrele /e.azecimale inclu literele e la = la > !i e la a la f
cu &alori e la &0 la &2.
=n orice alt caz$ constanta ntreag este o constant zecimal.
$xemplu# constanta zecimal ,& poate fi scris ca 0,3 n octal !i 0:&f sau
0<&> n /e.azecimal.
@ constant ntreag este generat pe un cu&nt (oi sau patru octe%i$ ac
sistemul e calcul este pe 4E sau B? e bi%i,.
@ constant zecimal a crei &aloare ep!e!te pe cel mai mare ntreg cu semn
reprezentabil pe un cu&nt scurt (4E bi%i, se consier e tip lon8 !i este generat
pe D octe%i.
@ constant octal sau /e.azecimal care ep!e!te pe cel mai mare ntreg
fr semn reprezentabil pe un cu&nt scurt se consier e asemenea e tip lon8.
@ constant ntreag e&ine negati& ac i se aplic operatorul unar e
negati&are 7.
Constante de tip e)plicit
@ constant ntreag zecimal$ octal sau /e.azecimal$ urmat imeiat e
litera l sau ? este o constant lung. Aceasta &a fi generat n calculator pe D
octe%i.
Exemplu$ &.,?
@ constant ntreag zecimal urmat imeiat e litera u sau @ este o
constant e tip ntreg fr semn. 1itera u sau @ poate fi urmat e litera l sau ?.
Exemplu$ &.,ul
Constante *lotante
@ constant flotant const intr-o parte ntreag$ un punct zecimal$ o parte
frac%ionar$ litera e sau A$ !i op%ional un e.ponent care este un ntreg cu semn.
Partea ntreag !i partea frac%ionar snt constituite in cte o succesiune e cifre.
=ntr-o constant flotant$ att partea ntreag ct !i partea frac%ionar pot lipsi$ ar
nu ambele; e asemenea poate lipsi punctul zecimal sau litera e !i e.ponentul$ ar
nu eoat (!i punctul !i litera e !i e.ponentul,.
Exemplu$ &.,./21e3 sau 0.&.e,
@rice constant flotant se consier a fi n precizie e.tins.
33333333333333333333333333333333333333333333
44
Constante caracter
@ constant caracter const intr-un singur caracter scris ntre apostrofuri$ e
e.emplu B:B. Jaloarea unei constante caracter este &aloarea numeric a
caracterului$ n setul e caractere al calculatorului. 0e e.emplu n setul e
caractere A*C++ caracterul zero sau B0B are &aloarea /5 n zecimal$ total iferit
e &aloarea numeric zero.
Constantele caracter particip la opera%iile aritmetice ca !i oricare alte numere.
0e e.emplu$ ac &ariabila c con%ine &aloarea A*C++ a unei cifre$ atunci prin
instruc%iunea#
c ! c 7 B0B ;
aceast &aloare se transform n &aloarea efecti& a cifrei.
Anumite caractere negrafice !i caractere grafice B (apostrof, !i \ (bacLslas/,
pot fi reprezentate ca !i constante caracter cu ajutorul unor secvene de evitare.
Acestea ofer e altfel !i un mecanism general pentru reprezentarea caracterelor
mai ificil e introus n calculator !i a oricror configura%ii e bi%i. Aceste
sec&en%e e e&itare snt#
\n ne:-line \r carriage return \\ bacLslas/
\t tab orizontal \f form fee \B apostrof
\' bacLspace \a semnal sonor \" g/ilimele
\ooo configura%ie e bi%i precizat n baza C
\:hh configura%ie e bi%i precizat n baza 4E
Kiecare in aceste sec&en%e$ e!i e format in mai multe caractere$ reprezint
n realitate un singur caracter.
Exemplu$ sec&en%a B\0/0B &a genera caracterul spa%iu.
Constante simbolice
@ constant simbolic este un ientificator cu &aloare e constant. Jaloarea
constantei poate fi orice !ir e caractere introus prin construc%ia #define
(capitolul !apte,.
$xemplu# #define C=< &000
0up ntlnirea acestei construc%ii compilatorul &a nlocui toate apari%iile
constantei simbolice C=< cu &aloarea &000.
)umele constantelor simbolice se scriu e obicei cu litere mari (fr a fi
obligatoriu,.
33333333333333333333333333333333333333333333
4?
.%. .iruri
"n !ir este o succesiune e caractere scrise ntre g/ilimele$ e e.emplu
"=DEF".
N/ilimelele nu fac parte in !ir; ele ser&esc numai pentru elimitarea !irului.
Caracterul " (g/ilimele, poate aprea ntr-un !ir ac se utilizeaz sec&en%a e
e&itare \". =n interiorul unui !ir pot fi folosite !i alte sec&en%e e e&itare pentru
constante caracter$ e asemenea poate fi folosit caracterul \ (bacLslas/, la sfr!itul
unui rn pentru a a posibilitatea continurii unui !ir pe mai multe linii$ situa%ie n
care caracterul \ nsu!i &a fi ignorat.
Pentru !irul e caractere se mai folose!te enumirea constant !ir sau
constant e tip !ir.
Cn un !ir apare ntr-un program C$ compilatorul creeaz un masi& e
caractere care con%ine caracterele !irului !i plaseaz automat caracterul null (7, la
sfr!itul !irului$ astfel ca programele care opereaz asupra !irurilor s poat etecta
sfr!itul acestora. Aceast reprezentare nseamn c$ teoretic$ nu e.ist o limit a
lungimii unui !ir$ iar programele trebuie s parcurg !irul$ analiznu-l pentru a-i
etermina lungimea. *e amit !i !iruri e lungime zero.
'e/nic$ un !ir este un masi& ale crui elemente snt caractere. Gl are tipul
masi& e caractere !i clasa e memorie static (capitolul trei,. "n !ir este
ini%ializat cu caracterele ate.
1a alocare$ memoria fizic cerut este cu un octet mai mare ect numrul e
caractere scrise ntre g/ilimele$ atorit augrii automate a caracterului null la
sfr!itul fiecrui !ir.
Exemplu. *ec&en%a urmtoare etermin lungimea !irului e caractere s$
e.cluzn caracterul terminal null.
for (n!0; s)i*; n$$) ;
Atragem aten%ia asupra iferen%ei intre o constant caracter !i un !ir care
con%ine un singur caracter. ":" nu este acela!i lucru cu B:B. B:B este un singur
caracter$ folosit pentru a genera pe un octet &aloarea numeric a literei x$ in setul
e caractere al calculatorului. ":" este un !ir e caractere$ care n calculator se
reprezint pe oi octe%i$ intre care primul con%ine un caracter (litera x,$ iar al
oilea caracterul null care inic sfr!itul e !ir.
./. 0peratori
1imbajul C prezint un numr mare e operatori care pot fi clasifica%i up
i&erse criterii. G.ist operatori unari$ binari !i ternari$ operatori aritmetici$ logici$
operatori pe bi%i etc. Capitolul patru este rezer&at n e.clusi&itate escrierii
operatorilor efini%i n limbajul C.
33333333333333333333333333333333333333333333
4B
.1. 2eparatori
"n separator este un caracter sau un !ir e caractere care separ unit%ile
le.icale ntr-un program scris n C.
*eparatorul cel mai frec&ent este a!a numitul spa%iu alb (blanc, care con%ine
unul sau mai multe spa%ii$ tab-uri$ ne:-line-uri sau comentarii.
Aceste construc%ii snt eliminate n faza e analiza le.ical a compilrii.
0m mai jos lista separatorilor ami!i n limbajul C.
( ) Parantezele mici ncareaz lista e argumente ale unei
func%ii sau elimiteaz anumite pr%i n carul e.presiilor
aritmetice etc
{ Acolaele ncareaz instruc%iunile compuse$ care
constituie corpul unor instruc%iuni sau corpul func%iilor
) * Parantezele mari ncareaz imensiunile e masi& sau
inicii elementelor e masi&
" " N/ilimelele ncareaz un !ir e caractere
B B Apostrofurile ncareaz un singur caracter sau o sec&en%
e e&itare
; Punct !i &irgula termin o instruc%iune
+0 *las/ asterisc nceput e comentariu
0+ Asterisc slas/ sfr!it e comentariu
"n comentariu este un !ir e caractere care ncepe cu caracterele +0 !i se
termin cu caracterele 0+.
"n comentariu poate s apar oriune ntr-un program une poate aprea un
blanc !i are rol e separator; el nu influen%eaz cu nimic semnifica%ia programului$
scopul lui fiin oar o ocumentare a acestuia.
)u se amit comentarii imbricate.
33333333333333333333333333333333333333333333
4D
%. 3ariabile
Ca !i constantele$ &ariabilele snt elemente e baz cu care opereaz un
program scris n C. @ &ariabil este un obiect e programare cruia i se atribuie un
nume !i i se asociaz o zon e memorie.
Jariabilele se eosebesc up nume !i pot primi iferite &alori. )umele
&ariabilelor snt ientificatori. )umele e &ariabile se scriu e obicei cu litere mici
(fr a fi obligatoriu,.
=n limbajul C$ &ariabilele snt caracterizate prin ou atribute# clas e
memorie !i tip. Acestea i snt atribuite unei &ariabile prin intermeiul unei
eclara%ii. 0eclara%iile enumer &ariabilele care urmeaz a fi folosite$ stabilesc
clasa e memorie$ tipul &ariabilelor !i e&entual &alorile ini%iale. *inta.a unei
eclara%ii este#
clas tip list-variabile;
1ista e &ariabile poate a&ea un element sau mai multe$ n al oilea caz ele
fiin separate prin &irgul.
Clasa e memorie precizeaz care func%ii pot &eea &ariabilele eclarate n
carul unui moul#
< oar func%ia > blocul une acestea snt efinite# &ariabile automatice !i &ariabile
statice interne;
< toate func%iile in carul moulului care urmeaz eclara%iei# &ariabile globale
statice;
< toate func%iile in toate moulele care cunosc eclara%ia# &ariabile globale
e.terne.
Clasa e memorie precizeaz n plus !i urata e &ia% a &ariabilelor eclarate.
Jariabilele automatice e.ist oar pe urata e.ecu%iei func%iei sau blocului une
au fost efinite. Jariabilele statice !i e.terne e.ist pe toat urata e.ecu%iei
programului.
'ipul unei &ariabile precizeaz omeniul e &alori pe care le poate lua !i
opera%iile care se pot efectua cu aceste &alori.
0eclara%iile se folosesc pentru a specifica interpretarea pe care compilatorul
trebuie s o ea fiecrui ientificator$ !i pot aprea n afara oricrei func%ii sau la
nceputul unei func%ii naintea oricrei instruc%iuni. )u orice eclara%ie rezer& !i
memorie pentru un anumit ientificator$ e aceea eosebim#
eclara%ia e efini%ie a unei &ariabile$ care creeaz &ariabila !i i se aloc
memorie;
eclara%ia e utilizare a unei &ariabile$ care oar anun% propriet%ile
&ariabilei care urmeaz a fi folosit.
33333333333333333333333333333333333333333333
4A
%.1. Clase de memorie
1imbajul C prezint patru clase e memorie# automatic$ e.tern$ static$
registru.
3ariabile automatice
Jariabilele automatice snt &ariabile locale fiecrui bloc sau func%ii. Gle se
eclar prin specificatorul e clas e memorie auto sau implicit prin conte.t. @
&ariabil care apare n corpul unei func%ii sau al unui bloc pentru care nu s-a fcut
nici o eclara%ie e clas e memorie se consier implicit e clas auto.
@ &ariabil auto este actualizat la fiecare intrare n bloc !i se istruge n
momentul cn controlul a prsit blocul. Gle nu !i re%in &alorile e la un apel la
altul al func%iei sau blocului !i trebuie ini%ializate la fiecare intrare. 0ac nu snt
ini%ializate$ con%in &alori reziuale. )ici o func%ie nu are acces la &ariabilele auto
in alt func%ie. =n func%ii iferite pot e.ista &ariabile locale cu acelea!i nume$ fr
ca &ariabilele s aib &reo legtur ntre ele.
Exemple. =n fiecare program in primul capitol$ &ariabilele locale snt
automatice.
3ariabile re'istru
@ &ariabil registru se eclar prin specificatorul e clas e memorie
re8ister. Ca !i &ariabilele auto ele snt locale unui bloc sau func%ii !i &alorile
lor se pier la ie!irea in blocul sau func%ia respecti&. Jariabilele eclarate
re8ister inic compilatorului c &ariabilele respecti&e &or fi folosite foarte
es. 0ac este posibil$ &ariabilele re8ister &or li plasate e ctre compilator n
regi!trii rapizi ai calculatorului$ ceea ce conuce la programe mai compacte !i mai
rapie.
Jariabile re8ister pot fi numai &ariabilele automatice sau parametrii
formali ai unei func%ii. Practic e.ist cte&a restric%ii asupra &ariabilelor
re8ister care reflect realitatea /ar:are-ului e baz. Astfel#
numai cte&a &ariabile in fiecare func%ie pot fi pstrate n regi!tri (e obicei
ou sau trei,; eclara%ia re8ister este ignorat pentru celelalte &ariabile;
numai tipurile e ate ntregi !i pointer snt amise;
nu este posibil referirea la aresa unei &ariabile re8ister.
3ariabile statice
Jariabilele statice se eclar prin specificatorul e clas e memorie
static. Aceste &ariabile snt la rnul lor e ou feluri# interne !i e.terne.
Jariabilele statice interne snt locale unei func%ii !i se efinesc n interiorul
unei func%ii; spre eosebire e &ariabilele auto$ ele !i pstreaz &alorile tot
33333333333333333333333333333333333333333333
4E
timpul e.ecu%iei programului. Jariabilele statice interne nu snt create !i istruse
e fiecare at cn func%ia este acti&at sau prsit; ele ofer n carul unei
func%ii o memorie particular permanent pentru func%ia respecti&.
Alte func%ii nu au acces la &ariabilele statice interne proprii unei func%ii.
Gle pot fi eclarate !i implicit prin conte.t; e e.emplu !irurile e caractere
care apar n interiorul unei func%ii < cum ar fi argumentele func%iei printf < snt
&ariabile statice interne.
Jariabilele statice e.terne se efinesc n afara oricrei func%ii !i orice func%ie
are acces la ele. Aceste &ariabile snt ns globale numai pentru fi!ierul surs n
care ele au fost efinite. )u snt recunoscute n alte fi!iere.
=n concluzie$ &ariabila static este e.tern ac este efinit n afara oricrei
func%ii !i este static intern ac este efinit n interiorul unei func%ii.
=n general$ func%iile snt consierate obiecte e.terne. G.ist ns !i
posibilitatea s eclarm o func%ie e clas static. Aceasta face ca numele
func%iei s nu fie recunoscut n afara fi!ierului n care a fost eclarat.
=n sec%iunea rezer&at problemei ini%ializrilor e la sfr!itul acestui capitol
&om a un e.emplu care ilustreaz comportamentul &ariabilelor automatice !i
statice.
3ariabile e)terne
Jariabilele e.terne snt &ariabile cu caracter global. Gle se efinesc n afara
oricrei func%ii !i pot fi apelate prin nume in oricare moul (fi!ier surs, care
intr n alctuirea programului.
=n eclara%ia e efini%ie aceste &ariabile nu necesit specificarea nici unei
clase e memorie. 1a ntlnirea unei efini%ii e &ariabil e.tern compilatorul
aloc !i memorie pentru aceast &ariabil.
=ntr-un fi!ier surs omeniul e efini%ie !i ac%iune al unei &ariabile e.terne
este e la locul e eclara%ie pn la sfr!itul fi!ierului. Aceste &ariabile e.ist !i !i
pstreaz &alorile e-a lungul e.ecu%iei ntregului program.
Pentru ca o func%ie s poat utiliza o &ariabil e.tern$ numele &ariabilei
trebuie fcut cunoscut func%iei printr-o eclara%ie.
0etalii espre utilizarea &ariabilelor e.terne &or fi ate n capitolul !apte.
%.. 4ipuri de #ariabile
1imbajul C amite numai cte&a tipuri funamentale e &ariabile# caracter$
ntreg$ &irgul mobil.
Pentru fiecare in tipurile prezentate n continuare se precizeaz !i escriptorii
e format cei mai utiliza%i n carul func%iilor e intrare > ie!ire. =n capitolul zece
&a fi etaliat tema formatrii atelor e intrare !i e ie!ire.
33333333333333333333333333333333333333333333
46
4ipul caracter
@ &ariabil e tip caracter se eclar prin specificatorul e tip char. Sona e
memorie alocat unei &ariabile e tip char este e un octet. Ga este suficient e
mare pentru a putea memora orice caracter al setului e caractere implementate pe
calculator.
0ac un caracter in setul e caractere este memorat ntr-o &ariabil e tip
char$ atunci &aloarea sa este egal cu coul ntreg al caracterului respecti&. ai
alte cantit%i pot fi memorate n &ariabile e tip char$ ar implementarea este
epenent e sistemul e calcul.
0omeniul &alorilor &ariabilelor caracter este ntre 7&.5 !i &.3. Caracterele
setului A*C++ snt toate poziti&e$ ar o constant caracter specificat printr-o
sec&en% e e&itare poate fi !i negati&$ e e.emplu B\,33B are &aloarea 7&.
Acest lucru se ntmpl atunci cn aceast constant apare ntr-o e.presie$
moment n care se con&erte!te la tipul int prin e.tensia bitului cel mai in stnga
in octet (atorit moului e func%ionare a instruc%iunilor calculatorului,.
0omeniul &alorilor &ariabilelor caracter fr semn (unsi8ned char, este
ntre 0 !i .22.
Descriptori de format:
< "c pentru o &ariabil sau o &aloare e tip char;
< "s pentru o &ariabil sau o e.presie e tip !ir e caractere.
4ipul -ntre'
Jariabilele ntregi poziti&e sau negati&e pot fi eclarate prin specificatorul e
tip int. Sona e memorie alocat unei &ariabile ntregi poate fi e cel mult trei
imensiuni.
Rela%ii espre imensiune snt furnizate e calificatorii short$ lon8 !i
unsi8ned$ care pot fi aplica%i tipului int.
Calificatorul short se refer toteauna la numrul minim e octe%i pe care se
reprezint un ntreg$ e obicei ?.
Calificatorul lon8 se refer la numrul ma.im e octe%i pe care poate fi
reprezentat un ntreg$ e obicei D.
'ipul int are imensiunea natural sugerat e sistemul e calcul. 0omeniul
numerelor ntregi reprezentabile n ma!in epine e sistemul e calcul# un
ntreg poate lua &alori ntre 7,.315 !i ,.313 (sisteme e calcul pe 4E bi%i, sau
ntre 7.&/3/5,1/5 !i .&/3/5,1/3 (sisteme e calcul pe B? e bi%i,.
Calificatorul unsi8ned alturi e eclara%ia e tip int etermin ca &alorile
&ariabilelor astfel eclarate s fie consierate ntregi fr semn. "n ntreg fr
semn poate lua &alori ntre 0 !i 122,2 (sisteme e calcul pe 4E bi%i, sau ntre 0 !i
/.4/413.42 (sisteme e calcul pe B? e bi%i,.
33333333333333333333333333333333333333333333
4C
Jalorile e tip unsi8ned respect legile aritmeticii moulo ?
w
$ une w este
numrul e bi%i in reprezentarea unei &ariabile e tip int. )umerele e tipul
unsi8ned snt toteauna poziti&e.
0eclara%iile pentru calificatori snt e forma#
short int :;
lon8 int ;;
unsi8ned int 9;
unsi8ned lon8 int u;
Cu&ntul int poate fi omis n aceste situa%ii.
Descriptori de format:
< "d pentru o &ariabil sau o &aloare e tip int;
< "u pentru o &ariabil sau o &aloare e tip unsi8ned;
< "ld pentru o &ariabil sau o &aloare e tip lon8;
< "lu pentru o &ariabil sau o &aloare e tip unsi8ned lon8;
< "hd pentru o &ariabil sau o &aloare e tip short;
< "hu pentru o &ariabil sau o &aloare e tip unsi8ned short.
4ipul *lotant 5#ir'ul mobil6
Jariabilele flotante pot fi n simpl precizie !i atunci se eclar prin
specificatorul e tip float sau n ubl precizie !i atunci se eclar prin
specificatorul dou'le. -ajoritatea sistemelor e calcul amit !i reprezentarea n
precizie e.tins; o &ariabil n precizie e.tins se eclar prin specificatorul lon8
dou'le.
Descriptori de format:
< "f pentru o &ariabil sau o &aloare e tip float;
< "lf pentru o &ariabil sau o &aloare e tip dou'le;
< "?f pentru o &ariabil sau o &aloare e tip lon8 dou'le.
4ipuri deri#ate
=n afar e tipurile aritmetice funamentale$ e.ist$ n principiu$ o clas
infinit e tipuri eri&ate$ construite in tipurile funamentale n urmtoarele
mouri#
< masive de T pentru masi&e e obiecte e un tip at T$ une T este unul intre
tipurile amise;
< funcii care returneaz T pentru func%ii care returneaz obiecte e un tip at T ;
< pointer la T pentru pointeri la obiecte e un tip at T ;
< structuri pentru un !ir e obiecte e tipuri iferite;
< reuniuni care pot con%ine obiecte e tipuri iferite$ tratate ntr-o singur zon e
memorie.
33333333333333333333333333333333333333333333
4F
=n general aceste metoe e construire e noi tipuri e obiecte pot fi aplicate
recursi&. 'ipurile eri&ate &or fi etaliate n capitolele opt !i nou.
%.%. 0biecte 7i #alori8st-n'a
Alte ou no%iuni folosite n escrierea limbajului C snt obiectul !i valoarea#
stnga.
"n obiect este con%inutul unei zone e memorie.
@ valoare#stnga este o e.presie care se refer la un obiect. "n e.emplu
e&ient e valoare#stnga este un ientificator. G.ist operatori care prouc
valori#stnga# e e.emplu$ ac $ este o e.presie e tip pointer$ atunci *$ este o
e.presie valoare#stnga care se refer la obiectul pe care-l inic $. )umele
valoare#stnga (n limba englez left value, a fost sugerat in faptul c n e.presia
e atribuire $4 b $? operanul stng $4 apare n stnga operatorului e atribuire.
=n paragraful e escriere a operatorilor se &a inica ac operanzii snt valori#
stnga sau ac rezultatul opera%iei este o valoare#stnga.
$xemple.
s ! a;
=n partea reapt a operatorului e atribuire$ a reprezint valoarea variabilei
respective. @pera%ia s = V; semnific# &aloarea V se atribuie &ariabilei s.
0p ! 0G;
=n partea reapt a operatorului e atribuire$ 0G reprezint valoarea aflat la
adresa indicat de q. @pera%ia 0p = V; semnific# &aloarea V se memoreaz la
aresa inicat e p.
%./. Con#ersii de tip
"n numr mare e operatori pot cauza con&ersia &alorilor unui operan e la
un tip la altul. 0ac ntr-o e.presie apar operanzi e iferite tipuri$ ei snt
con&erti%i la un tip comun up un mic numr e reguli. =n general se fac automat
numai con&ersiile care an sens$ e e.emplu# in ntreg n flotant$ ntr-o e.presie
e forma f$i. G.presii care nu au sens$ ca e e.emplu un numr flotant ca inice$
nu snt amise.
Caractere 7i -ntre'i
"n caracter poate aprea oriune une un ntreg este amis. =n toate cazurile
&aloarea caracterului este con&ertit automat ntr-un ntreg. 0eci ntr-o e.presie
aritmetic tipul char !i int pot aprea mpreun. Aceasta permite o fle.ibilitate
consierabil n anumite tipuri e transformri e caractere. "n astfel e e.emplu
este func%ia atoi escris n capitolul !ase care con&erte!te un !ir e cifre n
ec/i&alentul lor numeric.
33333333333333333333333333333333333333333333
?7
G.presia urmtoare prouce &aloarea numeric a caracterului (cifr, memorat
n A*C++#
s)i* 7 B0B
Atragem aten%ia c atunci cn o &ariabil e tip char este con&ertit la tipul
int$ se poate prouce un ntreg negati&$ ac bitul cel mai in stnga al octetului
con%ine 4. Caracterele in setul e caractere A*C++ nu e&in nicioat negati&e$
ar anumite configura%ii e bi%i memorate n &ariabile e tip caracter pot aprea ca
negati&e prin e.tensia la tipul int.
Con&ersia tipului int n char se face cu piererea bi%ilor e orin superior.
=ntregii e tip short snt con&erti%i automat la int. Con&ersia ntregilor se
face cu e.tensie e semn; ntregii snt toteauna cantit%i cu semn.
"n ntreg lon8 este con&ertit la un ntreg short sau char prin trunc/iere
la stnga; surplusul e bi%i e orin superior se piere.
Con#ersii *lotante
'oate opera%iile aritmetice n &irgul mobil se e.ecut n precizie e.tins.
Con&ersia e la &irgul mobil la ntreg se face prin trunc/ierea pr%ii frac%ionare.
Con&ersia e la ntreg la &irgul mobil este acceptat.
9ntre'i *r semn
=ntr-o e.presie n care apar oi operanzi$ intre care unul unsi8ned iar
cellalt un ntreg e orice alt tip$ ntregul cu semn este con&ertit n ntreg fr
semn !i rezultatul este un ntreg fr semn.
Cn un int trece n unsi8ned$ &aloarea sa este cel mai mic ntreg fr
semn congruent cu ntregul cu semn (moulo ?
4E
sau ?
B?
,. =ntr-o reprezentare la
complementul fa% e ?$ con&ersia este conceptual$ nu e.ist nici o sc/imbare
real a configura%iei e bi%i.
Cn un ntreg fr semn este con&ertit la lon8$ &aloarea rezultatului este
numeric aceea!i ca !i a ntregului fr semn$ astfel con&ersia nu face altce&a ect
s aauge zerouri la stnga.
Con#ersii aritmetice
0ac un operator aritmetic binar are oi operanzi e tipuri iferite$ atunci tipul
e ni&el mai sczut este con&ertit la tipul e ni&el mai nalt nainte e opera%ie.
Rezultatul este e tipul e ni&el mai nalt. +erar/ia tipurilor este urmtoarea#
< char < short < int < lon8;
< float < dou'le < lon8 dou'le;
< tip ntreg cu semn < tip ntreg fr semn;
< tip ntreg < tip &irgul mobil.
33333333333333333333333333333333333333333333
?4
Con#ersii prin atribuire
Con&ersiile e tip se pot face prin atribuire; &aloarea membrului rept este
con&ertit la tipul membrului stng$ care este tipul rezultatului.
Con#ersii lo'ice
G.presiile rela%ionale e forma i<H !i e.presiile logice legate prin operatorii
## !i II snt efinite ca a&n &aloarea 4 ac snt ae&rate !i 7 ac snt false.
Astfel atribuirea#
d ! (c>!B0B) ## (c<!B4B);
l face pe d egal cu 4 ac c este cifr !i egal cu 7 n caz contrar.
Con#ersii e)plicite
0ac con&ersiile e pn aici le-am putea consiera implicite$ e.ist !i
con&ersii e.plicite e tipuri pentru orice e.presie. Aceste con&ersii se fac prin
construc%ia special numit cast e forma#
(nume#tip) expresie
=n aceast construc%ie expresie este con&ertit la tipul specificat up regulile
precizate mai sus. -ai precis aceasta este ec/i&alent cu atribuirea e.presiei
respecti&e unei &ariabile e un tip specificat$ !i aceast nou &ariabil este apoi
folosit n locul ntregii e.presii. 0e e.emplu$ n e.presia#
sGrt((dou'le)n)
se con&erte!te n la dou'le nainte e a se transmite func%iei sGrt. Jariabila n
nu-!i moific &aloarea.
:)presia constant
@ e.presie constant este o e.presie care con%ine numai constante. Aceste
e.presii snt e&aluate n momentul compilrii !i nu n timpul e.ecu%iei; ele pot fi
astfel utilizate n orice loc une sinta.a cere o constant$ ca e e.emplu#
#define JC=< &000
char lin)JC=<$&*;
%.1. Masi#e
=n limbajul C se pot efini masi&e uniimensionale$ biimensionale$
triimensionale etc. "n masi& se compune in mai multe elemente e acela!i tip;
un element se ientific prin inice (pozi%ia relati& n masi&,$ sau prin inici
(ac masi&ul este multiimensional,.
$xemple#
char s)&00*;
int a)&0*)&2*;
33333333333333333333333333333333333333333333
??
Prima linie eclar un !ir e caractere# s)0*$ s)&*$ ...$ s)44*. A oua linie
eclar o matrice e ntregi# a)0*)0*$ ...$ a)0*)&/*$ a)&*)0*$ ...$ a)&*
)&/*$ ...$ a)4*)0*$ ...$ a)4*)&/*.
Acest subiect &a fi etaliat n capitolul opt.
%.;. Iniiali"ri
=ntr-o eclara%ie se poate specifica o &aloare ini%ial pentru ientificatorul care
se eclar. +ni%ializatorul este preceat e semnul = !i const intr-o e.presie
(&ariabile simple, sau o list e &alori incluse n acolae (masi&e sau structuri,.
'oate e.presiile intr-un iniializator pentru &ariabile statice sau e.terne
trebuie s fie e.presii constante sau e.presii care se reuc la aresa unei &ariabile
eclarate anterior. Jariabilele e clas auto sau re8ister pot fi ini%ializate cu
e.presii oarecare$ nu neaprat e.presii constante$ care implic constante sau
&ariabile eclarate anterior sau c/iar func%ii.
=n absen%a ini%ializrii e.plicite$ &ariabilele statice !i e.terne snt ini%ializate
implicit cu &aloarea 7. Jariabilele auto !i re8ister au &alori ini%iale
neefinite (reziuale,.
Pentru &ariabilele statice !i e.terne$ ini%ializarea se face o singur at$ n
principiu nainte ca programul s nceap s se e.ecute.
Pentru &ariabilele auto !i re8ister$ ini%ializarea este fcut la fiecare
intrare n func%ie sau bloc.
Problema ini%ializrii masi&elor !i masi&elor e pointeri este etaliat n
capitolul opt. Problema ini%ializrii structurilor este etaliat n capitolul nou.
#include <stdio.h>
int e ! &;
int f() {
int a ! .;
a$$; e$$;
return a $ e;

int 8() {
static int s ! .;
s$$; e$$;
return s $ e;

int main() {
int (&,(.,(,,(/;
(& ! f(); (. ! 8();
(, ! f(); (/ ! 8();
printf(""d "d "d "d "d\n",(&,(.,(,,(/,e);
return 0;
33333333333333333333333333333333333333333333
?B

* e.ecutm pas cu pas acest program.


(& ! f()$ a ! ,; e ! .; (& ! 2;
(. ! 8()$ s ! ,; e ! ,; (. ! 1;
(, ! f()$ a ! ,; e ! /; (, ! 3;
&ariabila a este reini%ializat la intrarea n func%ia f;
(/ ! 8()$ s ! /; e ! 2; (& ! 4;
&ariabila s !i pstreaz &aloarea la intrarea n func%ia 8;
*e &or afi!a &alorile# 2 1 3 4 2
%.<. Cali*icatorul const
Jaloarea unei &ariabile eclarate cu acest calificator nu poate fi moificat.
*inta.a#
const tip nume-variabil = valoare ;
nume-funcie(...= const tip 0nume-variabil= ...);
=n prima &ariant (eclararea unei &ariabile, se atribuie o &aloare ini%ial unei
&ariabile care nu mai poate fi ulterior moificat e program. 0e e.emplu$
const int (irsta ! ,4;
@rice atribuire pentru &ariabila (irsta &a genera o eroare e compilare.
=n a oua &ariant (eclararea unei func%ii, calificatorul const este folosit
mpreun cu un parametru pointer ntr-o list e parametri ai unei func%ii. Kunc%ia
nu poate moifica &ariabila pe care o inic pointerul#
int printf (const char 0format, ...);
AtenieT @ &ariabil eclarat cu const poate fi inirect moificat prin
intermeiul unui pointer#
int 0p ! #(irsta;
0p ! ,2;
33333333333333333333333333333333333333333333
?D
/. 0peratori 7i e)presii
1imbajul C prezint un numr mare e operatori$ caracteriza%i prin iferite
ni&ele e prioritate sau preceen%.
=n acest capitol escriem operatorii n orinea escresctoare a preceen%ei
lor. Jom preciza e fiecare at ac asociati&itatea este la stnga sau la reapta.
G.presiile combin &ariabile !i constante pentru a prouce &alori noi !i le &om
introuce pe msur ce &om prezen%a operatorii.
/.1. :)presii primare
constant
@ constant este o expresie#primar. 'ipul su poate fi int$ lon8 sau
dou'le. Constantele caracter snt e tip int$ constantele flotante snt e tip
lon8 dou'le.
identificator
"n ientificator este o expresie#primar$ cu coni%ia c el s fi fost eclarat
corespunztor. 'ipul su este specificat n eclara%ia sa.
0ac tipul unui ientificator este masiv de T$ atunci &aloarea expresiei#
identificator este un pointer la primul obiect al masi&ului$ iar tipul e.presiei este
pointer la T. -ai mult$ un ientificator e masi& nu este o e.presie valoare#stnga
(etalii n capitolul opt,.
1a fel$ un ientificator eclarat e tip funcie care returneaz T$ care nu apare
pe pozi%ie e apel e func%ie este con&ertit la pointer la funcie care returneaz T
(etalii n capitolul opt,.
ir
"n !ir este o expresie#primar. 'ipul su original este masiv de caractere$ ar
urmn acelea!i reguli escrise mai sus pentru ientificatori$ acesta este moificat
n pointer la caracter !i rezultatul este un pointer la primul caracter al !irului.
(expresie)
@ e.presie ntre paranteze rotune este o expresie#primar$ al crei tip !i
&aloare snt ientice cu cele ale e.presiei in interiorul parantezelor (e.presia in
paranteze poate fi !i o valoare#stnga,.
expresie-primar)expresie-indice*
@ expresie#primar urmat e o e.presie ntre paranteze ptrate este o
expresie#primar. *ensul intuiti& este e ine.are. 0e obicei expresia#primar are
tipul pointer la T$ expresia#indice are tipul int$ iar rezultatul are tipul T. @
33333333333333333333333333333333333333333333
?A
e.presie e forma E4)E?* este ientic (prin efini%ie, cu 0((E4)$(E?))$
une * este operatorul e inirectare (etalii n capitolul opt,.
expresie-primar(list-expresii)
"n apel e func%ie este o expresie#primar. Ga const intr-o expresie#
primar urmat e o perec/e e paranteze rotune$ care con%in o list#expresii
separate prin &irgule. %ista#expresii constituie argumentele reale ale func%iei;
aceast list poate fi !i &i. $xpresia#primar trebuie s fie e tipul funcie care
returneaz T$ iar rezultatul apelului e func%ie &a fi e tipul T (etalii n capitolul
!ase,.
=naintea apelului$ oricare argument e tip float este con&ertit la tipul
dou'le$ oricare argument e tip char sau short este con&ertit la tipul int.
)umele e masi&e snt con&ertite n pointeri la nceputul masi&ului. )ici o alt
con&ersie nu se efectueaz automat.
0ac este necesar ca tipul unui argument actual s coinci cu cel al
argumentului formal$ se &a folosi un cast.
*nt permise apeluri recursi&e la orice func%ie.
0espre efinirea !i apelul func%iilor$ etalii n capitolul !ase.
valoare-stnga . identificator
@ valoare#stnga urmat e un punct !i un ientificator este o expresie#
primar. &aloarea#stnga enume!te o structur sau o reuniune (capitolul nou,
iar ientificatorul enume!te un membru in structur sau reuniune. Rezultatul
este o valoare#stnga care se refer la membrul enumit in structur sau
reuniune.
expresie-primar 7> identificator
@ expresie#primar urmat e o sgeat (constituit intr-o liniu% !i semnul
> urmat e un ientificator, este o expresie#primar. Prima e.presie trebuie s
fie un pointer la o structur sau reuniune$ iar ientificatorul trebuie s fie numele
unui membru in structura sau reuniunea respecti&. Rezultatul este o valoare#
stnga care se refer la membrul enumit in structura sau reuniunea ctre care
inic e.presia pointer.
G.presia E4>E? este ientic in punctul e &eere al rezultatului cu
(0E4).E? (etalii n capitolul nou,.
!ist-expresii
@ list e e.presii este consierat e asemenea e.presie$ ac acestea snt
separate prin &irgul.
33333333333333333333333333333333333333333333
?E
/.. 0peratori unari
G.presiile unare se grupeaz e la reapta la stnga.
0 expresie
@peratorul unar 0 este operatorul e inirectare. G.presia care-l urmeaz
trebuie s fie un pointer$ iar rezultatul este o &aloare-stnga care se refer la
obiectul ctre care inic e.presia. 0ac tipul e.presiei este pointer la T atunci
tipul rezultatului este T. Acest operator trateaz operanul su ca o ares$ face
acces la ea !i i ob%ine con%inutul (etalii n capitolul opt,.
# valoare-stnga
@peratorul unar & este operatorul e ob%inere a aresei unui obiect sau e
ob%inere a unui pointer la obiectul respecti&. @peranul este o valoare#stnga iar
rezultatul este un pointer la obiectul referit e valoarea#stnga. 0ac tipul valorii#
stnga este T atunci tipul rezultatului este pointer la T (etalii n capitolul opt,.
expresie
@peratorul unar 7 este operatorul e negati&are. @peranul su este o
e.presie$ iar rezultatul este negati&area operanului. =n acest caz snt aplicate
con&ersiile aritmetice obi!nuite. )egati&area unui ntreg e tip unsi8ned se face
sczn &aloarea sa in ?
w
$ une w este numrul e bi%i rezer&a%i tipului int.
% expresie
@peratorul unar % este operatorul e negare logic. @peranul su este o
e.presie$ iar rezultatul su este 4 sau 7 up cum &aloarea operanului este 7 sau
iferit e zero. 'ipul rezultatului este int. Acest operator este aplicabil la orice
e.presie e tip aritmetic sau la pointeri.
K expresie
@peratorul unar K (tila, este operatorul e complementare la unu. Gl
con&erte!te fiecare bit 4 la 7 !i in&ers. Gl este un operator logic pe bi%i.
@peranul su trebuie s fie e tip ntreg. *e aplic con&ersiile aritmetice
obi!nuite.
$$ valoare-stnga
valoare-stnga $$
@peratorul unar $$ este operatorul e incrementare. @peranul su este o
valoare#stnga. @peratorul prouce incrementarea operanului cu 4. Acest
operator prezint un aspect eosebit eoarece el poate fi folosit ca un operator
prefi. (naintea &ariabilei# $$n, sau ca un operator postfi. (up &ariabil# n$$,.
=n ambele cazuri efectul este incrementarea lui n. 0ar e.presia $$n
incrementeaz pe n nainte e folosirea &alorii sale$ n timp ce n$$ incrementeaz
33333333333333333333333333333333333333333333
?6
pe n up ce &aloarea sa a fost utilizat. Aceasta nseamn c$ n conte.tul n care
se urmre!te numai incrementarea lui n$ oricare construc%ie poate fi folosit$ ar
ntr-un conte.t n care !i &aloarea lui n este folosit$ $$n !i n$$ furnizeaz ou
&alori istincte.
Exemplu$ ac n este A$ atunci
: ! n$$; atribuie lui : &aloarea A
: ! $$n; atribuie lui : &aloarea E
=n ambele cazuri n e&ine E.
Rezultatul opera%iei nu este o valoare#stnga$ ar tipul su este tipul valorii#
stnga.
77 valoare-stnga
valoare-stnga 77
@peratorul unar 77 este operatorul e ecrementare. Acest operator este
analog cu operatorul $$ oar c prouce ecrementarea cu 4 a operanului.
(nume-tip) expresie
@peratorul (nume#tip) este operatorul e con&ersie e tip. Prin nume#tip
n%elegem unul intre tipurile funamentale amise n C inclusi& tipul pointer.
@peranul acestui operator este o expresie. @peratorul prouce con&ersia &alorii
expresiei la tipul enumit. Aceast construc%ie se nume!te cast.
si9eof(operand)
@peratorul si9eof furnizeaz imensiunea n octe%i a operanului su.
Aplicat unui masi& sau structuri$ rezultatul este numrul total e octe%i in masi&
sau structur. 0imensiunea se etermin n momentul compilrii$ in eclara%iile
obiectelor in e.presie. *emantic$ aceast e.presie este o constant ntreag care
se poate folosi n orice loc n care se cere o constant. Cea mai frec&ent utilizare
este n comunicarea cu rutinele e alocare a memoriei sau cele e intrare > ie!ire.
@peratorul si9eof poate fi aplicat !i unui nume#tip. =n acest caz el
furnizeaz imensiunea n octe%i a unui obiect e tipul inicat.
/.%. 0peratori aritmetici
Expresie-multiplicativ$
expresie 0 expresie
expresie + expresie
expresie " expresie
@peratorii multiplicati&i 0 + !i " snt operatori aritmetici binari !i se grupeaz
e la stnga la reapta.
33333333333333333333333333333333333333333333
?C
@peratorul binar 0 inic nmul%irea. @peratorul este asociati&$ ar n
e.presiile n care apar mai mul%i operatori e nmul%ire$ orinea e e&aluare nu se
specific. Compilatorul rearanjeaz c/iar !i un calcul cu paranteze. Astfel
a0('0c) poate fi e&aluat ca (a0')0c. Aceasta nu implic iferen%e$ ar ac
totu!i se ore!te o anumit orine$ atunci se &or introuce &ariabile temporare.
@peratorul binar + inic mpr%irea. Cn se mpart ou numere ntregi
poziti&e$ trunc/ierea se face spre zero; ac unul intre operanzi este negati&
atunci trunc/ierea epine e sistemul e calcul.
@peratorul binar " furnizeaz restul mpr%irii primei e.presii la cea e a
oua. @peranzii trebuie s fie e tip ntreg. Restul are toteauna semnul
empr%itului. 'oteauna (a+')0'$a"' este egal cu a (ac ' este iferit e
7,. *nt e.ecutate con&ersiile aritmetice obi!nuite.
Expresie-aditiv$
expresie $ expresie
expresie 7 expresie
@peratorii aiti&i $ !i 7 snt operatori aritmetici binari !i se grupeaz e la
stnga la reapta. *e e.ecut con&ersiile aritmetice obi!nuite.
@peratorul binar $ prouce suma operanzilor si. Gl este asociati& !i
e.presiile care con%in mai mul%i operatori pot fi rearanjate la fel ca n cazul
operatorului e nmul%ire.
@peratorul binar 7 prouce iferen%a operanzilor si.
/./. 0peratori de comparare
Expresie-relaional$
expresie < expresie
expresie > expresie
expresie <! expresie
expresie >! expresie
@peratorii rela%ionali <$ >$ <!$ >! se grupeaz e la stnga la reapta.
@peratorii < (mai mic,$ > (mai mare,$ <! (mai mic sau egal, !i >! (mai mare
sau egal, prouc &aloarea 7 ac rela%ia specificat este fals !i 4 ac ea este
ae&rat.
'ipul rezultatului este int. *e e.ecut con&ersiile aritmetice obi!nuite.
Ace!ti operatori au preceen%a mai mic ect operatorii aritmetici.
Expresie-egalitate$
expresie !! expresie
expresie %! expresie
33333333333333333333333333333333333333333333
?F
@peratorii !! (egal cu, !i %! (iferit e, snt analogi cu operatorii rela%ionali$
ar preceen%a lor este mai mic. Astfel c a<' !! c<d este 4 ac a<' !i
c<d au aceea!i &aloare e ae&r.
/.1. 0peratori lo'ici pe bii
Expresie-deplasare$
expresie << expresie
expresie >> expresie
@peratorii e eplasare << !i >> snt operatori logici pe bi%i. Gi se
grupeaz e la stnga la reapta.
@peratorul << prouce eplasarea la stnga a operanului in stnga cu un
numr e pozi%ii binare at e operanul in reapta.
@peratorul >> prouce eplasarea la reapta a operanului in stnga cu un
numr e pozi%ii binare at e operanul in reapta.
=n ambele cazuri se e.ecut con&ersiile aritmetice obi!nuite asupra
operanzilor$ fiecare intre ei trebuin s fie e tip ntreg. @peranul in reapta
este con&ertit la int; tipul rezultatului este cel al operanului in stnga.
Rezultatul este neefinit ac operanul in reapta este negati& sau mai mare sau
egal cu lungimea obiectului$ n bi%i. Astfel &aloarea e.presiei E4<<E? este E4
(interpretat ca !i configura%ie e bi%i, eplasat la stnga cu E? pozi%ii bit; bi%ii
elibera%i e&in zero. G.presia E4>>E? este E4 eplasat la reapta cu E? pozi%ii
binare. 0eplasarea la reapta este logic (bi%ii elibera%i e&in 7, ac E4 este e
tip unsi8ned$ altfel ea este aritmetic (bi%ii elibera%i e&in copii ale bitului
semn,.
$xemplu# :<<. eplaseaz pe : la stnga cu ? pozi%ii$ bi%ii elibera%i e&in 7;
aceasta este ec/i&alent cu multiplicarea lui : cu D.
Expresie-"#$
expresie # expresie
@peratorul # este operatorul '( logic pe bi%i. Gl este asociati& !i e.presiile care
con%in operatorul # pot fi rearanjate. Rezultatul este func%ia logic '( pe bi%i
aplicat operanzilor si. @peratorul se aplic numai la operanzi e tipuri ntregi.
1egea up care func%ioneaz este#
#
7 4
7 7 7
4 7 4
@peratorul # este eseori folosit pentru a masca o anumit mul%ime e bi%i# e
e.emplu#
33333333333333333333333333333333333333333333
B7
c ! n # 0&33;
pune pe zero to%i bi%ii afar e ultimii 6 bi%i e orin inferior ai lui n$ fr a afecta
con%inutul lui n.
Expresie-$A%-exclusiv$
expresie L expresie
@peratorul L este operatorul )*+#exclusiv logic pe bi%i. Gl este asociati& !i
e.presiile care-l con%in pot fi rearanjate. Rezultatul este func%ia logic )*+#
exclusiv pe bi%i aplicat operanzilor si. @peratorul se aplic numai la operanzi e
tipuri ntregi. 1egea up care func%ioneaz este#
L
7 4
7 7 4
4 4 7
Expresie-$A%-inclusiv$
expresie I expresie
@peratorul I este operatorul )*+#inclusiv logic pe bi%i. Gl este asociati& !i
e.presiile care-l con%in pot fi rearanjate. Rezultatul este func%ia logic )*+#
inclusiv pe bi%i aplicat operanzilor si. @peratorul se aplic numai la operanzi e
tipuri ntregi. 1egea up care func%ioneaz este#
I
7 4
7 7 4
4 4 4
@peratorul I este folosit pentru a pozi%iona bi%i; e e.emplu#
: ! : I C=MN;
pune pe 4 to%i bi%ii in : care corespun la bi%i pozi%iona%i pe 4 in C=MN. *e
efectueaz con&ersiile aritmetice obi!nuite.
/.;. 0peratori pentru e)presii lo'ice
Expresie-"#-logic$
expresie ## expresie
@peratorul ## este operatorul '(#logic !i el se grupeaz e la stnga la reapta.
Rezultatul este 4 ac ambii operanzi snt iferi%i e zero !i 7 n rest. *pre
eosebire e operatorul '( pe bi%i #$ operatorul '(#logic ## garanteaz o e&aluare
e la stnga la reapta; mai mult$ al oilea operan nu este e&aluat ac primul
operan este 7.
33333333333333333333333333333333333333333333
B4
@peranzii nu trebuie s aib n mo obligatoriu acela!i tip$ ar fiecare trebuie
s aib unul intre tipurile funamentale sau pointer. Rezultatul este toteauna e
tip int.
Expresie-$A%-logic$
expresie II expresie
@peratorul II este operatorul )*+#logic !i el se grupeaz e la stnga la
reapta. Rezultatul este 4 ac cel pu%in unul intre operanzi este iferit e zero !i
7 n rest.
*pre eosebire e operatorul )*+#inclusiv pe bi%i I$ operatorul )*+#logic II
garanteaz o e&aluare e la stnga la reapta; mai mult$ al oilea operan nu este
e&aluat ac &aloarea primului operan este iferit e zero.
@peranzii nu trebuie s aib n mo obligatoriu acela!i tip$ ar fiecare trebuie
s aib unul intre tipurile funamentale sau pointer. Rezultatul este toteauna e
tip int.
/.<. 0peratorul condiional
Expresie-condiional$
expresie O expresie $ expresie
@peratorul coni%ional OP este un operator ternar. Prima e.presie se
e&alueaz !i ac ea este iferit e zero sau ae&rat$ rezultatul este &aloarea
celei e-a oua e.presii$ altfel rezultatul este &aloarea e.presiei a treia. 0e
e.emplu e.presia#
9 ! (a>') O a P ';
calculeaz ma.imul intre a !i ' !i l atribuie lui 9. *e e&alueaz mai nti prima
e.presie a>'. 0ac ea este ae&rat se e&alueaz a oua e.presie !i &aloarea ei
este rezultatul opera%iei$ aceast &aloare se atribuie lui 9. 0ac prima e.presie nu
este ae&rat atunci 9 ia &aloarea lui '.
G.presia coni%ional poate fi folosit peste tot une sinta.a cere o e.presie.
0ac este posibil$ se e.ecut con&ersiile aritmetice obi!nuite pentru a auce
e.presia a oua !i a treia la un tip comun; ac ambele e.presii snt pointeri e
acela!i tip$ rezultatul are !i el acela!i tip; ac numai o e.presie este un pointer$
cealalt trebuie sa fie constanta 7$ iar rezultatul este e tipul pointerului.
=ntoteauna numai una intre e.presiile a oua !i a treia este e&aluat.
0ac f este flotant !i n ntreg$ atunci e.presia
(h>0) O fP n
este e tip dou'le iniferent ac n este poziti& sau negati&. Parantezele nu snt
necesare eoarece preceen%a operatorului OP este mai mic$ ar ele pot fi folosite
pentru a face e.presia coni%ional mai lizibil.
33333333333333333333333333333333333333333333
B?
/.>. 0peratori de atribuire
G.ist mai mul%i operatori e atribuire$ care se grupeaz to%i e la reapta la
stnga. @peranul stng este o &aloare-stnga$ operanul rept este o e.presie.
'ipul e.presiei e atribuire este tipul operanului stng.
Rezultatul este &aloarea memorat n operanul stng up ce atribuirea a a&ut
loc. Cele ou pr%i ale unui operator e atribuire compus snt unit%i le.icale
(simboluri, istincte.
Expresie-atribuire$
valoare-stnga ! expresie
valoare-stnga op! expresie
une op poate fi unul in operatorii $$ 7$ 0$ +$ "$ <<$ >>$ #$ L$ I.
=ntr-o atribuire simpl cu !$ &aloarea e.presiei nlocuie!te pe cea a obiectului
referit e valoare#stnga. 0ac ambii operanzi au tip aritmetic$ atunci operanul
rept este con&ertit la tipul operanului stng nainte e atribuire.
G.presiile e forma E4 op! E? se interpreteaz ca fiin ec/i&alente cu
e.presiile e forma E4 ! E4 op E?; totu!i E4 este e&aluat o singur at.
Exemplu$ e.presia : 0! ;$& este ec/i&alent cu
: ! : 0 (;$&)
!i nu cu
: ! : 0 ; $ &
Pentru operatorii $! !i 7!$ operanul stng poate fi !i un pointer$ n care caz
operanul in reapta este con&ertit la ntreg (capitolul opt,. 'o%i operanzii in
reapta !i to%i operanzii in stnga care nu snt pointeri trebuie s fie e tip
aritmetic.
Atribuirea prescurtat este a&antajoas n cazul cn n membrul stng a&em
e.presii complicate$ eoarece ele se e&alueaz o singur at.
/.?. 0peratorul #ir'ul
Expresie-virgul$
expresie, expresie
@ perec/e e e.presii separate prin &irgul se e&alueaz e la stnga la reapta
!i &aloarea e.presiei in stnga se neglijeaz. 'ipul !i &aloarea rezultatului snt
cele ale operanului in reapta. Ace!ti operatori se grupeaz e la stnga la
reapta. =n conte.tele n care &irgula are un sens special$ (e e.emplu ntr-o list
e argumente reale ale unei func%ii !i lista e ini%ializare,$ operatorul &irgul
escris aici poate aprea numai n paranteze. 0e e.emplu func%ia#
f(a,(t!,,t$.),c)
33333333333333333333333333333333333333333333
BB
are trei argumente$ intre care al oilea are &aloarea A. G.presia acestui argument
este o e.presie &irgul. =n calculul &alorii lui se e&alueaz nti e.presia in stnga
!i se ob%ine &aloarea B pentru t$ apoi cu aceast &aloare se e&alueaz a oua
e.presie !i se ob%ine t=A. Prima &aloare a lui t se piere.
/.1@. &recedena 7i ordinea de e#aluare
'abelul e la sfr!itul acestei sec%iuni constituie un rezumat al regulilor e
preceen% !i asociati&itate ale tuturor operatorilor.
@peratorii in aceea!i linie au aceea!i preceen%; liniile snt scrise n orinea
escresctoare a preceen%ei$ astfel e e.emplu operatorii 0$ + !i " au to%i aceea!i
preceen%$ care este mai mare ect aceea a operatorilor $ !i 7.
0up cum s-a men%ionat eja$ e.presiile care con%in unul intre operatorii
asociati&i sau comutati&i (0$ $$ #$ L$ I, pot fi rearanjate e compilator c/iar ac
con%in paranteze. =n cele mai multe cazuri aceasta nu prouce nici o iferen%; n
cazurile n care o asemenea iferen% ar putea aprea pot fi utilizate &ariabile
temporare e.plicite$ pentru a for%a orinea e e&aluare.
1imbajul C$ ca !i multe alte limbaje$ nu specific n ce orine snt e&alua%i
operanzii unui operator. 0m n continuare ou e.emple#
: ! f() $ 8();
a)i* ! i$$;
=n asemenea situa%ii trebuie memorate rezultate intermeiare n &ariabile
temporare pentru a garanta o e.ecu%ie n orinea orit.
*ingurele cazuri n care se garanteaz e&aluarea e la stnga la reapta se
refer la operatorii pentru e.presii logice ## !i II. =n aceste cazuri se garanteaz
n plus un numr minim e e&aluri.
0perator Asociati#itate
() )* 7> .
stnga la reapta
% $$ 77 7 (tip) 0 # si9eof
reapta la stnga
0 + "
stnga la reapta
$ 7
stnga la reapta
<< >>
stnga la reapta
< <! > >!
stnga la reapta
!! %!
stnga la reapta
#
stnga la reapta
L
stnga la reapta
I
stnga la reapta
##
stnga la reapta
II
stnga la reapta
OP
reapta la stnga
! op!
reapta la stnga
33333333333333333333333333333333333333333333
BD
,
stnga la reapta
33333333333333333333333333333333333333333333
BA
1. Instruciuni
=ntr-un program scris n limbajul C instruc%iunile se e.ecut sec&en%ial$ n
afar e cazul n care se inic altfel.
+nstruc%iunile pot fi scrise cte una pe o linie pentru o lizibilitate mai bun$ ar
nu este obligatoriu.
1.1. Instruciunea expresie
Cele mai multe instruc%iuni snt instruc%iuni expresie. @ e.presie e&ine
instruc%iune ac ea este urmat e punct !i &irgul.
a ! ' $ c;
n$$;
scanf(. . .);
=n limbajul C punct !i &irgula este un terminator e instruc%iune !i este
obligatoriu.
@ instruc%iune e atribuire poate aprea pe post e e.presie ntr-o alt
instruc%iune. Kunc%ia strcp; copiaz !irul s peste !irul t.
(oid strcp;(char t)*, const char s)*) {
int i ! 0;
while (t)i*!s)i*) i$$;

G.presia t)i*!s)i* este o atribuire !i are &aloarea True sau !alse n


func%ie e &aloarea s)i*.
1.. Instruciunea compus sau blocul
+nstruc%iunea compus este o grupare e eclara%ii !i instruc%iuni nc/ise ntre
acolae. Aceasta a fost introus cu scopul e a folosi mai multe instruc%iuni acolo
une sinta.a cere o instruc%iune. +nstruc%iunea compus sau blocul este
ec/i&alent sintactic cu o singur instruc%iune.
Kormat#
{
list#declaratori
list#instruciuni

0ac anumi%i ientificatori in lista#declaratori au fost eclara%i anterior$


atunci eclara%ia e.terioar este ignorat pe urata blocului$ up care !i reia
sensul su.
33333333333333333333333333333333333333333333
BE
@rice ini%ializare pentru &ariabilele auto !i re8ister se efectueaz la
fiecare intrare n bloc. +ni%ializrile pentru &ariabilele static se e.ecut numai o
singur at cn programul ncepe s se e.ecute.
"n bloc se termin cu o acola reapt care nu este urmat nicioat e
caracterul punct !i &irgul.
1.%. Instruciunea if
*inta.a instruc%iunii coni%ionale if amite ou formate#
if (expresie) if (expresie) instruciune-4
instruciune-4 else instruciune-?
+nstruc%iunea if se folose!te pentru a lua ecizii. =n ambele cazuri se
e&alueaz e.presia !i ac ea este adevrat (eci iferit e zero, se e.ecut
instruciune-4. 0ac e.presia este fals (are &aloarea zero, !i instruc%iunea if are
!i parte e else atunci se e.ecut instruciune-?.
=n al oilea caz una !i numai una intre cele ou instruc%iuni se e.ecut.
0eoarece un if testeaz pur !i simplu &aloarea numeric a unei e.presii$ se
amite o prescurtare !i anume#
if (expresie)
n loc e#
if (expresie != 0)
0eoarece partea else a unei instruc%iuni if este op%ional$ e.ist o
ambiguitate cn un else este omis intr-o sec&en% e if imbricat. Aceasta se
rezol& asociin else cu ultimul if care nu are else.
if (n>0) if (n>0) {
if (a>') if (a>')
9 ! a; 9 ! a;
else
9 ! '; else
9 ! ';
=n e.emplul e mai sus$ n primul caz partea else se asociaz if-ului in
interior. 0ac nu orim acest lucru atunci folosim acolaele pentru a for%a
asocierea$ ca n al oilea caz.
+nstruc%iunea coni%ional amite !i construc%ia else8if#
if (e)presie81) instruciune81
else
if (e)presie8) instruciune8
else
if (e)presie8%) instruciune8%
else instruciune8/
33333333333333333333333333333333333333333333
B6
Aceast casca e if-uri se folose!te frec&ent n programe$ ca mo e a
e.prima o ecizie multipl.
G.presiile se e&alueaz n orinea n care apar; ac se ntlne!te o e.presie
ae&rat$ atunci se e.ecut instruc%iunea asociat cu ea !i astfel se termin
ntregul lan%.
@ricare instruc%iune poate fi o instruc%iune simpl sau un grup e instruc%iuni
ntre acolae.
+nstruc%iunea up ultimul else se e.ecut n cazul n care nici o e.presie nu
a fost ae&rat.
0ac n acest caz nu e.ist nici o ac%iune e.plicit e fcut$ atunci ultima
parte poate s lipseasc#
else instruciune8/
Pot e.ista un numr arbitrar e construc%ii#
else if (expresie) instruciune
grupate ntre un if ini%ial !i un else final.
=ntoteauna un else se asociaz cu ultimul if ntlnit.
1./. Instruciunile while 7i do
Kormatul instruc%iunii while#
while (expresie) instruciune
+nstruc%iunea se e.ecut repetat atta timp ct &aloarea e.presiei este iferit
e zero. 'estul are loc naintea fiecrei e.ecu%ii a instruc%iunii. Prin urmare ciclul
este urmtorul# se testeaz coni%ia in paranteze ac ea este ae&rat (e.presia
in paranteze are o &aloare iferit e zero, se e.ecut corpul instruc%iunii
while$ se &erific in nou coni%ia$ ac ea este ae&rat se e.ecut in nou
corpul instruc%iunii. Cn coni%ia e&ine fals (&aloarea e.presiei in paranteze
este zero, se continu e.ecu%ia cu instruc%iunea e up corpul instruc%iunii
while$ eci instruc%iunea while se termin.
Kormatul instruc%iunii do#
do instruciune
while (expresie);
+nstruc%iunea se e.ecut repetat pn cn &aloarea e.presiei e&ine zero.
'estul are loc dup fiecare e.ecu%ie a instruc%iunii.
unsi8ned n, c ! 0; unsi8ned n, c ! 0;
scanf(""u",#n); scanf(""u",#n);
while (n>0) { do {
n +! &0; c$$; c$$; n +! &0;
while (n>0);
printf(""u",c); printf(""u",c);
33333333333333333333333333333333333333333333
BC
*ec&en%a in stnga afi!eaz numrul e cifre zecimale ale &alorii lui n numai
ac n > 7$ altfel afi!eaz zero. *ec&en%a in reapta afi!eaz numrul e cifre
zecimale ale &alorii lui n n orice coni%ii.
1.1. Instruciunea for
Kormat#
for (expresie-4; expresie-?; expresie-B) instruciune
Aceast instruc%iune este ec/i&alent cu sec&en%a#
expresie-4;
while (expresie-?) {
instruciune;
expresie-B;

$xpresie-4 constituie ini%ializarea ciclului !i se e.ecut o singur at naintea


ciclului. $xpresie-? specific testul care controleaz ciclul. Gl se e.ecut naintea
fiecrei itera%ii. 0ac coni%ia in test este ae&rat atunci se e.ecut corpul
ciclului$ up care se e.ecut expresie-B$ care const e cele mai multe ori n
moificarea &alorii &ariabilei e control al ciclului. *e re&ine apoi la ree&aluarea
coni%iei. Ciclul se termin cn coni%ia e&ine fals.
@ricare intre e.presiile instruc%iunii for sau c/iar toate pot lipsi.
0ac lipse!te expresie-?$ aceasta implic faptul c clauza while este
ec/i&alent cu while (&)$ ceea ce nseamn o coni%ie toteauna ae&rat.
Alte omisiuni e e.presii snt pur !i simplu eliminate in e.panarea e mai sus.
+nstruc%iunile while !i for permit un lucru emn e obser&at$ !i anume# ele
e.ecut testul e control la nceputul ciclului !i naintea intrrii n corpul
instruc%iunii.
0ac nu este nimic e fcut$ nu se face nimic$ cu riscul e a nu intra nicioat
n corpul instruc%iunii.
Exemple. 4, =n primul capitol$ al treilea !i al patrulea program folosesc
instruc%iunea for pentru a parcurge un !ir e &alori. * notm faptul c fiecare
e.presie poate fi orict e comple.. *ec&en%a urmtoare etermin suma primelor
n numere naturale.
unsi8ned s,i;
scanf(""u",#n);
for (s!0,i!&; i<!n; i$$)
s $! i;
printf(""u",s);
33333333333333333333333333333333333333333333
BF
?, Kunc%ia strlen(s) returneaz lungimea !irului e caractere s$ e.cluzn
caracterul terminal null.
int strlen(const char s)*) {
int n;
for (n!0; s)i*; $$n) ;
return n;

B, +nstruc%iunea e ini%ializare (expresie-4, trebuie s fie una singur$ e


aceea$ ac a&em mai multe opera%ii e fcut$ ele trebuie separate prin &irgul !i
nu prin punct !i &irgul. Aceea!i obser&a%ie este &alabil !i pentru expresie-B.
Kunc%ia strre( in&erseaz un !ir e caractere#
(oid strre((char s)*) {
int i,H;
for (i!0,H!strlen(s)7&; i<H; i$$,H77) {
char c ! s)i*;
s)i* ! s)H*;
s)H* ! c;

D, Relum problema in sec%iunea preceent# nu-se o &aloare natural n$


s se etermine numrul e cifre zecimale.
unsi8ned n,c;
scanf(""u",#n);
for (c!%n; n; c$$)
n +! &0;
printf(""u",c);
A, Kunc%ia strcp; poate fi implementat !i astfel.
(oid strcp;(char t)*, const char s)*) {
int i;
for (i!0; t)i*!s)i*; i$$) ;

1.;. Instruciunea switch


+nstruc%iunea switch este o ecizie multipl special !i etermin transferul
controlului unei instruc%iuni sau unui bloc e instruc%iuni intr-un !ir e
instruc%iuni n func%ie e &aloarea unei e.presii.
Kormat#
switch (expresie) instruciune#bloc
G.presia este supus la con&ersiile aritmetice obi!nuite ar rezultatul e&alurii
trebuie s fie e tip ntreg.
33333333333333333333333333333333333333333333
D7
Kiecare instruc%iune in corpul instruc%iunii switch poate fi etic/etat cu una
sau mai multe prefi.e case astfel#
case expresie#constantP
une expresie#constant trebuie s fie e tip ntreg.
Poate e.ista e asemenea cel mult o instruc%iune etic/etat cu
defaultP
Cn o instruc%iune switch se e.ecut$ se e&alueaz e.presia in paranteze
!i &aloarea ei se compar cu fiecare constant in fiecare case.
0ac se gse!te o constant case egal cu &aloarea e.presiei$ atunci se
e.ecut sec&en%a care urmeaz up case-ul respecti&.
0ac nici o constant case nu este egal cu &aloarea e.presiei !i ac e.ist
un prefi. default$ atunci se e.ecut sec&en%a e up el$ altfel nici o
instruc%iune in switch nu se e.ecut.
Prefi.ele case !i default nu altereaz flu.ul e control$ care continu
printre astfel e prefi.e.
Pentru ie!irea in switch se folose!te instruc%iunea 'rea- sau return.
0ac o sec&en% e instruc%iuni este urmat e un nou case fr s fie nc/eiat
cu 'rea- sau return$ nu se iese din switch. =n concluzie$ ie!irea in
switch trebuie s fie e.plicit.
Exemplu. "n meniu poate fi implementat astfel#
char op)50*;
do {
8ets(op);
switch (op)0*) {
case BiBP case BQBP
Qnitiali9are(. . .); 'rea-;
case BaBP case B=BP
=dau8are(. . .); 'rea-;
case BmBP case BCBP
Codificare(. . .); 'rea-;
case BsBP case BMBP
Mter8ere(. . .); 'rea-;
case BcBP case BEBP
Eonsultare(. . .); 'rea-;
case BlBP case B?BP
?istare(. . .); 'rea-;
defaultP
Aroare(. . .); 'rea-;

while (op%!BtB ## op%!BRB);
33333333333333333333333333333333333333333333
D4
=n func%ie e op%iunea orit (primul caracter in !irul op, se selecteaz
ac%iunea asociat &alorii respecti&e. 0ac op%iunea nu este recunoscut$ se
selecteaz ac%iunea care semnaleaz o eroare. 'oate aceste ac%iuni se e.ecut n
carul unui ciclu do. Acesta se nc/eie n momentul n care se introuce op%iunea
BtB sau BRB.
1.<. Instruciunile 'rea- 7i continue
Kormatul instruc%iunii 'rea-#
'rea-;
Aceast instruc%iune etermin terminarea celei mai interioare instruc%iuni
while$ do$ for sau switch care o con%ine. Controlul trece la instruc%iunea
care urmeaz up instruc%iunea astfel terminat.
$xemplu. Kie un !ir e caractere s; s se elimine spa%iile e la sfr!itul !irului.
for (i!strlen(s)7&; i>!0; i77)
if (s)i*%!B B) 'rea-;
s)i$&* ! 0;
Kormatul instruc%iunii continue#
continue;
Aceast instruc%iune etermin trecerea controlului la por%iunea e continuare
a ciclului celei mai interioare instruc%iuni while$ do sau for care o con%ine$
aic la sfr!itul ciclului !i reluarea urmtoarei itera%ii a ciclului. =n while !i do
se continu cu testul$ iar n for se continu cu expresie#B.
-ai precis n fiecare intre instruc%iunile#
while (...) {
. . .
continP;

for (...) {
. . .
continP;

do {
. . .
continP;
while (...);
ac apare o instruc%iune continue aceasta este ec/i&alent cu un salt la
etic/eta contin. 0up continP urmeaz o instruc%iune &i.
*ec&en%a urmtoare prelucreaz numai elementele poziti&e ale unui masi&.
for (i!0; i<n; i$$) {
if (a)i*<0) +0 sare peste elementele ne8ati(e 0+
continue;
& & & '( prelucrea) elementele po)itive ('

+n exemplu de utilizare a instruciunii 8oto
Pentru a efectua un salt e.plicit n interiorul unui program C se poate folosi !i
instruc%iunea 8oto$ e!i aceasta conuce la programe greu e &erificat.
33333333333333333333333333333333333333333333
D?
Kie ou masi&e$ a cu n elemente !i ' cu m elemente. * se etermine ac
e.ist cel pu%in o &aloare comun. @ sec&en% care utilizeaz instruc%iunea 8oto
se poate scrie astfel#
for (i!0; i<n; i$$)
for (H!0; H<m; H$$)
if (a)i*!!')H*)
8oto e8ale;
>Y )u s-a gsit nici un element; prelucrri necesare acestui caz Y>
8oto contin;
e8aleP
>Y "n element comun pe pozi%iile i !i j; prelucrri necesare acestui caz Y>
continP
>Y Continu e.ecu%ia up finalizarea prelucrrilor pentru cazul epistat Y>
0ac scriem o func%ie n acest scop$ nu a&em ne&oie s folosim instruc%iunea
8oto. Kunc%ia &a memora pozi%iile i !i H n &ariabile ale cror arese snt
comunicate e o func%ie apelant. 0ac nu e.ist o &aloare comun atunci aceste
&ariabile &or con%ine &alori negati&e.
(oid Eomun(dou'le a)*, int n, dou'le ')*, int m,
int 0pi, int 0pH) {
int i,H;
0pi ! 0pH ! 7&;
for (i!0; i<n; i$$)
for (H!0; H<m; H$$)
if (a)i*!!')H*) {
0pi ! i; 0pH ! H;
return;

Aceast func%ie poate fi apelat astfel#


Eomun(a,n,',m,#-,#l);
1.>. Instruciunea return
@ instruc%iune return permite ie!irea intr-o func%ie !i transmiterea
controlului apelantului func%iei. @ func%ie poate returna &alori apelantului su$ prin
intermeiul unei instruc%iuni return.
Kormate#
return;
return expresie;
Primul format se folose!te pentru func%ii e tip (oid$ care nu returneaz n
mo e.plicit o &aloare. =n al oilea format &aloarea e.presiei este returnat
33333333333333333333333333333333333333333333
DB
func%iei apelante. 0ac este ne&oie$ e.presia este con&ertit$ ca ntr-o atribuire$ la
tipul func%iei n care ea apare.
0etalii espre instruc%iunea return &or fi prezentate n capitolul urmtor.
1.11. Instruciunea #id
Kormat#
;
+nstruc%iunea &i este util ntr-o instruc%iune compus$ sau pentru a
introuce un corp nul ntr-o instruc%iune e ciclare care cere corp al instruc%iunii$
ca e e.emplu while sau for.
Exemplu$
for (nc!0; s)nc*; $$nc) ;
=n aceast instruc%iune$ care numr caracterele unui !ir$ corpul lui for este
&i$ eoarece toat acti&itatea se face n partea e test !i actualizare ar sinta.a lui
for cere un corp al instruc%iunii. +nstruc%iunea &i satisface acest lucru.
Am precizat anterior c o instruc%iune compus nu este urmat nicioat e
caracterul punct !i &irgul.
if (...) {
. . .
;
else . . .
Aceast sec&en% este gre!it$ eoarece up instruc%iunea compus urmeaz o
instruc%iune &i$ !i clauza else apare izolat fr a a&ea nici o instruc%iune if
asociat.
33333333333333333333333333333333333333333333
DD
;. Auncii
Kunc%iile snt elementele e baz ale unui program scris n C# orice program$
e orice imensiune$ const in una sau mai multe func%ii$ care specific opera%iile
care trebuie efectuate.
@ func%ie ofer un mo con&enabil e ncapsulare a anumitor calcule ntr-o
cutie neagr care poate fi utilizat apoi fr a a&ea grija con%inutului ei. Kunc%iile
snt ntr-ae&r singurul mo e a face fa% comple.it%ii programelor mari$ permit
esfacerea programelor mari n moule mai mici$ !i au utilizatorului posibilitatea
e a ez&olta programe$ folosin ceea ce al%ii au fcut eja$ n loc s o ia e la
nceput.
1imbajul C a fost conceput s permit efinirea e func%ii eficiente !i u!or e
mnuit. =n general e bine s concepem programe constituite in mai multe func%ii
mici ect in pu%ine func%ii e imensiuni mari. "n program poate fi mpr%it n
mai multe fi!iere surs n mo con&enabil$ iar fi!ierele surs pot fi compilate
separat.
"n program C const intr-o sec&en% e efini%ii e.terne e func%ii !i e ate.
=n fiecare program trebuie s e.iste o func%ie cu numele impus main; orice
program !i ncepe e.ecu%ia cu func%ia main. Celelalte func%ii snt apelate in
interiorul func%iei main. "nele intre func%iile apelate snt efinite n acela!i
program$ altele snt con%inute ntr-o bibliotec e func%ii.
;.1. Be*iniia unei *uncii
@ func%ie se efine!te astfel#
clas tip#funcie nume#funcie(list#parametri) {
list#declaraii
list#instruciuni

=ntr-o eclara%ie$ numele func%iei este urmat e paranteze c/iar ac lista


parametrilor este &i. 0ac func%ia are mai mul%i parametri$ eclara%iile acestora
snt separate prin &irgul. "n eclarator e func%ie care nu o !i efine!te nu
con%ine corpul func%iei$ acesta fiin nlocuit cu caracterul punct !i &irgul.
0up cum se obser&$ iferitele pr%i pot s lipseasc; o func%ie minim este#
dumm;() {
func%ia care nu face nimic. Aceast func%ie poate fi util n programe$ %inn locul
unei alte func%ii n ez&oltarea ulterioar a programului.
)umele func%iei poate fi preceat e un tip$ ac func%ia returneaz o &aloare
e alt tip ect int$ sau ac tipul acesteia este (oid. @ func%ie e tip (oid nu
returneaz o &aloare n mo e.plicit$ e.ecut oar o sec&en% e instruc%iuni.
33333333333333333333333333333333333333333333
DA
)umele func%iei poate fi e asemenea preceat e clasa e memorie e:tern
sau static$ al%i specificatori e clas nu snt ami!i. 0ac nici un specificator
e clas e memorie nu este prezent$ atunci func%ia este automat eclarat e.tern$
eoarece n C nu se amite ca o func%ie s fie efinit n interiorul altei func%ii.
0ac o func%ie este eclarat static$ ea poate fi apelat numai in fi!ierul une
a fost efinit.
Comunicarea ntre func%ii se face prin argumente !i &alori returnate e func%ii.
Comunicarea ntre func%ii poate fi fcut !i prin intermeiul &ariabilelor globale.
*e recoman ca efini%ia unei func%ii sau cel pu%in eclararea ei s se fac
nainte e orice apelare. Astfel compilatorul poate epista imeiat neconcoran%e
ntre tipurile e parametri.
* ilustrm mecanismul efinirii unei func%ii scriin func%ia factorial
fact(n). Aceast func%ie este folosit ntr-un program care calculeaz &aloarea
e.presiei
,T ( T
T
, n ,
n
,
n
C

=
#include <stdio.h>
int fact(int n) {
int i,p;
for (p!i!&; i<!n; i$$)
p 0! i;
return p;

int main() {
int n,-,i;
puts("Salori n si -P ");
scanf(""d "d",#n,#-);
printf("Eom'inariP"d\n",fact(n)+fact(-)+fact(n7-));
return 0;

Kunc%ia fact este apelat n programul principal e trei ori$ fiecare apel
transmite func%iei un argument.
@ sec&en% mai eficient < in punctul e &eere al &olumului e calcul !i al
corectituinii acestora < se bazeaz pe urmtoarea formul#
,
, n n n
,
n
C
4
...
?
4
4
+

=
Kunc%ia fact prouce rezultate eronate pentru &alori mari ale lui n (n C$
sisteme e calcul pe 4E bi%i; n 4?$ sisteme e calcul pe B? e bi%i,. Kunc%ia
com'$ bazat pe rela%ia e mai sus$ permite operarea cu &alori mai mari ale
parametrilor n !i -.
33333333333333333333333333333333333333333333
DE
int com'(int n, int -) {
int i,p;
for (p!i!&; i<!-; i$$)
p ! p 0 (n7i$&) + i;
return p;

AtenieT =n acest caz nu putem folosi forma compact


p 0! (n7i$&) + i;
eoarece se &a e&alua mai nti e.presia in reapta !i rezultatul &a fi nmul%it cu
&aloarea lui p. Astfel se &or ob%ine rezultate eronate pentru orice &aloare n par.
;.. Apelul *unciilor+ *uncii recursi#e
=n limbajul C orice func%ie este apelat prin numele ei$ urmat e lista real a
argumentelor$ nc/is ntre paranteze.
0ac ntr-o e.presie numele func%iei nu este urmat imeiat e o parantez
stnga ($ aic nu se apeleaz func%ia respecti&$ se genereaz un pointer la
func%ie. 0etalii espre acest subiect &or fi prezentate n capitolul opt.
Kunc%iile n C pot fi efinite recursi&$ eci o func%ie se poate apela pe ea ns!i
fie irect$ fie inirect. =n general ns recursi&itatea nu face economie e
memorie$ eoarece trebuie men%inut o sti& cu &alorile e prelucrat.
Exemple. 4, Kunc%ia rcom' implementeaz formula recursi& e calcul a
&alorii
,
n
C #
int rcom'(int n, int -) {
if (n!!- II -!!0) return &;
else return rcom'(n,-7&) $ rcom'(n7&,-7&);

?, Kunc%ia rfi'o implementeaz proceura recursi& e calcul a termenului


e rang n in !irul lui Kibonacci#

> +

=

4 $
4 $
? 4
n ! !
n n
!
n n
n
int rfi'o(int n) {
if (n<!&) return &;
else return fi'o(n7&) $ fi'o(n7.);

33333333333333333333333333333333333333333333
D6
*implitatea cu care snt efinite aceste func%ii ar putea cuceri imeiat pe un
programator nee.perimentat. 'rebuie s atragem aten%ia asupra faptului c cele
ou efini%ii au o comple.itate e.ponen%ial# pentru o &aloare oarecare a lui n$
numrul e opera%ii elementare efectuate (aritmetice !i logice, este apro.imati&
propor%ional cu ?
n
.
0e aceea recursi&itatea este justificat numai n situa%ia n care !tim cu
certituine c se ob%ine o efini%ie a&n comple.itate acceptabil. "n e.emplu n
acest sens &a fi at n capitolul nou# gestionarea unei structuri e ate e tip
arbore.
Am &zut n sec%iunea preceent o efini%ie simpl !i eficient a unei func%ii
care calculeaz &aloarea
,
n
C . =n continuare prezentm o efini%ie simpl !i
eficient pentru eterminarea unui termen in !irul lui Kibonacci#
int fi'o(int n) {
int a,',c,i;
a ! 0; ' ! &; c ! n;
for (i!.; i<!n; i$$) {
c ! a $ ';
a ! '; ' ! c;

return p;

Kunc%ia folose!te &ariabilele locale a !i ' pentru a memora termenii !


,<?
!i !
,<
4
. 1a un anumit pas se calculeaz !
,
= !
,<?
+ !
,<4
n &ariabila c$ !i apoi &ariabilele
a !i b memoreaz termenii !
,<4
!i !
,
.
;.%. !e#enirea din *uncii
Re&enirea intr-o func%ie se face prin intermeiul unei instruc%iuni return.
Jaloarea pe care o func%ie o calculeaz poate fi returnat prin instruc%iunea
return$ care up cum am &zut are ou formate. Ca argument al acestei
instruc%iuni poate aprea orice e.presie amis n C. Kunc%ia returneaz &aloarea
acestei e.presii func%iei apelante.
@ func%ie e tip (oid nu returneaz n mo e.plicit o &aloare. @ instruc%iune
return$ fr e.presie ca parametru$ cauzeaz oar transferul controlului func%iei
apelante.
1a rnul su func%ia apelant poate ignora &aloarea returnat.
0ac nu se precizeaz tipul func%iei$ aceasta returneaz o &aloare e tip ntreg.
0ac se ore!te ca func%ia s returneze un alt tip$ atunci numele tipului trebuie s
precea numele func%iei.
33333333333333333333333333333333333333333333
DC
Pentru a e&ita orice confuzie recomanm ca tipul &alorii returnate e func%ie
s fie ntoteauna precizat$ iar ac orim n mo e.pres ca func%ia s nu
returneze o &aloare n mo e.plicit s o eclarm e tip (oid.
0e e.emplu$ func%ia atof(s) in biblioteca asociat limbajului C
con&erte!te !irul s e cifre n &aloarea sa n ubl precizie. Putem eclara func%ia
sub forma#
dou'le atof(char s)*);
0ac o func%ie returneaz o &aloare e tip char$ nu este ne&oie e nici o
eclara%ie e tip atorit con&ersiilor implicite. 'oteauna tipul char este
con&ertit la int n e.presii.
;./. Ar'umentele *unciei 7i transmiterea parametrilor
@ meto e a comunica atele ntre func%ii este prin argumente. Parantezele
care urmeaz imeiat up numele func%iei nc/i lista argumentelor.
=n limbajul C argumentele func%iilor snt transmise prin &aloare. Aceasta
nseamn c n C func%ia apelat prime!te &alorile argumentelor sale ntr-o copie
particular e &ariabile locale (concret pe sti&,.
Apelul prin &aloare este o posibilitate$ ar nu !i o obligati&itate. Apelul prin
&aloare conuce la programe mai compacte cu mai pu%ine &ariabile e.terne$
eoarece argumentele pot fi tratate ca &ariabile locale$ !i care pot fi moificate
con&enabil n rutina apelat.
Ca e.emplu$ prezentm o &ersiune a func%iei factorial care face uz e acest
fapt#
int fact(int n) {
int p;
for (p!&; n>0; 77n)
p 0! n;
return p;

Argumentul n este utilizat ca o &ariabil automatic !i este ecrementat pn


e&ine zero; astfel nu este ne&oie e nc o &ariabil i. @rice opera%ii s-ar face
asupra lui n n interiorul func%iei$ ele nu au efect asupra argumentului pentru care
func%ia a fost apelat.
0ac totu!i se ore!te alterarea efecti& a unui argument al func%iei apelante$
acest lucru se realizeaz cu ajutorul pointerilor sau al &ariabilelor eclarate
e.terne. =n cazul pointerilor$ func%ia apelant trebuie s furnizeze aresa &ariabilei
care trebuie moificat (te/nic printr-un pointer la aceast &ariabil,$ iar func%ia
apelat trebuie s eclare argumentul corespunztor ca fiin un pointer. Referirea
la &ariabila care trebuie moificat se face prin aresare inirect (capitolul opt,.
33333333333333333333333333333333333333333333
DF
Printre argumentele func%iei pot aprea !i nume e masi&e. =n acest caz
&aloarea transmis func%iei este n realitate aresa e nceput a masi&ului
(elementele masi&ului nu snt copiate,. Prin ine.area acestei &alori func%ia poate
a&ea acces !i poate moifica orice element in masi&. 0ac a fost precizat
calificatorul const$ moificarea nu este permis.
Pentru func%iile cu numr &ariabil e parametri stanarul A)*+ efine!te o
construc%ie special ... (trei puncte, numit elips. Acesta este e e.emplu cazul
func%iilor e citire !i scriere cu format (familiile ...scanf !i ...printf < capitolul
zece,. =n acest caz$ parametrii fic!i snt &erifica%i la compilare$ iar cei &ariabili snt
transmi!i fr nici o &erificare.
;.1. :)emple de *uncii 7i pro'rame
4. Acest e.emplu este un program e cutare !i afi!are a tuturor liniilor intr-
un te.t care con%in o anumit configura%ie e caractere$ e e.emplu cu&ntul
englezesc UtheU. *tructura e baz a acestui program este#
while (mai e.ist linii surs)
if (linia con%ine configura%ia e caractere)
afi!eaz linia
Pentru a citi cte o linie in fi!ierul e intrare &om folosi func%ia 8ets in
bibliotec$ cunoscut in primul capitol une a fost folosit ntr-un e.emplu.
Aceast func%ie cite!te o linie e la intrarea stanar !i o epune ntr-un !ir e
caractere precizat prin argumentul acesteia. 0ac la intrarea stanar mai e.ist
linii (se mai poate citi, func%ia returneaz aresa !irului une a fost memorat
linia$ n caz contrar func%ia returneaz &aloarea )"11 (zero,.
Kunc%ia inde: caut configura%ia e caractere orit n interiorul liniei !i
furnizeaz pozi%ia sau ine.ul n !irul s$ une ncepe !irul t$ sau 4 ac linia nu
con%ine !irul t. Argumentele func%iei snt# s care reprezint aresa !irului e
stuiat$ !i t care reprezint configura%ia cutat.
Pentru afi!area unei linii folosim func%ia puts in bibliotec$ e asemenea
cunoscut in primul capitol.
Programul care realizeaz structura e mai sus este#
#include <stdio.h>
int inde:(char s)*, char t)*) {
+0 returneaz pozi%ia in !irul s une ncepe !irul t$ sau 4 0+
int i,H,-;
for (i!0; s)i*%!0; i$$) {
for (H!i, -!0; (t)-*%!0) ## (s)H*!!t)-*);
H$$, -$$) ;
if (t)-*!!0)
33333333333333333333333333333333333333333333
A7
return i;

return 7&;

int main() { +0 afi!eaz toate liniile care con%in cu&ntul Ut/eU 0+


char lin)50*;
while (8ets(lin)>0)
if (inde:(lin,"the")>!0)
puts(lin);

?. Kunc%ia atof con&erte!te un !ir e cifre in formatul A*C++ ntr-un numr


flotant n precizie ubl. Aceast func%ie accept un !ir care con%ine reprezentarea
unui numr zecimal (e&entual cu semn,$ compus in parte ntreag !i parte
frac%ionar (oricare putn lipsi,$ separate prin punct zecimal.
dou'le atof(char s)*) {
dou'le (al,fr;
int i,sn;
sn ! &; i ! 0;
if (s)0*!!B$B II s)0*!!B7B)
sn ! (s)i$$*!!B$B) O & P 7&;
for ((al!0; s)i*>!B0B ## s)i*<!B4B; i$$)
(al ! &0 0 (al $ s)i* 7 B0B;
if (s)i*!! B.B)
i$$;
for (fr!&; s)i*>!B0B ## s)i*<!B4B; i$$) {
(al ! &0 0 (al $s)i* 7 B0BP
fr 0! &0;

return sn 0 (al + fr;

B. Kunc%ia atoi con&erte!te un !ir e cifre n ec/i&alentul lor numeric ntreg.


int atoi(char s)*) {
int i,sn,(;
i ! 0; sn ! &;
if (s)i*!!B$B II s)i*!!B7B)
sn ! (s)i$$*!!B$B) O & P 7&;
for ((!i!0; s)i*>!B0B ## s)i*<!B4B; i$$)
( ! &0 0 ( $ s)i* 7 B0B;
return sn 0 (;

33333333333333333333333333333333333333333333
A4
D. Kunc%ia lower con&erte!te literele mari in setul e caractere A*C++ n
litere mici. 0ac lo:er prime!te un caracter care nu este o liter mare atunci l
returneaz nesc/imbat.
int lower(int c) {
if (c>!B=B ## c<!BTB)
return c $ BaB 7 B=B;
else
return c;

A. Kunc%ia 'inar; realizeaz cutarea &alorii : ntr-un masi& sortat ($ care


are n elemente.
int 'inar;(int :, int ()*, int n) {
int l,r,m;
l ! 0; r ! n 7 &;
while (l<!r) {
m ! (l $ r) + .;
if (()m*!!:) return m;
if (()m*<:) l ! m $ &;
else r ! m 7 &;

return 7&;

Kunc%ia returneaz pozi%ia lui : (un numr ntre 7 !i n4,$ ac : apare n (


sau 4 altfel.
33333333333333333333333333333333333333333333
A?
<. Be"#oltarea pro'ramelor mari
=n multe situa%ii este mai con&enabil s fragmentm un program mare n
moule mai mici$ pe care le putem ez&olta mai u!or inepenent unele e altele$
!i n final s le asamblm ntr-un singur program. 0e altfel acesta este principiul
e baz care se aplic la proiectele realizate n colecti&e e programatori.
0intre moulele (fi!ierele surs, care intr n compunerea programului$ unul
singur con%ine func%ia main. Acest moul apeleaz func%ii !i utilizeaz &ariabile
care pot fi efinite n alte moule$ cu alte cu&inte snt externe. 0eoarece aceste
moule snt compilate n mo inepenent$ este necesar un mecanism care s
permit o eclarare unitar a elementelor puse n comun. Astfel compilatorul
poate !ti n orice moment cel fel e parametri a!teapt o anumit func%ie$ sau n ce
conte.t poate fi utilizat o &ariabil.
1imbajul C ofer o facilitate e e.tensie cu ajutorul unui preprocesor e
macro-opera%ii simple. Kolosirea irecti&elor e compilare #define !i
#include este cea mai uzual meto pentru e.tensia limbajului$ caracterul C
(iez, inicn faptul c aceste linii &or fi tratate e ctre preprocesor. 1iniile
preceate e caracterul C au o sinta. inepenent e restul limbajului !i pot
aprea oriune n fi!ierul surs$ a&n efect e la punctul e efini%ie pn la
sfr!itul fi!ierului.
<.1. Includerea *i7ierelor
#include "nume-fiier"
Aceast linie realizeaz nlocuirea liniei respecti&e cu ntregul con%inut al
fi!ierului nume#fiier. Ki!ierul enumit este cutat n primul rn n irectorul
fi!ierului surs curent !i apoi ntr-o succesiune e irectoare stanar$ cum ar fi
biblioteca +-@ stanar asociat compilatorului.
1inia urmtoare caut fi!ierul nume#fiier numai n biblioteca stanar !i nu n
irectorul fi!ierului surs#
#include <nume-fiier>
0eseori$ o linie sau mai multe linii$ e una sau ambele forme apar la nceputul
fiecrui fi!ier surs pentru a inclue efini%ii comune (prin eclara%ii #define !i
eclara%ii e.terne pentru &ariabilele globale,.
Kacilitatea e incluere a unor fi!iere ntr-un te.t surs este eosebit e util
pentru gruparea eclara%iilor unui program mare. Ga &a asigura faptul c toate
fi!ierele surs &or primi acelea!i efini%ii !i eclara%ii e &ariabile$ n felul acesta
eliminnu-se un tip particular e erori. 0ac se moific un fi!ier inclus printr-o
linie #include$ toate fi!ierele care epin e el trebuie recompilate.
33333333333333333333333333333333333333333333
AB
<.. 9nlocuirea simbolurilor+ substituii macro
@ efini%ie e forma#
#define identificator ir#simboluri
etermin ca preprocesorul s nlocuiasc toate apari%iile ulterioare ale
ientificatorului cu ir#simboluri at (ir#simboluri nu se termin cu ; (punct !i
&irgul, eoarece n urma substitu%iei ientificatorului cu acest !ir ar aprea prea
multe caractere ; < unele situa%ii conuc c/iar la erori e sinta..
'ir#simboluri sau te.tul e nlocuire este arbitrar. =n mo normal el este tot
restul liniei ce urmeaz up ientificator. @ efini%ie ns poate fi continuat pe
mai multe linii$ introucn ca ultim caracter n linia e continuat caracterul \
(bacLslas/,.
"n ientificator care este subiectul unei linii #define poate fi reefinit
ulterior n program printr-o alt linie #define. =n acest caz$ prima efini%ie are
efect numai pn la efini%ia urmtoare. *ubstitu%iile nu se realizeaz n cazul n
care ientificatorii snt ncara%i ntre g/ilimele. 0e e.emplu fie efini%ia#
#define =?>= &
@riune &a aprea n programul surs ientificatorul =?>= el &a fi nlocuit cu
constanta &$ cu e.cep%ia unei situa%ii e forma#
printf("=?>=");
n care se &a afi!a c/iar te.tul *%!* !i nu constanta &$ eoarece ientificatorul
este ncarat ntre g/ilimele.
Aceast facilitate este eosebit e &aloroas pentru efinirea constantelor
simbolice ca n#
#define JC=< &00
int ta')JC=<*;
eoarece ntr-o e&entual moificare a imensiunii tabelului ta' se &a moifica
oar o singur linie n fi!ierul surs. @ linie e forma#
#define identif (identif#.,///,identif#n, ir#simboluri
n care nu e.ist spa%iu ntre primul ientificator !i caracterul ( (parantez stnga,
este o efini%ie pentru o macro-opera%ie cu argumente$ n care te.tul e nlocuire
(ir#simboluri, epine e moul n care se apeleaz macro-ul respecti&. Ca un
e.emplu s efinim o macro-opera%ie numit ma: n felul urmtor#
#define Ca:(a,') ((a)>(') O (a) P ('))
atunci linia intr-un program surs#
: ! Ca:(p$G,r$s);
&a fi nlocuit cu#
: ! ((p$G)>(r$s) O (p$G) P (r$s));
Aceast macro-efini%ie furnizeaz o funcie maximum care se e.paneaz
n co$ n loc s se realizeze un apel e func%ie. Acest macro &a ser&i pentru orice
33333333333333333333333333333333333333333333
AD
tip e ate$ nefiin ne&oie e iferite tipuri e func%ii ma.imum pentru iferite
tipuri e ate$ a!a cum este necesar n cazul func%iilor propriu-zise.
0ac se e.amineaz atent e.panarea lui Ca: se pot obser&a anumite
probleme ce pot genera erori$ !i anume# e.presiile fiin e&aluate e ou ori$ n
cazul n care ele con%in opera%ii ce genereaz efecte colaterale (apelurile e func%ii$
operatorii e incrementare, se pot ob%ine rezultate total eronate.
0e asemenea$ trebuie a&ut mare grij la folosirea parantezelor pentru a face
sigur orinea e&alurii orite. 0e e.emplu macro-opera%ia MGuare(:) efinit
prin#
#define MGuare(:) :0:
care se apeleaz n programul surs sub forma#
9 ! MGuare(9$&);
&a prouce un rezultat$ altul ect cel scontat$ atorit priorit%ii mai mari a
operatorului 0 fa% e cea a operatorului $.
<.%. Compilarea condiionat
@ linie e control a compilatorului e forma urmtoare &erific ac e.presia
constant este e&aluat la o &aloare iferit e zero#
#if expresie#constant
@ linie e control e forma urmtoare &erific ac ientificatorul a fost eja
efinit#
#ifdef identificator
@ linie e control e forma urmtoare &erific ac ientificatorul este
neefinit#
#ifndef identificator
'oate cele trei forme e linii e control preceente pot fi urmate e un numr
arbitrar e linii care$ e&entual$ pot s con%in o linie e control forma#
#else
!i apoi e o linie e control e forma#
#endif
0ac coni%ia supus &erificrii este ae&rat$ atunci orice linie ntre #else
!i #endif este ignorat. 0ac coni%ia este fals atunci toate liniile ntre testul e
&erificare !i un #else sau n lipsa unui #else pn la #endif snt ignorate.
'oate aceste construc%ii pot fi imbricate.
<./. :)emple
4, *e cite!te e la tastatur o perec/e e numere naturale p !i G. * se
etermine ac fiecare in cele ou numere este prim sau nu$ !i s se calculeze
cel mai mare i&izor comun.
33333333333333333333333333333333333333333333
AA
* rezol&m aceast problem folosin ou fi!iere surs. Primul con%ine
func%ia main !i apeleaz ou func%ii# eprim !i cmmdc. Al oilea fi!ier
implementeaz cele ou func%ii.
Prezentm mai nti un fi!ier /eaer (numere.h, care con%ine eclara%iile
celor ou func%ii.
#ifndef UJumereUH
#define UJumereUH
unsi8ned eprim(unsi8ned n);
unsi8ned cmmdc(unsi8ned p, unsi8ned G);
#endif
Ki!ierul surs princn.c con%ine func%iile main !i citire. * obser&m c
func%ia citire este eclarat static$ e aceea nu poate fi apelat e alte
moule.
#include <stdio.h>
#include "numere.h"
static (oid citire(unsi8ned 0n) {
scanf(""u",n);
if (eprim(0n))
printf(""u e prim\n",0n);
else
printf(""u nu e prim\n",0n);

int main() {
unsi8ned p,G,-;
citire(#p); citire(#G);
- ! cmmdc(p,G);
printf("EmmdcP "u\n",-);
return 0;

Ki!ierul surs numere.c este proiectat pentru a putea fi folosit n mai multe
aplica%ii care au ne&oie e astfel e func%ii. Prin incluerea fi!ierului numere.h
se garanteaz c efini%ia func%iilor este conform cu a!teptrile moulului
principal$ n care este inclus acela!i fi!ier /eaer.
#include "numere.h"
unsi8ned eprim(unsi8ned n) {
unsi8ned i,a,r;
if (n!!0) return 0;
if (n</) return &;
if ((n#&)!!0) return 0;
for (i!,; ; i$!.) {
r ! n"i;
if (r!!0) return 0;
33333333333333333333333333333333333333333333
AE
a ! n+i;
if (a<!i) return &;

unsi8ned cmmdc(unsi8ned p, unsi8ned G) {


while ((p>0) ## (G>0))
if (p>G) p "! G;
else G "! p;
if (p!!0) return G;
else return p;

Pentru a ob%ine un program e.ecutabil in aceste ou fi!iere se poate utiliza o


singur coman e compilare#
*c princ.c numere.c opiuni-de-compilare
une *c este numele compilatorului folosit (e.emplu# 'cc$ 8cc,. @p%iunile e
compilare (atunci cn snt necesare, snt specifice meiului e programare
folosit.
?, Al oilea proiect gestioneaz o list e &alori numerice asupra creia se
efectueaz urmtoarele opera%ii#
< ini%ializare$ opera%ie realizat automat la lansarea n e.ecu%ie a programului;
< augarea unei &alori n list$ ac aceasta nu e.ist eja;
< interogare# o anumit &aloare se afl n listZ
< !tergerea unei &alori in list;
< men%inerea n permanen% a unei rela%ii e orine cresctoare.
-asi&ul ?is)* memoreaz lista e &alori$ care are un numr e ne
elemente$ ini%ial zero.
Prezentm mai nti un fi!ier /eaer (lista.h, care con%ine eclara%iile celor
trei func%ii$ precum !i a &ariabilelor e.terne ?is !i ne.
#ifndef U?istaUH
#define U?istaUH
e:tern dou'le ?is)*;
e:tern int ne;
int =dau8are(dou'le ();
int Mter8ere(dou'le ();
int Qntero8are(dou'le ();
#endif
Ki!ierul surs princl.c con%ine func%ia main. Acesta a!teapt e la
terminal op%iunea utilizatorului$ urmat e un spa%iu !i e &aloarea care se ore!te
a fi prelucrat. =n func%ie e op%iune se apeleaz func%ia corespunztoare sau se
afi!eaz un mesaj e eroare. 0up fiecare opera%ie se afi!eaz lista &alorilor.
33333333333333333333333333333333333333333333
A6
#include <stdio.h>
#include "lista.h"
int main() {
dou'le atof(char s)*);
dou'le (;
int i;
char o)50*;
do {
8ets(o); ( ! atof(op$.);
switch (o)0*) {
case BaBP
i ! =dau8are(();
'rea-;
case BsBP
if (Mter8ere(())
puts("M7a sters");
else puts("Ju e:ista");
'rea-;
case BiBP
i ! Qntero8are(();
if (i>!0)
printf("Vo9itiaP "d\n",i);
else puts("Ju e:ista");
'rea-;
defaultP
puts("Wptiune eronata");
'rea-;

puts("?istaP");
for (i!0; i<ne; i$$)
printf(" ".,lf",?is)i*);
puts("");
while (o%!BtB);
return 0;

Ki!ierul surs lista.c efine!te &ariabilele ?is)* !i ne$ !i func%iile


=dau8are$ Qntero8are$ Mter8ere.
Kunc%ia =dau8are aaug o &aloare ( n list ac aceasta nu e.ist.
Jalorile mai mari snt eplasate spre reapta cu o pozi%ie pentru a face loc noii
&alori. Returneaz pozi%ia &alorii n list up (o e&entual, augare.
Kunc%ia Mter8ere !terge o &aloare ( in list ac aceasta e.ist. Jalorile
mai mari snt eplasate spre stnga cu o pozi%ie pentru a pstra lista compact.
Returneaz True ac opera%ia a reu!it !i !alse n caz contrar.
33333333333333333333333333333333333333333333
AC
Kunc%ia Qntero8are returneaz pozi%ia pe care se afl &aloarea ( n list$
ac aceasta e.ist$ sau 6& n caz contrar. 0eoarece lista este oronat se face o
cutare binar. Aceast func%ie este apelat !i e func%ia =dau8are.
#include "lista.h"
dou'le ?is)&00*;
int ne;
int =dau8are(dou'le () {
int -;
- ! Qntero8are(();
if (-<0) {
for (-!ne7&; ->!0; -77)
if (?is)-*>()
?is)-$&* ! ?is)-*;
else 'rea-;
?is)-$&* ! (; ne$$;

return -;

int Mter8ere(dou'le () {
int -;
- ! Qntero8are(();
if (-<0) return 0;
for (; -<ne; -$$)
?is)-* ! ?is)-$&*;
ne77;
return &;

int Qntero8are(dou'le () {
int l,r,m;
dou'le d;
l ! 0; r ! ne 6 &;
while (l<!r) {
m ! (l $ r) + .; d ! ?is)m* 6 (;
if (d!!0) return m;
if (d<0) l ! m $ &;
else r ! m 6 &;

return 6&;

Proiectele < programe e imensiuni mari < snt compuse e cele mai multe
ori in moule care se elaboreaz !i se pun la punct n mo inepenent. "neori
pot fi ientificate func%ii care prezint un interes general mai mare$ !i care pot fi
utilizate n elaborarea unor tipuri e aplica%ii foarte i&erse. Acestea snt ez&ol-
33333333333333333333333333333333333333333333
AF
tate separat !i$ up ce au fost puse la punct n totalitate$ se epun ntr-o bibliotec
e func%ii n format obiect. =n momentul n care acestea snt incluse n proiecte nu
se mai piere timp cu compilarea moulelor surs. =n sc/imb moulele care le
apeleaz au ne&oie e moul cum snt efinite aceste func%ii$ !i acesta se pstreaz
ca !i eclara%ii n fi!iere /eaer.
Ki!ierele /eaer pstreaz !i alte informa%ii comune mai multor moule$ cum
snt e e.emplu tipurile efinite e programator$ cel mai aesea tipuri structurate
(etalii n capitolul nou,.
33333333333333333333333333333333333333333333
E7
>. &ointeri 7i masi#e
"n pointer este o &ariabil care con%ine aresa unei alte &ariabile. Pointerii
snt foarte mult utiliza%i n programe scrise n C$ pe e o parte pentru c uneori snt
unicul mijloc e a e.prima un calcul$ iar pe e alt parte pentru c ofer
posibilitatea scrierii unui program mai compact !i mai eficient ect ar putea fi
ob%inut prin alte ci.
>.1. &ointeri 7i adrese
0eoarece un pointer con%ine aresa unui obiect$ cu ajutorul lui putem a&ea
acces$ n mo inirect$ la acea &ariabil (obiect,.
* presupunem c : este o &ariabil e tip ntreg !i p: un pointer la un ntreg.
Atunci aplicn operatorul unar # lui :$ instruc%iunea#
p: ! #:;
atribuie &ariabilei p: aresa &ariabilei :; n acest fel spunem c p: inic
(pointeaz, spre :.
+n&ers$ ac p: con%ine aresa &ariabilei :$ atunci instruc%iunea#
; ! 0p:;
atribuie &ariabilei y con%inutul loca%iei pe care o inic p:.
Jariabila : are asociat o zon e memorie$ !i aceast zon are (presupunem,
aresa CAAD. 0up atribuirea p: = #:$ &ariabila p: &a a&ea &aloarea CAAD.
G&ient toate &ariabilele care snt implicate n aceste instruc%iuni trebuie
eclarate. Aceste eclara%ii snt#
int :,;,0p:;
0eclara%iile &ariabilelor : !i ; snt eja cunoscute. 0eclara%ia pointerului p:
este o noutate. Aceasta inic faptul c o combina%ie e forma 0p: este un ntreg$
iar &ariabila p: care apare n conte.tul 0p: este ec/i&alent cu un pointer la o
&ariabil e tip ntreg. =n locul tipului ntreg poate aprea oricare intre tipurile
amise n limbaj !i se refer la obiectele pe care le inic p:.
Pointerii pot aprea !i n e.presii; n e.presia urmtoare &ariabilei ; i se
atribuie &aloare &ariabilei : plus &#
; ! 0p: $ &;
+nstruc%iunea urmtoare are ca efect con&ertirea &alorii &ariabilei : pe care o
inic p: n tip dou'le !i apoi epunerea rcinii ptrate a &alorii astfel
con&ertite n &ariabila d#
d ! sGrt((dou'le)0p:);
Referiri la pointeri pot aprea e asemenea !i n partea stng a atribuirilor.
0ac$ e e.emplu$ p: inic spre :$ atunci urmtoarea instruc%iune atribuie
&ariabilei : &aloarea zero#
33333333333333333333333333333333333333333333
E4
0p: ! 0;
+nstruc%iunile urmtoare snt ec/i&alente$ !i incrementeaz &aloarea &ariabilei
: cu &#
0p: $! &;
(0p:)$$;
=n acest ultim e.emplu parantezele snt obligatorii eoarece$ n lipsa lor$
e.presia ar incrementa pe p: n loc e &aloarea &ariabilei pe care o inic
(operatorii unari 0$ $$ au aceea!i preceen% !i snt e&alua%i e la reapta spre
stnga,.
&ointeri de tip (oid 5tip 'eneric de pointer6
"n pointer poate fi eclarat e tip (oid. =n aceast situa%ie pointerul nu poate
fi folosit pentru inirectare (ereferen%iere, fr un cast e.plicit$ !i aceasta
eoarece compilatorul nu poate cunoa!te tipul obiectului pe care pointerul l
inic.
int i;
float f;
(oid 0p;
p ! #i; +0 p indic spre i 0+
0(int 0)p ! .;
p ! #f; +0 p indic spre * 0+
0(float 0)p ! &.2;
Pointerii generici snt foarte utiliza%i e unele func%ii e bibliotec$ atunci
cn este ne&oie s se opereze cu zone e memorie care pot con%ine informa%ii e
orice natur# opera%ii e intrare > ie!ire fr format (capitolul zece,$ alocri e
memorie$ sortare !i cutare (capitolul unsprezece,. Aceste func%ii nu cunosc tipul
atelor cu care opereaz$ pentru aceste func%ii zonele e memorie nu au un tip
precizat. Acest fapt este e&ien%iat prin pointeri e tip (oid.
>. &ointeri 7i ar'umente de *uncii
0ac transmiterea argumentelor la func%ii se face prin &aloare (!i nu prin
referin%,$ func%ia apelat nu are posibilitatea e a altera o &ariabil in func%ia
apelant. Problema care se pune este cum procem ac orim s moificm
&aloarea unui argumentZ
0e e.emplu$ o rutin e sortare trebuie s sc/imbe ntre ele ou elemente
care nu respect orinea orit$ cu ajutorul unei func%ii swap. Kie func%ia swap
efinit astfel#
(oid swap(int :, int ;) { +0 're7it 0+
int tmp;
tmp ! :;
33333333333333333333333333333333333333333333
E?
: ! ;;
; ! tmp;

Kunc%ia swap apelat prin swap(a,') nu &a realiza ac%iunea orit


eoarece ea nu poate afecta argumentele a !i ' in rutina apelant.
G.ist ns o posibilitate e a ob%ine efectul orit$ ac func%ia apelant
transmite ca argumente pointeri la &alorile ce se oresc intersc/imbate. Atunci n
func%ia apelant apelul &a fi#
swap(#a,#');
iar forma corect a lui swap este#
(oid swap(int 0p:, int 0p;) {+0 intersc,imb 0p: 7i 0p; 0+
int tmp;
tmp ! 0p:;
0p: ! 0p;;
0p; ! tmp;

-oificarea nu este permis ac parametrul e tip pointer este preceat e


eclaratorul const.
>.%. &ointeri 7i masi#e
=n limbajul C e.ist o strns legtur ntre pointeri !i masi&e. @rice opera%ie
care poate fi realizat prin inicarea masi&ului poate fi e asemenea fcut prin
pointeri$ care conuce n plus la o accelerare a opera%iei. 0eclara%ia#
int a)&0*;
efine!te un masi& e imensiune 47$ care reprezint un bloc e 47 obiecte
consecuti&e numite a)0*$ ... a)4*. )ota%ia a)i* reprezint al i-lea element al
masi&ului sau elementul in pozi%ia i+&$ ncepn cu primul element. 0ac pa
este un pointer la un ntreg$ !i a este un masi& e ntregi$ atunci instruc%iunea e
atribuire ncarc &ariabila pa cu aresa primului element al masi&ului a.
int 0pa,a)&0*;
pa ! #a)0*;
Atribuirea urmtoare copiaz con%inutul lui a)0* n :#
: ! 0pa;
0ac pa inic un element particular al unui masi& a$ atunci prin efini%ie
pa$i inic un element cu i pozi%ii up elementul pe care l inic pa$ up
cum pa7i inic un element cu i pozi%ii nainte e cel pe care inic pa. Astfel$
ac &ariabila pa inic pe a)0* atunci 0(pa$i) se refer la con%inutul lui
a)i*.
Aceste obser&a%ii snt ae&rate iniferent e tipul &ariabilelor in masi&ul a.
33333333333333333333333333333333333333333333
EB
=ntreaga aritmetic cu pointeri are n &eere faptul c e.presia pa$i nseamn
e fapt nmul%irea lui i cu lungimea elementului pe care l inic pa !i aunarea
apoi la pa$ ob%innu-se astfel aresa elementului e inice i al masi&ului.
Coresponen%a intre ine.area ntr-un masi& !i aritmetica e pointeri este
foarte strns. 0e fapt$ o referire la un masi& este con&ertit e compilator ntr-un
pointer la nceputul masi&ului. Gfectul este c un nume e masi& este o e.presie
pointer$ eoarece numele unui masi& este ientic cu numele elementului e inice
zero in masi&.
Cele ou instruc%iuni e atribuire snt ientice#
pa ! #a)&*;
pa ! a $ &;
0e asemenea$ e.presiile a)i* !i 0(a$i) snt ientice. Aplicn operatorul #
la ambele pr%i ob%inem #a)i* ientic cu a$i. Pe e alt parte$ ac pa este un
pointer$ e.presiile pot folosi acest pointer ca un inice# pa)i* este ientic cu
0(pa$i). Pe scurt orice e.presie e masi& !i inice poate fi scris ca un pointer
!i un eplasament !i in&ers$ c/iar n aceea!i instruc%iune.
G.ist ns o singur iferen% ntre un nume e masi& !i un pointer la
nceputul masi&ului. "n pointer este o &ariabil$ eci urmtoarele instruc%iuni snt
corecte#
pa ! a;
pa$$;
0ar un nume e masi& este o constant !i eci urmtoarele construc%ii nu snt
permise#
a ! pa;
a$$;
p ! #a;
Cn se transmite unei func%ii un nume e masi&$ ceea ce se transmite e fapt
este aresa primului element al masi&ului. A!aar$ un nume e masi&$ argument al
unei func%ii$ este n realitate un pointer$ aic o &ariabil care con%ine o ares. Kie
e e.emplu func%ia strlen care etermin lungimea !irului s#
int strlen(const char 0s) {
int n;
for (n!0; 0s; s$$) n$$;
return n;

+ncrementarea lui s este legal eoarece s este o &ariabil pointer. s$$ nu


afecteaz !irul e caractere in func%ia care apeleaz pe strlen$ ci numai copia
aresei !irului in func%ia strlen.
Gste posibil s se transmit unei func%ii$ ca argument$ numai o parte a unui
masi&$ printr-un pointer la nceputul sub-masi&ului respecti&. 0e e.emplu$ ac a
este un masi&$ atunci#
33333333333333333333333333333333333333333333
ED
f(#a).*)
f(a$.)
transmit func%iei f aresa elementului a).*$ eoarece #a).* !i a$. snt
e.presii pointer care$ ambele$ se refer la al treilea element al masi&ului a. =n
carul func%iei f argumentul se poate eclara astfel#
f(int arr)*) {. . .
f(int 0arr) {. . .
0eclara%iile int arr)* !i int 0arr snt ec/i&alente.
>./. Aritmetica de adrese
0ac p este un pointer$ atunci urmtoarea instruc%iune incrementeaz pe p
pentru a inica cu i elemente up elementul pe care l inic n prealabil p#
p $! i;
Aceast construc%ie !i altele similare snt cele mai simple !i comune formule
ale aritmeticii e arese$ care constituie o caracteristic puternic a limbajului C.
Pentru e.emplificare relum in&ersarea caracterelor unui !ir#
(oid strre((char s)*) {
int i,H;
char c;
for (i!0,H!strlen(s)7&; i<H; i$$,H77) {
c ! s)i*;
s)i* ! s)H*;
s)H* ! c;

Jersiunea cu pointeri a acestei func%ii este#


(oid strre((char s)*) {
char 0p,0G,c;
for (p!s,G!s$strlen(s)7&; p<G; p$$,G77) {
c ! 0p;
0p ! 0G;
0G ! c;

G.emplul e mai sus emonstreaz cte&a in facilit%ile aritmeticii e arese


(pointeri,. =n primul rn$ pointerii pot fi compara%i n anumite situa%ii. Rela%iile <$
<!$ >$ >!$ !!$ %! snt &alie numai dac p i G snt pointeri la elementele
aceluiai masiv. Rela%ia p<G$ e e.emplu$ este ae&rat ac p inic un
element mai apropiat e nceputul masi&ului ect elementul inicat e pointerul
G. Comparrile ntre pointeri pot uce ns la rezultate impre&izibile ac ei se
refer la elemente apar%inn la masi&e iferite.
33333333333333333333333333333333333333333333
EA
*e obser& c pointerii !i ntregii pot fi auna%i sau sczu%i. Construc%ia e
forma p$n nseamn aresa celui e-al n-lea element up cel inicat e p$
iniferent e tipul elementului pe care l inic p. Compilatorul C aliniaz
&aloarea lui n conform imensiunii elementelor pe care le inic p$ imensiunea
fiin eterminat in eclara%ia lui p (scara e aliniere este 4 pentru char$ ?
pentru short int etc,.
0ac p !i G inic elemente ale aceluia!i masi&$ p7G este numrul
elementelor intre cele pe care le inic p !i G. * scriem alte &ersiuni ale func%iei
strlen folosin aceast ultim obser&a%ie#
int strlen(char 0s) { int strlen(char 0s) {
char 0p; char 0p;
p ! s; for (p!s; 0p; p$$) ;
while (0p) p$$; return p7s;
return p7s;

=n acest e.emplu s rmne constant cu aresa e nceput a !irului$ n timp ce p


a&anseaz la urmtorul caracter e fiecare at. 0iferen%a p7s intre aresa
ultimului element al !irului !i aresa primului element al !irului inic numrul e
elemente.
*nt amise e asemenea incrementrile !i ecrementrile precum !i alte
combina%ii ca e e.emplu 0$$p !i 077p.
=n afar e opera%iile binare men%ionate (aunarea sau scerea pointerilor cu
ntregi !i scerea sau compararea a oi pointeri,$ celelalte opera%ii cu pointeri snt
ilegale. )u este permis aunarea$ nmul%irea$ mpr%irea sau eplasarea
pointerilor$ up cum nici aunarea lor cu constante e tip dou'le sau float.
>.1. &ointeri la caracter 7i *uncii
@ constant !ir este un masi& e caractere$ care n reprezentarea intern este
terminat cu caracterul 0$ astfel nct programul poate epista sfr!itul lui.
1ungimea acestui !ir n memorie este astfel cu 4 mai mare ect numrul e
caractere ce apar efecti& ntre g/ilimelele e nceput !i sfr!it e !ir.
Cea mai frec&ent apari%ie a unei constante !ir este ca argument la func%ii$ caz
n care accesul la ea se realizeaz prin intermeiul unui pointer.
=n e.emplul#
puts("Duna dimineata");
func%ia puts prime!te e fapt un pointer la masi&ul e caractere.
=n prelucrarea unui !ir e caractere snt implica%i numai pointeri$ limbajul C
neoferin nici un operator care s trateze !irul e caractere ca o unitate e
informa%ie.
33333333333333333333333333333333333333333333
EE
Jom prezenta cte&a aspecte legate e pointeri !i masi&e analizn ou
e.emple. * consierm pentru nceput func%ia strcp;(t,s) care copiaz !irul
s (source, peste !irul t (target,. @ prim &ersiune a programului ar fi urmtoarea#
(oid strcp;(char t)*, const char s)*) {
int i;
i ! 0;
while (t)i*!s)i*) i$$;

@ a oua &ersiune cu ajutorul pointerilor este urmtoarea#


(oid strcp;(char 0t, const char 0s) {
while (0t$$!0s$$) ;

Aceast &ersiune cu pointeri moific prin incrementare pe t !i s n partea e


test. Jaloarea lui 0s$$ este caracterul inicat e pointerul s$ nainte e
incrementare. )ota%ia postfi. $$ asigur c s &a fi moificat up preluarea
con%inutului inicat e el$ e la &ec/ea pozi%ie a lui s$ up care s se
incrementeaz. 1a fel$ t &a fi moificat up memorarea caracterului la &ec/ea
pozi%ie a lui t$ up care !i t se incrementeaz. Gfectul este c se copiaz
caracterele !irului s n !irul t pn la caracterul terminal 0 inclusi&.
Am preferat s e&itm reunan%a comparrii cu caracterul 0$ facilitate care
rezult in structura instruc%iunii while. Am fi putut scrie !i astfel#
while ((0t$$!0s$$)%!0) ;
* consierm$ ca al oilea e.emplu$ func%ia strcmp(t,s) care compar
caracterele !irurilor t !i s !i returneaz o &aloare negati&$ zero sau poziti&$ up
cum !irul t este le.icografic mai mic$ egal sau mai mare ca !irul s. Jaloarea
returnat se ob%ine prin scerea caracterelor primei pozi%ii n care t !i s ifer.
@ prim &ersiune a func%iei strcmp(t,s) este urmtoarea#
int strcmp(const char t, const char s) {
int i;
i ! 0;
while (t)i*!!s)i*)
if (t)i$$*!!0)
return 0;
return t)i*7s)i*;

@ &ersiune cu pointeri a aceleia!i func%ii este#


int strcmp(const char 0t, const char 0s) {
for (; 0t!!0s; t$$,s$$)
if (0t!!0)
33333333333333333333333333333333333333333333
E6
return 0;
return 0t70s;

>.;. Masi#e multidimensionale


1imbajul C ofer facilitatea utilizrii masi&elor multi-imensionale$ e!i n
practic ele snt folosite mai rar ect masi&ele e pointeri.
-asi&ele multi-imensionale snt folosite mai ales e programatorii nceptori
n scop iactic.
* consierm problema con&ersiei atei$ e la zi in lun$ la zi in an !i
in&ers$ %inn cont e faptul c anul poate s fie bisect sau nu. 0efinim ou
func%ii care s realizeze cele ou con&ersii.
Kunc%ia JrTile con&erte!te ziua !i luna n numrul e zile e la nceputul
anului$ !i func%ia ?unaTi con&erte!te numrul e zile n lun !i zi.
Ambele func%ii au ne&oie e aceea!i informa%ie !i anume un tabel cu numrul
zilelor in fiecare lun. 0eoarece numrul zilelor in lun ifer pentru anii
bisec%i e cele pentru anii nebisec%i este mai u!or s consierm un tabel
biimensional n care prima linie s corespun numrului e zile ale lunilor
pentru anii nebisec%i$ iar a oua linie s corespun numrului e zile pentru anii
bisec%i. =n felul acesta nu trebuie s %inem o e&ien% n timpul calculului a ceea ce
se ntmpl cu luna februarie. Atunci masi&ul biimensional care con%ine
informa%iile pentru cele ou func%ii este urmtorul#
static int Tile).*)&,* ! {
{0,,&,.5,,&,,0,,&,,0,,&,,&,,0,,&,,0,,&,
{0,,&,.4,,&,,0,,&,,0,,&,,&,,0,,&,,0,,&
;
-asi&ul Tile trebuie s fie eclarat global pentru a putea fi folosit e ambele
func%ii.
=n limbajul C$ prin efini%ie$ un masi& cu ou imensiuni este n realitate un
masi& cu o imensiune ale crui elemente snt masi&e. 0e aceea inicii se scriu
sub forma )i*)H* n loc e )i,H*$ cum se proceeaz n multe alte limbaje.
=ntr-un masi& biimensional elementele snt memorate pe linie$ aic inicele cel
mai in reapta &ariaz cel mai rapi.
"n masi& se ini%ializeaz cu ajutorul unei liste e ini%ializatori nc/i!i ntre
acolae; fiecare linie a unui masi& biimensional se ini%ializeaz cu ajutorul unei
subliste e ini%ializatori. =n cazul e.emplului nostru$ masi&ul Tile ncepe cu o
coloan zero$ pentru ca numerele lunilor s fie ntre 4 !i 4? !i nu ntre 7 !i 44$
aceasta pentru a nu face moificri n calculul inicilor.
ai atunci func%iile care realizeaz con&ersiile cerute e e.emplul nostru snt#
int JrTile (int an, int luna, int 9i) {
33333333333333333333333333333333333333333333
EC
int i,'is;
'is ! %(an"/) ## (an"&00) II %(an"/00);
for (i!&; i<luna; i$$)
9i $! Tile)'is*)i*;
return 9i;

0eoarece &ariabila 'is poate lua ca &alori numai zero sau unu$ up cum
e.presia (scris e ata aceasta e.plicit,#
(an"/!!0) ## (an"&00%!0) II (an"/00!!0)
este fals sau ae&rat$ ea poate fi folosit ca inice e linie n tabelul Tile care
are oar ou linii n e.emplul nostru.
(oid ?unaTi(int an, int 9ian, int 0plun, int 0p9i) {
int i,'is;
'is ! %(an"/) ## (an"&00) II %(an"/00);
for (i!&; 9ian>Tile)'is*)i*; i$$)
9ian 7! Tile)'is*)i*;
0plun ! i; 0p9i ! 9ian;

0eoarece aceast ultim func%ie returneaz ou &alori$ argumentele care


corespun lunii !i zilei snt pointeri.
Exemplu. ?unaTi(&45/,1&,#m,#d) &a ncrca pe m cu B$ iar pe d cu 4
(aic 4 martie,.
0ac un masi& biimensional trebuie transmis unei func%ii$ eclara%ia
argumentelor func%iei trebuie s inclu imensiunea coloanei. 0imensiunea liniei
nu este necesar s apar n mo obligatoriu$ eoarece ceea ce se transmite e fapt
este un pointer la masi&e e cte 4B ntregi$ n cazul e.emplului nostru. Astfel$
ac masi&ul Tile trebuie transmis unei func%ii f$ atunci eclara%ia lui f poate fi#
f(int (0Tile))&,*);
f(int Tile)*)&,*);
une eclara%ia (0Tile))&,*) inic faptul c argumentul lui f este un pointer
la un masi& e 4B ntregi.
=n general$ un masi& d-imensional a)i*)H*...)l* e rangul i0H0...0l
este un masi& (d4,-imensional e rangul H0-0...0l ale crui elemente$ fiecare$
snt masi&e (d?,-imensionale e rang -0...0l ale crui elemente$ fiecare$ snt
masi&e (dB,-imensionale !.a.m.. @ricare intre e.presiile urmtoare# a)i*$
a)i*)H*...$ a)i*)H*...)l* pot aprea n e.presii. Prima are tipul masi&$
ultima are tipul int$ e e.emplu$ ac masi&ul este e tipul int. Jom mai
re&eni asupra acestei probleme cu etalii.
33333333333333333333333333333333333333333333
EF
>.<. Masi#e de pointeri 7i pointeri la pointeri
0eoarece pointerii snt &ariabile$ are sens no%iunea e masi& e pointeri. Jom
ilustra moul e lucru cu masi&e e pointeri pe un e.emplu.
* scriem un program care s sorteze le.icografic liniile e lungimi iferite
ale unui te.t$ linii care spre eosebire e ntregi nu pot fi comparate sau sc/imbate
printr-o singur opera%ie.
Citirea te.tului ecurge astfel. *e cite!te o linie in te.tul introus e la
intrarea stanar$ !irul e caractere fiin epus ntr-un masi& lin. 0eoarece !i
urmtoarele linii &or fi epuse tot aici$ este ne&oie s se sal&eze con%inutul acestui
masi&. =n acest scop se cere sistemului e operare s se creeze un uplicat al
acestui !ir prin apelul func%iei strdup. Aceasta &a rezer&a o zon e memorie$
&a copia !irul at n zona respecti& !i ne &a comunica aresa acestei zone.
Kunc%iile care opereaz cu !iruri e caractere snt eclarate cu#
#include <strin8.h>
Aresele liniilor snt memorate ntr-un masi& e pointeri la caracter. Astfel
ou linii e te.t pot fi comparate transmi%n pointerii lor func%iei strcmp. 0ac
ou linii care nu respect orinea trebuie s fie sc/imbate$ se sc/imb oar
pointerii lor in masi&ul e pointeri !i nu te.tul efecti& al liniilor.
=n primul pas al procesului e sortare se citesc toate liniile te.tului e la
intrare. =n al oilea pas se sorteaz liniile n orine le.icografic. =n ultimul pas se
afi!eaz liniile sortate n noua orine.
Jom scrie programul prin func%iile sale$ fiecare func%ie realizn unul in cei
trei pa!i e mai sus. @ rutin principal &a controla cele trei func%ii. Ga are
urmtorul co#
int main() { >Y program care sorteaz liniile e la intrare Y>
#define J?QJ &00 >Y nr ma.im e linii e sortat Y>
char 0linptr)J?QJ*; >Y pointeri la linii Y>
int nrl; >Y nr linii intrare citite Y>
nrl ! Xead?ines(linptr,J?QJ);
if (nrl>!0) {
Mort(linptr,nrl);
Yrite?ines(linptr,nrl);

else puts("Qntrare prea mare pentru sort");
return 0;

Cele B func%ii care realizeaz ntregul proces snt# Xead?ines$ Mort !i


Yrite?ines.
33333333333333333333333333333333333333333333
67
Rutina e intrare Xead?ines trebuie s memoreze caracterele fiecrei linii
!i s construiasc un masi& e pointeri la liniile citite. 'rebuie$ e asemenea$ s
numere liniile in te.tul e la intrare$ eoarece aceast informa%ie este necesar n
procesul e sortare !i e afi!are. =ntruct func%ia e intrare poate prelucra numai un
numr finit e linii e intrare$ ea poate returna un numr ilegal$ cum ar fi 4$ spre
a semnala c numrul liniilor e intrare este prea mare pentru capacitatea e care
ispune.
Atunci func%ia Xead?ines care cite!te liniile te.tului e la intrare este
urmtoarea#
int Xead?ines(char 0linptr)*, int nma:) {
int nrl ! 0;
char 0p,lin)50*;
while (8ets(lin)) {
if (nrl>!nma:) return 7&;
p ! strdup(lin);
if (%p) return 7&;
linptr)nrl$$* ! p;

return nrl;

Rutina care afi!eaz liniile n noua lor orine este Yrite?ines !i are
urmtorul co#
(oid Yrite?ines(char 0linptr)*, int nrl) {
int i;
for (i!0; i<nrl; i$$)
puts(linptr)i*);

0eclara%ia nou care apare n aceste programe este#


char 0linptr)J?QJ*;
care inic faptul c linptr este un masi& e J?QJ elemente$ fiecare element al
masi&ului fiin un pointer la un caracter. Astfel linptr)i* este un pointer la un
caracter$ iar 0linptr)i* permite accesul la caracterul respecti&.
0eoarece linptr este el nsu!i un masi&$ care se transmite ca argument
func%iei Yrite?ines$ el &a fi tratat ca un pointer !i atunci func%ia
Yrite?ines mai poate fi scris !i astfel#
(oid Yrite?ines(char 0linptr)*, int nrl) {
while (77nrl>!0)
puts(0linptr$$);

33333333333333333333333333333333333333333333
64
=n func%ia puts$ linptr inic ini%ial prima linie e afi!at; fiecare
incrementare a&anseaz pe 0linptr la urmtoarea linie e afi!at$ n timp ce nrl
se mic!oreaz up fiecare afi!are a unei linii cu 4.
Kunc%ia care realizeaz sortarea efecti& a liniilor se bazeaz pe algoritmul e
njumt%ire !i are urmtorul co#
(oid Mort(char 0()*, int n) {
int 8ap,i,H;
char 0tmp;
for (8ap!n+.; 8ap>0; 8ap+!.)
for (i!8ap; i<n; i$$)
for (H!i78ap; H>!0; H7!8ap) {
if (strcmp(()H*,()H$8ap*)<!0)
'rea-;
tmp ! ()H*;
()H* ! ()H$8ap*;
()H$8ap* ! tmp;

0eoarece fiecare element al masi&ului ( (care este e fapt masi&ul linptr


in func%ia main, este un pointer la primul caracter al unei linii$ &ariabila tmp &a
fi !i ea un pointer la un caracter$ eci opera%iile e atribuire in ciclu up
&ariabila H snt amise !i ele realizeaz rein&ersarea pointerilor la linii ac ele nu
snt n orinea cerut.
*tructura programului este urmtoarea#
#include <stdli'.h>
#include <strin8.h>
#include <stdio.h>
int Xead?ines(...) { ...
(oid Yrite?ines(...) { ...
(oid Mort(...) { ...
int main(...) { ...
* re%inem urmtoarele lucruri legate e masi&e !i pointeri. 0e cte ori apare
ntr-o e.presie un ientificator e tip masi& el este con&ertit ntr-un pointer la
primul element al masi&ului. Prin efini%ie$ operatorul e ine.are )* este
interpretat astfel nct E4)E?* este ientic cu 0((E4)$(E?)). 0ac E4 este un
masi&$ iar E? un ntreg$ atunci E4)E?* se refer la elementul e inice E? al
masi&ului E4.
@ regul corespunztoare se aplic !i masi&elor multi-imensionale. 0ac E4
este un masi& d-imensional$ e rangul i0H0...0-$ atunci ori e cte ori e4 apare
ntr-o e.presie$ e4 &a fi con&ertit ntr-un pointer la un masi& (d4,-imensional e
33333333333333333333333333333333333333333333
6?
rangul H0...0-$ ale crui elemente snt masi&e. 0ac operatorul 0 se aplic acestui
pointer$ rezultatul este masi&ul (d4,-imensional$ care se &a con&erti imeiat
ntr-un pointer la un masi& (d?,-imensional !.a.m.. Ra%ionamentul se poate
aplica n mo inucti& pn cn$ n final$ ca urmare a aplicrii operatorului 0 se
ob%ine ca rezultat un ntreg$ e e.emplu$ ac masi&ul a fost eclarat e tipul int.
* consierm$ e e.emplu$ masi&ul#
int <),*)2*;
< este un masi& e ntregi$ e rangul BA. Cn < apare ntr-o e.presie$ el este
con&ertit ntr-un pointer la (primul in cele trei, masi&e e A ntregi.
UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
IUUUUUUUUUUUUUUIUUUUUUUUUUUUUUIUUUUUUUUUUUUUUI
IUUIUUIUUIUUIUUIUUIUUIUUIUUIUUIUUIUUIUUIUUIUUI
<)0* <)&* <).*
=n e.presia <)i*$ care este ec/i&alent cu e.presia 0(<$i)$ < este con&ertit
ntr-un pointer la un masi&$ ale crui elemente snt la rnul lor masi&e e A
elemente; apoi i se con&erte!te la tipul <$ aic inicele i se nmul%e!te cu
lungimea elementului pe care l inic < (aic A ntregi, !i apoi rezultatele se
aun. *e aplic operatorul 0 pentru ob%inerea masi&ului i (e A ntregi, care la
rnul lui este con&ertit ntr-un pointer la primul ntreg in cei cinci.
*e obser& eci c primul inice in eclara%ia unui masi& nu joac rol n
calculul aresei.
>.>. Iniiali"area masi#elor 7i masi#elor de pointeri
+ni%ializatorul unei &ariabile eclarate masi& const intr-o list e
ini%ializatori separa%i prin &irgul !i nc/i!i ntre acolae$ corespunztori tuturor
elementelor masi&ului. Gi snt scri!i n orinea cresctoare a inicilor masi&ului.
0ac masi&ul con%ine sub-masi&e atunci regula se aplic recursi& membrilor
masi&ului. 0ac n lista e ini%ializare e.ist mai pu%ini ini%ializatori ect
elementele masi&ului$ restul elementelor neini%ializate se ini%ializeaz cu zero. )u
se amite ini%ializarea unui masi& e clas automatic.
Acolaele { !i se pot omite n urmtoarele situa%ii#
< ac ini%ializatorul ncepe cu acola stnga {$ atunci lista e ini%ializatori$
separa%i prin &irgul$ &a ini%ializa elementele masi&ului; nu se accept s e.iste
mai mul%i ini%ializatori ect numrul elementelor masi&ului;
< ac ns ini%ializatorul nu ncepe cu acola stnga {$ atunci se iau in lista e
ini%ializatori at%ia ini%ializatori c%i corespun numrului e elemente ale
masi&ului$ restul ini%ializatorilor &or ini%ializa urmtorul membru al masi&ului$
care are ca parte (sub-masi&, masi&ul eja ini%ializat.
33333333333333333333333333333333333333333333
6B
"n masi& e caractere poate fi ini%ializat cu un !ir$ caz n care caracterele
succesi&e ale !irului ini%ializeaz elementele masi&ului.
Exemple$
4, int :)* ! {&,,,2;
Aceast eclara%ie efine!te !i ini%ializeaz pe : ca un masi& uniimensional cu
trei elemente$ c/iar ac nu s-a specificat imensiunea masi&ului. Prezen%a
ini%ializatorilor nc/i!i ntre acolae etermin imensiunea masi&ului.
?, 0eclara%ia
int ;)/*),*!{
{&,,,2,
{.,/,1,
{,,2,3
;
este o ini%ializare complet nc/is ntre acolae. Jalorile 4$B$A ini%ializeaz prima
linie a masi&ului ;)0* !i anume pe ;)0*)0*$ ;)0*)&*$ ;)0*).*. =n mo
analog urmtoarele ou linii ini%ializeaz pe ;)&* !i ;).*. 0eoarece
ini%ializatorii snt mai putini ect numrul elementelor masi&ului$ linia ;),* se
&a ini%ializa cu zero$ respecti& elementele ;),*)0*$ ;),*)&*$ ;),*).* &or
a&ea &alorile zero.
B, Acela!i efect se poate ob%ine in eclara%ia#
int ;)/*),* ! {&,,,2,.,/,1,,,2,3;
une ini%ializatorul masi&ului ; ncepe cu acolaa stng n timp ce ini%ializatorul
pentru masi&ul ;)0* nu$ fapt pentru care primii trei ini%ializatori snt folosi%i
pentru ini%ializarea lui ;)0*$ restul ini%ializatorilor fiin folosi%i pentru
ini%ializarea masi&elor ;)&* !i respecti& ;).*.
D, 0eclara%ia#
int ;)/*),* ! {
{&,{.,,{,,,{/
;
ini%ializeaz masi&ul ;)0* cu (4$7$7,$ masi&ul ;)&* cu (?$7$7,$ masi&ul ;).* cu
(B$7$7, !i masi&ul ;)/* cu (D$7$7,.
A, 0eclara%ia#
static char ms8)* ! "Aroare de sinta:a";
ini%ializeaz elementele masi&ului e caractere ms8 cu caracterele succesi&e ale
!irului at.
=n ceea ce pri&e!te ini%ializarea unui masi& e pointeri s consierm
urmtorul e.emplu.
33333333333333333333333333333333333333333333
6D
Kie func%ia Jume?una care returneaz un pointer la un !ir e caractere care
inic numele unei luni a anului. Kunc%ia at con%ine un masi& e !iruri e
caractere !i returneaz un pointer la un astfel e !ir$ cn ea este apelat.
Coul func%iei este urmtorul#
char 0Jume?una(int n) { +0 returnea" numele lunii a n8a 0+
static char 0J?)* ! {
"luna ile8ala", "ianuarie", "fe'ruarie",
"martie", "aprilie", "mai", "iunie", "iulie",
"au8ust", "septem'rie", "octom'rie",
"noiem'rie", "decem'rie"

return (n<&) II (n>&.) O J?)0* P J?)n* ;

=n acest e.emplu$ J? este un masi& e pointeri la caracter$ al crui ini%ializator


este o list e !iruri e caractere. Compilatorul aloc o zon e memorie pentru
memorarea acestor !iruri !i genereaz cte un pointer la fiecare in ele pe care apoi
i introuce n masi&ul name. 0eci J?)i* &a con%ine un pointer la !irul e
caractere a&n inice i al ini%ializatorului. )u este necesar s se specifice
imensiunea masi&ului J? eoarece compilatorul o etermin numrn
ini%ializatorii furniza%i !i o completeaz n eclara%ia masi&ului.
>.?. Masi#e de pointeri 7i masi#e multidimensionale
Aesea se creeaz confuzii n ceea ce pri&e!te iferen%a intre un masi&
biimensional !i un masi& e pointeri. Kie ate eclara%iile#
int a)&0*)&0*,0')&0*;
=n acest caz a este un masi& e ntregi cruia i se aloc spa%iu pentru toate cele
477 e elemente$ iar calculul inicilor se face n mo obi!nuit pentru a a&ea acces
la oricare element al masi&ului.
Pentru masi&ul ' eclara%ia aloc spa%iu numai pentru zece pointeri$ fiecare
trebuin s fie ncrcat cu aresa unui masi& e ntregi.
Presupunn c fiecare pointer inic un masi& e zece elemente nseamn c
ar trebui alocate nc o sut e loca%ii e memorie pentru elementele masi&elor.
=n aceast accep%iune$ folosirea masi&elor a !i ' poate fi similar n sensul c
a)2*)2* !i ')2*)2*$ e e.emplu$ se refer ambele la unul !i acela!i ntreg
(ac fiecare element ')i* este ini%ializat cu aresa masi&ului a)i*,.
Astfel$ masi&ul e pointeri utilizeaz mai mult spa%iu e memorie ect
masi&ele biimensionale !i pot cere un pas e ini%ializare e.plicit. 0ar masi&ele e
pointeri prezint ou a&antaje$ !i anume# accesul la un element se face cu
aresare inirect$ prin intermeiul unui pointer$ n loc e proceura obi!nuit
folosin nmul%irea !i apoi aunarea$ iar al oilea a&antaj const n aceea c
33333333333333333333333333333333333333333333
6A
imensiunea masi&elor e pointeri poate fi &ariabil. Acest lucru nseamn c un
element al masi&ului e pointeri ' poate inica un masi& e zece elemente$ altul
un masi& e ou elemente !i altul poate s nu inice nici un masi&.
Cu toate c problema prezentat n acest paragraf a fost escris n termenii
ntregilor$ ea este cel mai frec&ent utilizat n memorarea !irurilor e caractere e
lungimi iferite (ca n func%ia Jume?una prezentat mai sus,.
Prezentm n continuare un moel e rezol&are a alocrii e memorie pentru o
matrice e imensiuni care snt cunoscute abia n momentul e.ecu%iei. =n
biblioteca limbajului C e.ist func%ii care ne ofer posibilitatea e a aloca
memorie necesar pentru memorarea unor ate. 0up ce atele au fost prelucrate$
memoria ocupat nu mai este necesar !i poate fi eliberat.
0eclara%iile acestor func%ii se ob%in cu#
#include <stdli'.h>
Pentru alocarea unei zone e memorie apelm func%ia malloc#
(oid 0malloc(unsi8ned n);
Kunc%ia aloc o zon e memorie e n octe%i !i returneaz aresa acesteia.
@ zon e memorie a&n aresa p (p fiin un pointer, poate fi eliberat up
ce nu mai este necesar#
(oid free((oid 0p);
Presupunem c trebuie s alocm memorie pentru o matrice e elemente
ntregi a&n n linii !i m coloane.
#include <stdli'.h>
int 00QntCatr(int n, int m) {
int i,00p;
p ! (int 00)malloc(n0si9eof(int 0));
p)0* ! (int 0)malloc(nm0si9eof(int));
for (i!&; i<n; i$$)
p)i* ! p)i7&* $ m;
return p;

+ni%ial se aloc memorie une se &or epune aresele celor n linii$ e aceea
primul apel malloc cere o zon e memorie pentru n pointeri. =n continuare
trebuie alocat memorie !i pentru matricea propriu-zis. Pentru simplificare am
preferat s alocm o zon continu e nm ntregi (al oilea apel malloc,.
=n acest moment putem etermina aresa fiecrei linii a matricei. Prima linie
are eterminat aresa in momentul alocrii. Pentru o linie oarecare i (i > 7,
aresa acesteia se ob%ine in aresa liniei preceente la care se aaug m (numrul
e elemente ale liniei,; a se &eea !i figura e mai jos.
333 33333333333333333333333333333333
_33_<<<<_33_33_33_33_33_33_33_33_33_
33333333333333333333333333333333333333333333
6E
_33_<<<<<<<<<<<<
_
_
_33_<<<<<<<<<<<<<<<<<<<
_
Gste foarte important s se respecte ace!ti pa!i n alocarea memoriei pentru
matrice. =n caz contrar &ariabilele pointer con%in &alori necunoscute !i nu e.ist
garan%ii c inic spre zone e memorie sigure# este foarte probabil c programul
nu are acces la zonele respecti&e.
Kunc%ia principal &a fi scris astfel#
int main() {
int 00Cat,n,m;
+0 alte de*iniii de #ariabile 0+
+0 Cite7te #alorile n 7i m 0+
Cat ! QntCatr(n,m);
+0 Completea" matricea cu #alori Cat)i*)H* ... 0+
+0 &relucrea" matricea 0+
free(Cat)0*); free(Cat); +0 :liberea" memoria 0+

Gste foarte important s se respecte !i pa!ii preciza%i pentru eliberarea


memoriei ocupate# mai nti zona ocupat e matrice !i apoi !i zona ocupat e
pointeri. 0ac se elibereaz mai nti zona ocupat e pointeri$ programul nu mai
are acces la zona respecti&$ !i un apel free(Cat)0*) &a fi respins e sistemul
e operare.
* relum problema alocrii e memorie pentru o matrice n cazul general$
une cunoa!tem#
< n# numrul liniilor matricei;
< C)*# masi& care inic numrul elementelor in fiecare linie;
< s# mrimea n octe%i a unui element al matricei (se ob%ine cu operatorul
si9eof,; toate elementele matricei snt e acela!i tip.
(oid 00Zenmatr(int n, int C)*, int s) {
int i;
(oid 00p;
p ! ((oid 00)malloc(n0si9eof((oid 0));
for (i!0; i<n; i$$)
p)i* ! malloc(C)i*0s);
return p;

*pre eosebire e e.emplul preceent$ une toat memoria a fost alocat ntr-
o singur opera%ie (al oilea apel malloc,$ aici am alocat separat memorie pentru
fiecare linie.
Apelul acestei func%ii necesit anumite pregtiri#
33333333333333333333333333333333333333333333
66
dou'le 00Fm; +0 pentru o matrice cu elemente de tip double 0+
int n,0C;
+0 alte de*iniii de #ariabile 0+
+0 Cite7te #aloarea n 0+
C ! (int 0)malloc(n0si9eof(int));
+0 preci"ea" pentru *iecare linie numrul de elemente 0+
Fm ! (dou'le 00)Zenmatr(n,C,si9eof(dou'le));
+0 0peraii cu elementele matricei 0+
-emoria ocupat se elibereaz astfel#
for (i!0; i<n; i$$)
free(Fm)i*);
free(Fm); free(C);
Gste posibil s alocm o zon compact pentru memorarea matricei$ trebuie
mai nti s eterminm numrul total e elemente. A oua &ariant a func%iei
ZenCatr este#
(oid 00Zenmatr(int n, int C)*, int s) {
int i,l;
char 00p;
p ! (char 00)malloc(n0si9eof((oid 0));
for (l!i!0; i<n; i$$)
l $! C)i*;
p)0* ! (char 0)malloc(l0s);
for (i!&; i<n; i$$)
p)i* ! p)i7&* $ C)i* 0 s;
return p;

-emoria ocupat e matrice se elibereaz cu ou apeluri free$ a!a cum am


artat mai sus n cazul matricei e ntregi.
Consierm c acest stil e programare$ bazat pe alocarea compact$ este mai
a&antajos eoarece se e&it o fragmentare e.cesi& a memoriei. *istemul e
operare memoreaz informa%ii suplimentare (ascunse programatorului, care i
permit ulterior s elibereze o zon e memorie la cerere.
>.1@. Ar'umentele unei linii de comand
=n sistemul e calcul care amite limbajul C trebuie s e.iste posibilitatea ca
n momentul e.ecu%iei unui program scris n acest limbaj s i se transmit acestuia
argumente sau parametri prin linia e coman. Cn un program este lansat n
e.ecu%ie !i func%ia main este apelat$ apelul &a con%ine ou argumente.
=n literatura e specialitate eclara%ia func%iei main este#
int main(int ar8c, char 0ar8()*);
33333333333333333333333333333333333333333333
6C
Pentru a ob%ine escrieri compacte ale programelor am preferat s folosim
numele ac !i a( pentru argumentele func%iei main. Primul argument reprezint
numrul e argumente in linia e coman care a lansat programul. Al oilea
argument este un pointer la un masi& e pointeri la !iruri e caractere care con%in
argumentele$ cte unul pe !ir.
* ilustrm acest mo inamic e comunicare ntre utilizator !i programul su
printr-un e.emplu.
Kie programul numit pri care orim s afi!eze la terminal argumentele lui
luate in linia e coman$ afi!area fcnu-se pe o linie$ iar argumentele afi!ate
s fie separate prin spa%ii.
Comana#
pri succes cole8i
&a a&ea ca rezultat afi!area la terminal a te.tului
succes colegi
Prin con&en%ie$ a()0* este un pointer la numele pri al programului apelat$
astfel c ac$ care specific numrul e argumente in linia e coman$ este cel
pu%in 4.
=n e.emplul nostru$ ac este B$ iar a()0*$ a()&* !i a().* snt pointeri la
pri$ succes !i respecti& cole8i. Primul argument efecti& este a()&* iar
ultimul este a()ac7&*. 0ac ac este 4$ nseamn c linia e coman nu are
nici un argument up numele programului.
Atunci programul pri are urmtorul co#
int main(int ac, char 0a()*) { +0 a*i7ea" ar'umentele 0+
int i;
for (i!&; i<ac; i$$)
printf(""s"c",a()i*,(i<ac7&)OB BPB\nB);
return 0;

0eoarece a( este un pointer la un masi& e pointeri$ e.ist mai multe


posibilit%i e a scrie acest program. * mai scriem o &ersiune a acestui program.
int main(int ac, char 0a()*) { +0 #ersiunea a doua 0+
while (77ac>0)
printf(""s"c",0$$a(,(a(>&) O B B P B\nB);
return 0;

0eoarece a( este un pointer la un masi& e pointeri$ prin incrementare 0$


$a( &a inica spre a()&* n loc e a()0*. Kiecare incrementare succesi&
pozi%ioneaz pe a( la urmtorul argument$ iar 0a( este pointerul la argumentul
!irului respecti&. =n acela!i timp ac este ecrementat pn e&ine zero$ moment n
care nu mai snt argumente e afi!at.
33333333333333333333333333333333333333333333
6F
Aceast &ersiune arat c argumentul func%iei printf poate fi o e.presie ca
oricare alta.
Ca un al oilea e.emplu$ s reconsierm un program anterior care afi!eaz
fiecare linie a unui te.t care con%ine un !ir specificat e caractere (!ablon,.
0orim acum ca acest !ablon s poat fi precizat printr-un argument n linia e
coman la momentul e.ecu%iei.
ai atunci func%ia principal a programului care caut !ablonul at e primul
argument al liniei e coman este#
int main(int ac, char 0a() *) {
char lin)50*;
if (ac%!.)
puts("?inia de comanda eronata");
else
while (8ets(lin))
if (inde:(lin,a()&*)>!0)
puts(lin);
return 0;

une linia e coman este e e.emplu# find lim'aH n care find este numele
programului$ iar lim'aH este !ablonul cutat. Rezultatul &a fi afi!area tuturor
liniilor te.tului e intrare care con%in cu&ntul lim'aH.
* elaborm acum moelul e baz$ legat e linia e coman !i argumentele
ei.
* presupunem c orim s introucem n linia e coman ou argumente
op%ionale# unul care s afi!eze toate liniile cu e.cep%ia acelora care con%in
!ablonul$ !i al oilea care s precea fiecare linie afi!at cu numrul ei e linie.
@ con&en%ie pentru programele scrise n limbajul C este ca argumentele intr-
o linie e coman care ncep cu un caracter 7 s introuc un parametru op%ional.
0ac alegem$ e e.emplu$ 7: pentru a inica cu excepia !i 7n pentru a cere
numrarea liniilor$ atunci comana#
find 7: 7n la
a&n intrarea#
la miezul stinselor lumini
s#a0ung victorios,
la temelii, la rdcini,
la mduv, la os/
&a prouce afi!area liniei a oua$ preceat e numrul ei$ eoarece aceast linie
nu con%ine !ablonul la.
Argumentele op%ionale snt permise n orice orine n linia e coman.
Analizarea !i prelucrarea argumentelor unei linii e coman trebuie efectuat n
33333333333333333333333333333333333333333333
C7
func%ia principal main$ ini%ializn n mo corespunztor anumite &ariabile.
Celelalte func%ii ale programului nu &or mai %ine e&ien%a acestor argumente.
Gste mai como pentru utilizator ac argumentele op%ionale snt concatenate$
ca n comana#
find 7:n la
Caracterele : respecti& n inic oar absen%a sau prezen%a acestor op%iuni
(switch, !i nu snt tratate in punct e &eere al &alorii lor.
Kie programul care caut !ablonul la n liniile e la intrare !i le afi!eaz pe
acelea$ care nu con%in !ablonul$ preceate e numrul lor e linie. Programul
trateaz corect att prima form a liniei e coman ct !i a oua. =n continuare
este prezentat oar func%ia principal a acestui program.
int main(int ac, char 0a()*) { +0 caut un 7ablon 0+
char lin)50*,0s;
lon8 nl;
int e:c,num,tst;
nl ! num ! 0;
while (77ac>0 ## (0$$a())0*!!B7B)
for (s!a()0*$&; 0s%!0; s$$)
switch(0s) {
case B:BP e:c ! &; 'rea-;
case BnBP num ! &; 'rea-;
defaultP
printf("findP optiune ile8ala "c\n",0s);
ac ! 0;
'rea-;

if (ac%!&)
puts("Ju e:ista ar8umente sau sa'lon");
else
while (8ets(lin) {
nl$$;
tst ! inde:(lin,0a()>!0;
if (tst%!e:cept) {
if (num)
printf(""/dP",nl);
puts(lin);

0ac nu e.ist erori n linia e coman$ atunci la sfr!itul primului ciclu


:/ile ac trebuie s fie 4$ iar 0a( con%ine aresa !ablonului. 0$$a( este un
pointer la un !ir argument$ iar (0$$a())0* este primul caracter al !irului. =n
aceast ultim e.presie parantezele snt necesare eoarece fr ele e.presia
33333333333333333333333333333333333333333333
C4
nseamn 0$$(a()0*) ceea ce este cu totul altce&a (!i gre!it,# al oilea caracter
in numele programului. @ alternati& corect pentru (0$$a())0* este 00$
$a(.
>.11. &ointeri la *uncii
=n limbajul C o func%ie nu este o &ariabil$ ar putem efini un pointer la o
func%ie$ care apoi poate fi prelucrat$ transmis unor alte func%ii$ introus ntr-un
masi& !i a!a mai eparte. Relati& la o func%ie se pot face oar ou opera%ii# apelul
ei !i consierarea aresei ei. 0ac numele unei func%ii apare ntr-o e.presie$ fr a
fi urmat imeiat e o parantez stng$ eci nu pe pozi%ia unui apel la ea$ atunci se
genereaz un pointer la aceast func%ie. Pentru a transmite o func%ie unei alte
func%ii$ ca argument$ se poate procea n felul urmtor#
int f();
8(f);
une func%ia f este un argument pentru func%ia 8. 0efini%ia func%iei 8 &a fi#
8(int (0funcpt)()) {
funcpt();

=n e.presia 8(f)$ f nu este un apel e func%ie. =n acest caz$ pentru


argumentul func%iei 8 se genereaz un pointer la func%ia f. 0eci 8 apeleaz
func%ia f printr-un pointer la ea.
0eclara%iile in func%ia 8 trebuie stuiate cu grij.
int (0funcpt)();
spune c funcpt este un pointer la o func%ie care returneaz un ntreg. Primul set
e paranteze este necesar$ eoarece fr el
int 0funcpt();
ar nsemna c funcpt este o func%ie care returneaz un pointer la un ntreg$ ceea
ce este cu totul iferit fa% e sensul primei e.presii. Kolosirea lui funcpt n
e.presia#
funcpt();
inic apelul func%iei a crei ares este at e pointerul funcpt.
Ca un e.emplu$ s consierm proceura e sortare a liniilor e la intrare$
moificat n sensul ca ac argumentul op%ional 7n apare n linia e coman$
atunci liniile se &or sorta nu le.icografic ci numeric$ liniile con%inn grupe e
numere.
@ sortare const e regul in trei componente# o comparare care etermin
orinea oricrei perec/i e elemente$ un sc/imb pentru a in&ersa orinea
elementelor implicate$ !i un algoritm e sortare care face comparrile !i
in&ersrile pn cn elementele snt ause n orinea cerut. Algoritmul e sortare
este inepenent e opera%iile e comparare astfel nct$ transmi%n iferite func%ii
33333333333333333333333333333333333333333333
C?
e comparare func%iei e sortare$ elementele e intrare se pot aranja up iferite
criterii.
Compararea le.icografic a ou linii se realizeaz prin func%ia strcmp. -ai
a&em ne&oie e o rutin numcmp care s compare ou linii pe baza &alorilor
numerice !i care s returneze aceia!i inicatori ca !i rutina strcmp.
0eclarm aceste trei func%ii n func%ia principal main$ iar pointerii la aceste
func%ii i transmitem ca argumente func%iei sort$ care la rnul ei &a apela aceste
func%ii prin intermeiul pointerilor respecti&i.
Kunc%ia principal main &a a&ea atunci urmtorul co#
#define J?QJ &00 +0 numr ma)im de linii de sortat 0+
int main (int ac, char 0a()*) {
char 0linptr)J?QJ*; +0 pointeri la linii te)t 0+
int nrl; +0 numr de linii citite 0+
int num ! 0; +0 1 dac sort numeric 0+
if (ac>& ## a()&*)0*!!B7B ## a()&*)&*!!BnB)
num ! &;
nrl ! Xead?ines(linptr,J?QJ);
if (nrl>!0) {
if (num) Mort(linptr,nrl,numcmp);
else Mort(linptr,nrl,strcmp);
Yrite?ines(linptr,nrl);

else puts("Qntrare prea mare pentru Mort");

=n apelul func%iei Mort$ argumentele strcmp !i numcmp snt aresele


func%iilor respecti&e. 0eoarece ele snt eclarate func%ii care returneaz un ntreg
(a se &eea mai jos structura programului,$ operatorul & nu trebuie s precea
numele func%iilor$ compilatorul fiin cel care gestioneaz transmiterea areselor
func%iilor.
* sintetizm ntr-o eclara%ie elementele comune ale celor ou func%ii#
t;pedef int (0VUfunc)(const char 0, const char 0);
Aceast eclara%ie efine!te ientificatorul VUfunc ca fiin un tip pointer la o
func%ie care returneaz un ntreg$ !i are ca argumente oi pointeri la caracter.
Glementele celor ou masi&e nu pot fi moificate. 'ipul VUfunc poate fi folosit
n continuare pentru a construi noi eclara%ii.
Kunc%ia Mort care aranjeaz liniile n orinea cresctoare se &a moifica
astfel#
(oid Mort(char 0()*, int n, VUfunc comp) {
int 8ap,i,H;
char 0tmp;
33333333333333333333333333333333333333333333
CB
for (8ap!n+.; 8ap>0; 8ap+!.)
for (i!8ap; i<n; i$$)
for (H!i78ap; H>!0; H7!8ap) {
if (comp(()H*,()H$8ap*)<!0)
'rea-;
tmp ! ()H*;
()H* ! ()H$8ap*;
()H$8ap* ! tmp;

Kunc%ia numcmp este efinit astfel#


int numcmp(const char 0s&, const char 0s.) {
dou'le atof(char 0s),(&,(.;
(& ! atof(s&);
(. ! atof(s.);
if ((&<(.) return 7&;
if ((&>(.) return &;
return 0;

*tructura programului este urmtoarea#


#include <stdli'.h>
#include <strin8.h>
#include <stdio.h>
int Xead?ines(...) {...
(oid Yrite?ines(...) {...
int numcmp(...) {...
t;pedef int (0VUfunc)(const char 0, const char 0);
(oid Mort(...) {...
int main(...) {...
=n func%ia main$ n locul &ariabilei num e tip ntreg putem folosi un pointer
e tip VUfunc astfel#
VUfunc >comp ! strcmp;
if (ac>& ## a()&*)0*!!B7B ## a()&*)&*!!BnB)
>comp ! numcmp;
nrl ! Xead?ines(linptr,J?QJ);
if (nrl>!0) {
Mort(linptr,nrl,>comp);
Yrite?ines(linptr,nrl);

0ac programul este compus in mai multe moule$ se utilizeaz un fi!ier
/eaer care con%ine eclara%iile tuturor func%iilor utilizate. Acest fi!ier trebuie
inclus n fiecare moul.
33333333333333333333333333333333333333333333
CD
?. 2tructuri 7i reuniuni
@ structur este o colec%ie e una sau mai multe &ariabile$ e acela!i tip sau e
tipuri iferite$ grupate mpreun sub un singur nume pentru a putea fi tratate
mpreun.
*tructurile ajut la organizarea atelor comple.e$ n special n programele
mari$ eoarece permit unui grup e &ariabile legate s fie tratate ca o singur
entitate. =n acest capitol &om ilustra moul e utilizare a structurilor.
?.1. :lemente de ba"
*inta.a unei eclara%ii e structur este#
struct nume#ablon#structur {
list#declaraii#membri
list#variabile;
)umele !ablonului structurii poate lipsi$ n acest caz !ablonul nu &a a&ea un
nume$ !i lista &ariabilelor este obligatorie.
1ista &ariabilelor poate lipsi$ n acest caz !ablonul e tip structur trebuie s
aib un nume. Astfel se efine!te un !ablon pentru &ariabile care &or fi efinite
ulterior$ a&n acest tip structurat#
struct nume#ablon#structur list#variabile;
Kiecare &ariabil in list &a fi compus in acelea!i elemente (membri,$ a!a
cum a fost efinit !ablonul.
* re&enim asupra rutinei e con&ersie a atei care a fost prezentat n
capitolul anterior. @ at calenaristic se compune in zi$ lun !i an. Aceste trei
&ariabile pot fi grupate ntr-o singur structur astfel#
struct MUdata {
int 9i,luna,an;
;
Cu&ntul c/eie struct introuce o eclara%ie e structur care este o list e
eclara%ii nc/ise ntre acolae. Acest cu&nt poate fi urmat op%ional e un nume$
numit marcaj e structur sau etic/et e structur$ cum este n e.emplul nostru
numele MUdata. -arcajul enume!te acest tip e structur !i poate fi folosit n
continuare ca o prescurtare pentru eclara%ia e structur etaliat creia i este
asociat.
Glementele sau &ariabilele men%ionate ntr-o structur se numesc membri ai
structurii. "n membru al structurii sau o etic/et !i o &ariabil oarecare$
nemembru$ pot a&ea acela!i nume fr a genera conflicte$ eoarece ele &or fi
ntoteauna eosebite una e alta in conte.t.
33333333333333333333333333333333333333333333
CA
0eclara%ia urmtoare efine!te &ariabila d ca o structur a&n acela!i !ablon
ca structura MUdata#
struct MUdata d;
@ structur e.tern sau static poate fi ini%ializat$ ata!n up efini%ia ei o
list e ini%ializatori pentru componente$ e e.emplu#
struct MUdata d ! {/,3,&45/;
"n membru al unei structuri este referit printr-o e.presie e forma#
nume#structur.membru
n care operatorul membru e structur . leag numele membrului e numele
structurii. Ca e.emplu fie atribuirea#
'is ! %(d.an"/) ## (d.an"&00) II %(d.an"/00);
*tructurile pot fi imbricate# o nregistrare e stat e plat$ e e.emplu$ poate fi
e urmtoarea form#
struct MUpers {
lon8 nrl;
char num)?J@C*,adr)?=FX*;
lon8 sal;
struct MUdata dnast,dan8;
;
'ipul structur MUpers con%ine ou structuri e !ablon MUdata. 0eclara%ia
urmtoare efine!te o &ariabil e tip structur cu numele an8$ a&n acela!i
!ablon ca structura MUpers#
struct MUpers an8;
=n acest caz#
an8.dnast.luna se refer la luna e na!tere
an8.dan8.an se refer la anul angajrii
*ingurele opera%ii pe care le &om aplica unei structuri &or fi accesul la un
membru al structurii !i consierarea aresei ei cu ajutorul operatorului #.
*tructurile e clas automatic$ ca !i masi&ele e aceea!i clas$ nu pot fi
ini%ializate; pot fi ini%ializate numai structurile e.terne !i statice$ regulile e
ini%ializare fiin acelea!i ca pentru masi&e.
*tructurile !i func%iile conlucreaz foarte eficient prin intermeiul pointerilor.
Ca un e.emplu$ s rescriem func%ia e con&ersie a atei$ care etermin numrul
zilei in an.
int JrTile(const struct MUdata 0pd) {
int i,9i,'is;
9i ! pd7>9i;
'is ! %(pd7>an"/) ## (pd7>an"&00) II %(pd7>an"/00);
for (i!&; i<pd7>luna; i$$)
9i $! Tile)'is*)i*;
33333333333333333333333333333333333333333333
CE
return 9i;

0eclara%ia in lista e argumente inic faptul c pd este un pointer la o


structur e !ablonul MUdata. )ota%ia pd7>an inic faptul c se refer la
membrul an al acestei structuri. =n general$ ac p este un pointer la o structur$
p7>membru#structur se refer la un membru particular (operatorul 7> se
formeaz in semnul minus urmat e semnul mai mare,.
0eoarece pd este pointer la o structur$ membrul an poate fi e asemenea
referit prin# (0pd).an$ ar nota%ia 7> se impune ca un mo con&enabil e
prescurtare. =n nota%ia (0pd).an$ parantezele snt necesare eoarece preceen%a
operatorului . (membru e structur, este mai mare ect cea a operatorului 0
(inirectare,.
@peratorii 7> !i . ai structurilor$ mpreun cu () (moificare priorit%i$ liste
e argumente, !i )* (ine.are, se gsesc n &rful listei e preceen%$ fiin in
acest punct e &eere foarte apropia%i. Astfel$ fie eclara%ia urmtoare care
efine!te un pointer p la o structur#
struct {
int :,0;;
0p;
*emnifica%iile urmtoarelor e.presii snt#
$$p7>:
+ncrementeaz membrul :$ nu pointerul p$ eoarece operatorul 7> are o
preceen% mai mare ect $$. Parantezele pot fi folosite pentru a moifica
orinea operatorilor at e preceen%a.
($$p)7>:
+ncrementeaz mai nti pointerul p$ apoi acceseaz membrul :$ in structura
inicat e noua &aloare a lui p.
(p$$)7>:
Acceseaz mai nti membrul :$ apoi incrementeaz pointerul p.
0p7>;
+nic con%inutul e la aresa memorat la ;.
0p7>;$$
Acceseaz mai nti ceea ce inic ;$ apoi incrementeaz pe ;.
(0p7>;)$$
+ncrementeaz ceea ce inic ;.
0p$$7>;
33333333333333333333333333333333333333333333
C6
Acceseaz mai nti ceea ce inic ;$ apoi incrementeaz pointerul p.
?.. t;pedef
*tilul e utilizare a tipurilor e ate structurate prezentat mai sus este foarte
frec&ent$ !i se ntlne!te mai ales n programe care apeleaz func%ii ale sistemelor
e operare 1inu..
Consierm totu!i c a scrie eclara%ii e func%ii care au ca !i parametri ate
structurate$ sau a efini &ariabile e tip structur$ este estul e neplcut atorit
cerin%ei e a preciza numele tipului preceat e cu&ntul rezer&at struct. 0e
aceea$ pe parcursul lucrrii &om folosi o facilitate (t;pedef, e a efini
sinonime pentru tipuri e ate e.istente$ care pot fi funamentale (preefinite, sau
efinite e programator.
=ntr-o eclara%ie t;pedef fiecare ientificator care apare ca parte a unui
eclarator e&ine sintactic ec/i&alent cu cu&ntul c/eie rezer&at pentru tipul
asociat cu ientificatorul. 0e e.emplu$ eclara%ia urmtoare l face pe ?AJZRH
sinonim cu int#
t;pedef int ?AJZRH;
'ipul ?AJZRH poate fi folosit ulterior n eclara%ii n acela!i mo ca !i tipul
int#
?AJZRH len,ma:len,0l8m)*;
=n mo similar$ eclara%ia urmtoare l face pe MRXQJZ sinonim cu char0$
aic pointer la caracter#
t;pedef char 0MRXQJZ;
'ipul MRXQJZ poate fi folosit n eclara%ii ulterioare#
MRXQJZ p,linptr)J?QJ*;
@bser&m c tipul care se eclar prin t;pedef apare pe pozi%ia numelui e
&ariabil$ nu imeiat up cu&ntul rezer&at t;pedef.
Relum efini%ia tipului VUfunc in capitolul preceent#
t;pedef int (0VUfunc)(const char 0, const char 0);
Aceast eclara%ie efine!te ientificatorul VUfunc ca fiin un tip pointer la o
func%ie care returneaz un ntreg$ !i are ca argumente oi pointeri la caracter.
Glementele celor ou masi&e nu pot fi moificate. 'ipul VUfunc poate fi folosit
n continuare pentru a construi noi eclara%ii.
Rescriem efini%iile e tipuri in sec%iunea preceent#
t;pedef struct {
int 9i,luna,an;
RUdata;
33333333333333333333333333333333333333333333
CC
@ structur e.tern sau static poate fi ini%ializat$ ata!n up efini%ia ei o
list e ini%ializatori pentru componente$ e e.emplu#
RUdata d ! {/,3,&45/;
*tructurile pot fi imbricate# un tip e nregistrare e stat e plat$ e e.emplu$
poate fi efinit astfel#
t;pedef struct {
lon8 nrl;
char num)?J@C*,adr)?=FX*;
lon8 sal;
RUdata dnast,dan8;
RUpers;
Kunc%ia JrTile poate fi eclarat astfel#
int JrTile(const RUdata 0pd);
G.ist ou moti&e principale care impun folosirea eclara%iilor t;pedef.
Primul este legat e problemele e portabilitate. Cn se folosesc eclara%ii
t;pedef pentru tipuri e ate care snt epenente e ma!in$ atunci pentru o
compilare pe un alt sistem e calcul este necesar moificarea oar a acestor
eclara%ii nu !i a atelor in program. 1a sfr!itul acestui capitol &om a un
e.emplu n acest sens relun efinirea tipului structurat at calenaristic.
Al oilea const n faptul c prin crearea e noi nume e tipuri se ofer
posibilitatea folosirii unor nume mai sugesti&e n program$ eci o mai rapi
n%elegere a programului.
=n continuare pe parcursul lucrrii &om folosi facilitatea t;pedef pentru a
efini tipuri comple.e e ate !i n special structuri.
?.%. Masi#e de structuri
*tructurile snt n mo special utile pentru tratarea masi&elor e &ariabile
legate prin conte.t. Pentru e.emplificare &om consiera un program care numr
intrrile fiecrui cu&nt c/eie intr-un te.t. Pentru aceasta a&em ne&oie e un
masi& e !iruri e caractere pentru pstrarea cu&intelor c/eie !i un masi& e
ntregi pentru a contoriza apari%iile acestora. @ posibilitate este e a folosi ou
masi&e paralele -e;w !i -e;c eclarate prin#
char 0-e;w)JNA[M*;
int -e;c)JNA[M*;
respecti& unul e pointeri la !iruri e caractere !i cellalt e ntregi.
Kiecrui cu&nt c/eie i corespune perec/ea (-e;w$-e;c, astfel nct putem
consiera cele ou masi&e ca fiin un masi& e perec/i. "rmtoarea eclara%ie
efine!te un tip structur RU-e;#
t;pedef struct {
33333333333333333333333333333333333333333333
CF
char 0-e;w;
int -e;c;
RU-e;;
Kolosim acest tip structur pentru a efini un masi& -e;m$ une JNA[M este o
constant efinit cu ajutorul irecti&ei #define#
RU-e; -e;m)JNA[M*;
Kiecare element al masi&ului este o structur e acela!i !ablon ca !i structura
RU-e;.
0eoarece masi&ul e structuri -e;m con%ine$ n cazul nostru$ o mul%ime
constant e cu&inte c/eie$ este mai u!or e ini%ializat o at pentru toteauna
c/iar n locul une este efinit. +ni%ializarea structurilor este o opera%ie analog cu
ini%ializarea unui masi& n sensul c efini%ia este urmat e o list e ini%ializatori
nc/i!i n acolae.
Atunci masi&ul e structuri -e;m &a fi ini%ializat astfel#
RU-e; -e;m)* ! {
"'rea-",0, "case",0, "char",0,
DE ... ED "while",0
;
+ni%ializatorii snt perec/i care corespun la membrii structurii. +ni%ializarea ar
putea fi fcut !i incluzn ini%ializatorii fiecrei structuri in masi& n acolae ca
n#
RU-e; -e;m)* ! { {"'rea-",0,{"case",0, . . .
ar parantezele interioare nu mai snt necesare ac ini%ializatorii snt &ariabile
simple sau !iruri e caractere !i ac to%i ini%ializatorii snt prezen%i.
0ac masi&ul -e;m este global$ e&entualii membri pentru care nu se
precizeaz o &aloare ini%ial &or primi &aloarea zero$ ar n acest caz parantezele
interioare snt necesare#
RU-e; -e;m)* ! { {"'rea-",{"case", . . .
Compilatorul &a etermina$ pe baza ini%ializatorilor$ imensiunea masi&ului
e structuri -e;m$ moti& pentru care nu este necesar inicarea imensiunii
masi&ului la ini%ializare.
Programul e numrare a cu&intelor c/eie ncepe cu efinirea masi&ului e
structuri -e;m. Kunc%ia principal main cite!te cte un cu&nt (!ir e caractere,
in te.tul e la intrarea stanar prin apelul repetat al func%iei scanf. Kiecare !ir
este apoi cutat n tabelul -e;m cu ajutorul unei func%ii e cutare 'inar;. 1ista
cu&intelor c/eie trebuie s fie n orine cresctoare pentru ca func%ia 'inar; s
lucreze corect. 0ac !irul cercetat este un cu&nt c/eie atunci func%ia 'inar;
33333333333333333333333333333333333333333333
F7
returneaz numrul e orine al acestuia n tabelul cu&intelor c/eie$ altfel
returneaz 4.
int 'inar;(char 0word, const RU-e; -t)*, int n) {
int l,r,m,c;
l ! 0; r ! n 7 &;
while (l<!r) {
m !(l $ r) + .;
c ! strcmp(word,-t)mid*.-e;w);
if (cond!!0) return m;
if (cond<0) r ! m 7 &;
else l ! m $ &;

return 7&;

int main() { >Y numr cu&intele c/eie Y>


int n;
char word),1*;
while (scanf(""s",word)%!AW>) {
n ! 'inar;(word,-e;m,JNA[M);
if (n>!0) -e;m)n*.-e;c$$;
for (n!0; n<JNA[M; n$$)
if (-e;m)n*.-e;c>0)
printf(""/d "s\n",-e;m)n*.-e;c,
-e;m)n*.-e;w);
return 0;

#mportantT Kunc%ia scanf cu escriptorul e format ""s" furnizeaz n


masi&ul word un !ir e caractere care nu conine spaii. 0ac !irul are cel pu%in
BE e caractere$ comportamentul programului este impre&izibil. 0ac orim s
prelum cel mult BA e caractere folosim formatul "",2s". Citirea !i scrierea cu
format &or fi etaliate n capitolul 47.
Jaloarea JNA[M este numrul cu&intelor c/eie in -e;m (imensiunea
masi&ului e structuri,. 0e!i putem calcula acest numr manual$ este mai simplu
!i mai sigur s-o facem prin program$ mai ales ac lista cu&intelor c/eie este
supus moificrilor. @ posibilitate e a calcula JNA[M prin program este e a
termina lista ini%ializatorilor cu un pointer J@?? !i apoi prin ciclare pe -e;m s
etectm sfr!itul lui. Acest lucru nu este necesar eoarece imensiunea masi&ului
e structuri este perfect eterminat n momentul compilrii. )umrul e intrri se
etermin mpr%in imensiunea masi&ului la imensiunea structurii -e;.
@peratorul si9eof furnizeaz imensiunea n octe%i a argumentului su.
33333333333333333333333333333333333333333333
F4
=n cazul nostru$ numrul cu&intelor c/eie este imensiunea masi&ului -e;m
mpr%it la imensiunea unui element e masi&. Acest calcul este fcut ntr-o
linie #define pentru a a o &aloare ientificatorului JNA[M#
#define JNA[M (si9eof(-e;m)+si9eof(RU-e;))
*tructura programului este urmtoarea#
#include <stdli'.h>
#include <strin8.h>
#include <stdio.h>
t;pedef struct { . . . RU-e;;
RU-e; -e;m)* ! { . . . ;
int 'inar;(. . .) {. . .
int main(. . .) {. . .
?./. &ointeri la structuri
Pentru a ilustra moul e corelare intre pointeri !i masi&ele e structuri$ s
rescriem programul e numrare a cu&intelor c/eie intr-un te.t$ e ata aceasta
folosin pointeri n loc e inici e masi&.
0eclara%ia e.tern a masi&ului e structuri -e;m nu necesit moificri$ n
timp ce func%iile main !i 'inar; a. Prezentm n continuare aceste func%ii
moificate.
RU-e; 0'inar;(char 0word, RU-e; -t)*,int n) {
int c;
struct -e; 0m;
struct -e; 0l ! -t;
struct -e; 0r ! -t $ n 7 &;
l ! -t; r ! -t $ n 7 &;
while (l<!r) {
m ! l $ (r 7 l) + .;
c ! strcmp(word,m7>-e;w);
if (c!!0) return m;
if (c>0) l ! m $ &;
else r ! m 7 &;

return J@??;

int main() { >Y numr cu&intele c/eie$ &ersiune cu pointeri Y>


int t;
char word),1*;
RU-e; 0p;
while (scanf(""s",word)%!AW>)
if (p!'inar;(word,-e;m,JNA[M))
p7>-e;c$$;
33333333333333333333333333333333333333333333
F?
for (p!-e;m; p<-e;m$JNA[M; p$$)
if (p7>-e;c>0)
printf(""/d "s\n",p7>-e;c,p7>-e;w);

* obser&m cte&a lucruri importante n acest e.emplu. =n primul rn$


eclara%ia func%iei 'inar; trebuie s inice c ea returneaz un pointer la o
structur e acela!i !ablon cu structura RU-e;$ n loc e un ntreg. 0ac 'inar;
gse!te un cu&nt n structura RU-e;$ atunci returneaz un pointer la el; ac nu-4
gse!te returneaz J@??. =n func%ie e aceste ou &alori returnate$ func%ia main
semnaleaz gsirea cu&ntului prin incrementarea cmpului -e;c corespunztor
cu&ntului sau trece irect la citirea urmtorului cu&nt.
=n al oilea rn$ toate opera%iile e acces la elementele masi&ului e structuri
-e;m se fac prin intermeiul pointerilor. Acest lucru etermin o moificare
semnificati& n func%ia 'inar;. Calculul elementului mijlociu nu se mai poate
face simplu prin#
m ! (l $ r) + .
eoarece aunarea a oi pointeri este o opera%ie ilegal$ neefinit. Aceast
instruc%iune trebuie moificat n#
m ! l $ (r 7 l) + .
care face ca aresa memorat la m s inice elementul e la jumtatea istan%ei
intre l !i r.
* mai obser&m ini%ializarea pointerilor l !i r$ care este perfect legal$
eoarece este posibil ini%ializarea unui pointer cu o ares a unui element eja
efinit.
=n func%ia main a&em urmtorul ciclu#
for(p!-e;m; p<-e;m$JNA[M; p$$) . . .
0ac p este un pointer la un masi& e structuri$ orice opera%ie asupra lui p %ine
cont e imensiunea unei structuri$ astfel nct p$$ incrementeaz pointerul p la
urmtoarea structur in masi&$ aunn la p imensiunea corespunztoare a
structurii. )u ntoteauna imensiunea structurii este egal cu suma imensiunilor
membrilor ei$ eoarece in cerin%e e aliniere a unor membri pot aprea goluri
n interiorul acesteia.
0e aceea$ ac orim s economisim ct mai mult memorie n cazul
masi&elor e structuri$ recomanm gruparea membrilor astfel nct s eliminm
pe ct posibil apari%ia unor astfel e goluri. =n principiu$ fiecare tip e ate are
anumite cerin%e e aliniere#
< short la multiplu e ?;
< lon8$ float$ dou'le$ lon8 dou'le la multiplu e D.
0imensiunea unei structuri este rotunjit la un multiplu ntreg corespunztor
acestor cerin%e.
33333333333333333333333333333333333333333333
FB
?.1. 2tructuri auto8re*erite
@ alt problem legat e efinirea !i utilizarea structurilor este cutarea n
tabele. Cn se ntlne!te o linie e forma#
#define [AM &
simbolul [AM !i te.tul e substitu%ie & se memoreaz ntr-o tabel. -ai trziu$ ori
e cte ori te.tul [AM &a aprea n instruc%iuni$ el &a fi nlocuit cu constanta &.
Crearea !i gestionarea tabelelor e simboluri este o problem e baz n
procesul e compilare. 0eoarece nu !tim inainte cte simboluri &or aprea n
program$ nu putem efini un masi& care s memoreze aceste informa%ii#
compilatorul trebuie s cunoasc numrul e elemente n momentul compilrii.
0e aceea &om aloca spa%iu pentru fiecare simbol nou$ !i aceste zone &or fi legate
ntre ele.
0efinim ou func%ii care gestioneaz simbolurile !i te.tele lor e substitu%ie.
Prima$ Qnstall(s,t) nregistreaz simbolul s !i te.tul e substitu%ie t ntr-o
tabel$ s !i t fiin !iruri e caractere. A oua$ ?oo-up(s) caut !irul s n tabel
!i returneaz fie un pointer la locul une a fost gsit$ fie J@?? ac !irul s nu
figureaz n tabel.
Algoritmul folosit pentru crearea !i gestionarea tabelei e simboluri este o
cutare pe baz e /as/ing (ispersie,. Kiecrui simbol i se calculeaz un co /as/
astfel# se aun courile A*C++ ale caracterelor simbolului !i se ia restul pro&enit
in mpr%irea numrului ob%inut in aunare !i imensiunea tabelului. Astfel$
fiecrui simbol i se asociaz un co /as/ H care &erific rela%ia#
0<!H<0:&00 (n /e.azecimal,
Coul /as/ astfel ob%inut &a fi folosit apoi ca un inice ntr-o tabel e
pointeri. "n element al acestei tabele (masi&, inic nceputul unui lan% e blocuri
care escriu simboluri cu acela!i co /as/. 0ac un element al tabelei este J@??
nseamn c nici un simbol nu are &aloarea respecti& e /as/ing.
"n bloc intr-un lan% inicat e un element al tabelei este o structur care
con%ine un pointer la simbol$ un pointer la te.tul e substitu%ie !i un pointer la
urmtorul bloc in lan%. "n pointer J@?? la urmtorul bloc in lan% inic sfr!itul
lan%ului.
F h
@
FF #nfo FF #nfo FF #nfo F
F h
1
FF #nfo FF #nfo FF #nfo FF #nfo F
F h

FF #nfo FF #nfo F
aablonul unei structuri (no, este urmtorul#
t;pedef struct MUlist {
char 0num,0def;
33333333333333333333333333333333333333333333
FD
struct MUlist 0n:t; > Y urmtoarea intrare n lan% Y>
RUlist, 0VUlist;
Aceast eclara%ie recursi& a unui no este perfect legal$ eoarece o
structur nu poate con%ine ca !i component o intrare a ei ns!i$ ar poate con%ine
un pointer la o structur e acela!i !ablon cu ea.
0eclara%ia e mai sus efine!te un tip structurat cu numele RUlist$ sinonim
cu tipul struct MUlist. 'ipul VUlist este sinonim cu RUlist 0 !i cu
struct MUlist 0.
-asi&ul e pointeri care inic nceputurile lan%ului e blocuri ce escriu
simboluri e acela!i co /as/ este#
#define JH=MH 0:&00
static RUlist 0hasht)JH=MH*;
Algoritmul e /as/ing pe care-l prezentm nu este cel mai bun posibil$ ar are
meritul e a fi e.trem e simplu#
int hashf(char 0s) { >Y formeaz &aloarea /as/ pentru !irul s Y>
int h(;
for (h(!0; 0s;) h( $! 0s$$;
return h( " JH=MH;

Acesta prouce un inice n masi&ul e pointeri hasht. =n procesul e


cutare a unui simbol$ ac acesta e.ist trebuie s se afle n lan%ul e blocuri care
ncepe la aresa con%inut e elementul in hasht cu inicele respecti&.
Cutarea n tabela e simboluri hasht se realizeaz cu func%ia ?oo-up.
0ac simbolul cutat este prezent une&a n lan%$ func%ia returneaz un pointer la
el$ altfel returneaz J@??.
RUlist 0?oo-up(char 0s) { >Y caut !irul s n hasht Y>
RUlist 0np;
for (np!hasht)hashf(s)*; np; np!np7>n:t)
if (strcmp(s,np7>num)!!0)
return np; >Y s-a gsit s Y>
return J@??; >Y nu s-a gsit s Y>

0ac orim s eliminm un no in list$ a&em ne&oie s !tim unde este


memorat adresa acestuia. 0ac noul neorit este primul in list$ aresa
acestuia este memorat ntr-un element in masi&ul hast$ altfel aceast ares
este memorat n membrul n:t al noului preceent in list. Jariabila pointer
pp &a re%ine une se afl memorat aresa care ne intereseaz. =n parcurgerea
listei$ &aloarea &ariabilei pp este tot timpul cu un pas n urma lui np$ care inic
noul curent.
VUlist 0pp;
33333333333333333333333333333333333333333333
FA
RUlist 0?oo-up(char 0s) { >Y caut !irul s n hasht Y>
RUlist 0np;
pp ! hasht $ hashf(s);
while (np!0pp) {
if (strcmp(s,np7>num)!!0)
return np;
pp ! #np7>n:t;

return pp ! J@??;

Kiecare no in list are tipul RUlist !i con%ine$ printre altele$ !i aresa


urmtorului no. 0ar aresa primului no e memorat ntr-un element care are alt
tip ect RUlist. 0e aceea a&em ne&oie s memorm adresa zonei une este
memorat aresa care ne intereseaz$ e une necesitatea efini%iei globale
VUlist 0pp;
Aceast efini%ie este ec/i&alent cu
RUlist 00pp;
0ac !i elementele masi&ului ar a&ea tipul RUlist$ nu am a&ea ne&oie e
ou ni&ele e inirectare$ ar fi suficient s memorm aresa noului preceent
ntr-o &ariabil pointer la RUlist.
Rutina Qnstall folose!te func%ia ?oo-up pentru a etermina ac simbolul
nou care trebuie introus n lan% este eja prezent sau nu. 0ac mai e.ist o
efini%ie anterioar pentru acest simbol$ ea trebuie nlocuit cu efini%ia nou;
altfel se creeaz o intrare nou pentru acest simbol$ care se introuce la nceputul
lan%ului. Kunc%ia Qnstall returneaz J@?? ac in anumite moti&e nu e.ist
suficient spa%iu pentru crearea unui bloc nou.
RUlist 0Qnstall(char 0num, char 0def) {
>Y scrie (num$ def, n hta' Y>
RUlist 0np;
int h(;
np ! ?oo-up(num);
if (np!!J@??) { >Y nu s-a gsit Y>
np ! (RUlist0)calloc(&,si9eof(0np));
if (np!!J@??) return J@??; >Y nu e.ist spa%iu Y>
np7>num ! strdup(num);
if (np!!J@??) return J@??;
h( ! hashf(np7>num);
np7>n:t ! hasht)h(*;
hasht)h(* ! np;

else >Y noul e.ist eja Y>
free(np7>def); >Y elibereaz efini%ia &ec/e Y>
33333333333333333333333333333333333333333333
FE
np7>def ! strdup(def);
if (np7>def!!J@??) return J@??;
return np;

Rutina Xemo(e elimin in list ultimul element consultat.


(oid Xemo(e() {
RUlist 0np;
if (%pp) return;
free(np!(0pp)7>n:t);
0pp ! np; pp ! J@??;

Cum eliberm toate zonele ocupate e o listZ 'rebuie s fim foarte aten%i
eoarece$ nainte e a elibera memoria ocupat e noul curent$ trebuie eliberat
memoria ocupat e noul care urmeaz celui curent. Prezentm mai nti &arianta
recursi&#
(oid >ree?ist(RUlist 0np) {
if (np) {
>ree?ist(np7>n:t);
free(np);

0efini%ia recursi& a func%iei >ree?ist consum estul e mult memorie


in sti&$ e aceea rem n continuare !i &arianta nerecursi&$ mai eficient.
(oid >ree?ist(RUlist 0np) {
RUlist 0n:;
while (np) {
n: ! np7>n:t;
free(np);
np ! n:;

Kunc%ia main$ care utilizeaz aceste rutine$ nu are ne&oie s ini%ializeze


elementele masi&ului hasht cu J@??$ eoarece acesta este eclarat global !i este
automat ini%ializat corespunztor. 0e la intrarea stanar se a!teapt introucerea
unor comenzi#
$ nume valoare
6 nume
O nume
Comana + insereaz n list simbolul nume cu &aloarea at. 0ac numele
introus nu e.ist n listele hasht atunci se afi!eaz un mesaj corespunztor$
altfel se afi!eaz &ec/ea &aloare care este apoi nlocuit e noua &aloare.
33333333333333333333333333333333333333333333
F6
Comana O afi!eaz &aloarea simbolului nume$ ac acesta e.ist n listele
hasht.
Comana 6 elimin simbolul nume$ ac acesta e.ist n liste.
0up epuizarea atelor introuse memoria ocupat e cele JH=MH liste este
eliberat.
int main() {
char num),1*,def),1*,op;
RUlist 0np;
int i;
while (scanf(" "c",#op)%!AW>)
switch (op) {
case B$BP
scanf(""s "s",num,def);
np ! ?oo-up(num);
if (%np)
puts("Jew name\n");
else
printf("Wld (alueP "s\n",np7>def);
Qnstall(num,def);
'rea-;
case B7BP case BOBP
scanf(""s",num);
np ! ?oo-up(num);
if (%np)
puts("Jot in list");
else
switch (op) {
case B7BP
Xemo(e(); puts("Xemo(ed");
'rea-;
case BOBP
printf("SalueP "s\n",np7>def);
'rea-;


for (i!0; i<JH=MH; i$$)
>ree?ist(hasht)i*);
return 0;

?.;. Arbori binari de cutare


* consierm problema numrului apari%iilor tuturor cu&intelor intr-un te.t
e intrare. 0eoarece lista cu&intelor nu este cunoscut inainte$ n-o putem sorta
33333333333333333333333333333333333333333333
FC
folosin algoritmul prezentat la sfr!itul capitolului preceent$ altfel contorizarea
ar fi fost foarte simpl pentru o list eja oronat. )u putem utiliza nici liste
nln%uite pentru a &eea ac un cu&nt citit e.ist sau nu n liste$ pentru c
timpul e e.ecu%ie al programului ar cre!te ptratic cu numrul cu&intelor e la
intrare.
"n mo e a organiza atele pentru a lucra eficient cu o list e cu&inte
arbitrare este e a pstra mul%imea e cu&inte tot timpul sortat$ plasn fiecare
nou cu&nt in intrare pe o pozi%ie corespunztoare$ relati& la intrrile anterioare.
0ac am realiza acest lucru prin eplasarea cu&intelor ntr-un masi& liniar$
programul ar ura$ e asemenea$ foarte mult. 0e aceea$ pentru rezol&area eficient
a acestei probleme &om folosi o structur e ate numit arbore binar#
UUUUU
I car I
+ \
I 'ac I I lac I
+
I cer I
Kiecare no al arborelui &a reprezenta un cu&nt istinct in intrare !i &a
con%ine urmtoarea informa%ie#
< un pointer la un !ir e caractere;
< un contor pentru numrul e apari%ii;
< un pointer la escenentul stng al noului;
< un pointer la escenentul rept al noului; nici un no al arborelui nu &a a&ea
mai mult ect oi escenen%i ar poate a&ea un escenent sau c/iar nici unul.
Arborele se construie!te astfel nct pentru orice no$ sub-arborele stng al su
con%ine numai cu&intele care snt mai mici ect cu&ntul in no$ iar sub-arborele
rept con%ine numai cu&intele care snt mai mari ect cu&ntul in no$
compararea fcnu-se in punct e &eere le.icografic.
Pentru a !ti ac un cu&nt nou in intrare e.ist eja n arbore$ se porne!te e
la noul rcin !i se compar noul cu&nt cu cu&ntul memorat n noul
rcin. 0ac ele coinci se incrementeaz contorul e numrare a apari%iilor
pentru noul rcin !i se &a citi un nou cu&nt in intrare.
0ac noul cu&nt in intrare este mai mic ect cu&ntul memorat n noul
rcin$ cutarea continu cu escenentul stng$ altfel se in&estig/eaz
escenentul rept. 0ac nu e.ist nici un escenent pe irec%ia cerut$ noul
cu&nt nu e.ist n arbore !i &a fi inserat pe pozi%ia escenentului corespunztor.
*e obser& c acest proces e cutare este recursi&$ eoarece cutarea in fiecare
no utilizeaz o cutare ntr-unul intre escenen%ii si.
Prin urmare se impune e la sine ca rutinele e inserare n arbore !i e afi!are
s fie recursi&e.
33333333333333333333333333333333333333333333
FF
Re&enin la escrierea unui no$ el apare ca fiin o structur cu patru
componente#
t;pedef struct MUnode { >Y noul e baz Y>
char 0w; >Y pointer la cu&nt Y>
int c; >Y numrtor e apari%ii Y>
struct MUnode 0l; >Y escenent stng (left, Y>
struct MUnode 0r; >Y escenent rept (rig/t, Y>
RUnode,0VUnode;
0eclara%ia e mai sus efine!te un tip structurat cu numele RUnode$ sinonim
cu tipul struct MUnode. 'ipul VUnode este sinonim cu RUnode 0 !i cu
struct MUnode 0.
Kunc%ia principal main cite!te cte un cu&nt in te.tul e la intrarea
stanar$ !i l plaseaz n arbore prin rutina RreeQnsert.
int main() { >Y contorizare apari%ii cu&inte Y>
char word),1*;
VUnode root;
root ! J@??;
while (scanf(""s",word)%!AW>)
RreeQnsert(#root,word);
RreeVrint(root);
Rree>ree(root);

Kunc%ia RreeQnsert gestioneaz fiecare cu&nt in intrare ncepn cu cel


mai nalt ni&el al arborelui (rcina,. 1a fiecare pas$ cu&ntul in intrare este
comparat cu cu&ntul asociat rcinii !i este apoi transmis n jos$ fie
escenentului stng$ fie celui rept$ printr-un apel recursi& la rutina
RreeQnsert. =n acest proces$ cu&ntul fie e.ist eja$ une&a n arbore$ caz n
care contorul lui e numrare a apari%iilor se incrementeaz$ fie cutarea continu
pn la ntlnirea unui pointer J@??$ caz n care noul trebuie creat !i augat
arborelui. Cn se creeaz un no nou$ rutina RreeQnsert l leag noul al
crui escenent este noul no$ n cmpul l sau r$ up cum noul cu&nt este mai
mic sau mai mare fa% e cu&ntul origine. 'ocmai in acest moti& rutina
RreeQnsert prime!te adresa &ariabilei pointer care &a inica spre &iitorul no
fiu.
(oid RreeQnsert(VUnode 0p, char 0w) {
int c;
if (0p) {
c ! strcmp(w,(0p)7>w);
if (c!!0) (0p)7>c$$;
else
if (c<0) >Y noul cu&nt mai mic$ mergem spre stnga Y>
33333333333333333333333333333333333333333333
477
RreeQnsert(#(0p)7>l,w);
else >Y noul cu&nt mai mare$ mergem spre reapta Y>
RreeQnsert(#(0p)7>r,w);

else {
0p ! (VUnode)calloc(&,si9eof(RUnode));
(0p)7>w ! strdup(w);
(0p)7>c ! &;

Am consierat c este mai como s solicitm alocare e memorie pentru un


no apeln func%ia calloc#
(oid calloc(unsi8ned ne, unsi8ned s9);
Argumentele acestei func%ii snt ne# numrul e elemente pe care le &a a&ea
zona$ !i s9# mrimea n octe%i a unui element$ care se poate ob%ine cu operatorul
si9eof. Con%inutul zonei e memorie este pus la zero$ spre eosebire e func%ia
malloc care pstreaz nesc/imbat acest con%inut (&alori reziuale,.
1a augarea unui no nou$ func%ia calloc ini%ializeaz pointerii spre cei
oi escenen%i cu )"11. Rmne s crem o copie a !irului at cu func%ia
strdup$ eja cunoscut$ !i s ini%ializm contorul cu 4.
Rutina RreeVrint afi!eaz arborele astfel nct pentru fiecare no se
afi!eaz sub-arborele lui stng$ aic toate cu&intele mai mici ect cu&ntul
curent$ apoi cu&ntul curent !i la sfr!it sub-arborele rept$ aic toate cu&intele
mai mari ect cu&ntul curent. Kunc%ia RreeVrint este una in cele mai tipice
rutine recursi&e.
(oid RreeVrint(VUnode p) {
if (p) {
Rreeprint(p7>l);
printf(""2d "s\n",p7>c,p7>w);
RreeVrint(p7>r);

Gste important e re%inut faptul c n algoritmul e cutare n arbore$ pentru a


ajunge la un anumit no$ se parcurg toate nourile preceente pe ramura
respecti& (stng sau reapt,$ ncepn ntoteauna cu noul rcin. 0up
fiecare ie!ire in rutina RreeQnsert$ atorit recursi&it%ii se parcurge acela!i
rum$ e ata aceasta e la noul gsit spre rcina arborelui$ refcnu-se to%i
pointerii rumului parcurs.
@ obser&a%ie legat e acest e.emplu# ac arborele este nebalansatc$ aic
cu&intele nu sosesc n orine aleatoare in punct e &eere le.icografic$ atunci
timpul e e.ecu%ie al programului poate e&eni foarte mare. Cazul limit n acest
sens este acela n care cu&intele e la intrare snt eja n orine (cresctoare sau
33333333333333333333333333333333333333333333
474
escresctoare,$ caz n care programul nostru simuleaz o cutare liniar ntr-un
mo estul e costisitor.
Rutina Rree>ree elibereaz memoria ocupat e nourile arborelui.
@rinea n care se face eliberarea este urmtoarea# mai nti sub-arborele stng$
apoi sub-arborele rept$ !i n final noul curent. ai aici eliberarea memoriei
ocupate e no trebuie s respecte o orine# mai nti memoria ocupat e !irul e
caractere$ apoi memoria ocupat e noul propriu-zis.
(oid Rree>ree(VUnode p) {
if (p) {
Rree>ree(p7>l);
Rree>ree(p7>r);
free(p7>w); free(p);

?.<. C-mpuri
"n cmp se efine!te ca fiin o mul%ime e bi%i consecuti&i intr-un cu&nt sau
ntreg. Concret$ in moti&e e economie a spa%iului e memorie$ este util
mpac/etarea unor obiecte ntr-un singur cu&nt ma!in. "n caz frec&ent e acest
tip este utilizarea unui set e flaguri$ fiecare pe un bit$ pentru tabela e simboluri a
unui compilator.
Kiecare simbol intr-un program are anumite informa%ii asociate lui$ cum snt
e e.emplu clasa e memorie$ tipul$ ac este sau nu cu&nt c/eie !.a.m.. Cel mai
compact mo e a coifica aceste informa%ii este folosirea unui set e flaguri$ e
cte un bit$ ntr-un singur ntreg sau caracter.
-oul cel mai uzual pentru a face acest lucru este e a efini un set e m!ti$
fiecare masc fiin corespunztoare pozi%iei bitului n interiorul caracterului sau
cu&ntului. 0e e.emplu#
#define NA[YWXF 0&
#define A<RAXJ=? 0.
#define MR=RQE 0/
efinesc m!tile NA[YWXF$ A<RAXJ=? !i MR=RQE care se refer la bi%ii 7$ 4 !i
respecti& ? in caracter sau cu&nt. Atunci accesarea acestor bi%i se realizeaz cu
ajutorul opera%iilor e eplasare$ mascare !i complementare$ escri!i ntr-un
capitol anterior. )umerele trebuie s fie puteri ale lui ?.
G.presii e forma urmtoare apar frec&ent !i ele seteaz bi%ii 4 !i ? in
caracterul sau ntregul flags (n e.emplul nostru,#
fla8s I ! A<RAXJ=? I MR=RQE;
G.presia urmtoare selecteaz bi%ii 4 !i ? in flags#
fla8s #! A<RAXJ=? I MR=RQE;
33333333333333333333333333333333333333333333
47?
G.presia urmtoare este ae&rat cn cel pu%in unul in bi%ii 4 sau ? in
flags este unu#
if (fla8s # (A<RAXJ=? I MR=RQE)) ...
G.presia urmtoare este ae&rat cn bi%ii 4 !i ? in flags snt ambii zero#
if (%(fla8s # (A<RAXJ=? I MR=RQE))) ...
1imbajul C ofer aceste e.presii ca o alternati& pentru posibilitatea e a
efini !i e a accesa bi%ii intr-un cu&nt n mo irect$ folosin operatorii logici
pe bi%i.
*inta.a efini%iei cmpului !i a accesului la el se bazeaz pe structuri. 0e
e.emplu construc%iile #define in e.emplul e mai sus pot fi nlocuite prin
efinirea a trei cmpuri#
struct {
unsi8ned isU-e;wordP&;
unsi8ned isUe:ternalP&;
unsi8ned isUstaticP&;
fla8s;
Aceast construc%ie efine!te &ariabila fla8s care con%ine B cmpuri$ fiecare
e cte un bit. )umrul care urmeaz up P (ou puncte, reprezint lungimea
cmpului n bi%i. Cmpurile snt eclarate unsi8ned pentru a sublinia c ele snt
cantit%i fr semn. Pentru a ne referi la un cmp ini&iual in &ariabila fla8s
folosim o nota%ie similar cu nota%ia folosit pentru membrii structurilor.
fla8s.isU-e;word
fla8s.isUstatic
Cmpurile se comport ca ni!te ntregi mici fr semn !i pot participa n
e.presii aritmetice ca orice al%i ntregi. Astfel$ e.presiile anterioare pot fi scrise
mai natural sub forma urmtoare#
fla8s.isUe:tern ! fla8s.isUstatic ! &;
pentru setarea bi%ilor 4 !i ? in &ariabila fla8s$
fla8s.isUe:tern ! fla8s.isUstatic ! 0;
pentru !tergerea bi%ilor$ iar#
if (fla8s.isUe:tern!!0 ## fla8s.isUstatic!!0)
pentru testarea lor.
"n cmp nu trebuie s ep!easc limitele unui cu&nt (4E sau B? e bi%i$ n
func%ie e sistemul e calcul,. =n caz contrar$ cmpul se aliniaz la limita
urmtorului cu&nt. Cmpurile nu necesit s fie enumite. "n cmp fr nume$
escris numai prin caracterul P !i lungimea lui n bi%i$ este folosit pentru a rezer&a
spa%iu n &eerea alinierii urmtorului cmp. 1ungimea zero a unui cmp poate fi
folosit pentru for%area alinierii urmtorului cmp la limita unui nou cu&nt$ el
fiin presupus a con%ine tot cmpuri !i nu un membru obi!nuit al structuri$
eoarece n acest ultim caz alinierea se face n mo automat. )ici un cmp nu
33333333333333333333333333333333333333333333
47B
poate fi mai lung ect un cu&nt. Cmpurile se atribuie e la reapta la stnga$ e
la pozi%iile cele mai pu%in semnificati&e la cele mai semnificati&e.
Cmpurile nu pot constitui masi&e$ nu au arese$ astfel nct operatorul & nu se
poate aplica asupra lor.
?.>. !euniuni
@ reuniune este o &ariabil care poate con%ine$ la momente iferite$ obiecte e
iferite tipuri !i imensiuni; compilatorul este cel care %ine e&ien%a imensiunilor
!i aliniamentului.
Reuniunile ofer posibilitatea ca mai multe tipuri iferite e ate s fie tratate
ntr-o singur zon e memorie.
* relum e.emplul tabelei e simboluri a unui compilator$ presupunn c se
gestioneaz constante e tip int$ float sau !iruri e caractere.
Jaloarea unei constante particulare ar putea fi memorat ntr-o &ariabil e tip
corespunztor$ ar este mai con&enabil$ pentru gestiunea tabelei e simboluri$ ca
&aloarea s fie memorat n aceea!i zon e memorie$ iniferent e tipul ei.
Acesta este scopul unei reuniuni# e a furniza o singur &ariabil care s poat
con%ine oricare intre &alorile unor tipuri e ate. Ca !i n cazul cmpurilor$
sinta.a efini%iei !i accesului la o reuniune se bazeaz pe structuri. Kie efini%ia#
union uUta8 {
int i(al;
float f(al;
char 0p(al;
u(al;
Jariabila u(al &a fi suficient e mare ca s poat pstra pe cea mai mare
intre cele trei tipuri e componente. @ricare intre tipurile e mai sus poate fi
atribuit &ariabilei u(al !i apoi folosit n e.presii n mo corespunztor$ aic
tipul n u(al este tipul ultim atribuit. "tilizatorul este cel care %ine e&ien%a
tipului curent memorat ntr-o reuniune.
*intactic$ membrii unei reuniuni snt accesibili printr-o construc%ie e forma#
nume#reuniune. membru
pointer#la#reuniune7>membru
0ac &ariabila ut;pe este utilizat pentru a %ine e&ien%a tipului curent
memorat n u(al$ atunci putem a&ea urmtorul co#
switch (ut;pe) {
case QJRP
printf (""d\n",u(al.i(al); 'rea-;
case >?W=RP
printf(""f\n",u(al.f(al); 'rea-;
case MRXQJZP
33333333333333333333333333333333333333333333
47D
printf(""s\n",u(al.p(al); 'rea-;
defaultP
printf("tip incorect "d in ut;pe\n",ut;pe);
'rea-;

Reuniunile pot aprea n structuri !i masi&e !i in&ers. *inta.a pentru accesarea
unui membru al unei reuniuni intr-o structur (sau in&ers, este ientic cu cea
pentru structurile imbricate. 0e e.emplu$ n masi&ul e structuri
s;mta')JM[C* efinit e#
struct {
char 0name;
int fla8s,ut;pe;
union {
int i(al;
float f(al;
char 0p(al;
u(al;
s;mta')JM[C*;
&ariabila i(al se refer prin#
s;mta')i*.u(al.i(al
iar primul caracter al !irului inicat e p(al prin#
0s;mta')i*.u(al.p(al
'e/nic$ o reuniune este o structur n care to%i membrii au eplasamentul zero$
structura fiin suficient e mare pentru a putea pstra pe cel mai mare membru.
Alinierea este corespunztoare pentru toate tipurile reuniunii. Pointerii la reuniuni
pot fi folosi%i n mo similar cu pointerii la structuri.
"rmtorul e.emplu trebuie stuiat cu aten%ie$ eoarece implementarea este
epenent e ar/itectura sistemului e calcul. 0e aceea &om prezenta ou
eclara%ii e tip$ corespunztoare celor ou mouri e reprezentare a &alorilor
ntregi#
< pentru ar/itecturi 1ig $ndian#
t;pedef struct {
short an;
char luna, 9i;
RUstruc;
< pentru ar/itecturi %ittle $ndian#
t;pedef struct {
char luna, 9i;
short an;
33333333333333333333333333333333333333333333
47A
RUstruc;
=n continuare putem efini un tip at calenaristic#
t;pedef union {
RUstruc ds;
lon8 dn;
RUdata;
Kie urmtoarele efini%ii e &ariabile#
RUdata dc&, dc.;
=n continuare putem interpreta con%inutul &ariabilelor dc& !i dc. fie ca
structuri fie ca ntregi lungi.
@ &ariabil e acest tip se ini%ializeaz astfel#
dc&.ds.an ! . . .;
dc&.ds.luna ! . . .;
dc&.ds.9i ! . . .;
0ou ate calenaristice se compar ct se poate e natural#
dc&.dn < dc..dn
Cum putem epista automat ce fel e ar/itectur are sistemul e calculZ
union {
lon8 l;
char c)/*;
tst ! 0:&.,/2135;
if (tst.c)0*!!0:&.) puts("Di8 Andian");
else puts("?ittle Andian");
33333333333333333333333333333333333333333333
47E
1@. 0peraii de intrare D ie7ire
=ntruct limbajul C nu a fost ez&oltat pentru un sistem particular e operare$
!i atorit faptului c s-a orit realizarea unei portabilit%i ct mai mari$ att a unui
compilator C$ ct !i a programelor scrise n acest limbaj$ el nu pose facilit%i e
intrare > ie!ire.
G.ist totu!i un sistem e intrare > ie!ire constituit intr-un numr e
subprograme care realizeaz func%ii e intrare > ie!ire pentru programe scrise n C$
ar care nu fac parte in limbajul C. Aceste subprograme se gsesc n biblioteca
C.
*copul acestui capitol este e a escrie cele mai utilizate subprograme e
intrare > ie!ire !i interfa%a lor cu programele scrise n limbajul C.
1@.1. Intrri 7i ie7iri standard+ *i7iere
*istemul +>@ ofer utilizatorului trei fiiere stanar e lucru. Cu&ntul fi!ier
a fost pus ntre g/ilimele$ eoarece limbajul nu efine!te acest tip e at !i pentru
c fi!ierele reprezint mai egrab ni!te flu.uri e intrare > ie!ire stanar puse la
ispozi%ia utilizatorului. Aceste fi!iere snt#
< fi!ierul stanar e intrare (stdin,;
< fi!ierul stanar e ie!ire (stdout,;
< fi!ierul stanar e afi!are a mesajelor (stderr,.
'oate aceste trei fi!iere snt sec&en%iale !i n momentul e.ecu%iei unui program
C snt implicit efinite !i esc/ise.
stdin !i stdout snt asociate n mo normal terminalului e la care a fost
lansat programul n e.ecu%ie. *istemul +>@ permite reirectarea acestor fi!iere pe
alte periferice !i nc/ierea lor la nc/eierea e.ecu%iei programului. Reirectarea
fi!ierului stdin se specific prin construc%ia#
<specificator#fiier#intrare
n linia e coman prin care a fost lansat programul.
Reirectarea fi!ierului stdout se specific prin construc%ia#
>specificator#fiier#ieire
n linia e coman prin care a fost lansat programul.
Reirectarea fi!ierului stdout pe un alt periferic$ n scopul efecturii unei
opera%ii e augare (appen, se specific prin construc%ia#
>>specificator#fiier#ieire
stderr este ntoteauna asociat terminalului e la care a fost lansat
programul n e.ecu%ie !i nu poate fi reirectat.
Astfel c o linie e coman a unui program poate arta astfel#
"rog <intrare#standard >ieire#standard ali parametri
33333333333333333333333333333333333333333333
476
"rog < intrare#standard >> ieire#standard ali parametri
Kiecare in parametri poate lipsi; n lipsa unui specificator e intrare sau ie!ire
stanar se folose!te terminalul curent. Asocierea unui fi!ier cu intrarea sau
ie!irea stanar este fcut e sistemul e operare$ programul primin oar
informa%ii espre ceilal%i parametri in linia e coman.
Pentru a se putea face o referire la fi!iere orice program C trebuie s con%in
fi!ierul stdio.h$ care se inclue printr-o linie e forma#
#include <stdio.h>
Pentru claritatea !i lizibilitatea programelor scrise n C$ ct !i pentru crearea
unei imagini sugesti&e asupra lucrului cu fi!iere$ n fi!ierul e efini%ii stanar
stdio.h s-a efinit un nou nume e tip e at !i anume >Q?A care este o
structur. Pentru a referi un fi!ier$ este necesar o eclara%ie e forma#
>Q?A 0fp;
une fp &a fi numele e at cu care se &a referi fi!ierul n orice opera%ie e intrare
> ie!ire asociat. +at cte&a informa%ii pstrate e structura >Q?A#
< un ientificator e fi!ier pe care sistemul e operare l asociaz flu.ului pe
urata prelucrrii; acesta poate fi aflat cu ajutorul func%iei fileno;
< aresele zonelor tampon asociate; pozi%ia curent n aceste zone;
< inicatorii e sfr!it e fi!ier !i e eroare;
< alte informa%ii.
1@.. Accesul la *i7iere+ desc,idere 7i -nc,idere
)ume
fopen - esc/ie un flu.
0eclara%ie
>Q?A 0fopen(const char 0num, const char 0mod);
0escriere
Kunc%ia fopen esc/ie fi!ierul al crui nume este un !ir inicat e num !i i
asociaz un flu..
Argumentul mod inic un !ir care ncepe cu una in sec&en%ele urmtoare#
r esc/ie un fi!ier pentru citire;
r$ esc/ie pentru citire !i scriere;
w trunc/iaz fi!ierul la lungime zero sau creeaz un fi!ier pentru scriere;
w$ esc/ie pentru augare la sfr!it$ n citire !i scriere; fi!ierul este creat ac
nu e.ist$ altfel este trunc/iat;
a esc/ie pentru augare la sfr!it$ n scriere; fi!ierul este creat ac nu e.ist;
a$ esc/ie pentru augare la sfr!it$ n citire !i scriere; fi!ierul este creat ac
nu e.ist;
33333333333333333333333333333333333333333333
47C
0up esc/iere$ n primele patru cazuri inicatorul pozi%iei n flu. este la
nceputul fi!ierului$ n ultimele ou la sfr!itul acestuia.
airul mod inclue e asemenea litera ' (esc/ie un fi!ier binar, sau t
(esc/ie un fi!ier te.t, fie pe ultima pozi%ie fie pe cea in mijloc.
@pera%iile e citire !i scriere pot alterna n cazul flu.urilor rea > :rite n orice
orine. * re%inem c stanarul A)*+ C cere s e.iste o func%ie e pozi%ionare
ntre o opera%ie e intrare !i una e ie!ire$ sau ntre o opera%ie e ie!ire !i una e
intrare$ cu e.cep%ia cazului cn o opera%ie e citire etecteaz sfr!itul e fi!ier.
Aceast opera%ie poate fi inefecti& < cum ar fi fsee-(flu:, 0?,
MAANUE@X) apelat cu scop e sincronizare.
Jalori returnate
=n caz e succes se returneaz un pointer e tip >Q?A. =n caz e eroare se
returneaz )"11 !i &ariabila global errno inic coul erorii.
)ume
fclose - nc/ie un flu.
0eclara%ie
int fclose( >Q?A 0flu:);
0escriere
Kunc%ia fclose nc/ie fi!ierul asociat flu.ului flu:. 0ac flu: a fost
esc/is pentru ie!ire$ orice ate aflate n zone tampon snt scrise n fi!ier n
prealabil cu un apel fflush.
Jalori returnate
=n caz e succes se returneaz 0. =n caz e eroare se returneaz AW> !i
&ariabila global errno inic coul erorii.
)ume
tmpfile - creeaz un fi!ier temporar
0eclara%ie
>Q?A 0tmpfile();
0escriere
Kunc%ia tmpfile genereaz un nume unic e fi!ier temporar. Acesta este
esc/is n mo binar pentru scriere > citire ("w'$",. Ki!ierul &a fi !ters automat la
nc/iere sau la terminarea programului.
Jaloare returnat
33333333333333333333333333333333333333333333
47F
Kunc%ia returneaz un escriptor e flu. n caz e succes$ sau J@?? ac nu
poate fi generat un nume unic e fi!ier sau ac fi!ierul nu poate fi esc/is. =n caz
e eroare &ariabila global errno inic coul erorii.
)ume
fflush - for%eaz scrierea n flu.
0eclara%ie
int fflush(>Q?A 0flu:);
0escriere
Kunc%ia fflush for%eaz o scriere a tuturor atelor aflate n zone tampon ale
flu.ului flu:. Klu.ul rmne esc/is.
Jalori returnate
=n caz e succes se returneaz 0. =n caz e eroare se returneaz AW> !i
&ariabila global errno inic coul erorii.
)ume
fsee-$ ftell$ rewind - repozi%ioneaz un flu.
0eclara%ie
int fsee-(>Q?A 0flu:, lon8 ofs, int reper);
lon8 ftell(>Q?A 0flu:);
(oid rewind(>Q?A 0flu:);
0escriere
Kunc%ia fsee- seteaz inicatorul e pozi%ie pentru fi!ierul asociat flu.ului
flu:. )oua pozi%ie$ at n octe%i$ se ob%ine aunn ofs octe%i (offset, la pozi%ia
specificat e reper. 0ac reper este MAANUMAR$ MAANUE@X$ sau
MAANUAJF$ ofs este relati& la nceputul fi!ierului$ pozi%ia curent a
inicatorului$ respecti& sfr!itul fi!ierului. Kunc%ia fsee- !terge inicatorul e
sfr!it e fi!ier.
Kunc%ia ftell ob%ine &aloarea curent a inicatorului e pozi%ie pentru
fi!ierul asociat flu.ului flu:.
Kunc%ia rewind pozi%ioneaz inicatorul e pozi%ie pentru fi!ierul asociat
flu.ului flu: la nceputul fi!ierului. Gste ec/i&alent cu#
((oid)fsee-(flu:, 0?, MAANUMAR)
cu completarea c func%ia rewind !terge !i inicatorul e eroare al flu.ului.
Jalori returnate
33333333333333333333333333333333333333333333
447
Kunc%ia rewind nu returneaz nici o &aloare. =n caz e succes$ fsee-
returneaz 0$ !i ftell returneaz offset-ul curent. =n caz e eroare se returneaz
AW> !i &ariabila global errno inic coul erorii.
)ume
fileno < returneaz escriptorul asociat flu.ului
0eclara%ie
int fileno(>Q?A 0flu:);
0escriere
Kunc%ia fileno e.amineaz argumentul flu: !i returneaz escriptorul
asociat e sistemul e operare acestui flu..
1@.%. Citire 7i scriere *r *ormat
)ume
f8ets - cite!te un !ir e caractere intr-un flu. te.t
0eclara%ie
char 0f8ets(char 0s, int si9e, >Q?A 0flu:);
0escriere
Kunc%ia f8ets cite!te cel mult si9e7& caractere in flu: !i le memoreaz
n zona inicat e s. Citirea se opre!te la etectarea sfr!itului e fi!ier sau ne:-
line. 0ac se cite!te caracterul ne:-line acesta este memorat n s. 0up ultimul
caracter se memoreaz null.
Apeluri ale acestei func%ii pot fi combinate cu orice apeluri ale altor func%ii e
intrare in bibliotec (fscanf$ e e.emplu, pentru un acela!i flu. e intrare.
Jalori returnate
Kunc%ia returneaz aresa s n caz e succes$ sau J@?? n caz e eroare sau la
ntlnirea sfr!itului e fi!ier ac nu s-a citit nici un caracter.
)ume
fputs - scrie un !ir e caractere ntr-un flu. te.t
0eclara%ie
int fputs(const char 0s, >Q?A 0flu:);
0escriere
Kunc%ia fputs scrie !irul s n flu. fr caracterul terminator null.
Apeluri ale acestei func%ii pot fi combinate cu orice apeluri ale altor func%ii e
ie!ire in bibliotec (fprintf$ e e.emplu, pentru un acela!i flu. e ie!ire.
33333333333333333333333333333333333333333333
444
Jalori returnate
Kunc%ia returneaz o &aloare non-negati& n caz e succes$ sau AW> n caz e
eroare.
)ume
fread$ fwrite - intrri > ie!iri pentru flu.uri binare
0eclara%ie
unsi8ned fread((oid 0ptr, unsi8ned si9e,
unsi8ned nel, >Q?A 0flu:);
unsi8ned fwrite(const (oid 0ptr, unsi8ned
si9e, unsi8ned nel, >Q?A 0flu:);
0escriere
Kunc%ia fread cite!te nel elemente$ fiecare a&n mrimea si9e octe%i$ in
flu.ul inicat e flu:$ !i le memoreaz n zona inicat e ptr.
Kunc%ia fwrite scrie nel elemente$ fiecare a&n mrimea si9e octe%i$ in
flu.ul inicat e flu:$ pe care le ia in zona inicat e ptr.
Jalori returnate
Kunc%iile returneaz numrul e elemente citite sau scrise cu succes (!i nu
numrul e caractere,. 0ac apare o eroare sau se ntlne!te sfr!itul e fi!ier$
&aloarea returnat este mai mic ect nel (posibil zero,.
1@./. Citire cu *ormat
)ume
scanf$ fscanf$ sscanf - citire cu format
0eclara%ie
int scanf(const char 0fmt, ...);
int fscanf(>Q?A 0flu:, const char 0fmt, ...);
int sscanf(char 0str, const char 0fmt, ...);
0escriere
Kunc%iile in familia ...scanf scaneaz intrarea n concoran% cu !irul e
caractere fmt up cum se escrie mai jos. Acest format poate con%ine
specificatori e con&ersie; rezultatele unor astfel e con&ersii (ac se efectueaz,
se memoreaz prin intermeiul argumentelor pointer. Kunc%ia scanf cite!te !irul
e intrare in flu.ul stanar stdin$ fscanf in flu:$ !i sscanf in !irul
inicat e str.
Kiecare argument pointer trebuie s corespun n orine ca tip cu fiecare
specificator e con&ersie (ar a se &eea suprimarea mai jos,. 0ac argumentele
33333333333333333333333333333333333333333333
44?
nu snt suficiente comportamentul programului este impre&izibil. 'oate
con&ersiile snt introuse e caracterul ". airul format poate con%ine !i alte
caractere. *pa%ii albe (blanc$ tab$ sau ne:-line, in !irul format se potri&esc cu
orice spa%iu alb n orice numr (inclusi& nici unul, in !irul e intrare. @rice alte
caractere trebuie s se potri&easc e.act. *canarea se opre!te atunci cn un
caracter in !irul e intrare nu se potri&e!te cu cel in format. *canarea se opre!te
e asemenea atunci cn o con&ersie nu se mai poate efectua (a se &eea mai jos,.
Con&ersii
0up caracterul " care introuce o con&ersie poate urma un numr e
caractere inicatori$ up cum urmeaz#
0 *uprim atribuirea. Con&ersia care urmeaz se face n mo obi!nuit$ ar nu se
folose!te nici un argument pointer; rezultatul con&ersiei este pur !i simplu
abanonat.
h Con&ersia este e tip d$ i$ o$ u$ : sau n !i argumentul asociat este un pointer
la short (n loc e int,.
l Con&ersia este e tip d$ i$ o$ u$ : sau n !i argumentul asociat este un pointer
la lon8 (n loc e int,$ sau con&ersia este e tip e$ f$ 8 !i argumentul
asociat este un pointer la dou'le (n loc e float,.
? Con&ersia este e tip e$ f$ 8 !i argumentul asociat este un pointer la lon8
dou'le.
=n completare la ace!ti inicatori poate e.ista o mrime w ma.im op%ional
pentru cmp$ e.primat ca un ntreg zecimal$ ntre caracterul " !i cel e con&ersie$
!i naintea inicatorului. 0ac nu este at o mrime ma.im se folose!te
mrimea implicit infinit (cu o e.cep%ie la con&ersia e tip c,; n caz contrar se
scaneaz cel mult un numr e w caractere n timpul con&ersiei. =nainte e a
ncepe o con&ersie$ majoritatea con&ersiilor ignor spa%iile albe; acestea nu snt
contorizate n mrimea cmpului.
*nt isponibile urmtoarele con&ersii#
" Potri&ire cu un caracter ". Cu alte cu&inte$ "" n !irul format trebuie s se
potri&easc cu un caracter ". )u se efectueaz nici o con&ersie !i nici o
atribuire.
d Potri&ire cu un ntreg zecimal (e&entual cu semn,; argumentul asociat trebuie
s fie un pointer la int.
i Potri&ire cu un ntreg (e&entual cu semn,; argumentul asociat trebuie s fie un
pointer la int. Jaloarea ntreag este citit n baza 4E ac ncepe cu 0: sau
33333333333333333333333333333333333333333333
44B
0<$ n baza C ac ncepe cu 0$ !i n baza 47 n caz contrar. *nt folosite
numai caracterele care corespun bazei respecti&e.
o Potri&ire cu un ntreg octal fr semn; argumentul asociat trebuie s fie un
pointer la unsi8ned.
u Potri&ire cu un ntreg zecimal fr semn; argumentul asociat trebuie s fie un
pointer la unsi8ned.
: Potri&ire cu un ntreg /e.azecimal fr semn; argumentul asociat trebuie s fie
un pointer la unsi8ned.
f Potri&ire cu un numr n &irgul mobil (e&entual cu semn,; argumentul
asociat trebuie s fie un pointer la float.
e$8 Gc/i&alent cu f.
s Potri&ire cu o sec&en% e caractere iferite e spa%iu alb; argumentul asociat
trebuie s fie un pointer la char$ !i zona trebuie s fie suficient e mare
pentru a putea primi toat sec&en%a !i caracterul terminator null. airul e
intrare se termin la un spa%iu alb sau la atingerea mrimii ma.ime a cmpului
(prima coni%ie ntlnit,.
c Potri&ire cu o sec&en% e caractere e mrime w (ac aceasta este
specificat; prin lips se ia w=4,; argumentul asociat trebuie s fie un pointer
la char$ !i zona trebuie s fie suficient e mare pentru a putea primi toat
sec&en%a (nu se aaug terminator null,. )u se ignor ca e obicei spa%iile albe
in fa%. Pentru a ignora mai nti spa%iile albe se inic un spa%iu e.plicit n
format.
) Potri&ire cu o sec&en% ne&i e caractere in setul specificat e caractere
acceptate; argumentul asociat trebuie s fie un pointer la char$ !i zona
trebuie s fie suficient e mare pentru a putea primi toat sec&en%a !i
caracterul terminator null. )u se ignor ca e obicei spa%iile albe in fa%.
airul e intrare &a fi format in caractere aflate n (sau care nu se afl n, setul
specificat n format; setul este efinit e caracterele aflate ntre ) !i *. *etul
e.clue acele caractere ac primul caracter up ) este L. Pentru a inclue
caracterul * n set$ acesta trebuie s fie primul caracter up ) sau L;
caracterul * aflat n orice alt pozi%ie nc/ie setul. Caracterul 7 are !i el un
rol special# plasat ntre ou alte caractere aaug toate celelalte caractere
aflate n inter&alul respecti& la set. Pentru a inclue caracterul 7 acesta trebuie
s fie ultimul caracter nainte e *. 0e e.emplu$ "")L*0747*" semnific
setul orice caracter cu excepia *$ 0 pn la 4$ i 7. airul se termin la
33333333333333333333333333333333333333333333
44D
apari%ia unui caracter care nu se afl (sau$ ac se precizeaz L$ care se afl, n
set sau ac se atinge mrimea ma.im specificat.
n )u se prelucreaz nimic in !irul e intrare; n sc/imb$ numrul e caractere
consumate pn la acest punct in !irul e intrare este memorat la argumentul
asociat$ care trebuie s fie un pointer la int.
Jalori returnate
Kunc%iile returneaz numrul e &alori atribuite$ care poate fi mai mic ect
numrul e argumente pointer$ sau c/iar zero$ n cazul n care apar nepotri&iri
ntre format !i !irul e intrare. Sero inic faptul c$ c/iar ac a&em un !ir e
intrare isponibil$ nu s-a efectuat nici o con&ersie (!i atribuire,; aceast situa%ie
apare atunci cn un caracter in !irul e intrare este in&ali$ cum ar fi un caracter
alfabetic pentru o con&ersie "d. Jaloarea AW> este returnat ac apare o eroare
nainte e prima con&ersie$ cum ar fi etectarea sfr!itului e fi!ier. 0ac o eroare
sau un sfr!it e fi!ier apare up ce o con&ersie a nceput$ se returneaz numrul
e con&ersii efectuate cu succes$ !i se pozi%ioneaz bitul corespunztor in
structura >Q?A$ care poate fi testat.
1@.1. 2criere cu *ormat
)ume
printf$ fprintf$ sprintf - scriere cu format
0eclara%ie
int printf(const char 0fmt, ...);
int fprintf(>Q?A 0flu:, const char 0fmt, ...);
int sprintf(char 0str, const char 0fmt, ...);
0escriere
Kunc%iile in familia ...printf genereaz o ie!ire n concoran% cu format up
cum se escrie mai jos. Kunc%ia printf afi!eaz ie!irea la flu.ul stanar
stdout; fprintf scrie ie!irea la flu:; sprintf scrie ie!irea n !irul e
caractere str.
Aceste func%ii genereaz ie!irea sub controlul !irului format care specific
cum se con&ertesc argumentele pentru ie!ire.
airul e formatare
airul fmt este un !ir e caractere$ printre care se pot afla zero sau mai multe
irecti&e# caractere obi!nuite (iferite e ", care snt copiate a!a cum snt n flu.ul
e ie!ire$ !i specifica%ii e con&ersie$ fiecare intre ele rezultn in ncrcarea a
zero sau mai multe argumente. Kiecare specifica%ie e con&ersie este introus e
caracterul " !i se termin cu un specificator e con&ersie. =ntre acestea pot fi (n
33333333333333333333333333333333333333333333
44A
aceast orine, zero sau mai mul%i inicatori$ o mrime minim a cmpului
op%ional$ o precizie op%ional !i un moificator op%ional e lungime.
Argumentele trebuie s corespun n orine ca tip cu specificatorii e
con&ersie. Acestea snt folosite n orinea at$ une fiecare caracter 0 !i fiecare
specificator e con&ersie solicit urmtorul argument. 0ac argumentele nu snt
suficiente comportamentul programului este impre&izibil.
Caractere inicatori
Caracterul " este urmat e zero$ unul sau mai mul%i inicatori#
0 Jaloarea numeric este con&ertit cu zerouri la stnga. Pentru con&ersii e tip
d$ i$ o$ u$ :$ <$ e$ A$ f$ >$ 8 !i Z$ &aloarea con&ertit este completat cu
zerouri la stnga n loc e blanc. 0ac apar inicatorii 0 !i 7 mpreun$
inicatorul 0 este ignorat. 0ac pentru o con&ersie numeric (d$ i$ o$ u$ :$ <,
este at o precizie$ inicatorul 0 este ignorat. Pentru alte con&ersii rezultatul
este neefinit.
7 Jaloarea con&ertit este aliniat la stnga (implicit alinierea se face la
reapta,. Cu e.cep%ia con&ersiilor e tip n$ &aloarea con&ertit este completat
la reapta cu blanc$ n loc s fie completat la stnga cu blanc sau zero. 0ac
apar inicatorii 0 !i 7 mpreun$ inicatorul 0 este ignorat.
)p (spa%iu, =n cazul unui rezultat al unei con&ersii cu semn$ naintea unui numr
poziti& sau !ir &i se pune un blanc.
$ *emnul ($ sau 7, este plasat naintea numrului generat e o con&ersie cu
semn. +mplicit semnul este folosit numai pentru numere negati&e. 0ac apar
inicatorii $ !i )p mpreun$ inicatorul )p este ignorat.
1%imea cmpului
"n !ir e cifre zecimale (cu prima cifr nenul, specific o l%ime minim
pentru cmp. 0ac &aloarea con&ertit are mai pu%ine caractere ect l%imea
specificat$ &a fi completat cu spa%ii la stnga (sau reapta$ ac s-a specificat
aliniere la stnga,. =n locul unui numr zecimal se poate folosi * pentru a specifica
faptul c l%imea cmpului este at e argumentul coresponent$ care trebuie s
fie e tip int. @ &aloare negati& pentru l%ime este consierat un inicator 7
urmat e o &aloare poziti& pentru l%ime. =n nici un caz nu se &a trunc/ia cmpul;
ac rezultatul con&ersiei este mai mare ect l%imea cmpului$ cmpul este
e.panat pentru a con%ine rezultatul con&ersiei.
Precizia
Precizia (op%ional, este at e caracterul . urmat e un !ir e cifre zecimale.
=n locul !irului e cifre zecimale se poate scrie 0 pentru a specifica faptul c
precizia este at e argumentul coresponent$ care trebuie s fie e tip int.
33333333333333333333333333333333333333333333
44E
0ac precizia este at oar e caracterul . sau ac precizia este negati&$ atunci
aceasta se consier zero. Precizia numrul minim e cifre care apar pentru
con&ersii e tip d$ i$ o$ u$ :$ <$ numrul e cifre care apar up punctul zecimal
pentru con&ersii e tip e$ A$ f$ >$ numrul ma.im e cifre semnificati&e pentru
con&ersii e tip 8 !i Z$ sau numrul ma.im e caractere generate pentru con&ersii
e tip s.
0ac se folose!te 0 pentru l%ime sau precizie (sau ambele,$ argumentele se
iau n orine# l%ime$ precizie$ &aloare e scris.
-oificator e lungime
=n acest caz prin con&ersie ntreag n%elegem con&ersie e tip d$ i$ o$ u$ :$ <.
h Con&ersia ntreag care urmeaz corespune unui argument short sau
unsi8ned short$ sau urmtoarea con&ersie e tip n corespune unui
argument e tip pointer la short.
l Con&ersia care urmeaz corespune unui argument e tip#
< lon8 sau unsi8ned lon8$ ac este o con&ersie e tip d$ i$ o$ u$ :$ <
sau n;
< dou'le$ ac este o con&ersie e tip f.
? "rmtoarea con&ersie e tip e$ A$ f$ >$ 8$ Z corespune unui argument lon8
dou'le.
*pecificator e con&ersie
"n caracter care specific tipul con&ersiei care se &a face. *pecificatorii e
con&ersie !i semnifica%ia lor snt#
d$i
Argumentul e tip int este con&ertit la nota%ia zecimal cu semn. Precizia$
ac este at$ numrul minim e cifre care trebuie s apar; ac &aloarea
con&ertit necesit mai pu%ine cifre$ aceasta este completat la stnga cu
zerouri. Precizia implicit este 4. 0ac &aloarea 7 este afi!at cu precizie
e.plicit 7$ ie!irea este &i.
o$u$:$<
Argumentul e tip unsi8ned este con&ertit la nota%ie octal fr semn (o,$
zecimal fr semn (u,$ sau /e.azecimal fr semn (: !i <,. 1iterele
a'cdef se folosesc pentru con&ersii e tip :$ literele =DEFA> pentru
con&ersii e tip <. Precizia$ ac este at$ numrul minim e cifre care
trebuie s apar; ac &aloarea con&ertit necesit mai pu%ine cifre$ aceasta
este completat la stnga cu zerouri. Precizia implicit este 4. 0ac &aloarea 7
este afi!at cu precizie e.plicit 7$ ie!irea este &i.
33333333333333333333333333333333333333333333
446
e$A
Argumentul e tip flotant este rotunjit !i con&ertit n stil I7\d.dddeGdd
une a&em o cifr nainte e punctul zecimal !i numrul e cifre up acesta
este egal cu precizia; ac aceasta lipse!te se consier E; ac precizia este
zero$ punctul zecimal nu apare. @ con&ersie e tip A folose!te litera A (n loc
e e, pentru a introuce e.ponentul. G.ponentul are ntoteauna cel pu%in
ou cifre; ac &aloarea este zero$ e.ponentul este 00.
f$>
Argumentul e tip flotant este rotunjit !i con&ertit n nota%ie zecimal n stil
I7\ddd.ddd$ une numrul e cifre up punctul zecimal este egal cu precizia
specificat. 0ac precizia lipse!te se consier E; ac precizia este e.plicit
zero$ punctul zecimal nu apare. 0ac punctul zecimal apare$ cel pu%in o cifr
apare naintea acestuia.
8$Z
Argumentul e tip flotant este con&ertit n stil f sau e (sau A pentru con&ersii
e tip Z,. Precizia specific numrul e cifre semnificati&e. 0ac precizia
lipse!te se consier E; ac precizia este zero se consier 4. *tilul e este
folosit ac e.ponentul rezultat n urma con&ersiei este mai mic ect D ori
mai mare sau egal cu precizia. Serourile finale snt eliminate in partea
frac%ionar a rezultatului; punctul zecimal apare numai ac este urmat e cel
pu%in o cifr.
c Argumentul e tip int este con&ertit la unsi8ned char !i se scrie
caracterul rezultat.
s Argumentul e tip const char 0 este un pointer la un !ir e caractere.
Caracterele in !ir snt scrise pn la (fr a inclue, caracterul terminator
null; ac precizia este specificat$ nu se scrie un numr mai mare ect cel
specificat. 0ac precizia este at$ nu e ne&oie e caracterul null; ac
precizia nu este specificat$ !irul trebuie s con%in un caracter terminator null.
p Argumentul e tip pointer este scris n /e.azecimal; formatul este specific
sistemului e calcul.
n )umrul e caractere scrise pn n acest moment este memorat la argumentul
e tip int 0. )u se face nici o con&ersie.
" *e scrie un caracter ". )u se face nici o con&ersie. *pecifica%ia complet este
"".
Jaloare returnat
33333333333333333333333333333333333333333333
44C
Kunc%iile returneaz numrul e caractere generate (nu se inclue caracterul
terminator null pentru sprintf,.
1@.;. 4ratarea erorilor
)ume
perror - afi!eaz un mesaj e eroare sistem
0eclara%ie
(oid perror(const char 0s);
#include <errno.h>
const char 0s;sUerrlist)*;
int s;sUnerr;
0escriere
Rutina perror afi!eaz un mesaj la ie!irea stanar e eroare$ care escrie
ultima eroare ntlnit la ultimul apel sistem sau func%ie e bibliotec. -ai nti se
afi!eaz argumentul s$ apoi &irgula !i blanc$ !i n final mesajul e eroare !i ne:-
line. *e recoman (mai ales pentru epanare, ca argumentul s s inclu numele
func%iei n care a aprut eroarea. Coul erorii se ia in &ariabila e.tern errno.
1ista global e erori s;sUerrlist)* ine.at cu errno poate fi folosit
pentru a ob%ine mesajul e eroare fr ne:-line. "ltimul inice e mesaj in list
este s;sUnerr7&. *e recoman o aten%ie eosebit n cazul accesului irect la
list eoarece unele couri noi e eroare pot lipsi in s;sUerrlist)*.
0ac un apel sistem e!ueaz &ariabila errno inic coul erorii. Aceste
&alori pot fi gsite n <errno.h>. Kunc%ia perror ser&e!te la afi!area acestui
co e eroare ntr-o form lizibil. 0ac un apel terminat cu eroare nu este imeiat
urmat e un apel perror$ &aloarea &ariabilei errno se poate piere ac nu e
sal&at.
)ume
clearerr$ feof$ ferror - &erific !i reseteaz starea
flu.ului
0eclara%ie
(oid clearerr(>Q?A 0flu:);
int feof(>Q?A 0flu:);
int ferror(>Q?A 0flu:);
0escriere
Kunc%ia clearerr !terge inicatorii e sfr!it e fi!ier !i eroare ai flu.ului.
33333333333333333333333333333333333333333333
44F
Kunc%ia feof testeaz inicatorul e sfr!it e fi!ier al flu.ului$ !i returneaz
non-zero ac este setat. Acesta este setat ac o opera%ie e citire a etectat
sfr!itul e fi!ier.
Kunc%ia ferror testeaz inicatorul e eroare al flu.ului$ !i returneaz non-
zero ac este setat. Acesta este setat ac o opera%ie e citire sau scriere a
etectat o eroare (atorat e e.emplu /ar:are-ului,.
Kunc%iile e citire (cu sau fr format, nu fac istinc%ie ntre sfr!it e fi!ier !i
eroare$ astfel c trebuie apelate func%iile feof !i ferror pentru a etermina
cauza terminrii.
AtenieH Gste foarte frec&ent folosirea incorect a func%iei feof pentru a
testa ac s-a ajuns la sfr!itul fi!ierului. )u se recoman n nici un caz acest stil
e programare#
#define ?MQX 50
char lin)?MQX*;
>Q?A 0fi,0fo;
fi!fopen(nume-fiier-intrare,"rt");
fo!fopen(nume-fiier-ieire,"wt");
while (%feof(fi)) { DE 're7itH ED
f8ets(lin,?MQX,fi);
fputs(lin,fo);

fclose(fi); fclose(fo);
=n aceast sec&en%$ ac !i ultima linie a fi!ierului te.t e intrare este
terminat cu ne:-line$ aceasta &a fi scris e ou ori n fi!ierul e ie!ire. 0e ceZ
0up ce se cite!te ultima linie nc nu este pozi%ionat inicatorul e sfr!it e
fi!ier$ eci func%ia f8ets nc returneaz succes. 1a reluarea ciclului se ncearc
un nou f8ets !i abia acum se episteaz sfr!itul e fi!ier$ fapt marcat n zona
rezer&at flu.ului fi. Astfel con%inutul !irului lin rmne nemoificat !i este
scris a oua oar n fi!ierul e ie!ire. Abia la o nou reluare a ciclului func%ia
feof ne spune c s-a epistat sfr!itul e fi!ier.
=n acest manual snt prezentate mai multe programe care efectueaz iferite
prelucrri asupra unor fi!iere te.t. Pentru simplitate toate programele presupun c
nu apar erori la citire sau la scriere.
1@.<. 0peraii cu directoare
Kunc%iile e parcurgere a cataloagelor e fi!iere escrise n aceast sec%iune
(opendir$ readdir$ closedir, snt efinite e mai multe meii e
programare C (printre care !i N)" C pentru sistemul e operare 1inu.,$ precum
!i e stanarul P@*+Q. Aceste func%ii snt eclarate n <dirent.h>.
33333333333333333333333333333333333333333333
4?7
Kunc%iile e reenumire !i !tergere a unor fi!iere snt escrise n
<stdio.h>.
)ume
opendir - esc/ie un irector
0eclara%ie
FQX 0opendir(const char 0nume);
0escriere
Kunc%ia opendir esc/ie un flu. pentru irectorul cu numele nume$ !i
returneaz un pointer la flu.ul esc/is. Klu.ul este pozi%ionat pe prima intrare in
irector.
Jaloare returnat
Kunc%ia returneaz un pointer la flu. n caz e succes$ sau )"11 n caz e
eroare !i &ariabila global errno inic coul erorii.
Cte&a erori posibile
A=EEAM Acces interzis
AJWRFQX nume nu este un irector
)ume
readdir - cite!te intr-un irector
0eclara%ie
struct dirent 0readdir(FQX 0dir);
0escriere
Kunc%ia readdir returneaz un pointer la o structur e tip dirent care
reprezint urmtoarea intrare in irectorul inicat e flu.ul dir. Returneaz
)"11 ac s-a epistat sfr!itul e irector sau ac a aprut o eroare.
*tructura e tip dirent con%ine un cmp char dUname)*. "tilizarea altor
cmpuri in structur reuce portabilitatea programelor.
Jaloare returnat
Kunc%ia returneaz un pointer la o structur e tip dirent$ sau )"11 ac s-
a epistat sfr!itul e irector sau ac a aprut o eroare.
)ume
closedir - nc/ie un irector
0eclara%ie
int closedir(FQX 0dir);
33333333333333333333333333333333333333333333
4?4
0escriere
Kunc%ia closedir nc/ie flu.ul dir.
Jaloare returnat
Kunc%ia returneaz 0 n caz e succes sau AW> n caz e eroare.
)ume
rename - reenume!te un fi!ier
remo(e - !terge un fi!ier
0eclara%ie
int rename(const char 0old, const char 0new);
int remo(e(const char 0name);
0escriere
Kunc%ia rename sc/imb numele unui fi!ier in old n new. 0ac a fost
precizat un periferic n new$ acesta trebuie s coinci cu cel in old.
0irectoarele in old !i new pot s fie iferite$ astfel c rename poate fi folosit
pentru a muta un fi!ier intr-un irector n altul. )u se permit specificatori
generici (:ilcars,.
Kunc%ia remo(e !terge fi!ierul specificat prin name.
Jaloare returnat
=n caz e succes se returneaz 0. =n caz e eroare se returneaz AW> !i
&ariabila global errno inic coul erorii.
1@.>. &ro'rame demonstrati#e
Primele trei programe primesc ca parametri n linia e coman numele
fi!ierelor pe care le &or prelucra. "ltimul program prime!te ca parametru n linia
e coman numele irectorului al crui con%inut &a fi afi!at.
4, 0eterminarea mrimii unui fi!ier
#include <stdio.h>
>Q?A 0f;
int main(int ac, char 00a() {
if (ac%!.) {
fputs("@n ar8ument%\n",stderr);
return &;

f ! fopen(a()&*,"r'");
if (%f) {
perror("Aroare la deschidere");
return &;
33333333333333333333333333333333333333333333
4??

fsee-(f,0,MAANUAJF);
fprintf(stderr,">ile "s, si9e "ld\n",ftell(f));
fclose(f);
return 0;

?, Copierea unui fi!ier


Kunc%iile f8ets !i fputs se folosesc pentru flu.uri esc/ise n mo te.t.
Cum se utilizeaz pentru copierea unui fi!ier te.tZ
#include <stdio.h>
#define ?MQX 50
char lin)?MQX*;
>Q?A 0fi, 0fo;
int main(int ac, char 00a() {
if (ac%!,) {
fputs("Foua ar8umente%\n",stderr);

fi!fopen(a()&*,"rt"); fo!fopen(a().*,"wt");
if (%fi II %fo) {
perror("Aroare la deschidere");
return &;

while (f8ets(lin,?MQX,fi))
fputs(lin,fo);
fclose(fi); fclose(fo);
return 0;

Kunc%iile fread !i fwrite se folosesc pentru flu.uri esc/ise n mo binar.


Cum se utilizeaz pentru copierea unui fi!ier binarZ
#include <stdio.h>
#define ?TWJ /041
char 9on)?TWJ*;
>Q?A 0fi, 0fo;
unsi8ned -;
int main(int ac, char 00a() {
if (ac%!,) {
fputs("Foua ar8umente%\n",stderr);
return &;

fi!fopen(a()&*,"r'"); fo!fopen(a().*,"w'");
if (%fi II %fo) {
perror("Aroare la deschidere");
return &;
33333333333333333333333333333333333333333333
4?B

while (-!fread(9on,&,?TWJ,fi))
fwrite(9on,&,-,fo);
fclose(fi); fclose(fo);
return 0;

B, Prelucrarea unui fi!ier te.t


Programul prezentat n continuare cite!te un fi!ier te.t care con%ine pe fiecare
linie un !ir e caractere (fr spa%ii, !i trei &alori ntregi$ !i afi!eaz pe terminal
numele pe 4? pozi%ii aliniat la stnga !i meia aritmetic a celor trei &alori ntregi.
#include <stdio.h>
>Q?A 0fi;
char num)&0*;
int a,',c;
dou'le m;
int main(int ac, char 00a() {
if (ac%!.) {
fputs("@n ar8ument%\n",stderr);
return &;

fi!fopen(a()&*,"rt");
if (%fi) {
perror("Aroare la deschidere");
return &;

while (fscanf(fi,""s "d "d "d",num,#a,#',#c)%!AW>)
{
m!(a$'$c)+,.0;
printf(""7&.s"1..lf\n",num,m);

fclose(fi);
return 0;

D, Afi!area con%inutului unui irector


#include <dirent.h>
#include <stdio.h>
FQX 0dir;
struct dirent 0ent;
int main(int ac, char 00a() {
if (ac%!.) {
printf("@n parametru\n");
return &;

33333333333333333333333333333333333333333333
4?D
dir ! opendir(a()&*);
if (%dir) {
perror("Aroare open dir");
return &;

while (ent!readdir(dir))
printf(""s\n",ent7>dUname);
return 0;

33333333333333333333333333333333333333333333
4?A
11. Alte rutine din biblioteca standard
=n acest capitol snt escrise func%ii care rezol& probleme legate e alocarea
inamic a memoriei$ sortare !i cutare$ clasificare$ opera%ii cu blocuri e
memorie !i !iruri e caractere$ func%ii matematice.
11.1. Alocarea dinamic a memoriei
)ume
calloc$ malloc$ realloc - aloc memoria n mo inamic
free - elibereaz memoria alocat n mo inamic
0eclara%ie
#include <stdli'.h>
(oid 0calloc(unsi8ned nel, unsi8ned si9e);
(oid 0malloc(unsi8ned si9e);
(oid 0realloc((oid 0ptr, unsi8ned si9e);
(oid free((oid 0ptr);
0escriere
Kunc%ia calloc aloc memorie pentru un masi& e nel elemente$ fiecare e
mrime si9e octe%i !i returneaz un pointer la memoria alocat. Con%inutul
memoriei este pus la zero.
Kunc%ia malloc aloc si9e octe%i !i returneaz un pointer la memoria
alocat. Con%inutul memoriei nu este !ters.
Kunc%ia free elibereaz spa%iul e memorie inicat e ptr$ care trebuie s fi
fost returnat e un apel anterior malloc$ calloc sau realloc. =n caz contrar$
sau ac a e.istat eja un apel anterior free(ptr)$ comportamentul
programului este impre&izibil.
Kunc%ia realloc moific mrimea blocului e memorie inicat e ptr la
si9e octe%i. Con%inutul rmne nesc/imbat la mrimea minim intre mrimea
&ec/e !i cea nou; noul spa%iu e memorie care este e&entual alocat este
neini%ializat. 0ac ptr este J@?? apelul este ec/i&alent cu malloc(si9e);
ac si9e este egal cu zero apelul este ec/i&alent cu free(ptr). Cu e.cep%ia
cazului cn ptr este J@??$ acesta trebuie s fi fost returnat e un apel preceent
malloc$ calloc sau realloc.
Jalori returnate
Pentru calloc !i malloc &aloarea returnat este un pointer la memoria
alocat$ aliniat n mo corespunztor pentru orice tip e &ariabile$ sau J@?? ac
nu e.ist suficient memorie continu.
33333333333333333333333333333333333333333333
4?E
Kunc%ia free nu returneaz nimic.
Kunc%ia realloc returneaz un pointer la noua zon e memorie alocat$
aliniat n mo corespunztor pentru orice tip e &ariabile. Jaloarea acestuia
poate fi iferit e ptr$ poate fi J@?? ac nu e.ist suficient memorie
continu sau ac &aloarea si9e este egal cu 0. 0ac realloc e!ueaz$ blocul
original rmne neatins < nu este nici eliberat nici mutat.
11.. 2ortare 7i cutare
)ume
Gsort - sorteaz un masi&
'search - cutare binar ntr-un masi& sortat
0eclara%ie
#include <stdli'.h>
(oid Gsort((oid 0'ase, unsi8ned nel,
unsi8ned si9e, int (0comp)
(const (oid 0, const (oid 0));
(oid 0'search(const (oid 0-e;, const (oid
0'ase, unsi8ned nel, unsi8ned si9e, int
(0comp)(const (oid 0, const (oid 0));
0escriere
Kunc%ia Gsort sorteaz un masi& e nel elemente$ fiecare e mrime si9e.
Argumentul 'ase inic spre nceputul masi&ului.
Glementele masi&ului snt sortate n orine cresctoare n concoran% cu
func%ia e comparare referit e comp$ apelat cu ou argumente care inic
spre obiectele ce se compar. Kunc%ia e comparare trebuie s returneze un ntreg
mai mic ect$ egal cu$ sau mai mare ect zero ac primul argument este
consierat a fi mai mic ect$ egal cu$ respecti& mai mare ect al oilea. 0ac cele
ou elemente comparate snt egale$ orinea n masi&ul sortat este neefinit.
Kunc%ia 'search caut ntr-un masi& e nel elemente$ fiecare e mrime
si9e$ un membru care coincie cu obiectul inicat e -e;. Argumentul 'ase
inic spre nceputul masi&ului.
Con%inutul masi&ului trebuie s fie sortat cresctor n concoran% cu func%ia
e comparare referit e comp$ apelat cu ou argumente care inic spre
obiectele ce se compar. Kunc%ia e comparare se efine!te ca n cazul Gsort.
Primul argument este aresa c/eii$ al oilea este aresa unui element in masi&.
Jaloare returnat
Kunc%ia 'search returneaz un pointer la un membru al masi&ului care
coincie cu obiectul inicat e -e;$ sau J@?? ac nu se gse!te nici un
33333333333333333333333333333333333333333333
4?6
membru. 0ac e.ist mai multe elemente care coinci cu -e;$ poate fi returnat
oricare element cu aceast proprietate.
11.%. !utine de clasi*icare
)ume
isalnum$ isalpha$ isascii$ iscntrl$ isdi8it$
is8raph$ islower$ isprint$ ispunct$ isspace$
isupper$ is:di8it - rutine e clasificare
tolower - con&ersie n liter mic
toupper - con&ersie n liter mare
0eclara%ie
#include <ct;pe.h>
int isalnum(int c);
int isalpha(int c);
int isascii(int c);
int iscntrl(int c);
int isdi8it(int c);
int is8raph(int c);
int islower(int c);
int isprint(int c);
int ispunct(int c);
int isspace(int c);
int isupper(int c);
int is:di8it(int c);
int toupper(int c);
int tolower(int c);
0escriere
Primele 4? func%ii &erific ac c$ care trebuie s fie o &aloare e tip
unsi8ned char sau AW>$ se afl n una in clasele e caractere enumerate mai
sus.
isalnum
Jerific ac c este alfanumeric (liter sau cifr,.
isalpha
Jerific ac c este alfabetic (liter mare sau mic,.
isascii
Jerific ac c este o &aloare pe 6 bi%i in setul e caractere A*C++.
iscntrl
33333333333333333333333333333333333333333333
4?C
Jerific ac c este un caracter e control.
isdi8it
Jerific ac c este o cifr (ntre 7 !i F,.
is8raph
Jerific ac c este un caracter afi!abil cu e.cep%ia spa%iului.
islower
Jerific ac c este o liter mic.
isprint
Jerific ac c este un caracter afi!abil inclusi& spa%iu.
ispunct
Jerific ac c este un caracter iferit e spa%iu !i non-alfanumeric.
isspace
Jerific ac c este un spa%iu alb.
isupper
Jerific ac c este o liter mare.
is:di8it
Jerific ac c este o cifr /e.azecimal in setul#
7 4 ? B D A E 6 C F a b c e f A B C 0 G K
tolower
Con&erte!te caracterul c$ ac este o liter$ la litera mic corespunztoare.
toupper
Con&erte!te caracterul c$ ac este o liter$ la litera mare corespunztoare.
Jaloare returnat
Jaloarea returnat e func%iile is... este nenul ac caracterul c se afl n
clasa testat$ !i zero n caz contrar.
Jaloarea returnat e func%iile to... este litera con&ertit ac caracterul c este
o liter$ !i neefinit n caz contrar.
11./. 0peraii cu blocuri de memorie
Pentru majoritatea func%iilor in aceast categorie compilatorul e.paneaz
coul acestora folosin instruc%iuni pe !iruri e caractere. Aceste func%ii snt
eclarate n <strin8.h>
)ume
33333333333333333333333333333333333333333333
4?F
memcp; - copiaz o zon e memorie
0eclara%ie
(oid 0memcp;((oid 0dest, const (oid 0src,
unsi8ned n);
(oid 0memmo(e((oid 0dest, const (oid 0src,
unsi8ned n);
0escriere
Kunc%ia memcp; copiaz n octe%i in zona e memorie src n zona e
memorie dest. Sonele e memorie nu trebuie s se suprapun. 0ac e.ist acest
risc se utilizeaz memmo(e.
Jaloare returnat
Kunc%iile returneaz un pointer la dest.
)ume
memcmp - compar ou zone e memorie
0eclara%ie
int memcmp(const (oid 0s&, const (oid 0s.,
unsi8ned n);
0escriere
Kunc%ia memcmp compar primii n octe%i ai zonelor e memorie s& !i s..
Jaloare returnat
Returneaz un ntreg mai mic ect$ egal cu$ sau mai mare ect zero ac s&
este mai mic ect$ coincie$ respecti& este mai mare ect s..
)ume
memset - umple o zon e memorie cu o constant pe un octet
0eclara%ie
(oid 0memset((oid 0s, int c, unsi8ned n);
0escriere
Kunc%ia memset umple primii n octe%i ai zonei e memorie inicat e s cu
constanta c pe un octet.
Jaloare returnat
Kunc%ia returneaz un pointer la zona e memorie s.
)ume
memchr - caut n memorie un caracter
33333333333333333333333333333333333333333333
4B7
0eclara%ie
(oid 0memchr(const (oid 0s, int c, unsi8ned n);
0escriere
Kunc%ia memchr caut caracterul c n primii n octe%i e memorie inica%i e
s. Cutarea se opre!te la primul octet care are &aloarea c (interpretat ca
unsi8ned char,.
Jaloare returnat
Kunc%ia returneaz un pointer la octetul gsit sau )"11 ac &aloarea nu
e.ist n zona e memorie.
11.1. 0peraii cu 7iruri de caractere
Pentru majoritatea func%iilor in aceast categorie compilatorul e.paneaz
coul acestora folosin instruc%iuni pe !iruri e caractere. Aceste func%ii snt
eclarate n <strin8.h>
)ume
strlen - calculeaz lungimea unui !ir
0eclara%ie
unsi8ned strlen(const char 0s);
0escriere
Kunc%ia strlen calculeaz lungimea !irului s$ fr a inclue caracterul
terminator null.
Jaloare returnat
Kunc%ia returneaz numrul e caractere in s.
)ume
strcp;$ strncp; - copiaz un !ir e caractere
0eclara%ie
char 0strcp;(char 0dest, const char 0src);
char 0strncp;(char 0dest, const char 0src,
unsi8ned n);
0escriere
Kunc%ia strcp; copiaz !irul inicat e src (inclusi& caracterul terminator
null, n zona inicat e dest. airurile nu trebuie s se suprapun$ !i n plus zona
dest trebuie s fie suficient e mare pentru a primi copia.
33333333333333333333333333333333333333333333
4B4
Kunc%ia strncp; este similar$ cu e.cep%ia faptului c nu se copiaz mai
mult e n octe%i in src. Astfel$ ac caracterul terminator null nu se afl n
primii n octe%i in src$ rezultatul nu &a fi terminat cu null. =n cazul n care
lungimea lui src este mai mic ect n$ restul octe%ilor in dest primesc
&aloarea null.
Jaloare returnat
Kunc%iile returneaz un pointer la !irul dest.
)ume
strdup - uplic un !ir
0eclara%ie
char 0strdup(const char 0s);
0escriere
Kunc%ia strdup returneaz un pointer la un nou !ir care este un uplicat al
!irului s. -emoria pentru noul !ir se ob%ine cu malloc$ !i poate fi eliberat cu
free.
Jaloare returnat
Kunc%ia returneaz un pointer la !irul uplicat$ sau )"11 ac nu e.ist
memorie suficient isponibil.
)ume
strcat$ strncat - concateneaz ou !iruri
0eclara%ie
char 0strcat(char 0dest, const char 0src);
char 0strncat(char 0dest, const char 0src,
unsi8ned n);
0escriere
Kunc%ia strcat aaug !irul src la !irul dest suprascriin caracterul null
e la sfr!itul lui dest$ !i la sfr!it aaug un caracter terminator null. airurile nu
trebuie s se suprapun$ !i n plus !irul dest trebuie s aib suficient spa%iu
pentru a pstra rezultatul.
Kunc%ia strncat este similar$ cu e.cep%ia faptului c numai primele n
caractere in src se aaug la dest.
Jaloare returnat
Kunc%iile returneaz un pointer la !irul rezultat dest.
33333333333333333333333333333333333333333333
4B?
)ume
strcmp - compar ou !iruri e caractere
0eclara%ie
int strcmp(const char 0s&, const char 0s.);
0escriere
Kunc%ia strcmp compar cele ou !iruri s& !i s..
Jaloare returnat
Kunc%ia returneaz un ntreg mai mic ect$ egal cu$ sau mai mare ect zero
ac s& este mai mic ect$ coincie$ respecti& este mai mare ect s..
)ume
strchr$ strrchr - localizeaz un caracter
0eclara%ie
char 0strchr(const char 0s, int c);
char 0strrchr(const char 0s, int c);
0escriere
Kunc%ia strchr returneaz un pointer la prima apari%ie a caracterului c n
!irul s.
Kunc%ia strrchr returneaz un pointer la ultima apari%ie a caracterului c n
!irul s.
Jaloare returnat
Kunc%iile returneaz un pointer la caracterul gsit sau )"11 ac &aloarea nu
a fost gsit.
)ume
strstr - localizeaz un sub!ir
0eclara%ie
char 0strstr(const char 0sir, const char 0su's);
0escriere
Kunc%ia strstr gse!te prima apari%ie a sub!irului su's n !irul sir.
Caracterul terminator null nu este luat n consierare.
Jaloare returnat
Kunc%ia returneaz un pointer la nceputul sub!irului$ sau )"11 ac sub!irul
nu este gsit.
33333333333333333333333333333333333333333333
4BB
)ume
strspn$ strcspn - caut un set e caractere ntr-un !ir
0eclara%ie
unsi8ned strspn(const char 0s, const char 0acc);
unsi8ned strcspn(const char 0s, const char 0reH);
0escriere
Kunc%ia strspn etermin lungimea segmentului ini%ial in s format n
ntregime numai cu caractere in acc.
Kunc%ia strcspn etermin lungimea segmentului ini%ial in s format n
ntregime numai cu caractere care nu se gsesc n reH.
Jalori returnate
Kunc%ia strspn returneaz pozi%ia primului caracter in s care nu se afl n
acc.
Kunc%ia strcspn returneaz pozi%ia primului caracter in s care se afl n
reH.
11.;. Biblioteca matematic
4, Kunc%iile in prima categorie snt eclarate n <stdli'.h>
)ume
rand$ srand - generarea numerelor pseuo-aleatoare
0eclara%ie
int rand((oid);
(oid srand(unsi8ned int seed);
0escriere
Kunc%ia rand returneaz un ntreg pseuo-aleator ntre 0 !i X=JFUC=<
(pentru majoritatea meiilor e programare C aceast constant este egal cu
&aloarea ma.im cu semn reprezentabil pe un cu&nt al sistemului e calcul,.
Kunc%ia srand ini%ializeaz generatorul cu &aloarea seed pentru o nou
sec&en% e &alori ntregi pseuo-aleatoare care &or fi returnate e rand. Aceste
sec&en%e se repet ac srand se apeleaz cu aceea!i &aloare seed.
*e obi!nuie!te ca generatorul s fie ini%ializat cu o &aloare at e ceasul
sistemului e calcul$ ca n e.emplul e mai jos#
#include <time.h>
srand(time(J@??));
Jaloare returnat
Kunc%ia rand returneaz o &aloare ntre 0 !i X=JFUC=<.
33333333333333333333333333333333333333333333
4BD
@bser&a%ie
=n lucrarea 2umerical 3ecipes in C4 The *rt of )cientific Computing -
8illiam O Press$ Brian P Klanner2$ *aul A 'euLolsL2$ 8illiam ' Jetterling >
)e: RorL# Cambrige "ni&ersit2 Press$ 4FF7 (4st e$ p ?76,$ se face urmtorul
comentariu#
Dac dorii s generai o valoare aleatoare ntreag ntre . i .5, se
recomand s folosii secvena
H!&$(int)(&0.00rand()+(X=JFUC=<$&.0));
i nu o secven de tipul
H!&$(int)(&000000.00rand())"&0;
care folosete biii de rang inferior.
'ot n fi!ierul <stdli'.h> snt escrise !i urmtoarele func%ii#
int a's(int i); &aloare absolut
lon8 la's(lon8 i); &aloare absolut
int atoi(char 0s); con&ersie in A*C++ n ntreg
lon8 atol(char 0s); con&ersie in A*C++ n ntreg lung
dou'le atof(char 0s); con&ersie in A*C++ n ubl precizie
"rmtoarele func%ii e con&ersie necesit o iscu%ie etaliat#
dou'le strtod(char 0str, char 00end);
con&ersie in A*C++ n ubl precizie
lon8 strtol(char 0str, char 00end, int 'ase);
con&ersie in A*C++ n ntreg lung
unsi8ned lon8 strtoul(char 0str, char 00end, int 'ase);
con&ersie in A*C++ n ntreg lung fr semn
airul e caractere str este con&ertit n reprezentare binar$ ca !i n cazul
func%iilor atoi$ atol$ atof. Pentru con&ersii e tip ntreg se precizeaz !i baza
e numera%ie folosit$ care poate fi ntre ? !i BE. Pentru baze mai mari ect zece
se folosesc litere mici sau mari. =n plus$ ac parametrul end inic o ares
&ali (nu este null,$ la ie!ire prime!te aresa primului caracter in&ali in str$
care nu respect regulile e scriere a unei &alori numerice e tipul a!teptat.
?, Kunc%iile in a oua categorie snt eclarate n <math.h>
dou'le fa's(dou'le :); &aloare absolut
dou'le floor(dou'le :); parte ntreag inferioar
dou'le ceil(dou'le :); parte ntreag superioar
dou'le sGrt(dou'le :);
x
dou'le sin(dou'le :); sin(x,
dou'le cos(dou'le :); cos(x,
dou'le tan(dou'le :); tg(x,
33333333333333333333333333333333333333333333
4BA
dou'le asin(dou'le :); arcsin(x,
dou'le acos(dou'le :); arccos(x,
dou'le atan(dou'le :); arctg(x, n I-/?$/?\
dou'le atan.(dou'le ;, dou'le :);
arctg(y'x, n I<$\
dou'le e:p(dou'le :); e
x
dou'le lo8(dou'le :); ln(x,
dou'le pow(dou'le :, dou'le ;); x
y
dou'le sinh(dou'le :); sin/(x,
dou'le cosh(dou'le :); cos/(x,
dou'le tanh(dou'le :); tg/(x,
dou'le lde:p(dou'le :, int e); x ?
e
dou'le fmod(dou'le :, dou'le ;); x moulo y
Kunc%ia fmod returneaz o &aloare f efinit astfel# x = a y + f
a este o &aloare ntreag (at e x/y, !i 7 _f _ d y; f are semnul lui x.
"rmtoarele ou func%ii returneaz ou &alori# una este &aloarea returnat
e func%ie (e tip dou'le,$ !i cealalt returnat prin intermeiul unui argument
e tip pointer la int respecti& dou'le.
dou'le fre:p(dou'le :, int 0e);
Kunc%ia fre:p esparte &aloarea x n ou pr%i# o parte frac%ionar normalizat
(f I7.A$4,, !i un e.ponent e. 0ac x este 7 atunci f=7 !i e=7. Jaloarea returnat
este f.
dou'le modf(dou'le :, dou'le 0n);
Kunc%ia modf esparte &aloarea x n ou pr%i# o parte frac%ionar subunitar f !i
o parte ntreag n. Jalorile f !i n au acela!i semn ca !i x. Jaloarea returnat este f.
11.<. Auncii pentru timp 7i dat calendaristic
Kunc%iile in aceast categorie$ mpreun cu tipurile !i structurile e ate
folosite$ snt eclarate n <time.h>
Auncia time
0ata !i ora calenaristic se reprezint n format compact printr-o &aloare e
tip timeUt. -ajoritatea meiilor e programare efinesc acest tip ca un sinonim
pentru unsi8ned lon8. Aceast &aloare se ob%ine prin apelul func%iei time.
timeUt time(timeUt 0tims);
33333333333333333333333333333333333333333333
4BE
Kunc%ia returneaz ata !i ora curent n cooronate uni&ersale ("'C,$ care
reprezint numrul e secune e la nceputul erei "ni. (4 ianuarie 4F67$ ora
7#77#77,.
Jaloarea returnat este memorat la aresa inicat e argumentul tims$
ac acesta nu este )"11. 0ac argumentul tims este )"11$ trebuie s
memorm &aloarea returnat.
2tructura tm 5dat calendaristic de*alcat6
Auncia 'mtime
@ &aloare e tip timeIt poate fi efalcat pe componente !i memorat ntr-o
structur#
struct tm {
int tmUsec; >Y secune$ ntre 7 !i AF Y>
int tmUmin; >Y minute$ ntre 7 !i AF Y>
int tmUhour; >Y ore$ ntre 7 !i ?B Y>
int tmUmda;; >Y ziua in lun$ ntre 4 !i B4 Y>
int tmUmon; >Y luna$ ntre 7 !i 44 Y>
int tmU;ear; >Y anul curent minus 4F77 Y>
int tmUwda;; >Y ziua in sptmn$ uminica# 7 Y>
int tmU;da;; >Y ziua in an$ ntre 7 !i BEA Y>
int tmUisdst; >Y op%iunea a2lig/t sa&ing time Y>
;
Observaie. Alegerea numelui tm pentru aceast structur a fost ct se poate
e neinspirat. Programatorii trebuie s fie eosebit e aten%i ca$ atunci cn
folosesc func%ii in aceast categorie$ s nu foloseasc n nici un caz numele tm
pentru efini%ii proprii.
Kunc%ia 8mtime efectueaz aceast efalcare. Aceast func%ie returneaz
aresa unei zone une se afl ata calenaristic efalcat. +nforma%iile in
aceast zon trebuie sal&ate n cazul n care se efectueaz prelucrri ulterioare. "n
apel ulterior al func%iei 8mtime le &a suprascrie$ zona fiin alocat static n
interiorul acesteia.
struct tm 08mtime(const timeUt 0tims);
Auncia mJtime
timeUt m-time(struct tm 0datc);
Aceast func%ie efectueaz con&ersia in&ers$ e la o structur efalcat la o
&aloare compact. Gste suficient s completm &alorile tmU;ear$ tmUmon$
tmUmda;$ tmUhour$ tmUmin$ tmUsec. 0ac o &aloare se afl n afara
33333333333333333333333333333333333333333333
4B6
limitelor permise$ acestea snt automat normalizate. 0e e.emplu$ ora ?A#77#77
este ec/i&alat cu ora 4#77#77 a zilei urmtoare. Kunc%ia corecteaz (ac e
ne&oie, toate &alorile structurii. 0ac ata calenaristic nu poate fi reprezentat
ca o &aloare e tip timeUt$ func!ia returneaz &aloarea (timeUt,(<4,.
Aunciile ctime 7i asctime
char 0ctime(const timeUt 0tims);
char 0asctime(const struct 0datc);
Aceste func%ii con&ertesc ata calenaristic n reprezentare A*C++. Aceste
func%ii returneaz aresa unui !ir e forma#
"Mun \un 02 &0P00P00 .002"
+nforma%iile in aceast zon trebuie sal&ate n cazul n care se efectueaz
prelucrri ulterioare. "n apel ulterior al func%iei le &a suprascrie$ zona fiin
alocat static n interiorul acesteia.
Auncia clocJ
cloc-Ut cloc-((oid);
Kunc%ia cloc- returneaz o apro.imare a timpului pe care procesorul l-a
folosit pentru program pn la momentul apelului. 'ipul cloc-Ut este efinit e
majoritatea meiilor e programare ca un sinonim pentru unsi8ned lon8.
)umrul e secune e la lansarea programului se ob%ine astfel#
(dou'le)cloc-()+E?WENMUVAXUMAEWJF
Constanta E?WENMUVAXUMAEWJF este specific meiului e programare folosit.
0e e.emplu$ biblioteca N)" C Compiler pentru sistemul e operare 1inu.
efine!te &aloarea 4777777. @ consecin% a acestui fapt este c pe un sistem e
calcul pe B? e bi%i func%ia cloc- &a returna aceea!i &aloare la apro.imati&
fiecare 6? e minute.
Observaie. *tanarul C nu impune ca aceast cronometrare s nceap e la
zero la lansarea programului. 0e aceea$ pentru a garanta un ma.im e
portabilitate$ cronometrarea se face astfel#
main() {
dou'le stm;
stm ! cloc-();
. . .
printf("RimeP".,lf\n",(cloc-()7stm)+
E?WENMUVAXUMAEWJF);

"nele sisteme e operare$ e e.emplu 1inu.$ permit cronometrarea e.act a


timpului e rulare a unui program (e&ient$ cu limitarea la 6? e minute,$
incluzn aici !i timpul ocupat e sistemul e operare pentru efectuarea unor
33333333333333333333333333333333333333333333
4BC
opera%ii cerute e program. )u este cronometrat timpul ct procesorul este ocupat
cu rularea altui program.
11.>. :)ecutarea unei comen"i sistem
Kunc%ia s;stem$ eclarat n <stdli'.h>$ ofer posibilitatea e a e.ecuta
o coman sub controlul programului.
)ume
s;stem < e.ecut o coman a interpretorului e comenzi
0eclara%ie
s;stem(char 0com);
0escriere
Kunc%ia s;stem e.ecut comana com prin lansarea interpretorului e
comenzi cu acest parametru.
*e recoman folosirea cu aten%ie a acestei func%ii sub unele sisteme e
operare (e e.emplu 1inu.,$ ac interpretorul e comenzi permite precizarea mai
multor comenzi ntr-o singur linie.
11.?. &ro'rame demonstrati#e
4, Programul prezentat n continuare genereaz un !ir e n &alori ntregi
aleatoare n inter&alul I7$C4\ pe care le epune n masi&ul < (alocat inamic,$ !i
apoi le sorteaz cresctor. =n continuare se genereaz - &alori ntregi aleatoare pe
care le caut n masi&ul <. Pentru fiecare cutare cu succes se afi!eaz pe terminal
&aloarea cutat !i pozi%ia n masi&.
Jalorile n$ - !i C se iau n aceast orine in linia e coman.
#include <stdli'.h>
#include <stdio.h>
#include <time.h>
int cmp(const (oid 0=, const (oid 0D) {
return 0(int 0)=70(int 0)D;

int main(int ac, int 00a() {


int 0<,0p,C,n,-,i,(;
if (ac%!/) {
fputs("Rrei ar8umente%\n",stderr);
return &;

n!atoi(a()&*); -!atoi(a().*);
C!atoi(a(),*);
33333333333333333333333333333333333333333333
4BF
<!(int 0)malloc(n0si9eof(int));
if (%<) return &;
srand(time(J@??));
for (i!0; i<n; i$$)
<)i*!rand()"C;
Gsort(<,n,si9eof(int),cmp);
for (i!0; i<-; i$$) {
(!rand()"C;
p!(int 0)'search(#(,<,n,si9eof(int),cmp);
if (p)
printf("SalP "d VosP "d\n",(,p7<);

free(<);
return 0;

?, * relum al treilea e.emplu in capitolul preceent. *e cite!te un fi!ier


te.t care con%ine pe fiecare linie un nume (!ir e caractere fr spa%iu, !i trei &alori
reale (note,. Pentru fiecare linie se calculeaz meia aritmetic a celor trei &alori
!i se etermin ac elementul este amis (fiecare not este minimum A, sau
respins (cel pu%in o not este sub A,. =n final se afi!eaz liniile n orinea
urmtoare# mai nti elementele amise n orinea escresctoare a meiei$ !i apoi
elementele respinse n orine alfabetic up nume. *e afi!eaz oar numele$
situa%ia (=+X, !i meia.
=n acest e.emplu punem n e&ien% o moalitate como e selectare a
membrilor unei structuri cu ajutorul macrourilor. -acroul C'r selecteaz in
zona referit e pointerul V membrul f. 0eoarece pointerul V (care poate fi
argumentul = sau D al func%iei comp, refer o zon e tip (oid$ este necesar mai
nti un cast pentru a preciza tipul concret al acesteia. -embrul f poate fi# nm$ ar$
md$ efini%i n carul structurii e tip MtAl.
0eoarece nu !tim e la nceput cte linii are fi!ierul e intrare$ sntem ne&oi%i
s folosim urmtoarea strategie. 1a nceput alocm pentru masi&ul Al o zon care
s memoreze J= elemente. Pe msur ce aceast zon se completeaz$ la un
moment at numrul e linii citite coincie cu J=. =n acest moment se aloc o
zon nou care s poat memora un numr mai mare e elemente. 0esigur$ e
fiecare at se &a actualiza mrimea spa%iului alocat.
#include <stdli'.h>
#include <strin8.h>
#include <stdio.h>
#define J= ,.
t;pedef struct {
char nm)&&*, ar;
33333333333333333333333333333333333333333333
4D7
float na, n', nc, md;
MtAl;
#define C'r(V,f) ((MtAl 0)V)7>f
int comp(const (oid 0=, const (oid 0D) {
float w;
int d;
if (d!C'r(=,ar)7C'r(D,ar))
return d;
if (C'r(=,ar)!!B=B) {
w!C'r(D,md)7C'r(=,md);
if (w>0) return &;
if (w<0) return 7&;

return strcmp(C'r(=,nm),C'r(D,nm));

int main(int ac, char 00a() {


int na,ne,i;
MtAl 0Al;
>Q?A 0fi;
if (ac%!.) {
fputs("@n ar8ument%\n",stderr);
return &;

fi!fopen(a()&*,"rt");
if (%fi) {
perror("Aroare la deschidere");
return &;

na!J=; ne!0;
Al!(MtAl 0)malloc(na0si9eof(MtAl));
while (fscanf(fi,""s "f "f "f",Al)ne*.nm,
#Al)ne*.na,#Al)ne*.n', #Al)ne*.nc)
%!AW>) {
if ((Al)ne*.na>!2) ## (Al)ne*.n'>!2) ##
(Al)ne*.nc>!2)) Al)ne*.ar!B=B;
else Al)ne*.ar!BXB;
Al)ne*.md!(Al)ne*.na$Al)ne*.n'$Al)ne*.nc)+,.0;
ne$$;
if (ne!!na) {
na$!J=;
Al!(MtAl 0)realloc(Al,na0si9eof(MtAl));


fclose(fi);
Gsort(Al,ne,si9eof(MtAl),comp);
for (i!0; i<ne; i$$)
33333333333333333333333333333333333333333333
4D4
printf(""7&.s "c"1..lf\n",Al)i*.nm,
Al)i*.ar,Al)i*.md);
free(Al);
return 0;

B, *e cite!te intr-un fi!ier te.t o &aloare natural n. "rmtoarele linii con%in


n cu&inte$ fiecare cu&nt a&n acela!i numr e litere (cel mult 47,. * se afi!eze
cu&intele in fi!ier oronate alfabetic.
Pentru a memora lista e cu&inte folosim urmtoarea strategie. =n loc s
alocm pentru fiecare cu&nt (!ir e caractere, citit o zon nou e memorie$
alocm e la nceput o zon n care s putem memora toate cu&intele in list.
Aceast zon &a a&ea mrimea e (l$&)0n octe%i$ une l este lungimea fiecrui
cu&nt (numrul e litere,. 0e ce (l$&)# trebuie s memorm !i caracterul
terminator null.
A&antaje# memoria este utilizat mai eficient ac se aloc e la nceput o
zon contigu e imensiune mai mare$ !i se reuce foarte mult fragmentarea
memoriei.
#include <stdli'.h>
#include <strin8.h>
#include <stdio.h>
int comp(const (oid 0=, const (oid 0D) {
return strcmp((char 0)=,(char 0)D);

int main(int ac, char 00a() {


char 0E,s)&&*;
int n,l,i;
>Q?A 0fi;
if (ac%!.) {
fputs("@n ar8ument%\n",stderr);
return &;

fi!fopen(a()&*,"rt");
if (%fi) {
perror("Aroare la deschidere");
return &;

fscanf(fi,""d "s",n,s);
l!strlen(s);
E!(char 0)malloc((l$&)0n);
strcp;(E,s);
for (i!&; i<n; i$$)
fscanf(fi,""s",E$(l$&)0i);
fclose(fi);
33333333333333333333333333333333333333333333
4D?
Gsort(E,n,l$&,comp);
for (i!0; i<n; i$$)
printf(""s\n",E$(l$&)0i);
free(E);
return 0;

33333333333333333333333333333333333333333333
4DB
Biblio'ra*ie 5inclusi# manuale electronice6
Pentru o escriere etaliat a limbajului C recomanm#
Brian 8 9ernig/am$ 0ennis - Ritc/ie - The C "rogramming %anguage
Prentice-Oall *oft:are *eries$ 4FCC
/ttp#>>freebooLs.b2.ru>CanCpp./tml
Oerbert *c/ilt - 6anual C complet
Gitura 'eora$ 4FFC
Brian Bro:n - C "rogramming
/ttp#>>:::..ploiter.com>mirrors>cprogram>cstart./tm
*te&e *ummit - (ntroductory C "rogramming Class 2otes
/ttp#>>:::.esLimo.com>Hscs>cclass>cclass./tml
*te&e *ummit - (ntermediate C "rogramming Class 2otes
/ttp#>>:::.esLimo.com>Hscs>cclass>cclass./tml
33333333333333333333333333333333333333333333
4DD
Cuprins
4. Neneralit%i asupra limbajului C. . . . . . . . . . . . . . . . . . . . D
4.4. +ntroucere. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D
4.?. Reprezentarea &alorilor numerice . . . . . . . . . . . . . . . . . . . . . . A
4.B. Primele programe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E
?. "nit%ile le.icale ale limbajului C . . . . . . . . . . . . . . . . . . 4D
?.4. +entificatori; cu&inte c/eie . . . . . . . . . . . . . . . . . . . . . . . . . . 4D
?.?. Constante. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4A
?.B. airuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
?.D. @peratori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4C
?.A. *eparatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4C
B. Jariabile. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ?7
B.4. Clase e memorie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ?4
B.?. 'ipuri funamentale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ?B
B.B. @biecte !i &alori-stnga . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ?E
B.D. Con&ersii e tip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ?6
B.A. -asi&e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B7
B.E. +ni%ializri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B7
B.6. Calificatorul const . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B?
D. @peratori !i e.presii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . BB
D.4. G.presii primare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . BB
D.?. @peratori unari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . BA
D.B. @peratori aritmetici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B6
D.D. @peratori e comparare. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . BC
D.A. @peratori logici pe bi%i. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . BF
D.E. @peratori pentru e.presii logice . . . . . . . . . . . . . . . . . . . . . . . D4
D.6. @peratorul coni%ional. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D?
D.C. @peratori e atribuire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DB
D.F. @peratorul &irgul . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DD
D.47. Preceen%a !i orinea e e&aluare . . . . . . . . . . . . . . . . . . . . . DD
A. +nstruc%iuni. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DE
A.4. +nstruc%iunea expresie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DE
A.?. +nstruc%iunea compus sau blocul . . . . . . . . . . . . . . . . . . . . . . DE
A.B. +nstruc%iunea if. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . D6
A.D. +nstruc%iunile while !i do. . . . . . . . . . . . . . . . . . . . . . . . . . . DF
A.A. +nstruc%iunea for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DF
A.E. +nstruc%iunea switch. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A4
A.6. +nstruc%iunile 'rea- !i continue. . . . . . . . . . . . . . . . . . . . AB
A.C. +nstruc%iunea return . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AA
A.F. +nstruc%iunea &i . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . AA
33333333333333333333333333333333333333333333
4DA
E. Kunc%ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A6
E.4. 0efini%ia func%iilor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A6
E.?. Apelul func%iilor; func%ii recursi&e . . . . . . .. . . . . . . . . . . . . . . AF
E.B. Re&enirea in func%ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E4
E.D. Argumentele func%iei !i transmiterea parametrilor . . . . . . . . . E?
E.A. G.emple e func%ii !i programe. . . . . . . . . . . . . . . . . . . . . . . . EB
6. 0ez&oltarea programelor mari . . . . . . . . . . . . . . . . . . . . . E6
6.l. =nlocuirea simbolurilor$ substitu%ii macro . . . . . . . . . . . . . . . . E6
6.?. +ncluerea fi!ierelor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . EC
6.B. Compilarea coni%ionat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
6.D. G.emple. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
C. Pointeri !i masi&e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6E
C.4. Pointeri !i arese . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6E
C.? Pointeri !i argumente e func%ii . . . . . . . . . . . . . . . . . . . . . . . . 6C
C.B. Pointeri !i masi&e. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6F
C.D. Aritmetica e arese . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C4
C.A. Pointeri la caracter !i func%ii . . . . . . . . . . . . . . . . . . . . . . . . . . CB
C.E. -asi&e multiimensionale . . . . . . . . . . . . . . . . . . . . . . . . . . . CD
C.6. -asi&e e pointeri !i pointeri la pointeri . . . . . . . . . . . . . . . . C6
C.C. +ni%ializarea masi&elor !i masi&elor e pointeri . . . . . . . . . . . F4
C.F. -asi&e e pointeri !i masi&e multiimensionale . . . . . . . . . . FD
C.47. Argumentele unei linii e coman . . . . . . . . . . . . . . . . . . . FC
C.44. Pointeri la func%ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47?
F. *tructuri !i reuniuni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47E
F.4. Glemente e baz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47E
F.?. t;pedef. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47F
F.B. -asi&e e structuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 444
F.D. Pointeri la structuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44A
F.A. *tructuri auto-referite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446
F.E. Arbori binari e cutare. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4?B
F.6. Cmpuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4?6
F.C. Reuniuni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4?F
47. +ntrri > ie!iri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4BB
47.4. +ntrri !i ie!iri stanar; fi!iere . . . . . . . . . . . . . . . . . . . . . . . 4BB
47.?. Accesul la fi!iere; esc/iere !i nc/iere. . . . . . . . . . . . . . . 4BA
47.B. Citire !i scriere fr format . . . . . . . . . . . . . . . . . . . . . . . . . . 4BC
47.D. Citire cu format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4D7
47.A. *criere cu format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4DB
47.E. 'ratarea erorilor. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4DC
47.6. @pera%ii cu irectoare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4A7
47.C. Programe emonstrati&e . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4A?
33333333333333333333333333333333333333333333
4DE
44. Alte rutine in biblioteca stanar . . . . . . . . . . . . . . . . . 4AE
44.4. Alocarea inamic a memoriei . . . . . . . . . . . . . . . . . . . . . . . 4AE
44.?. *ortare !i cutare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4A6
44.B. Rutine e clasificare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4AC
44.D. @pera%ii cu blocuri e memorie. . . . . . . . . . . . . . . . . . . . . . . 4E7
44.A. @pera%ii cu !iruri e caractere . . . . . . . . . . . . . . . . . . . . . . . . 4E?
44.E. Biblioteca matematic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4EE
44.6. Kunc%ii pentru timp !i at calenaristic . . . . . . . . . . . . . . . 4EC
44.C. G.ecutarea unei comenzi sistem . . . . . . . . . . . . . . . . . . . . . . 464
44.F. Programe emonstrati&e . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46?
Bibliografie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 466
33333333333333333333333333333333333333333333
4D6

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