Sunteți pe pagina 1din 8

CURS NR. 11+12.

Funcţii utilizator
11.1. Introducere
Noţiunea de funcţie este foarte importantă în limbajul C, datorită faptului că un program C este compus
în principal din funcţii. Un program scris în C conţine o funcţie principală, numită main(), execuţia
programului fiind asigurată de această funcţie.
Din corpul funcţiei main pot fi apelate alte funcţii care să realizeze anumite acţiuni specifice. Aceste
funcţii apelate pot fi funcţii de bibliotecă sau pot fi funcţii definite de utilizator.
La apelul unei funcţii de bibliotecă trebuie ca înainte de apel să se includă în program (prin intermediul
directivelor preprocesor #include) fişierul antet care conţine prototipul funcţiei. Datorită acestei includeri, în
etapele de compilare şi link-editare funcţia de bibliotecă va fi recunoscută, fişierul antet fiind căutat şi legat la
programul sursă.
Un programator care doreşte să-şi scrie propriile funcţii trebuie să aibă în vedere trei elemente:
definiţiile, prototipul şi apelul funcţiilor.
Noţiunea de funcţie a apărut în contextul modularizării programelor, adică în contextul scrierii
programelor formate din mai multe module, astfel încât fiecare modul să execute o anumită acţiune. Modulele
trebuie să fie coordonate din cadrul unui modul principal.
Avantajele utilizării funcţiilor sunt:
- funcţiile pot fi apelate din diferite părţi ale unui program şi pentru valori diferite ale parametrilor
acestora;
- funcţiile pot fi utilizate şi de alţi programatori;
- funcţiile pot fi utilizate şi în alte programe.

11.2. Definiţia funcţiei


Forma generală a unei funcţii este:
tip nume_funcţie (listă_de_declaraţii_parametrii_formali)
{
Corp
}
unde: tip – poate fi un tip de date predefinit sau un tip definit de utilizator. Acesta reprezintă tipul valorii
returnate de funcţie;
nume_funcţie – reprezintă numele funcţiei, prin intermediul acestuia funcţia este apelată,;
parametrii formali sunt argumentele funcţiei de la definiţia acesteia. Pentru fiecare dintre aceştia
trebuie declarat tipul scriind în cadrul unei liste tipul şi numele parametrilor corespunzători.
{ } – cele două acolade definesc corpul funcţiei, acesta cuprinde în general declaraţii de variabile şi
instrucţiuni.

11.3. Apelul funcţiei


Poate fi făcut în două moduri:
A. Printr-o instrucţiune de apel, sub forma:
nume_funcţie(listă_param_efectivi);
Această formă de apel este specifică funcţiilor care nu returnează valori la revenire. O funcţie nu
returnează valori la revenire dacă tipul din faţa numelui funcţiei este cuvântul cheie void.
Dacă tip lipseşte din faţa numelui funcţiei la definiţie se consideră că ea returnează o valoare de tip int.
Cuvântul cheie void poate fi utilizat şi-n parantezele rotunde de după numele funcţiei în cazul în care
funcţia nu are parametrii.
Lista parametrilor efectivi conţine parametrii de la apelul funcţiei, valorile acestora trebuie să fie
cunoscute în momentul apelului.
Parametrii sunt despărţiţi prin virgulă, între lista parametrilor efectivi de la apel şi lista parametrilor
formali de la declarare trebuie să existe concordanţă de tip, număr şi ordine, altfel va apare eroare la
compilare.
1
Tot printr-o instrucţiune de apel pot fi apelate şi funcţiile care returnează o valoare la revenire. În acest
caz, valoarea returnată de pierde.
Exemplu: scanf(“%d”,&a); Funcţia scanf returnează numărul de câmpuri citite corect.
B. Al doilea mod de apelare a funcţiilor este specific funcţiilor care returnează valori, apelul acestora
realizându-se ca şi operand într-o expresie.
La revenirea din funcţie cu valoarea returnată de aceasta se vor efectua calculele din expresia în care s-a
făcut apelul.
Exemplu: int a, b; a = b – 5 + getch();
Funcţia getch() returnează codul ASCII al caracterului tastat.

11.4. Prototipul funcţiei funcţiei


Se formează scriind prima linie din definiţie urmată de caracterul ;.
tip nume_funcţie (listă_de_declaraţii_parametrii_formali);
Prototipul se mai numeşte şi declaraţia funcţiei deoarece are un rol similar cu cel al declarării
variabilelor. Prin intermediul prototipului o funcţie este declarată înainte de apel, dar dacă definiţia funcţiei
respective a fost plasată în program înaintea apelului funcţiei atunci prototipul nu mai este necesar. Definiţiile
de funcţii pot fi plasate oriunde în program, inaintea funcţiei main sau după aceasta şi în orice ordine.
Apelul unei funcţii poate fi făcut din corpul funcţiei main sau din corpul oricărei alte funcţii, inclusiv o
funcţie se poate apela pe ea însăşi.
Pentru prototipul unei funcţii există şi o formă prescurtată de scriere:
tip nume_funcţie (lista_tipurilor_parametrilor_formali);
Observaţie: între listele parametrilor formali din prototip şi listele parametrilor efectivi de la apel trebuie
să existe corespondenţă de nr., tip şi ordine.
Exemple:
void f(void); – funcţia nu are parametrii şi nu are valori;
void fct(int a, float b); - reprezintă prototipul unei funcţii cu doi parametri: primul de tip int,
al doilea de tip float, funcţia nu returnează valoare.
void fct(int, float); - forma prescurtată.

Program exemplu: Calculul ariei bazei, ariei laterale, ariei totale şi a volumului pentru un cilindru
pentru care se introduc raza bazei şi înălţimea.
#include<stdio.h>
#include<conio.h>
#include<math.h>
void cilindru(void)
{ float raza, inalt, ariab, arial, ariat, volum;
printf("\n Introduceti raza bazei:") scanf("%f",&raza);
printf("\n Introduceti inaltimea:"); scanf("%f",&inalt);
ariab=M_PI*raza*raza;
arial=2*M_PI*raza*inalt;
ariat=2*ariab+arial;
volum=ariab*inalt;
printf("\n Aria bazei: Ab = %5.2f",ariab);
printf("\n Aria laterala: Al = %5.2f",arial);
printf("\n Aria totala: At = %5.2f",ariat);
printf("\n Volumul: V = %5.2f",volum);
}

2
void main(void)
{ clrscr();
printf("\n Calculeaza ariile si volumul unui cilindru:");
cilindru();
getch();
}
Observaţie: Programul conţine o funcţie creată de utilizator (denumită cilindru) cu ajutorul căreia se
citesc datele de intrare (raza bazei şî înălţimea) şi se calculează ariile şi volumul cilindrului. În corpul funcţiei
main se apelează această funcţie.
Variabile locale:
Variabilele declarate în corpul unei funcţii sau în corpul unui bloc se numesc variabile locale. Aceste
variabile sunt “vizibile” numai în interiorul funcţiei sau blocului în care au fost declarate, lor li se alocă
memorie la execuţie, la intrarea în corpul funcţiei sau a blocului, durata lor de viaţă este numai pe pasrcursul
execuţiei corpului sau a blocului şi sunt distruse la ieşirea din corpul funcţiei sau din bloc. Din acest motiv
numele de variabile pot fi utilizate în două funcţii diferite, cu valori şi semnificaţii diferite în cele două funcţii,
fiecăruia i se alocă un spaţiu de memorie separat şi sunt văzute numai în corpul funcţiei în care a fost declarată.
Aceste variabile se mai numesc şi automatice (auto) pentru că aparţin clasei de memorare auto.

11.5. Funcţii care returnează valoare. Instrucţiunea return


În limbajul C o funcţie poate returna o singură valoare sau nici o valoare. Funcţiile care returnează o
valoare au în corpul lor, la definiţie, instrucţiunea return. Această instrucţiune efectuează două acţiuni:
- determină revenirea din corpul funcţiei în funcţia care a făcut apelul;
- returnează funcţiei care a făcut apelul valoarea scrisă după cuvântul cheie return.
Dacă tipul valorii returnate nu coincide cu tipul valorii scris la definiţie şi în prototip la revenirea din
funcţie se face o conversie de tip spre tipul din definiţie (prototip).

Exemplu: Funcţie care citeşte de la tastatură o valoare strict pozitivă şi o returnează funcţiei apelante.
Programul realizează calculul factorialului unui număr întreg, strict pozitiv citit cu ajutorul funcţiei create.

#include<stdio.h>
#include<conio.h>

int citstrpoz(void)
{ int a;
do{ printf(“\n Introduceti un numar:”)
scanf (“%d”,&a);
} while(a<=0);
return a;
}

void main(void)
{ int i,n; long int fact=1; clrscr();
n = citstrpoz(); // citirea valorii lui n
for(i=1;i<=n;i++) // calculul factorialului
fact*=i;
printf(“\n %n! = %ld”,n,fact); // afisarea valorii factorialului
getch();
}

11.6. Funcţia standard exit()


Funcţia standard exit este o funcţie de bibliotecă al cărei prototip este de forma:
void exit (int cod);
3
Funcţia este definită în biblioteca de funcţii stdlib.h sau process.h.
La apelul funcţiei se realizează următoarele:
- se videază zonele tampon ale fişierelor deschise în scriere;
- se închid toate fişierele deschise în cadrul programului;
- se termină execuţia programului.
Prin intermediul parametrului cod se poate preciza dacă execuţia programului se termină la eroare sau
este o terminare normală, fără eroare:
- cod ≠ 0: terminare program la eroare;
- cod = 0: terminare normală a programului;
Funcţia standard exit() se foloseşte când dorim să terminăm programul din puncte diferite, în funcţie de
îndeplinirea unor anumite condiţii.
Program exemplu: Se calculează xy unde x este un real iar y este un întreg cuprins în intervalul [1,100].

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
void eroare(void) // functia eroare
{printf("\n EROARE!!!!! \n Program TERMINAT!!!"); getch(); }

void main(void)
{float x; int y,i; double p=1; clrscr();
printf("\n Introdu valoarea bazei: x = "); scanf("%f",&x); // citirea lui x
// citirea lui y. Se verifica daca s-a introdus un numar intreg, daca NU se intrerupe
// executia programului
printf("\n Introdu valoarea exponentului: y = ");
if( scanf("%d",&y)!=1 )
{ printf("\n Nu ai introdus un numar intreg"); eroare(); exit(1); }
// se verifica daca y apartine intervalului [1, 100]
if(y<1 || y>100)
{printf("\n y nu apartine intervalului [1,100]"); eroare(); exit(1); }
// se calculeaza valoarea xy
for(i=1;i<=y;i++)
p*=x;
// se afiseaza rezultatul
printf("\n %f la puterea %d = %f",x,y,p); getch();
// sfarsit program
exit(0); printf("\n****");
}

11.7. Funcţii cu parametri


Parametri unei funcţii permit transferul de valori de la funcţia care a făcut apelul înspre funcţia apelată
sau invers. În limbajul C, apelul funcţiilor se face prin valoare, adică la apelul funcţiilor sunt transmise valorile
parametrilor efectivi. În alte limbaje (Fortran) apelul funcţiilor se face prin referinţă adică, la apel adresele
parametrilor efectivi sunt transmise parametrilor formali. Limbajul C++ permite ambele apeluri, atât prin
valoare cât şi prin referinţă.
În limbajul C, prin intermediul pointerilor se poate realiza un pseudo apel prin referinţă (se transmit
pointeri ca şi parametri).
La apelul prin valoare transferul datelor se face într-o singură direcţie: dinspre funcţia care a făcut
apelul înspre funcţia apelată. La apelul prin referinţă, transferul datelor se face în ambele direcţii deoarece
transmiţând ca parametru o adresă de memorie, funcţia apelată va cunoaşte acea adresă deci va avea acces la
valoarea conţinută la adresa respectivă din memorie şi va putea modifica acea valoare.
4
Program exemplu: Program care calculează valorile funcţiei y = f(x) = 3x2 + 5x + 7 pentru valori ale
lui x aparţinând intervalului [a, b] parcurs cu pasul h.
#include<stdio.h>
#include<conio.h>
float f(float x)
{ return 3*x*x+5*x+7;}
void main(void)
{ float a,b,h,x,y;
clrscr();
// citirea datelor de intrare (a, b, h)
printf("\n Introduceti a:");scanf("%f",&a);
printf("\n Introduceti b:");scanf(“%f”,&b);
printf("\n Introduceti h:");scanf(“%f”,&h);
// calculul valorilor functiei y = f(x), pentru valori ale lui x din intervalul [a,b] parcurs // cu pasul
h
for(x=a;x<=b;x+=h)
{ y=f(x); // apelul functiei f
printf("\n f( %f ) = %f",x,y);
}
getch();
}

11.8. Parametri tablouri


În cazul în care la apelul unei funcţii printre parametrii efectivi apare un nume de tablou, parametrul
formal corespunzător de la definiţia funcţiei sau din prototip trebuie declarat sub formă de tablou, precizând
tipul, numele tabloului şi între paranteze drepte [ ] limitele superioare ale dimensiunilor tabloului.
Deoarece numele unui tablou este o variabilă aparte care în C are ca valoare adresa de început a
tabloului, scriind la apelul funcţiei un nume de tablou înseamnă că s-a transmis adresa de început a tabloului.
Din această cauză, funcţia apelată având acces la adresa tabloului va putea determina adresa fiecărui element de
tablou şi va putea modifica valorile elementelor tabloului, în plus aceste modificări vor putea fi “văzute” şi de
funcţia care a făcut apelul.
Dacă este cunoscută adresa de început a unui tablou unidimensional se pot determina adresele
elementelor de tablou, fără a trasnmite funcţiei dimensiunile tabloului. Din această cauză în cazul tablourilor
unidimensionale declarate ca parametrii formali ai unei funcţii se admite să nu se specifice limita superioară a
indicelui tabloului. În cazul tablourilor cu două sau mai multe dimensiuni la declararea lor ca parametri formali
ai unei funcţii limita superioară a primului indice paote să lipsească, restul trebuie precizate.
Observaţie: trebuie să existe concordanţă între dimensiunile tablourilor folosiţi ca parametrii efectivi.şi
limitele indicilor tablourilor declarate ca parametri formali.
Exemplu:
float func(float tab[10], int n);
La apel:

float a[10];
int v;

y = func(a, v);

5
Observaţie: Limitele superioare ale tablourilor declarate ca şi parametrii formali pot să lipsească, adică:
float func(float tab[ ], int n);
Program exemplu: Calculul sumei elementelor strict pozitive dintr-un şir de numere reale.
#include<stdio.h>
#include<conio.h>
// functie pt. citirea elementelor sirului
void cit_sir(int n, float a[])
{ int i;
for(i=1;i<=n;i++) {printf("\n a[%d]=",i); scanf("%f",&a[i]); }
}
// functie pt. afisarea elementelor sirului
void tip_sir(int n, float a[ ])
{ int i;
for(i=1;i<=n;i++) printf("%7.2f",a[i]);
}
// functie pt. calculul sumei elem. str. poz. dintr-un sir
float suma_poz(int n, float a[])
{ float s=0;int i;
for(i=1;i<=n;i++) if(a[i]>0) s+=a[i]; return s;
}
void main(void) // functia principala
{ int n; float a[15], s; clrscr();
printf("\n Introduceti numarul de elemente:"); scanf("%d",&n);
cit_sir(n,a); tip_sir(n,a); s = suma_poz(n,a); // apelul functiilor create anterior
printf("\n Suma elem. str. poz. este: s = %7.2f",s);//afisarea sumei calculate anterior
getch();
}

11.9. Variabile declarate la nivel extern


În cazul în care declaraţiile de variabile se plasează în program în afara corpului oricărei funcţii se spune
că declaraţiile au fost făcute la nivel extern. Variabilele respective se mai numesc variabile externe sau globale.
De obicei, declaraţiile variabilelor globale se plasează la începutul programului, înaintea corpului
oricărei funcţii deoarece ele sunt vizibile din punctul în care au ost declarate în jos.
Variabilele declarate la nivel extern vor fi văzute din corpul tuturor funcţiiloe care urmează după
declaraţie de aceea aceste variabile pot servi la transferul de date între diferitele funcţii ale programului.
Dezavantajul variabilelor declarate la nivel extern constă în faptul că deoarece ele sunt văzute de toate funcţiile
din program valorile lor pot fi modificate accidental caz în care rezultatul execuţiei programului este eronat.
Aceste variabile au durata de viaţă pe toată durata execuţiei programului, lor li se alocă memorie la
compilare şi nu la execuţie. În cazul în care nu au primit valori explicite la declarare, ele primesc implicit
valoarea iniţială 0.
Prin folosirea într-un program a variabilelor declarate la nivel extern, transferul de date între funcţiile
programului se poate face prin următoarele modalităţi:
1. transferul de date dinspre funcţia apelantă spre funcţia apelată se poate face prin intermediul
parametrilor sau a variabilelor externe care au o anumită valoare la apelul funcţiilor;
2. transferul de valori de la funcţia apelată la funcţia apelantă se poate realiza prin valoarea
unică returnată de funcţia la revenire sau prin valorile variabilelor xterne modificate în cadrul
funcţiei apelate.

6
Program exemplu nr. 1: Calculul sumei elementelor strict pozitive dintr-un şir de numere reale.
#include<stdio.h>
#include<conio.h>
int n; float a[15], s; // declaratii de variabile globale
void cit_sir() // functie pt. citirea elementelor sirului
{ int i;
for(i=1;i<=n;i++)
{printf("\n a[%d]=",i); scanf("%f",&a[i]);}
}
void tip_sir() // functie pt. afisarea elementelor sirului
{ int i;
for(i=1;i<=n;i++) printf("%7.2f",a[i]);
}
float suma_poz() // functie pt. calculul sumei elem. str. poz. dintr-un sir
{ float s=0;int i;
for(i=1;i<=n;i++) if(a[i]>0) s+=a[i];
return s;
}
void main(void) // functia principala
{ clrscr();
printf("\n Introduceti numarul de elemente:"); scanf("%d",&n);
cit_sir(); tip_sir(); s = suma_poz(); // apelul functiilor create anterior
printf("\n Suma elem. str. poz. este: s = %7.2f",s);//afisarea sumei calculate anterior
getch();
}
Observaţie: din definiţiile funcţiilor au dispărut declaraţiile de variabile. Acestea nu mai sunt necesare
deoarece variabilele n, a[ ] şi s sunt vizibile în toate funcţiile din program.
Program exemplu nr. 2: Determinarea numărului de elemente nule dintr-o matrice dreptunghiulară.

#include<stdio.h>
#include<conio.h>

// citirea matricei
void cit_mat(int m, int n, float mat[][10])
{ int i,j; float c;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
{printf("\n a[%d][%d] = ",i,j);
scanf("%f",&mat[i][j]);
}
}

// afisarea matricei
void tip_mat(int m, int n, float mat[][10])
{ int i,j;
for(i=1;i<=m;i++)
{ printf("\n");
for(j=1;j<=n;j++)
printf("%7.2f",mat[i][j]);
}
}

7
// determinarea nr. de elemente nule
int nrnulemat(int m,int n, float mat[][10])
{ int i,j,nn=0;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
if(mat[i][j]==0)
nn++;
return nn;
}

void main(void)
{ int m,n,nrnule; float mat[10][10];
clrscr();
printf("\n Introduceti m si n:"); scanf("%d %d",&m, &n);

// apelul functiilor create anterior


cit_mat(m,n,mat);
tip_mat(m,n,mat);
nrnule=nrnulemat(m,n,mat);

printf("\n Nr. de elem. nule este = %d",nrnule);

getch();
}

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