Post on 04-Apr-2018
7/29/2019 Programare in C
1/130
Limbajul de programare C
6.2. Limbajul de programare C
6.2.1. Vocabularul limbajului. Caractere
La scrierea programelorTURBO Cse folosete setul de caractere al codului ASCII.
Caracterele din acest set se codific prin ntregi din intervalul [0,127]. Un astfel de ntreg
poate fi pstrat n binar pe un octet (8 bii). Mulimea caracterelor poate fi mprit n trei
grupe: caractere negrafice, spaiu i caractere grafice.
Spaiulare codul 32. Caracterele negrafice, exceptnd caracterulDEL, care are codul
ASCII127, au coduri ASCIImai mici dect 32. Caracterele grafice au codurile ASCIImai
mari dect 32. n grupa caracterelor grafice distingem: litere mari, litere mici, cifre, caractere
speciale.Literele mari i mici sunt cele ale alfabetului englez. Literele mari au codurile ASCII
n intervalul [65,90]. Valoarea 65 este atribuit literei A, iar 90 literei Z. Celelalte valori
corespund celorlalte litere n aa fel nct ordinea alfabetic a lor s induc ordinea cresctoare
a codurilorASCII.
n mod analog, literele mici au codurile ASCII n intervalul [97,122]. Cifrele 0-9 se
codific prin codurileASCII48-57.
Codul ASCII de valoare zero definete caracterul NUL. Acesta este un caracter
impropriu i spre deosebire de celelalte caractere el nu poate fi generat de la tastatur i nu areefect nici la ieire. El poate fi utilizat pentru a termina un ir arbitrar de caractere deoarece nici
un caracter de la intrare nu poate coincide cu el.
Restul caracterelor negrafice au diferite funcii. Aa, de exemplu, codul ASCII 10
realizeaz deplasarea cursorului n coloana 1 de la linia urmtoare, iar codul 13 deplaseaz
cursorul n coloana ntia de pe aceeai linie. Caracterul cu codul ASCII10 se numete LF
(Line Feed) iar caracterul cu codul ASCII13 se numete CR (Carriage Return). Cele dou
caractere se pot introduce de la tastatur acionnd tasta Enter (numit i RETURN)
obinndu-se caracterul de rnd nou (newline). Acest caracter are i o notaie special n
limbajul C i anume el se noteaz prin: \n. Pentru tabulator se utilizeaz notaia: \t.Caracterele: spaiu, newline, tabulator orizontal le numim caractere sau spaii albe (white
space).
6.2.1.1. Identificatori (nume)
Un identificator (nume), n limbajul C, este o succesiune de litere i eventual cifre,
care ncepe cu o liter. n calitate de litere se folosesc litere mici i litere mari ale alfabetului
englez, precum i caracterul de subliniere (_). Literele mici se consider distincte de cele
134
7/29/2019 Programare in C
2/130
Limbajul de programare C
mari. Exemple corecte de identificatori: ecuatia_de_grad_doi, x1,x2, a, b, anul_I, _functie, A,
XB. Exemplegreite de identificatori: 1_EM, 3_ut.
6.2.1.2. Cuvinte cheie
Un cuvnt cheie este un cuvnt mprumutat din limba englez, care are un neles
predefinit. Cuvinte cheie se scriu cu litere mici n limbajul C.Un cuvnt cheie nu poate avea alt utilizare ntr-un program C dect cea care i-a fost
predefinit. Fiind o succesiune de litere, un cuvnt cheie este totodat i un nume.
Exemple: if while for break do
Lista cuvintelor cheie este dat n anexa I.
Sensul fiecrui cuvnt cheie va rezulta la definirea construciei n care se utilizeaz.
6.2.1.3. Tipurile de baz din limbajul C
Un program n limbajul C, ca de altfel n orice limbaj de programare, realizeaz osuccesiune de prelucrri asupra unor date. Datele sunt diferite funie de natura (tipul) lor.
n limbajul Cdistingem cteva tipuri predefinite de date, pe care le numim tipuri de
baz. n afara acestor tipuri utilizatorul i poate defini tipuri noi funcie de specificul datelor
problemei pe care o are de rezolvat.
n tabelul 6.1 de mai jos se indic tipurile de baz din limbajul TURBO C.
Tabelul 6.1.
Cuvnt
cheie
Lungime
n bii
Tip de reprezentare intern
int 16 ntreg binar reprezentat prin complement fa de 2 pe 2 octei
short 16 idem
long 32 ntreg binar reprezentat prin complement fa de 2 pe 4 octei
unsigned 16 ntreg binar fr semn
char 8 caracter reprezentat prin cod ASCII
float 32 numr reprezentat n virgul flotant n simpl precizie
double 64 numr reprezentat n virgul flotant n dubl precizie
long double 80 numr reprezentat n virgul flotant n dubl precizie
Datele de tip int(ntregi cu semn) aparin intervalului [-32768, 32767]. Datele de tip
long(ntregi cu semn n dubl precizie) aparin intervalului [-231, 331]. Datele de tip unsingned
(ntregi fr semn) aparin intervalului [0,65535]. Datele de tip char au valori n intervalul
[0,255] sau [-128,127]. Se pot utiliza ntregi fr semn n dubl lungime folosind succesiunea
de cuvinte cheie: unsigned long. O dat flotant n simpl precizie de tipfloat, difer de zero,
135
7/29/2019 Programare in C
3/130
Limbajul de programare C
are valoarea absolut n intervalul [3.4*10-38, 3.4*1038]. O dat flotant n dubl precizie de tip
double, long double n intervalul [3.4*10-4932, 1.1*104932].
6.2.1.4. Constante
O contant are o valoare i un tip. Att tipul ct i valoarea unei constante se definescprin caracterele care compun constanta respectiv.
a) Constante ntregi
O constant ntreag poate fi un ir de cifre, care eventual este precedat de un semn. O
constant ntreag se reprezint prin complement fa de 2 pe 16 bii sau chiar 32 de bii dac
nu ncape pe 16 bii. n cazul n care dorim ca o constant ntreag s fie reprezentat pe 32 de
bii, chiar dac ea se poate reprezenta pe 16 bii, vom termina constanta respectiv prin L sau l.
n felul acesta, se impune tipul longpentru constanta respectiv.
O constant ntreag, precedat de un zero nesemnificati, se consider scris nsistemul de numeraie cu baza 8. De asemenea, o constant ntreag care ncepe cu 0x sau 0X
(zero urmat de litera x mic sau mare) se consider scris n sistemul de numeraie cu baza 16.
n rest se consider c baza de numeraie este 10.
Exemple de reprezentri sunt artate n tabelul 6.2.
Tabelul 6.2.
Repreze
ntare
Lungimea
reprezentriiLungime de reprezentare intern
31645 16 bii ntreg zecimal reprezentat n binar prin complement fa de 2
-12345 16 bii ntreg zecimal reprezentat n binar prin complement fa de 2
12345L 32 bii ntreg zecimal reprezentat n binar prin complement fa de 2
012345 16 biintreg octal reprezentat n binar
(o cifr octal se reprezint pe 3 bii)
0xa12b 16 biintreg hexazecimal reprezentat n binar
(o cifr hexazecimal se reprezint pe 4 bii)
923456 32 bii ntreg zecimal reprezentat n binar prin complement fa de 2
b) Constant flotant (real)
O constant flotant este un numr raional care se compune din:
- un semn care poate i lipsi n cazul unui numr nenegativ;
- o parte ntreag care poate fi i vid;
- o parte fracionar care poate fi i vid;
- un exponent care poate fi i vid;
136
7/29/2019 Programare in C
4/130
Limbajul de programare C
Exemple:
7125.34 -49.0 85. 367e-2 .3789 -.128 4.3E20 -.29e+15
c) Constant caracter
O constant caracter reprezint un caracter i are ca valoare codul ASCII al
caracterului respectiv. O constant caracter grafic se poate scrie incluznd caracterul
respectiv ntre caractere apostrof.
Anumite caractere negrafice au notaii speciale la scrierea crora se utilizeaz
caracterul backslash (\). Aa, de exemplu, am vzut c pentru caracterul tabulator orizontal
folosim notaia: \t.
O astfel de constant caracterse va scrie incluznd notaia respectiv ntre caractere
apostrof. Deci constanta caractertabulator orizontalse va scrie: \t
n mod analog, constanta caracter de rnd nou (newline) se va scrie: \n
Alte constante caracter care au notaii consacrate sunt prezentate n tabelul 6.3:Tabelul 6.3
CaracterReprezentare prin constant
caracterValoare
revenire cu o poziie (backspace) \b 8
retur de car \r 13
salt de pagin la imprimant \f 12
Caracterul backslash poate fi folosit pentru a reprezenta nsui constanta caracterapostrof sau chiarbackslash. Astfel:
\ - reprezint constanta caracterapostrof;
\\ - reprezint constanta backslash.
d) Constant ir sau ir de caractere
O constant ir este o succesiune de zero sau mai multe caractere delimitate prin
ghilimele. Ghilimelele nu fac parte din irul de caractere. Dac dorim s folosim caractere
negrafice n compunerea unui ir de caractere, atunci putem folosi convenia de utilizare a
caracterului backslash indicat mai sus. n particular, dac ntr-un ir de caractere dorim s
reprezentm chiar caracterul ghilimele, atunci vom scrie: \. De asemenea, nsui caracterul
backslash se va scrie: \\.
6.2.1.5. Variabile simple
Prin variabil nelegem o dat a crei valoare se poate schimba n timpul executrii
programului care o conine.
137
7/29/2019 Programare in C
5/130
Limbajul de programare C
Unei variabile i se ataeaz un nume prin intermediul cruia putem referi sau chiar
modifica valoarea variabilei respective. Valorile pe care le poate avea o variabil trebuiesc s
aparin unui acelai tip. De aceea, unei variabile i corespunde un tip.
Corespondena ntre numele i tipul unei variabile se realizeaz printr-o construcie
special numit declaraie.Sintaxa unei declaraiin limbajul Ceste urmtoarea:
nume_tip lista_de_variabile;
Exemple:
int i,k,x; - i,kixsunt variabile de tip int(ele pot avea ca valori ntregi binari
reprezentai prin complement fa de 2 pe 16 bii);
float a,b; - a i b sunt variabile de tip float (valorile lor sunt reprezentate n
format flotant simpl precizie pe 32 de bii);
char c; - c este o variabil de tip char(valorile ei sunt ntregi din intervalul
[0,255] sau [-128, 127]).
6.2.1.6. Comentarii
n limbajul C un comentariu ncepe prin succesiunea de caractere: /* i se termin
prin: */.
Se pot aduga comentarii pe o singur linie precedate de o succesiune de dou
caractere /.
6.2.2. Expresii
6.2.2.1. Structura expresiilor n limbajul C
O expresie n limbajul Cse compune dintr-un operand sau mai muli operanzi legai
prin operatori.
O expresie are o valoare i un tip care se determin aplicnd operatorii prezeni
conform prioritilor i asociativitii acestora.
n limbajul Coperatorii se asociaz de la stnga la dreapta, exceptnd operatorii unari,
condiionali i de atribuire, care se asociaz de la dreapta la stnga.ntr-o expresie pot fi folosite parantezele rotunde pentru a impune o anumit ordine n
executarea operaiilor.
Operatorii limbajului Cpot fi grupai n mai multe clase. Cu toate acestea ei pot fi
utilizai mpreun ntr-o aceeai expresie.
6.2.2.2. Operatorii aritmetici
Acetia sunt:
138
7/29/2019 Programare in C
6/130
7/29/2019 Programare in C
7/130
Limbajul de programare C
! (negaia logic operator unar);
&& (Ilogic); (SAUlogic).Operatorul ! are aceeai prioritate cu operatorii unari + i -. De altfel toi
operatorii unari au aceeai prioritate n limbajul C.
Operatorul && (Ilogic) este mai prioritar dect operatorul (SAUlogic), darare o prioritate mai mic dect operatorii de egalitate.
n limbajul C nu exist valori logice speciale. Valoarea fals se reprezint prin zero.
Orice valoare diferit de zero reprezint valoarea adevrat.
Operatorii logici se evalueaz de la stnga la dreapta. Dac la evaluarea unei expresii
se ajunge ntr-un punct n care se cunoate valoarea ntregii expresii, atunci restul expresiei nu
se mai evalueaz.
Exemplu:
an%4= = 0 && an% 100! = 0 || an% 400 = = 0.
Variabila an, din expresia de mai sus, are valoarea unui ntreg ce reprezint un an
calendaristic. Expresia are valoarea 1 dac anul reprezentat prin valoarea variabilei an este
bisect i zero n caz contrar.
ntr-adevr, un an este bisect dac are loc una din urmtoarele condiii:
a) anul este multiplu de 4 i nu este multiplu de 100; sau
b) este multiplu de 400.
Condiia a) se exprim prin: multiplu de 4: an%4 = = 0
i: &&nu e multiplu de 100: an%100! = 0
Condiia b) se exprim prin: multiplu de 400: an%400 = = 0
n final cele dou condiii se leag prin operatorul || (SAU) i n felul acesta se obine
expresia cerut.
6.2.2.6. Operatori logici pe bii
Acetia, n ordine descresctoare a prioritii lor sunt:
~ (operator unar; complement fa de unu)
> (deplasri)
& (Ipe bii)
^ (SAU-EXCLUSIVpe bii)
| (SAUpe bii)
Operatorul ~are ca effect inversarea tuturor biilor: biii care iniial au avut valoarea 1
vor deveni 0, iar cei care au avut valoarea 0 vor deveni 1.
Operatorul
7/29/2019 Programare in C
8/130
7/29/2019 Programare in C
9/130
7/29/2019 Programare in C
10/130
Limbajul de programare C
Construciile de mai jos sunt eronate:
x%=y - operatorul % nu se poate aplica la operanzi care nu sunt
ntregi.
i=j - construcia op= implic un operator binar;x=i+(j*(k-y)+2.3 - lipsete o parantez nchis;
y=3(x-10) - lipsete operatorul * dup 3.
6.2.2.8. Operatori de incrementare i decrementare
Aceti operatori sunt unari i deci au aceeai prioritate cu ceilali operatori unari din
limbajul C. Operatorul de incrementare se noteaz prin ++, iar cel de decrementare prin
--.
Operatorul de incrementare mrete valoarea operandului su cu unu, iar cel de
decrementare micoreaz valoarea operandului cu unu. Operatorii pot fi astfel :
prefixai: ++ operand -- operandpostfixai: operand ++ operand --
n cazul n care sunt folosii prefixai, ei se aplic nti i apoi se folosete valoarea
operandului la care s-a aplicat. Cnd sunt postfixai, se folosete valoarea operandului
nemodificat de operatorul respectiv, apoi se aplic.
Exemple:
Dacxare valoarea 3, atunci n atribuireay= ++xluiy i se atribuie valoarea 4 deoarece
nti s-a incrementatxi apoi s-a folosit valoareax. n schimb, dac folosim atribuireay=x++,
pentru aceeai valoare a lui x, atunci lui y i se atribuie valoarea 3. n ambele cazuri x se
mrete cu 1. Diferena const numai n valoarea atribuit: n primul caz ( operator prefixat),
se atribuie valoarea incrementat, iar n al doilea caz (operator postfixat), se atribuie valoarea
neincrementat.
Menionm c aceti operatori se pot aplica numai la urmtorii operanzi: variabil
simpl cu indici, referire la elementul unei structuri(structurile vor fi definite mai trziu).
Exemple:
int i,j; double x,y;
j=i++ - este echivalent cu atribuirile j=i; i=i+1;
y= -- x - este echivalent cu secvena de atribuire: x=x-1; y=x;x=tab[3]-- - este echivalent cu: x= tab[3]; tab[3]=tab[3]-1;
i=++tab[j+1] - este echivalent cu: tab[j+1]=tab[j+1]+1; i=tab[j+1];
x=tab[++j] - este echivalent cu: j=j+1; x= tab[j];
x = tab[i--] - este echivalent cu: x=tab[i]; i=i-1;
y=++i-j - este echivalent cu: i=i+1;y=i-j;
y=i++-j - este echivalent cu: y=i-j; i=i+1;
Construciile urmtoare sunt eronate:
y=(i-j)++ - operatorul ++ nu se poate aplica expresiei i-j;
143
7/29/2019 Programare in C
11/130
Limbajul de programare C
x= --(i-j) - operatorul nu se poate aplica expresiei i-j;
i=j- - - - - nu mai reprezint operatorul de decrementare.
6.2.2.9. Operatorul de conversie explicit (operatorul cast)
Adesea dorim s form tipul unui operand sau chiar al unei expresii. Acest lucru este
posibil folosind o construcie de forma: (tip) operand.
Prin aceasta, valoarea operandului se convertete spre tipul indicat n paranteze.
Exemplu:
int x,y;double z;
Fie x = 10 i y = 4, valorile lui x i respectiv y. Atunci n urma atribuirii: z = x/y, z
primete valoarea 2 deoarece 10/4 d ctul 2 (mprirea dintre operanzi ntregi are ca
rezultat ctul ntreg). n schimb, dac vom converti cei doi operanzi spre tipul double,
atunci mprirea nu mai este ntreag i rezultatul va fi 2,5. O astfel de conversie areforma:
z = (double)x/y
n expresiile de mai sus, construcia (tip) este un operator unar prin care se expliciteaz
conversia dorit. El are aceeai prioritate ca restul operatorilor unari, iar expresia
(tip)operandse numete expresie cast.
6.2.2.10. Operatorul dimensiune (sizeof)
Lungimea n octei a unei date se poate determin folosind o construcie de forma:
sizeof(data) unde data este numele unei variabile simple, al unui tablou, al unei structuri, alunui tip sau referirea la elementul unui tablou sau structur. Sizeof este operatorul unar
dimensiune i are aceeai prioritate ca ceilali operatori unari. n expresia de mai sus,
parantezele rotunde sunt obligatorii numai n cazul n care data este numele unui tip.
Exemple:
int i; float x; double d; char c; int tab[10]; double dtab[10];
sizeof(i) sau sizeof i - are valoarea 2;
sizeof(x) sau sizeof x - are valoarea 4;
sizeof(float) - are valoarea 4;sizeof(d) sau sizeof d - are valoarea 8;
sizeof(double) - are valoarea 8;
sizeof(c) sau sizeof c - are valoarea 1;
sizeof(tab[i]) sau sizeof tab[i] - are valoarea 2;
sizeof(tab) sau sizeof tab - are valoarea 20;
sizeof(dtab) sau sizeof dtab - are valoarea 80.
6.2.2.11. Regula conversiilor implicite
144
7/29/2019 Programare in C
12/130
Limbajul de programare C
O expresie poate conine operanzi de tipuri diferite. Nu exist restricii n acest sens.
Astfel, de exemplu ntr-o expresie se pot folosi operanzi de tip char. Acetia se convertesc n
mod automatspre tipul int, nainte de a face operaii cu ei.
Dac operanzii unui operator binar sunt de acelai tip, se aplic operatorul asupra
operanzilor respectivi, iar tipul rezultatului este acelai cu al operanzilor. n caz contrar
sunt necesare conversii care se execut n mod automat, conform regulii de mai jos
(regula conversiilor implicite):
1.Fiecare operand de tip charse convertete spre tipul int;
2.Dac unul dintre operanzi este de tip long double, atunci cellalt operand se
convertete spre tipul long double i rezultatul va avea tipul long double;
3.Dac unul dintre operanzi este de tip double, atunci cellalt operand se convertete
spre tipul double i rezultatul va avea tipul double;
4.Dac unul dintre operanzi este de tipfloat, atunci cellalt operand se convertete spretipulfloati rezultatul va avea tipulfloat;
5.Dac unul dintre operanzi este de tip long, atunci cellalt operand se convertete spre
tipul longi rezultatul va avea tipul long;
6.Dac unul dintre operanzi este de tip unsigned, atunci cellalt operand se convertete
spre tipul unsignedi rezultatul va avea tipul unsigned;
7.Dac unul dintre operanzi este de tip int, atunci cellalt operand se convertete spre
tipul inti rezultatul va avea tipul int;
Exemple:
int i,j,k; float a,b; double x,y;unsigned p; long r; char c;
Valorile diferitelor expresii sunt prezentate n tabelul 6.3.
Tabelul 6.3.
Expresii Conversii Tipul expresieii+j/k - inta/b - float
x+y - doublei+a i spre float float
i-3.5 i spre double doublei+5 - inti+32767 - int
i+x i spre double doublei-c c spre int int
x+100 100 spre double doublep-20 20 spre unsingned unsignedr*5 5 spre long longi*31 - int
(long)i*3 i spre long, 3 spre long long(double)i/j i spre double, j spre double double
145
7/29/2019 Programare in C
13/130
Limbajul de programare C
(double)(i/j)
se realizeaz mprirea ntreag
ntre i i j i rezultatul se
convertete spre double.
double
6.2.2.12. Operatori condiionali
Operatorii condiionalise utilizeaz n evaluri de expresiicare prezint alternative.
O astfel de expresie are formatul: exp1? exp2:exp3 unde exp1, exp2 i exp3 sunt
expresii.
O astfel de expresie se evalueaz n felul urmtor:
1.Se evalueaz expresia exp1;
2.Dac exp1 este diferit de zero, atunci valoarea i tipulexpresiei condiionale este
egal cu expresia exp2, altfel cu expresia exp3.
Operatorii condiionali sunt ? i :. Ei trebuie s fie folosii mpreun, adic operatorul
? Trebuie s aib un corespondent : i numai unul.Ei au prioritatea imediat mai mic dect operatorul logic SAU(||) i imediat mai mare
dect operatorii de atribuire.
Exemple:
1. y?x/y:x*x
n acest exemplu, exp1 estey, exp2 estex/y iarexp3 estex*x.
Expresia se evalueaz astfel: dac y este diferit de zero atunci rezultatul este valoarea
i tipulexpresieix/y, altfel este valoarea i tipulexpresieix*x.
O expresie condiional este un caz particular de expresie i deci este legal i
urmtoarea expresie de atribuire:z=y?x/y:x*x.
Aceast expresie exprim un proces de calcul pe care l putem descrie n pseudocod,
astfel:
dac y 0 atunci z x/y
altfel z x*x
2. Determinarea maximului dintre dou numere a i b.
dac a>b atunci max a
altfel max b
Expresia corespunztoare din limbajul Cva fi:
max = (a > b)?a : b
n acest exemplu: exp1 este a > b, exp2 este a, iarexp3 este b.
6.2.2.13. Operatorul virgul
146
7/29/2019 Programare in C
14/130
Limbajul de programare C
Exist cazuri n care este util s grupm mai multe expresii ntr-una singur, expresii
care s se evalueze succesiv.
n acest scop se folosete operatorul virgul, care separ secvena de expresii, acestea
grupndu-se ntr-o singur expresie.
Operatorul virgul are cea mai mic prioritate dintre toi operatorii limbajului C.
Prioritatea lui este imediat mai mic dect a operatorilor de atribuire.
Cu ajutorul lui construim expresii de forma: exp1, exp2,,expn .
Aceast expresie, ca oricare alta, are o valoare i un tip. Att valoarea, ct i tipul
ntregii expresii coincide cu valoarea i tipul lui expn deci cu a ultimei expresii.
Exemple:
++i,--j - i se mrete cu o unitate, apoi j se micoreaz cu o
unitate; valoarea i tipul ntregii expresii coincid cu ale luij;
k=(x=10,y=2*i-5,z=3*j,i+j) - se execut pe rnd cele 3 atribuiri, apoi se efectueazsuma i+jcare se atribuie lui k.
Amintim c toi operatorii se asociaz de la stnga la dreapta, exceptnd cei unari,
condiionali i de atribuire care se asociaz de la dreapta la stnga. n tabelul 6.4 sunt
prezentate prioritile operatorilor.
Tabelul 6.4
( ) [ ] .-(unar) +(unar) *(unar) &(unar) ! ++ -- (tip) sizeof
* / %+ -
>< = >
= = ! =&^
&&
? :
= op= op poate fi: (binar) / % +(binar) -(binar) >>
7/29/2019 Programare in C
15/130
Limbajul de programare C
6.3. Structura programelor C
6.3.1. Structura unui program n limbajul C
Un program n limbajul Cse compune din una sau mai multe funcii. Dintre acestea
una este funcia principal. Funcia principal definete adresa de lansare a programului. Un
program n Cse lanseaz cu prima instruciune a funciei principale.
Fiecare funcie are un nume. Funcia principal are numele main.
6.3.2. Structura unei funcii
n limbajul Cexist dou feluri de funcii: funcii care returneaz o valoarei funcii
care nu returneaz o valoarela revenirea din ele.Structura unei funciieste urmtoarea:
tip nume (lista parametrilor formali)
{
declaraii de variabile locale
instruciuni
}
unde:
- tip definete tipul valorii returnate de funcie i este un cuvnt cheie pentru tipurile de
baz. Dac funcia nu returneaz nici o valoare, se poate utiliza cuvntul cheie void. Dac tip
este absent, se presupune c funcia sau nu returneaz nici o valoare sau returneaz o valoare
de tip int. Se recomand ca utilizatorul s indice totodat tipul deoarece absena lui constituie
o surs potenial de erori.- lista_parametrilor_formali este fie vid, fie conine declaraiile parametrilor formali
separate prin virgul.
Menionm c parantezele rotunde sunt prezente chiar i atunci cnd lista
parametrilor formali este vid.
6.4. Preprocesare
Un program n limbajul C poate fi prelucrat nainte de a fi compilat . O astfel de
prelucrare se numetepreprocesare.
Prin preprocesare se pot realiza:
- includeri de texte;
- definiii i apeluri de macrouri simple;
- compilare condiionat;
6.4.1. Includerea unui fiier surs
148
7/29/2019 Programare in C
16/130
Limbajul de programare C
Fiierele surs pot fi incluse cu ajutorul construciei #include. Aceast construcie are
una din urmtoarele formate:
#include specificator_de_fiier sau
#include
unde:
- specificator_de_fiier trebuie s fie un nume de fiier valid din punct de vedere alsistemului de operareDOS, care poate avea o extensie (.h, .cetc.) i opional o
cale. Diferena dintre cele dou formate const n algoritmul de cutare al
fiierului care se include.
Astfel, varianta specific includerea unui fiier standard, care este cutat de
obicei n directorulINCLUDE.
n cazul n care se utilizeaz caracterele ghilimele, utilizatorul furnizeaz fiierul care
se include. Acest fiier va fi cutat n directorul curent sau ntr-un director precizat.
Un fiier standard care trebuie inclus frecvent este fiierul stdio.h. Includerile defiiere, de obicei, se fac la nceputul fiierului surs. n felul acesta datele coninute n el se pot
utiliza n tot fiierul surs. De aceea, la nceputul fiierelor surs vom ntlni mai multe
includeri de fiiere, printre care de obicei se va afla i fiierul stdio.h: #include .
Un exemplu de nchidere a unui fiier utilizator este: #include mouse.h.
6.4.2. Constante simbolice
O alt construcie tratat de procesor este construcia define. Un format simplu al
acestei construcii este urmtorul:
#define nume succesiune_de_caractere.
O constant simbolic este definit din punctul apariiei construciei define
corespunztoare ei i pn la sfritul fiierului surs respectiv sau pn la redefinirea sau
anihilarea ei prin intermediul construciei #undef.
Exemplu: #define A 100
6.5. Intrri/ieiri standard
Operaiile de intrare/ieire se realizeaz prin apeluri de funcii. Datele de
intrare/ieire se presupune c sunt organizate nfiiere.
Unui programBORLAND C i se ataeaz n mod automat urmtoarele fiiere:
- stdin - intrare standard;
- stdout - ieire standard;
- stderr - ieire standard pentru erori;
- stdprn - ieire standard pentru imprimant;
- stdaux - intrare/ieire serial.
149
7/29/2019 Programare in C
17/130
Limbajul de programare C
6.5.1. Funcia standard printf
Funcia de bibliotecprintfrealizeaz ieiri cu format. Sintaxa funciei este:
printf(control, par1, par2,parn),
unde controleste un ir de caractere care conine texte de scris, specificatori de format pentru
datele care se scriu, iarpar1, par2,parn sunt expresii ale cror valori se scriu conform
specificatorilor de format prezentai n parametrul de control.
Un specificator de format ncepe cu un caracter procent (%). n continuare, ntr-un
specificator de format mai putem avea:
1.Un caracter- opional: implicit, datele se aliniaz n dreapta cmpului n care se
scriu. Atunci cnd caracterul - este prezent, data corespunztoare este ncadrat la stnga.
2.Un ir de cifre zecimale opionale, care definete dimensiunea minim a cmpului
afectat datei respective.3.Un punct opional, urmat de unir de cifre zecimal. irul de cifre zecimal aflat dup
punct defineteprecizia datei care se scrie sub controlul specificatorului respectiv.
4.Una sau dou litere, care definesc tipul de conversie aplicatdatei care se scrie. n
cazul n care specificatorul de format conine dou litere, prima poate fi l.
n tabelul 6.5 sunt prezentate intrrile/ieirile standard utilizate n limbajul C.
Tabelul 6.5.
Litera Conversia realizat
ddata se convertete din tipul intizecimali se scriu la ieire caracterele zecimale
ale ei, eventual precedate de semnul -, dac este negativ.o data se convertete din tipul intn octali se scriu la ieire caracterele ei octale;
xdata se convertete din tipul intn hexazecimali se scriu la ieire caracterele ei
hexazecimale; cifrele peste 9 se scriu cu literele mici (a-f);X ca i n cazul literei x, dar se vor folosi literele mari (A-F);u data se convertete din tipul usingnednzecimal ntreg fr semn;
cvaloarea parametrului care i corespunde se consider c reprezint codul ASCIIal
unui caracteri se scrie caracterul respectiv;
sparametrul care-i corespunde se scrie ca un ir de caractere; se consider c irul se
termin la ntlnirea caracteruluiNUL (\0);
f
valoarea parametrului care-i corespunde se convertete din tipfloatsau double n
formatul: dd ...d.ddd(d reprezint o cifr zecimal), unde numrul de cifre dup
punctul zecimal este fie cel indicat de precizie specificatorului de format, fie este
egal cu 6; partea ntreag este precedat de semnul minus dac numrul este negativ;
e
conversia se realizeaz de tipulfloatsau double n formatul:
d.dd..dedddunde numrul cifrelor de dup punctul zecimal este dat de preciziaspecificatorului de format sau este egal cu 6, dac acesta este absent; partea ntreag
este precedat de minus dac numrul este negativ;
150
7/29/2019 Programare in C
18/130
Limbajul de programare C
E
ca i n cazul literei e cu deosebirea c litera e se schimb cu literaE:
d.dd..dEdddn ambele cazuri, la exponent se va scrie una, dou sau trei cifre, nfuncie de valoarea numrului;
g
se aplic una din conversiile definite de literelefsau e, alegndu-se aceea care se
reprezint pe un numr minim de caractere; de asemenea, zerourile de la sfritul
prii fracionare se omit;G ca igcu singura deosebire c se utilizeazEn loc de e.
Funcia printf returneaz lungimea total n octei a datelor scrise la terminal sau
valoarea simbolic EOF n caz de eroare. EOFeste o constant simbolic definit n fiierul
stdio.h. Ea este definit astfel: #define EOF 1.
Exemple:
Fie declaraiile: int i,j; float a; double x; int c; long k;
i = 558 a = 47.389 x = -123.5e20 c = x j = -123 k = 45678
Mai jos apelm funciaprintfcu diferii specificatori de format care permit afiarea laterminal a valorilor acestor variabile. n tabelul 6.6sunt prezentate rezultatele afiate n cazul
apelrii funcieiprintf:
Tabelul 6.6.
Nr.crt. Apelul funciei printf Afiri
1. printf (i=%d\n,i); i = 5582. printf (i=%2d\n,i); i = 5583. printf (i=%5d\n,i); i = 5584. printf (i=%o\n,i); i = 1056
5. printf (i=%x\n,i); i = 22e6. printf (j=%d\n,j); j = -1237. printf (a=%.3f\n,a); a = 47.3898. printf (a=%.2f\n,a); a = 47.399. printf (x=%e\n,x); x = -1.235000e+22
10. printf (c=%c,cod = %d\n,c,c); c = x, cod = 12011. printf (k=%ld\n,k); k =45678
6.5.2. Funcia standard scanf
Funcia bibliotec scanf realizeaz intrri cu format de la intrarea standard stdin
(intrare de la terminalul de la care s-a lansat programul). Ea poate fi apelat printr-o
instruciune de apel de forma:
scanf(control, par1, par2, .., parn);
Ca i n cazul funciei printf, parametrul control este delimitat de ghilimele i poate
conine texte i specificatori de format.
Caracterele albe din parametrul de control sunt neglijate.
- parametrii par1, par2, .., parn definesc zonele receptoare ale datelor citite prin
intermediul funciei scanf. Fiecare dintre ei reprezint adresa unei zone receptoare.
151
7/29/2019 Programare in C
19/130
Limbajul de programare C
Acest lucru se indic, n limbajul C, printr-o construcie de forma: &nume care
determin adresa zonei de memorie rezervat variabilei num. Caracterul&, din
construcia de mai sus, reprezint un operator unar, numit operatorul adres. El
are aceeai prioritate ca i ceilali operatori unari din limbajul C.
Funciascanf
citete toate cmpurile care corespund specificatorilor de format i
eventual textelor scrise n parametrul de control. n cazul unei erori, citirea se ntrerupe n
locul n care s-a ntlnit eroarea. La revenirea din ea funcia scanf returneaz numrul
cmpurilor citite corect.
Exemplul 1:
voidmain () /* citete un intreg de 4 cifre i scrie cifrele
respective precedate fiecare de cte un spaiu */
{
intcif1, cif2, cif3, cif4;
scanf (%1d%1d%1d%1d, &cif1, &cif2, &cif3, &cif4);
printf(%2d%2d%2d%2d\n, cif1, cif2, cif3, cif4);
}
Exemplul 2:
Programul urmtor citete o dat calendaristic scris sub forma: zzllaaaa
zz - ziua cu 2 cifre;
ll - luna cu 2 cifre;
aaaa - anul cu 4 cifre.
apoi se scrie data respectiv permutnd anul cu ziua, astfel nct dac la intrare se citete, spreexemplu, 01031992, la ieire se va obine 19920301.
voidmain () /* citete zzllaaaa i rescrie aaaallzz */
{
intziua, luna, anul;
scanf (%2d%2d%4d, &ziua, &luna, &anul);
printf(%4d%02d%02d\n, anul, luna, ziua);
}
Exemplul 3:
#define MAX 50
voidmain () /* citete nume, prenume i data naterii i rescrie datele respective astfel:
linia 1: nume prenume
linia 2: zi luna an */
{ intziua, luna, an;
char nume [MAX+1], prenume [MAX+1];
scanf (%50s%50s%d%d%d, nume, prenume, &zi, &luna, &an);
152
7/29/2019 Programare in C
20/130
Limbajul de programare C
printf(%s%s\n, nume, prenume);
printf(%d %d %d\n, zi, luna, an);
}
Exemplu de linie de intrare: Popescu Ion 1 9 1991
6.5.3. Funcia standard putchar
Funcia standardputcharse poate utiliza pentru a scrie un caracter n fiierul standard
de ieirestdout, n poziia curent a cursorului.
Exemple:
1) putchar(A);
- se scrie caracterul A n fiierul de ieire n poziia curent a cursorului;
2) putchar(A+10);
- se scrie caracterul de cod A+10 = 65+10=75, adic literaK;
3) putchar(\n);- se scrie caracterul de rnd nou (newline). Aceasta are ca efect deplasarea
cursorului n coloana 1 din linia urmtoare.
6.5.4. Funcia standard getchar
Aceast funcie citete de la intrarea standard (fiierul standard stdin) caracterul curent
i returneaz codul ASCIIal caracterului citit. Tipul valorii returnate este int. La ntlnirea
sfritului de fiier (^Z) se returneaz valoareaEOF.
Funciagetcharpoate fi apelat printr-o instruciune de forma:getchar()
sau utiliznd-o ca operand ntr-o expresie. Folosind expresia de atribuire:
c =getchar ()
se citete caracterul curent de la intrare.
6.5.5. Funciile standard getch i getche
Funcia getche citete de la intrarea standard caracterul curent i returneaz codul
ASCII al caracterului citit. Spre deosebire de getchar, aceast funcie are acces direct lacaracter, de ndat ce acesta a fost tastat. Se apeleaz la fel ca i getchar, adic fie printr-o
instruciune de apel de forma:getche ();
Funcia getch este similar cu funcia getche cu singura deosebire c citirea se face
fr ecou (caracterul tastat nu se afieaz la terminal i nici cursorul nu se deplaseaz). Ea se
apeleaz n acelai mod ca i funciagetche.
6.5.6. Funciile standard gets i puts
153
7/29/2019 Programare in C
21/130
Limbajul de programare C
Pentru a introduce de la terminal un ir de caractere se poate folosi funcia gets. Ea
permite citirea cu ecou a caracterelor coduluiASCII.
Funciagets are ca parametru adresa de nceput a zonei n care se pstreaz caracterele
citite. De obicei, aceast zon de memorie poate fi zona alocat unui tablou de tip char.
Funciagets
returneaz adresa de nceput a zonei n care s-au pstrat caracterele sau
zero n cazul n care s-a ntlnit sfritul (^Z).
Exemplu:
char t[255]; gets(t);
La acest apel se citesc caracterele tastate pe un rnd i se pstreaz n tabloul t.
Caracterul tastat nainte de a aciona tasta ENTER este urmat n tabloul tde caracterulNUL,
iar la revenirea din funcie se returneaz adresa zonei receptoare adic valoarea lui t.
Funcia puts realizeaz operaia invers fa de funciagets. Ea afieaz la terminal
caracterele irului de caractere ASCII aflate ntr-o zon de memorie. Adresa de nceput a
acestei zone de memorie este parametrul funcieiputs.Exemplu:
char t[255]; gets(t); puts(t);
Se d funciay(x) definit ca mai jos:
( )
+
7/29/2019 Programare in C
22/130
7/29/2019 Programare in C
23/130
Limbajul de programare C
( )
>+
=
7/29/2019 Programare in C
24/130
Limbajul de programare C
f = f*i;
i++;}
printf(n = %d,n! = %g\n, n,f);
}
Observaie:Instruciunile din corpul ciclului while:
f = f*i;
i++;
pot fi nlocuite cu una singur:f*=i++; Deci ciclul while se poate scrie mai compact astfel:
while(i max) max = i;
printf(max = %d\n, max);
}
6.6.5. Instruciunea FOR
Instruciunea for, ca i instruciunea while, realizeaz o structur repetitivcondiionat anterior. Este folosit pentru repetarea operaiilor n care se cunoate numrul de
pai i dup o condiie. Formatul instruciunii este:
for(exp1; exp2; exp3) instruciune
unde exp1, exp2, exp3 sunt expresii.
Antetulciclului este definit de:for(exp1; exp2; exp3)
Instruciunea care se execut repetat formeaz corpulciclului, exp1 constituie partea de
iniializare a ciclului, exp2 este partea de reiniializare a lui, iarexp3 reprezint condiia de
continuare a ciclului. De obicei, exp1 i exp3 reprezint atribuiri.Instruciuneaforse execut conform urmtorilor pai:
1.Se execut secvena de iniializare definit de expresia exp1.
2.Se evalueaz exp2. Dac exp2 are valoarea zero, atunci se iese din ciclu. Altfel se
execut instruciunea din corpul ciclului.
3.Se execut secvena de reiniializare definit de exp3, apoi se reia de la pasul 2.
Echivalena dintre instruciunile while iforeste sintetizat astfel:
exp1;
while (exp2)
157
7/29/2019 Programare in C
25/130
Limbajul de programare C
{
instruciune
exp3;
}
Un exemplu foarte simplu de ciclu cu pas este nsumarea elementelor unui tablou.s = 0;
for(i=0; i
7/29/2019 Programare in C
26/130
7/29/2019 Programare in C
27/130
Limbajul de programare C
Aceast instruciune realizeaz structura repetitiv condiionat posterior. Aceast
structur nu este obligatorie pentru a scrie programe, ea putndu-se realiza prin celelalte
structuri. Are urmtorul format:
do
instruciunewhile (expresie);
Aceasta, la rndul ei, poate fi scris printr-o secven n care se folosete instruciunea
while:
instruciune
while (expresie) instruciune
Exemple:
1. Programul urmtor utilizeaz o metod iterativ simpl pentru extragerea rdcinii
ptrate dintr-un numr. Fie irul:
x0, x1, ... xn,
unde xn=1/2(xn-1+a/xn-1)
Se poate demonstra c acest ir converge, pentru a>0, ctre rdcina ptrat din a.
Convergena este rapid pentru 0
7/29/2019 Programare in C
28/130
7/29/2019 Programare in C
29/130
Limbajul de programare C
default: printf (luna eronata);
}
printf (\t%d\n, zz);
}
6.6.8. Instruciunea BREAKFormatul instruciunii este urmtorul:
break;
Aa cum s-a vzut n paragraful 6.6.7, se poate folosi instruciunea breakpentru a iei
dintr-o instruciune switch.
Ea mai poate fi utilizat pentru a iei dintr-o instruciune ciclic.
6.6.9. Instruciunea CONTINUE
Instruciunea are urmtorul format: continue;Efect:
1.n ciclurile while i do-while realizeaz saltul la evaluarea expresiei care decide
asupra continuitii ciclului;
2.n ciclul for realizeaz saltul la pasul de reiniializare.
Un exemplu de program n care se poate utiliza instruciunea continue este urmtorul:
Se citesc de la tastatur temperaturile nregistrate pe durata a n zile. Se cere
programul C care afieaz pe ecran media temperaturilor pozitive. Programul va citi toate
temperaturile indiferent dac sunt pozitive sau negative i calculeaz media celor pozitive. ncazul n care se ntlnete o temperatur negativ se va ignora.
#include
#include
voidmain()
{
intn,i;
floatsuma_temp,temperatura,temp_medie,nr_temp_pozitive;
puts("\nIntroduceti numarul de zile:");
scanf("%d",&n);
nr_temp_pozitive=suma_temp=0;
for(i=1;i
7/29/2019 Programare in C
30/130
Limbajul de programare C
}
temp_medie=suma_temp/nr_temp_pozitive;
printf("\nTemperatura medie pozitiva este %.2f",temp_medie);
getch();
}
6.6.10. Instruciunea GOTO
Instruciuneagoto are urmtorul format:
goto nume_de_etichet;
Ea realizeaz saltul la instruciunea prefixat de eticheta al crui nume se afl scris
dup cuvntul cheiegoto.
Eticheta trebuie s fie urmat de caracterul :.
Un exemplu de program n care se folosete instruciuneagoto este urmtorul:
Se citesc de la tastatur temperaturile nregistrate pe durata a n zile. Se cere
programul Ccare afieaz numrul zilei n care s-a ntlnit prima temperatur negativ sau un
mesaj n cazul n care nu s-a ntlnit o temperatur negativ.
#include
#include
voidmain()
{ intn,i;
floattemperatura;
puts("\nIntroduceti numarul de zile:");
scanf("%d",&n);for(i=1;i
7/29/2019 Programare in C
31/130
Limbajul de programare C
Untablou este reprezentat printr-o mulime finit i ordonat de elemente de acelai tip
care are asociat un nume.
Tablourile se folosesc n cazul aplicaiilor care lucreaz cu mai multe date i pentru
care declararea unor variabile simple nu mai este suficient. Un astfel de exemplu ar fi un
program care citete temperaturile nregistrate ntr-o perioad oarecare de timp i apoi le
prelucreaz (determin temperatura minim, maxim, le ordoneaz cresctor sau descresctor,etc.).
n acest caz declararea unei variabile simple cum este variabila temperatura din
exemplele anterioare nu mai este suficient, deoarece ea poate memora la un moment dat doar
temperatura curent, nu i pe celelalte temperaturi.
n astfel de situaii se utilizeaz date structurate. Datele structurate sunt date care
conin mai multe date de acelai tip sau de tipuri diferite. Tablourile sunt structuri de date care
conin date de acelai tip. Referirea la o dat din cadrul tabloului se face utiliznd un indice.
Indicele reprezint poziia datei n tablou.Untablou, ca orice variabil simpl, trebuie declarat nainte de a fi utilizat. Declaraia
de tablou, n forma cea mai simpl, conine tipul comun, al elementelor sale, numele tabloului
i limitele superioare pentru fiecare indice, incluse ntre paranteze drepte:
tip lista_de_elemente;
unde lista_de_elemente se compune dintr-un element sau mai multe, separate prin virgul. Un
element dintr-o astfel de list are formatul: nume[lim1][lim2][limn] n care lim1, lim2, ,
limn sunt expresii constante care au valori ntregi. Prin expresie constant nelegem o
expresie care poate fi evaluat la ntlnirea ei de ctre compilator.
Exemple:
1.Fie v un vector cu 10 componente de tip ntreg. El se declar astfel: int v[10];
2.Fie a o matrice cu 100 de linii i 4 coloane. Elementele ei sunt reprezentate n virgul
flotant simpl precizie. Ea se declar astfel:float a[100] [4];
La elementele unui tablou ne referim prin variabile cu indici. O astfel de variabil se
compune din numele tabloului urmat de unul sau mai muli indici, fiecare indice inclus n
paranteze drepte. Numrul indicilor definete dimensiunea tabloului.Indiciisunt expresii care
au valori ntregi.Limita inferioar a indicilor estezero.
Astfel, dac v este tabloul declarat n exemplul 1, atunci elementele lui sunt: v[0], v[1],v[2], v[3], v[4], v[5], v[6], v[7], v[8], v[9].
n cazul matricei a declarate n exemplu 2, elementele ei vor fi
pe prima linie: a[0] [0], a[0] [1], a[0] [2], a[0] [3]
pe a doua linie: a[1] [0], a[1] [1], a[1] [2], a[1] [3]
. . .
pe ultima linie: a[99] [0], a[99] [1], a[99] [2], a[99] [3]
164
7/29/2019 Programare in C
32/130
7/29/2019 Programare in C
33/130
Limbajul de programare C
for(i=0;i
7/29/2019 Programare in C
34/130
Limbajul de programare C
printf("\nIntroduceti nr. de coloane:");
scanf("%d",&m);
printf("\nIntroduceti elementele matricei\n");
for(i=0;i
7/29/2019 Programare in C
35/130
Limbajul de programare C
relativ simplu, algoritm cunoscut sub denumirea de bubblesort sau sortare prin metoda
bulelor.
Algoritmul const din parcurgerea vectorului de mai multe ori, n fiecare parcurgere
comparndu-se elementele aflate pe poziii alturate. Ori de cte ori cele dou elemente
comparate nu se afl n ordinea dorit, ele se vor interschimba. Pentru interschimbare se va
folosi o variabil auxiliaraux. Algoritmul se consider ncheiat n urma unei parcurgeri avectorului n care nu se mai efectueaz nici o interchimbare. Pentru a se marca efectuarea unei
interschimbri se va utiliza o variabil de tip ntreg, gata, cu rol de adevrat/fals.
Aceast variabil va primi valoarea 1 nainte de fiecare parcurgere a vectorului i valoarea
0 n momentul n care se efectueaz o interschimbare. Algoritmul se va considera ncheiat
cnd variabilagatava rmne 1 la sfritul parcurgerii vectorului.
Algoritmul este explicat pentru vectorul:
A = [9, 2, 6, 1, 3 ].a) Prima parcurgere:
gata = 1
i=0 i=1 i=2 i=39 2 2 2 2 gata=02 9 6 6 6 gata=06 6 9 1 1 gata=01 1 1 9 3 gata=03 3 3 3 9
b) A doua parcurgere:
gata = 1
i=0 i=1 i=2 i=32 2 2 2 26 6 1 1 1 gata=01 1 6 3 3 gata=03 3 3 6 69 9 9 9 9
168
7/29/2019 Programare in C
36/130
7/29/2019 Programare in C
37/130
Limbajul de programare C
getch();
}
6.8. Apelul i revenirea dintr-o funcie
6.8.1 Apelul unei funcii
Am amintit n capitolul 1 c funciile sunt de dou feluri:
- funcii care returneaz o valoare la revenirea din ea;
- funcii care nu returneaz o valoare la revenirea din ea.
O funcie care nu returneaz o valoare la revenirea din ea se apeleaz printr-o
instruciune de apel. Ea are urmtorul format:
nume(lista_parametrilor_efectivi);
n cazul n care o funcie returneaz o valoare, ea poate fi apelat fie printr-o
instruciune de apel, fie sub forma unui operand al unei expresii. Apelul se face printr-oinstruciune de apel atunci cnd nu dorim s utilizm valoarea returnat de funcia respectiv.
Definiiaunei funcii are structura urmtoare:
Antet
instruciune compus
Antetulare formatul:
tip nume(lista_parametrilor_formali)
Funciile care nu returneaz o valoare la revenirea din ele au ca tip cuvntul cheie void.
De asemenea, dac lista_parametrilor_formali este vid, ea poate fi definit prin cuvntul
cheie void. Lista parametrilor formali conine declaraiile acestora separate prin virgul.
Parametrii formali ai unei funcii sunt reprezentai de datele prin care funcia respectiv
comunic cu alte funcii din cadrul programului respectiv. Ea se pune n coresponden cu lista
parametrilor efectivi din instruciunea de apel. Cele dou liste de parametrii trebuie s coincid
ca numr, ordine i tip.
6.8.2 Prototipul unei funcii
O funcie poate fi apelat dac ea este definit n fiierul surs nainte de a fi apelat.
Acest lucru nu este totdeauna posibil i n astfel de cazuri apelulfunciei trebuie s fie
precedat deprototipulei.Prototipulpoate fi scris la nceputul fiierului surs i n acest caz el
va fi valabil n tot fiierul surs.
Prototipul unei funcii este de fapt antetul funciei i conine toate informaiile
referitoare la funcia respectiv: numele funciei, tipul returnatde funcie, numruli tipul
parametrilor funciei.
170
7/29/2019 Programare in C
38/130
Limbajul de programare C
Exemple:
1) double val(double x, int a); Acest prototip indic faptul c funcia valreturneaz o
valoare flotant n dubl precizie i are doi parametri, primul de tip double i al doilea de tip
int.
Exemple de instruciuni de apel:
y= val(z,b); s=val(12.6, 5);n aceste exemple s,ziy trebuie s fie variabile de tipul double iarb o variabil de
tipul int.
Se observ c o funcie poate fi apelat fie cu parametrii constani, fie cu parametrii
variabili.
2) void citire(void);
Conform acestui prototip funcia citire nu returneaz nici o valoare i nu are
parametrii. Funcia poate fi apelat printr-o instruciune de apel de forma:
citire( );3) double sum (double x[], int n);
Funcia sum returneaz o valoare flotant n dubl precizie. Ea are doi parametrii: un
tablou unidimensional de tip double i o variabil de tip int. Aceast funcie se poate apela
printr-o instruciune de apel de forma:
s=sum(a,m);
unde a trebuie s fie un tablou cu elemente de tip double, mo variabil de tipul int, iars o
variabil de tipul double.6.8.3. Apel prin valoare i apel prin referin
La apelul unei funcii, fiecrui parametru formal i se atribuie valoarea parametrului
efectiv care-i corespunde. Deci, la apelul unei funcii, se transfer valorile parametrilor
efectivi. Din aceast cauz, se spune c apelul este prin valoare.
n anumite limbaje de programare, la apel se transfer nu valorile parametrilor efectivi
ci adresele acestor valori. n acest caz se spune c apelul este prin referin.
ntre cele dou tipuri de apeluri exist o diferen esenial i anume: n cazul apelului
prin valoare, funcia apelat nu poate modifica parametrii efectivi din funcia care a fcutapelul, neavnd acces la ei. De fapt funcia primete o copie a valorilor de apel.
n cazul apelului prin referin, funcia apelat dispunnd de adresa parametrilor
efectivi, i poate modifica pe acetia.
n limbajul C, apelul prin referin se realizeaz n cazul n care parametrul efectiv este
numele unui tablou. n acest caz, se transfer valoarea numelui tabloului, adic adresa
primului su element. n felul acesta, funcia apelat dispune de adresa de nceput a tabloului
utilizat ca parametru i n consecin ea poate modifica elementele tabloului respectiv.
171
7/29/2019 Programare in C
39/130
Limbajul de programare C
n concluzie, n limbajul C, transferul parametrilor se face prin valoare. Acest
transfer devine prin referin n cazul n care parametrul efectiv este numele unui tablou sau se
cere explicit acest lucru adugnd caracterul & n faa parametrului.
6.8.4. Revenirea dintr-o funcie
Revenirea dintr-o funcie se poate face n dou moduri:
-la ntlnirea instruciunii return;
-dup execuia ultimei sale instruciuni, adic a instruciunii care precede acolada
nchis ce termin corpul funciei respective.
Instruciunea return are dou formate: return;
sau return expresie;
Primul format se utilizeaz cnd funcia nu returneaz o valoare, iar cel de al doilea
format se utilizeaz atunci cnd funcia returneaz o valoare.
Un exemplu de program care utilizeaz funcii definite de utilizatori este urmtorul:Se citesc de la tastatur cele n elemente de tip ntreg ale unui vector. Se cere
programul Ccare determin:
a) Suma cifrelor fiecrui element din vector;
b) Inversul fircrui element din vector;
c) Cel mai mare divizor comun al elementelor din vector.
Pentru ca programul s realizeze aceste cerine vom defini trei funcii utilizator:
a) O funcie suma_cifrecare va calcula suma cifrelor unui numr ntreg transmis
ca parametru;b) O funcie invers care va returna inversul unui numr ntreg transmis ca
parametru;
c) O funcie cmmdccare va determina cel mai mare divizor comun a dou numere
ntregi transmise ca parametri.
Programul este prezentat n continuare:
#include
#include
intsuma_cifre(intn){ ints;
s = 0;
while (n!=0)
{ s = s + n % 10;
n = n / 10; }
return s; }
intinvers(intn)
{ intinv;
172
7/29/2019 Programare in C
40/130
7/29/2019 Programare in C
41/130
Limbajul de programare C
O prim clas de memorie este aceea alocat variabilelor globale. Lor li se aloc
memorie pe toat perioada execuiei programului i ele pot fi utilizate n tot programul.
O alt clas de memorie este alocat variabilelor locale. O astfel de variabil nu este
valabil n tot programul. Ea are o utilizare local.
6.9.1. Variabile globale
O variabil globalare o definiie i attea declaraii de variabil extern cte sunt
necesare.
n mod implicit, definiia unei variabile globale determin ca variabila respectivs fie
definit ncepnd din punctul scrierii ei i pn la sfritul fiierului surs respectiv. De aceea
se recomand ca definiiile variabilelor globale s fie scrise la nceputul fiierului surs.
Exemplu:
inti; double x;
voidmain (){
i = 100;
x = i*x;
}
Variabilele iix, fiind definite n afara funciilor programului, sunt globale.
Construciile int ii respectiv double xsunt definiiile lor, iar din punct de vedere
sintactic ele au acelai format ca declaraii obinuite.
Ele pot fi folosite n toate funciile din fiierul surs care conine definiiile lor fr alte
declaraii suplimentare.
n schimb, pentru a le utiliza n funcii ale programului situate n alte fiiere surs dect
n cel n care sunt definite, ele trebuie declarate ca externe n funciile respective.
O declaraie de variabil extern este la fel ca i o declaraie obinuit, doar c ea
ncepe prin cuvntul extern.
De exemplu, dac dorim s folosim variabile globale i i x definite mai sus ntr-o
funcief, aflat ntr-un alt fiier surs dect cel n care au fost ele definite, atunci n corpulfunciei fle vom declara ca externe:
f ()
{ extern inti;
extern double x;
x = i*x;
}
174
7/29/2019 Programare in C
42/130
Limbajul de programare C
Compilatorul aloc memorie pentru variabilele globale n momentul ntlnirii
definiiilor lor. Aceast memorie se afl ntr-o zon special destinat acestui scop i ea
rmne alocat pe ntreaga durat a execuiei programului.
6.9.2. Variabile locale
Variabilele localenu sunt valabile n tot programul. Exemple de variabile locale suntvariabilele declarate n corpul unei funcii i care nu sunt declarate ca externe. Ele pot fi
folosite numai n corpul funciei respective, adic ncepnd din momentul apelrii funciei
respective i pn la revenirea din ea.
Astfel de variabile pot fi alocate pe stiv. n acest caz, lor li se aloc memorie pe stiv
la intrarea n funcia n care sunt declarate i i pierd alocarea respectiv la ieirea din funcie,
cnd se reface stiva la forma dinaintea apelului.
Stiva este o zon de memorie cu o destinaie special. Ea are o structur de tip LIFO
(LastInput First Output). ntr-o astfel de zon de memorie se aloc pe rnd memorievariabilelor locale declarate n corpul funciilor. Eliberarea memoriei astfel alocate se face n
ordine invers alocrii ei, la terminarea execuiei funciei respective.
Variabilele alocate n acest fel se numesc automatice. Ele se declar n corpul
funciilor i au sintaxa obinuit.
Se poate ca variabilele locale s nu fie alocate pe stiv, ci ntr-o zon de memorie
destinat special n acest scop. O astfel de variabil se spune c este static.
O variabil static declarat n corpul unei funcii are domeniul de valabilitate numai
corpul funciei respective, ca i variabilele automatice. Spre deosebire de ele, variabila staticnu se aloc pe stiv, ci ntr-o zon de memorie destinat acestui scop.
n cazul n care o variabil static este declarat n afara funciilor, ea este definit din
punctul n care a fost declarat i pn la sfritul fiierului surs care conine declaraia ei.
Spre deosebire de variabilele globale, o variabil static declarat n acest fel nu poate fi
declarat ca extern.
Menionm c tablourile de dimensiuni mari se recomand a fi declarate statice,
deoarece dac ele sunt automatice, pot s conduc la depirea stivei alocate programului.
Amintim c, implicit, dimensiunea stivei alocate unui program este de 4K octei.
Exemple:
1. Fiierul fis1.cpp este un fiier surs care conine dou variabile globale i i x o
variabil staticy i dou funcii main if, care i ele conin la rndul lor variabilele statice a
i b.
/* variabile globale
int i; /* definitia variabilei i */
175
7/29/2019 Programare in C
43/130
Limbajul de programare C
double x; /*definitia variabilelor x
*/
/* variabile statice */
static int y;
voidmain ()
{
static char a; /* variabila statica
*/
int c; /* variabila automatica
*/
.
/* se pot folosi variabilele i, x, y, a si c*/
.
}
f()
{ intp; /* variabila automatica
*/
staticfloat b; /* variabila statica */
..
/* se pot folosi variabilele i, x, y, p si b */
.
}
Variabilele a i c sunt locale funciei maini ele nu pot fi folosite n funcia f. La fel,
variabilelep i b sunt locale n funciafi nu pot fi folosite n funcia main.
2. Funcia fis2.cpp conine funciile f1 i f2 care intr n componena aceluiai
program ca i funciile mainifdin fiierul fis2.cpp.
/* variabile statice */
staticusingnedt;
f1 ()
{
extern inti; /* declaratie externa pentru i */
extern double x; /* declaratie externa pentru x */
static intk;
.
/* se pot folosi variabilele i, x, k si t */
}
176
7/29/2019 Programare in C
44/130
7/29/2019 Programare in C
45/130
Limbajul de programare C
evaluat de compilator la ntlnirea ei, deoarece variabilele globale i statice se iniializeaz
prin valori definite la compilare.
Variabilele automatice se iniializeaz la execuie, de fiecare dat cnd se activeaz
funcia n care sunt declarate. Din aceast cauz, nu mai este necesar ca expresia s fie o
expresie constant. Totui, la ntlnirea ei, trebuie s fie definii operanzii expresie de
iniializare.Exemplu:
f (intn) ;
{ intx = 10;
int y = x*n;
}
La ntlnirea expresieix*n sunt deja definii ambii operanzi:
- xa fost n prealabil iniializat;
- n are o valoare care a fost deja transferat la apel.
Variabilele globale i statice neiniializate au implicit valoarea egal cu zero.Variabilele automatice neiniializate au o valoare iniial imprevizibil.
Tablourile se pot iniializa printr-o list de expresii incluse ntre acolade. Astfel, un
tablou unidimensional se poate iniializa folosind urmtorul format:
tip nume [n] = {exp1, exp2, , expn}; sau
static tip nume [n] = {exp1, exp2, , expn}; dac tabloul este static
Pentru un tablou bidimensional vom folosi urmtorul format:
tip nume [n] = {
{exp11, exp12, , exp1m},{exp21, exp22, , exp2m},...............
{expn1, expn2, , expnm},
};
Exemple:
int it[ ] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
intmatrice [4] [3] = {{-1, 0, 1}, {-1}, {0, 1}, {0, 0, 1}}.
Observaii:1. n cazul vectorului it nu s-a specificat la declarare dimensiunea acestuia deoarece
ea rezult n urma iniializrii, fiind egal cu 9;
2. La iniializarea elementelor tabloului matrice o parte din elemente pot rmne
neiniializate.
6.10. Pointeri n limbajul C
Unpointereste o variabil care are ca valori adrese.
178
7/29/2019 Programare in C
46/130
Limbajul de programare C
Pointerii se utilizeaz pentru a face referire la date cunoscute prin adresele lor. Astfel,
dac p este o variabil de tip care are ca valoare adresa zonei de memorie alocat pentru
variabila ntreagx, atunci: p reprezint valoarea variabileix, ca n figura 6.2:
n figura 6.2 valoarea 2500 reprezint adresa de memorie a valorii 5, adic este un
pointer.
Operatorul (unar) are aceeai prioritate ca i ceilali operatori unari dinlimbajul C.
Dac p conine adresa zonei de memorie alocat variabilei x, vom spune c p
pointeaz sprexsau c p conine adresa lui x.
Pentru a atribui unui pointeradresa unei variabile, putem folosi operatorul unar &.
Astfel, dac dorim cap s pointeze sprex, putem utiliza atribuirea:p = &x;
6.10.1. Declaraia de pointer
n general, unpointerse declar prin:
tip nume;ceea ce nseamn c numeeste un pointer care pointeaz spre o zon de memorie ce conine o
dat de tipul tip.
Comparnd declaraia anterioar de pointer cu una obinuit:
tip nume;putem considera c tip dintr-o declaraie pointerreprezint tip dintr-o declaraie obinuit.De aceea, construcia tip se spune c reprezint un tip nou, tipul pointer.
Exist cazuri n care dorim ca un pointers fie utilizat cu mai multe tipuri de date. n
acest caz, la declararea lui nu dorim s specificm un tip anume. Aceasta se realizeaz folosind
cuvntul cheie voidastfel:
voidnume;Exemple:
179
x
Memoria p (adresa de memorie
a variabilei x)
5
Memoria
2500
Fig. 6.2. Referirea la o variabil utiliznd pointeri.
7/29/2019 Programare in C
47/130
Limbajul de programare C
Fie declaraiile:
intx,y;
intp;
1. y = x+100; este echivalent cu secvena:
p = &x;
y = p+100;n care luiy i se atribuie suma dintre coninutul zonei a crei adres se afl np i 100.
2. x = y; este echivalent cu secvena:
p = &x;
p = y;
n care coninutul zonei a crei adres se afl np devine egal cu valoarea luiy.
3. x++; este echivalent cu secvena:
p = &x;
(p)++;n care coninutul zonei a crei adres se afl np se mrete cu 1.
4. Fie funciaperm de mai jos:
voidperm(intx,inty)
{ int temp;
temp=x;
x=y;
y=temp; }
Un apel de forma:
perm (a,b);nu are nici un efect, deoarece la acest apel valoarea lui a se transfer parametruluix, iar a lui b
parametrului y. Apoi funcia perm permut valorile parametrilorx i y, ns prin aceasta
valorile parametrilor efectivi a i b rmn nemodificate. Deci la revenirea din funcia perm,
variabilele a i b au aceleai valori nemodificate de apel.
Pentru a realiza o permutare a valorilor acestor variabile, este necesar s se transfere nu
valorile, ci adresele variabilelor.
Acest lucru este posibil dac modificm apelul n felul urmtor:perm (&a, &b);
n acest caz parametrii formali ai funciei perm au ca valori adrese, deci ei sunt
pointeri. Avnd n vedere acest fapt, funciaperm sufer urmtoarele modificri:
voidperm(intx,inty); /*x si y sunt pointeri spre
intregi*/
{ inttemp;
180
7/29/2019 Programare in C
48/130
7/29/2019 Programare in C
49/130
Limbajul de programare C
float medii[30];
Aceast declaraie va avea ca efect alocarea unei zone contigue de 30 de locaii
(fiecare avnd dimensiunea de 4 octei), chiar dac programatorul va stoca doar 25 de medii.
Varianta cupointeriva consta n declararea unui pointersprefloat, la care se va aloca exact
attea locaii ct studeni sunt.
Un alt exemplu este cel n care lucrm cu tablouri de caractere. De exemplu, pentru apstra numele unei persoane, se putea folosi un tablou declarat astfel:
char Nume[20];
Varianta cu pointeri va consta n declaraia urmtoare:
char *Nume;
Aceast variant este mult mai flexibil oferind posibilitatea de a aloca exact attea
poziii ct este necesar.
6.10.3. Operaii cu pointeri
Asupra pointerilor se pot face diferite operaii, indicate n cele ce urmeaz.
a) Operaii de incrementare i decrementare
Operatorii de incrementareidecrementarese pot aplica variabilelor de tip pointer.
Ei se execut altfel dect asupra datelor de alte tipuri.
Efect:
- operatorul de incrementare aplicat asupra unui operand de tip pointer spre tipul t
mrete adresa coninut de operand cu numrul de octei necesari pentru a pstra o dat detipul t;
- operatorul de decrementare se execut n mod analog.
Observaie:
Aceast proprietate este foarte util cnd se au n vedere prelucrri de tablou. Fie
declaraiile de mai jos:
int tab[n];
int *p;
int i;
unde n este o constant ntreag, fiep = &tab[i]; unde 0
7/29/2019 Programare in C
50/130
Limbajul de programare C
Efect:
- expresia p+n mrete valoarea lui p cu nt, unde teste numrul de octei necesaripentru a memora o dat de un tip spre care pointeazp;
- n mod analog, expresiap-nmicoreaz valoarea luipcu nt.Dac a este un tablou cu elemente de tipul t, atunci a este un pointer, deci expresia
a+n este corect i va reprezenta un pointerspre elementul a[n](adresa acestuia). Valoareaacestui element se poate obine din expresia (a+n).
n acest fel se pot nlocui indicii de tablou prin expresii cu pointeri.
c) Compararea a doi pointeri
Doipointericare pointeaz spre elementele aceluiai tablou pot fi comparai folosind
operatorii de relaie i de egalitate.
Astfel, dacp i q sunt doipointericare pointeaz spre elementele t[i]respectiv t[j]ale
tabloului t, expresia p
7/29/2019 Programare in C
51/130
Limbajul de programare C
void *malloc (usingned n);
unde n este numrul de octei ai zonei de memorie care se aloc.
n cazul n care n este prea mare, funcia returneaz pointerulNULL.
Funcia calloc are prototipul:
void *calloc (usingned nrelem, usingned dimelem);
unde: - dimelem este dimensiunea n octei a unui element de dat;- nrelem este numrul elementelor pentru are se aloc memorie.
Prin aceast funcie se aloc nrelem*dimelem octei.
Ea returneazpointerulspre nceputul zonei rezervate saupointerul NULL n cazul n
care numrul octeilor este prea mare (depete zona de memorie liber afectat alocrilor
dinamice).
Elementele din zona de memorie alocat prin calloc au valoareazero.
Funciafree elibereaz o zon de memorie care n prealabil a fost alocat prin malloc
sau calloc. Prototipul ei este:
void free(void *p);
unde p este pointerul returnat de malloc sau calloc la alocare, deci este pointerul spre
nceputul zonei care se elibereaz.
Exemplu:
Funcia memoreaz un ir de caracatere ntr-o zon de memorie alocat prin funcia
malloc. Ea returneaz adresa de nceput a zonei n care s-a salvat irul de caractere, deci
returneaz un pointer spre tipul char.
#include #include
#include
char *memoreaza (char *s)
/* memoreaza sirul de caractere spre care pointeaza s in zona
de memorie furnizata de malloc*/
{
if((p = (char *) malloc (strlen(s)+1)) ! = NULL)
{ strcpy(p,s); return p;
}
elsereturn NULL;
}
n exemplul anterior s-au utilizat dou funcii specifice irurilor de caractere, strlen,
care returneaz lungimea unui ir de caractere i strcpy, care copiaz un ir de caractere n
altul, funcii definite n fiierul string.h.
184
7/29/2019 Programare in C
52/130
Limbajul de programare C
6.10.5. Prelucrarea tablourilor unidimensionale folosind pointeri
S-a artat c numele unui tablou estepointer constant care are ca valoare adresa
primului element al su.Pentru declaraia:
tip a[];
identificatorul a are ca valoare adresa elementului a[0], adic &a[0].Fie tip*p; atunci atribuirea de formap = a; este corect i n urma acestei atribuiri, p
are valoare tot adresa lui a[0].
Dac utilizm ca parametru efectiv numele unui tablou unidimensional, atunci
parametrul formal corespunztor poate fi declarat fie ca un tablou unidimensional (cu
paranteze ptrate vide), fie printr-un pointer:
tip a [100]
f(a);
Antetul luifse definete prin unul din formatele:
f(tip t[]) sau f(tip*t).
Indiferent care dintre antete se alege, n corpul funcieifse pot folosi att variabilele cu
indici: t[exp]ct i expresii cu pointeri: *(t+exp) pentru a face acces la elementele tabloului
tab.
S-a artat c n general, dac tab este un tablou unidimensional de tipul tip, atunci a+n
este chiar adresa elementului a[n]. Deci:
x = a[n] sau x = *(a+n)sunt atribuiri care au acelai effect (atribuire lui xvaloarea elementului a[n]). Expresiile cu
pointeri pot fi folosite i n stnga operatorului de atribuire, adic:
a[n] = x
i *(a+n) = x
au acelai efect.
Din cele de mai sus rezult c variabilele cu indici se pot echivala prin expresii cu
pointeri. Este posibil s procedm i invers, adic s nlocuim expresiile cu pointeri prin
variabile cu indici, dei acest lucru nu este recomandabil.
Fie, de exemplu, declaraia: tip*p = (tip*)malloc(...);
Expresia *(p+n) este echivalent cu expresiap[n].
Exemplu:
Programul urmtor calculeaz i afieaz suma elementelor ntregi ale unui vector de
dimensiune n .
#include
185
7/29/2019 Programare in C
53/130
7/29/2019 Programare in C
54/130
7/29/2019 Programare in C
55/130
Limbajul de programare C
Dac n cazul tablourilor unidimensionale, tab+n este adresa elementului tab[n], adic
&tab[n], n cazul tablourilor bidimensionale, expresia tab+n este adresa elementului
tab[n][0].
Aceast interpretare rezult din faptul c un tablou bidimensionaltrebuie considerat ca
fiind un tablou de tablouri unidimensionale. n general, un tablou k dimensional este un
tablou de tablouri k-1 dimensionale.Fie, de exemplu, declaraia:
tip tab[m][n];
Tabloul tab poate fi privit ca m tablouri unidimensionale. Astfel, tab[0], tab[1], ,
tab[m-1] sunt cele m elemente ale lui tab i fiecare este un pointer spre cte un tablou
unidimensional de n elemente. De aici rezult c tab[0] are ca valoare adresa lui tab[0][0],
tab[1]are ca valoare adresa lui tab[1][0]i n general tab[i]are ca valoare adresa lui tab[i][0].
n figura 6.4 este prezentat interpretarea tablourilor bidimensionale descris anterior.
Cum *(tab+i) are ca valoare chiar tab[i], rezult c tab[i][0] are aceeai valoare cu
*(*(tab+i)).De asemenea, tab[i]+j are ca valoare adresa lui tab[i][j]. Deci tab[i][j] are aceeai
valoare ca i expresia *(tab[i]+j), iar aceasta din urm are aceeai valoare cu expresia
*(*(tab+i)+j).
nseamn c atribuirile *(*(tab+i)+j) = xi tab[i][j] = xsunt echivalente.
Dac tab este un tablou unidimensionaldeclarat prin:
tip tab[...];
atunci tab are tipul tip*adicpointerspre tip.
Dac tab este un tablou bidimensionaldeclarat prin:
tip tab[m][n];
atunci tab are tipul tip (*)[n]adicpointerspre tip.
Menionm c n declaraia de mai sus m i n sunt expresii constante.
S presupunem c tab este parametru la apelul funcieif:
... f(tab).
n acest caz, parametrul formal al funcieifpoate fi declarat n urmtoarele moduri:
... f (tip t[ ][n]) sau ... f(tip(*p)[n]).
188
tab[0][0] tab[0][1] tab[0][n-1]
tab[1][0] tab[1][1] tab[1][n-1]
... ... ...
tab[m-1][0] tab[m-1][1] tab[m-1][n-1]
tab[0]
tab[1]
...
tab[m-1]
Fig. 6.4. Interpretarea tabloului bidimensional ca o mulime detablouri unidimensionale.
7/29/2019 Programare in C
56/130
Limbajul de programare C
Fie declaraia:
tip *tab1[n];
n acest caz tab1 este un tablou unidimensional de pointeri spre tipul tip, adic
fiecare element din cele n ale tabloului tab1 este unpointerspre tip. Tablourile tab i tab1 nu
trebuie confundate. Tabloului tab i se aloc o memorie de m*n*sizeof(tip) octei. Tabloului
tab1 i se aloc n*sizeof(tip*) octei.Dac o funcie g are la apel ca parametru pe tabloul tab1: ... g(tab1) ... atunci
parametrul formal al funcieigpoate fi declarat n urmtoarele moduri:
... g(tip*p[]) sau ...g(tip**p).
Exemple:
1. Fie declaraiile:
double tab[2][3] = {{0, 1, 2}, {3, 4, 5}};
double *p;
n tabelul 6.7sunt prezentate rezultate ale execuiei unor instruciuni:
Tabelul 6.7.
Instruciuni
Eleme
ntul
afiat
Valoarea
elementului
p = tab[0];
printf (%g, *p);tab[0] [0]; 0
p = tab[1];
printf (%g, *p);tab[1] [0]; 3
printf (%g, *(*(tab))); tab[0] [0]; 0
printf (%g, *(*(tab+1)+2)); tab[1] [2]; 5
2. Considerm funciafdefinit astfel:
voidf(double (*p)[3])
{ inti, j;
for(i=0; i
7/29/2019 Programare in C
57/130
Limbajul de programare C
double t0[3] = {10, 11, 12};
double t1[3] = {13, 14, 15};
i atribuirile t[0] = t0; t[1] = t1;
Definim funciaf1 astfel:
voidf1(double *p[ ])
{
}
unde corpul funcieif1 coincide cu al funcieif.
La apelurilef1(t); se listeaz valorile elementelor tablourilort0 i t1, separate prin cte
un spaiu, adic:
10 11 12 13 14 15
Acelai rezultat se obine dac antetul luif1 se schimb cu:
void f1 (double **p)
n ambele situaii, expresiap[i][j]poate fi schimbat cu *(*(p+i)+j).Ca o consecin a celor prezentate anterior,putem renuna la tablourile bidimensionale
statice i putem folosi tablouri de pointeri. Acest lucru este posibil pentru c pointerii, fiind
variabile, pot forma alte tipuri de date structurate, de exemplu tablouri. Dac Teste un tip de
date oarecare, tipul pointerilor spre acel tip va fi T*.
Un tablou de pointeri spre tipul Tse declar prin :
T *Nume[dim];
unde Nume va fi numele tabloului de pointeri, iardim numrul depointeridin tablou.
Cu ajutorul unui tablou de pointeri, se pot pstra datele unei matrici, darcu avantajul cfiecare linie are o lungime variabil.
S considerm un exemplu n care se dau notele a n candidai la cele m probe date la
un concurs pentru obinerea unui post. Putem folosi un tablou de pointeri pentru afiarea
notelor fiecrui candidat i pentru determinarea mediei obinute de fiecare candidat. Notele
candidailor vor putea fi stocate i accesate cu ajutorul unui tablou de pointeri, declarat astfel:
Note[I]
Note[0]Note[1]
.Note[19]
Prezentm programul surs n varianta cu tablouri de pointeri:
#include
#include
#include
190
4 5 8 9 6 7 5
9 9 6 7 9 8 8
8 7 4 5 6 7 8
Fig. 6.5. Memorarea notelor studenilorutiliznd pointerii.
int *Note[20];
adic ca un tablou de 20 de pointeri, cte un
pointer pentru fiecare candidat. De fapt,fiecare pointer va conine adresa unei zone
de memorie unde sunt stocate notele acelui
candidat (zona ce trebuie rezervat ). Acest
lucru se observ n figura 6.5:
7/29/2019 Programare in C
58/130
Limbajul de programare C
intN, M, *Note[20];
float*Media;
voidCitire (void)
{ intI, J;
printf("\n Dati numarul de candidati");
scanf("%d",&N);printf("\n Dati numarul de probe");
scanf("%d",&M);
for(I=0; I
7/29/2019 Programare in C
59/130
7/29/2019 Programare in C
60/130
7/29/2019 Programare in C
61/130
7/29/2019 Programare in C
62/130
Limbajul de programare C
(*p)(double) - nseamn cp este un pointer spre funcii cu argumente de
tip double.
double (*p)(double) - nseamn c p este un pointer spre funcii care
returneaz o valoare de tip double i are ca parametru un double.
Pointerul p va putea fi folosit pentru a accesa valorile funciei. Apelarea funciei se
face cu expresia (*p)(x). Mai mult, funcia general construit anterior, se va putea apela( pentru exemplele de funcii prezentate anterior) astfel :
ValInt= Integrala(10, 20, 100, f1);
sau
A=-3.14; B=3.14 ; // adic A i B sunt egale cu Pi i Pi
ValInt= Integrala(A, B, 100, f2);
Trebuie s atragem atenia asupra faptului c construcia double *p(double) este
corect, dar are alt semnificaie: reprezint prototipul unei funcii ce returneaz un pointer
spre double (!!). Acest lucru este datorat faptului c parantezele () sunt mai prioritare dect
operatorul *.Prezentm programul care calculeaz valoarea integralei.
#include
#include
#include
#include
double f(double x)
{ return x*x-1; }
double f1(double x)
{ return sin(x*x); }
double f2(double x)
{ return exp(x); }
double Integrala(double A, double B, intn, double (*p)(double))
{ double pas,S;inti;
pas=(B-A)/n;
S=0;
for(i=0;i
7/29/2019 Programare in C
63/130
Limbajul de programare C
A=-3.14;
B=3.14;
ValInt=Integrala(A,B,100,f1);
printf("\n valoarea integralei din f=sin(x*x) este %lf",ValInt);
ValInt=Integrala(10,100,100,f2);
printf("\n valoarea integralei din f=exp(x) este %lf",ValInt);getch(); }
196
7/29/2019 Programare in C
64/130
Limbajul de programare C
6.10.8. Tratarea parametrilor din linia de comand
n linia de comand folosit la apelul execuiei unui program se pot utiliza diferii
parametri. n cazul utilizrii mediului de dezvoltare integratBorland C, aceti parametri se pot
defini utiliznd submeniul Arguments al meniului Options. Se selecteaz meniul Options
folosind sgeile sau tastnd O. Apoi se selecteaz submeniul Arguments cu ajutorul
sgeilor sau tastndA. n acest moment se afieaz o fereastr i se vor tasta parametrii care
s fie prezeni la lansarea programului. Parametrii se tasteaz unul dup altul, separai prin
blancuri. Dup ultimul parametru se va aciona tastaENTER.
Aceti parametri pot fi utilizai parametrii argc i argv ai funciei principale.
Parametrul argc este de tip ntreg i indic numrul de parametri din linia de comand
(sau diferii cu ajutorul submeniului Arguments). Parametrul argv este un tablou de pointeri
spre zonele n care sunt pstrai parametrii liniei de comand. Acetia se consider iruri de
caractere. n felul acesta, antetul funciei principale va fi:
main (int argc, char *argv[])Exemplu:
Considernd c la lansarea programuluiprogs-au furnizat parametrii:
15 SEPTEMBRIE 2001
n acest caz argc = 4, iar tabloul argv conine pointerii:
- argv[0] - pointeri spre numele programului (calea, numele i extensia.EXE);
- argv[1] - pointeri spre 15;
- argv[2] - pointeri spre SEPTEMBRIE;
- argv[3] - pointeri spre 2001.
Observaii:1) Lansarea unui program se face cu prima instruciune a funciei principale. Parametrii
argc i argv au deja n acest moment valorile indicate mai sus. Deci ei pot fi analizai chiar
ncepnd cu prima instruciune a funciei principale.
2) n mod frecvent aceti parametri reprezint diferite opiuni ale programului, date
calendaristice, nume de fiiere etc.
3)argv[0]este ntotdeaunapointerulspre numele fiierului cu imaginea executabil a
programului.Exemple:
1. Programul urmtor afieaz parametrii din linia de comand.
voidmain(intargc, char*argv[])
/*afiseaza parametrii din linia de comanda */
{ inti;
for(i = 0; i
7/29/2019 Programare in C
65/130
7/29/2019 Programare in C
66/130
7/29/2019 Programare in C
67/130
7/29/2019 Programare in C
68/130
Limbajul de programare C
*(int*) &k=3;
*(int*) &1 = -3;
printf(dimensiunile lui I,j,n,1\n);
printf(%d %d %d %d\n, sizeof(i), sizeof(j), sizeof(n), sizeof(1));
printf(dimensiunile lui x,s,s1,s2\n);
printf(%d %d %d %d\n, sizeof(x), strlen(s), strlen(s1), strlen(s1),strlen(s2));
printf(valorile lui i,n,s,s1,s2\n);
printf(i = %d n=%d s=%s s1=%s s2=s%\n, i,n,s,s1,s2);
printf(valorile lui j,k,1\n);
printf(j=%d k=%d l=%d\n, j,k,l);
*(double *) &pi=3.14159;
printf(valorile lui x,pi\n);
printf(x=%.10f pi=%.10f\n, x,pi);
/* modificari folosind pointeri */
*(int*)&i = 10000;
q=&l; *q=7;
printf(valorile modificate ale lui i si l\n);
printf(i=%d l=%d\n, i, l);
*(double *) &pi = 3.14159265;
printf(valorea modificata a lui pi\n);
printf(%.10f\n, pi);
*s = 1; *(s+1) = 2;printf(valorea modificata a zonei spre care pointeaza s\n);
printf(s=%s\n, s);
p = s1; *p=1;
printf(valorea modificata a zonei spre care pointeaza s1\n);
printf(s=%s\n, s1);
}
Rezultatele programului:
dimensiunile lui i,j,n,1
2 2 2 2
dimensiunile lui x,s,s1,s2
8 3 3 5
valorile lui I,n,s,s1,s2
i = 10 n = 12 s = sir s1 = abc s2 = ABCDE
Valorile lui j,k,l
j = 1234 k=3 l=3
201
7/29/2019 Programare in C
69/130
Limbajul de programare C
Valorile lui x, pi
x = 1.2345678900 pi=3.1415900000
Valorile modificate ale lui I si l
i = 10000 l=7
valoarea modificata a lui pi
3.1415926000valoarea modificata a zonei spre care pointeaza s
s = 12r
valoarea modificata a zonei spre care pointeaza s1
s1 = 1bc
Observaii:
1) Declaraia constpermite protejarea valorii atribuite unui nume fa de eventualele
ncercri ulterioare de a modifica accidental aceste valori prin simple atribuiri.
2) n cazul n care programatorul dorete s fac o astfel de modificare, ea se poate
realiza, dar nu direct, ci doar indirect, folosind pointerii.De exemplu, dac dorim s modificm valoarea constantei idin exemplu 1 de la 10 la
100, putem realiza acest lucru prin instruciunea urmtoare:
*(int*)&i = 100
Aceasta este posibil deoarece unui nume declarat prin consti se aloc memorie.
Expresia de mai sus este echivalent cu secvena:
int*p;................
p = &i;
*p = 100;
ntr-adevr, &ireprezint adresa zonei alocate numelui i. Atunci (int *)&iconvertete
aceast adres spre un pointer spre ntregi, deci ea are aceeai valoare ca i p dup
instruciunea p = &i; Prin urmare, instruciunea *p = 100; devine echivalent cu
*(int*)&i = 100;
Modificatorul const se folosete frecvent la declaraia parametrilor formali de tip
pointer. O astfel de declaraie are formatul:
Un parametru formal declarat prin construcia:tip*nume_parametru_formal
corespunde unui parametru efectiv a crui valoarea este o adres.
La apel, valoarea parametrului formal devine egal cu aceast adres. Datorit acestui
fapt funcia apelat poate s modifice data aflat la adresa respectiv.
Modificatorul const utilizat la declararea unui astfel de parametru formal interzice
funciei apelate s modifice data de la adresa recepionat la apel de ctre parametrul formal
corespunztor.
202
7/29/2019 Programare in C
70/130
Limbajul de programare C
Acest mecanism este utilizat frecvent n cazul funciilor de tratare a irurilor de
caractere.
Exemple:
1. Funcia strlen din biblioteca standard a limbajului Care prototipul:
unsigned strlen(const char*s);
Ea se apeleaz prin expresii de atribuire de forma:n = strlen(x);
undexeste un pointer spre o zon de memorie n care se afl un ir de caractere.
Funcia strlen determin lungimea irului aflat la adresa recepionat de ctre
parametrul s. Ea nu are voie s modifice irul respectiv i din aceast cauz parametrul s se
declar folosind modificatorul const.
2. Funcia strcpy din biblioteca standard a limbajului Care prototipul:
Char * strcpy (char*dest, const char * sursa);
Aceast funcie copiaz irul aflat la adresa recepionat de parametrul surs n zonade memorie a crei adres este atribuit parametrului dest. Deoarece funcia strcpy nu are voie
s modifice irul de la adresa surs, la destinaia acestui parametru s-a utilizat modificatorul
const. n schimb, funcia schimb coninutul de la adresa dest, unde se copiaz irul i deci
parametrul destnu se mai declar prin modificatorul const.
Funcia strcpy returneaz adresa din dest, adic adresa zonei n care s-a copiat irul.
3. Funcia strcatdin biblioteca standard a limbajului Care prototipul:
char*strcat(char*a, const char*b);
irul spre care pointeaz bse concateneaz la sfritul irului spre care pointeaz a.irul spre care pointeaz nu poate fi modificat de ctre funcia strcat i din aceast cauz
parametrul b este declarat cu modificatorul const.
Funcia returneaz pointerul spre irul rezultat, deci chiar valoarea parametrului a.
4. Funcia strcmp din biblioteca standard a limbajului Care prototipul:
int strcmp (const char *a, const char *b);
Funcia compar irurile spre care pointeaz a i b. Ea nu poate modifica cele dou
iruri i de aceea cei doi parametri au fost declarai prin modificatorul const.
6.10.10. Stiva, exemplu de structur ce folosete pointeri
Prin stiv se nelege o mulime ordonat de elemente la care accesul se realizeaz
conform principiuluiLIFO (LastIn FirstOut).
Cel mai simplu procedeu de implementare a unei stive este pstrarea elementelor ei
ntr-un tablou unidimensional.
n zona de memorie afectat stivei se pot pstra elementele ei unul dup altul. De
asemenea ele se pot scoate din aceast zon n ordine invers pstrrii lor. Astfel, la un
moment dat, se scoate ultimul element pus n stiv i numai acesta.
203
7/29/2019 Programare in C
71/130
7/29/2019 Programare in C
72/130
Limbajul de programare C
Exemplul 1: Se vor defini funciile push, pop i clearpentru o stiv de tip nreg de
maxim 1000 de elemente.
# define MAX 1000
staticintstack[MAX]
static next = 0; /* indicele pentru baza
stivei */voidpush(x) /* pune pe stiva valoarea
lui x */
intx;
{ if(next0) return stack [--next];
else { printf (stiva este vida\n); return 0; }
}
voidclear() /* videaza
stiva */
{ next = 0;
}
Exemplul 2: S se rescrise funciile push, pop i clear folosind pointeri n locul
variabilelor cu indici, considernd un numr maxim de 1000 de elemente.
# define MAX 1000staticintstack[MAX]
staticint*next = stack;
/* pointerul next se initializeaza cu adresa de indice a zonei afectate stivei */
voidpush(intx) /* pune pe stiva valoarea
lui x */
{ if(nextstack) return (*--next);
else { printf (stiva este vida\n); return 0;}
}
voidclear() /* videaza
stiva */
{ next = stack; }
205
7/29/2019 Programare in C
73/130
Limbajul de programare C
6.11. Structuri i tipuri definite de utilizator
n anumite situaii practice se lucreaz cu seturi mari de date. Aceste date pot s fie
toate de acelai tip sau s fie de tipuri diferite. Dac datele sunt de acelai tip ele se pot grupa
n structuri de tip tablou. Dac sunt de tip diferit, spunem despre grupa respectiv de date c
formeaz o structur.
6.11.1. Declaraia de structur
O structur se poate declara n felul urmtor:
struct nume { list de_declarat