Sunteți pe pagina 1din 91

Programare_ Limbajul_C

i
CUPRINS


CUPRINS _______________________________________________________________________ i
Cap 1 INTRODUCERE N LIMBAJUL C _____________________________________________4
1.1 Scurt istoric_________________________________________________________________4
1.2 Forma unui program C _______________________________________________________8
1.3 Compilarea unui program C___________________________________________________9
Cap 2 Tipuri, operatori, expresii_____________________________________________________11
2.1. Tipuri simple ______________________________________________________________11
2.2. Literali ___________________________________________________________________12
2.3. Declararea unei variabile i a unei constante ____________________________________13
2.4. Operatori _________________________________________________________________14
2.4.1. Operatori aritmetici ______________________________________________________15
2.4.2. Operatorii relaionali (de comparaie) ________________________________________15
2.4.3. Operatori logici _________________________________________________________16
2.4.4. Operatori la nivel de bit ___________________________________________________16
2.4.5. Operatorul de asignare ____________________________________________________16
2.4.6. Operatorul condiional ____________________________________________________17
2.4.7. Operatorul virgul _______________________________________________________17
2.4.8. Precedena operatorilor ___________________________________________________18
Cap 3 FUNCTII _________________________________________________________________19
3.1. Definirea unei funcii _______________________________________________________19
3.2. Returnarea unui apel _______________________________________________________20
3.3. Funcii cu un numr variabil de parametri _____________________________________20
3.4. Sfritul execuiei unui program______________________________________________20
3.5. Apelul i transmiterea parametrilor ___________________________________________21
3.6. Funcia principal main _____________________________________________________22
Cap 4 FUNCII DE INTRARE IEIRE______________________________________________24
4.1.Fluxuri i fiiere ____________________________________________________________24
Semnificaia __________________________________________________________________26
4.2. Funcii de intrare/ieire pentru caractere_______________________________________27
4.3. Scrierea cu format__________________________________________________________28
4.5. Citirea cu format ___________________________________________________________32
Cap 5 INSTRUCIUNI DE CONTROL ______________________________________________35
5.1. Instruciunea if ____________________________________________________________36
5.3. Instruciunea while_________________________________________________________38
5.4. Instruc]iunea do ... while ___________________________________________________39
Gheorghe GRIGORA

ii
5.5. Instruciunea for ___________________________________________________________39
5.6. Instruciunea break ________________________________________________________41
5.7. Instruciunea continue _____________________________________________________42
5.8. Instruciunea go to_________________________________________________________42
5.9. Exerciii __________________________________________________________________43
1. Calculul factorialului. _____________________________________________________43
2. Conversie _________________________________________________________________43
3. Numrarea biilor 1 ntr-un numr ______________________________________________43
4. Prezentare de date __________________________________________________________43
5.10. Soluii la exerciii _________________________________________________________43
1. Calculul factorialului ________________________________________________________43
2. Conversie _________________________________________________________________44
3. Numrarea biilor 1 ntr-un numr ______________________________________________45
4. Prezentare de date __________________________________________________________45
Cap 6 TABLOURI I POINTERI ___________________________________________________47
6.1. Pointeri ___________________________________________________________________47
6.2. Tablouri cu o dimensiune____________________________________________________48
6.2.1. Referenierea unui element al tabloului _______________________________________48
6.2.2. Iniializarea unui tablou ___________________________________________________48
6.3. Relaia ntre pointeri i tablouri ______________________________________________50
6.4. Operaii aritmetice cu pointeri _______________________________________________51
6.5. iruri de caractere _________________________________________________________51
6.6. Tablouri cu mai multe dimensiuni ____________________________________________51
6.7. Tablouri de pointeri ________________________________________________________53
6.8. Pointeri i alocarea memoriei_________________________________________________54
6.9. Operatorul sizeof________________________________________________________55
6.10. Pointeri ctre funcii _______________________________________________________55
6.11. Exerciii _________________________________________________________________57
6.12. Soluii ___________________________________________________________________57
Cap 7 CONSTRUIREA DE NOI TIPURI _____________________________________________59
7.1. Redenumirea unui tip_______________________________________________________59
7.2. Tipul structur ____________________________________________________________60
7.3. Accesul i iniializarea cmpurilor unei structuri ________________________________61
7.4. Structuri autorefereniate ___________________________________________________61
7.5. Tipul enumerare ___________________________________________________________63
7.6. Uniuni ____________________________________________________________________63
7.7. Exerciii __________________________________________________________________65
7.8. Soluii ____________________________________________________________________66
Cap 8 GESTIUNEA MEMORIEI ___________________________________________________70
Programare_ Limbajul_C

iii
8.1. Precizarea unui mecanism de memorare _______________________________________71
8.2. Gestiunea automat a memoriei ______________________________________________71
8.3. Gestionarea register a memoriei ____________________________________________71
8.4. Gestionarea static a memoriei _______________________________________________72
8.5. Variabile globale ___________________________________________________________72
8.6. Declararea variabilelor externe _______________________________________________72
8.7. Gestiunea dinamic a memoriei_______________________________________________73
8.8. Exerciii __________________________________________________________________73
8.9. Soluii ____________________________________________________________________74
Cap 9 CONVERSIA DE TIP _______________________________________________________76
9.1. Mecanisme de conversie ____________________________________________________76
9.1.1 Conversia la asignare _____________________________________________________77
9.1.2 Evaluarea expresiilor aritmetice _____________________________________________77
9.1.3. Evaluarea expresiilor logice________________________________________________78
9.1.4 Conversii explicite _______________________________________________________78
9.1.5 Conversie de pointeri. Pointerul universal _____________________________________79
Cap 10 PREPROCESORUL________________________________________________________80
10.1 Directive preprocesor ______________________________________________________80
10.1.1 Constante simbolice. Directiva #define______________________________________81
10.1.2 Includerea fiierelor _____________________________________________________81
10.1.3 Compilare condiionat___________________________________________________82
10.1.4 Directiva #error ______________________________________________________82
10.2 Macroinstruiuni __________________________________________________________83
10.2.1 Macroinstruciuni predefinite ______________________________________________83
10.2.2 Macroinstruciuni tip funcie_______________________________________________83
Cap 11 EXERCIII_______________________________________________________________84
BIBLIOGRAFIE_________________________________________________________________86
ANEXA ________________________________________________________________________87
Biblioteca standard C __________________________________________________________87
Codul ASCII __________________________________________________________________90


Cap 1 INTRODUCERE N LIMBAJUL C









1.1 Scurt istoric
1.2 Forma unui program C
1.3 Compilarea unui program C
















1.1 Scurt istoric


Strmoii limbajului C sunt limbajele de programare CPL, BCPL, B i Algol 68. CPL a fost dezvoltat
la Universitile Cambridge i London n anii 1960-1963. BCPL a fost proiectat de Martin Richards n
1967 i face parte din categoria low-level languages, sau systems programming languages. n anii
60, la Bell Laboratories n USA, Ken Thomson a nceput proiectarea sistemului de operare Unix. Primul
limbaj de nivel nalt implementat sub acest sistem de operare a fost limbajul B, un limbaj bazat pe BCPL
care a fost proiectat de asemenea de ctre Ken Thompson n 1970. Asemnarea cu BCPL a fost mai
degrab semantic; sintaxa este total diferit. Proiectarea limbajului B a fost influienat de limitele
mainii pe care a fost implementat: un PDP-7 cu capacitatea 4K ( cuvinte de 18 bii).
Limbajele BCPL i B sunt limbaje de nivel sczut fa de limbajul Pascal i nici unul din ele nu este
tipizat: toate datele sunt considerate cuvinte main nct, exemple simple de programe duc la complicaii
nebnuite. n una din implementrile BCPL-ului, operanzii flotani din expresii trebuiau precedai de
punct; restul operanzilor erau considerai ntregi.
Problemele create n jurul limbajelor BCPL i B au dus la dezvoltarea unui nou limbaj, bazat pe B,
care la nceput s-a numit NB dar numele su a fost stabilit C. Numele C, considerat la nceput a proveni
de la Cambridge, este oficial din Combined dar neoficial se consider a fi iniiala pronumelui lui
Programare_ Limbajul_C

5
Cristopher Strachey, cel care a condus echipa ce a proiectat CPL-ul. Limbajul a fost proiectat i
implementat de ctre Dennis Ritchie la Bell Laboratories n 1972. n mare parte ( construciile for i
switch, tratarea pointerilor etc.) limbajul a fost influienat i de Algol 68. Genealogia limbajului C este
prezentat n Figura 1.1.
Ritchie a lucrat pe un calculator DEC PDP-11 sub sistemul de operare Unix. Din acest motiv varianta
clasic a limbajului C a fost asociat sistemului de operare Unix - versiunea 5 i mult vreme a constituit
un standard (neoficial de altfel) al limbajului [KeR 78].
Odat cu cretere popularitii calculatoarelor personale, au aprut numeroase alte implementri ale
limbajului C i astfel a crescut i popularitatea acestuia. Un fapt cu totul inedit a fost acela c, mare parte
din implementrile C -ului s-au dovedit de un mare grad de compatibilitate: un program scris pentru una
din variante putea fi compilat cu succes folosind o alt variant. Se nelege c au existat i neconcordane
n multitudinea de dialecte ale limbajului. Pentru eliminarea acestora n 1983 a fost creat o comisie
care s stabileasc un standard al acestui limbaj. Standardul ANSI ( American National Standard
Institute) a fost redactat abia n decembrie 1989 i a fost pus la dispoziia celor interesai la nceputul lui
1990. Firma Borland a folosit acest standard n faza de proiect i a realizat implementrile Turbo C care
se bucur de un succes remarcabil. De altfel, n prezent , toate compilatoarele C sunt compatibile cu
standardul ANSI C; unele din acestea au adugate o serie de faciliti sau extensii proprii care nu
mpiedic compilarea unui program standard.




FORTRAN I (1957)


FORTRAN II (1958)



ALGOL 60 (1960)
CPL (1963)

ALGOL 68 (1968)
BCPL (1967)

B (1970)



C (1972)


C++ (1984)
Figura 1.1.


Limbajul C este privit ca un limbaj de nivel mediu ntruct combin cele mai reuite elemente ale
limbajelor de nivel nalt ( Pas-cal, Fortran, Algol, Modula, Ada) cu gradul de control i flexibilitatea
oferite de ctre limbajul de asamblare. C permite manevrarea biilor, a octeilor i a adreselor de memorie,
adic a elementelor de baz n funcionarea unui calculator. n ciuda acestui fapt , programele scrise n C
Gheorghe GRIGORA

6
au un grad mare de portabilitate: uurina de a adapta programele scrise pentru o anumit categorie de
calculatoare sau sisteme de operare la alte calculatoare sau sisteme de operare.
Limbajul C are structuri de control adecvate precum i faciliti de structurare a datelor care l fac s
fie folosit ntr-o diversitate de domenii. Are de asemenea o mulime bogat de operatori care-i dau un
nalt grad de expresivitate. Unul din motivele pentru care limbajul C este n acelai timp agreat de mare
parte din programatori i dezagreat de alt mare parte din programatori, este lipsa total a verificrii
tipului (type checking). De exemplu, o variabil de un tip scalar oarecare poate apare n aceeai expresie
cu o variabil de un alt tip scalar. Cei care agreaz limbajul C i apreciaz flexibilitatea sa, cei care nu-l
agreaz l consider un limbaj lipsit de siguran.
Ceea ce este sigur, este c datorit faptului c face parte din sistemul de operare Unix, limbajul a
cptat o mare popularitate n lumea academic i nu numai. Compilatoarele oferite mpreun cu sistemul
Unix sunt relativ ieftine (uneori chiar gratuite) i pot fi folosite pe o diversitate de maini.
O nou versiune a limbajului C, numit C++, a aprut n 1984. Originea acestui limbaj STR 94
trebuie cutat n proiectul care a nceput n Aprilie 1979 la Computing Research Center of Bell
Laboratories n Murray Hill, New Jersey, USA, proiect ce trebuia s realizeze distribuirea nucleului
UNIX ntr-o reea de computere conectate LAN. Pentru realizarea acestui proiect, Bjarne Stroustrup a
realizat n Octombrie 1979 un preprocesor, numit Cpre, care a adugat la limbajul C conceptul de clas
folosit pentru prima dat de limbajul Simula ( dezvoltat n anii 1962-1967 de norvegienii Kristen
Nyagaard i Ole-Johan Dahl). n martie 1980 preprocesorul mbuntit era implementat pe 16 sisteme
iar limbajul acceptat de acesta a fost numit C cu Clase. Motivele pentru care a fost ales limbajul C (n
faa altor limbaje ale vremii: Modula-2, Ada, Smalltalk, Mesa, Clu) pentru acest proiect sunt expuse chiar
de creatorul noului limbaj:
C este un limbaj flexibil: se poate folosi n orice domeniu i permite utilizarea oricror tehnici de
programare;
C este un limbaj eficient: semantica sa este low level ceea ce nseamn c pot fi folosite cu
eficien resursele hardware pentru programele C. Aa cum vom vedea pe parcursul prezentrii
limbajului, acesta oglindete conceptele fundamentale ale unui computer tradiional;
C este un limbaj disponibil: un limbaj pentru care se poate gsi cu uurin un compilator,
indiferent de ce calculator dispunem;
C este un limbaj portabil: chiar dac un program C nu este automat portabil de la o main la alta,
acest lucru este posibil n general fr un efort deosebit.
Cele mai mari influiene asupra noului limbaj le-au avut: Simula care a dat clasele, Algol 68 care a
dat suprancrcarea operatorilor, referinele i abilitatea de a declara variabile oriunde n cadrul unui bloc
i BCPL de unde a fost luat forma de prezentare a comentariilor cu //. Dup numele C cu clase
limbajul a fost botezat C84. Asta pentru scurt timp ns deoarece comitetul ANSI pentru standardizarea
C-ului a atras atenia c se poate crea o confuzie cu aceast denumire; era vorba totui de un nou limbaj,
chiar dac era cldit pe C. Numele C++ a fost sugerat de Rick Mascitti, un membru al echipei lui
Stroustrup, i a fost folosit pentru prima dat n Decembrie 1983.Iat ce spune Stroustrup despre aceast
alegere: <<I picked C++ because it wos short, had a nice interpretation, and wasnt of the form
adjective C. In C++, ++ can, depending on context, be read as next, succesor or increment ,
tough it is always pronounced plus plus.>>
n figura 1.2. este prezentat genealogia limbajului C++ iar figura 1.3. prezint etapele importante din
proiectarea limbajului.
Datele care apar n parantez se refer la prima implementare disponibil pentru limbajul
respectiv(dup [STR 94]). C++arm reprezint The Annotated C++ Reference Manual iar C++std este
standardul ANSI C++.





Programare_ Limbajul_C

7
Fortran(1956)

Algol 60(1960)

CPL(1963)


BCPL(1967)


Simula 67(1969)


C


Algol 68(1977)


C cu Clase (1980)



Ada (1983)
C++ (1984)

ANSI C ML(1976)
(1986)
Clu(1978)


C++arm(1990)


C++std (1995)

Figura 1.2.


1979 Mai nceputul proiectului C cu clase
Octombrie Prima implementare a lui C cu clase
1980 Aprilie Primul raport intern la Bell Labs asupra lui C cu clase
1982 Ianuarie Primul articol extern asupra lui C cu clase
1983 August Prima implementare a limbajului C++
Decembrie Limbajul a fost botezat C++
1984 Ianuarie Primul manual C++
1985 Februarie Prima lansare extern C++
Octombrie Manualul The C++ Programming Language
1986 Septembrie Prima conferin OOPSLA (centrat pe Smalltalk)
1987 Noiembrie Prima conferin USENIX C++
Gheorghe GRIGORA

8
Decembrie Prima lansare GNU C++
1988 Ianuarie Prima implementare Oregon Software C++
Iunie Prima implementare Zortech C++
1990 Martie Prima reuniune tehnic ANSI X3J16 pentru C++
Mai Prima implementare Borland C++
Mai C++arm: The Annotated C++ Reference Manual
1991 Iunie Prima reuniune ISO WG21
1992 Februarie Prima lansare DEC C++
Martie Prima lansare Microsoft C++
Mai Prima lansare IBM C++
1994 August A fost nregistrat Raportul Comitetului ANSI/ISO

Figura 1.3.
1.2 Forma unui program C
n general, cel care se apuc de nvat limbajul C, mai tie cel puin un limbaj de programare (Pascal
n cele mai multe cazuri). Aceasta pentru c n programa de liceu, la disciplina de informatic, se ncepe
cu un limbaj diferit de C iar n nvmntul superior, la facultile care au n planul de nvmnt
informatic i chiar la cele de profil, primul limbaj de programare studiat (cel puin pn acum) a fost
altul dect limbajul C. Vom ncepe prezentarea printr-un exemplu.

Programul 1
/* Calculul celui mai mare divizor comun (cmmdc) a doua numere intregi
pozitive a si b. Metoda care se aplica pentru a determina cmmdc este
urmatoarea:
- se calculeaza restul impartirii intregi a lui a prin b;
- daca acest rest este nul, b este valoarea cautata. In caz
contrar, a capata valoarea lui b, b capata valoarea restului si
procedeul se repeta.
*/
# include <stdio.h>
int cmmdc (int x, int y){
int rest;
do {
rest = x%y;
x = y;
y = rest;
} while (rest!=0);
return x;
}
int main (){
int a,b;
char raspuns;
do {
printf (" Introduceti 2 valori intregi pozitive -->");
scanf ("%d%d", &a, &b);
if (b>a) {
int c = a;a = b;b = c;
}
printf (" Cmmdc al celor doua numere este:
%d\n",cmmdc (a,b));
printf (" Continuati ? d)a n)u -->");
Programare_ Limbajul_C

9
scanf ("%c", &raspuns);
} while (raspuns!=n);
return 0;
}

S trecem n revist structura programului prezentat.
Primele linii din program constituie comentarii. Aceste comentarii sunt incluse ntre "parantezele"
/* i */. Urmeaz o linie ce ncepe cu #. Pe aceast linie este o directiv care este gestionat de
precompilator (preprocesor) i permite includerea definiiilor funciilor intrare/ieire furnizate de sistem i
care se gsesc n fiierul stdio.h.
Programul pe care l-am prezentat este constituit din dou funcii: main i cmmdc. Trebuie reinut
faptul c orice program C conine definiia unei funcii cu numele main care ine locul programului
principal: punctul de intrare n execuia unui program C este funcia main. Corpul unei funcii este
delimitat de acolade: { ine locul lui begin (dinalte limbaje) iar } al lui end.
n corpul funciei main n Programul 1 avem apeluri la alte funcii: printf, scanf, cmmdc. n
limbajul C nu exist instruciuni de intrare/ieire; operaiile de intrare/ieire se realizeaz prin apel la
funciile unei biblioteci standard furnizate de sistem. Aceste funcii vor fi prezentate mai trziu ntr-un
capitol special. n exemplul de aici avem:
printf cu un parametru aflat ntre ghilimele: acest text va fi tiprit pe ecran
scanf cu trei parametri: "%d%d", &a i %b. Acesta este un apel la o operaie de citire a unor date pe
care le introducem de la tastatur. Parametrul "%d%d" specific formatul de citire a dou
numere ntregi (d de la digit) iar parametrii &a, &b corespund adreselor (faptul c & apare n
fa) unde vor fi memorate cele dou valori ntregi: &a adresa variabilei a, iar &b adresa
variabilei b.
printf ("Cmmdc al celor doua numere este: %dn" cmmdc (a,b))
este un apel la o operaie de scriere (pe ecranul monitorului) a textului: cuprins ntre " i " n
afar de %dn care reprezint formatul cu care se va tipri valoarea returnat de apelul la
funcia cmmdc (a,b): va fi scris un numr ntreg (%d) dup care se trece la linie nou
(caracterul n).
Definiiile acestor funcii se afl n fiierul sistemului stdio.h.
Construcia "do {..} while ( .. )" care apare i n funcia main i n funcia cmmdc este una din
structurile iterative de care dispune limbajul C: grupul de instruciuni cuprins ntre acoladele de dup do
se execut atta timp ct condiia scris dup while este ndeplinit (de precizat c acel grup de
instruciuni se execut mcar odat).
Structurile de control ale limbajului C se vor prezenta ntr-un capitol special.
1.3 Compilarea unui program C
Se tie c exist dou metode generale de transformare a unui program surs ntr-un program
executabil: compilarea i interpretarea. Limbajul C a fost optimizat special n vederea compilrii. Dei au
fost concepute i interpretoare de C i acestea sunt disponibile pentru diferite medii, C a fost gndit de la
bun nceput ca fiind destinat compilrii.
Crearea unui format executabil al unui program C parcurge urmtoarele trei etape:
1. Crearea programului;
2. Compilarea programului;
3. Legarea programului cu funciile necesare existente n bibliotec.
Majoritatea compilatoarelor C asigur medii de programare care includ faciliti pentru realizarea
tuturor etapelor precizate mai sus. Dac se folosete un compilator care nu are integrat un editor (cum
sunt cele din sistemul de operare UNIX), atunci trebuie folosit un editor pentru crearea fiierului surs C.
Atenie ns: compilatoarele accept ca fiiere de intrare (programe surs) numai fiiere text standard.
Prin urmare, dac se creaz un fiier surs cu editorul Word su Windows, acesta trebuie salvat ca fiier
text pentru a putea fi utilizat de un compilator.
Gheorghe GRIGORA

10
Toate programele n C constau dintr-una sau mai multe funcii; singura funcie care trebuie s fie
prezent n orice program se numete main( ). Aceasta este prima funcie apelat la nceputul executrii
programului. ntr-un program C corect conceput, funcia main( ) conine, n esen, o schem a ceea ce
face programul, schem compus din apeluri ale altor funcii aflate n biblioteca standard a limbajului C
sau definite de programator. Standardul ANSI C precizeaz setul minimal de funcii care va fi inclus n
biblioteca standard; compilatoarele ce exist pe pia conin cu siguran i alte funcii. Procesul de legare
(linking) este acela n care programul de legare(linker) combin codul scris de programator cu codul
obiect al funciilor utilizate i care se gsete n bibliteca standard. Unele compilatoare au programul
propriu de legare, altele folosesc programul de legare al sistemului de operare.
Un program C compilat creeaz i folosete patru zone de memorie disjuncte, care ndeplinesc funcii
distincte (figura 1.4.).
Prima regiune este aceea care stocheaz codul programului.Urmeaz o zon de memorie n care sunt
stocate variabilele globale. Celelalte dou zone reprezint aa zisa stiv a programului i zona de
manevr. Stiva este folosit n timpul execuiei programului n scopurile:
memoreaz adresele de revenire ale apelurilor la funcii;
memoreaz argumentele funciilor;
memoreaz variabilele locale;
memoreaz starea curent a unitii centrale de prelucrare.

STIVA






ZONA DE MANEVR

VARIABILE GLOBALE


CODUL PROGRAMULUI

Figura 1.4.

Zona de manevr (heap) este o regiune de memorie liber pe care programul , prin intermediul
funciilor de alocare dinamic ale limbajului C, le folosete pentru stocarea unor articole de genul listelor
nlnuite i arborilor.
S mai precizm , n ncheierea acestei scurte introduceri , c n general, compilatoarele existente pe
pia, sunt compilatoare C++. Aa cum vom vedea n partea a doua a acestei cri, C++ este o versiune
extins a limbajului C, care a fost conceput pentru programarea orientat pe obiecte. De aceea C++
accept limbajul C: orice program C va putea fi compilat de un compilator C++.Dup unii autori,
programarea n limbajul C va dinui mult vreme de acum ncolo, aa cum dinuie de cnd a fost creat
limbajul i, un programator care nu tie C nu va putea programa n C++.






Programare_ Limbajul_C

11

Cap 2 Tipuri, operatori, expresii









2.1. Tipuri simple
2.2. Literali
2.3. Declararea unei variabile
2.4. Operatori





O expresie n limbajul C ca n orice limbaj de programare este o secven de operatori i operanzi
care descrie algoritmul de calcul al unei valori. Operanzii ntr-o expresie sunt nume de variabile, nume de
constante (literali), apeluri la funcii. Aceti operanzi, fiecare dintre ei, au un anume tip iar n funcie de
aceste tipuri se vor aplica algoritmi specifici pentru determinarea valorii expresiei.

2.1. Tipuri simple

Tipurile simple (sau tipurile de baz) ale limbajului C definesc dimensiunea zonei de memorie
ocupat de valoarea unei variabile precum i modul n care va fi interpretat coninutul acestei zone.
Limbajul C ofer de asemenea un mecanism de conversie a tipului care va fi prezentat mai trziu n
lucrare.
Tipurile de baz ale limbajului C pot fi grupate n trei mulimi:

Tipuri ntregi: char, short, int i long. Aceste tipuri sunt utilizate pentru reprezentarea numerelor
ntregi. Diferena dintre acestea const n dimensiunea zonei de memorie ocupat de o variabil de
acest tip i implicit de mrimea domeniului de valori. Acest lucru este sintetizat n Tabela 1.

Tabela 1. Tipurile ntregi
Tipul Dimensiunea
memoriei ocupate
Domeniul
char 8 bii - 128..127
short 16 bii - 32768..32767
int 16 bii - 32768..32767
long
(long int)
32 bii -2147483648..
2147483647

Gheorghe GRIGORA

12
Tipuri reale: float, double
Aceste tipuri sunt folosite pentru a reprezenta numere reale. Ele se disting prin precizia de
reprezentare: float numere reale n simpl precizie aproximativ 6 cifre semnificative - iar double
pentru numere reale n dubl precizie aproximativ 15 cifre semnificative..

Tipul vid: void. Este un tip folosit pentru reprezentri de dimensiune nul. Pentru tipurile ntregi se
pot folosi specificrile signed i unsigned. Specificarea signed tip este echi-valent cu tip iar unsigned
tip are semnificaia din Tabela 2.

Tabela 2. Tipuri ntregi unsigned
Tipul Dimensiunea Domeniul
unsigned char 8 bii 0 .. 255
unsigned short 16 bii 0 .. 65535
unsigned (int) 16 bii 0 .. 65535
unsigned long (int) 32 bii 0 .. 4294967295
2.2. Literali

Literalii (sau constantele literale) sunt valori constante; ele reprezint valori care nu pot fi
modificate pe parcursul execuiei unui program. n limbajul C se folosesc diferite reguli sintactice pentru
reprezentarea constantelor. Tabela 3 sintetizeaz unele din aceste reguli.

Tabela 3. Constante literale
Constante Exemple Explicaii
ntregi 123, -457, ^423, 0
O12, O3724
ox7F, OX3, A24E
39u, o245u, 57F3u
Notaia zecimal
Notaia octal (prefix O)
Notaie hexazecimal (prefix ox sau OX)
Constante fr semn
ntregi
long
12L, 42153l, o42l
423uL, 25AfuL
Reprezentare pe 32 bii
Constante fr semn pe 32 bii
flotant 3.14159, -12.03, .425
-15.2E^3, 10e-12
Reprezentare fr exponent
Reprezentare cu exponent
caracter a, A, ^
ir ir de caractere

Exist i caractere speciale (de control) care sunt compuse din caracterul \ i din alt caracter.
Acestea sunt:
\n - interlinie (linie nou); \t - tabulare;
\\ - caracterul \ (backslash); \f - retur de linie;
\o - caracterul NULL; \ - caracterul
\ - caracterul ; \r - retur de car;
\u - tabulare vertical; \b - backspace;
\ddd - caracter de cod octal ddd;
\xhh - caracter de cod hexazecimal hh.



Programare_ Limbajul_C

13
2.3. Declararea unei variabile i a unei constante

Toate variabilele unui program trebuiesc declarate nainte de a fi utilizate. Variabilele sunt
obiectele de baz ale limbajului i au un nume care este un identificator.
Un identificator n limbajul C este un ir de caractere care trebuie s ndeplineasc condiiile:
- primul caracter este liter sau _ (underscore);
- urmtoarele caractere sunt caractere alfanumerice (litere sau cifre) sau _.
- Nu trebuie s coincid cu vreun cuvnt cheie (vezi Tabela 4)
Tabela 4. Cuvintele cheie ale limbajelor C i C^^

asm
auto
break
case
catch
char
class
const
continue
default
delete
do
double
else
enum
extern
float
for
friend
goto
handle
if
inline
int
long
new
operator
overload
private
protected
public
register
return
short
signed
sizeof
static
struct
switch
template
this
throw
try
typedef
union
unsigned
virtual
void
volatile
while
O variabil se declar prin una din urmtoarele instruciuni:

tip nume;
tip nume = valoare;

Mai multe variabile de acela i tip pot fi declarate n aceea i instruc iune, desp r ite prin virgule.

O constant se declar prin:

const tip nume= valoare;

Exemple:
int i, j, k;
float eps = 1.e-4, pi = 3.14159;
char n1='\n';
const double e = 2.71828182845905;
const float pi = 3.14159;
const char mesaj[ ] = "Eroare";

Variabilele se declar la nceputul funciilor (variabile locale) sau n exteriorul tuturor funciilor
(variabile globale). n afar de tipul variabilei i eventual o valoare iniial pentru aceasta, ntr-o
declaraie se specific clasa de alocare (implicit sau explicit). Clasele principale de alocare sunt
automatic i static.
Variabilele din clasa automatic sunt definite n interiorul funciilor fiind locale funciei n care au
fost definite, avnd durata de via pe parcursul execuiei funciei. Aceast clas este implicit; explicit se
poate specifica prin cuvntul cheie aut:
aut int x;
Tot n interiorul unei funcii variabilele mai pot fi definite i n clasa register care este
asemntoare cu cea automatic cu deosebirea c, dac e posibil, alocarea se face n registrele unitii
Gheorghe GRIGORA

14
centrale i nu n memoria RAM. Variabilele din clasele auto i register nu i pstreaz valoarea de la un
apel la altul al funciei n care sunt definite.
Variabilele din clasa static difer de cele din clasa auto sau register prin aceea c sunt memorate
n locaii fixe de memorie (au o adres fix, permanent). Dac se definesc n interiorul unei funcii
trebuie s aib neaprat n fa cuvntul rezervat static (se mai spune c sunt n clasa static internal).
Variabilele definite n exteriorul tuturor funciilor fr vreun specificator de clas sunt n clasa
extern i au alocate adrese fixe. Tabelul 5 sintetizeaz clasele de alocare.
Tabelul 5. Clase de alocare
CLASA CARACTERISTICI

Vizibilitate
Adre
s
fix
Pstreaz
valoarea
Durata de
via
Auto,
Register
n interiorul funciei NU NU Pe durata
funciei
Static
internal
n interiorul funciei DA DA Pe durata
aplicaiei
External n toate modulele DA DA Pe durata
aplicaiei
Static
external
n modulul n care-i
definit
DA DA Pe durata
aplicaiei
External
(n funcie)
n toate modulele
aplicaiei
DA - -
Static
External
(n funcie)
n toate modulele
aplicaiei
DA - -
n capitolul al optulea sunt tratate mai n amnunt problemele legate de gestiunea memoriei.
2.4. Operatori
Operatorii se folosesc la constituirea de expresii pornind de la constante i variabile. Evaluarea
expresiilor se face nlocuind operanzii prin valorile sale i efectund operaiile conform cu specificaiile
acestora. Am vzut c operanzii pot fi variabile, constante sau apeluri la funcii (despre care se va vorbi
mai trziu). Fiecare dintre acetia au un tip declarat. Dac tipul operanzilor este acelai ntr-o expresie,
evaluarea se face n mod natural. Spre exemplu, dac se declar:
float alpha = 20.45;
float beta = 25;
atunci evaluarea expresiei:
alpha + sqrt (beta),se face n ordinea indicat mai jos:
alpha + sqrt (25)
alpha + 5.0
20.45 + 5.0
25.45
Dac operanzii au tipuri diferite , se aplic conversii implicite de tip: unul din operanzi se convertete
la tipul celuilalt iar tipul rezultatului va fi tipul comun.
Operatorii ce pot apare ntr-un program C sunt de patru feluri:
operatori primari de parantetizare; acetia delimiteaz subexpresii i pot schimba
asociativitatea operatorilor. De pild expresiile
x * y +z i x * (y + z)
vor fi evaluate diferit pentru aceleai valori ale variabilelor, ca i perechea:
x + y * z ; (x + y) * z.
Programare_ Limbajul_C

15
operatori binari cu notaie infixat adic:
operand operator operand.
Exemplu: x + y x % y.
operatori unari cu notaie prefixat sau postfixat:
-x, ++x, y--, x++.
operatorul ternar condiional
operand 1 ? operand 2 : operand 3.
2.4.1. Operatori aritmetici
Operatorii aritmetici sunt aceea care se aplic operanzilor numerici. Acetia pot fi unari sau binari
iar n privina asociativitii, acolo unde nu este specificat altfel, aceasta este de la stnga la dreapta.
Operatorii unari:
+,- plus i minus unari; asociativitatea este de la dreapta la stnga;
++ autoincrementarea;
-- autodecrementarea;
Negaia are semnificaia obinuit: schimb semnul valorii expresiei n faa creia se afl.
Operatorii ++ i -- incrementeaz (decrementeaz) cu 1 valoarea unei variabile i pot fi :
prefixai: variabila este incrementat (decrementat) nainte de evaluarea expresiei n care se afl iar
asociativitatea este de la dreapta la stnga;
postfixai: variabila este incrementat (decrementat) dup evaluarea expresiei n care se afl iar
asociativitatea este de la stnga la dreapta..
Exemple: Fie declaraia
int i = 10, j, k, l, m;
atunci: j = i ++ /* j = 10 apoi i = 10 */
k = ++i /* i = 12 apoi k = 12 */
l = i-- /* l = 12 apoi i = 11 */
m = --i /* i = 10 apoi m = 10 */
Operatorii binari sunt urmtorii
+ adunare * nmulire
- scdere / mprire
% modulo
La aceti operatori se adaug funciile din biblioteca matematic - prezentate n Anexa care sunt
operatori cu scriere prefixat:
- funciile trigonometrice uzuale: sin, cos, tan, asin, acos, atan;
- funcia de ridicare la putere pow;
- funciile exponenial, logaritmic etc.
2.4.2. Operatorii relaionali (de comparaie)
Operatorii relaionali sunt operatori binari i permit compararea valorilor a doi operanzi (expresii)
iar rezultatul evalurii este zero (dac rezultatul este fals) sau 1 (dac rezultatul este adevrat). Acetia
sunt operatori binari iar sintaxa lor n C este:
< (mai mic) <= (mai mic sau egal)
> (mai mare) >= (mai mare sau egal)
== (egal) != (diferit)
Cum rezultatul unei comparri este un numr ntreg este posibil asignarea acestuia unei variabile
ntregi:
int a, x, y
a = (x! = y);
n secvena anterioar, dac x va fi egal cu y atunci a va cpta valoarea 0 iar n caz contrar a va
cpta valoarea 1.
Gheorghe GRIGORA

16
2.4.3. Operatori logici
Operatorii logici sunt operatori binari care se aplic unor operanzi ce au valori adevrat (1) sau
fals (0) i ei corespund operaiilor logice uzuale:
! - negaia logic cu asociativitate de la dreapta
la stnga
- disjuncia logic (sau)
&& - conjuncia logic (i)
Expresia:
op1&&op2 are valoarea adevrat (1) dac cei doi operanzi sunt evaluai la adevrat, iar dac
unul din ei are valoarea fals (0) atunci expresia are valoarea zero.
op1op2 are valoarea zero (fals) dac i numai dac op1 i op2 au ambii valoareea zero
(fals).
!op1 are valoarea fals dac op1 este adevrat i are valoarea adevrat dac op1 este fals.
2.4.4. Operatori la nivel de bit
Limbajul C dispune de ase operatori pentru tratarea informaiei la nivel de bit. Acetia se pot
aplica doar operanzilor de tip ntreg (char, int, short, long) i servesc la poziionarea sau interpretarea
valorilor ntregi ca o secven de valori binare. Aceti operatori sunt:
& - conjuncie logic la nivel de bit;
- disjuncie logic la nivel de bit;
^ - sau exclusiv la nivel de bit;
<< - deplasare la stnga;
>> - deplasare la dreapta;
~ - negare la nivel de bit (operator unar).

Semnificaia primilor trei operatori binari (&, |, ^) este cea natural (aminitm c 1 reprezint valoarea
logic adevrat iar 0 valoarea fals). Exemplele urmtoare sunt edificatoare.
op1 =01100100
op2 =10111010

op1 & op2 = 00100000
op1 | op2 = 11111110
op1 ^ op2 = 11011110
De asemenea negaia (~) acioneaz la nivelul fiecrui bit schimbnd 1 =n 0 i 0 =n 1.
~ op1 = 10011011
Operatorii binari de decalare ( << i >>) servesc la decalarea cu un anumit numr de bii (dat de cel
de-al doilea operand) la stnga sau la dreapta n cadrul primului operand. n particular se poate obine
(rapid!) nmulirea cu 2
op2
(op1 << op2) sau cu 2
-op2
(op1 >> op2).
Exemple:
x = 13;
y = x << 2;
z = x >> 2;
x = 0000 0000 0000 1101 (= 13)
y = 0000 0000 0011 0100 (= 13.4)
z = 0000 0000 0000 0011 (= 13/4)
2.4.5. Operatorul de asignare
Operatorul de asignare, exprimat prin =, are ca efect evaluarea expresiei din dreapta semnului = i
atribuirea acestei valori variabilei ce se afl n stnga acestui semn.

variabila = expresie;
Programare_ Limbajul_C

17
Pe lng acest tip de asignare, limbajul C permite compunerea asignrii (#) cu un operator binar (op)
obinndu-se operatori de asignare compus:

e1 op = e2; unde e1 i e2 sunt expresii.

Aceast asignare este echivalent cu :

e1 = (e1) op (e2);

Se obin asignri compuse cu:
Operatori aritmetici: +=, -=, *=, /=, %=
Operatori logici la nivel de bit: &=, |=, ^=
Operatori de decalare: <<=, >>=
Faptul c atribuirea este privit ca un operator binar, permite ca acetia s formeze expresii care au
atribuite valori. Astfel
variabil = expresie;
este o expresie ce are ca valoare, valoarea expresiei din dreapta semnului # . Acest lucru permite
atribuirea n lanpreciznd c asociativitatea operatorului de asignare este de la dreapta la stnga:


var
1
= var
2
= ... = var
n
= expresie;

prin care cele n variabile capt valoarea expresiei din partea dreapt.
Spre exemplu
i = j = k = l = 1;
este o construcie valid n C; prin aceasta cele patru variabile i, j, k, l capt valoarea 1.
2.4.6. Operatorul condiional
Acesta este singurul operator ternar al limbajului C. Forma general a sa este:

op1 ? op2 : op3;

unde op1,op2,op3 sunt operanzi. Dac op1 are valoarea adevrat, expresia este egal cu op2 iar dac op1
are valoarea fals, expresia este egal cu op3.
Exemplu:

max = (a > b) ? a : b;

este o expresie echivalent cu construcia:

if (a > b)
max = a;
else
max = b;
Operatorul condiional se noteaz cu ?: i are asociativitatea de la dreapta la stnga.
2.4.7. Operatorul virgul
Forma general a unei expresii ce utilizeaz acest operator este:
expresie
1
,expresie
2
, ...

Gheorghe GRIGORA

18
Expresiile sunt evaluate de la stnga la dreapta iar valoarea ntregii expresii este valoarea (i tipul, se
nelege) expresiei ultime ce apare n acest ir.
O asemenea construcie apare frecvent n instruciuni for pentru realizarea mai multor aciuni:

for(i = 0,j = 0, i < 100; i++, j++)
for(i = 0,j = n-1, i < j; i++, j--)
2.4.8. Precedena operatorilor
Asociativitatea i precedena operatorilor indic ordinea n care se evalueaz subexpresiile ntr-o
expresie. Pentru limbajul C, operatorilor unari, operatorul condiional i cel de atribuire li se aplic
asociativitatea la dreapta pe cnd tuturor celorlali li se aplic asociativitatea la stnga. Am vzut c
operatorii primari de parantetizare pot schimba asociativitatea operatorilor. Precedena operatorilor
limbajului C este dat n tabelul nr. 6.
Tabelul nr.6.

Operator Funcia (semnificaia) Descrierea
::

::
Acces explicit la o variabil global
(unar)
Acces explicit la o clas (binar)

, .
[]
( )
sizeof
Selectarea unui membru
Indexarea unui tablou
Apel la o funcie
Lungimea n bii

-> , .
~
!
+, -
*
&
()
new,delete
Incrementare, decrementare
Negare pe bii
Negare logic
Plus, minus unari
Acces la o variabil
Adresa unei variabile
Conversie de tip (cast)
Operatori de gestiune a memoriei

->* , .* Selectarea unui membru
*, /, % Operatori multiplicativi
+ , - Operatori aritmetici
>> , << Operatori de decalare
<,<=, >, >= Operatori relaionali
==, != Egalitate, inegalitate
& Conjuncie pe bit
^ Sau exclusiv pe bit
| Sau (disjunctiv) pe bit
&& Conjuncie logic
|| Disjuncie logic
?: Afectare condiional
=,*=,/=, %=
+=, -=, <<=,
>>=
&=, ^=, |=

Operatori de asignare compus


, Operatorul virgul

Cap 3 FUNCTII








3.1. Definirea unei funcii
3.2. Returnarea unui apel
3.3. Funcii cu un numr variabil de parametri
3.4. Sfritul execuiei unui program
3.5. Apelul i transmiterea parametrilor
3.6. Funcia principal main


n limbajul C - spre deosebire de Pascal sau alte limbaje - nu exist noiunile distincte de
procedur i de funcie. n C exist doar funcii care returneaz o valoare. Este posibil definirea de
funcii care s retuneze valoarea vid: n acest caz tipul valorii returnate este void.
n general, utilizarea unei funcii permite:
- descompunerea unei secvene lungi de procesare a informaiei ntr-o mulime de secvene mici de
transformri de baz ale informaiei;
- furnizarea ctre ali programatori a unor elemente de baz de nivel nalt; detaliile acestor elemente
rmn ascunse pentru utilizator. Aceste elemente de nivel nalt ofer o claritate n plus programului
global i permite - relativ uor - modificri ulterioare ale acestuia.

3.1. Definirea unei funcii

Definiia unei funcii are urmtoarea sintax:







n aceast definiie, tip este unul din cuvintele rezervate care definete tipul funciei, respectiv
tipul valorii returnate de un apel la aceast funcie. Dac aceast specificare lipsete, tipul implicit al
funciei este int. Funciile care returneaz n programul apelant valoarea vid se declar de tip void.
Numele unei funcii este un identificator i acesta trebuie s respecte aceleai reguli ca cele
referitoare la numele unei variabile. S precizm c nu se poate defini o funcie n interiorul altei
funcii.
Mulimea funciilor unui program poate fi partiionat n mai multe fiiere care pot fi compilate
separat. Limbajul C permite de asemenea utilizarea unor funcii predefinite (printf, getc, etc.), funcii ce
se gsesc n bibliotecile sistemului. Apelurile la aceste funcii sunt gestionate n faza de editare a
legturilor.
Aa cum o variabil trebuie declarat nainte de a fi utilizat ntr-o expresie, o funcie trebuie
declarat nainte de a fi apelat. Declararea unei funcii const n a da signatura funciei. Signatura unei
tip nume (lista parametri)
{
declaratii (de variabile);
instructiuni;
}
Gheorghe GRIGORA

20
funcii definete att tipul su (tipul valorii returnabile) ct i numrul i tipul argumentelor sale. Exist
dou moduri de a declara o funcie:
- implicit: n definiia funciei, linia de nceput conine tipul su i argumentele sale (numr i tip);
- explicit: printr-o instruciune ce descrie signatura sa n cazul n care se face apel la o funcie
descris ntr-un fiier separat sau n cazul n care apelul la funcia respectiv precede declaraia funciei n
acelai fiier.
Iat cteva instruciuni de declarare a unei funcii:
long int cod (const char *, int);
char* decod (long int);
void schimbare (int , int);
int strlen (const char* s);
int funct ( );

n ultima linie avem un exemplu de funcie fr parametri (numrul parametrilor este zero).

3.2. Returnarea unui apel
Sintaxa instruciunii de returnare a valorii unei funcii este:




O funcie f returneaz o valoare n corpul funciei din care s-a fcut apel la f, prin instruciunea
return (plasat n corpul lui f). Valoarea expresiei "expresie" va fi returnat i poate fi utilizat n
programul apelant. Tipul acestei expresii trebuie s fie acelai cu tipul funciei. O funcie care returneaz
valoarea vid (funcie de tip void) poate conine instruciunea "return" fr argument sau poate omite
aceast instruciune.

3.3. Funcii cu un numr variabil de parametri

Exist funcii care pot avea un numr nedeterminat de parametri. Un exemplu la ndemn l ofer
funciile sistemului: printf, scanf, etc.:
printf ("Un apel cu un singur argument \n");
printf("x\%f\n",x);/*Un apel cu 2 argumente */
printf ("a\%d,b\%d\n",a,b); /*3 argumente */.

Definirea unor astfel de funcii se face printr-o sintax de forma:

int printf (char *, ... );

care n C++ se numete "elips".

3.4. Sfritul execuiei unui program



Funcia "exit" este o funcie sistem care termin execuia unui program. Acesta este singurul exemplu
de apel la o funcie care nu returneaz nimic: sistemul oprete execuia programului i raporteaz valoarea
return expresie;
exit (valoare);
Programare_ Limbajul_C

21
transmis la apel. Aceast valoare poate fi util atunci cnd programul este executat n interiorul unei linii
de comand a interpretorului de comenzi. Prin convenie, valoarea nul (0) semnific faptul c programul
se termin normal iar o valoare nenul (1 sau -1) semnific faptul c s-a produs o eroare. n absena unei
instruciuni exit, valoarea implicit a codului returnat la sfritul execuiei unui program este 0.
3.5. Apelul i transmiterea parametrilor

Apelul unei funcii se face prin:

nume (list _ parametri_actuali);

dac funcia este declarat fr tip i prin folosirea numelui funciei urmat de lista de parametri actuali
ntr-o expresie (n care este permis tipul ei) atunci cnd funcia este declarat cu tip .
Ordinea evalurii parametrilor este n general de la stnga la dreapta dar acest lucru nu este
garantat de orice compilator, nct trebuiesc luate msurile corespunztoare. De pild, secvena:
int n = 10;
printf ("%d %d \n", n++, n);
tiprete (cu unele compilatoare) 10 10 i nu 10 11.
S precizm c n C nu exist dect un singur mod de transmitere a parametrilor i anume
transmiterea prin valoare. Asta nseamn c parametrul actual (de la apel) i parametrul formal
corespunztor (declarat n antetul funciei) sunt dou variabile distincte. Modificrile efectuate asupra
parametrilor formali nu au dect un efect local care nu este vizibil n afara funciei. Asta nseamn c o
funcie nu poate modifica parametrii actuali..
Un exemplu clasic al consecinei acestui mod de transfer al parametrilor este ilustrat mai jos:

void schimba1(int x, int y){
int temp = x;
x = y,
y temp;
}
main ( ){
int a = 1, b = 2;
schimba1(a,b);
printf ("a = %d, b =%d", a, b);
}
Apelul funciei schimba1 n funcia main nu are efectul scontat: prin apelul la printf se tipresc
valorile 1 i 2 pentru a respectiv b. Pentru nlturarea acestui efect este posibil simularea unui mod de
transmitere prin referin, punnd drept parametri actuali valorile adreselor variabilelor ce trebuiesc
modificate. n C adresa unei variabile poate fi specificat ntr-o variabil de tip "pointer" (de care vom
vorbi mai trziu). Funcia schimba2 care simuleaz transmiterea parametrilor prin referin este:

void schimba2(int* x , int* y){
int temp = *x;
*x = *y;
*y = temp;
}

iar apelul n funcia main se face prin:
schimba2 (&a , &b);
S facem precizarea c i n cazul funciei schimba2 transmiterea parametrilor se face prin valoare:
am simulat aici transferul prin referin ce ar fi trebuit s se fac n cazul funciei schimba1. Singura
Gheorghe GRIGORA

22
diferen este c valoarea transmis prin parametrii actuali &a,&b este adresa lui a respectiv b i prin
funcia schimba2 se modific valorile refereniate. Aadar, pentru schimbarea coninutului unor variabile
printr-o funcie, parametrul corespunztor trebuie s fie de tip pointer. Argumentele de tip pointer vor fi
utilizate de asemenea pentru transmiterea ca parametru a unei variabile de tip structur (vezi Cap.7)
precum i pentru limitarea numrului de valori ce trebuiesc puse n stiva de apel a execuiei unui
program. n capitolul 6 vom discuta mai pe larg modul de transmitere al parametrilor de tip tablou ca
argumente ale unei funcii.

3.6. Funcia principal main






Funcia main este singura funcie absolut necesar ntr-un program C. Aceasta definete punctul
de intrare n execuia programului. Parametrii funciei main permit recuperarea argumentelor transmise
din momentul execuiei programului. Valoarea ntreag returnat de funcia main este valoarea transmis
mediului la sfritul execuiei programului (vezi funcia exit). Utilizarea instruciunii return precizeaz
condiia de terminare ( 0 - succes, 1- eroare).
Parametrii disponibili la apelul funciei main sunt:
- argc: numrul argumentelor din linia de comand (inclusiv numele programului);
- argv: un tablou de pointeri ctre fiecare din argumentele liniei de comand; n particular, arg[0]
conine numele programului executabil.
n cazul n care programatorul nu dorete s utilizeze argumentele (parametrii) transmise la
execuie, este permis utilizarea funciei main fr parametri: int main( ) este o declaraie valid pentru
funcia main.
n general, la lansarea unui program, linia de comand conine numele programului urmat de o
list de parametri:
nume-program p
1
, p
2
, ..., p
n

atunci argc va avea valoarea n^1 iar argv va fi un tablou ce conine pointeri astfel:

0 nume - program
1 p
1

:
.


n p
n

0

Iat un exemplu de utilizare a acestor argumente :
Programul 2
main (int argc, char* argv[ ] ){
if (argc<2)
printf ("Nu exista argumente in aceasta executie ! \n");
else {
printf ("Argumentele executiei sunt: \n");
for (i 1; i < argc; i++)
int main(int argc,char* argv [ ])
{
instructiuni;
}
Programare_ Limbajul_C

23
printf ("%s", argv [i] );
}
}

Dac acest program are numele prg2 atunci linia de comand:

prg2

produce scrierea mesajului:
Nu exista argumente in aceasta executie !
iar linia de comand:

prg2 Iata niste argumente !

produce scrierea mesajului:

Iata niste argumente !
Gheorghe GRIGORA

24

Cap 4 FUNCII DE INTRARE IEIRE





4.1 Fluxuri i fiiere
4.2 Accesul la fiiere. Tipul FILE
4.3 Funcii de intrare /ieire pentru caractere
4.4 Scrierea cu format
4.5 Citirea cu format



4.1.Fluxuri i fiiere
Sistemul de fiiere al limbajului C este conceput pentru a lucra cu o mare varietate de dispozitive,
inclusiv cu terminale, uniti de disc sau de band etc.. Dei fiecare dintre acestea este foarte diferit de
celelalte, sistemul de fiiere le transform pe fiecare ntr-un dispozitiv logic numit flux. Fluxurile sunt
independente de dispozitivele iniiale , nct aceeai funcie care scrie date pe un fiier de pe disc poate fi
folosit pentru a scrie date pe o alt categorie de dispozitive: consola, imprimanta. Aadar dispozitivul
fizic pe care se scriu datele se numete fiier iar abstractizarea acestuia se numete flux (sau stream).
Exist dou tipuri de fluxuri:
Fluxul text este o scven de caractere. Standardul ANSI C permite organizarea unui flux text n
linii care se ncheie cu un caracter linie nou(n). Acesta din urm este opional pe ultima linie i este
determinat de modul de implementare. Datorit posibilelor conversii s-ar putea ca numrul de caractere
scrise/citite s difere de numrul de caractere existente pe dispozitivul extern.
Fluxul binar este o secven de octei cu coresponden biunivoc fa de octeii existeni pe
dispozitivul extern: numrul de octei scrii/citii este acelai cu numrul acestora de pe dispozitivul
extern.
Un fiier n limbajul C poate fi un terminal, o imprimant sau o zon (fiier) pe disc. Un flux se
poate asocia unui fiier executnd o operaie de deschidere: odat deschis, pot avea loc transferuri
de informaii ntre fiier i programul curent n execuie. Unificarea sistemului de intrare/ieire n
C se face prin pointerii de fiier. Un pointer de fiier este un pointer ctre informaia care
definete diverse caracteristici ale unui fiier(nume, stare, poziie curent etc). Pointerul de fiier
identific un anumit fiier i este folosit de ctre fluxul asociat pentru a conduce operaia de
intrare/ieire.
Pentru a putea utiliza ntr-un program funciile standard de intrare/ieire trebuie scris la nceputul
acestui program o directiv "include" care are ca argument numele fiierului antet ce conine definiiile
acestor funcii: stdio.h .


Orice program C ncepe execuia prin deschiderea unitilor de intrare/ieire standard:






# include <stdio.h>
stdin : unitatea standard de intrare
stdout : unitatea standard de ie[ire
stderr : unitatea de eroare
stdprn : unitatea standard de ie[ire prn (imprimant\)
Programare_ Limbajul_C

25

Aceste uniti standard sunt asociate, n lipsa altor indicaii, tastaturii calculatorului (intrare) i
ecranului (ieire i eroare). Sistemul de fiiere ANSI C este compus din mai multe funcii legate una de
alta. Cele mai frecvent folosite dintre acestea sunt date n Tabelul 5 i vor fi prezentate n continuare.

Tabelul 5
NUME OPERA}IE
fopen( ) Deschide un fiier
fclose( ) nchide un fiier
putc( ) Scrie un caracter ntr-un fiier
fputc( ) Analog lui putc()
puts( ) Scrie un ir pe ecran
fputs( ) Scrie un ir pe fiier
getc( ) Citete un caracter dintr-un fiier
fgetc( ) Analog lui getc( )
gets( ) Citete un ir de la tastatur
fgets( ) Citete un ir din fiier
fseek( ) Caut un anumit octet ntr-un fiier
printf( ) Scrie la ieirea standard
fprintf( ) Analogul pentru fiiere al funciei printf( )
scanf( ) Citete din intrarea standard
fscanf( ) Analogul pentru fiiere al funciei scanf( )
feof( ) Returneaz adevrat dac se atinge sfritul fiierului
ferror( ) Returneaz adevrat dac survine o eroare
rewind( ) Iniializeaz indicatorul de poziie al fiierului la nceput
remove( ) terge un fiier
fflush( ) Golete coninutul unui fiier
4.1. Accesul la fiiere. Tipul FILE
Conceptul de baz pentru intrri/ieiri standard este cel de pointer la fiier. Bibliotecile standard C
ofer o serie de funcii pentru operaii de intrare/ieire orientate pe fiiere. Dispozitivele standard de
intrare (tastatura) i de ieire (ecranul) sunt vzute tot ca fiiere cu pointerii stdin i stdout. Aceste fiiere
(stdin, stdout) pot fi orientate i ctre alte dispozitive sau fiiere.
Declararea unei variabile de tip "pointer la fiier" se face folosind tipul FILE definit n fiierul
antet stdio.h i are forma:



unde pointer_la_fiier este un identificator (numele pointerului).
Deschiderea unui fiier se face prin funcia fopen care returneaz ca rezultat un pointer la un
descriptor de fiier. Acest dispozitiv este gestionat de sistem pentru a asigura intrrile i ieirile efectuate
n program.



Aici, fiier este un ir de caractere (identificator) ce desemneaz numele extern al fiierului iar mod este
un ir de caractere ce descrie modul de deschidere al fiierului. Modurile posibile de deschidere (deci
irurile de caractere ce constituie parametrul lui fopen) sunt date n Tabelul 6.
FILE* pointer_la_fi[ier
FILE* fopen(const char* fi[ier,const char* mod)
Gheorghe GRIGORA

26
Tabelul 6.
mod
Semnificaia
"r" Citire
"w" Creare (schimbare) pentru scriere
"a" Adugare la sfritul fiierului (existent)
"r+" Actualizare (citire/scriere)
"w+" Schimbare pentru actualizare
"a+" Actualizare cu scriere la sfritul fiierului (existent)

Facem precizarea c, deschiderea unui fiier existent n modurile "w" sau "w+" produce pierderea
coninutului su de pn atunci. Dac funcia fopen returneaz o valoare nenul, aceasta indic
faptul c deschiderea s-a efectuat corect. Valoarea returnat este un pointer la un descriptor de fiier
valid, valoare ce va fi utilizat n apelul la funciile de intrare/ieire. Dac deschiderea nu s-a efectuat
corect valoarea returnat este NULL(pointer la informaia nul) . Acest lucru poate fi folosit pentru
tratarea erorilor la deschiderea fiierului.
nchiderea unui fiier se face prin apelul la funcia fclose:



Funcia returneaz EOF n caz de eroare i 0 n caz normal. Prin nchidere se elibereaz descriptorul de
fiier, se actualizeaz fiierul pe disc i nceteaz conexiunea logic ntre pointer i fiier.
Apelul la fclose se poate face prin:





Fiierele pot fi reasignate prin program folosind funcia freopen:



Apelul la aceast funcie nchide fiierul cu pointerul "pf", deschide fiierul cu numele
nume_fiier n modul de acces "mod", atribuind pointerul "pf" la acest fiier. Aceasta permite
redireciona-rea dispozitivelor periferice prin program. Programul urmtor ilustreaz acest fapt.
Programul 3

# include <stdio.h>
main ( ){
printf ("Mesaj scris pe monitor \n");
if(freopen("iesire.dat","w+",stdout)==NULL) {
fprintf (stderr, "Eroare la reasignare \n");
exit (1);
}
printf ("Mesaj scris in fisierul iesire.dat \n");
fclose (stdout);
if (freopen ("CON", "wt", stdout) == NULL) {
fprintf (stderr, "eroare la reasignarea lui stdout la CON\n");
exit (1);
int fclose (FILE* pointer_la_fi[ier)
int cod;
FILE* pointer_la_fi[ier

cod = fclose (pointer_la_fi[ier)
FILE* freopen (const char* nume_fisier,
const char* mod, FILE* pf);
Programare_ Limbajul_C

27
}
printf ("Mesaj scris din nou pe monitor \n");
}

Limbajul C dispune i de posibilitatea:
tergerii de fiiere prin funcia remove:


redenumirii unui fiier:



crerii unui fiier temporar:

FILE*tmpfile (void);

4.2. Funcii de intrare/ieire pentru caractere

int fgetc(FILE* flux);

char c;
FILE* pointer_la_fiier;

c = fgetc(pointer_la_fiier);

Funcia fgetc returneaz valoarea ntreag a caracterului urmtor din fiierul pointat cu
pointer_la_fiier sau constanta EOF n caz de eroare sau sfrit de fiier.
Funcia fputc scrie un caracter la sfritul fiierului pointat prin pointer_la_fiier. n caz de eroare
este returnat valoarea EOF. Exist de asemenea dou funcii getchar i putchar care permit exprimarea n
C, simplificat, a scrierii apelului la fgetc i fputc n cazul n care intrarea respectiv ieirea este cea
standard : stdin respectiv stdout.

int fputc(char c, FILE* flux);

int cod;
char c;
FILE* pointer_la_fiier;

cod = fgetc(c, pointer_la_fiier);

Spre exemplu:
c = getchar ( ); este echivalent cu:
c = fgetc (stdin);
iar putchar (c); este echivalent cu:
fput (c, stdout);.



int remove(const char* nume_fi[ier);
int rename (const char* nume_nou,
const char* nume_vechi );
Gheorghe GRIGORA

28
4.3. Scrierea cu format

Funciile de scriere cu format permit afiarea sub forma unui ir de caractere a diverselor valori.
Acestea pot fi transmise la ieirea standard, ntr-un fiier sau ntr-un ir de caractere.

int printf(const char* ir_format, );
int fprintf(FILE* flux,const char* ir_format,);
int sprintf(char* s,const char* ir_format,);

Funcia printf se utilizeaz pentru afiarea la ieirea standard, fprintf pentru scrierea ntr-un fiier,
iar sprintf pentru scrierea ntr-un ir de caractere.
Formatul "ir-format" este un ir de caractere ce conine fie caractere ordinare fie directive de
conversie pentru transformarea valorii unei variabile ntr-un ir de caractere
Caracterele ordinare sunt transmise la ieire aa cum apar ele pe cnd directivele de conversie
indic formatul de ieire pentru argumentele transmise n apelul funciei. O directiv se specific prin
caracterul % urmat de o secven de caractere ce identific formatul. Aceast secven conine, n ordine:
eventual unul sau mai muli indicatori ce modific semnificaia conversiei. Indicatorii disponibili n C
sunt:

- : rezultatul conversiei se va cadra la dreapta;
+ : la formatul de ieire va fi ataat semnul + sau - cu excepia cazului cnd primul caracter nu este
semn;
#: desemneaz un format alternativ. Dac formatul este octal se va aduga un o naintea numrului;
dac acesta este hexazecimal se va aduga ox sau OX naintea numrului. Pentru formatele flotante
( e, E, f, g, G) rezultatul se va afia cu un punct zecimal; n plus , la g sau G se vor afia i zerourile
nesemnificative de dup punctul zecimal.

eventual un numr pentru a indica dimensiunea minimal a cmpului n care se va afia. Dac
dimensiunea rezultat prin conversie este mai mic, caracterele se vor cadra la stnga (implicit) sau la
dreapta (pentru -). Se pot utiliza i dimensiuni variabile: se utilizeaz '*' n loc de numrul ce indic
dimensiunea iar variabila respectiv se pune n lista de argumente.
eventual caracterul l care precizeaz c numrul ce urmeaz a fi afiat este un "ntreg lung" (long
integer).
caracterul ce indic formatul conversiei. Formatele ce se folosesc n C sunt date n Tabelul 7.

Tabelul 7. Formatele de conversie utilizate de printf.
CARACTE
R
TIP
ARGUMEN
T
CONVERSIA
d sau i int ntreg n notaie zecimal cu semn;
o int ntreg n notaie octal fr semn;
x, p sau X int ntreg n notaie hexa fr semn; pentru x sau p se folosesc literele
a, b, c, d, e, f, iar pentru X literele A, B, C, D, E, F;
u int ntreg n notaie zecimal fr semn
f float sau
double
real n notaie zecimal sub forma
[-]mmm.dddddd sau numrul de d este dat de argumente de
precizie (implicit acesta este 6);
Programare_ Limbajul_C

29
e sau E float sau
double
real n notaie zecimal sub forma:
[-]m.dddddde xx sau
[-]m.ddddddE xx.
Numrul de d este dat de argumente de precizie (implicit este 6);
g sau G float sau
double
afiare n acelai stil cu e dac exponentul este -4 sau superior
preciziei; n stil f n caz contrar;
c int afiarea unui singur caracter dup conversie n unsigned char;
s char* afiarea unui ir de caractere pn la ntlnirea caracterului '@0'
(sfrit de ir) sau pn cnd numrul de caractere este egal cu
numrul de precizie;
p void* afieaz argumentul n notaia pointer;
n int* nu exist nici conversie nici afiare n acest caz: este vorba de
referine la un pointer la un ntreg n care se va stoca numrul de
caractere afiate pn n prezent;
% Permite afiarea caracterului %


Exemple
Urmtoarele programe ilustreaz folosirea formatelor de afiare la apelul funciei printf rezultatele
sunt ilustrate la sfritul fiecrui program.
Programul 4

# include <stdio.h>
int main ( )
{
int i = 123;
long int l = 123456789L;
unsigned int ui = 45678U;
unsigned long int ul = 987654321UL;
double d = 123.45;
printf(" Forma zecimala:\n");
printf(" i = %d\n", i);
printf(" l = %ld\n", l);
printf(" ui = %u\n", ui);
printf(" ul = %lu\n\n", ul);

printf(" Forma octala:\n");
printf(" ui = %o\n", ui);
printf(" ul = %d\n", i);
printf(" i = %lo\n\n",ul);

In urma execuiei se va afia:
Forma zecimala:
i = 123
l = 123456789
ui = 45678
ul = 987654321

Gheorghe GRIGORA

30
Forma octala:
ui = 131156
ul = 7267464261


printf("Scrierea hexazecimala:\n");
printf(" ui = %X\n", ui);
printf(" ul = %lX\n\n", ul);

printf("Afisarea semnului:\n");
printf("|% d| |%+d| |%d|\n",-123,-123,-123);
printf("|% d| |%+d| |%d|\n", 123, 123, 123);

printf("Afisare in octal si hexazecimal:\n");
printf("|%x| |%#x|\n", 123, 123);
printf("|%X| |%#X|\n", 123, 123);
printf("|%o| |%#o|\n", 123, 123);
printf("\n");

n urma execuiei se va afia:
Scrierea hexazecimala:
ui = B26E
ul = 3ADE68B1

Afisarea semnului:
|-123| |-123| |-123|
| 123| |+123| |123|

Afisare in octal si hexazecimal:
|76| |0x7b|
|7B| |0X7B|
|173| |0173|


/*Specificarea lungimii campului si a
**numarului de cifre*/
printf("|%.4d|\n", 123);
printf("|%+.4d|\n", 123);
printf("|%.4X|\n", 123);
printf("\n");

printf("|%5d| |%-5d|\n", 123, 123);
printf("|%+5d| |%+-5d|\n",123, 123);
printf("|%#5d| |%#-5d|\n",123, 123);
printf("\n");

printf("|%+6.4d|\n", 123);
printf("|%+6.4o|\n", 123);
printf("|%+6.4X|\n", 123);
printf("\n");

Programare_ Limbajul_C

31


Iat ce se va afia:
|0123|
|+0123|
|0X007B|

| 123| |123 |
| +123| |+123 |
| 0X7B| |0X7B |

| +0123|
| 0173|
|0X007B|

/* Afisarea numerelor in virgula flotanta*/
printf("|%f|\n" 3.14157);
printf("|%.3f|\n" 3.14157);
printf("|%.0f|\n" 3.14157);
printf("|%#.0f|\n" 3.14157);
printf("|%E|\n" 3.14157e123);
printf("|%E|\n" 3.14157e123);
printf("|%.3E|\n" 3.14157e123);
printf("|%.0E|\n" 3.14157e123);
printf("|%#.0E|\n" 3.14157e123);

printf("|%f|\t|%G|\n", 3.1, 3.1);
printf("|%E|\t|%G|\n", 3.1e10, 3.110);

printf("|%G|\t|%G|\n", -0.0001, 0.00001);
printf("|%f|\t|%G|\n", 3.1e5, 3.1e7);
printf("|%.11G|\t|%.11G|\n", 3.1e6, 3.1e11);
return0;
}
Iat ce se va afia de aceast dat:
|3.141570|
|3.142|
|3|
|3.|
|3.141570E+123|
|1.142E+123|
|3E+123|
|3.E+123|
|3.100000| |3.1|
|3.100000E+10| |3.1E+10|
|-1.0001| |1E-05|
|310000| |3.1E+07|
|3100000| |3.1 E+11|

Gheorghe GRIGORA

32
4.5. Citirea cu format

Funciile de citire cu format permit interpretarea unui ir de caractere ca o secven de valori n
concordan cu un format dat. Rezultatul interpretrii este ncrcat la adresele ce se dau ca argumente la
apelul funciilor de citire. Aceste funcii, corespunztoare citirii de la intrarea standard, de la un fiier
respectiv dintr-un ir de caractere sunt:

int scanf (const char* ir_format,);
int fscanf (FILE* flux, const char* ir_format,);
int sscanf (char* s, const char* ir_format, );

Formatul (ir_format) este un ir de caractere care poate conine:
- caractere de spaiere sau tabulare care vor fi ignorate;
- caractere ordinare (n afar de %) care trebuie s corespund urmtorului caracter citit;
- directive de specificare a formatului, care ncep cu '%'.
Directivele pentru specificarea unui format sunt utilizate pentru precizarea conversiei urmtorului
cmp citit. n general, rezultatul citirii este memorat n variabila corespunztoare din lista argumentelor
funciei. Se poate face o omisiune de afectare, punnd caracterul '*' n directiv (de ex. %*s): n acest caz
cmpul este citit dar nu-i memorat.
Cmpul ce urmeaz a fi convertit (ce este citit) se ntinde pn la primul spaiu sau numrul de
caractere din acest cmp este specificat n format.
Caracterele pentru specificarea unui format de citire sunt date n Tabelul 8.

Tabelul 8. Formatele de conversie pentru scanf

CARACTER FORMAT DE INTRARE TIPUL ARGUMENTULUI
d ntreg n notaie zecimal; int*
i ntreg n notaie octal(primul caracter 'o')
sau hexa (primul caracter 'Ox' sau 'OX');
int*
o ntreg n notaie octal; int*
u ntreg fr semn n notaie zecimal; unsigned int*
x ntreg n notaie hexa; int*
c caracter. Implicit se citete un singur
caracter. Dac este indicat un numr q
(%qC) atunci sunt citite cel mult q
caractere, citindu-se i spaiile care, de
obicei sunt ignorate. Pentru citirea
urmtorului caracter diferit de spaiu se
folosete %ls.
char*
s ir de caractere: se citete pn la ntlnirea
unui spaiu sau pn la atingerea numrului
de caractere indicat;
char*
e, f, g real n notaie virgul flotant; float*
double*
p valoarea unei adrese; void*
n scrie n argument numrul de caractere
citite pn acum. Nu se face nici o operaie
de citire;
int*
Programare_ Limbajul_C

33
[...] citete caracterele din intrare att timp ct
acestea aparin muli-mii indicate n [ ].
Adaug la argument caracterul '@0' (sfrit
de ir);
char*
[

...] citete caracterele din intrare att ct


acestea nu sunt n mulimea indicat n [ ]
dup care adaug '@0';
char*
% permite indicarea caracterului literal '%'.
-

Programul urmtor ilustreaz utilizarea formatelor de intrare.
Programul 5

#include <stdio.h>
int main(){
int i1, i2, i3;
char c1, c2, c3;
char s1[10],s2[10],s3[10];
char s4[5], s5[5], s6[5];
printf("Introduceti trei numere intregi: ");
scanf("%d%d%d", &i1, &i2, &i3);
printf("Ati introdus:%d\t%d\t%d\n",i1,i2,i3);

printf("Introduceti trei numere intregi: ");
scanf("%4d%3d%4d", &i1, &i2, &i3);
printf("Ati introdus:%d\t%d\t%d\n",i1,i2,i3);

printf("Introduceti un text: ");
scanf("%s%s%s, s1, s2, s3");
printf("s1=|%s|\ts2=|%s|\ts3=|%s|\n",s1,s2,s3);

printf("Introduceti un text: ");
scanf("%4s %4s %4s", s1, s2, s3);
printf("s1=|%s|\ts2=|%s|\ts3=|%s|\n",s1,s2,s3);
scanf("%c%c%c", &c1,&c2,&c3);
printf("c1= |%c|\tc2=|%c|\tc3=|%c|\n"c1,c2,c3);
printf("Introduceti un text: ");
scanf("%4c%4c%4c", s4,s5,s6);
s4[4] =s5[4] =s6[4] ="\0";
printf("s4=|%4s|\ts5=|%4s|\ts6=|%4s|\n",s4,s5,s6) return 0;
}

Rezultatul unei execuii a acestui program este:

Introduceti trei numere intregi: 5454 -9988 0
A-ti introdus numerele: 5454 -9988 0
Introduceti trei numere intregi: 5454998 390
A-ti introdus numerele: 5454 998 390
Introduceti un text: Iata un exemplu!
s1=|Iata| s2=|un| s3=|exemplu!|
Gheorghe GRIGORA

34
Introduceti un text: Iata un exemplu!
s1=|Iata| s2=|un| s3=|exem|
c1=|p| c2=|l| c3=|u|
Introduceti un text: Iata un exemplu!:
s4=|!
Ia| s5=|ta u| s6=|n ex|


Cap 5 INSTRUCIUNI DE CONTROL





5.1. Instruc]iunile if
5.2. Instruc]iunea switch
5.3. Instruc]iunea while
5.4. Instruc]iunea do...while
5.5. Instruc]iunea for
5.6. Instruc]iunea break
5.7. Instruc]iunea continue
5.8. Instruc]iunea go to
5.9. Exerci]ii
5.10. Solu]ii la exerci]ii






Limbajul C ofer\ urm\toarele tipuri de instruc]iuni:
declara]ii;
expresii;
instruc]iuni de control;
blocuri de instruc]iuni;
defini]ii de func]ii.
~n capitolul 2 am v\zut cum se construiesc expresiile `n C. O expresie urmat\ de caracterul ';' este
o instruc]iune `n C. ~n general o instruc]iune se termin\ prin ';'. Urm\toarele construc]ii sunt instruc]iuni C
de tip expresii:
i = 1;
j ++;
++ k;
cod = printf ("%d\n", alpha);
Un bloc este un [ir de instruc]iuni `ncadrat `n acolade: { [i } (care joac\ rolul de begin ... end din
alte limbaje). Un bloc este echivalent cu o instruc]iune. Iat\ un bloc `n C:
{
i = 1;
j = 2;
s [i] = t [j];
i ++;
j --;
s [i] = t [j];
}
Instruc]iunile de declarare a variabilelor (declara]iile) sunt de forma(vezi [i paragraful 2.3) :

tip identificator;
tip identificator = valoare;

Vom trece `n revist\ `n continuare instruc]iunile de control ale limbajului C.
Gheorghe GRIGORA

36
5.1. Instruciunea if
if (expresie) if ( expresie )
instruc]iune1 instruc]iune1
else
instruc]iune2
Ca [i `n alte limbaje de programare aceast\ instruc]iune permite alegerea `ntre dou\ alternative.
Tipul expresiei de dup\ cuv=ntul rezervat if poate fi `ntreg (char, short, int sau long), real (float sau
double) sau tip pointer. Expresia se pune obligatoriu `ntre paranteze iar partea "else instruc]iune2;" este
facultativ\. Semantica acestei instruc]iuni este uzual\: dac\ valoarea expresiei "expresie" este nenul\
(ceea ce `nseamn\ "true") atunci se execut\ instruc]iune1 iar dac\ aceast\ valoare este nul\ ("false") se
execut\ instruc]iune2 (dac\ aceasta exist\).
Exemple:
if (x>y)
x = x-y;
else
y = y-x;

if ((c = getchar ( ) ) ! = EOF)
putchar (c);
if (x>y)
printf("%d este cel mai mare\n", x);
else
printf("%d este cel mai mare\n", y);

if (x>y)
printf("primul numar este cel mai mare\n");
else if (x==y)
printf("numerele sunt egale\n");
else
printf("al doilea numar este mai mare\n");

if ( a < b ) {
a += 2;
b += 1;
};
else
a -=b;
Aten]ie! ~n acest ultim exemplu este o eroare de sintax\: alternativa else nu poate fi asociat\ cu if pentru
c\ `naintea sa ( dup\ } ) apare caracterul ; care reprezint\ instruc]iunea vid\! Apare [i problema
ambiguit\]ii (a[a zisa problem\ dangling else):
if ( a == 1 )
if ( b == 2 )
printf ( b este egal cu doi\n);
else
printf ( b nu este egal cu doi\n);
C\rui if `i este ata[at else? Limbajul C rezolv\ problema aceasta prin ata[area lui else celui mai apropiat
if, deci exemplul este interpretat astfel:
if ( a == 1 )
if ( b == 2 )
printf ( b este egal cu doi\n);
Programare_ Limbajul_C

37
else
printf ( b nu este egal cu doi\n);


5.2. Instruc]iunea switch
switch(expresie){
case const
1
:
instruc]iune
1

case const
2
:
instruc]iune
2


case const
n
:
instruc]iune
n

default:
instruc]iune
}

Instruc]iunea switch este o structur\ de control cu alegeri multiple ce `nlocuie[te o succesiune de
alternative de tip if. Aceasta permite execu]ia unei anumite ramuri `n func]ie de valoarea expresiei
"expresie" din parantez\, care poate fi de tip `ntreg, caracter sau enumerare. Dac\ expresia are valoarea
const
1
atunci se execut\ instruc]iune
1
[i toate cele ce urmeaz\ dup\ aceasta p=n\ la `nt=lnirea unei
instruc]iuni "break", dac\ valoarea sa este const
2
atunci se execut\ instruc]iune
2
[i urm\toarele p=n\ la
"break" etc. Cazul default este facultativ; dac\ expresia nu are nici una din valorile indicate prin cons
1
,
cons
2
, ..., se execut\ instruc]iunile desemnate de ramura "default", dac\ aceasta exist\.
Exemplu:
switch (getchar ( ) ) {
case 'a':
printf ("s-a citit litera a\n");
break;
case 'b':
printf ("s-a citit litera b\n");
break;
case 'c':
printf ("s-a citit litera c\n");
break;
default:
printf ("s-a citit altceva decat a, b sau c\n");
break;
}

~n acest exemplu, pe fiecare ramur\ s-a folosit instruc]iunea break. Se `n]elege c\, `n cazul `n care
exist\ pe una din ramuri alte instruc]iuni de control, break poate lipsi (vezi exemplul de la insrtuc]iunea
for).



Gheorghe GRIGORA

38
5.3. Instruciunea while

while(expresie)
instruc]iune

Expresia "expresie", ce trebuie pus\ `ntre paranteze, este evaluat\ [i dac\ aceasta nu este nul\, se
execut\ "instruc]iune" (care poate fi, binen]eles, un bloc). Dup\ execu]ia acestei instruc]iuni se face din
nou evaluarea expresiei indicate `n while [i se repet\ execu]ia p=n\ c=nd evaluarea expresiei returneaz\ o
valoare nul\.
Exemplu:
int c, n = 0;
while ((c = getchar( )) != EOF){
putchar (c);
n++
}

int x, y;
while (x!=y) {
if (x>y)
x = x-y;
else
y = y-x;
}
Programul urm\tor ilustreaz\ utilizarea instruc]iunii while [i a instruc]iunii switch. Acest
program analizeaz\ un text [i num\r\ vocalele, spa]iile goale [i restul caracterelor din acesta.

Programul 6
# include <stdio.h>
int main (void){
int nvocale, naltele, nspatii;
char c;
nvocale = naltele = nspatii = 0;
printf ("Introduceti un text\n -->");
while ((c = getchar( )) != '\n') {
switch (c) {
case 'a': case 'A':
case 'e': case 'E':
case 'i': case 'I':
case 'o': case 'O':
case 'u': case 'U':
nvocale++; break;
case ' ': case '\t':
nspatii++; break;
default: naltele++;
}
}
printf("In text sunt %d vocale, %d spatii si %d alte
caractere.\n",nvocale,nspatii,naltele);
Programare_ Limbajul_C

39
return 0;
}

Rezultatul unei execu]ii:
Introduceti un text:
--> Iata un text pentru test !
In text sunt 8 vocale,5 spatii si 13 alte caractere.

5.4. Instructiunea do ... while

do
instruc]iune
while(expresie);

Spre deosebire de instruc]iunea while, "corpul" instruc]iunii do...while (adic\ "instruc]iune") se
execut\ la intrarea `n aceast\ bucl\ dup\ care se testeaz\ condi]ia "expresie": dac\ aceasta are valoare
nenul\ se execut\ din nou "instruc]iune" etc. Execu]ia se termin\ atunci c=nd "expresie" are valoarea nul\.
A[adar `n cazul do...while, "instruc]iune" se execut\ m\car o dat\ pe c=nd `n cazul while, dac\ "expresie"
este evaluat\ prima dat\ la zero, "instruc]iune" nu se execut\.
Exemplu:

int n = 0, c;
do {
c = getchar ( );
n++;
} while (c!= '\n');
printf ("Linia contine %d caractere \n", n-1);

int n = 1; c;
c = getchar ( )
while (c!= '\n') {
c = getchar ( );
n++
};
printf ("Linia contine %d caractere\n", n-1);

Se constat\ u[or c\ cele dou\ secven]e de program sunt echivalente.
5.5. Instruciunea for

for (expr1; expr2; expr3)
instruc]iune

Semantica acestei instruc]iuni poate fi descris\ `n dou\ moduri:
1. se execut\ (o singur\ dat\) expr1 [i se intr\ `n bucl\ (execu]ia de n 0 a instruc]iunii
"instruc]iune");
expresia expr2 se evalueaz\ [i se testeaz\ la fiecare `nceput de bucl\: dac\ este adev\rat\ atunci
se execut\ "instruc]iune" altfel bucla se termin\;
instruc]iunea expr3 se execut\ la fiecare sf=r[it de bucl\;
Gheorghe GRIGORA

40
2. Instruc]iunea este echivalent\ cu secven]a:
expr1;
while (expr2){
instruc]iune
expr3;
}
Instruc]iunea poate fi folosit\ [i prin suprimarea uneia dintre expr1, expr2 sau expr3 sau prin
suprimarea corpului ("instruc]iune"):
Suprimarea ini]ializ\rii;

for( ; expr2 ; expr3)
instruc]iune

Aceasta este echivalent\ cu secven]a dat\ mai sus (2.) din care lipse[te prima instruc]iune (expr1;)
Exemplu:

i = 0;
for(;(c = getchar( )) != '\0'; i++)
putchar (c);
printf("numarul de caractere:%d\n", i);
S\ observ\m c\ ini]ializarea lui i s-a f\cut `n afara instruc]iunii for !
Suprimarea expresiei de control:

for( expr ; ; expr3)
instruc]iune


Aceasta este o bucl\ infinit\. Singura modalitate de a ie[i din aceasta este utilizarea instruc]iunii
break.
Exemplu:

for (i = 0; ; c = getchar ( ), i++)
if (c == '\n')
break;

Suprimarea expresiei finale:

for( expr1 ; expr2 ; )
instruc]iune

Exemplu:

for (i = 0; (c = getchar( )) != '\0';){
putchar (c)
i++
}
printf ("numarul de caractere: %d\n", i);

Programare_ Limbajul_C

41
Suprimarea ini]ializ\rii [i a expresiei finale:

for( ; expr2 ; )
instruc]iune

Exemplu:

i = 0
for (; (c = getchar( )) != '\0'; {
putchar (c)
i++
}
printf ("numarul de caractere: %d\n", i);

Suprimarea corpului buclei:

for( expr1 ; expr2 ; expr3 ) ;

Exemplu:

for (i = 0; getchar( )!= '\n'; i++);
5.6. Instruciunea break

Instruc]iunea break permite ie[irea dintr-o bucl\ (for, while, do) sau dintr-o instruc]iune cu alegeri
multiple (switch). Iat\ c=teva exemple de utilizare a acestei instruc]iuni (vezi [i programul de la sf=r[itul
paragrafului 5.3):
1.
while ( ( c = getchar( )) != EOF) {
sum++;
if (sum>=50) {
printf ("50\n");
break;
}
}
printf ("Iesire din bucla while\n");

~n acest prim exemplu, instruc]iunea break permite ie[irea din bucla while dup\ citirea a 50 de
caractere [i nu la `nt=lnirea caracterului EOF.
2.
while ( ( c = getchar( ))!= EOF) {
sum++;
for (j = sum; sum <= 25; j++) {
j* = 1.5;
if ( j >= 75.5) break;
}
printf ("Total: %d", sum);
}
Gheorghe GRIGORA

42

~n acest caz instruc]iunea break permite ie[irea din bucla for.

5.7. Instruciunea continue
Instruc]iunea continue ignor\ toate instruc]iunile ce urmeaz\ dup\ ea, p=n\ la sf=r[itul buclei `n
care se afl\; ea provoac\ trecerea la urm\toarea itera]ie. Iat\ un exemplu:
int numar, suma = 0;
for (numar = 1; numar <= 100; numar++) {
if (numar % 5 == 0)
continue;
suma++ = numar;
}
print ("Suma este:%d\n", suma);

Se observ\ c\ prin continue se evit\ ad\ugarea la suma a numerelor multiple de 5.

5.8. Instruciunea go to
Instruc]iunea go to provoac\ saltul necondi]ionat la o etichet\, `n cuprinsul acelea[i func]ii.


Etichetele sunt nume ce se pun `n fa]a instruc]iunilor ]int\ urmate de ":". Este recomandat s\ se
evite folosirea instruc]iunii go to (a[a cer principiile program\rii structurate) dar uneori este util\. ~n
exemplul urm\tor se ilustreaz\ folosirea instruc]iunii go to [i modul cum ea poate fi evitat\:


for (i = 0; i < n; i++)
for (j=0; j < m; j++)
if (a [i] == b [j] )
go to gasit;
printf("Tablourile nu au elemente comune\ n");
.
.
.
gasit: printf (" a[%d]=b[%d]=%d\n",i,j,a [i]);


int gasit = 0;
for (i = 0; i < n && ! gasit; i++)
for (j = 0; j < m &&! gasit; j++)
gasit = (a [i] == b [j]);
if (gasit)
printf (" a[%d]= b[%d]= %d\n",i,j,a[i]);
else
printf ("Tablourile nu au elemente comune \n");



go to eticheta ;
Programare_ Limbajul_C

43
5.9. Exerciii
jgjj
1. Calculul factorialului.

Scrie]i un program care s\ realizeze urm\toarele:
- citirea unui num\r natural (dat de utilizator);
- calculul factorialului acestui num\r (iterativ);
- afi[area rezultaului.

2. Conversie
Scrie]i un program care cite[te un num\r hexazecimal (ca o succesiune de caractere), verific\
validitatea sa [i efectueaz\ conversia `n zecimal. Se va utiliza o itera]ie pentru citirea caracter cu caracter
a num\rului, itera]ia se opre[te dac\ se cite[te un caracter ce nu este cifr\ hexazecimal\ [i, pe m\sur\ ce se
citesc cifrele hexazecimale se face conversia `n zecimal. Scrie]i dou\ variante ale programului:
a) programul con]ine doar func]ia principal\ main ( )
b) func]ia principal\ main face apel la o func]ie de conversie a unui caracter reprezent=nd o cifr\
hexazecimal\ `n valoarea sa zecimal\:
int conversie (char x);

3. Numrarea biilor 1 ntr-un numr
Scrie]i un program care cite[te 10 numere `ntregi [i pentru fiecare din acestea calculeaz\ num\rul
bi]ilor ce au valoarea 1. ~n bucla de citire, se va face apel la o func]ie ce num\r\ bi]ii 1.

4. Prezentare de date
Scrie]i un program care cite[te n valori `ntregi [i le afi[eaz\ c=te l pe fiecare linie, ad\ug=nd la
sf=r[itul liniei suma lor. Ultima linie va con]ine suma sumelor, aliniat\ la sf=r[it de linie. Numerele n [i l
se definesc ca valori constante.


5.10. Soluii la exerciii

1. Calculul factorialului
Iat\ o solu]ia incomplet\ a problemei. Programul va trebui completat cu un test pentru a controla
valoarea citit\ [i cu un test pentru a verifica dac\ rezultatul calculului nu dep\[e[te capacitatea de
reprezentare a unui num\r `ntreg.

/* Calculul lui n! */
# include <stdio.h>
int main (void)
{
int n, i, fact;
printf ("Introduceti un numar natural ->");
scanf ("%d", &n);
fact = 1;
for (i = 2; i < = n; i++)
fact * = i;
Gheorghe GRIGORA

44
printf (" %d ! = %d\", n, fact);
return 0;
}

2. Conversie
Vom construi o bucl\ while care se execut\ at=ta timp c=t ultimul caracter citit este o cifr\ hexazecimal\:
0-9 sau a-f sau A-F. Dac\ este o astfel de cifr\, se converte[te `n valoare `ntreag\, p\str=nd valoarea
cumulat\ a num\rului zecimal ob]inut. Prima solu]ie face conversie `n func]ia main ( ) iar a doua solu]ie
folose[te o func]ie de conversie.

a)

/*Citirea unui numar hexa si conversia sa in zecimal*/
# include <stdio.h>
int main (void){
int numar = 0;
char c;
printf (" Introduceti un numar hexa ->");
c = getchar ( ) ;
while (( c>= '0') && (c<='9')||
(c>= 'a') && (c<='f')||
(c>= 'A') && (c<='F') {
if ((c>= '0') && (c<='9'))
numar = numar*16 + (c - '0');
else if ((c>= 'a') && (c<='f'))
numar = numar*16 + (c - 'a' + 10);
else
numar = numar*16 + (c - 'A' + 10);
c = getchar ( );
}
printf("Conversia zecimala :%d\n", numar);
return 0;
}



b)

/*Citirea unui numar hexa si conversia sa in zecimal*/
# include <stdio.h>
int conversie (char x){
return (x>= '0') && ( x<= '9') ? x - '0':
((x>='a')&&(x<='f')?x-'a':x-'A')+10;
}
int main (void){
int numar = 0;
char c;
printf (" Introduceti un numar hexa ->");
c = getchar ( ) ;
while (( c>= '0') && (c<='9')||
Programare_ Limbajul_C

45
(c>= 'a') && (c<='f ')||
(c>= 'A') && (c<='F') {
numar = numar*16 + conversie (c);
c = getchar ( ) ;
}
printf ("Conversia zecimala: %d\n", numar);
return 0;
}


3. Numrarea biilor 1 ntr-un numr
Determinarea bi]ilor 1 se face prin decalaj succesiv [i testarea bitului.

/* Numararea bitilor 1 din reprezentarea binara a unui numar intreg */
# include <stdio.h>
int numarbit(int);
int main (void)
{
int i;
int val;
for (i = 0; i < 10; i++) {
printf ("Introduceti o valoare intreaga: ");
scanf ("%d", &val);
printf ("Numarul bitilor 1 este: %d\n",
numarbit(val));
}
return 0;
}
int numarbit(int x){
int n = 0;
while (x!=0) {
if (x & 01)
n++;
x >>=1;
}
return n;
}

~n func]ia numarbit, transmiterea parametrului se face prin valoare; se poate a[adar utiliza x ca
variabil\ de lucru. Prin instruc]iunea x >>=1 se decaleaz\ bi]ii lui x cu o pozi]ie la dreapta; la st=nga se
adaug\ un zero.

4. Prezentare de date
/* Se citesc n intregi si se afiseaza cate l pe **linie impreuna cu suma acestora la sfarsit de
**linie.Ultima linie contine suma sumelor */
# include <stdio.h>
const n = 10;
const l = 3;
int main (void){
Gheorghe GRIGORA

46
int val, /*ultima valoare intreaga citita */
sumap=0, /*suma din linia curenta*/
nl=0,/*numarul intregilor pe linie */
suma=0, /* suma sumelor par]iale */
nt; /*numarul total de intregi */
printf ("Introduceti%d numere intregi", n);
for (nt = 0; nt < n, nt++) {
scanf ("%d", &val);
++nl;
suma p+= val;
printf ("%6d", val);
if (nl == l ) {
printf (" %6d\n", sumap);
nl = 0;
suma += sumap;
sumap = 0;
}
}
if (nl! = 0) {
/*ultima linie este incompleta: se **completeaza cu spatii*/
int i;
for (i = nl; i < l; i++)
printf (" ");
suma += sumap;
printf ("%6d\n", sumap);
}
/* alinierea sumei totale pe ultima linie */
int i;
for (i = 0; i < l; i++)
printf (" ");
printf ("%d\n", suma);
return 0 ;
}


Cap 6 TABLOURI I POINTERI





6.1. Pointeri
6.2. Tablouri cu o dimensiune
6.3. Rela]ia `ntre pointeri [i tablouri
6.4. Opera]ii aritmetice cu pointeri
6.5. {iruri de caractere
6.6. Tablouri cu mai multe dimensiuni
6.7. Tablouri de pointeri
6.8. Pointeri [i alocarea memoriei
6.9. Operatorul sizeof
6.10. Pointeri c\tre func]ii
6.11. Exerci]ii
6.12. Solu]ii









6.1. Pointeri



Un pointer este o variabil\ ce con]ine adresa unei alte variabile. Pointerii au tip :
aceasta `nseamn\ c\ un pointer nu poate fi folosit dec=t pentru a con]ine adrese de
variabile de un singur tip. De exemplu, prin declara]iile:
int *pi;
char *pc;
se specific\ faptul c\ pi este un pointer la o variabil\ de tip `ntreg iar pc un pointer la o variabil\ de tip
"char".
Operatorul unar "&" numit operator de referen]iere sau adresare, aplicat unei variabile, permite
ob]inerea adresei acesteia:
int i;
pi = &i;
Operatorul unar "*", dereferen]iere, indirectare, permite derefen]ierea unui pointer, furniz=nd
valoarea variabilei pointate de acesta:
int x;
x = *pi x = i;
Utilizarea operatorului "*" este destul de delicat\, chiar periculoas\ am spune: acesta permite
citirea sau scrierea `n orice zon\ de memorie. Utilizarea unui pointer care este ini]ializat gre[it este o
eroare des `nt=lnit\ `n programare [i din p\cate consecin]ele sunt imprevizibile.
tip *identificator;
Gheorghe GRIGORA

48
O aplica]ie important\ privind utilizarea pointerilor este transferul prin referin]\ al
parametrilor unei func]ii. A[a cum s-a precizat la capitolul "Func]ii", `n limbajul C
transferul implicit al parametrilor este prin valoare. Dac\ se dore[te modificarea unui
parametru formal, trebuie transmis\ func]iei adresa variabilei iar `n corpul func]iei s\ se
foloseasc\ operatorul de dereferen]iere.
Exemplul clasic pentru acest procedeu este acela al func]iei de interschimbare a dou\ variabile.
Forma "clasic\" a func]iei, incorect\ (semantic) `n limbaj C, este:
void schimbare (int a, int b) {
int temp = a; a = b; b = temp;
}
Un apel al acestei func]ii (prin schimbare (x, y);) nu are nici un efect asupra variabilelor x,y
(actuale) pentru c\ func]ia lucreaz\ cu variabilele ei locale a [i b. Varianta corect\ este:

void schimbare_corecta (int *p, int *q){
int temp;
temp = *p; *p = *q; *q = temp;
}

Apelul corespunz\tor este:
int x = 1, y = 2;
schimbare_corecta (&x, &y);

6.2. Tablouri cu o dimensiune



Un tablou este o colec]ie de elemente(date) de acela[i tip, fiecare din acestea
putnd fi accesibil. Declaraia
int vector[10];

define[te un tablou cu numele "vector" care are 10 elemente de acela[i tip, `ntreg. A[adar, o declara]ie de
tablou cu o dimensiune con]ine tipul tabloului (tip), numele tabloului (nume) - care este un identificator -
precum [i dimensiunea sa, dimensiune. Dimensiunea este o constant\ `ntreag\ [i specific\ num\rul
elementelor tabloului.

6.2.1. Referenierea unui element al tabloului
Elementele unui tablou pot fi accesate prin numele tabloului urmat de o expresie `ntre paranteze
p\trate - numit\ expresie indice - care trebuie s\ aib\ valoarea `ntre 0 [i dimensiune - 1. Primul element al
tabloului este cel de indice 0 iar ultimul este cel de indice dimensiune -1. ~n declara]ia de mai sus, int
vector[10]; cele 10 elemente ale tabloului vector sunt:
vector[0], vector[1],, vector[9]
La declararea unui tablou se aloc\ o zon\ de memorie contigu\ care s\ stocheze toate elementele
tabloului. Adresa primului element (cel de indice 0) este [i adresa tabloului iar celelalte elemente se
raporteaz\ la acesta.

6.2.2. Iniializarea unui tablou
Ini]ializarea unui tablou se face prin semnul "#" dup\ declara]ia acestuia urmat de o list\ de valori
ini]iale, separate prin virgule, care se `nchid `ntre acolade.

tip nume[dimensiune];
Programare_ Limbajul_C

49








Exemple:
1. int a[4] = {1, 2, 3, 4};
char s[4] = {'a', 'b', 'c', '\o'};

2.
# define marime 5;
char tab[marime];
tab[0] = 'a';
tab[1] = tab[2] = 'b';
tab[3] = tab[4] = 'd';

Tabloul va avea structura:
'a' 'b' 'b' 'd' 'd'

tab[marime - 1] = 'e';
tab[marime/2] = 'c';
Dupa aceste transformari structura sa va fi:
'a' 'b' 'c' 'd' 'e'

Dac\ lista de valori ini]iale (dat\ dup\ declara]ie) cuprinde mai pu]ine elemente dec=t dimensiunea
declarat\ a tabloului, atunci celelalte valori se ini]ializeaz\ cu zero. Spre exemplu
int a[10] = {5, 2, 3, 1};
are ca efect crearea tabloului:
5 2 3 1 0 0 0 0 0 0

~n cazul unui tablou care se ini]ializeaz\, poate fi omis\ dimensiunea; aceasta se determin\ de
c\tre compilator:
float x[ ] = {2, 0, 5.2, 3, 4, 0};
2 0 5.2 3 4 0

~n cazul tablourilor de caractere, ini]ializarea se poate face [i cu [iruri de caractere incluse `ntre
ghilimele; declara]ia:
char s[6] = "abcdef" ;
este echivalent\ cu:
char s[6] = {'a', 'b', 'c', 'd', 'e', 'f'};
iar declara]ia: char s[ ] = "abcdef" ;
este echivalent\ cu:
char s[ ] = {'a', 'b', 'c', 'd', 'e', 'f', '\0'};
De notat c\ `n cazul sirurilor de caractere ce se memoreaz\ `ntr-un tablou, ultimul element al tabloului
este caracterul \0; acest caracter noteaz\ sf=r[itul [irului( vezi paragraful 6.5).
Ini]ializarea unui tablou se poate face [i prin citirea succesiv\ a tuturor elementelor
sale:
int i;
tip nume[dim] = {
valoare_1,
valoare_2,
...
};
Gheorghe GRIGORA

50
float x [20];
for (i=0; i < 20; i++) {
scanf (" %f", &x[i]);
}
Este de remarcat faptul c\ nu se face nici o verificare a limitelor unui tablou atunci c=nd se
acceseaz\ un element al s\u. Spre exemplu dac\ se declar\
int a[3], b[3], c[3];
[i alocarea se face astfel:
a[0] a[1] a[2] b[0] b[1] b[2] c[0] c[1] c[2]

atunci expresiile a[4], b[1], c[-2], sunt echivalente, `n sensul c\ ele reprezint\ adresa aceleia[i zone de
memorie.
6.3. Relaia ntre pointeri i tablouri
S\ consider\m urm\toarea secven]\:
int tab[10];
int *pa;
pa = &tab[0];
Ultima instruc]iune asigneaz\ variabilei pointer pa adresa primului element al tabloului tab. Nota]ia
"*pa" este echivalent\ cu nota]ia tab[0] iar nota]ia "*(pa+1)" este echivalent\ cu nota]ia tab[1]. A[adar,
`n general "*(pa+i)" este totuna cu tab[i]. Urm\toarele secven]e for sunt echivalente:


for ( i = 0; i < 10; i++)
tab[i] = 100;


for ( i = 0, pa = &tab[0]; i < 10; i++)
*(pa+i) = 100;


for ( i = 0, pa = &tab[0]; i < 10; i++)
*(pa++) = 100;


~n limbajul C, numele unui tablou poate fi utilizat ca pointer (constant) la adresa de `nceput a
tabloului. De aceea, cu declara]iile de mai sus, este perfect valid\ asignarea
pa = tab;
care este echivalent\ cu "pa=&tab[0];". Nu sunt valide (e lesne de dedus) expresiile:
tab = pa; sau tab ++;
A[adar se poate scrie [i:

for ( i = 0, pa = tab; i < 10; i++, pa++)
*pa = 100;

~n rezumat, echivalen]a `ntre elementele unui tablou [i numele s\u se exprim\ prin:




tablou[i] *(tablou + i)
&tablou[i] tablou + i
Programare_ Limbajul_C

51
6.4. Operaii aritmetice cu pointeri
Opera]iile aritmetice permise asupra pointerilor sunt adunarea/ sc\derea unei constante,
incrementarea/decrementarea (^^, --) [i sc\derea a doi pointeri de acela[i tip.
Trebuie precizat `ns\ c\ unitatea care intr\ `n discu]ie nu este octetul ci adresa obiectului pointat.
S\ urm\rim urm\torul exemplu:
float ftablou[10];
float *pf = ftablou;
pf++;
~n acest exemplu, dup\ incrementare, pf pointeaz\ la cel de-al doilea element al tabloului ftablou.
Iat\ [i alte exemple: `n partea st=ng\ se descrie o expresie `n care apar pointeri iar `n dreapta expresia
echivalent\ `n termenii tabloului.

Nota]ia pointer Nota]ia tablou
ptr = tablou i = 0
ptr1 = ptr + 5 i = i + 5
ptr + i tablou [i]
ptr + 4 tablou [4]
ptr - 3 tablou [-3]
ptr1 - ptr j - i
ptr ++ i ++

6.5. iruri de caractere
~n limbajul C, nu exist\ un tip de baz\ pentru [iruri (lan]uri) de caractere. Pentru a reprezenta un
[ir de caractere, se utilizeaz\ tablourile de caractere. Prin conven]ie, ultimul caracter dintr-un astfel de
lan] este caracterul NULL (' @0').
Tabloul de caractere (pe care-l numim mesaj):
's' 'a' 'l' 'u' 't' '!' ' @o'
poate fi declarat prin una din urm\toarele trei instruc]iuni:
char mesaj[7] = {'s','a','l','u','t','!', '\o'};
char mesaj[7] = "salut!";
char mesaj[ ] = "salut!";
Citirea respectiv tip\rirea acestui [ir se face prin instruc]iunile:
scanf("%s", mesaj);
printf("%s", mesaj);
scanf("%s", &mesaj[0]);
printf("%s", mesaj[0]);
Exist\ o bibliotec\ de func]ii standard pentru manipularea [irurilor de caractere care se prezint\ `n
anex\.

6.6. Tablouri cu mai multe dimensiuni
Declararea unui tablou cu N dimensiuni se face prin:



~n aceast\ declara]ie, dim_1, dim_2, ..., dim_n trebuie s\ fie constante. Un tablou declarat `n acest
mod se compune din dim_1*dim_2*...*dim_n elemente de acela[i tip (declarat) stocate `ntr-o zon\
contigu\ de memorie.
tip nume[dim_1][dim_2]...[dim_n];
Gheorghe GRIGORA

52
Pentru a accesa un element dintr-un tablou exist\ mai multe moduri de notare, `n
concordan]\ cu modul de stocare a elementelor tabloului `n memorie.
Iat\ de exemplu o declara]ie a unui tablou cu dou\ dimensiuni de valori 3 respectiv 4 (a[adar o
matrice cu 3 linii [i 4 coloane).
int t[3][4];

O prim\ viziune a reprezent\rii acestuia `n memorie este cea natural\ a unei
matrice:
t [0][0] t [0][1] t [0][2] t [0][3]
t [1][0] t [1][1] t [1][2] t [1][3]
t [2][0] t [2][1] t [2][2] t [2][3]
Elementeul ha[urat din acest tablou se referen]iaz\ prin t[1][2] (este elementul de pe linia 2 [i
coloana 3 din matrice, datorit\ numerot\rii indicilor de la 0).
O alt\ viziune (acceptat\ de C) a acestui tablou este aceea a unui tablou cu o singur\ dimensiune
`n care fiecare element este la r=ndul s\u un tablou cu o dimensiune:
t

t[0] t
[0][0]
t [0][1] t [0][2] t [0][3]

t[1] t
[1][0]
t [1][1] t [1][2] t [1][3]

t[2] t
[2][0]
t [2][1] t [2][2] t [2][3]

Elementul t[1] reprezint\ un tablou cu o dimensiune iar elementul ha[urat este referen]iat prin
*(t[1]+3).
~n sf=r[it a treia viziune a tabloului este aceea a unei succesiuni de elemente
dispuse `ntr-o zon\ contigu\:
t [0][0] t [0][1] t [0][2] t [0][3]


t [1][0] t [1][1] t [1][2] t [1][3]


t [2][0] t [2][1] t [2][2] t [2][3]
Elementul ha[urat (acela[i ca [i `n cazurile anterioare) se referen]iaz\ prin:
*( *t + 6)
sau prin nota]ia echivalent\:
*( &( t[0][0] + 6))
S\ not\m c\ `n acest caz t este de tip pointer de pointer de `ntregi (dubl\ adresare indirect\).
O problem\ important\ relativ la tablourile cu mai multe dimensiuni este cea a ini]ializ\rii
acestora. A[a cum referen]ierea unui element al tabloului poate fi f\cut\ `n mai multe moduri, [i
ini]ializarea unui tablou se poate face `n moduri diferite (sintactic vorbind). S\ exemplific\m aceste
moduri cu referiri la acela[i tablou pe care l-am reprezentat mai sus, t[3][4]:
ini]ializarea prin enumerarea tuturor elementelor tabloului ( `n ordinea liniilor dac\-i vorba
de matrice):
int t[3][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
ini]ializarea fiec\rei dimensiuni de tablou, separat:
int t[3][4] ={{1, 2, 3, 4},{5, 6, 7, 8},
Programare_ Limbajul_C

53
{9, 10, 11, 12}
};
ini]ializarea numai a unor elemente din tablou:
int t[3][4] = {{1},{5, 6}};
Astfel t [0][0] va fi ini]ializat cu 1, t [1][0] cu 5 iar t [1][1] cu 6; restul elementelor sunt ini]ializate
cu zero.

6.7. Tablouri de pointeri
Pointerii fiind variabile, pot intra `n componen]a unui tablou. Un tablou unidimensional de
pointeri corespunde la un tablou (cu dou\ dimensiuni) de elemente de tipul pointat. Iat\ cum se declar\ un
tablou de pointeri cu 7 componente ce se ini]ializeaz\ cu adresele [irurilor constante ce reprezint\ numele
zilelor dintr-o s\pt\m=n\.
char *zi[7] = {"luni", "marti", "miercuri",
"joi", "vineri", "sambata", "duminica");
};

zi[0] zi[1] zi[2] zi[3] zi[4] zi[5] zi[6]


'l' 'm' 'm' 'j' 'v' 's' 'd'
'u' 'a' 'i' 'o' 'i' 'a' 'u'
'n' 'r' 'e' 'i' 'n' 'm
'
'm
'

'i' 't' 'r' 'e' 'b' 'i'
'i' 'c' 'r' 'a' 'n'
'u' 'i' 't' 'i'
'r' 'a' 'c'
'i' 'a'

S\ consider\m un tablou de pointeri de tip char, cu numele tabp. O func]ie care s\ afi[eze toate
[irurile de caractere (pointate de tabp) la un singur apel ar putea ar\ta astfel:

void scrie(char *tabp [ ], int n)
{
int i;
for (i = 0; i < n; i++)
if (tabp [i] != NULL)
printf ( "%s\n", tabp[i] );
}
Apelul acestei func]ii pentru scrierea zilelor s\pt\m=nii este:
scrie (zi, 7);
S\ mai d\m un exemplu de func]ie care sorteaz\ lexicografic (alfabetic) [irurile pointate de tabp:
void sortare (char* tabp[ ], int n){
int i, sortat = 0;
char *temp;
while (! sortat) {
sortat = 1;
for (i = 0; i < n-1; i++)
if (strcmp (tabp [i], tabp [i+1]) > 0) {
Gheorghe GRIGORA

54
temp =tabp [i];
tabp [i] = tabp [i+1];
tabp [i+1] = temp;
sortat = 0;
}
}
}

Apelul pentru sortarea alfabetic\ a zilelor s\pt\m=nii este
sortare(zi, 7);
~n corpul func]iei sortare s-a folosit un apel la func]ia strcmp care compar\ 2 [iruri de caractere
s
1
[i s
2
; rezultatul este negativ dac\ s
1
< s
2
, pozitiv dac\ s
1
> s
2
[i zero dac\ s
1
# s
2
.

6.8. Pointeri i alocarea memoriei
Printre func]iile de alocare a memoriei (vezi Anexa ), "maloc" [i "free" joac\ un rol important
pentru c\ ele permit alocarea / dealocarea `n mod dinamic a spa]iului din memorie. Acest spa]iu este
posibil de accesat cu ajutorul variabilelor de tip pointer.
# include <stdlib.h>

void *malloc (size_t dim);
void free(void *ptr);

Alocarea dinamic\ a memoriei este deosebit de util\ at=ta timp c=t programatorul folose[te
structuri de date pentru care nu [tie dimensiunea la scrierea programului. ~n cursul execu]iei programul
poate aloca memorie `n limitele impuse de sistem.
Func]ia malloc are ca argument num\rul de octe]i dori]i a fi aloca]i [i `ntoarce ca rezultat un
pointer c\tre zona de memorie liber\ alocat\ de sistem. Pointerul returnat este de tip "void" ce corespunde
unui pointer la o variabil\ de tip oarecare. Pentru specificarea m\rimii unui tip particular, se poate utiliza
operatorul "sizeof" (vezi sec]iunea urm\toare). Dac\ nu mai este memorie disponibil\ (nu se poate face
alocarea) func]ia malloc returneaz\ valoarea NULL.
Iat\ un exemplu:
char *tampon;
element *ptr;
/*presupunem ca tipul element este definit undeva */
--------
tampon = malloc(512);
/* s-a alocat o memorie tampon de 512 caractere*/
ptr = malloc(32*sizeof(element));
/*s-a alocat o zona de 32 de "elemente"*/
if ((tampon == NULL || ptr == NULL)) {
printf ("Alocare imposibila ! \n");
...
...
Func]ia "free" permite dealocarea spa]iului de memorie alocat `n prealabil de malloc. De pild\,
dup\ utilizarea memoriei tampon [i ptr (`n exemplul de mai sus) se scrie (`n program)
free (tampon);
free (((char*)ptr);
Programare_ Limbajul_C

55
6.9. Operatorul sizeof




Operatorul sizeof ofer\ dimensiunea `n octe]i a tipului expresiei considerate(tipului respectiv).
Dac\ se aplic\ unui tablou, operatorul sizeof ofer\ dimensiunea `n octe]i a memoriei ocupat\ de `ntreg
tabloul. Pentru a ob]ine num\rul elementelor tabloului t se utilizeaz\ expresia sizeof t sau sizeof t[0].
S\ not\m `n acela[i timp c\, atunci c=nd este parametrul unei func]ii, un tablou este considerat ca [i un
pointer; prin urmare operatorul sizeof nu ofer\ dimensiunea memoriei ocupat\ de tablou ci dimensiunea
tipului pointer. Acest lucru se ilustreaz\ `n exemplul urm\tor:

double tab [100];
void f(double[ ]);
/*declaratia este echivalenta cu void f(double*)*/
int main( ){
int i = sizeof tab;
/* i este initializat cu 100 * sizeof(double)*/
f(tab);
...
}

void f(double t[ ]){
int i = sizeof t;
/* i este initializat cu sizeof(double)*/
}

Pentru a ob]ine dimensiunea memoriei ocupat\ de un tip anume se folose[te:
sizeof(tip);
De aceast\ dat\ parantezele sunt obligatorii.
Apelul sizeof(long); ofer\ num\rul de octe]i utiliza]i pentru a memora un `ntreg long (este incorect
a scrie sizeof long).

6.10. Pointeri ctre funcii
O func]ie are un nume care este identificator dar acesta nu constituie o variabil\ `n C. Este posibil, pe
de alt\ parte, de a defini o variabil\ de tip pointer c\tre o func]ie. Declara]ia unui pointer la o func]ie este
de forma:



tip: este tipul returnat de func]ia pointat\;
nume: este identificatorul pointerului la func]ie;
lista_arg : este lista argumentelor func]iei pointate.
De exemplu declara]ia:
char *(*p)(char*,const char*);
precizeaz\ c\ p este un pointer la o func]ie de tip char* (pointer la tipul char), are doi parametri, unul de
tip char*, cel\lalt de tipul const char*.
Este important a se pune *nume `n parantez\ deoarece declara]ia tip *nume (lista_parametri)
precizeaaz\ c\ nume este o func]ie de tip tip*.
sizeof expresie;
sizeof(tip);
tip(*nume)(lista_arg);
Gheorghe GRIGORA

56
Un exemplu de utilizare a tipului pointer la o func]ie este func]ia de comparare cmp ce apare ca
argument la func]ia de sortare qsort (vezi anexa ):
void qsort(const void* baza, size_t n, size_n t,
int(*cmp)(const void* val1, const void* val2))
Func]ia qsort este o func]ie de sortare general\ care permite sortarea unui tablou de elemente de tip
oarecare(baza) prin specificarea unei func]ii de comparare. Iat\ un program ce utilizeaz\ func]ia qsort :
# include <stdio.h>
# include <stdlib.h>
# include <string.h>

enum {n_max = 10};
int tab_int[n_max];
/* tab_int este tabloul ce contine lungimile liniilor **ce trebuie sortat */
char* tab_nume[n_max] = {
"Ionescu Ion",
"Constantin Vasile",
"Ion Gheorghe",
"Constantin Mircea",
"Constantinescu Ioana",
"Vasiliu Catalina",
"Vasilescu Maria",
"Constantiniu Calin",
"Vasile Radu",
"Vasilescu Cristi" };
/* tab_nume este tabloul ce trebuie ordonat **lexicografic */
/* se definesc functiile de comparatie */
int comp_int (const void* n1, const void* n2)
{
return(*(int*)n1- *(int*)n2);
}
int comp_nume (const void* p1, const void* p2)
{
return(strcmp(*(char**)p1,*(char**)p2));
}
int main(void)
{
int i;
printf("Lista initiala de nume : \n");
for(i = 0; i < n_max; i++)
printf("%2d: %s\n",i,tab_nume[i]);
for (i = 0, i < n_max; i++)
tab_int[i] = strlen(tab_nume[i]);
qsort(tab_int, n_max, sizeof(int), comp_int);
qsort(tab_nume,n_max,sizeof(char*),comp_nume);
printf("Lungimile numelor sortate:\n");
for(i = 0; i < n_max ; i++)
printf("%2d: %d\n",i,tab_int[i]);
printf("Nume ordonate lexicografic: \n");
for(i = 0; i < n_max; i++)
printf("%2d: %s\n",i,tab_nume[i]);
return 0;
}
Programare_ Limbajul_C

57
6.11. Exerciii
1. A[a cum s-a mai precizat, `n C, [irurile de caractere sunt memorate `n tablouri `n care ultimul element
este un delimitator de sf=r[it de [ir: caracterul NULL(\0). ~n anex\ sunt date func]iile din biblioteca
standard care se aplic\ [irurilor de caractere. S\ se scrie programe C care s\ implementeze func]iile:
a) int strlen(const char*s) : func]ie ce returneaz\ dimensiunea [irului s;
b) char* strcpy(char* dest,const char* sursa) : func]ie ce copie [irul sursa `n [irul dest [i returneaz\
dest;
c) char* strcat(char* dest,const char* sursa): func]ie ce concateneaz\ [irul sursa la sf=r[itul [irului
dest [i returneaz\ valoarea lui dest;
d) int strcmp(const char* s1, const char* s2) : func]ie ce compar\ [irurile s1 [i s2 conform ordinii
lexicografice. Dac\ are loc rela]ia s1 < s2, se returneaz\ o valoare negativ\, dac\ s1 = s2 se
returneaz\ 0 [i dac\ s1 > s2 se returneaz\ o valoare pozitiv\.

6.12. Soluii
1. Implementarea func]iilor de la a) la d) se poate face folosind nota]ia tablou sau aritmetica pointerilor.

int strlen(const char *s){
int i = 0;
while(s[i++] != '\0')
;
return -- i ;
}

char *strcpy(char* dest, const char *sursa){
int i = 0;
while(sursa[i] != '\0') {
dest[i] = sursa[i];
i++
}
dest[i] = '\0';
return dest;
}

char *strcat(char *dest, const char *sursa){
while(*dest != '\0')
dest++;
while(*scr != '\0')
*dest++ = *src++;
*dest = '\0';
return dest;
}
char *strcmp(const char *s1, const char *s2){
int i = 0;
while((s1[i] == s2[i] && (s1[i] != '\0'))
i++;
return s1[i] - s2[i];
}
Gheorghe GRIGORA

58
Iat\ [i un program care testeaz\ aceste func]ii. Se folose[te func]ia assert (anexa ) care are ca
parametru o expresie logic\ ce descrie o proprietate ce trebuie verificat\. Dac\ evaluarea acestui
parametru este valoarea fals (0) atunci assert returneaz\ un mesaj de eroare.

# include <stdlib.h>
# include <assert.h>

int strlen(const char *s)
char* strcopy(char *dest, const char *sursa);
char* strcat(char *dest, const char *sursa);
int strcmp(const char *s1, const char *s2);
int main(){
char *inceput = "Iat\";
char *mijloc = "un mic";
char *sfarsit = "exemplu ! ";
char *mesaj;
int lungime;
lungime = strlen(inceput)+ strlen(mijloc)
+strlen(sfarsit);
assert(lungime==strlen("Iata un mic exemplu ! "));
mesaj = malloc(lung + 1);
strcat(strcat(strcopy(mesaj,inceput),mijloc),
sfarsit);
assert(strcmp(mesaj, "Iata un mic exemplu !")== 0);
assert(strcmp(mesaj,inceput) > 0);
assert(strcmp(mesaj, "Iat un micut exemplu!") < 0);
return 0;
}



Cap 7 CONSTRUIREA DE NOI TIPURI


7.1 Redenumirea unui tip
7.2 Tipul structur\
7.3 Accesul [i ini]ializarea c=mpurilor unei structuri
7.4 Structuri autoreferen]iate
7.5 Tipul enumerare
7.6 Uniuni
7.7 Exerci]ii
7.8 Solu]ii










~n capitolul al doilea au fost introduse tipurile de baz\ ale limbajului C. ~n anumite programe este util
s\ regrup\m diferite variabile pentru a exprima o anume rela]ie ce le caracterizeaz\. De pild\ un tablou
permite a regrupa o mul]ime de elemente de acela[i tip. ~n acest capitol vom vedea c\ `n C putem construi
structuri sau uniuni care permit regruparea elementelor de tipuri diferite `n scopul de a defini un nou
tip. De asemenea exist\ posibilitatea de a renumi (redenumi) un anume tip.

7.1. Redenumirea unui tip

Instruc]iunea typedef permite redenumirea unui tip. Sintaxa ei este:



Aici tip este tipul ce se dore[te a fi redenumit iar nume_nou este numele ce se d\ acestuia.
Instruc]iunea permite redenumirea at=t a tipurilor de baz\ (deja existente) c=t [i a tipurilor construite.
Iat\ c=teva exemple:
typedef long Mare;
typedef char Mesaj[49];
typedef char Luna[10];
Mare a,b;
Mesaj salut="!Bine a-ti venit la cursul<Limbajul C>";
Luna ianuarie = "ianuarie";

typedef tip nume_nou;
Gheorghe GRIGORA

60
7.2. Tipul structur
Instruc]iunea pentru definirea structurilor este:







Structura este o colec]ie de una sau mai multe variabile (numite membri) grupate sub un singur
nume. ~n instruc]iunea de mai sus nume este facultativ; el este totu[i util pentru a identifica structura
definit\. Fiecare linie din partea declara]ii define[te un c=mp al structurii. O variabil\ de tipul struct
nume poate fi definit\ `n aceea[i instruc]iune `n care este definit\ structura sau separat Iat\ c=teva
exemple:

struct Persoana{
char nume[20];
char prenume[20];
int varsta;
} amicul;

struct Persoana colegul;

struct Data{
short ziua;
short luna;
short anul;
};
struct Student{
char *nume;
char *prenume;
struct Data data_nasterii;
int an;
char *grupa;
}
struct Student ionescu, popescu;
typedef struct{
short ziua;
short luna;
short anul;
} Data;

typedef struct {
char nume[20];
char prenume[20]
Data data_nasterii;
} Persoana;

Persoana ionescu, popescu;

S\ observ\m c\ structurile se pot defini f\r\ nume; prin typedef li se atribuie un nume.

struct nume{
declara]ii
};
Programare_ Limbajul_C

61
7.3. Accesul i iniializarea cmpurilor unei structuri

Accesul la c=mpurile unei variabile de tip structur\ se face utiliz=nd numele unei variabilei urmat\ de
punct (.) [i de numele c=mpului selec]ionat. Elementul desemnat `n acest mod este echivalent cu o
variabil\ de acela[i tip cu c=mpul definit `n structur\. Iat\,de pild\, urm\rind exemplele din paragraful
precedent, avem:
ionescu.nume este de tip char*;
ionescu.data_nasterii.ziua este de tip short;
amicul.varsta este de tip int.
S\ consider\m acum declara]ia:
typedef struct{
char nume[40] ;
char prenume[40];
int varsta;
} Persoana;
Persoana ionescu, dan, *necunoscut;
Aici, variabilele ionescu [i dan sunt definite ca fiind de tip Persoana , care este un tip
structur\, iar necunoscut este o variabil\ de tip pointer la structura Persoana . Accesul la c=mpurile
unei astfel de variabile(pointer la o structur\) se face ad\ug=nd dup\ numele varibilei pointer o s\geat\
(->) , urmat\ de numele c=mpului.
Exemplu:
necunoscut = &ionescu;
necunoscut ->varsta = 41;
dan.nume = necunoscut->nume;
O form\ echivalent\ este urm\toarea:
(*necunoscut).varsta = 41;
dan.varsta = (*necunoscut).nume;

Ini]ializarea unei variabile de tip structur\ se poate face `n maniera `n care se ini]ializeaz\ un tablou:
se descrie cu ajutorul unei liste de valori ini]iale c=mpurile structurii:

Persoana ionescu = { "Ionescu", "Vasile" , 42 };
Persoana necunoscut = { " " , " " , 0};

Dou\ structuri de acela[i fel pot s\ apar\ `ntr-o expresie de atribuire. O atribuire de structuri este o
copiere bit cu bit a elementelor corespunz\toare, `nc=t o astfel de expresie are sens doar dac\ structurile
sunt de acela[i tip. Are sens asfel:
necunoscut = ionescu ;
Prin aceasta, c=mpurile din variabila ionescu sunt copiate `n c=mpurile corespunz\toare din
variabila necunoscut.

7.4. Structuri autorefereniate

Utilizarea structurilor permite construirea de structuri de date evoluate ca: fi[iere, liste, arbori etc..
De pild\, `ntr-un arbore binar, fiecare nod este compus dintr-o informa]ie (valoarea nodului) [i doi
pointeri, unul la subarborele st=ng altul la cel drept. Iat\ cum poate fi definit\ o astfel de structur\:

typedef struct {
...
} valoare;
Gheorghe GRIGORA

62
/* s-a definit tipul "valoare" pentru **informatia din nodurile arborelui*/
typedef struct Arbore{
valoare val;
struct Arbore *stang;
struct Arbore *drept;
} Arbore;

S\ observ\m c\ structura Arbore se autoreferen]iaz\: printre c=mpurile structurii arbore sunt dou\
care sunt de acela]i tip struct Arbore. Din acest motiv structura are un nume: Arbore. Programul
urm\tor ilustreaz\ utilizarea unei structuri autoreferen]iate: se construiesc doi arbori binari folosind
func]ia adauga [i se afi[eaz\ un arbore `n nota]ia infix (func]ia afisare).

Programul Arbori binari.

# include <stdio.h>
# include <stlib.h>
typedef int valoare;
typedef struct Arbore{
valoare val;
struct Arbore* stang;
struct Arbore* drept;
} Arbore;
Arbore* adauga(valoare v, Arbore* s, Arbore* d);
void afisare (Arbore* a);
int main( ){
Arbore* a1;
Arbore* a2;
a1=adauga(1, adauga(2, adauga(3, NULL, NULL),
NULL), adauga(4, NULL, NULL));
printf("Primul arbore este: \n");
afisare(a1);
a2=adauga(10, a1, adauga(20, NULL, NULL));
printf("\n");
printf("Al doilea arbore este: \n");
afisare(a2);
printf("\n");
return 0;
}
Arbore* adauga(valoare v, Arbore* s, Arbore* d){
Arbore* c;
c=malloc (sizeof (Arbore));
c->val = v;
c->stang = s;
c->drept = d;
return c;
}
void afisare (Arbore* a){
if (a! = NULL) {
printf ("(%d", a->val , " ");
afisare (a->stang);
printf (" ");
afisare (a->drept);
Programare_ Limbajul_C

63
printf (")");
} else
printf ("nil");
}

Execu]ia programului are ca rezultat afi[area urm\toarelor informa]ii:
Primul arbore este:
(1 (2 (3 nil nil) nil) (4 nil nil))
Al doilea arbore este:
(10(1 (2 (3 nil nil) nil) (4 nil nil)) (20 nil nil))

7.5. Tipul enumerare

Definirea unui tip enumerare se face prin instruc]iunea:



Un tip enumerare permite ca, `ntr-o maniera elegant\,s\ definim un tip care nu poate lua valori dec=t
`ntr-o mul]ime precizat\ de valori constante. Primul identificator constant din lista de identificatori cap\t\
valoarea 0, al doilea valoarea 1, etc. cu excep]ia cazului `n care programatorul ofer\ valori ini]iale acestor
identificatori.
Exemple:
enum Bool {da, nu};
Aici da are valoarea 0 iar nu are valoarea 1.
enum Bool {da=1, nu=0};
enum Bool {nu, da}
~n ambele situa]ii, nu are valoarea 0 iar da are valoarea 1.
enum Luna {ian=1, feb, mar, april, mai,
iunie, iulie, august, sept, oct, nov, dec};
Aici, pentru c\ lui ian i s-a dat valoarea ini]ial\ 1, celelalte luni vor avea respectiv valorile 2, 3, ..., 12.
Similar cu definirea variabilelor de tip structura se definesc variabilele de tip enumerare:
enum Bool raspuns;
enum Bool spune=da;
Evident se poate redenumi [i tipul enumerare:
Typedef enum {da, nu} Bool
Bool raspuns=nu;
7.6. Uniuni

Uniunile sunt structuri care pot con]ine (la momente de timp diferite), obiecte de tipuri diferite. De
fapt, este vorba despre zone de memorie care, la un moment dat con]in un anume tip de variabil\ iar la alt
moment acest tip se poate schimba. Sintaxa este similar\ cu cea care define[te o structur\:






Lista de declara]ii, spre deosebire de cea de la structur\, care definea c=mpurile acesteia, define[te o
list\ de alegeri posibile. Uniunea trebuie privit\ ca o structur\ `n care membrii ocup\ aceea[i zon\ de
enum nume { lista_de_identificatori};
union nume {
declara]ii
};
Gheorghe GRIGORA

64
memorie; dimensiunea memoriei alocat\ pentru o variabil\ de tip uniune este dimensiunea celui mai mare
membru al uniunii. S\ not\m c\, la un moment dat doar un membru al uniunii poate ocupa memoria.
~n exemplul urm\tor se specific\ faptul c\ un punct `n plan poate fi definit fie prin coordonatele sale
carteziene fie prin cele polare.

Typedef union {
struct {
long abscisa;
long ordonata;
} cart;
struct {
float ro;
float teta;
} pol;
} Coordonate;
float pi=3.1415926;
Coordonate p1, p2;
...
printf("%d%d\n",p1.cart.abscisa,p1.cart.ordonata);
printf("%f%f\n",p2.pol.ro,p2.pol.teta);

O variabil\ de tip Coordonate, cum sunt de pild\ p1 [i p2, poate con]ine fie valori `ntregi
reprezent=nd coordonatele carteziene fie valori flotante reprezent\nd coordonatele polare. Desigur c\ `n
acest caz se presupune c\ prin program se afl\ c\ p1 este de tip cart iar p2 este de tip pol. Declara]iile
precedente pot fi modificate astfel (pentru a memora `n variabil\ `ns\[i tipul de reprezentare ales) :

typedef enum {cart=1,pol=2,nec=0} TipCoord;
typedef union {
TipCoord tip;
struct {
TipCoord tip;
long abscisa;
long ordonata;
} cart;
struct {
TidCoord tip;
float ro;
float teta;
} pol;
} Coordonate;


C=mpul tip este prezent `n toate alternativele uniunii [i el poate fi consultat prin referin]a
p1.tip sau p1.cart.tip sau p1.pol.tip. Se mai poate elimina [i aceast\ redondan]\ prin urm\toarea
declara]ie:

typedef struct {
TipCoord tip;
union {
struct {
long abscisa;
long ordonata;
Programare_ Limbajul_C

65
} cart;
struct {
float ro;
float teta;
} pol;
} val;
} Coordonate;

Dezavantajul este c\ numirea coordonatelor se face printr-o cascad\ mai mare :
p1.val.cart.abscisa
p1.val.cart.ordonata , dac\ p1.tip=1
p2.val.pol.ro
p2.val.pol.teta , dac\ p2.tip=2

7.7. Exerciii

1. Scrie]i un program pentru consultarea unei agende telefonice la nivelul personalului unei societ\]i.
Pentru aceasta va trebui s\ se realizeze urm\toarele:
1.1 crearea agendei telefonice sub forma unui fi[ier text. Acest fi[ier va con]ine o mul]ime de linii,
fiecare av=nd c=te dou\ c=mpuri: un [ir de caractere ce `nseamn\ identitatea abonatului [i un num\r care
corespunde num\rului s\u de telefon. Iat\ un exemplu:
andrei 1427
anca 2130
ana 2131
barbu 2140
bogdan 1430

[tefan 2143
victor 2114
zeno 1442
1.2 crearea programului care realizeaz\ urm\toarele:
a) ini]ializarea unui tablou de elemente structurate prin citirea fi[ierului ce reprezint\
agenda telefonic\;
b) consultarea agendei: la furnizarea unui nume programul ofer\ num\rul de telefon
corespunz\tor (dac\ acesta exist\).
De exemplu:
anca
tel.: 2130
anuta
persoan\ necunoscut\
[tefan
tel.: 2143
quit
2. S\ se scrie un program care s\ realizeze:
a) alc\tuirea unei liste de adrese care folose[te un tablou de structur\ pentru stocarea
informa]iilor legate de adrese (nume, strada, ora[, codul po[tal);
b) completarea tabloului de structuri cu noi adrese;
c) afi[area pe ecran a listei de adrese.
Gheorghe GRIGORA

66

7.8. Soluii
1. Vom construi dou\ func]ii pentru c\utarea `n agenda telefonic\: caut\_secv pentru c\utarea secven]ial\
[i caut\_dih pentru c\utarea dihotomic\(binar\).

# include <stdio.h>
# include <string.h>
# define dim_agenda 100
# define lung_nume 20
typedef char sir[lung_nume]
typedef struct {
sir nume;
int tel;
} persoana;
/* s-a definit o structura de tip persoana*/
persoana agenda[dim_agenda];
/* s-a definit agenda ca un tablou de persoane */
int n=0; /* numarul persoanelor din agenda */
/* urmeaza functia de cautare secventiala */
int cauta_secv(char cineva[ ]) {
int compar=1;
int i=0;
while ((compar>0) && (i<n)) {
compar=strcmp(cineva, agenda[i].nume);
i++;
}
return (compar==0)? i-1:-1;
}
/* urmeaza functia de cautare dihotomica */
int cauta_dih(char cineva[ ]){
int compar=1;
int i;
int a=0;
int b=n-1;
while ((compar!=0) && (a<=b)) {
i=(a+b)/2;
compar=strcmp(cineva,agenda[i].nume);
if (compar<0)
b=i-1;/* se cauta in prima parte */
else if (compar>0)
a=i+1;/* se cauta in a doua parte */
}
return (compar==0)? i:-1;
}
int main(void){
FILE* fisier;
sir cineva;
int i, fin=0;
/* initializarea agendei telefonice */
fisier=fopen("telefon.txt","r");
do {
Programare_ Limbajul_C

67
fscanf(fisier,"%s%d",&(agenda[n].nume), &(agenda[n].tel));
n++;
} while (!feof(fisier));
printf("Consultare agenda telefonica\n");
printf("\t Dati prenumele celui cautat \n");
printf("\t sau "quit" pentru sfarsit \n");
while (!fin) {
printf(">");
scanf("%s", & cineva);
fin=(strcmp(cineva, "quit")==0);
if (!fin) {
i=cauta_secv(cineva);
/* sau
i=cauta_dih(cineva);
*/
if (i==-1)
printf("tel.%s:necunoscut!\n",cineva);
else printf("tel.%s:%d\n",cineva,agenda[i].tel);
}
}
return 0;
}

2. Programul con]ine func]iile:
init_lista -ini]ializarea listei;
select_meniu -afi[area op]iunilor;
introducere -ad\ugarea unui nou nume `n urm\toarea
structur\ liber\;
gaseste_liber -exploreaz\ tabloul de structuri `n c\utarea
unui element nefolosit;
sterge -[tergerea unei adrese;
afiseaz\ -afi[area listei de adrese.



/* Program pentru listarea unor adrese folosind un **tablou de structuri*/

# include <stdio.h>
# include <stdlib.h>
# define MAX 100
struct adresa {
char nume[30];
char strada[40];
unsigned long int numar;
char oras[20];
unsigned long int cod_postal;
} adresa_info[MAX];
void init_lista(void), introducere(void);
void sterge(void), afiseaza(void);
int select_meniu(void), gaseste_liber(void);
void main(void){
char optiune;
init_lista();
Gheorghe GRIGORA

68
for(;;) {
optiune=select_meniu();
switch(optiune) {
case 1: introducere();
break;
case 2: sterge();
break;
case 3: afiseaza();
break;
case 4: exit(0);
}
}
}
void init_lista(void){
register int t;
for(t=0;t<MAX;++t)adresa_info[t].nume[0]= \0;
}
int select_meniu(void){
char s[80];
int c;
printf("1. Introduceti un nume \n");
printf("2. Stergeti un nume \n");
printf("3. Afisati fisierul \n");
printf("4. Iesire din program \n");
do {
printf("\n Introduceti optiunea dvs.: ");
gets(s);
c=atoi(s);
} while (c<0 || c>4);
return c;
}
void introducere(void){
int liber;
char s[80];
liber=gaseste_liber();
if (liber==-1) {
printf("\n Lista este completa. ");
return;
}
printf("Introduceti numele: ");
gets(adresa_info[liber].nume);
printf("Introduceti numele strazii: ");
gets(adresa_info[liber].strada);
printf("Introduceti numarul: ");
gets(s);
adresa_info[liber].numar=strtoul(s, \0,10);
printf("Introduceti numele orasului: ");
gets(adresa_info[liber].oras);
printf("Introduceti codul postal: ");
gets(s);
adresa_info[liber].cod_postal=
strtoul(s, \0,10);
Programare_ Limbajul_C

69
}
gaseste_liber(void){
register int t;
for(t=0;adresa_info[t].nume[0]&&t<MAX;++t);
if (t==MAX) return -1;
/* Nu mai este loc in lista*/
return t;
}
void sterge(void){
register int liber;
char s[80];
printf("Introduceti nr. inregistrarii: ");
gets(s);
liber=atoi(s);
if (liber>=0 & liber<MAX)
adresa_info[liber].nume[0]= \0;
}
void afiseaza(void){
register int t;
for (t=0; t<MAX; ++t) {
if (adresa_info[t].nume[0]) {
printf("%s\n",adresa_info[t].nume);
printf("%s\n",adresa_info[t].strada);
printf("%lu\n",adresa_info[t].numar);
printf("%s\n",adresa_info[t].oras);
printf("%lu\n",
adresa_info[t].cod_postal);
}
}
printf("\n\n");
}



Cap 8 GESTIUNEA MEMORIEI





8.1 Precizarea unui mecanism de memorare
8.2 Gestiunea automat\ a memoriei
8.3 Gestionarea register a memoriei
8.4 Gestionarea static\ a memoriei
8.5 Variabile globale
8.6 Declararea variabilelor externe
8.7 Gestiunea dinamic\ a memoriei
8.8 Exerci]ii
8.9 Solu]ii















Limbajul C ofer\ programatorului posibilitatea de a preciza mecanismul pe care-l dore[te pentru
memorarea unei variabile. Acest mecanism se refer\ la gestionarea memoriei `n cursul execu]iei
programului. Memorarea poate fi:
static\, `n segmentul datelor programului;
automat\, `n stiva de execu]ie;
dinamic\, `n memoria disponibil\;
`ntr-un registru al calculatorului.

~n general programatorul nu trebuie s\ se g=ndeasc\ explicit la un mecanism anume de memorare.
Compilatorul asociaz\ `n mod automat unei variabile un tip de memorare care corespunde locului unde s-
a f\cut declararea. ~n acela[i timp `ns\, nu este lipsit de interes ca programatorul s\ cunoasc\
particularit\]ile fiec\rui tip de mecanism de memorare [i de asemenea s\ cunoasc\ modul `n care
compilatorul va administra variabilele pe care le declar\ `n program.


Programare_ Limbajul_C

71
8.1. Precizarea unui mecanism de memorare

Programatorul are posibilitatea s\ precizeze un mecanism de memorare prin instruc]iunea:




unde: mem este unul din cuvintele cheie: auto, register, static, extern;
tip este cuv=ntul cheie ce define[te tipul variabilei;
identificator este numele variabilei.
A[adar, o variabil\ este identificat\ printr-un nume (identificator), posed\ un anume tip [i este
administrat\ de un anume mecanism de memorare.
Tipul variabilei va determina:
- dimensiunea zonei de memorie alocat\ pentru a reprezenta variabila;
- interpretarea con]inutului variabilei atunci c=nd ea este supus\ unor instruc]iuni.
Categoria de memorare (mem) c\reia-i apar]ine variabila va determina:
- vizibilitatea variabilei: identificarea p\r]ii din program capabil\ s\ foloseasc\ acea variabil\;
- durata de via]\ a variabilei: perioada de timp `n care variabila este accesibil\;
- ini]ializarea variabilei: con]inutul implicit (dac\ exist\ unul) al variabilei la crearea sa.
Vom trece `n revist\ aceste mecanisme de memorare.

8.2. Gestiunea automat a memoriei

Variabilele cu gestiune automat\ corespund variabilelor alocate `n stivele de execu]ie. Declararea se
face prin:



[i trebuie s\ fie totdeauna `n interiorul unui bloc. Cuv=ntul cheie auto nu este obligatoriu; `n lipsa
acestuia, o variabil\ definit\ `ntr-un bloc va fi o variabil\ cu gestiune automat\. Durata de via]\ [i
vizibilitatea unei variabile auto vor fi limitate la interiorul blocului `n care este definit\, `ncep=nd cu
locul de declarare. Ini]ializarea unei variabile auto se va efectua la fiecare intrare `n bloc; valoarea
ini]ial\, dac\ nu este dat\ explicit, va fi nedefinit\. S\ mai not\m c\ limbajul C standard (ISO) permite
ini]ializarea tablourilor [i structurilor `n cazul gestiunii automate a memoriei.
Exemple:
auto float x;
auto float *p = &x;
char mesaj[ ] = "Mesaj initial";
/*cuvantul auto a fost omis;el este implicit */
/* x are o valoare nedefinita pe cand p este un
**pointer care are ca valoare adresa lui x */
8.3. Gestionarea register a memoriei




Cuv=ntul cheie register permite programatorului s\ indice faptul c\ variabila ce se define[te se
memoreaz\ `n unul din regi[trii calculatorului.
Cum num\rul de regi[tri este limitat [i depinde de tipul de ma[in\ pe care ruleaz\ programul, cerin]a
aceasta este satisf\cut\ `n mod real doar dac\ este posibil\. Utilizarea acestei clase de memorare trebuie
mem tip identificator;
auto tip identificator ;
register tip identificator ;
Gheorghe GRIGORA

72
v\zut\ ca o directiv\ de optimizare dat\ compilatorului; acesta ]ine cont de ea at=ta timp c=t exist\ regi[tri
disponibili `n ma[in\.
Declara]ia register trebuie s\ fie plasat\ `n interiorul unui bloc. Ea este efectiv\ doar pentru
variabilele care pot fi codificate pe un cuv=nt-ma[in\: caractere, `ntregi, pointeri. ~n plus, este imposibil a
se ob]ine adresa unei astfel de variabile.
Valoarea ini]ial\ a unei variabile registru este, implicit, nedefinit\.
Exemple de utilizare a unor astfel de variabile sunt `n solu]ia exerci]iului 2 din capitolul precedent.

8.4. Gestionarea static a memoriei




Variabilele statice sunt alocate `n segmentul de date al programului; durata lor de via]\ este timpul de
execu]ie al programului `nsu[i. Implicit sunt ini]ializate cu 0 la `nc\rcarea programului, `nainte de
execu]ia func]iei main. ~n cazul tablourilor sau structurilor, ansamblul c=mpurilor va fi ini]ializat cu zero.
Vizibilitatea unei astfel de variabile statice depinde de locul `n care a fost declarat\:
- `n interiorul unui bloc: va fi vizibil\ doar `n blocul acela (la fel ca variabilele auto);
- `n exteriorul unui bloc: va fi vizibil\ `ncep=nd cu definirea sa p=n\ la sf=r[itul fi[ierului.

8.5. Variabile globale

O variabil\ global\ este o variabil\ static\ care poate fi referen]iat\ `n orice loc al programului. O
astfel de variabil\ se declar\ prin:




`n exteriorul oric\rui bloc; prin urmare nu se poate defini o variabil\ global\ `n corpul unei func]ii. Ea este
definit\ `ncep=nd cu declara]ia sa, p=n\ la sf=r[itul fi[ierului surs\. Pentru a defini o variabil\ global\ `n alt
fi[ier, se folose[te cuv=ntul cheie extern. Este u[or de `n]eles c\, utilizarea unei variabile globale vine
`n contradic]ie cu principiile program\rii modulare. ~n acela[i timp ele permit:
- evitarea transmiterii unor argumente la func]ii apelate, oferindu-le posibilitatea s\ accead\ la
aceste argumente, declarate `n alte fi[iere, [i av=nd `n fi[ierul local specificarea extern. Aten]ie
`ns\ c\ o variabil\ global\ poate fi modificat\ indirect pe perioada apelului la o func]ie.
- ini]ializarea structurilor [i tablourilor fie `n mod explicit indic=nd valori ini]iale, fie implicit cu
valori 0.

8.6. Declararea variabilelor externe
O variabil\ extern\ poate fi declarat\ `n orice punct al programului prin:



Aceast\ declara]ie permite declararea local\ a unei variabile definit\ `n alt fi[ier(cu acela[i nume).
Aceast\ facilitate este legat\ de faptul c\ limbajul C permite compilarea [i legarea separat\ a diferitelor
module de program: prin declararea unei variabile extern se comunic\ tuturor fi[ierelor variabilele globale
necesare programului. Cuv=ntul rezervat extern indic\ compilatorului faptul c\ tipurile [i numele
variabilelor care urmeaz\ au fost declarate `n alt\ parte [i nu mai aloc\ din nou spa]iu de memorie pentru
acestea.

static tip identificator ;
tip identificator ;
extern tip identificator ;
Programare_ Limbajul_C

73
Exemple:
Fi[ier 1 Fi[ier 2 Fi[ier 2
int x,y; extern int x, y; extern int x,y;
char c; extern char c; extern char c;
main(void){ fun1(void){...x=...}; funct1(void)
... fun2(void){...y=...}; {
} ... x=..
... ..
}
~n cazul declar\rii func]iilor ce se definesc `n alt modul (fi[ier), cuv=ntul extern este facultativ.
Declara]ia:
extern void functie(char);
este echivalent\ cu:
void functie (char);
~n cazul func]iilor important este s\ se descrie signatura sa, adic\ tipul rezultatului [i al parametrilor de
apel.

8.7. Gestiunea dinamic a memoriei

Gestiunea dinamic\ a memoriei permite crearea de noi variabile pe parcursul execu]iei programului.
Aceast\ gestiune se efectueaz\ `n memoria disponibil\ care se nume[te gr\mad\ (heap). Durata de via]\
a unei variabile alocat\ dinamic este explicit\:
-variabila este creat\ `n urma execu]iei opera]iei de alocare a memoriei (func]ia malloc `n C [i
operatorul new `n C++);
-variabila dispare `n urma execu]iei opera]iei de restituire a memoriei (func]ia free `n C [i operatorul
delete `n C++).
S\ not\m c\ o variabil\ alocat\ dinamic nu are un nume explicit. Ea este referen]iat\ folosind o variabil\
pointer (vezi cap. 6) care con]ine adresa sa. De aceea, vizibilitatea unei variabile alocat\ dinamic este
legat\ de tipul de gestiune al pointerilor care referen]iaz\ indirect acea variabil\. De exemplu:
Persoana *ptr;
ptr=malloc(sizeof(Persoana));
Avem aici de-a face cu o variabil\ alocat\ dinamic care este referen]iat\ cu ajutorul pointerului ptr prin
*ptr.
8.8. Exerciii

1. S\ se construiasc\ un program, format din trei module, care s\ implementeze func]iile uzuale aplicate
unei stive de caractere: push, pop, top, stiva_vid\, stiva_plin\. Modulele vor fi:
-stiva.h, care con]ine declara]iile func]iilor din modulul stiva.c;
-stiva.c, care con]ine implementarea func]iilor;
-prog.c, care con]ine modulul principal.
2. Defini]i un modul pentru gestionarea unei stive de [iruri de caractere. Caracteristicile modulului sunt
definite `n fi[ierul header stiva.h care are con]inutul:
# define dimensiune_sir 80
# define dimensiune_stiva 10
typedef char sir[dimensiune_sir];
void push(const sir ch);
void pop(sir ch);
int stiva_vida(void);
int stiva_plina(void);
Gheorghe GRIGORA

74
Utiliza]i func]iile de manipulare a [irurilor de caractere (Anexa ) pentru definirea func]iilor acestui modul.
Pornind de la acest modul scrie]i un program test care realizeaz\:
a) citirea unui [ir de [iruri de caractere care se vor `mpinge `n stiv\ (se vor stivui); citirea se va face
p=n\ la `nt=lnirea sf=r[itului de fi[ier sau p=n\ la umplerea stivei;
b) scoate [irurile din stiv\ [i le afi[eaz\ (evident `n ordinea invers\ stivuirii).
8.9. Soluii

1. /* stiva.h : header ce contine declaratiile **functiilor din modulul stiva.c */
void push(char);
void pop(void);
char top_stiva(void);
int stiva_vida(void);
int stiva_plina(void);
/* stiva.c : modul de gestionare a stivei de **caractere */
# define dim 100;
static char stiva[dim];
static int index=0;
void push(char c){stiva[index++]=c;}
void pop(){--index;}
char top_stiva(){return(stiva[index-1]);}
int stiva_vida(){return(index==0);}
int stiva_plina(){return(index==dim);}
/* prog.c : modulul principal */
# include "stiva.h"
# include "stiva.c"
# include <stdlib.h>
# include <stdio.h>
int main()
{
char element;
printf("Incarcati stiva: \n>");
while(!stiva_plina()&&scanf("%c",&element)!=EOF){
push(element); printf(">");
}
printf("\n");
printf("Iata continutul stivei: \n");
while (!stiva_vida()) {
element=top_stiva(); printf("<%c\n",element);
pop();
}
return 0;
}
2. /*stiva.h*/
# define dimensiune_sir 80
# define dimensiune_stiva 10
typedef char sir[dimensiune_sir];
void push(const sir ch);
void pop(sir ch);
int stiva_vida(void);
int stiva_plina(void);
/*modul.c
Programare_ Limbajul_C

75
** Gestionarea unei stive de siruri de caractere.
*/
# include <stdio.h>
# include <assert.h>
# include <string.h>
# include "stiva.h"
/*
** variabile cu clasa de memorare *static*,
**nevizibile in alte fisiere.
*/
static int index=0;
/* indicile top-ului stivei */
static sir stiva[dimensiune_stiva];
void push(const sir c){
/* Se copie c in stiva dupa care se incrementeaza **index. Inainte de aceasta se apeleaza
functia **assert care impune o conditie pentru a continua **executia: stiva sa nu fie plina.
*/
assert(!stiva_plina());
strcpy(stiva[index],c);
index++;
}
void pop(sir c){
/* se decrementeaza index apoi se copie top-ul **stivei in c */
assert(!stiva_vida());
--index;
strcpy(c,stiva[index]);
}
int stiva_vida(void){ return(index==0);}
int stiva_plina(void){
return(index==dimensiune_stiva);
}
/* test.c : programul de test ce consta din doua **iteratii: prima pentru citirea din fisierul de
**intrare si stivuirea informatiei, a doua pentru **afisarea rezultatului destivuirii.
*/
# include <stdio.h>
# include "stiva.h"
int main(void){
sir x;
printf("Se incarca stiva: \n>");
while(!stiva_plina()&&scanf("%s",x)!=EOF) {
push(x);
printf(">");
}
printf("\n");
printf("Iata continutul stivei: \n");
while (!stiva_goala()) {
pop(x);
printf("<%s\n",x);
}
return 0;
}


Cap 9 CONVERSIA DE TIP




9.1 Mecanisme de conversie
9.1.1. Conversia la asignare
9.1.2. Evaluarea expresiilor aritmetice
9.1.3. Evaluarea expresiilor logice
9.1.4. Conversii explicite
9.1.5. Conversii de pointeri. Pointerul universal.










Conversia de tip `n limbajul C ofer\ un mecanism simplu pentru evaluarea expresiilor aritmetice [i
pentru transmiterea parametrilor. Trebuie s\ facem distinc]ia `ntre dou\ maniere de conversie: aceea care
are drept scop schimbarea interpret\rii con]inutului unei variabile [i conversia care are drept consecin]\
modificarea con]inutului unei variabile. ~n primul caz de pild\, se poate interpreta con]inutul unei
variabile de tip caracter ca fiind o valoare `ntreag\ [i drept urmare posibilitatea utiliz\rii acesteia `ntr-o
expresie aritmetic\. ~n al doilea caz se poate converti o valoare real\ la o valoare `ntreag\; ca o consecin]\
se pierde valoarea frac]ionar\ a variabilei reale.

9.1. Mecanisme de conversie


Se disting patru cazuri `n care `ntr-un program C se aplic un mecanism de conversie:
1. asignarea cu tipuri diferite ale variabilelor termeni ai asignrii:
float f;
int i=10;
f=i;
2. evaluarea unei expresii aritmetice sau logice n care componentele expresiei au tipuri diferite:
float pi=3.14;
int i=2;
......
if (pi>2)
pi=pi/i;
3. utilizarea operatorilor de conversie:

float f1=(float)14/5; /* f1=2.8 */
Programare_ Limbajul_C

77
float f2=14/5; /* f2=2.0 */
apelul unei funcii:
printf(%d\n,z);
/*caracterul z este convertit la un intreg */
~n cazul `n care se utilizeaz\ operatori de conversie, compilatorul este cel care gireaz\ aceste
conversii. Conversiile `ntre tipurile de baz\ ale limbajului sunt considerate permise iar tratamentul la care
sunt supuse datele de c\tre compilator este bine stabilit de regulile limbajului. Alte conversii `n care
intervin tipuri definite de programator sunt considerate ilicite [i sunt respinse de compilator. Vom detalia
`n continuare aceste mecanisme.
9.1.1 Conversia la asignare

~n conversia la asignare, c=nd apar dou\ tipuri diferite, lucrurile se petrec dup\ cum urmeaz\:
1. asign\ri `n care intervin dou\ tipuri `ntregi:
(a) reprezentarea tipului surs\ este mai mare ca dimensiune dec=t
reprezentarea tipului destinatar:
char=short/int/long
short=int/long
int=long
~n acest caz bi]ii de rang superior din valoarea din partea dreapt\ a asign\rii sunt suprima]i `nc=t
exist\, poten]ial, o pierdere de informa]ie.
(b) reprezentarea tipului destinatar este mai mare ca dimensiune
dec=t cea a tipului surs\:
long=int/short/char
int=short/char
short=char
~n acest caz nu exist\ pierdere de informa]ie: bi]ii sursei sunt completa]i cu zero (p\str=ndu-se
eventualul bit semn). Dac\ destinatarul este un tip far\ semn, mecanismul este acela[i; bitul semn `n
schimb nu se mai transfer\:
unsigned long=int/short/char
unsigned=short/char
unsigned short=char
2. asignarea unei valori reale la o valoare `ntreag\:
char/short/int/long=float/double

~n acest caz sunt suprimate cifrele de la partea zecimal\: este conversie prin trunchiere [i nu prin
rotunjire. Dac\ valoarea p\r]ii `ntregi a sursei este prea mare pentru a fi reprezentat\ `ntr-un `ntreg, apare
o eroare (Floating point exception).
3. asignarea unei valori reale `n dubl\ precizie la o variabil\ real\ `n simpl\ precizie:
float=double

~n acest caz exist\ o pierdere a preciziei reprezent\rii valorii reale. Poate ap\rea [i aici eroarea
Floating point exception dac\ partea exponent este prea mare pentru o variabil\ real\ `n simpl\ precizie.
9.1.2 Evaluarea expresiilor aritmetice

- tipurile `ntregi mai mici dec=t int sunt convertite la int;
- tipul float este convertit la double;
Faza II:
- se alege tipul de evaluare: `ntreg, real, f\r\ semn, etc.
~n rezumat, lucrurile se petrec astfel:


Gheorghe GRIGORA

78

Dac\ un operand este: Cel\lalt operand se converte[te la: Rezultatul este:
double double double
unsigned long unsigned long unsigned long
long long long
unsigned unsigned unsigned
Exemple:

i
(int)
+ c
(char)
Faza 1:
Faza 2:
Rezultatul:
int
int


int
int
int

i
(int)
+ (a
(long)
+ b)
(float)
Faza 1
Faza 2
Rezultat
Faza 1
Faza 2
Rezultat



int
double





double
long
double


double
double
double
double
double

9.1.3. Evaluarea expresiilor logice
Rezultatul evalu\rii unei expresii logice va fi 0 (reprezent=nd false) sau 1 (reprezent=nd true). De
aceea evaluarea unei expresii logice se face prin:
evaluarea operanzilor: dac\ valoarea aritmetic\ este 0 atunci aceasta se interpreteaz\ prin false,
`n caz contrar prin true;
asignarea valorilor 0-1: dac\ evaluarea expresiilor este false (true), valoarea asignat\ acesteia
este 0 (1).
Exemple:
x=50;
b=(x>0) && (x<31); /* b capata valoarea 0 */
i=10
while (i--) {
.....
}
~nainte de prima evaluare a expresiei i- -, i are valoarea 10 deci expresia cap\t\ valoarea true,
dup\ care, i se decrementeaz\, etc.

9.1.4 Conversii explicite

Conversiile explicite se exprim\ prin:
(tip) expresie
sau
tip ( expresie )
At=ta timp c=t conversia este permis\, rezultatul expresiei este convertit la tipul indicat. Operanzii ce
apar `n aceast\ expresie r\m=n neschimba]i.
Ace[ti operatori de conversie permit programatorului s\ specifice o conversie care nu se face implicit
de c\tre compilator. Ace[tia pot fi utiliza]i:
- pentru for]area conversiilor `n expresii;
Programare_ Limbajul_C

79
- pentru transmiterea valorilor cu tipurile cerute ca parametri `n func]ii;
- schimbarea tipului valorii returnate de o func]ie.
Exemple:
int a=21; b=4;
float f;
double r;
f=a/b; /* f5.0; */
f=(float)a/b; /* f=5.25; */
f=a/(float)b; /* f=5.25; */
....
r=sqrt(double(a));
....
a=(int)ceil(r);
/*functia ceil returneaza o valoare de tip intreg*/

9.1.5 Conversie de pointeri. Pointerul universal

Conversia `ntre pointeri la tipuri diferite nu este implicit\. Compilatorul for]eaz\ conversia [i afi[eaz\
un mesaj de avertisment (warning) `ntotdeauna c=nd `ntr-un program apare o astfel de conversie. S\
consider\m de pild\ urm\toarea secven]\:
char *alocare(int dim);
int *ptr;
ptr = alocare(100);
~n cea de-a treia linie a secven]ei de mai sus apare o asignare `ntre pointeri incompatibili. Aceast\
incompatibilitate se poate evita `n dou\ moduri. O prim\ solu]ie const\ `n a utiliza o conversie explicit\:
....
ptr=(int*) alocare(100);
O a doua solu]ie const\ `n a utiliza tipul pointer universal void*. O variabil\ pointer de tip void* poate
primi ca valoare pointer la un tip oarecare. Reciproc, o valoare de tip void* este implicit convertit\ la o
valoare pointer de un tip oarecare. Pentru exemplul precedent se procedeaz\ astfel:

void* alocare(int dim);
int* ptr1
double* ptr2
ptr1=alocare(10);
ptr2=alocare(20);

Asign\rile pentru ptr1, ptr2 sunt corecte: tabloul de pointeri alocare este de tip void* `nc=t ace[ti
pointeri pot fi asigna]i la pointeri de orice tip.
Tipul pointer universal void* este folosit frecvent `n func]iile disponibile din bibliotecile limbajului C
(Anexa) `n scopul de a realiza conversii implicite `ntre pointeri de tipuri diferite.


Cap 10 PREPROCESORUL




10.1 Directive preprocesor
10.1.1 Constante simbolice. Directiva #define
10.1.2 Includerea fi[ierelor
10.1.3 Compilare condi]ionat\
10.1.4 Directiva #error
10.2 Macroinstruc]iuni
10.2.1 Macroinstruc]iuni predefinite
10.2.2 Macroinstruc]iuni tip func]ie





~n codul surs\ al unui program C se pot include instruc]iuni destinate compilatorului; acestea se
numesc directive pentru preprocesor.
Preprocesorul realizeaz\ o faz\ de precompilare care are ca obiect:
includerea unor fi[iere (specificate) `n program;
compil\ri condi]ionate conform unor parametri (valori) transmise `n comanda de compilare;
definirea unor constante simbolice;
definirea macroinstruc]iunilor. Programatorul asociaz\ o secven]\ de instruc]iuni unui
identificator. La apari]ia acestui identificator `n program, preprocesorul substituie secven]a
corespunz\toare de instruc]iuni `n locul acestui identificator.
Precompilarea este o faz\ de prelucrare independent\ de compilarea propriu-zis\. ~n acela[i timp `ns\,
ea face parte integrant\ din procesul de compilare: apelul compilatorului pentru un program execut\ mai
`nt=i `nc\rcarea preprocesorului. Rezultatul activit\]ii preprocesorului este un fi[ier surs\ `n care sunt
tratate toate directivele de precompilare [i care este transmis compilatorului.

10.1 Directive preprocesor

Preprocesorul trateaz\ doar liniile ce `ncep prin caracterul #; acestea sunt directive c\tre
preprocesor. O directiv\ este de forma:

# instruc]iune argumente

Principalele instruc]iuni pentru preprocesor sunt:

define ifndef undef
if else endif
elif include ifdif
line error pragma

De notat c\ un r=nd `n fi[ierul surs\ C nu poate con]ine mai mult de o directiv\.
Programare_ Limbajul_C

81
10.1.1 Constante simbolice. Directiva #define

O constant\ simbolic\ asociaz\ unui identificator un [ir de caractere. Preprocesorul `nlocuie[te fiecare
apari]ie a identificatorului, `n textul surs\, prin [irul de caractere asociat. Constanta simbolic\ se define[te
cu directiva define:

# define identificator [ir_de_caractere


Exemple:
# define NULL 0L
# define TRUE 1
# define FALSE 0
# define EOF (-1)
Utilizarea constantelor simbolice are diverse scopuri. Acest mecanism permite:
a asigna unui identificator un [ir de caractere;
a defini existen]a unei constante simbolice:
# define ident
a suprima defini]ia [i existen]a unei constante simbolice:
# undef ident
Vizibilitatea constantelor simbolice `ncepe cu definirea lor (directiva #define) [i ]ine p=n\ la
sf=r[itul fi[ierului, cu excep]ia cazului c=nd `n acesta apare o directiv\ #undefine pentru
identificatorul corespunz\tor.
Exemplu:
# define EOF (-1)
....
# define UNU
....
# undefine UNU
....

10.1.2 Includerea fiierelor

Directiva #include cere compilatorului s\ ia `n considerare [i un alt fi[ier surs\ `n afar\ de cel `n care
se afl\ directiva. Forma acestei directive este:

# include <nume_fisier>
/* se caut\ fi[ierul `ncep=nd cu directoarele standard */
sau
# include nume_fisier
/* se caut\ fi[ierul `n directorul curent sau cel indicat prin cale */

Includerea fi[ierelor poate fi utilizat\ pentru:
a insera fi[iere surs\ din biblioteci C care pot con]ine module de aplica]ii sau defini]ii de func]ii;
a insera fi[iere header (care au extensia .h). Aceste fi[iere con]in:
1. constante simbolice [i macroinstruc]iuni standard;
2. declara]ii de func]ii incluse `ntr-o bibliotec\;
3. defini]ii de tipuri.
4.
Exemplu Pentru a folosi func]iile din biblioteca matematic\ se include fi[ierul math.h care con]ine
declararea acestor func]ii:

Gheorghe GRIGORA

82
# include <math.h>
....
val=pow(M_PI, (double)n);
/* se calculeaza puterea a n-a a lui */
~n fi[ierul math.h se afl\ defini]ia constantei M_PI [i a func]iei pow( ).

10.1.3 Compilare condiionat

Directivele de compilare condi]ionat\ permit compilarea selectiv\ a unor por]iuni din programul
surs\. Aceste directive sunt:

# if expr_constanta
# else
# endif
# elif expr_constanta
# ifdef identificator
# ifndef identificator

Directiva if prin expr_constant\ care urmeaz\ dup\ ea permite includerea por]iunii de cod `ntre
if [i endif `n procesul de compilare, doar dac\ expresia este evaluat\ la true (`n caz contrar aceast\
por]iune de cod este ignorat\ de compilator).
Directiva else ofer\ o alternativ\ `n cazul `n care if e[ueaz\; este asem\n\toare instruc]iunii if-
else din limbajul C.
Directiva elif are sensul de else if; ea poate determina un lan] de if-else-if:

# if expresie
cod;
# elif expresie1
cod1;
# elif expresie2
cod2;
....
# elif expresien
codn;
# endif
Directivele ifdef (if defined) [i ifndef (if not defined) sunt utilizate pentru compilarea
condi]ionat\ de definirea anterioar\ a lui identificator `ntr-o directiv\ de tipul #define. Ambele
directive pot folosi o alternativ\ de forma #else dar nu [i #elif.
~n concluzie, compilarea condi]ionat\ este folosit\ pentru:
scrierea de programe portabile: constantele simbolice ce se testeaz\ pot reprezenta tipul [i
caracteristicile ma[inilor utilizate pentru o anume por]iune de cod;
optimizarea unor coduri utiliz=nd avantajele specifice fiec\rei ma[ini;
traseul de execu]ie al programelor `n faza de test.

10.1.4 Directiva #error

Directiva #error cere compilatorului s\ sisteze compilarea. Are forma:
# error mesaj
La `nt=lnirea directivei este `ntrerupt\ compilarea [i se afi[eaz\ mesaj-ul ce este scris `n linia
directivei. Se utilizeaz\ la depanarea programelor.
Programare_ Limbajul_C

83
10.2 Macroinstruiuni

Prin acest mecanism programatorul asociaz\ o secven]\ de instruc]iuni unui identificator.

10.2.1 Macroinstruciuni predefinite

Limbajul standard ANSI C define[te cinci nume de macroinstruc]iuni predefinite, `ncorporate `n
compilator. Acestea sunt:
_LINE_, _FILE_, _DATE_, _TIME_, _STDC_.
Identificatorul _LINE_ con]ine num\rul liniei de cod la compilare iar _FILE_ este un [ir care con]ine
numele fi[ierului surs\ compilat. Con]inutul acestor doi identificatori poate fi modificat prin directiva
#line:
# line num\r;
# line nume_fi[ier;
# line num\r nume_fi[ier;

Aici num\r este orice `ntreg pozitiv; acesta devine noua valoare a lui _LINE_ `n punctul `n care se
`nt=lne[te directiva, iar nume_fi[ier este un identificator valid de fi[ier care devine noua valoare a lui
_FILE_.
Macroinstruc]iunea _DATE_ con]ine un [ir de forma lun\/zi/an `n care lun\, zi, an sunt compuse
din c=te dou\ cifre ce reprezint\ `n ansamblu data conversiei fi[ierului surs\ `n cod obiect. Ora la care a
fost executat\ aceast\ conversie este con]inut\ `n _TIME_ sub forma [irului ora/minute/secunde.
Macroinstruc]iunea _STDC_ con]ine constanta 1 scris\ `n baza 10. Aceasta semnific\ faptul c\
implementarea este conform standardului ANSI C. Dac\ _STDC_ nu-i definit\ sau con]ine altceva dec=t
1, implementarea nu este `n variant\ standard.

10.2.2 Macroinstruciuni tip funcie

Aceste macroinstruc]iuni utilizator se definesc cu directiva #define:
# define nume_macro
secven]\_caractere

Aici, nume_macro poate fi un identificator ce reprezint\ numele macroinstruc]iunii. Acesta, utilizat
`ntr-un text surs\, va fi `nlocuit cu secven]\_caractere care poate `nsemna o secven]\ de instruc]iuni C
(vezi [i 10.1.1). Dar nume_macro poate fi [i numele unei func]ii urmat\ de parametri: prin aceasta se
define[te o macroinstruc]iune de tip func]ie care poate fi apelat\ `n orice punct al programului `n care a
fost definit\.
Exemplu:
# define <stdio.h>
# define ABS(a) (a)<0?-(a):(a)
void main(void){
printf(Valoarea absoluta a lui -1 si 1:
%d%d,ABS(-1),ABS(1));
}
Folosirea func]iilor definite ca macroinstruc]iuni are, pe de o parte, un avantaj major: m\rirea vitezei
de execu]ie a codului fiindc\ nu mai apare nici o `nc\rcare suplimentar\ legat\ de apelarea func]iei. Pe de
alt\ parte `ns\, dac\ dimensiunea macroinstruc]iunii tip func]ie este mare, acest supliment de vitez\ este
anihilat de cre[terea dimensiunii programului, datorit\ codului care apare de mai multe ori.


Cap 11 EXERCIII






1. S\ se scrie un program numit maxmin.c care s\ execute :
a. citirea unui intreg pozitiv n;
b. citirea a n numere reale;
c. determinarea valorilor maxim [i minim dintre cele n numere citite;


2. S\ se scrie un program numit sumedia.c care s\ citeasc\ niste numere reale [i, pentru fiecare
s\ scrie un r=nd `ntr-un tabel ce are forma:

Nr.crt. Num\r Min Max Suma Media
. . . .

unde Min(Max) `nseamn\ cel mai mic(mare) dintre numerele citite p=n\ `n acel moment, Suma [i Media
fiind suma (media) numerelor citite p=n\ `n acel moment


3. S\ se scrie un program care s\ numere literele mici, literele mari , cifrele [i celelalte
caractere(la un loc) dintr-un text(fi[ier).
4. S\ se scrie func]ii recursive pentru calculul factorialului unui num\r dat n, a puterilor 1,2 , k
a unui num\r n, a sumei numerelor naturale m [i n. S\ se foloseasc\ aceste func[ii `ntr-un
program principal.
5. S\ se scrie o func]ie int este_prim(int n) care s\z returneze 1 dac\ num\rul n este prim [i
zero `n caz contrar. S\ se scrie o func]ie fibonacci ( int n) care s\ returneze al n-ulea
termen al [irului lui Fibonacci. S\ se foloseasc\ cele dou\ func]ii pentru a verifica dac\ al n-
ulea termen din [irul lui Fibonacci este num\r prim ( n = 1, , 12).
6. Folosind func]ia este_prim( ) de la exerci]iul precedent, scrie]i un program ce s\ verifice
conjectura lui Goldbach pentru toate numerele pare dintr-un interval dat [a,b] : Orice num\r
par n mai mare ca 2 este suma a dou\ numere prime. De exemplu:
700 = 17 + 683 , 702 = 11 + 691, 704 = 3 + 701, etc.
7. Urm\toarea func]ie calculeaz\, recursiv, cel mai mare divizor comun a dou\ numere `ntregi
pozitive p [i q:
int cmmdc_r(int p, int q)
{
int r;
if (( r = p % q ) == 0 )
return q;
else
return cmmdc_r(q, r);
}
Scrie]i un program pentru testarea acestei func]ii precum [i pentru calculul celui mai mare
divizor comun a n numere date. Scrie]i apoi [i testa]i varianta iterativ\ a func]iei, cu numele :
int cmmdc_i (int p, int q)
8. Descrie]i [i implementa]i trei algoritmi de sortare.
9. Construi]i o func]ie int numar_cuvinte(const char *s) care s\ returneze numarul
cuvintelor din [irul s ( cuvintele sunt desp\r]ite prin spa]iu/spa]ii). S\ se testeze aceast\ func]ie
pentru un [ir anume(fi[ier).
Programare_ Limbajul_C

85

10. S\ se scrie [i apoi s\ se testeze func]ii pentru adunarea a doi vectori [i pentru adunarea a dou\
matrice.
11. S\ se scrie un program `n care s\ se foloseasc\ func]ia sistemului :

void qsort(void *array, size_t n_els,size_t el_size,
int compare(const void *, const void *))

pentru a sorta o list\ de numere reale `n ordinea cresc\toare relativ la p\r]ile frac]ionare a
acestor numere. De exemplu lista:
2.43, 45.01, 23.90, 123.04, 0.98
este sortat\ astfel:
45.01, 123.04, 2.43, 23.90, 0.98

12. S\ se scrie func]iile care implementeaz\ o stiv\ `n C(push, pop, top, etc). S\ se foloseasc\
acestea pentru a verific\ dac\ un [ir de caractere format numai din literele a, b, c este palindrom
cu centrul c:
[irurile: aabacabaa , bababbcbbabab, c, aca, bbcbb
sunt palindroame pe c=nd [irurile:
aabbcbb. ccab, aaaaaaaacaaaabb, acb, aaaa
nu sunt palindroame.

13. Fie a un tablou bidimensional (m x n). Un punct sa al acestui tablou este un element a[i0,j0]
cu proprietatea:
a[i0,j0] = min{a[i0,j] : 0<=j<=n-1} = max{a[i,j0] : 0<=i<=m-1}
Scrieti un program care determina punctele sa (daca exista) ale unui tablou bidimensional.
14. Se da o matrice patratica. Sa se ordoneze crescator fiecare linie a matricii, apoi sa se
rearanjeze liniile astfel incat suma elementelor de pe diagonala sa fie minima.

15. Scrieti un program care, avand la intrare doua siruri de caractere, determina cel mai lung
subsir comun si pozitiile la care acesta incepe in fiecare dintre cele doua siruri.
16. Proiectati structuri de date pentru reprezentarea unui punct, a unui triunghi, dreptunghi, cerc.
Scrieti proceduri de citire si scriere a unui punct, triunghi etc.
Scrieti o procedura care determina, pentru un triunghi dat, numarul punctelor de coordonate
intregi aflate in interiorul sau.
Scrieti o procedura similara pentru cerc.
17. Proiectati o structura de date pentru reprezentarea datei calendaristice si scrieti subprograme
care:
verifica daca valoarea unei variabile din structura este o data valida.
calculeaza data calendaristica care urmeaza unei anumite date.
calculeaza data calendaristica care precede o anumita data.
18. Sa se proiecteze o structura de date pentru reprezentarea multimilor finite de numere
complexe si sa se scrie proceduri care realizeaza operatii cu multimi de numere complexe
reprezentate astfel.


Gheorghe GRIGORA

86

BIBLIOGRAFIE

1. Herbert Schildt C - Manual Complet, Bucuresti, Ed. Teora 1998
2. Liviu Negrescu Limbajele C si C++ pentru incepatori, vol I- III, Cluj-Napoca
Volumul I - Limbajul C
Volumul II - Limbajul C++
Volumul III - Limbajele C si C++ in Aplicatii
3. Cristea,V.,C.Giumale, E.Kalisz. A.P\nsiu, Limbajul C standard. Editura Teora, 1992.
4. Grigora[, Gh. Programarea calculatoarelor:Fundamente, Editura Spiru Haret, Ia[i, 1999.
5. P\tru], B., Aplica]ii `n C [i C++, Editura Teora, Bucure[ti, 1998.
6. Musc\, Gh. [i al]ii, Informatic\ aplicat\, manual pentru licee de informatic\, cls.XI, Editura
Didactic\, Bucure[ti 1998

ANEXA



Biblioteca standard C


FI{IERE HEADER
<assert.h> <limits.h> <signal.h> <stdlib.h>
<ctype.h> <locale.h> <stdarg.h> <string.h>
<errno.h> <math.h> <stddef.h> <time.h>
<float.h> <setjmp.h> <stdio.h>


1. Fi[ierul <assert.h> con]ine macro-ul assert()
void assert (int expr);

Dac\ expr este zero, este tip\rit un mesaj(diagnostic) [i se iese din program.

2. Fi[ierul <ctype.h> con]ine macrouri (func]ii) pentru testarea caracterelor:

int isalnum(int c); /* c este alfanumeric? */
int isalpha(int c); /* c este alfabetic? */
int iscntrl(int c); /* c este car. de control? */
int isdigit(int c); /* c este cifra? */
int isgraph(int c); /* c este car. grafic? */
int islower(int c); /* c este litera mica? */
int isprint(int c); /* c este tiparibil? */
int ispunct(int c); /* c este car. punctuatie? */
int isspace(int c); /* c este spatiu? */
int isupper(int c); /* c este litera mare? */
int isxdigit(int c); /* c este cifra hexa? */

Mai con]ine:
int tolower (int c) [i int toupper ( int c)

funcii ce permit transformarea literelor din mari ]n mici sau invers.

3. Fi[ierul <errno.h> con]ine macrouri folosite pentru raportarea erorilor.

4. Fi[irerul <float.h> con]ine defini]iile unor constante pentru limitele unor valori flotante:
DBL_MAX, FLT_MAX, DBL_MIN, DBL_EPSILON etc.


5. Fi[ierul <limits.h> con]ine defini]iile unor constante ce caracterizeaz\ `ntregii: CHAR_BIT,
CHAR_MAX, INT_MAX etc.
Gheorghe GRIGORA

88
6. Fi[ierul <locale.h> con]ine construc]ii (structuri, func]ii) ce permit setarea unor propriet\]i locale:
forma punctului zecimal, informa]ii monetare etc.

7. Fi[ierul <math.h> con]ine prototipuri pentru func]iile matematice:

double cos ( double x); double acos ( double x);
double sin ( double x); double asin ( double x);
double tan ( double x); double atan ( double x);
double cosh ( double x); double exp ( double x);
double sinh ( double x); double log ( double x);
double tanh ( double x); double log10 ( double x);
double ceil ( double x); double flor ( double x);
double fabs ( double x); double sqrt ( double x);
double atan2 ( double y, double x);
double fmod ( double x, double y);
double pow ( double x, double y);

8. Fi[ierul <setjmp> con]ine declara]ii [i prototipuri ce permite programatorului s\ utilizeze salturi
nelocale.

9. Fi[ierul < signal.h> con]ine construc]ii ce permit programatorului s\ m=nuiasc\ condi]ii sau
semnale excep]ionale.

10. Fi[ierul <stdarg.h> con]ine o redefinire (typedef) de tip [i trei m macrouri ce permit scrierea de
func]ii cu un num\r variabil de argument ( ca [i printf ).


11. Fi[ierul <stddef.h> con]ine defini]ii de tip [i macrouri ce se folosesc `n alte defini]ii:

typedef char wchar_t; /* tipul wide character*/
typedef int ptrdiff_t; /*tipul diferen]\ de pointeri */
typedef unsigned size_t; /*tipul ob]inut din sizeof() */
#define NULL;

12. Fi[ierul <stdio.h> con]ine macrourile, defini]iile de tip [i prototipurile func]iilor utilizate de
programator pentru a accesa fi[iere.
Sunt definite aici constantele BUFSIZ, EOF, FILENAME_MAX, FOPEN_MAX, NULL,
TMP_MAX. De asemenea sunt defini]i pointerii stdin, stdout, stderr [i pentru structura FILE. Func]ii
pentru accesul la fi[iere:

FILE *fopen (const char *filename, const char *mode);
int fclose (FILE *fp);
int fflush (FILE *fp);
FILE *tmpfile (void);
int fseek (FILE *fp, long offset, int place); /* Pozi]ioneaz\ indicatorul pentru urm\toarea opera]ie `n
fi[ier la place + offset */
long ftell (FILE *fp); /* Returneaz\ valoarea indicatorului de pozi]ie a fi[ierului pointat de fp*/
void rewind (FILE *fp); /* Seteaz\ indicatorul la `nceputul fi[ierului */
int fsetpos (FILE *fp, const fpos_t *pos); /* Seteaz\ indicatorul la valoarea pos */
int rename (const char *from, const char *to);
De asemnea fi[ierul mai con]ine prototipurile func]iilor de intrare/ie[ire (vezi cap.4).
Programare_ Limbajul_C

89
13. Fi[ierul <stdlib.h> con]ine prototipurile func]iilor de uz general : alocarea dinamic\ a memoriei,
c\utare binar\, sortare, generare de numere aleatoare, comunicarea cu sistemul, conversie de
stringuri,etc. Iat\ unele dintre ele:

void *calloc(size_t n, size_t el_size);
void *malloc(size_t size);
void *realloc(void *ptr, size_t size);
void free(void *ptr);
void *bsearch(const void *key_ptr, const void *a_ptr, size_t n_els, size_t el_size, int compare(const
void *, const void *));
void qsort(void *a_ptr, size_t n_els, size_t el_size,
int compare(const void *, const void *));
int rand(void);
void srand(unsigned seed);
int abs(int i);
long labs(long i);
div_t div(int numer, int denom);
ldiv_t ldiv(long numer, long denumer);
double atof(const char *s);
int atoi(const char *s);
long atol(const char *s);
double strtod(const char *s);
long strtol(const char *s, char **end_ptr, int base);
void abort(void);
void exit(int status);

14. Fi[ierul <string.h> con]ine prototipuri de func]ii pentru manipularea blocurilor de memorie sau a
[irurilor:

void memcmp(const void *p, const void *q, size_t n);
void *memcpy(void *to, void *from, size_t n);
void *memmove(void *to, void *from, size_t n);
void *memset(void *p, int c, size_t n);
char *strcat(char *s1, const char *s2); /*concatenare*/
char *strchr(const char *s, int c); /*cauta c `n [irul s*/
int strcmp(const char *s1, const char *s2); /* comparare [iruri*/
char *strcpy(char *s1, const char *s2) /* copie s2 `n s1 */
size_strlen(const char *s); /*lungimea [irului s */
char *strncat(char *s1, const char *s2, size_t n); /*concatenarea a cel mult n caractere din s1 la s2*/
int strncmp(const char *s1, const char *s2, size_t n); /* comparare a cel mult n caractere din [irurile s1
[i s2*/
char *strncpy(char *s1, const char *s2, size_t n) /* copie cel mult n caractere din s2 `n s1 */
char *strstr(const char *s1, const char *s2); /* caut\ `n s1 prima apari]ie a lui s2 */
char *strtok(char *s1, const char *s2); /* caut\ tokenuri `n s1 folosind caracterele din s2 ca separatori
*/


15. Fi[ierul <time.h> con]ine prototipuri ale func]iilor pentru ob]inerea datei, orei ]i cele privind ceasul
intern al calculatorului. Se folose[te structura tm care este definit\ astfel:

Gheorghe GRIGORA

90
struct tm {
int tm_sec; /*secunde 0..60*/
int tm_min; /*minutr 0..59 */
int tm_hour; /*ore 0..23 */
int tm_mday; /*ziua lunii 1..31 */
int tm_mon; /*luna anului 0..11 */
int tm_year; /*anul de la 1900 */
int tm_wday; /* zilele de la 0 la 6 */
int tm_yday; /*zilele din an 0..365 */
int tm_isdst; /* Indicator de timp */
};


Func]ii:
typedef long clock_t;
typedef long time_t;
clock_t clock(void); /*returneaz\ num\rul de tacturi CPU utilizate de program p=n\ aici*/
time_t time(time_t *tp); /*returneaz\ nr. de secunde trecute de la 1 Inuarie 1970 */
char *asctime(const struct tm *tp); /*converte[te timpul inregistrat [i pointat de tp `ntr-un string
ce reprezint\ data*/
char *ctime (const time_t *t_ptr); ?8 converte[te timpul pointat de t_ptr la string - data*/
struct tm *localtime(const time_t *t_ptr);

De exemplu:

time_t acum;
acum = time(NULL);
printf("%s\n%s ", ctime(&acum),
asctime(localtime(acum)));
..

are ca efect scrierea datei calenderistice.

Codul ASCII

American Standard Code for Information Interchange
0 1 2 3 4 5 6 7 8 9
0 nul soh stx etx eot enq ack bel bs ht
1 nl vt np cr so si dle dc1 dc2 dc3
2 dc4 nak syn etb can em sub esc fs gs
3 rs us sp ! # $ % &
4 ( ) * + , - . / 0 1
5 2 3 4 5 6 7 8 9 : ;
6 < = > ? @ A B C D E
7 F G H I J K L M N O
8 P Q R S T U V W X Y
9 Z [ \ ] ^ _ a b c
10 d e f g h i j k l m
11 n o p q r s t u v w
12 x y z { | } ~ del
Programare_ Limbajul_C

91


Observa]ii:
Caracterul G este `n linia 7 [i coloana 1 deci are codul ASCII 71;
Caracterele cu codurile 0-31 [i 127 nu sunt tip\ribile;
Caracterul cu codul 32 este spa]iu (gol) [i se tip\re[te ca [i un spa]iu gol;
Codurile caracterelor 0-9, A - Z [i a - z sunt contigue;
Diferen]a `ntre codurile literelor mari [i cele mici corespunz\toare este 32;
~n tabela urm\toare se da semantica unora din caracterele de pe liniile 0-2.


~n]elesul unor abrevieri
bel audible bell ht tab orizontal
bs backspase nl linie nou\
cr retur car nul null
esc escape vt tab vertical


~n sistemele UNIX, comanda man ascii produce afi[area tabelei codurilor ASCII pe ecran.

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