Sunteți pe pagina 1din 9

Laborator 6.

Funcții în C


❻ Funcții în C

OBIECTIVELE LABORATORULUI

 Deprinderea modului de programare modular prin declararea și definirea funcțiilor;


 Deprinderea modului de lucru cu fișiere proiect;
 Înțelegerea conceptului de recursivitate prin parcurgerea exemplelor propuse în cadrul
laboratorului și prin dezvoltarea funcțiilor recursive proprii;
 Exersarea noțiunii de subrutină prin rezolvarea unor probleme asemănătoare cu cele
exemplificate în cadrul laboratorului;

1. FUNCȚII ÎN LIMBAJUL C

O funcţie reprezintă o secvenţă de instrucţiuni ce poate fi apelat ă din mai multe puncte ale unui
program, executând prelucrări determinate asupra unor date comunicate în momentul apelului.

1.1 FUNCȚII – declarare, definire, apel

DECLARAREA FUNCȚIILOR
Declarația unei funcții va da numele funcției, tipul datei returnate de aceasta și numărul și tipul
argumentelor care trebuie precizate la apelul funcței. Declaraţia funcţiei este necesară
compilatorului în momentul în care este nevoit să "rezolve" apelul funcţiei. Dacă funcţia a fost
definită înaintea primului său apel atunci declaraţia nu mai este necesară.
Sintaxa generală:

<tip_returnat> <nume_funcție>([<lista_declaratii_parametrii>]);

Exemple de declararea a funcțiilor

int maxim(int a, int b);


void afisare_vector(int n, float v[]);
float media_aritmetica(int, int[]);

Observații:
În momentul declarării nu este necesară cunoaşterea denumirii parametrilor formali ai
funcţiei, aşa că ei pot lipsi (ca nume, dar nu ca și tip).

DEFINIREA FUNCȚIILOR
Corpul funcţiei va apărea în afara funcţiei main și în afara oricărei alte funcţii din program. Dacă
plasăm acest corp de funcţie (definiţia funcţiei) după funcţia main, vom fi nevoiţi să declarăm funcţia
respectivă, declaraţie ce va apărea în faţa primului apel al funcţiei.
Sintaxa generală este:

Ghid practic pentru Programarea Calculatoarelor și Limbaje de Programare  1


Laborator 6. Funcții în C


[<tip_returnat>] <nume_funcție>([<lista_declaratii_parametrii>])
{
[<declaratii_identificatori_locali >]
[<instructiuni>]
[return [<expresie>]; ]
}

unde:

tip_returnat:= int|char|unsigned|float|double|short|long

Exemplu de definire a unei funcții

int maxim(int a, int b)


{
if(a>b)
return a;
else
return b;
}

APELUL FUNCȚIEI

Acesta poate fi utilizat în funcţia main sau în oricare alt ă funcţie din program, prin
specificarea numelui funcţiei şi, între paranteze rotunde, lista parametrilor reali, transmişi funcţiei.
Parametri reali pot fi, în cazul general, expresii de tipul parametrilor formali asociaţi sau expresii de
tipuri convertibile la acele tipuri.
Sintaxa generală:

<nume_funcție>([<lista_parametrii_reali>]);

Exemplu

#include <stdio.h>
#include <stdlib.h>

int main()
{
int x, y;
printf("Dati valori lui x si y: ");
scanf("%d%d", &x, &y);

printf("\nMaximul dintre %d si %d este %d.", x, y, maxim(x,y));


return 0;
}

1.2 Funcții predefinite

Funcțiile predefinite sunt acele funcții care sunt definite în bibliotecile ce însoțesc orice
mediu de programare. Bibliotecile conțin un fișier header (*.h), în care se regăsesc prototipurile
funcțiilor și alte declarații de variabile și fișierul sursă asociat în care regăsim definițiile funcțiilor
propriu-zise. Funcțiile predefinite sunt împărțite în biblioteci în funcție de aplicabilitatea lor. De

Ghid practic pentru Programarea Calculatoarelor și Limbaje de Programare  2


Laborator 6. Funcții în C


exemplu, funcțiile standard se regăsesc în biblioteca stdlib, funcțiile matematice în biblioteca math
etc.
Pentru a utiliza funcțiile predefinite trebuie ca fișierul header asociat bibliotecii să fie inclus
în programul apelant printr-o directivă preprocesor (#include <nume_biblioteca.h>).

Exemplu

#include <stdio.h>
#include <stdlib.h>

int main()
{
char text[50];
int i;

printf("Introduceti un text: ");


gets(text);

for(i=0;i<strlen(text);i++)
text[i] = toupper(text[i]);

printf("\nTextul introdus transformat in majuscule este: %s\n", text);

return 0;
}

1.3 Transmiterea parametrilor


Transmiterea valorilor parametrilor se face conform unor reguli similare celor de la iniţializarea
variabilelor. Astfel, tipul fiecărui parametru actual este comparat cu cel al parametrului formal
corespunzător şi se realizează conversiile implicite de tip:
 float la double;
 char şi short la int, etc.
Alte conversii necesare trebuie realizate prin operator cast.
Instrucţiunile din corpul funcţiei care se referă la parametri formali utilizează copiile valorilor
parametrilor efectivi (valorile stocate de aceştia). Dacă se modifică valoarea unui parametru, de fapt
este afectată doar copia, nu şi parametrul efectiv corespunzător.

Exemplu

#include <stdio.h>
#include <stdlib.h>

// Declaraţia funcţiei putere


double putere( double, int );

int main( void )


{
int p = 2; float f = 3.2f, val;

// Apelul funcţiei putere


val = putere( f-1, 3 );
//... prelucrează "val"
return 0;
}

// definitia/corpul functiei

Ghid practic pentru Programarea Calculatoarelor și Limbaje de Programare  3


Laborator 6. Funcții în C


double putere( double b, int exp )


{
double rez = 1;
for ( ; exp; exp-- )
rez *= b;
return rez;
}

Observații:
1. În cazul exemplului prezentat "f-1, 3" reprezinta parametri reali, iar "double b, int exp"
sunt parametri formali.
În momentul apelului "val = putere(f-1, 3);", cele doua expresii sunt evaluate, iar rezultatele
convertite la double, respectiv int. La pasul următor valorile deja convertite vor fi COPIATE în
parametrii "b", respectiv "exp".
2. În cazul parametrilor de tip ȘIR/MATRICE orice schimbare produsă în interiorul funcţiei va
fi vizibilă şi după revenirea din funcţie. Acest lucru este posibil deoarece, în aceste cazuri, se face
accesul la elementul unui şir pe baza adresei şirului, motiv pentru care accesul se va produce asupra
şirului transmis ca parametru.

Exemple utilizare parametrii de tip ȘIR/MATRICE

#include <stdio.h>
#include <stdlib.h>

// Declararea unei funcţii cu un parametru de tip ŞIR


void functiePSir( int n, int sir[] );
//void functiePSir( int n, int sir[ 100 ] );

// Declararea unei funcţii cu un parametru de tip MATRICE


void functiePMat( int n, int m, int mat[][20] );
//void functiePMat( int n, int m, int mat[10][20])

int main( void )


{
int N = 5, M = 3, sirA[ 100 ], matA[ 10 ][ 20 ];;

// Apelul funcţiei. Transmiterea unui şir ca parametru


functiePSir( N, sirA ); //functiePSir( N, &sirA[0] );
//functiePSir( N/2, &sirA[ N/2 ] );

// Apelul functiei. Transmiterea unei matrici ca parametru


functiePMat( N, M, matA );

return 0;
}

1.4 Organizarea codului în fișiere proiect

Un program scris în limbajul C (sau C++) este compus din unul sau mai multe fişiere sursă (*.c, *.cpp).
Un fişier sursă este un fişier text care conţine codul sursă (în limbajul C) al unui program. Fiecare
fişier sursă conţine una sau mai multe funcţii şi eventual, referinţe către unul sau mai multe fişiere
header (*.h).

Ghid practic pentru Programarea Calculatoarelor și Limbaje de Programare  4


Laborator 6. Funcții în C


2. FUNCȚII CU NUMĂR VARIABIL DE PARAMETRII

Prin intermediul acestui tip de funcţie avem posibilitatea de a transmite un număr variabil de
parametri reali, în momentul apelului funcţiei.
Acest număr de parametru reali poate varia de la un apel la altul, în cadrul aceluia si program.
O funcţie de acest gen va con ţine în lista parametrilor formali si simbolul elipsis (...). Declaraţia va fi
asemănătoare cu cea prezentată în continuare.

DECLARAREA FUNCȚIILOR

Declararea unei astfel de funcţii va arăta astfel:


#include <stdarg.h>
[tip_fct] <id_functie>( [lista_par_fix], ... );

DEFINIREA FUNCȚIILOR
Macrodefiniţiile utilizate în operarea funcţiilor cu număr variabil de argumente sunt:

void va_start( va_list ap, lastfix );


<type> va_arg( va_list ap, <type> );
void va_end ( va_list ap );

Aceste macrouri dau posibilitatea utilizatorului de a accesa argumentele unei funcţii ce nu are un
număr constant (fix) de argumente după cum urmează:
 va_start() - setează variabila ap de tip va_list la primul argument ce este transmis funcţiei;
 va_args() - transformă argumentul curent din lista la tipul type si îl întoarce, după care trece
la următorul argument din listă;
 va_end() - ajută funcţia să efectueze un return normal (să golească stiva înainte de
întoarcere).
Parametrul lastfix al funcţiei va_start() este de fapt numele ultimului parametru fix transmis
funcţiei.

Scheletul unei funcții cu număr variabil de parametrii

Ghid practic pentru Programarea Calculatoarelor și Limbaje de Programare  5


Laborator 6. Funcții în C


void modelFunctie( int a, ... )


{
int x;
/* Tipul de data "va_list" */
va_list va;

/* Macrodefiniţia "va_start()" va iniţializa lista de parametri


suplimentari cu următorul parametru de după ultimul parametru FIX.
*/
va_start( va, a );

/* Macrodefiniţia "va_arg()" va extrage urnătorul parametru de tip


"int" din lista. */
x = va_arg( va, int );

/* Eliberează lista de parametri suplimentari */


va_end( va );

APELUL FUNCȚIEI

Acesta poate fi utilizat în funcţia main sau în oricare alt ă funcţie din program, prin
specificarea numelui funcţiei şi, între paranteze rotunde, lista parametrilor reali, transmişi funcţiei.
Parametri reali pot fi, în cazul general, expresii de tipul parametrilor formali asociaţi sau expresii de
tipuri convertibile la acele tipuri.
Sintaxa generală:

int main( void )


{
int varA;
/* ... */

// apeluri functie
modelFunctie( varA );
modelFunctie( varA. 2, 3, 1, 0 );

/* ... */
return 0;

Exemplu de calcul a sumei unor numere transmise ca și parametrii variabili într-o funcție

#include <stdio.h>
#include <stdarg.h>

int suma( int nr_param, ... )


{
int x, i, s=0;

/* tipul de data "va_list" */


va_list va;

/* iniţializare lista de parametri suplimentari


* incepand cu următorul parametru de după ultimul parametru FIX. –
* nr_param */
va_start( va, nr_param );

Ghid practic pentru Programarea Calculatoarelor și Limbaje de Programare  6


Laborator 6. Funcții în C


/* extragerea fiecarui parametru de tip "int" din lista


* si adunarea lui la variabila 's'. */
for(i=0;i<nr_param;i++)
{
x = va_arg( va, int );
s+=x;
}

/* eliberează lista de parametri suplimentari */


va_end( va );

return s;
}

int main( void )


{
int s1, s2;

// apeluri functie
s1 = suma( 0 );
printf("suma( 0 ) = %d.\n",s1);

s2 = suma( 4, 2, 3, 1, 0 );
printf("suma( 4, 2, 3, 1, 0 ) = %d.\n",s2);

return 0;
}

3. FUNCȚII RECURSIVE

Recursivitatea este o tehnică de programare în care un subprogram se auto-apelează,


eventual cu alte valori pentru parametri reali (de apel). Recursivitatea poate fi directă – în definiția
funcției regăsim un apel al funcției însăși, și indirectă – când în corpul funcției există un apel al altei
funcții ce conține la rândul ei un apel al funcției recursive.
Pentru a evita apelul în cascadă (la infinit) în corpul funcției trebuie să existe o condiție de
oprire, respectiv de continuare.

EXEMPLIFICAREA RECURSIVITĂȚII ÎN PROBLEMA CALCULULUI FACTORIALULUI, n!

Matematic, factorialul este definit printr-o funcție produs (1) sau o relație de recurență (2):

n
n !   k 1 2  3 ... n (1)
k 1

1, daca n  0
n!   (2)
n  (n  1)!, daca n  0

Din relația de recurență (2) putem observa că valoarea lui n! se calculează în funcție de valoarea
lui (n-1)!, deci și pentru (n-1)! se aplică aceiași relație de recurență. În cele ce urmează sunt
prezentate două definiții ale funcției de calcul al factorialului pentru cele 2 relații, (1) și (2),
implementări reprezentând varianta iterativă, respectiv varianta recursivă a funcției factorial.

Ghid practic pentru Programarea Calculatoarelor și Limbaje de Programare  7


Laborator 6. Funcții în C


VARIANTA ITERATIVĂ VARIANTA RECURSIVĂ


n
1, daca n  0
n !   k 1 2  3 ... n n!  
k 1 n  (n  1)!, daca n  0
int fact( int n ) int fact( int n )
{ {
int i, f; if( n == 0 )
return 1; //condiţie de final
for( i = f = 1; i <= n; i++ ) return n * fact( n - 1 ); //apel
f *= i; recursiv

return f; }
}

PROBLEME PROPUSE SPRE REZOLVARE

1. Să se testeze toate exemplele prezentate în lucrarea de laborator.

2. Scrieţi un program ce va realiza diferite operaţii pe şiruri de numere întregi și care să afişeze şi să
implementeze opţiunile următorului meniu:
C. Citire şir de numere.
A. Afişare sir.
S. Afişare sumă.
F. Căutare element în vector.
I. Info autor.
X. Ieşire.

Obs. Pentru implementarea tuturor opțiunilor (exceptând optiunile ’I’ și ’X’) se vor utiliza funcții.

3. Scrieţi un program ce va calcula valorile funcţiei Ackermann. Funcţia Ackermann este


definită pentru argumentele m,n numere naturale prin:

n  1, daca m  0

a(m, n)  a(m  1,1), daca n  0
a(m  1, a(m, n  1)), altfel

4. Scrieţi un program ce va rezolva problema calculului celui mai mare divizor comun dintre
două numere naturale a și b. Aceasta problemă poate fi rezolvată recursiv, conform definiţiei
următoare:

 a, a  b

(a, b)  (a  b, b), a  b
(a, b  a), b  a

5. Scrieți un program care va calcula suma si produsul primelor numere naturale utilizând două
funcții recursive.

6. Scrieti un program care realizeaza calculul recursiv al sumei elementelor unui vector.

Ghid practic pentru Programarea Calculatoarelor și Limbaje de Programare  8


Laborator 6. Funcții în C


7. Să se implementeze o aplicație de tip meniu cu următoarele opțiuni:

C. citirea componentelor sirului


A. afisarea elementelor din sir
S. suma componentelor
P. produsul componentelor
n. numarul componentelor negative
p. produsul componentelor pozitive
m. media aritmetica a elementelor
X. Iesire
Obs. Pentru implementarea tuturor opțiunilor (exceptând optiunea ’X’) se vor utiliza funcții recursive.

3. Scrieţi un program care să afişeze şi să implementeze opţiunile următorului meniu (se vor utiliza
funcţii):
C. Citire matrice.
A. Afişare matrice.
S. Verificare dacă este simetrică sau nu.
F. Căutare element în matrice şi afişarea poziţiilor în care se găseşte elementul (o poziţie = o
pereche de coordonate (x, y)).
O. Afişare contur matrice.
P. Parcurgerea în spirala a matricei se memorează într-un vector, apoi se afişează toate
subşirurile de elemente consecutive. Aceasta opţiune va fi lansata în execuţie numai dacă
matricea este pătratică.
F. Info autor.
X. Ieşire.

Ghid practic pentru Programarea Calculatoarelor și Limbaje de Programare  9