| |
Functii
cu parametri
|
Definitia unei functii
|
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:
-
int -
functia este intreaga
-
void -
functia este void
-
float
- functia este reala.
Lista
parametrilor formali cuprinde declaratia parametrilor formali, separati
prin virgula:
| 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:
In
prototip, numele parametrilor formali pot fi omisi, aparand doar tipul
fiecaruia.
Prototipul
implicit este:
Apelul unei functii
|
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:
-
adresa
de revenire din functie
-
valorile
parametrilor formali
-
variabilele
locale.
In cazul
functiilor void fara parametri, apelul se face prin:
| 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
|
Transmiterea
parametrilor se face prin valoare - 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.
|
Parametru
actual
|
Parametru
formal
|
| &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] |
Exemple
|
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
//pozitiv cu numele transmis ca param
double
putere (double baza, int exp); //
calculeaza baza^exp
void
main(void){
int m,n;
double x,y;
m=intreg_poz("m");
n=intreg_poz("n");
if(m==0 && n==0){ //semnalare
eroare 0^0
puts("0^0 imposibil");
return; //
din main
}
printf("valorile lui x,y:"); scanf("%lf%lf",&x,&y);
printf("%lf^%d+%lf^%d+(%lf*%lf)^%d^%d ( cu putere ):%lf\n",
x,m,y,n,x,y,m,n,putere(x,m)+putere(y,n)
+putere(x*y,putere(m,n)));
printf("rezultat ( cu pow ):%lf\n",pow(x,m)+pow(y,n)
+pow(x*y,pow(m,n))); //se
tipareste si rezultatul obtinut
// cu
functia pow de biblioteca, pentru verificare
getche();
}
//
main
int
intreg_poz(char * nume_var){
int aux;
while(printf("%s(>=0):",nume_var),scanf("%d",&aux),aux<0);
return aux;
}
//
intreg_poz
double
putere (double baza, int exp){
int i; float rez;
for(i=rez=1;i<=exp;i++)rez*=baza;
return rez;
}
//
putere |
Folosind functia putere scrieti
programul care citeste N intregi ( N variabil, intre 2 si Max ) si calculeaza
i1^i2^i3^...^iN. Atentie la depasiri! Ce modificari trebuie operate asupra
tipurilor pentru ca rezultatul sa fie corect?
Observatie: intregii vor
fi cititi intr-un tablou de dimensiune Max.
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
int t=x;
x=y;
y=t;
}
void
intersch_ok(int* px,int* py){ //functia
primeste pointerii la
//variabilele de interschimbat
int t=*px;
*px=*py;
*py=t;
}
int
citire(char * nume){
int aux;
printf("%s=",nume);
scanf("%d",&aux);
return aux;
}
void
main(void){
int a,b;
clrscr();
a=citire("a");
b=citire("b");
intersch_er(a,b);
printf("dupa prima functie:a=%d,b=%d\n",a,b);
intersch_ok(&a,&b);
printf("dupa a doua functie:a=%d,b=%d\n",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){
// functia primeste adresa tabloului, numarul de maxim de elemente, adresa
variabilei
// ce va contine numarul de elemente citite si numele tabloului
// primul parametru formal poate fi definit echivalent:
// int t[10] - constanta fara efect, sau
// int t[]
int i;
printf("Tastati elementele tabloului %s (max %d sau terminati cu CTRL/Z):\n",
nume,dm);
for(i=0;i<dm;i++)
if(scanf("%d",&tab[i])==EOF)break;
*dc=i; //
numarul de elemente citite
}
void
tip(int * tab,int dc,char * nume){ //
functia primeste adresa tabloului, numarul de
// elemente citite si numele tabloului
int i;
printf("Elementele tabloului %s\n",nume);
for(i=0;i<dc;i++)
printf("%d ",tab[i]);
putchar('\n');
}
void
main(void){
int t1[2],t2[30],t3[40],d1,d2,d3; //
tablouri si numerele de elemente citite
cit(t1,2,&d1,"t1");
cit(t2,30,&d2,"t2");
cit(t3,40,&d3,"t3");
tip(t1,d1,"t1");
tip(t2,d2,"t2");
tip(t3,d3,"t3");
getche();
} |
Adaugati cate o functie pentru
fiecare din prelucrarile:
-
returneaza valoarea maximului
unui tablou, primit ca parametru
-
primeste un intreg, interpretat
ca indice in tabloul primit ca parametru; functia va aduna la elementul
de la acel indice, toate elementele anterioare, daca indicele este valid,
returnand 1, altfel 0
-
aduna doua tablouri ( pe lungimea
minima dintre dimensiunile lor ) intr-un al treilea; tablourile si dimensiunea
sunt parametri.
4.
Se tiparesc elementele a doua 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
// de linii si coloane initializate
// la parametrul t, a doua dimensiune trebuie neaparat precizata
// t poate fi declarat echivalent int t[dim1][10] - dim1, expr cta
// nu se ia in considerare
int i,j;
printf("Elementele matricii %s:\n",nume);
for(i=0;i<nl;i++){
for (j=0;j<nc;j++)
printf("%d ",t[i][j]);
putchar('\n');
} // for
i
}
void
main(void){
int t1[40][10]={{4,5},{3,4}},t2[50][10]={{9,15,8},{13,99,14}};
tip(t1,2,2,"t1");
tip(t2,2,3,"t2");
getchar();
} |
Adaugati cate o functie pentru
fiecare din prelucrarile:
-
citeste o matrice
-
returneaza suma elementelor
unei matrici
-
insumeaza doua matrici intr-o
a treia
-
inmulteste doua matrici intr-o
a treia.
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; |
Copyright
© 2001-2002. Carmen Holotescu
All
rights reserved. Published by Timsoft
|