Mai jos se reiau aspectele generale despre
functii, prezentate deja la Functii fara parametri,
detaliindu-se aspectele legate de functiile cu parametri, care returneaza
o valoare.
Functia este un concept important in matematica si programare. In limbajul C prelucrarile sunt organizate ca o ierarhie de apeluri de functii. Orice program trebuie sa contina cel putin o functie, functia main.
Functiile incapsuleaza prelucrari bine precizate si pot fi reutilizate in mai multe programe.
Pentru a putea fi utilizata intr-un program, o functie trebuie sa fie definita ( sau declarata ) si apelata.
Definitia
unei functii are urmatoarea
forma:
| tip_rezultat_returnat
nume_functie (lista_parametri_formali){ /*antetul
functiei*/
definirea variabilelor locale prelucrari /* instructiuni */ } /* intre { } corpul functiei */ |
Functiile nu pot fi definite incuibat ( ca in Pascal ).
Daca tip_rezultat_returnat este:
| lista_parametri_formali=tip_p1 nume_p1, tip_p2 nume_p2, ..., tip_pn nume_pn |
Parametrii formali sunt vizibili doar in corpul functiei care ii defineste. O functie poate deci prelucra variabilele globale, cele locale, precum si parametrii formali.
Pentru reutilizare si pentru a nu modifica accidental variabilele globale, este indicat ca o functie sa nu acceseze variabilele globale.
Daca functia nu returneaza nici un rezultat si
nu primeste parametri, definitia va fi:
| void nume_functie (void)
/*antetul functiei*/
definirea variabilelor locale prelucrari /* instructiuni */ } /* intre { } corpul functiei */ |
O functie void fara parametri poate prelucra variabilele globale si cele locale.
Declaratia unei functii se face
prin precizarea prototipului functiei:
| antet; |
In prototip, numele parametrilor formali pot fi omisi, aparand doar tipul fiecaruia.
Prototipul implicit este:
| int nume_functie(void); |
| nume_functie(lista_parametri_actuali)
/* poate
apare ca operand intr-o expresie, daca functia returneaza un rezultat */ |
La apelul unei functii, se executa corpul sau,
dupa care se revine in functia apelanta, la instructiunea urmatoare apelului.
O functie poate fi apelata, daca in fata apelului
exista definitia sau cel putin declaratia functiei.
Parametrii actuali sunt expresii, care trebuie sa corespunda ca numar si tipuri ( eventual prin conversie implicita ) cu parametrii formali. Parametrii actuali sunt transmisi prin valoare, la apelul functiei ( valorile lor sunt depuse pe stiva ). Modificarea valorii lor de catre functie nu este vizibila in exterior.
La apelul unei functii, pe stiva se creaza o inregistrare de activare, care cuprinde, de jos in sus:
| nume_functie(); //instructiune expresie |
Revenirea dintr-o functie se face la intalnirea instructiunii return, sau la terminarea executiei corpului functiei ( ultimul caz, ca functia sa nu contina instructiunea return, poate apare doar in cazul functiilor void - care nu returneaza nici un rezultat ).
Corpul unei functii poate contine una sau mai multe instructiuni return:
return;
//daca functia e void
return
expresie; //expresia e de acelasi tip cu tip_rezultat ( eventual
prin conversie
//implicita )
Transmiterea parametrilor se face prin valoare, adica valorile parametrilor
actuali sunt depuse pe stiva, la apelul unei functii, fiind prelucrate
ca parametri formali de catre functie; modificarea parametrilor formali
nu afecteaza deci parametrii actuali.
Daca se doreste ca o functie sa modifice valoarea unei variabile, trebuie
sa i se transmita pointerul la variabila
respectiva - vezi programul 2 care interschimba valorile
a doua variabile.
Daca parametrul este un tablou, cum numele este echivalent cu pointerul
la tablou, functia poate modifica valorile elementelor tabloului, primind
adresa lui - vezi programele 3 si 4,
unde apar ca parametri tablouri uni si bidimensionale. A se observa ca
trebuie sa se transmita ca parametri si dimensiunea/dimensiunilor tabloului/matricii.
Daca parametrul este sir de caractere, dimensiunea tabloului de caractere
nu trebuie sa se transmita, sfarsitul sirului fiind indicat de caracterul
terminator '\0' - vezi exemplul 5.
|
|
|
| &nume_variabila | tip_variabila * nume_param |
| nume_tab_unidim // forme
echivalente
&nume_tab_unidim &nume_tab_unidim[0] |
tip_baza * nume_param // forme
echivalente
tip_baza nume_param[] tip_baza nume_param[dim] |
| nume_tab_bidim //forme
echivalente
&nume_tab_bidim &nume_tab_bidim[0] |
tip_baza nume_param[][dim2] //dim2
trebuie sa apara
tip_baza nume_param[dim1][dim2] |
1. Sa se calculeze si sa se afiseze valoarea
expresiei xm+yn+(xy)m^n , x,y,m,n fiind
cititi de la tastatura, astfel incat intregii m,n sa fie pozitivi. Ridicarea
la putere se va realiza de o functie putere
care primeste baza si exponentul ca parametri si returneaza rezultatul.
A se observa faptul ca apelul functiei putere
( analog pow ) apare intr-o expresie si de
asemenea ca parametru actual intr-un apel.
| #include <stdio.h>
#include <math.h> int intreg_poz(char *nume_var); //
citeste cu validare un intreg
void main(void){
m=intreg_poz("m");
printf("%lf^%d+%lf^%d+(%lf*%lf)^%d^%d ( cu
putere ):%lf\n",
} // main int intreg_poz(char * nume_var){
double putere (double baza, int exp){
|
2. Programul de mai jos prezinta o varianta incorecta
si una corecta de interschimbare a doua variabile de catre o functie.
| #include <stdio.h>
#include <conio.h> void intersch_er(int x,int y){ //functia primeste
valorile de interschimbat
void intersch_ok(int* px,int* py){ //functia primeste
pointerii la
int citire(char * nume){
void main(void){
clrscr(); a=citire("a");
intersch_er(a,b);
getche();
|
3. Se citesc si se tiparesc elementele a trei tablouri
de intregi, de dimensiuni diferite. Citirea elementelor unui tablou se
face pana la tastarea lui CTRL/Z sau pana la introducerea numarului maxim
de elemente. A se observa ca aceeasi functie de citire, respectiv tiparire
poate citi/scrie tablouri de dimensiuni diferite, care au insa acelasi
tip de baza. Functiile trebuie sa primeasca insa dimensiunile tablourilor.
| #include <stdio.h>
void cit(int * tab,int
dm,int * dc,char * nume){
void tip(int * tab,int dc,char * nume){ // functia
primeste adresa tabloului, numarul de
void main(void){
cit(t1,2,&d1,"t1");
tip(t1,d1,"t1");
getche();
|
4. Se tiparesc elementele a trei matrici de intregi,
cu acelasi numar de coloane.
| #include <stdio.h>
#include <conio.h> void tip(int t[][10],int
nl, int nc,char *nume){//functia primeste numarul
void main(void){
|
5. Functia intreaga de mai jos transforma minusculele
din sirul primit ca parametru in majuscule si returneaza numarul de modificari
operate. Sunt date doua variante echivalente: in prima accesul la caracterele
sirului se face indexat, la a doua, prin indirectare.
| int prel_sir(char * s){
int i,nr; for(i=nr=0;i<strlen(s);i++) if((c=toupper(s[i]))!=s[i]){ s[i]=c; nr++; } return nr; |
| int prel_sir(char * s){
int i,nr; for(nr=0;*s;s++)//se marcheaza diferentele fata de prima varianta if((c=toupper(*s))!=*s){ *s=c; nr++; } return nr; |