Sunteți pe pagina 1din 48

CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

6
6
.
.

FUNCII
6.1. Structura unei funcii 6.6. Suprancrcarea funciilor
6.2. Transferul parametrilor unei funcii 6.7. Clase de memorare
6.3. Funcii cu parametri implicii 6.8. Moduri de alocare a memoriei
6.4. Funcii cu numr variabil de 6.9. Funcii recursive
parametri 6.10. Pointeri ctre funcii
6.5. Funcii predefinite 6.11. ntrebri i probleme

6.1. STRUCTURA UNEI FUNCII
Un program n limbajul C/C++ este un ansamblu de funcii, fiecare dintre acestea efectund o
activitate bine definit. Din punct de vedere conceptual, funcia reprezint o aplicaie definit
pe o mulime D (D=mulimea, domeniul de definiie), cu valori n mulimea C (C=mulimea
de valori, codomeniul), care ndeplinete condiia c oricrui element din D i corespunde un
unic element din C.

Funciile comunic prin argumente: ele primesc ca parametri (argumente) datele de intrare,
efectueaz prelucrrile descrise n corpul funciei asupra acestora i pot returna o valoare
(rezultatul, datele de ieire). Execuia oricrui program ncepe cu funcia principal, numit
main. Funciile pot fi descrise n cadrul aceluiai fiier, sau n fiiere diferite, care sunt
testate i compilate separat, asamblarea lor realizndu-se cu ajutorul linkeditorului de legturi.

O funcie este formata din antet i corp:
<antet_funcie>
{
<corpul_funciei>
}
Sau:
<tip_val_ret> <nume_func>(<lista_declaraiilor_param_ formali>)
{
<declaraii_variabile_locale>
<instruciuni>
[return <valoare>;]
}

Prima linie reprezint antetul funciei, n care se indic: tipul funciei, numele acesteia i lista
declaraiilor parametrilor formali. La fel ca un operand sau o expresie, o funcie are un tip, dat
de tipul valorii returnate de funcie n funcia apelant. Dac funcia nu ntoarce nici o
valoare, n locul tip_val_ret se specific void. Dac tip_val_ret lipsete, se consider,
implicit, c acesta este int. Nume_func este un identificator.
Lista_declaraiilor_param_formali (ncadrat ntre paranteze rotunde) const ntr-o list
(enumerare) care conine tipul i identificatorul fiecrui parametru de intrare, desprite prin
virgul. Tipul unui parametru poate fi oricare, chiar i tipul pointer. Dac lista parametrilor
formali este vid, n antet, dup numele funciei, apar doar parantezele ( ), sau (void).
Autor: Diana tefnescu
85
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Corpul funciei este un bloc, care implementeaz algoritmul de calcul folosit de ctre funcie.
n corpul funciei apar (n orice ordine) declaraii pentru variabilele locale i instruciuni.
Dac funcia ntoarce o valoare, se folosete instruciunea return <valoare>. La execuie,
la ntlnirea acestei instruciuni, se revine n funcia apelant.
6.1.1. DECLARAII I DEFINIII DE FUNCII
n limbajul C/C++ se utilizeaz declaraii i definiii de funcii.
Declaraia const n specificarea antetului funciei i are rolul de a informa compilatorul
asupra tipului, numelui funciei i a listei declaraiilor parametrilor formali (n care se poate
indica doar tipul parametrilor formali, nu i numele acestora). Fiind doar declarate, funciile
pot fi utilizate, corpul acestora urmnd s se specifice anterior. Declaraiile de funcii din care
lipsesc numele parametrilor formali.se numesc prototipuri.
Definiia conine antetul funciei i corpul acesteia. Nu este admis definirea unei funcii n
corpul altei funcii.

O form nvechit a antetului unei funcii este aceea n care se specific n lista parametrilor
formali doar numele acestora, nu i tipul, ceea ce poate conduce la erori.

<tip_val_ret> <nume_func> (<lista_parametrilor_ formali>)
<declararea_parametrilor_formali>
{ <declaraii_variabile_locale>
<instruciuni>
[return <valoare>;]
}
6.1.2. APELUL FUNCIILOR
n cazul n care o funcie nu returneaz nici o valoare, ea poate fi apelat printr-o construcie
urmat de punct i virgul, numit instruciune de apel, de forma:
<nume_funcie> (<lista_parametrilor_efectivi>);
n cazul n care funcia returneaz o valoare, apelul funciei va constitui operandul unei
expresii.

La apelul unei funcii, parametrii efectivi trebuie s corespund cu cei formali, ca ordine i
tip. n momentul apelului unei funcii, se atribuie parametrilor formali valorile parametrilor
efectivi, dup care se execut instruciunile din corpul funciei. La revenirea din funcie,
controlul este redat funciei apelante, i execuia continu cu instruciunea urmtoare (din
funcia apelant) instruciunii de apel.

Parametrii declarai n antetul unei funcii sunt numii formali, pentru a sublinia faptul c ei
nu reprezint valori concrete, ci numai in locul acestora pentru a putea exprima procesul de
calcul realizat prin funcie. Ei se concretizeaz la execuie prin apelurile funciei.
Parametrii folosii la apelul unei funcii sunt parametri reali, efectivi, concrei, iar valorile lor
vor fi atribuite parametrilor formali, la execuie. Utilizarea parametrilor formali la
implementarea funciilor i atribuirea de valori concrete pentru ei, la execuie, reprezint un
prim nivel de abstractizare n programare. Acest mod de programare se numete programare
procedural i realizeaz un proces de abstractizare prin parametri.
Autor: Diana tefnescu
86
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Variabilele declarate n interiorul unei funcii, ct i parametrii formali ai acesteia nu pot fi
accesai dect n interiorul acesteia. Aceste variabile sunt numite variabile locale i nu pot fi
accesate din alte funcii. Domeniul de vizibilitate a unei variabile este poriunea de cod la a
crei execuie variabila respectiv este accesibil. Deci, domeniul de vizibilitate a unei
variabile locale este funcia n care ea a fost definit (vezi i paragraful 6.7.).

Exemplu:
int f1(void)
{ double a,b; int c;
. . .
return c; // a, b, c - variabile locale, vizibile doar n corpul funciei
}
int main()
{ . . . . . . // variabile a i b nu sunt accesibile n main()
return 0;}

Dac n interiorul unei funcii exist instruciuni compuse (blocuri) care conin declaraii de
variabile, aceste variabile nu sunt vizibile n afara blocului.

Exemplu:
int main()
{ int a=1, b=2;
cout << "a=<<a<< b=<<b<< c=<<c\n; // a=1 b=2, c nedeclarat
. . . . . . . .
{ int a=5; b=6; int c=9;
cout << "a=<<a<< b=<<b<<\n; // a=5 b=6 c=9
. . . . . . . .
}
cout << "a=<<a<< b=<<b<< c=<<c\n; // a=1 b=6, c nedeclarat
. . . . . . . . . . . .
}

Exerciiul 1: S se scrie urmtorul program (pentru nelegerea modului de apel al unei
funcii) i s se urmreasc rezultatele execuiei acestuia.
#include <iostream
void f_afis(void)
.h>
{
cout<<Se execut instruciunile din corpul funciei\n;
double a=3, b=9.4; cout<<a<<*<<b<<=<<a*b<<\n;
cout<<Ieire din funcie!\n; }

int main()
{
cout<<Intrare n funcia principal\n;
f_afis( ); //apelul funciei f_afis, printr-o instruciune de apel
cout<<Terminat MAIN!\n; return 0;}

Exerciiul 2: S se scrie un program care citete dou numere i afieaz cel mai mare divizor
comun al acestora, folosind o funcie l calculeaz.
#include <iostream.h>
int cmmdc(int x, int y)
{if (x==0 || y==1 || x==1 || y==0) return 1;
if (x<0) x=-x;
if (y<0) y=-y;
Autor: Diana tefnescu
87
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

while (x != 0){
if ( y > x ) {int z=x; x=y; y=z; }
x-=y; // sau: x%=y;
}
return y;}

int main()
{
int n1,n2; cout<<n1=;cin>>n1; cout<<n2=;cin>>n2;
int diviz=cmmdc(n1,n2);
cout<<Cel mai mare divizor comun al nr-lor:<<n1<< i ;
cout<<n2<< este:<<diviz<<\n;
/* sau:
cout<<Cel mai mare divizor comun al nr-lor:<<n1<< i ;
cout<<n2<< este:<<cmmdc(n1,n2)<<\n;*/ return 0;}

Exerciiul 3: S se calculeze valoarea lui z, tiind c u (real) i m (natural) sunt citite de la
tastatur: z=2 ( 2 (u) + 1, m) + (2 u - 3, m + 1), unde:
2
(x,n)= , sin( ) cos( ) ix ix
i
n
2
1 =

(x)=
2
1
x
e

+ , : R x N R, : R R

#include <iostream.h>
#include <math.h>
double omega(double x, int n)
{ double s=0; int i;
for (i=1; i<=n; i++) s+=sin(i*x)*cos(i*x);
return s; }

double psi( double x)
{ return sqrt( 1 + exp (- pow (x, 2)));}

int main()
{double u, z; int m; cout<<u=; cin>>u; cout<<m=; cin>>m;
z=2*omega(2* psi(u) + 1, m) + omega(2*pow(u,2) - 3, m+1);
cout<<z=<<z<<\n; return 0 ;}

n exemplele anterioare, nainte de apelul funciilor folosite, acestea au fost definite
(antet+corp). S modificm implementarea exerciiului 3, folosind declaraiile funciilor
omega i psi.
Exist ns i cazuri n care definirea unei funcii nu poate fi fcut naintea apelului acesteia
(cazul funciilor care se apeleaz unele pe altele), i atunci, sunt absolut necesare declaraiile
funciilor.

Exerciiu:
#include <iostream.h>
#include <math.h>
double omega(double, int);
// prototipul funciei omega - antet din care lipsesc numele parametrilor formali
double psi(double); // prototipul funciei psi

int main()
{double u, z; int m; cout<<u=; cin>>u; cout<<m=; cin>>m;
z=2*omega(2* psi(u) + 1, m) + omega(2*pow(u,2) - 3, m+1);
cout<<z=<<z<<\n; return 0 ;}
Autor: Diana tefnescu
88
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

double omega(double x, int i) // definiia funciei omega
{ double s=0; int i;
for (i=1; i<=n; i++) s += sin (i*x) * cos (i*x);
return s; }

double psi( double x) // definiia funciei psi
{ return sqrt( 1 + exp (- pow (x, 2))); }

Prototipurile funciilor din biblioteci (predefinite), cum ar fi exemplul funciilor matematice,
se gsesc n headere (de exemplu, math.h). Utilizarea aceszor funcii impune doar includerea
n program a headerului asociat, cu ajutorul directivei preprocesor #include. n plus,
programatorul i poate crea propriile headere, care s conin declaraii de funcii, tipuri
globale, macrodefiniii, etc.

Similar cu declaraia de variabil, domeniul de vizibilitate a unei funcii este:
fiierul surs, dac declaraia funciei apare n afara oricrei funcii (la nivel global);
funcia sau blocul n care apare declaraia.
6.2. TRANSFERUL PARAMETRILOR UNEI FUNCII
S ne reamintim faptul c funciile comunic ntre ele prin argumente (parametri). Transferul
(transmiterea) parametrilor ctre funciile apelate se poate realiza n urmtoarele moduri:
Transfer prin valoare (specific limbajului C);
Transfer prin pointeri;
Transfer prin referin (specific limbajului C++).
6.2.1. TRANFERUL PARAMETRILOR PRIN VALOARE
n toate exemplele anterioare, parametrii - de la funcia apelant ctre funcia apelat - au fost
transmii prin valoare. n momentul apelului unei funcii, se transmit valorile parametrilor
efectivi, reali, care vor fi atribuite parametrilor formali. Deci procedeul de transmitere a
parametrilor prin valoare const n ncrcarea valorii parametrilor efectivi n zona de
memorie a parametrilor formali (n stiv). La apelul unei funcii, parametrii reali trebuie s
corespund - ca ordine i tip - cu cei formali.

Exerciiu: S se scrie urmtorul program (care ilustreaz transmiterea parametrilor prin
valoare) i s se urmreasc rezultatele execuiei acestuia.
void f1(float intr,int nr)// intr, nr - parametri formali
{for (int i=0; i<nr;i++) intr *= 2.0;
cout<<Val. Param. intr=<<intr<<\n;// intr=12
Copiere valoare
intr
data
1.5
1.5
Figura 6.1. Transmiterea
parametrilor prin valoare
}
int main()
{
float data=1.5; f1(data,3);
// apelul funciei f1, cu parametrii efectivi data i 3
cout<<data=<<data<<\n;
// data=1.5 (nemodificat)
}
Autor: Diana tefnescu
89
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Fiecare argument efectiv utilizat la apelul funciei este evaluat, iar valoarea obinut este
atribuit parametrului formal corespunztor. n funcia apelat, parametrul formal reprezint o
copie local a valorii parametrului efectiv. Orice modificare a valorii parametrului formal n
funcia apelat (printr-o operaie din corpul funciei), va determina doar modificarea copiei
locale a parametrului efectiv (figura 6.1.), neinfluennd n nici un mod valoarea parametrului
efectiv corespunztor. Faptul c variabila din programul apelant (parametrul efectiv) i
parametrul formal sunt obiecte distincte, poate constitui un mijloc util de protecie. n
exerciiul anterior, n corpul funciei f1, valoarea parametrului formal intr este modificat
(alterat) prin instruciunea ciclic for, ns valoarea parametrului efectiv (data) din funcia
apelant, rmne nemodificat.
n cazul transmiterii parametrilor prin valoare, parametrii efectivi pot fi chiar expresii.
Acestea sunt evaluate, iar valoarea lor va fi atribuit, la apel, parametrilor formali (vezi
exemplul urmtor).

Exemplu:
double psi(int a, double b)
{if (a > 0) return a*b*2;
else return -a+3*b; }
int main()
{ int x=4; double y=12.6, z;
z=psi ( 3*x+9, y-5) + 28; //parametrii efectivi sunt expresii
cout<<z=<<z<<\n; }

Transferul valorii parametrilor este nsoit de eventuale conversii de tip. Aceste conversii pot
fi realizate automat de compilator, n urma verificrii apelului de funcie, pe baza
informaiilor despre funcie, sau pot fi conversii explicite, specificate de programator, prin
operatorul cast.

Exemplu:
float f1(double, int);
int main()
{
int a, b; float g=f1(a, b); // conversie automat: int a -> double a
float h=f1( (double) a, b); // conversie explicit
}

Limbajul C este numit limbajul apelului prin valoare, deoarece, de fiecare dat cnd o
funcie transmite argumente unei funcii apelate, este transmis, de fapt, o copie a
parametrilor efectivi. n acest mod, dac valoarea parametrilor formali (iniializai cu valorile
parametrilor efectivi) se modific n interiorul funciei apelate, valorile parametrilor efectivi
din funcia apelant nu vor fi afectate.
6.2.2. TRANSFERUL PARAMETRILOR PRIN POINTERI
Exist i situaii n care parametrii transmii unei funcii sunt pointeri (variabile care conin
adrese). n aceste cazuri, parametrii formali ai funciei apelate vor fi iniializai cu valorile
parametrilor efectivi, deci cu valorile unor adrese. Astfel, funcia apelat poate modifica
coninutul locaiilor spre care pointeaz argumentele (pointerii).


Autor: Diana tefnescu
90
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Exerciiu: S se citeasc 2 valori ntregi i s se interschimbe cele dou valori. Se va folosi o
funcie de interschimbare.
#include <iostream.h>
void schimb(int *, int *); //prototipul functiei schimba
int main()
{int x, y, *ptx, *pty; ptx=&x; pty=&y; cout<<x=;cin>>x;
cout<<y=;cin>>y;cout<<x=<<x;cout<<y=<<y<<\n;
cout<<"Adr. lui x:"<<&x<<" Val lui x:"<<x<<'\n';
cout<<"Adr.lui y:"<<&y<<" Val y:"<<y<<'\n';
cout<<"Val. lui ptx:"<<ptx;
cout<<" Cont. locaiei spre care pointeaz ptx:<<*ptx<<'\n';
cout<<"Val. lui pty:"<<pty;
cout<<"Cont. locai
schimba(ptx, pty);
ei spre care pointeaz pty:"<<*pty;
// SAU: schimba(&x, &y);
cout<<"Adr. lui x:"<<&x<<" %x Val lui x: %d\n, &x, x);
cout<<"Adr. y:"<<&y<<" Val lui y:"<<y<<'\n';
cout<<"Val. lui ptx:"<<ptx;
cout<<" Cont. locaiei spre care pointeaz ptx:<<*ptx<<'\n';
cout<<"Val. lui pty:"<<pty;
cout<<" Cont. locaiei spre care pointeaz pty:"<<*pty<<'\n';
}
void schimb( int *p1, int *p2)
{cout<<"Val. lui p1:"<<p1;
cout<<" Cont. locaiei spre care pointeaz p1:"<<*p1<<'\n';
cout<<"Val. lui p2:"<<p2;
cout<<" Cont. locaiei spre care pointeaz p2:"<<*p2<<'\n';
int t = *p1; // int *t ; t=p1;
*p2=*p1; *p1=t;
cout<<"Val. lui p1:"<<p1;
cout<<" Cont. locaiei spre care pointeaz p1:<<*p1<<'\n';
cout<<"Val. lui p2:"<<p2;
cout<<" Cont. locaiei spre care pointeaz p2:"<<*p2<<'\n'; }

Dac parametrii funciei schimb ar fi fost transmii prin valoare, n corpul acesteia s-ar fi
interschimbat copiile parametrilor formali, iar n funcia main modificrile asupra
parametrilor transmii nu s-ar fi pstrat. n figura 6.2. este prezentat mecanismul de
transmitere a parametrilor prin pointeri.

















y x
0x34 0x5A
Parametrii formali p1 i p2, la apelul
funciei schimb, primesc valorile
parametrilor efectivi ptx i pty
( adresele variabilelor x i y). Astfel,
variabilele pointer p1 i ptx,
respectiv p2 i pty pointeaz ctre x
i y. Modificrile asupra valorilor
variabilelor x i y realizate n corpul
funciei schimb, se pstreaz i n
funcia
30 10 10 30
main.
pty
0x34 0x5A
ptx
0x34
p1
0x5A
p2
Figura 6.2. Transmiterea parametrilor unei funcii prin pointeri
Autor: Diana tefnescu
91
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Exerciiu: S se scrie urmtorul program i s se urmreasc rezultatele execuiei acestuia.

#include <iostream.h>
double omega (long *k)
{cout<<"k=", k);
// k conine adr. lui i
cout<<*k=;
cout<<k<<\n;
// *k = 35001
double s=2+(*k)-3;
// s = 35000
cout<<s=<<s<<\n;
0x451

n funcia main

n funcia omega

35001 (apoi 35017)
i
0x451 (adr.lui i)
k
35000
s
35000
w
Figura 6.3. Transferul parametrilor prin pointeri
*k+=17; // *k = 35017
cout<<*k=<<*k;
cout<<\n;
return s; }

int main()
{long i = 35001; double w;
cout<<"i="<<i;cout<<" Adr.lui i:"<<&i<<'\n';
w=omega(&i); cout<<i=<<i<< w=<<w<<\n; }// i = 350017 w = 35000
6.2.2.1. Funcii care returneaz pointeri
nsi valoarea returnat de o funcie poate fi un pointer, aa cum se observ n exemplul
urmtor:

Exemplu:
#include <iostream.h>
double *f (double *w, int k)
{ // w conine adr. de nceput a vectorului a
cout<<"w="<<w<<" *w="<<*w<<'\n'; // w= adr. lui a ;*w = a[0]=10
return w+=k; /*incrementeaza pointerului w cu 2(val. lui k); deci w pointeaz
ctre elementul de indice 2 din vectorul a*/
}

int main()
{double a[10]={10,1,2,3,4,5,6,7,8,9}; int i=2;
cout<<"Adr. lui a este:"<<a;
double *pa=a; // double *pa; pa=a;
cout<<"pa="<<pa<<'\n';// pointerul pa conine adresa de nceput a tabloului a
// a[i] = * (a + i)
// &a[i] = a + i
pa=f(a,i); cout<<"pa="<<pa<<" *pa="<<*pa<<'\n';
// pa conine adr. lui a[2], adica adr. a + 2 * sizeof(double);
*pa=1000;
cout<<"pa="<<pa<<"*pa="<<*pa<<'\n';//pa=0x *pa=1000
for (int j=0; j<10; j++)
cout<<"a["<<j<<"]="<<*(a+j)<<'\t';
// a[0]=10 a[1]=1 a[2]=1000 a[3]=3 a[4]=4 a[5]=5 a[6]=6 a[7]=7 a[8]=8 a[9]=9
}
Autor: Diana tefnescu
92
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

6.2.3. TRANSFERUL PARAMETRILOR PRIN REFERIN
6.2.3.1. Variabile referin
n limbajul C++ variabila referin reprezint un sinonim (alt nume) al altei variabile. n
exemplul urmtor definim variabila br, variabil referin ctre variabila b. Variabilele b i
br se gsesc, n memorie, la aceeai adres (pentru variabila referin br nu se aloc spaiu de
memorie) i sunt variabile sinonime. Aa cum se observ din exemplu, n orice expresie,
nlocuirea variabilei b cu br (sau invers) nu va modifica valoarea expresiei.

Exemplu:
c
b, br 7 12
12
Figura 6.4. Variabilele referin b, br
#include <stdio.h>
#include <iostream.h>
int main()
{
int b,c;
int &br=b; //br referin la variabila b
br=7;
cout<<"b="<<b<<'\n'; //b=7
cout<<"br="<<br<<'\n'; //br=7
cout<<"Adr. br este:"<<&br; //Adr. br este:0xfff4
printf("Adr. b este:"<<&b<<'\n'; //Adr. b este:0xfff4
b=12; cout<<"br="<<br<<'\n'; //br=12
cout<<"b="<<b<<'\n'; //b=12
c=br; cout<<"c="<<c<<'\n'; //c=12
}

n limbajul C++, se face diferen ntre variabilele pointer (au ca valoare o adres) i cele
referin (nume diferite pentru aceeai zon de memorie).

Exemplu:
int a=100, b=1000, *pa=&a, &ra=a; pa=&b;
//pa variabil pointer, ra referin, sinonim al variabilei a

Pentru variabilele ntregi a, b i pointerul pa se aloc spaiu de memorie, n timp ce pentru
pentru variabila referin ra nu se aloc spatiu n memorie (ra este un alt nume dat variabilei
a). Valoarea pointerului pa poate fi modificat (pa = &b, deci noua valoare a lui pa este
adresa variabilei b), n timp ce referinta ra rmne permanent asociat variabilei a, neputnd
fi modificat.
6.2.3.2. Parametrii transmii prin referin
n limbajul C++, parametrii unei funcii pot fi variabile referin. n acest mod de transmitere
a parametrilor, unui parametru formal i se poate asocia (atribui) chiar obiectul
parametrului efectiv. Astfel, parametrul efectiv poate fi modificat direct prin operaiile din
corpul funciei apelate (vezi exemplul urmtor i figura 6.5., care ilustreaz modul de
transmitere a parametrilor funciei f: primul parametru este transmis prin valoare, al doilea -
prin referin).

Autor: Diana tefnescu
93
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Exemplu:
#include <iostream.h>
#include <stdio.h>
void f(int, int &);
int main()
{int count = 7, index = 12;
printf("Val.inainte apel f:count=%3d index=%3d\n", count, index);
f(count, index);
printf("Val. dupa apel f:count=%3d index=%3d\n", count, index);
}

void f(int in1, int &in2)
{ in1 = in1 + 100;
in2 = in2 + 100;
printf("In corp f: %3d %3d\n", in1, in2);}
in1
Copiere valoare
count
index, in2
7 12 112
7 107
Figura 6.5.
//Rezultatele execuiei
// Val.inainte apel f: count= 7 index= 12
// In corp f: 107 112
// Val. dupa apel f: count= 7 index=112

Exemplul clasic pentru explicarea apelului prin referin este cel al funciei de permutare
(interschimbare) a dou variabile.

Modul de implementare a funciei de interschimbare n care acesteia i se transmit parametrii
prin valoare (ca n exemplul urmtor, funcia schimb) este inadecvat, deoarece modificarea
parametrilor formali (interschimbarea acestora) nu va determina i modificarea celor efectivi.

Fie funcia schimb definit astfel:
Parametri funciei schimb sunt transmii
prin valoare: parametrilor formali x, y li se
atribuie (la apel) valorile parametrilor
efectivi a, b. Funcia schimb permut
valorile parametrilor formali x i y, dar
permutarea nu are efect asupra parametrilor
efectivi a i b.
void schimb (double x, double y)
{ double t=x; x=y; y=t; }

int main()
{ double a=4.7, b=9.7;
. . . . . . . . . . .
schimb(a, b); // apel funcie
. . . . . . . . . . . }


Pentru ca funcia de interschimbare s poat permuta valorile parametrilor efectivi, n
limbajul C/C++ parametrii formali trebuie s fie pointeri ctre valorile care trebuie
interschimbate:


void pschimb(double *x, double *y)
Se atribuie pointerilor x i y (parametrii
formali) valorile pointerilor pa, pb
(parametrii efectivi), deci adresele
variabilelor a i b. Funcia pschimb
permut valorile spre care pointeaz
pointerii x i y, deci valorile lui a i b
(figura 6.5).
{ int t=*x; *x=*y; *y=t; }

int main()
{ double a=4.7, b=9.7;
. . . . . . . . . . .
pschimb(&a, &b); // apel funcie
/* SAU:
double *pa, *pb;
pa=&a; pb=&b;
pschimb(pa, pb);*/
. . . . . . . . . . . }
Autor: Diana tefnescu
94
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii












pschimb
&a
&b
4.7
*x
*y
aux
main
a
b
4.7 9.7
9.7 4.7
Figura 6.6. Transferul parametrilor
prin pointeri
rschimb
4.7 aux
main
x,a
y;b
4.7 9.7
9.7 4.7
Figura 6.7. Transferul parametrilor
prin referin
n limbajul C++ funcia de interschimbare poate fi implementat astfel nct parametrii
formali s fie variabile referine.

void rschimb(double &x, double &y)
{ int t=x; x=y; y=t; }

int main()
{ double a=4.7, b=9.7;
. . . . . . . . . . . . . . .
rschimb(a, b); // apel funcie
. . . . . . . . . . . . . . . }

n acest caz, x i y sunt sinonime cu a i b (nume diferite pentru aceleai grupuri de locaii de
memorie). Interschimbarea valorilor variabilelor de x i y nseamn, de fapt, chiar
interschimbarea valorilor variabilelor a i b (fig. 6.7.).

Comparnd funciile pschimb i rschimb, se observ c diferena dintre ele const n modul
de declarare a parametrilor formali. n cazul funciei pschimb parametrii formali sunt
pointeri (de tip double*), iar la apelul funciei, acetia primesc valorile parametrilor efectivi,
deci adresele variabilelor care vor fi interschimbate. n cazul funciei rschimb, parametrii
formali sunt referine ctre date de tip double, refer aceleai locaii de memorie (sunt
sinonime pentru) parametrii efectivi, deci interschimbarea din corpul funciei acioneaz chiar
asupra parametrilor efectivi.

Comparnd cele trei moduri de transmitere a parametrilor ctre o funcie, se poate observa:
1. La apelul prin valoare transferul datelor este unidirecional, adic valorile se transfer
numai de la funcia apelant ctre cea apelat. La apelul prin referin transferul datelor
este bidirecional, deoarece o modificare a parametrilor formali determin modificarea
parametrilor efectivi, care sunt sinonime (au nume diferite, dar refer aceleai locaii de
memorie).
2. La transmiterea parametrilor prin valoare, ca parametrii efectivi pot apare expresii sau
nume de variabile. La transmiterea parametrilor prin referin, ca parametri efectivi nu pot
apare expresii, ci doar nume de variabile. La transmiterea parametrilor prin pointeri, ca
parametri efectivi pot apare expresii de pointeri.
3. Transmiterea parametrilor unei funcii prin referin este specific limbajului C++.
4. Limbajul C este numit limbajul apelului prin valoare. Apelul poate deveni, ns, apel prin
referin n cazul variabilelor simple, folosind pointeri, sau aa cum vom vedea n
paragraful 6.4., n cazul n care parametru efectiv este un tablou.
5. n limbajul C++ se poate alege, pentru fiecare parametru, tipul de apel: prin valoare sau
prin referin, aa cum ilustreaz exemplele urmtoare.
Autor: Diana tefnescu
95
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Exerciiul 1: S se scrie urmtorul program i s se urmreasc rezultatele execuiei acestuia.
#include <iostream.h>
#include <stdio.h>

double func(int a, double b, double *c, double &d)
{cout<<"*********************** func *****************\n";
cout<<"a="<<a<<" b="<<b; //a=7 (a=t prin val); b=21 (b=u prin val)
cout<<" c="<<c<<" *c="<<*c<<'\n';// c=ffe(c=w=&u) *c=21
cout<<" d="<<d; //d=17
cout<<"Adr d="<<&d<<'\n'; //Adr d=ffe6 (adr d=adr v)
a+=2; cout<<"a="<<a<<'\n'; //a=9
d=2*a+b; cout<<"d="<<d<<'\n'; //d=39
*c=500;cout<<" c="<<c<<" *c="<<*c<<'\n'; // c=ffe(c=w=&u) *c=500
cout<<"*********************** func *****************\n";
return b+(*c); }

int main()
{cout<<"\n\n \n MAIN MAIN";
int t=7;double u=12, v=17, *w, z; cout<<"u="<<u<<'\n'; //u=12
w=&u;*w=21;cout<<"t="<<t<<" u="<<u<<" v="<<v;
//t=7 u=21 v=17
*w=21;cout<<" *w="<<*w<<" u="<<u<<'\n'; //*w=21 u=21
printf("w=%x Adr. u=%x\n",w,&u); //w=ffee Adr. u=ffee
printf("v=%f Adr v=%x\n",v,&v); //v=17.000000 Adr v=ffe6
z=func(t,u,w, v);
cout<<"t="<<t<<"u="<<u<<"v="<<v; //t=7 u=500 v=39 (v=d)
cout<<" *w="<<*w<<" z="<<z<<'\n'; //*w=500 w=ffee z=521
printf(" w=%x\n",w);}

Exemplul ilustreaz urmtoarele probleme:
La apelul funciei func, parametrii t i u sunt transmii prin valoare, deci valorile lor vor fi
atribuite parametrilor formali a i b. Orice modificare a parametrilor formali a i b, n funcia
func, nu va avea efect asupra parametrilor efectivi t i u. Al treilea parametru formal al
funciei func este pointer, deci c este de tip double * (pointer ctre double), sau *c este de
tip double.
La apelul funciei, valoarea pointerului w (adresa lui u : w=&u) este atribuit pointerului c.
Deci pointerii w i c conin aceeai adres, pointnd ctre un real. Dac s-ar modifica valoarea
spre care pointeaz c n func (vezi instruciunile din comentariu *c=500), aceast
modificare ar fi reflectat i n funcia apelant, deoarece pointerul w are acelai coninut ca i
pointerul c, deci pointeaz ctre aceeai locaie de memorie. Parametrul formal d se transmite
prin referin, deci, d i v sunt sinonime (memorate la aceeai adres). Modificarea valorii
variabilei d n func nseamn, de fapt, modificarea variabilei d (parametrul efectiv din
main).

Exerciiul 2: S se scrie urmtorul program (care ilustreaz legtura dintre pointeri i
vectori) i s se urmreasc rezultatele execuiei acestuia.
#include <iostream.h>
#include <stdio.h>
double omega(long &k)
{printf("Adr k=%x Val k=%ld\n",&k,k); //Adr k=0xfff2 Val k=200001
double s=2+k-3;cout<<"s="<<s<<'\n'; //s=200000
k+=17;printf("Adr.k=%xVal.k=%ld\n",&k,k);//Adr.k=0xfff2 Val.k=200018
return s; }
Autor: Diana tefnescu
96
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

int main()
{long a=200001;
printf("Adr a=%x Val a=%ld\n",&a,a); //Adr a=0xfff2 Val a=200001
double w=omega(a); cout<<"w="<<w<<'\n'; //s=200000
}

Aa cum s-a prezentat n paragrafele 2.5.3.2. i 5.6., modificatorii sunt cuvinte cheie utilizai
n declaraii sau definiii de variabile sau funcii. Modificatorul const poate apare n:
Declaraia unei variabile (precede tipul variabilei) restricionnd modificarea valorii datei;
La declararea variabilelor pointeri definind pointeri constani ctre date neconstante,
pointeri neconstani ctre date constante i pointeri constani ctre date constante.
n lista declaraiilor parametrilor formali ai unei funcii, conducnd la imposibilitatea de
a modifica valoarea parametrului respectiv n corpul funciei, ca n exemplul urmtor:

Exerciiul 3:
#include <iostream.h>
#include <stdio.h>
int func(const int &a)
{printf("Adr a=%x Val a=%d\n",&a,a);int b=2*a+1;
//modificarea valorii parametrului a nu este permis
cout<<"b="<<b<<'\n';return b;}
int main()
{const int c=33;int u;printf("Adr c=%x Val c=%d\n",&c,c);
u=func(c);cout<<"u="<<u<<'\n'; }
6.2.3.3. Funcii care returneaz referine
nsi valoarea returnat de o funcie poate fi o referin, aa cum ilustreaz exemplul
urmtor:

Exemplu:
#include <iostream.h>
#include <stdio.h>

double &func (double &a, double b)
{ printf("n funcie:\n");
printf("Val a=%f Adr a=%x\n", a, &a); //Val a=1.200000 Adr a=0xfffe
cout<<"b="<<b<<'\n'; //b=2.200000
a=2*b+1; printf(" Dup atrib: val a=%f Adr a=%x\n", a, &a);
//Dupa atrib: val a=5.40 Adr a=0xfffe
return a;
}

int main()
{double c=1.2;cout<<"***************MAIN****************\n";
printf("Val c=%f Adr c=%x\n",c, &c); //Val c=1.200000 Adr c=0xfffe
double d; printf("Adr. d=%x\n", &d); //Adr. d=0xffe6
d=func(c,2.2);
printf("Val d=%f Adr d=%x\n", d, &d); //Val d=5.400000 Adr d=0xffe6
}
Autor: Diana tefnescu
97
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

6.2.4. TABLOURI CA PARAMETRI
n limbajul C, cazul parametrilor tablou constituie o excepie de la regula transferului
parametrilor prin valoare. O variabil (structurat) tablou are ca valoare adresa de nceput a
tabloului (este un pointer constant).

Exerciiu: S se afle elementul minim dintr-un vector de maxim 10 elemente. Se vor scrie
dou funcii: de citire a elementelor vectorului i de aflare a elementului minim:
#include <iostream.h>
int min_tab(int a[], int nr_elem)
{int elm=a[0];
for (int ind=0; ind<nr_elem; ind++)
if (elm>=a[ind]) elm=a[ind];
return elm;
}

void citireVector(int b[], int nr_el)
{ for (int ind=0; ind<nr_el; ind++){
cout<<"Elem "<<ind+1<<"="; cin>>b[ind];}
}

int main()
{
int a[10]; int i,j,
citireVector(a,n);
n; cout<<"n="; cin>>n;
int min=min_tab(a,n); cout<<"Elem. min:"<<min<<'\n'; }

Aceleeai problem poate fi implementat folosind aritmetica pointerilor:

#include <iostream.h>
void citireVector(int *b, int nr_el)
{ for (int ind=0; ind<nr_el; ind++){
cout<<"Elem "<<ind+1<<"="; cin>>*(b+ind);}
}

int min_tab(int *a, int nr_elem)
{int elm=*a;
for (int ind=0; ind<nr_elem; ind++)
if ( elm>=*(a+ind) ) elm=*(a+ind);
return elm;
}

int main()
{
int a[10]; int i,j,n; cout<<"n="; cin>>n;
citireVector(a, n);
int min=min_tab(a,n);
cout<<"Elem. min:"<<min<<'\n';
}

n exemplul anterior au fost implementate funciile min_tab, care calculeaz i returneaz
valoarea elementului minim dintr-un tablou unidimensional (vector) de ntregi i
citireVector, care citete valorile elementelor vectorului. Ambelor funcii li se transmite
ca parametru, tabloul unidimensional (vectorul).
Autor: Diana tefnescu
98
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Din exemplele anterioare se poate observa:
1. Prototipul funciei min_tab poate fi unul dintre:
int min_tab(int a[], int nr_elem);
int min_tab(int *a, int nr_elem);
2. Echivalene:
int *a int a[]
a[i] *(a+i)
&a[i] a+i
3. Apelul funciilor:
citireVector(a,n);
int min=min_tab(a,n);
4. Pentru tablourile unidimensionale, la apel, se transmit numele tabloului sau pointerul care
are ca valoare adresa de nceput a zonei de memorie rezervate pentru tablou i numrul
de elemente (nr_elem).

Exerciiu: S se scrie urmtorul program i s se urmreasc rezultatele execuiei acestuia.
#include <iostream.h>
#include <stdio.h>
double omega(int j, double x, double t[], double *w)
{double s; cout<<"n funcia omega:";
cout<<"j="<<j<<" t[j]="<<t[j]<<" t[j+1]="<<t[j+1]<<'\n';
//j=2 (=i din main) t[j]=-3.21 t[j+1]=7.44
cout<<"j="<<j<<" w[j]="<<w[j]<<" w[j+1]="<<w[j+1]<<'\n';
//j=2 (=i din main) w[j]=-21.16 w[j+1]=92.2
t[j]=100; *(t+j+1)=200; w[j]=300; *(w+j+1)=400;
cout<<"Dup atribuiri:\n";
cout<<"j="<<j<<" t[j]="<< t[j]<<" t[j+1]="<<t[j+1]<<'\n';
//Dup atribuiri: j=2 t[j]=100 t[j+1]=200
cout<<"j="<<j<<" w[j]="<<w[j]<<" w[j+1]="<<w[j+1]<<'\n';
//j=2 w[j]=300 w[j+1]=400
int i=2*j+1; x=x+2.29*i; s=x+2*t[0]-w[1];
cout<<"i="<<i<<" x="<<x<<" s="<<s<<'\n';
//i=5 x=1.123+2.29*5 s=x+2*1.32-(-15.34) i=5 x=12.573 s=30.553
return s;}

void switch1(double *x, double *y)
{double t=*x; *x=*y; *y=t;}
void switch2(double &x, double &y)
{double t; t=x;x=y;y=t;}
int main()
{double a=123, b=456, u=1.123;
int i=2;
double r[]={1.32, 2.15, -3.21, 7.44, -15.8};
double q[]={12.26, -15.34, -21.16, 92.2, 71.6};
cout<<"i="<<i<<" u="<<u<<'\n';//i=2 u=1.123
double y=omega(i,u,r,q);getch();
cout<<"i="<<i<<" u="<<u<<'\n';
//i=2 u=1.123
cout<<"omega(i,u,r,q)=y="<<y<<'\n';//omega(i,u,r,q)=y=30.553
cout<<"r[i]="<<r[i]<<" r[i+1]="<<r[i+1];
cout<<" q[i]="<<q[i]<<" q[i+1]="<<q[i]<<'\n';
//r[i]=100 r[i+1]=200 q[i]=300 q[i+1]=400
cout<<"a="<<a<<" b="<<b<<'\n'; //a=123 b=456
switch1(&a,&b);
cout<<"Rez.intersch.a="<<a<<" b="<<b<<'\n';//Rez.intersch.a=456 b=123
Autor: Diana tefnescu
99
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

switch2(a,b);
cout<<"Rez.intersch.a="<<a<<" b="<<b<<'\n';//Rez.intersch.a=123 b=456
cout<<"r[i]="<<r[i]<<" r[i+1]="<<r[i+1]<<'\n';//r[i]=100 r[i+1]=200
switch1(r+i,r+i+1);
cout<<"Rez. intersch. r[i]="<<r[i]<<" r[i+1]="<<r[i+1]<<'\n';
// Rez.intersch. r[i]=200 r[i+1]=100
switch2(r[i],r[i+1]);
//switch2(*(r+i),*(r+i+1));
cout<<"Rez. intersch. r[i]="<<r[i]<<" r[i+1]="<<r[i+1]<<'\n';
// Rez.intersch. r[i]=100 r[i+1]=200
}

n exemplul anterior, parametrii formali i i x din funcia omega sunt transmii prin valoare;
parametrii t i w sunt parametri tablou, transmii prin referin (referin i pointeri). n
funcia switch1 parametrii sunt transmii prin pointeri. n funcia switch2 parametrii sunt
transmii prin referin.

Pentru tablourile multidimensionale, pentru ca elementele tabloului s poat fi referite n
funcie, compilatorul trebuie informat asupra modului de organizare a tabloului.
Pentru tablourile bidimensionale (vectori de vectori), poate fi omis doar precizarea
numrului de linii, deoarece pentru a adresa elementul a[i][j], compilatorul utilizeaz
relaia: &mat[i][j]=&mat+(i* N+j)*sizeof(tip), n care N reprezint numrul de
coloane, iar tip reprezint tipul tabloului.

Exerciiu: Fie o matrice de maxim 10 linii i 10 coloane, ale crei elemente se introduc de la
tastatur. S se implementeze dou funcii care afieaz matricea i calculeaz elementul
minim din matrice.

#include <iostream.h>
int min_tab(int a[][10], int nr_lin, int nr_col)
{int elm=a[0][0];
for (int il=0; il<nr_lin; il++)
for (int ic=0; ic<nr_col; ic++)
if (elm>=a[il][ic]) elm=a[il][ic];
return elm; }

void afisare(int a[][10], int nr_lin, int nr_col)
{
for (int i=0; i<nr_lin; i++)
{for (int j=0; j<nr_col; j++) cout<<a[i][j]<<'\t';
cout<<'\n';
}
}

int main()
{int mat[10][10];int i, j, M, N;cout<<"Nr. linii:"; cin>>M;
cout<<"Nr. coloane:"; cin>>N;
for (i=0; i<M; i++)
for (j=0; j<N; j++)
{ cout<<"mat["<<i<<","<<j<<"]="; cin>>mat[i][j];}
afisare(mat, M, N);
int min=min_tab(mat, M, N);
cout<<"Elem. min:"<<min<<'\n';
}
Autor: Diana tefnescu
100
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

6.2.5. TRANSFERUL PARAMETRILOR CTRE FUNCIA main
n unele situaii este necesar transmiterea unor informaii (opiuni, date iniiale, etc) ctre un
program la lansarea n execuie a acestuia, ceea ce implic transmiterea unor parametri ctre
funcia main. Pentru a putea transmite parametrii (n vederea prelucrrii ulterioare a acestora),
trebuie inclus headerul stdarg.h, iar prototipul funciei main are forma:
main (int argc, char *argv[ ], char *env[ ])

Funcia main poate returna o valoare ntreag: n antetul funciei se specific la tipul valorii
returnate int, sau nu se specific nimic (implicit, tipul este int), iar n corpul funciei apare
instruciunea return valoare_intreag;. Numrul returnat este transferat sistemului de operare
(programul apelant) i poate fi tratat ca un cod de eroare sau de succes al ncheierii execuiei
programului. Dac funcia main nu returneaz nici o valoare, n antetul su, la tipul valorii
returnate, se specific void.

Dac nu se lucreaz cu un mediu de programare integrat, argumentele transmise ctre
funcia main trebuie editate (specificate) n linia de comand prin care se lanseaz n execuie
programul respectiv. Linia de comand tastat la lansarea n execuie a programului este
format din grupuri de caractere delimitate de spaiu sau tab. Fiecare grup este memorat ntr-
un ir de caractere. Dac se lucreaz cu un mediu integrat (de exemplu, BorlandC), selecia
comanzii Arguments din meniul Run determin afiarea unei casete de dialog n care
utilizatorul poate introduce argumentele care vor fi transmise funciei main.

Semnificaia parametrilor (argc, argv i env) din antet este:
Adresele de nceput ale acestor iruri de caractere sunt memorate n tabloul de pointeri
argv[], n ordinea n care apar n linia de comand (argv[0] memoreaz adresa irului
care constituie numele programului, argv[1] - adresa primului argument, etc.).
Parametrul ntreg argc memoreaz numrul de elemente din tabloul argv (argc>=1).
Parametrul env[] este un tablou de pointeri ctre iruri de caractere care pot specifica
parametri ai sistemului de operare.

Exerciiul 1: S se implementeze un program care afieaz argumentele transmise ctre
funcia main.
#include <iostream.h>
#include <stdarg.h>
int main(int argc, char *argv[], char *env[])
{cout<<"Nume program:"<<argv[0]<<'\n';
//argv[0] contine numele programului
if(argc==1)
cout<<"Lipsa argumente!\n";
else
for (int i=1; i<argc; i++)
cout<<"Argumentul "<<i<<":"<<argv[i]<<'\n';
}

Exerciiul 2: S se implementeze un program care, la lansarea n execuie, primete ca
parametrii o ntrebare format din mai multe cuvinte. Ultimul cuvnt din ntrebare este un
grup de caractere, care vor fi cutate, pe rnd, n componena celorlalte cuvinte din ntrebare.
ntrebarea (cu excepia ultimului cuvnt) va fi afiat pe ecran. n situaia n care unul din
caracterele din acest ultim cuvnt este ntlnit n cadrul celorlalte cuvinte, programul
Autor: Diana tefnescu
101
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

returneaz o valoare ntreag care indic poziia caracterului n ultimul cuvnt. De exemplu,
dac se transmite ca parametru ctre funcia main ntrebarea "Ce mai faci? AFC", rezultatul
este: afiarea ntrebrii "Ce mai faci?"; la ntlnirea caracterului A, se returneaz valoarea 1;
n condiiile n care caracterul A nu ar fi fost ntlnit, ar fi fost cutat urmtorul caracter (F
din AFC), iar la ntlnirea acestuia, s-ar fi returnat valoarea 2, etc.; n condiiile n care
caracterul F nu ar fi fost ntlnit, ar fi fost cutat urmtorul caracter (C din AFC), iar la
ntlnirea acestuia, s-ar fi returnat valoarea 3, etc.; dac nici unul din caracterele componente
ale cuvntului AFC nu ar fi fost coninut n ntrebare, s-ar fi returnat codul 0.

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

main(int argc,char *argv[])
{int index, c, code; char next_char, *point;
if (argc < 3) /* testarea prezenei argumentelor n linia de comand*/
{ printf("Intrebare!!!!\n");return 0; }
argc--;
for(index = 1;index < argc;index++)
printf("%s ",argv[index]); /*afiarea cuv. 2, 3, , n-1 (fr cel care
conine caract. de comparare) din ntrebare */
c = getch(); printf("%c\n",c);
if (islower(c)) c = toupper(c);
point = argv[argc]; code = 0; index = 0;
do { next_char = *(point + index);
if (islower(next_char)) next_char = toupper(next_char);
if(next_char == c) code = index + 1;
index++;
} while (*(point + index)); /* NULL */
return code; /* returnarea codului de eroare */ }
6.3. FUNCII CU PARAMETRI IMPLICII
Spre deosebire de limbajul C, n limbajul C++ se pot face iniializri ale parametrilor formali.
Parametrii formali iniializai se numesc parametri implicii.
<tip_ret> <nume_fc>(<list_par_form_nein> <par_init>=<val1>[,...] );

De exemplu, antetul funciei cmmdc (care calculeaz i returneaz cel mai mare divizor
comun al numerelor ntregi primite ca argumente) poate avea urmtoarea form:
int cmmdc(int x, int y = 1);
Parametrul formal y este iniializat cu valoarea 1 i este parametru implicit. La apelul
funciilor cu parametri implicii, unui parametru implicit, poate s-i corespund sau nu, un
parametru efectiv. Dac la apel nu i corespunde un parametru efectiv, atunci parametrul
formal va primi valoarea prin care a fost iniializat (valoarea implicit). Dac la apel i
corespunde un parametru efectiv, parametrul formal va fi iniializat cu valoarea acestuia,
negijndu-se astfel valoarea implicit a parametrului formal. n exemplul anterior, la apelul:
int div=cmmdc(9);
x va lua valoarea 9, iar y va lua valoarea 1 (implicit).
Dac n lista declaraiilor parametrilor formali ai unei funcii exist i parametri implicii i
parametri neiniializai, parametrii implicii trebuie s ocupe ultimele poziii n list, nefiind
permis intercalarea acestora printre parametrii neiniializai.
Autor: Diana tefnescu
102
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Exerciiu: S se scrie urmtorul program care calculeaz volumul unui paralelipiped, cu
ajutorul unei funcii cu parametrii implicii. S se urmareasc rezultatele execuiei.
#include <iostream.h>
#include <stdio.h>
int calcul_volum(int lung, int lat = 2, int inalt = 3);
//prototipul funciei cu parametrii implicii
int main()
{int x = 10, y = 12, z = 15;
cout<<"Volum paralelipiped " << calcul_volum(x, y, z) << "\n";
//Lung= 10 Lat= 12 Inalt= 15 Volum paralelipiped 1800
cout << "Volum paralelipiped " << calcul_volum(x, y) << "\n";
//Lung= 10 Lat= 12 Inalt= 3 Volum paralelipiped 360
cout << "Volum paralelipiped " << calcul_volum(x) << "\n";
//Lung= 10 Lat= 2 Inalt= 3 Volum paralelipiped 60
cout << "Volum paralelipiped ";
cout << calcul_volum(x, 7) << "\n";
//Volum paralelipiped Lung= 10 Lat= 7 Inalt= 5 210
cout << "Volum paralelipiped ";
cout << calcul_volum(5, 5, 5) << "\n";
//Volum paralelipiped Lung= 5 Lat= 5 Inalt= 5 125
}
int calcul_volum(int lung, int lat, int inalt)
{printf("Lung=%4d Lat=%4d Inalt=%4d ", lung, lat, inalt);
return lung * lat * inalt;}
6.4. FUNCII CU NUMR VARIABIL DE PARAMETRI
n limbajele C i C++ se pot defini funcii cu un numr variabil de parametri. Parametrii care
trebuie s fie prezeni la orice apel al funciei se numesc parametri fici, ceilali se numesc
parametri variabili. n antetul unei funcii cu numr variabil de parametri, parametrii fici
ocup primele poziii din list, iar prezena parametrilor variabili se indic prin trei puncte
care se scriu dup ultimul parametru fix al funciei:
<tip_val_ret> <nume_f>(<lista-decl_p_form_ficsi>, . . . );

Exemplu: Fie antetul funciei numite vrf:
void vrf (int n, double a, . . . );
Funcia vrf are doi parametri fici (n i a) i parametri variabili, pentru care nu se
precizeaz numrul i tipul, care difer de la un apel al funciei la altul.

Funciile predefinite cu numr variabil de parametri sunt, de obicei, funcii de bibliotec (ex:
printf, scanf). Pentru a-i defini propriile funcii cu numr variabil de parametri,
utilizatorul trebuie s foloseasc macrouri speciale, care permit accesul la parametrii variabili
i se gsesc n headerul stdarg.h, aa cum ilustreaz exemplul urmtor:

Exemplu:
#include <iostream.h>
#include <stdarg.h>
void afisare(int, ...);//prototip functie cu nr. variabil de parametri
int main()
{int i = 5;int pv_unu = 1, pv_doi = 2;
afisare(pv_unu, i); /* Param.fix=1 Parametrii variabili sunt 5 */
afisare(3,i,i+pv_doi,i+pv_unu);/*Param.fix=3 Parametrii var. sunt 5 7 6 */
Autor: Diana tefnescu
103
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

afisare(pv_doi, 70, 300); /* Param.fix=2 Parametrii variabili sunt 70 300 */ }

void afisare(int nr, ...)
{va_list param_pt;
cout<<"Param.fix="<<nr<<'\n';
va_start(param_pt,nr); // Apel macro setup
cout << "Parametrii variabili sunt ";
for (int i = 0 ; i < nr ; i++)
cout << va_arg(param_pt,int) << " "; // Extragere parametru
cout << "\n";
va_end(param_pt); /* Inchidere macro*/ }
6.5. FUNCII PREDEFINITE
Orice mediu de programare este prevzut cu una sau mai multe biblioteci de funcii
predefinite. Orice bibliotec este format din:
fiierele header (conine prototipurile funciilor, declaraiile de variabile);
biblioteca (arhiva) propriu-zis (conine definiii de funcii).

Pentru ca funciile predefinite s poat fi utilizate ntr-un program, fiierele header n care se
gsesc prototipurile acestora trebuie incluse printr-o directiv preprocesor (exemplu
#include <stdio.h>). Deasemenea, utilizatorul i poate crea propriile headere. Pentru a
putea utiliza funciile din headerele proprii, utilizatorul trebuie s includ aceste headere n
programul apelant (exemplu #include "my_header.h").

Pentru funciile predefinite, au fost create fiiere header orientate pe anumite numite tipuri de
aplicaii. De exemplu, funciile matematice se gsesc n headerul <math.h>. Headerul
<stdlib.h> conine funcii standard, headerul <values.h> definete o serie de constante
simbolice (exemplu MAXINT, MAXLONG) care reprezint, n principal, valorile maxime i
minime ale diferitelor tipuri de date, etc.
6.5.1. FUNCII MATEMATICE (headerul <math.h>)
Funcii aritmetice

Valori absolute
int abs(int x);
Returneaz un ntreg care reprezint valoarea absolut a argumentului.
long int labs(long int x);
Analog cu abs, cu deosebirea c argumentul i valoarea returnat sunt de tip long int.
double fabs(double x);
Returneaz un real care reprezint valoarea absolut a argumentului real.

Funcii de rotunjire
double floor(double x);
Returneaz un real care reprezint cel mai apropiat numr, fr zecimale, mai mic sau
egal cu x (rotunjire prin lips).
double ceil(double x);
Returneaz un real care reprezint cel mai apropiat numr, fr zecimale, mai mare sau
egal cu x (rotunjire prin adaos).
Autor: Diana tefnescu
104
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Funcii trigonometrice
double sin(double x);
Returneaz valoarea lui sin(x), unde x este dat n radiani; valoarea real returnat se afl
n intervalul [-1, 1].
double cos(double x);
Returneaz valoarea lui cos(x), unde x este dat n radiani. Numrul real returnat se afl
n intervalul [-1, 1].
double tan(double x);
Returneaz valoarea lui tg(x), unde x este dat n radiani.

Funcii trigonometrice inverse
double asin(double x);
Returneaz valoarea lui arcsin(x), unde x se afl n intervalul [-1, 1]. Numrul real
returnat (n radiani) se afl n intervalul [-pi/2, pi/2].
double acos(double x);
Returneaz valoarea lui arccos(x), unde x se afl n intervalul [-1, 1]. Numrul real
returnat se afl n intervalul [0, pi].
double atan(double x);
Returneaz valoarea lui arctg(x), unde x este dat n radiani. Numrul real returnat se
afl n intervalul [0, pi].
double atan2(double y, double x);
Returneaz valoarea lui tg(y/x), cu excepia faptului c semnele argumentelor x i y
permit stabilirea cadranului i x poate fi zero. Valoarea returnat se afl n intervalul [-
pi,pi]. Dac x i y sunt coordonatele unui punct n plan, funcia returneaz valoarea
unghiului format de dreapta care unete originea axelor carteziene cu punctul, fa de
axa absciselor. Funcia folosete, deasemenea, la transformarea coordonatelor cartezine
n coordonate polare.

Funcii exponeniale i logaritmice
double exp(double x);
long double exp(long double x);
Returneaz valoarea e .
x
double log(double x);
Returneaz logaritmul natural al argumentului ( ln(x) ).
double log10(double x);
Returneaz logaritmul zecimal al argumentului (lg (x) ).
double pow(double baza, double exponent);
Returneaz un real care reprezint rezultatul ridicrii bazei la exponent ( baza ).
onent exp
double sqrt(double x);
Returneaz rdcina ptrat a argumentului

x .
double hypot(double x, double y);
Funcia distanei euclidiene - returneaz
2 2
y x + , deci lungimea ipotenuzei unui
triunghi dreptunghic, sau distana punctului P(x, y) fa de origine.

Funcii de generare a numerelor aleatoare
int rand(void) <stdlib.h>
Genereaz un numr aleator n intervalul [0, RAND_MAX].


Autor: Diana tefnescu
105
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

6.5.2. FUNCII DE CLASIFICARE (TESTARE) A CARACTERELOR
Toate aceste funcii (headerul <ctype.h>) primesc ca argument un caracter i returneaz un
numr ntreg care este pozitiv dac argumentul ndeplinete o anumit condiie, sau valoarea
zero dac argumentul nu ndeplinete condiia.
int isalnum(int c);
Returneaz valoare ntreag pozitiv daca argumentul este liter sau cifr. Echivalent
cu: isalpha(c)||isdigit(c)
int isalpha(int c);
Testeaz dac argumentul este liter mare sau mic. Echivalent cu isupper(c)||
islower(c).
int iscntrl(int c);
Testeaz dac argumentul este caracter de control (neimprimabil).
int isdigit(int c);
Testeaz dac argumentul este cifr.
int isxdigit(int c);
Testeaz dac argumentul este cifr hexagesimal (0-9, a-f, A-F).
int islower(int c);
Testeaz dac argumentul este liter mic.
int isupper(int c);
Testeaz dac argumentul este liter mare.
int ispunct(int c);
Testeaz dac argumentul este caracter de punctuaie (imprimabil, nu liter sau spaiu).
int isspace(int c);
Testeaz dac argumentul este spaiu alb (' ', '\n', '\t', '\v', '\r')
int isprint(int c);
Testeaz dac argumentul este caracter imprimabil, inclusiv blancul.
6.5.3. FUNCII DE CONVERSIE A CARACTERELOR (prototip n <ctype.h>)
int tolower(int c);
Funcia transform caracterul primit ca argument din liter mare, n liter mic i
returneaz codul ASCII al literei mici. Dac argumentul nu este liter mare, codul
returnat este chiar codul argumentului.
int toupper(int c);
Funcia transform caracterul primit ca argument din liter mic, n liter mare i
returneaz codul acesteia. Dac argumentul nu este liter mic, codul returnat este chiar
codul argumentului.
6.5.4. FUNCII DE CONVERSIE DIN IR N NUMR (prototip n <stdlib.h>)
long int atol(const char *npr);
Funcia convertete irul transmis ca argument (spre care pointeaz npr) ntr-un numr
cu semn, care este returnat ca o valoare de tipul long int. irul poate conine caracterele
'+' sau '-'. Se consider c numrul este n baza 10 i funcia nu semnalizeaz
eventualele erori de depire care pot apare la conversia din ir n numr.
int atoi(const char *sir);
Converteste irul spre care pointeaza argumentul ntr-un numr ntreg.
double atof(const char *sir);
Funcia converteste irul transmis ca argument ntr-un numr real cu semn (returneaz
valoare de tipul double). n secvena de cifre din ir poate apare litera 'e' sau 'E'
Autor: Diana tefnescu
106
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

(exponentul), urmat de caracterul '+' sau '-' i o alt secven de cifre. Funcia nu
semnaleaz eventualele erori de depire care pot apare.
6.5.5. FUNCII DE TERMINARE A UNUI PROCES (PROGRAM) ( <process.h>)
void exit(int status);
Termin execuia unui program. Codul returnat de terminarea corect este memorat n
constanta simbolic EXIT_SUCCES, iar codul de eroare - n EXIT_FAILURE.
void abort();
Termin forat execuia unui program.
int system(const char *comanda); prototip n <system.h>
Permite execuia unei comenzi DOS, specificate prin irul de caractere transmis ca
parametru.
6.5.6. FUNCII DE INTRARE/IEIRE (prototip n <stdio.h>)
Streamurile (fluxurile de date) implicite sunt: stdin (fiierul, dispozitivul standard de
intrare), stdout (fiierul, dispozitivul standard de ieire), stderr (fiier standard pentru
erori), stdprn (fiier standard pentru imprimant) i stdaux (dispozitivul auxiliar
standard). De cte ori este executat un program, streamurile implicite sunt deschise automat
de ctre sistem. n headerul <stdio.h> sunt definite i constantele NULL (definit ca 0) i
EOF (sfrit de fiier, definit ca -1, CTRL/Z).

int getchar(void);
Citete un caracter (cu ecou) din fiierul standard de intrare (tastatur).
int putchar(int c);
Afieaz caracterul primit ca argument n fiierul standard de ieire (monitor).
char *gets(char *sir);
Citete un ir de caractere din fiierul standard de intrare (pn la primul blank ntlnit
sau linie nou). Returneaz pointerul ctre irul citit.
int puts(const char *sir);
Afieaz irul argument n fiierul standard de ieire i adaug terminatorul de ir.
Returneaz codul ultimului caracter al irului (cel care precede NULL) sau -1 la eroare.
int printf(const char *format, ... );
Funcia scrie n fiierul standard de ieire (pe monitor) datele, ntr-un anumit format.
Funcia returneaz numrul de octei (caractere) afiai, sau 1 n cazul unei erori.
1. Parametrul fix al funciei conine:
Succesiuni de caractere afiate ca atare
Exemplu:
printf("\n Buna ziua!\n\n); // afiare: Buna ziua!
Specificatori de format care definesc conversiile care vor fi realizate asupra
datelor de ieire, din formatul intern, n cel extren (de afiare).
2. Parametrii variabili ai funciei sunt expresii. Valorile obinute n urma evalurii
acestora sunt afiate corespunztor specificatorilor de format care apar n
parametrul fix. De obicei, parametrul fix conine att specificatori de format, ct i
alte caractere. Numrul i tipul parametrilor variabili trebuie s corespund
specificatorului de format.

Forma general a specificatorului de format (parametrul fix) este:
% [-|c|][<sir_cifre_eventual_punct_zecimal>] <una_sau_doua_lit>
Autor: Diana tefnescu
107
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

- Implicit, datele se cadreaz (aliniaz) la dreapta cmpului n care se scriu. Prezena
caracterului determin cadrarea la stnga.
irul de cifre definete dimensiunea cmpului n care se scrie data. Dac scrierea datei
necesit un cmp de lungime mai mare, lungimea indicat n specificator este ignorat.
Dac scrierea datei necesit un cmp de lungime mai mic, data se va scrie n cmp,
cadrat la dreapta sau la stnga (dac apare semnul - ), completndu-se restul cmpului
cu caracterele nesemnificative implicite, adica spaii. irul de cifre aflate dupa punct
definesc precizia (numarul de zecimale cu care este afiat un numar real - implicit sunt
afiate 6 zecimale).
Literele definesc tipul conversiei (din formatul intern n cel extern) aplicat datei afiate:
c Afieaz un caracter
s Afieaz un ir de caractere
d Afieaz date ntregi; cele negative sunt precedate de semnul -.
o Afieaz date de tip int sau unsigned int n octal.
x sau X - Afieaz date de tip int sau unsigned int n hexagesimal.
fAfieaz date de tip float sau double n forma:
parte_ntreag.parte_fract
e sau E-Afieaz date de tip float sau double n forma:
parte_ntreag.parte_fractionar exponent
Exponentul ncepe cu e sau E i definete o putere a lui zece care nmulit cu restul
numrului d valoarea real a acestuia.
g sau GAfieaz o dat real fie ca n cazul specificatorului terminat cu f, fie ca n
cazul specificatorului terminat cu e. Criteriul de afisare se alege automat, astfel nct
afiarea s ocupe un numr minim de poziii n cmpul de afiare.
l Precede una din literele d, o, x, X, u. La afiare se fac conversii din tipul long sau
unsigned long.
L Precede una din literele f, e, E, g, G. La afiare se fac conversii din tipul long
double.

int scanf(const char *format, ... );
Funcia citete din fiierul standard de intrare (tastatura) valorile unor variabile, le
convertete din format extern n cel intern (conform specificatorului de format) i le
memoreaz la adresele specificate. Funcia returneaz numrul cmpurilor citite corect.
1. Parametrul fix al funciei conine:
Specificatorii de format care definesc conversiile aplicate datelor de intrare, din
formatul extern, n cel intren (n care sunt memorate). Specificatorii de format sunt
asemntori celor folosii de funcia printf: c, s, d, o, x sau X, u, f, l, L.
2. Parametrii variabili - list de adrese ale variabilelor care vor fi citite, deci n
aceast list, numele unei variabile simple va fi precedat de operatorul adres &.

int sprintf(char *sir_cu_format, const char *format, ... );
Funcia permite scrierea unor date, conform unui anumit format, n irul transmis ca
prim argument. Returneaz numrul de octei (caractere) scrise n ir, sau 1 la eroare.

int sscanf(char *sir_cu_format, const char *format, ... );
Funcia extrage valori din irul transmis ca prim argument i le depune n memorie, la
adresele specificate. Returneaz numrul cmpurilor citite corect.


Autor: Diana tefnescu
108
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Exerciiul 1: S se scrie urmtorul program (care ilustreaz modalitile de folosire a
funciilor predefinite) i s se urmreasc rezultatele execuiei acestuia.

#include <iostream.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <stdio.h>
#include <conio.h>
int main()
{ int x=-34;int a=abs(x);cout<<"a="<<a<<'\n';long int y=-
566666;
cout<<"labs(y)="<<labs(y)<<"fabs(-45.67)="<<fabs(-45.67)<<'\n';
cout<<"fabs(45.67)="<<fabs(45.67)<<'\n';
cout<<floor(78.99)<<'\n'; cout<<floor(78.45)<<'\n'; //78 78
cout<<floor(-78.45)<<'\n'; cout<<ceil(78.99)<<'\n'; //-79 79
cout<<ceil(78.45)<<'\n'; cout<<ceil(-78.45)<<'\n'; //79 -78
cout<<isalpha('8')<<'\n'; cout<<isalpha('f')<<'\n'; /*0 val dif.de
zero */ cout<<"Apasa tasta."; getch();
cout<<isalpha('%')<<'\n'; cout<<tolower('D')<<'\n';//0 100 (cod 'd')
cout<<toupper('a')<<'\n'; //65 (codul caracterului 'A')
char s1[]="-56.234 h mk";cout<<atol(s1)<<'\n'; //-56
cout<<atoi(s1)<<'\n'; cout<<atof(s1)<<'\n'; //-56 -56.234
cout<<atof("45E+3 n")<<'\n'; //45000
cout<<"EXECUTIA COMENZII DOS DIR\n";int cod_ret=system("dir");
cout<<"Val. cod retur="<<cod_ret<<'\n';
int c;cout<<"Astept car:";c=getchar();//Presupunem caracter introdus: e
cout<<"Caracterul citit este:"<<putchar(c);//Caracterul citit este: 101
// 101=codul carcterului e
cout<<'\n';puts(s1);cout<<'\n';printf("Afisarea unui mesaj\n");
int intreg=-45;
printf("VALOAREA VARIABILEI INTREG ESTE:%d\n", intreg);
printf("VALOAREA VARIABILEI INTREG ESTE:%10d\n", intreg);
printf("VALOAREA VARIABILEI INTREG ESTE:%-10d\n", intreg);
double real=2.45; cout<<"Apasa tasta."; getch();
printf("VALOAREA VARIABILEI real ESTE:%f\n", real);
printf("VALOAREA VARIABILEI real ESTE:%10.3f\n", real);
printf("VALOAREA VARIABILEI real ESTE:%10.5f\n", real);
printf("VALOAREA VARIABILEI real ESTE:%e\n", real);
printf("VAL.VAR.real:%f si\neste mem. la adr%x\n",real,&real );
printf("astept sir:");scanf("%s",s1);
printf("Sir citit:%s\n", s1);
char sir_f[100], C; cout<<"Apasa tasta."; getch();
sprintf(sir_f,"Codul caracterului %c este:%d",C, (int)C);
puts(sir_f);
/* se citeste cate un caracter de la tastatura, pana la intalnirea caracterului 'X' si se
afiseaza fiecare caracter citit */
char cc;
do { puts("Caracter=");
cc = getchar(); /* citire caracter */
putchar(cc); /* afisare caracter citit */
} while (cc != 'X');
cout<<"Apasa tasta."; getch();
}
Autor: Diana tefnescu
109
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Exerciiul 2: S se scrie urmtorul program (care ilustreaz modalitile de folosire a
funciilor predefinite) i s se urmreasc rezultatele execuiei acestuia.

#include <stdio.h>
#include <conio.h>
int main()
{ int a,b,c; char *format1;
format1 = "\n %04X %s %04X = %04X";
char *format2 = "\n %c%04X = %04X";
a = 0x0FF0; b = 0xFF00;
printf(" OPERATII LOGICE LA NIVEL DE BIT.\n\n");
c = a << 4; printf(format1,a,"<<",4,c);
printf(" Deplas stanga cu 4 sau cu o cifra hexa.");
c = a >> 4; printf(format1,a,">>",4,c);
printf(" Deplas dreapta cu 4 sau cu o cifra hexa.");
printf(" Right shift 4 bits or one hex digit.");
c = a & b; printf(format1,a,"&",b,c);
printf(" SI ");
c = a | b; printf(format1,a,"|",b,c);printf(" SAU ");
c = a ^ b; printf(format1,a,"^",b,c);
printf(" SAU EXCLUSIV (XOR).");
c = ~a; printf(format2,'~',a,c);
printf(" NOT .");
c = -a; printf(format2,'-',a,c);
printf(" Complement aritmetic in hexa.");
printf("\n");getch();}

Exerciiul 3: S se scrie urmtorul program (care ilustreaz modalitile de folosire a
funciilor predefinite) i s se urmreasc rezultatele execuiei acestuia.

#include <stdio.h>
#include <conio.h>
int main()
{ int n[5]={100,101,102,103,104}, rez[5], index;char linie[80];
sprintf(linie,"Vct:%d %d %d %d %d\n",n[0],n[1],n[2],n[3],n[4]);
printf("%s",linie); }

Exerciiul 4: S se scrie un program care pentru un numr natural, n, citit de la tastatur,
determin numrul k, k<n, astfel nct k are numrul maxim de divizori primi, diferii.

#include<iostream.h>
#include<conio.h>
#include<math.h>
int prim(int x)
{for(int i=2;i<=sqrt(x);i++)
if(!(x%i)) return 0;
return 1;}
int main()
{long k=1, n; cout<<"Introduceti valoarea lui n"; cin>>n;
for(int i=2;i<=n/2;i++)
if(prim(i) && (k*i)<n) k*=i;
cout<<"Numarul mai mic dect "<<n;
cout<<" cu cei mai multi divizori primi este "<< k<<'\n';
getch(); }
Autor: Diana tefnescu
110
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Exerciiul 5: S se rearanjeze elementele unei matrici de ntregi astfel nct s fie ordonate
cresctor att pe linii, ct i pe coloane.

#include<iostream.h>
#include<conio.h>
#include<stdio.h>
void citire(int a[][10], int m, int n)
{for(int i=0;i<m;i++)
for(int j=0;j<n;j++){
cout<<"a["<<i<<","<<j<<"]=";cin>>a[i][j];}
}
void afisare(int a[][10], int m, int n)
{for(int i=0;i<m;i++)
{ cout<<'\n';
for(int j=0;j<n;j++) cout<<'\t'<<a[i][j]; }
}
void ord(int a[][10], int m, int n, int dir, int k)
{int i,j,x;
if(dir==1)
{for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(a[k][i]>a[k][j]){x=a[k][i];a[k][i]=a[k][j];a[k][j]=x;}
}
else if(dir==2)
{for(i=0;i<m-1;i++)
for(j=i+1;j<m;j++)
if(a[i][k]>a[j][k]){x=a[i][k];a[i][k]=a[j][k];a[j][k]=x;}
}
}
int main()
{int A[10][10],n,m; int i,j;cout<<"Nr. linii="; cin>>m;
cout<<"Nr. coloane="; cin>>n;
citire(A,m,n);cout<<"Matricea initiala:\n";afisare(A,m,n);
for(i=0;i<m;i++) ord(A,m,n,1,i);
for(j=0;j<n;j++) ord(A,m,n,2,j);
cout<<"Matricea obtinuta:\n";afisare(A,m,n);getch();}

Exerciiul 6: S se scrie un program care descompune un numr natural, n, citit de la
tastatur, ntr-un produs de factori primi, sub forma:
n=factor1^puterea1*factor2^puterea2*

#include<math.h>
#include<stdio.h>
#include<iostream.h>
#include<conio.h>
int prim(int k)
{for(int i=2;i<=sqrt(k);i++)
if(k%i==0) return 0;
return 1; }
int main()
{long n,d=2,k;
cout<<"Dati n: ";cin>>n; cout<<n<<"=";
do { k=0;
while(n%d==0) { n/=d; k++; }
if(k!=0) cout<<d<<"^"<<k<<"*";
do d++; while(prim(d)==0);
}while(n!=1);
cout<<"\b \b"; }
Autor: Diana tefnescu
111
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Exerciiul 7: S se scrie un program care citete un numr natural, n, scris cu cifre arabe i l
afieaz folosind cifrele romane.

#include<iostream.h>
#include<string.h>
#include<conio.h>
#include<stdlib.h>
const char *rom="IVXLCDMP"; char sir[20];
void transforma(char n, int r)
{int i,j,x;char ret[4]="";r=2*r;x=(int)n-(int)'0';
if(x>=1&&x<=3)
{ for(i=1;i<=x;i++)
ret[i-1]=rom[r];
ret[i-1]='\x0'; }
else if(x==4)
{ ret[0]=rom[r];
ret[1]=rom[r+1];
ret[2]='\x0'; }
else if(x>5&&x<9)
{ ret[0]=rom[r+1];
for(i=6;i<=x;i++)
ret[i-5]=rom[r];
ret[i-5]='\x0'; }
else if(x==9)
{ ret[0]=rom[r];
ret[1]=rom[r+2];
ret[2]='\x0'; }
strcat(sir,ret); }

int main()
{ unsigned int n;char nr[4];
cout<<"Dati numar scris cu cifre arabe :"; cin>>n;
itoa(n,nr,10);int i,j;
for(j=0,i=strlen(nr);i>0;i--,j++)
transforma(nr[j],i-1);
cout<<"Numarul "<<n<<" scris cu cifre romane:"<<sir;getch();}

6.6. SUPRANCRCAREA FUNCIILOR
Limbajul C++ ofer posibilitatea de suprancrcare a numelui unei funcii (pe scurt,
suprancrcarea funciilor), ceea ce conduce la utilizarea unor funcii cu acelai nume, care
execut prelucrri diferite. Prototipurile unei funcii suprancrcate trebuie s difere ntre ele
prin numrul i/sau tipul parametrilor formali i/sau prin tipul valorii returnate. Selecia
funciei se realizeaz n momentul compilrii.
S urmrim exemplul urmtor, n care funcia afis este suprancrcat (patru funcii cu
acelai nume, dar cu prototipuri diferite). n momentul apelului, selecia uneia dintre cele
patru funcii se realizeaz pe baza parametrilor efectivi transmii, sau a valorii returnate.

Exemplu:
#include <iostream.h>
// prototipurile funciei afis, suprancrcat
int afis(const int);
//returneaz o valoare ntreag egal cu ptratul valorii argumentului ntreg
int afis(float); /*returneaz o valoare ntreag obinut prin conversia
Autor: Diana tefnescu
112
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

float -> int a triplului valorii argumentului real simpl precizie*/
float afis(const float, float); //returneaz media aritmetic a arg-lor
char * afis();//returneaz un ir de caractere
void afis(const char*);//afieaz irul constant transmis ca parametru
int main()
{int a = 12; float a1 = 14.33, a3 = 34.33;
cout << "Apel afis " << afis(a) << "\n";
cout << "Apel afis " << afis(2 * a) << "\n";
cout << "Apel afis " << afis(a1) << "\n";
cout << "Apel afis " << afis(a3) << "\n";
cout << "Apel afis " << afis(a1,a3) << "\n";
char *p=afis();
cout<<"p="<<p<<'\n';
afis("AFISARE SIR ARGUMENT!\n")
int afis(const int val)
{return val * val; }
int afis(float val)
{ return (int)(3.0 * val);}
float afis(const float i1, float i2)
{ return (i1 + i2)/2.0;}
char * afis()
{char *pp="Sir de caractere!!!!"; return pp;}
void afis(const char*s)
{cout<<s;}
6.7. CLASE DE MEMORARE
Definiii:
Variabilele declarate n afara oricrei funcii sunt variabilele globale.
Variabilele declarate n interiorul unui bloc sunt variabilele locale.
Poriunea de cod n care o variabil este accesibil reprezint scopul (domeniul de
vizibilitate) al variabilei respective.

Parametrii formali ai unei funcii sunt variabile locale ale funciei respective.
Domeniul de vizibilitate al unei variabile locale este blocul n care variabila respectiv este
definit.
n situaia n care numele unei variabile globale coincide cu numele unei variabile locale,
variabila local o "mascheaz" pe cea global, ca n exemplul urmtor: n interiorul blocului
din funcia main s-a redefinit variabila a, care este variabil local n interiorul blocului.
Variabila local a mascheaz variablila global numit tot a.

Exemplu:
#include <stdio.h>
int main()
{ int a,b; a=1; b=2;
printf("n afara blocului a=%d b=%d\n", a, b);
{int a=5; b=6;
printf("n interiorul blocului a=%d b=%d\n",a,b);
}
printf("n afara blocului a=%d b=%d\n", a, b); }
Autor: Diana tefnescu
113
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

n cazul variabilelor locale, compilatorul aloc memorie n momentul execuiei blocului sau
funciei n care acestea sunt definite. Cnd execuia funciei sau blocului se termin, se
elibereaz memoria pentru acestea i valorile pentru variabilele locale se pierd.

Definiii:
Timpul de via a unei variabile locale este durata de execuie a blocului (sau a
funciei) n care aceasta este definit.
Timpul de via a unei variabile globale este durata de execuie a programului.

n exemplul urmtor, variabila ntreag x este vizibil att n funcia main, ct i n funcia
func1 (x este variabila global, fiind definit n exteriorul oricrei funcii). Variabilele a i b
sunt variabile locale n funcia main (vizibile doar n main). Variabilele c i d sunt variabile
locale n funcia func1 (vizibile doar n func1). Varabila y este variabil extern i este
vizibil din punctul n care a fost definit, pn la sfritul fiierului surs (n acest caz, n
funcia func1).

Exemplu:
int x;
int main()
{int a,b;
//- - - - - - - - -
}
int y;
void func1(void)
{int c,d;
//- - - - - - - -
}

O variabil se caracterizeaz prin: nume, tip, valoare i clas de memorare.

Clasa de memorare se specific la declararea variabilei, prin unul din cuvintele cheie:
auto;
register;
extern;
static.

Clasa de memorare determin timpul de via i domeniul de vizibilitate (scopul) unei
variabile (tabelul 6.1).

Exemplu:
auto int a;
static int x;
extern double y;
register char c;

Clasa de memorare auto
Dac o variabil local este declarat fr a se indica n mod explicit o clas de
memorare, clasa de memorare considerat implicit este auto. Pentru acea variabil se
aloc memorie automat, la intrarea n blocul sau n funcia n care ea este declarat. Deci
domeniul de vizibilitate a variabilei este blocul sau funcia n care aceasta a fost definit.
Timpul de via este durata de execuie a blocului sau a funciei.
Autor: Diana tefnescu
114
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Clasa de memorare register
Variabilele din clasa register au acelai domeniu de vizibilitate i timp de via ca i cele
din clasa auto. Pentru memorarea variabilelor register se utilizeaz regitrii interni
(creterea eficienei) ai procesorului i ca urmare, unei astfel de variabile nu i se poate
aplica operatorul de refereniere.

Clasa de memorare extern
O variabil global declarat fr specificarea unei clase de memorare, este considerat
ca avnd clasa de memorare extern. Domeniul de vizibilitate este din momentul
declarrii pn la sfritul fiierului surs. Timpul de via este durata execuiei
fiierului. O variabil din clasa extern este iniializat automat cu valoarea 0.

Clasa de memorare static
Clasa de memorare static poate fi specificat att pentru variabilele locale, ct i pentru
cele globale:
Variabilele locale statice au ca domeniu de vizibilitate blocul sau funcia n care sunt
definite, iar ca timp de via - durata de execuie a programului. Se iniializeaz
automat cu 0.
Variabilele globale statice au ca domeniu de vizibilitate punctul n care au fost
definite pn la sfritul fiierului surs, iar ca timp de via - durata execuiei
programului.

Tabelul 6.1.
Clasa de
memorare
Variabila Domeniu vizibilitate Timp de via
auto
(register)
local
(intern)
Blocul sau funcia n care
au fost definite
Durata de execuie a blocului
sau a funciei
extern
global Din punctul definirii,
pn la sfritul fi-lui
(ROF)
Alte fiiere
Durata de execuie a blocului
sau a programului
static
global ROF --

local Bloc sau funcie --
nespecificat global Vezi extern Vezi extern

local Vezi auto Vezi auto

Exemplul: S se scrie urmtorul program (care utilizeaz variabile cu diferite clase de
memorare) i s se urmreasc rezultatele execuiei acestuia.
#include <stdio.h>

void f1(void);
void f2(void);
void f3(void);
int nr; /* variabla globala */
static int sg; /* variabla globala statica */

int main()
{ register int index; /* Variabila locala register, in main */
printf("Var glob nr=%d\n", nr);// Var glob nr=0
printf("Var glob statica sg=%d\n", sg); // Var glob statica sg=0
f1(); f2(); f3();
Autor: Diana tefnescu
115
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

for (index = 8;index > 0;index--) {
for (int stuff = 0;stuff <= 6;stuff++) /* stuff variabila locala
instructiunii compuse */
printf("%d ",stuff);
printf(" index este acum %d\n",index); }
//0123456 index este acum 8
//0123456 index este acum 7
//0123456 index este acum 6
//0123456 index este acum 5
//0123456 index este acum 4
//0123456 index este acum 3
//0123456 index este acum 2
//0123456 index este acum 1
}

int counter; /* domeniu de vizibilitate ROF*/

void f1(void)
{int index; /* Variabila locala in f1 */
index = 23;printf("In f1, index= %d\n",index);//In f1 index=23
printf("In f1, var globala counter= %d\n",counter);
//In f1, var globala counter=0
sg=99;printf("In f1, var globala statica sg= %d\n",sg); /*In f1,
var globala statica sg=99*/ }

void f2(void)
{int count; /* Variabila count locala functiei f2, o mascheaza pe cea globala */
static int sl;printf("In f2 sl= %d\n",sl); //in f2 sl=0
count = 53; printf("In f2 count= %d\n",count); //In f2 count=53
counter = 77;printf("In f2 var glob counter= %d\n",counter);
/*In f2 var glob counter=77*/ }

void f3(void)
{ printf("In f3 var globala counter=%d\n",counter);
/*In f3 var globala counter=77*/}
6.8. MODURI DE ALOCARE A MEMORIEI
Alocarea memoriei se poate realiza n urmtoarele moduri:
alocare static;
alocare dinamic;
alocare pe stiv.

Se aloc static memorie n urmtoarele cazuri:
pentru instruciunile de control propriu-zise;
pentru variabilele globale i variabilele locale declarate n mod explicit static.

Se aloc memorie pe stiv pentru variabilele locale.

Se aloc dinamic memorie n mod explicit, cu ajutorul funciilor de alocare dinamic, aflate
n headerul <alloc.h> (n limbajul C), sau cu ajutorul operatorului new (n limbajul C++).
Autor: Diana tefnescu
116
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Exemplu: S se urmreasc modul de declarare a variabilelor din secvena urmtoare i
alocarea memoriei pentru acestea.
























int a,b;
double x;

double f1(int c, double v)
{int b;
static double z;
}
double w;

int f1(int w)
{double a;}

int main()
{
double b, c;
int k;
b=f1(k,c);}
Stiv

Alocare static

a
b
x
c
v
b
z
w
w
a
b
c
k
Figura 6.8. Alocarea static i pe stiv
Pentru toate tipurile de date (simple sau structurate), la declararea acestora, compilatorul
aloc automat un numr de locaii de memorie (corespunztor tipului datei). Dimensiunea
zonei de memorie necesar pentru pstrarea valorilor datelor este fixat naintea lansrii n
execuie a programului. n cazul declarrii unui tablou de ntregi cu maximum 100 de
elemente vor fi alocai 100*sizeof(int) locaii de memorie succesive. n situaia n care
la un moment dat tabloul are doar 20 de elemente, pentru a aloca doar atta memorie ct este
necesar n momentul respectiv, se va aloca memorie n mod dinamic.

Este de dorit ca n cazul datelor a cror dimensiune nu este cunoscut a priori sau variaz n
limite largi, s se utilizeze o alt abordare: alocarea memoriei n mod dinamic. n mod
dinamic, memoria nu mai este alocat n momentul compilrii, ci n momentul execuiei.
Alocarea dinamic elimin necesitatea definirii complete a tuturor cerinelor de memorie n
momentul compilrii.
6.8.1. FUNCII DE ALOCARE DINAMIC A MEMORIEI
n limbajul C, alocarea memoriei n mod dinamic se face cu ajutorul funciilor malloc,
calloc, realloc; eliberarea zonei de memorie se face cu ajutorul funciei free.
Funciile de alocare/dealocare a memoriei au prototipurile n header-ele <stdlib.h> i
<alloc.h>:

void *malloc(size_t nr_octei_de_alocat);
Funcia malloc necesit un singur argument (numrul total de octei care vor fi reyervai) i
returneaz un pointer generic ctre zona de memorie alocat (pointerul conine adresa
primului octet al zonei de memorie rezervate).

Autor: Diana tefnescu
117
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

void *calloc(size_t nr_elem, size_t mrimea_unui_elem);
Funcia calloc lucreaz n mod similar cu malloc; aloc memorie pentru un tablou de
nr_elem, pentru fiecare element rezervndu-se un numr de octei specificat prin
mrimea_unui_elem i returneaz un pointer ctre zona de memorie alocat.

void *realloc(void *ptr, size_t mrime);
Funcia realloc permite modificarea zonei de memorie alocat dinamic cu ajutorul
funciilor malloc sau calloc.

Observaii:
1. n cazul n care nu se reuete alocarea dinamic a memoriei (de exemplu, memorie
insuficient), funciile malloc, calloc i realloc returneaz un pointer null.
2. Deoarece funciile malloc, calloc, realloc returneaz un pointer generic, rezultatul poate fi
atribuit oricrui tip de pointer. La atribuire, este indicat s se utilizeze operatorul de
conversie explicit (vezi exemplu).

Eliberarea memoriei (alocate dinamic cu una dintre funciile malloc, calloc sau realloc) se
realizeaz cu ajutorul funciei free, cu prototipul:
void free(void *ptr);
Funcia primete ca argument adresa de nceput a zonei de memorie care va fi eliberat.

Exemplu: S se aloce dinamic memorie pentru 20 de valori ntregi.
int *p;
p=(int*)malloc(20*sizeof(int));
//p=(int*)calloc(20, sizeof(int));

Exerciiul 1: S se scrie un program care implementeaz funcia numit introd_val.
Funcia trebuie s permit introducerea unui numr de valori reale, pentru care se aloc
memorie dinamic. Valorile citite cu ajutorul funciei introd_val sunt prelucrate n funcia
main, apoi memoria este eliberat.

#include <stdio.h>
#include <stdlib.h>
#include <alloc.h>
float *introd_val()
/* pentru a putea realiza eliberarea memoriei n funcia main, funcia introd_val
trebuie s returneze adresa de nceput a zonei de memorie alocate dinamic */
{double *p; int nr;printf("Numr valori:"); scanf("%d", nr);
if (!(p=(float*)malloc(nr*sizeof(float))) ){
printf("Memorie insuficient!\n");return NULL;
}
for (int i=0; i<nr; i++){
printf("Val %d=", i+1); scanf("%lf", p+i); return p;}
}

int main()
{float *pt; pt=introd_val();
// prelucrare tablou
free(pt);
}
Autor: Diana tefnescu
118
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Exerciiu: S se scrie un program care citete numele tuturor angajailor unei ntreprinderi.
Numrul angajailor este transmis ca argument ctre funcia main. Alocarea memoriei pentru
cei nr_ang angajai, ct i pentru numele fiecruia dintre acetia se va face n mod dinamic.

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
int main(int argc, char *argv[])
{char **ang_ptr;
char *nume;
int nr_ang, i;
if (argc==2){
nr_ang=atoi(argv[1]);/* numrul angajailor este transmis ca argument
ctre funcia main. El este convertit din ir de caractere n numr */
ang_ptr=(char**)calloc(nr_ang, sizeof(char*));
if ((ang_ptr==0){
printf("Memorie insuficient!\n");return 1;}
nume=(char*)calloc(30, sizeof(char));
for (i=0; i<nr_ang; ++i){
printf("Nume angajat:");
scanf("%s",nume);
ang_ptr[i]=(char*)calloc(strlen(nume)+1, sizeof(char));
strcpy(ang_ptr[i], nume);
}
free(nume);
printf("\n");
for (i=0; i<nr_ang; i++)
printf("Angajat nr %d: %s\n", i+1, ang_ptr[i]);}
else
printf("Lans.n execuie:%s numr angajai\n", argv[0]);}

Pentru a putea afla memoria RAM disponibil la un moment dat, se poate utiliza funcia
coreleft, cu prototipul:
unsigned coreleft(void);
6.8.2. OPERATORI DE ALOCARE DINAMIC A MEMORIE
n limbajul C++ alocarea dinamic a memoriei i eliberarea ei se pot realiza cu operatorii
new i delete. Folosirea acestor operatori reprezint o metod superioar, adaptat
programrii orientate obiect.
Operatorul new este un operator unar, care ofer posibilitatea alocrii dinamice de memoriei
att pentru date de tip predefinit, ct i pentru date de tip definit de utilizator. Operatorul
returneaz un pointer la zona de memorie alocat dinamic. n situaia n care nu exist
suficient memorie i alocarea nu reuete, operatorul new returneaz pointerul NULL.
Operatorul delete elibereaz zona de memorie spre care pointeaz argumentul su.
Sintaxa:
<tipdata_pointer> = new <tipdata>;
<tipdata_pointer> = new <tipdata>(<val_iniializare>);
//pentru iniializarea datei pentru care se aloc memorie dinamic
<tipdata_pointer> = new <tipdata>[nr_elem];
//alocarea memoriei pentru un tablou
delete <tipdata_pointer>;
delete [<nr_elem>] <tipdata_pointer>;
//eliberarea memoriei pentru tablouri
Autor: Diana tefnescu
119
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

<tipdata> reprezint tipul datei (predefinit sau obiect) pentru care se aloc dinamic
memorie, iar <tipdata_pointer> este o variabil pointer ctre tipul tipdata.

Exerciiul 1: S se aloce dinamic memorie pentru o dat de tip ntreg:
int *pint;
pint=new int;
//Sau:
int &i=*new int;
i=100; //i permite referirea la ntregul pstrat n zona de memorie alocat dinamic

Exerciiul 2: S se aloce dinamic memorie pentru o dat real, dubl precizie, iniializnd-o
cu valoarea -7.2.
double *p;
p=new double(-7.2);
//Sau:
double &p=* new double(-7.2);

Exerciiul 3: S se aloce dinamic memorie pentru un vector de m elemente reale.
double *vector; vector=new double[m];

Exerciiul 4: S se urmreasc rezultatele execuiei urmtorului program, care utilizeaz
pentru alocarea dinamic, respectiv eliberarea memoriei, operatorii new i delete.
#include <iostream.h>
int main()
{
int index, *p1, *p2; p1 = &index; *p1 = 100;
p2 = new int(173);// *p2 = 173;
cout << "Valori:" <<index << " " <<*p1 << " " << *p2 << "\n";
//Valori: 100 100 173
p1 = new int; p2 = p1; *p1 = 9999;
cout << "Valori:" <<index << " " <<*p1 << " " << *p2 << "\n";
//Valori: 100 9999 9999
delete p1;
float *fp1, *fp2 = new float;
fp1 = new float;*fp2 = 3.14159;*fp1 = 3 * (*fp2);
delete fp2;delete fp1;
char *c_p;c_p = new char[50];delete c_p;
c_p = new char[sizeof('A') + 133];delete c_p;
}

Exemplu: S se urmreasc rezultatele execuiei urmtorului program, care utilizeaz funcia
coreleft.
#include <iostream.h>
#include <alloc.h>
#include <conio.h>
int main()
{ int *a,*b;
cout<<"Mem. libera inainte de alocare:"<<coreleft()<<'\n';
cout<<"Adr. pointerilor a si b:"<<&a<<" "<<&b<<'\n';
cout<<"Val.point. a, b inainte de alocare:"<<a<<" "<<b<<'\n';
a=new int; b=new int[10];
cout<<"Mem. libera dupa alocare:"<<coreleft()<<'\n';
cout<<"Val.point. a, b dupa alocare:"<<a<<" "<<b<<'\n';
cout<<"Contin. Mem. alocate:\n"<<"*a="<<*a<<"\n*b="<<*b<<'\n';
for (int k=0;k<10;k++) cout<<"\nb["<<k<<"]="<<b[k];
cout<<'\n'; getch();
Autor: Diana tefnescu
120
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

*a=1732;
for (int u=0;u<10;u++) b[u]=2*u+1;
cout<<"Cont. zonelor alocate dupa atrib:"<<"\n*a="<<*a<<"\nb=";
for (u=0;u<10;u++) cout<<"\nb["<<u<<"]="<<b[u];
delete a; delete b;
cout<<"Mem. libera dupa eliberare:"<<coreleft()<<'\n';
cout<<"Val. point a si b dupa eliberare:"<<a<<" "<<b<<'\n';
cout<<"Cont. mem. eliberate:\n"<<"*a="<<*a<<"\n*b="<<*b<<'\n';
for (k=0;k<10;k++) cout<<"\nb["<<k<<"]="<<b[k];
cout<<'\n'; cout<<b[3]; getch(); }
6.9. FUNCII RECURSIVE
O funcie este numit funcie recursiv dac ea se autoapeleaz, fie direct (n definiia ei se
face apel la ea nsi), fie indirect (prin apelul altor funcii). Limbajele C/C++ dispun de
mecanisme speciale care permit suspendarea execuiei unei funcii, salvarea datelor i
reactivarea execuiei la momentul potrivit. Pentru fiecare apel al funciei, parametrii i
variabilele automatice se memoreaz pe stiv, avnd valori distincte la fiecare reapelare.
Orice apel al unei funcii conduce la o revenire n funcia respectiv, n punctul urmtor
instruciunii de apel. La revenirea dintr-o funcie, stiva este curat (revine la starea dinaintea
apelului).

Proiectarea unui algoritm recursiv trebuie s asigure ieirea din recursivitate. De aceea, apelul
recursiv este ntotdeauna inclus ntr-o structur de control de decizie sau repetitiv.

Un exemplu de funcie recursiv este funcia de calcul a factorialului, definit astfel:
fact(n)=1, dac n=0; (parte a procesului recursiv care nu se definete prin el nsui)
fact(n)=n*fact(n-1), dac n>0;

Exemplu: S se implementeze recursiv funcia care calculeaz n!, unde n este introdus de la
tastatur:
#include <iostream.h>
int fact(int n)
{if (n<0){
cout<<"Argument negativ!\n";
exit(2);
}
else if (n==0) return 1;
else return n*fact(n-1);
}
int main()
{int nr, f; cout<<"nr="; cin>>nr;
f=fact(nr); cout<<nr<<"!="<<f<<'\n'; }

Se observ c n corpul funciei fact se apeleaz nsi funcia fact. Presupunem c nr=4
(iniial, funcia fact este apelat pentru a calcula 4!). S urmrim diagramele din figurile 6.9.
i 6.10. La apelul funciei fact, valoarea parametrului de apel nr (nr=4) iniializeaz
parametrul formal n. Pe stiv se memoreaz adresa de revenire n funcia apelant (adr1) i
valoarea lui n (n=4) (figura 6.7.a.). Deoarece n>0, se execut intruciunea de pe ramura else
(return n*fact(n-1)). Funcia fact se autoapeleaz direct. Evaluarea expresiei 4*fact(3)
necesit cunoaterea operandului fact(3). Ca urmare, evaluarea se suspend temporar,
executndu-se apelul funciei fact(3). Se memoreaz pe stiv noua adres de revenire i noua
valoare a parametrului n (n=3) (figura 6.9.b.).
Autor: Diana tefnescu
121
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

La noul reapel al funciei fact, se execut din nou intruciunea de pe ramura else (return
n*fact(n-1)). Se memoreaz pe stiv adresa de revenire i noua valoare a parametrului n (n=2)
(figura 6.9.c.). La noul reapel al funciei fact, se execut din nou intruciunea de pe ramura
else (return n*fact(n-1)). Se memoreaz pe stiv adresa de revenire i noua valoare a
parametrului n (n=1) (figura 6.9.d.). La noul reapel al funciei fact, se execut din nou
intruciunea de pe ramura else (return n*fact(n-1)). Se memoreaz pe stiv adresa de revenire
i noua valoare a parametrului n (n=0) (figura 6.9.e.).

n acest moment n=0 i se revine din funcie cu valoarea 1 (1*fact(0)=1*1), la configuraia
stivei din figura 6.9.d.) (se cur stiva i se ajunge la configuraia din figura 6.9.d.). n acest
moment n=1 i se revine cu valoarea 2*fact(1)=2*1=2, se cura stiva i se ajunge la
configuraia stivei din figura 6.9.c. n acest moment n=2 i se revine cu valoarea
3*fact(2)=3*2=6, se cura stiva i se ajunge la configuraia stivei din figura 6.9.b. Se cur
stiva i se ajunge la configuraia stivei din figura 6.9.a.. n acest moment n=3 i se revine cu
valoarea 4*fact(3)=4*6=24.

O funcie recursiv poate fi realizat i iterativ. Modul de implementare trebuie ales n funcie
de problem. Dei implementarea recursiv a unui algoritm permite o descriere clar i
compact, recursivitatea nu conduce la economie de memorie i nici la execuia mai rapid a
programelor. n general, se recomand utilizarea funciilor recursive n anumite tehnici de
programare, cum ar fi unele metode de cutare (backtracking).

















Figura 6.9. Configuraia stivei
adr1
n=4
(a)
adr2
n=3
adr1
n=4
(b)
adr2
n=2
adr2
n=3
adr1
n=4
(c)
adr2
n=1
adr2
n=2
adr2
n=3
adr1
n=4
(d)
0!=
adr2
n=0
adr2
n=1
adr2
n=2
adr2
n=3
adr1
n=4
(e)
6
2
1
1 0
1
2
3
24
4
fact
fact
fact
fact
fact
Figura 6.10. Parametri funciei
fact
Exerciiul 1: Fie irul lui Fibonacci, definit astfel: f(0)=0, f(1)=1, f(n)=f(n-1)+f(n-
2), dac n>1. S se scrie un program care implementeaz algoritmul de calcul al irului
Fibonacci att recursiv, ct i iterativ. S se compare timpul de execuie n cele dou situaii.
#include <iostream.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <stdio.h>
long int iterativ_fib(long int n)//varianta de implementare iterativ
{if (n==0) return 0;
if (n==1) return 1;
int i; long int a, b, c; a=0; b=1;
for (i=2; i<=n; i++){
c=b; b+=a; a=c;}
return b; }
Autor: Diana tefnescu
122
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

long int recursiv_fib(long int n)//varianta de implementare recursiv
{if (n==0) return 0;
if (n==1) return 1;
long int i1=recursiv_fib(n-1);
long int i2=recursiv_fib(n-2);
return i1+i2;
}

int main()
{int n;
cout<<MAXLONG<<'\n';
for (n=10; n<=40; n++) {
clock_t t1, t2, t3;
cout<<CLK_TCK<<'\n';
t1=clock(); long int f1=iterativ_fib(n);
t2=clock(); long f2=recursiv_fib(n); t3=clock();
double timp1=(double)(t2-t1)/CLK_TCK;
double timp2=(double)(t3-t2)/CLK_TCK;
printf("ITERATIV: %10ld t=%20.10lf\n",f1,timp1);
printf("RECURSIV: %10ld t=%20.10lf\n",f2,timp2);
cout<<"Apasa o tasta....\n"; getch();
}
}

n exemplul anterior, pentru msurarea timpului de execuie s-a utilizat funcia clock, al
crei prototip se afl n header-ul time.h. Variabilele t1, t2 i t3 sunt de tipul clock_t,
tip definit n acelai header. Constanta simbolic CLK_TCK definete numrul de bti ale
ceasului, pe secund.

Exerciiul 2: S se calculeze suma S=1+2+3++n, unde n este introdus de la tastatur. Pentru
calculul sumei, se va folosi o funcie recursiv.
#include <iostream.h>
#include <conio.h>

int sum_rec(int n)
{if (n==0) return 0;
else return (n+sum_rec(n-1));}

int main()
{ int nr, S;nr=9; S= sum_rec(9); cout<<"S="<<S<<'\n'; }

Orice algoritm (program) recursiv poate fi transformat in unul iterativ, dar algoritmul sau
poate deveni mai complicat i mai greu de neles. Dei timpul de execuie a unei recursii este
semnificativ mai mare dect cel necesar execuiei iteraiei echivalente, uneori, soluia unei
probleme poate fi elaborat mult mai uor, mai clar i mai simplu de verificat, printr-un
algoritm recursiv. Recursia este folosit n special n prelucrarea unor structuri de date finite
recursiv (liste, arbori), n problemele cu definiii recursive (algoritmul lui Euclid de aflare a
c.m.m.d.c., factorialul, ridicarea la o putere ntreag prin nmuliri repetate, definirea
recursiva a unei expresii aritmetice, curbele recursive, calculul permutarilor, etc.) sau n
anumite tehnici de programare (tehnica divizrii - "divide and conquer" - aplicat n gsirea
minimului i maximului valorilor elementelor unui tablou, n cutarea binar, n sortarea
Quicksort, n problema turnurilor din Hanoi; tehnica cu revenire backtracking care
previne gsirea tuturor soluiilor, aplicat n problema celor opt regine, a relaiilor stabile,
a colorrii unei hri, tierea unui fir de lungime l n pri de lungimi date; tehnica nlnuie i
limiteaz - branch and bound numit i backtracking cu constrngeri).

Autor: Diana tefnescu
123
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii
Exerciiul 3: S se implementeze i s se testeze un program care:
a) Genereaz aleator i afieaz elementele unui vector ;
b) Sorteaz aceste elemente, cresctor, aplicnd metodele de sortare BubbleSort,
InsertSort, i QuickSort;
c) S se compare viteza de sortare pentru vectori de diverse dimensiuni (10,30,50,100
elemente).
Metoda BubbleSort a fost prezentat n capitolul 4.
Metoda QuickSort reprezint o alt metod de sortare a elementelor unui vector.
Algoritmul este recursiv: se mparte vectorul n dou partiii, fa de un element pivot (de
obicei, elementul din mijlocul vectorului). Partiia stng ncepe de la indexul i (la
primul apel i=0), iar partiia dreapt se termin cu indexul j (la primul apel j=n-1)
(figura 6.11.).






Partiia stng este extins la dreapta (i incrementat) pn cnd se gsete un element mai
mare dect pivotul; partiia dreapt este extins la stnga (j decrementat) pn cnd se gsete
un element mai mic dect pivotul. Cele dou elemente gsite, vect[i] i vect[j], sunt
interschimbate.
j i
. . . . . . .
0 n - 1
0
pivot i j
n - 1
Figura 6.11. Sortare prin metoda QuickSort
Se reia ciclic extinderea partiiilor pn cnd i i j se "ncrucieaz" (i devine mai mare ca
j). n final, partiia stng va conine elementele mai mici dect pivotul, iar partiia dreapt -
elementele mai mari dect pivotul, dar nesortate.

SUBALGORITM QuickSort (vect[ ], stg, drt) //la primul apel stg = 0 si drt = n - 1
NCEPUT SUBALGORITM
i stg
j drt
DAC i < j ATUNCI
NCEPUT
pivot=vect[(stg+drt)/2]
CT TIMP i <= j REPET
//extinderea partiiilor stnga i dreapta pn cnd i se ncrucieaz cu j
NCEPUT
CT TIMP i<drt si vect[i]<pivot REPET
i = i + 1
CT TIMP j<stg si vect[j] >pivot REPET
j = j - 1
DAC i<=j ATUNCI
NCEPUT //interschimb elementele vect[i] i vect[j]
aux vect[i]
vect[i]vect[j]
vect[j]aux
ii+1
jj-1
SFRIT
SFRIT
DAC j>stg ATUNCI // part. stng extinsa la max, apel qiuckSort pentru ea
CHEAM QuickSort(vect, stg, j)
DAC i<drt ATUNCI //par. dreapt extinsa la max, apel qiuckSort pentru ea
CHEAM QuickSort(vect, i, drt)
SFRIT
SFRIT SUBALGORITM
Autor: Diana tefnescu
124
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Algoritmul este reluat prin recursie pentru partiia stng (cu limitele ntre 0 i j ), apoi pentru
partiia dreapt (cu limitele ntre i i n-1 ). Recursia pentru partea stng se oprete atunci
cnd j atinge limita stng (devine 0), iar recursia pentru partiia dreapt se oprete cnd i
atinge limita dreapt (devine n-1).

Metoda InsertSort (metoda inseriei)
Metoda identific cel mai mic element al vectorului i l schimb cu primul element. Se reia
procedura pentru vectorul iniial, fr primul element i se caut minimul n noul vector, etc.

SUBALGORITM InsertSort (vect[ ], nr_elem)
NCEPUT SUBALGORITM
CT TIMP i< nr_elem REPET
NCEPUT
pozMincautMinim(vect,i,nr_elem) //se apeleaz alg. cautMinim
aux vect[i]
vect[i]vect[pozMin]
vect[pozMin]aux
i i+1
SFRIT
SFRIT SUBALGORITM

Funcia cautMin(vect[ ], indexIni, nr_elem) caut elementul minim al unui
vector, ncepnd de la poziia indexIni i returneaz poziia minimului gsit.

Mod de implementare (Se va completa programul cu instruciunile care obin i afieaz
timpului necesar ordonrii prin fiecare metod. Se vor compara rezultatele pentru un vector
de 10, 30, 50, 100 elemente):

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define TRUE 1
#define FALSE 0
void gener(double v[], int n)
//functia de generare aleatoare a elementelor vectorului v, cu n elemente
{for (int i=0; i<n; i++)
v[i]=1.0*rand()/100000;
}
void afis(double v[], int n)
//functia de afisare a vectorului
{for (int i=0; i<n; i++)
printf("%10.2f",v[i]);
printf("\n");
}
void copie_vect(double v1[], double v[], int n)
//functie de "duplicare "a unui vector; copie vectorul v in vectorul v1
{for (int i=0; i<n; i++)
v1[i]=v[i];
}
void bubbleSort(double v[], int n)
{int gata; gata=FALSE;
while (!gata){
gata=TRUE;
for (int i=0; i<n-1; i++)
if (v[i]>=v[i+1]){
double aux=v[i];
Autor: Diana tefnescu
125
v[i]=v[i+1];
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii
v[i+1]=aux;
// printf("Interschimbare element %d cu %d",i,i+1);
// afis(v,n);
gata=FALSE;}
}}

int cautMin(double v[], int indexIni, int n)
// cauta elementul minim, incepnd de la pozitia indexIni, inclusiv
{ double min=v[indexIni];
int pozMin=indexIni;
for (int i=indexIni; i<n; i++)
if (v[i]<=min){
min=v[i]; pozMin=i;
}
return pozMin;
}
void insertSort(double v[], int n)
{ int i;
for (i=0; i<n; i++){
int poz=cautMin(v, i, n);
double aux=v[i];
v[i]=v[poz];
v[poz]=aux;
}
}

void quickSort(double v[], int stg, int drt)
{int i,j; i=stg; j=drt; double pivot, aux;
if (i<j){
pivot=v[(stg+drt)/2];
while (i<=j){ //extindere partitie st si dr pana i se incrucis cu j
while (i<drt && v[i]<pivot) i++;
while (j>stg && v[j]>pivot) j--;
if (i<=j){
aux=v[i];v[i]=v[j];v[j]=aux; //interschimbare elemente
i++; j--;
}
}
if (j>stg) quickSort(v, stg, j);
if (i<drt) quickSort(v, i, drt);
}
}
int main()
{
clock_t ti,tf; int n; //n = nr elemente vector
printf("Nr componente vector:"); scanf("%d", &n);
double v[200], v1[200], v2[200], v3[200];
gener(v, n);
copie_vect(v1,v,n);
printf("\nInainte de ordonare: v1="); afis(v1, n); ti=clock();
bubbleSort(v1,n); tf=clock(); printf("\nDupa ord.:v1=");afis(v1, n);
printf("%10.7f", dif_b);
printf("\n\n****** INSERT SORT ******\n");
copie_vect(v2,v,n);
printf("\nInainte de ordonare INSERT: v2="); afis(v2, n);
insertSort(v2,n); printf("\nDupa ord. INSERT: v2=");afis(v2, n);
int st=0; int dr=n-1; copie_vect(v3, v, n);
printf("\n\n****** QUICK SORT ******\n");
printf("\nInainte ordonare QUICK: v3="); afis(v3, n);
Autor: Diana tefnescu
126
quickSort(v3, st, dr); printf("\nDupa ordonare QUICK: v3=");
afis(v3, n);
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii
}

Exerciiul 4: Problema turnurilor din Hanoi, inspirat dintr-o veche legend: Se consider
trei tije verticale (A, B i C), fixate pe o plac. Pe una dintre tije (A) sunt aranjate discuri (cu
orificiu n centru), n ordinea descresctoare a diametrelor. Scopul jocului este de a muta
turnul de discuri de pe tija iniial (A) pe tija B, folosind tija C ca tij de manevr. La fiecare
mutare se deplaseaz un singur disc, i n nici o etap nu este admis ca un disc mai mare s fie
aezat peste un disc mai mic.

Notm cele n discuri n ordinea descresctoare a diametrelor (discul 1 n vrful turnului,
discul n - la baza turnului). Pentru a muta n discuri de pe tija A pe B, folosind C, se mut mai
nti cele n-1 discuri de pe A pe B, folosind C; dup mutarea discurilor de deasupra, poate fi
mutat discul de la baza turnului (discul n), de pe A pe B. Se aduc apoi deasupra acestuia (pe
B) toate discurile de pe C (cele n-1), folosind tija A (rmas liber). Aceast secven se
repet pentru un numr de discuri n>1. Deci rezolvarea problemei pentru n discuri s-a redus
la rezolvarea aceleeai probleme, pentru n-1 discuri. Rolul tijelor se schimb n etapele
procesului de deplasare a discurilor, de aceea parametrii funciei hanoi specific rolul
fiecrei tije.

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define ERR 1
void hanoi(int n, char A, char B, char C)
{/* n-nr. Discurilor
A-tija sursa B-tija destinatie C-tija de manevra */
if (n==1){
printf("Se muta discul %d de pe tija %c pe tija %c\n", n, A, B);
getch(); return;}
/* n>1 problema ptr n-1 discuri
A-tija sursa C-tija destinatie B-tija de manevra */

hanoi(n-1, A, C, B);
/* mutarea discului n de pe A pe B */
printf("Se muta discul %d de pe tija %c pe tija %c\n", n, A, B);
getch();
/* n>1 problema ptr n-1 discuri
C-tija sursa B-tija destinatie A-tija de manevra */
hanoi(n-1, C, B, A);
}

int main()
{int nr; printf("Nr discuri=");
if (scanf("%d", &nr)!=1 || nr<=0){
//validarea numarului intreg citit (nr. discuri)
printf("Date intrare invalide!\n"); return ERR;}
else hanoi(nr, 'A', 'B', 'C');
}
Autor: Diana tefnescu
127
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

6.11. POINTERI CTRE FUNCII
Aa cum s-a evideniat n capitolul 5, exista trei categorii de variabilele pointer:
Pointeri cu tip;
Pointeri generici (void);
Pointeri ctre funcii.

Pointerii ctre funcii sunt variabile pointer care conin adresa de nceput a codului
executabil al unei funcii. Pointerii ctre funcii permit:
Transferul ca parametru al adresei unei funcii (exerciiul 2);
Apelul unei funcii cu ajutorul unui pointer ctre aceasta (exerciiul 1).

Declaraia unui pointer ctre funcie are urmtoarea form:
<tip> (*<nume_point>)(<lista_declar_param_formali>);
unde:
nume_point este un pointer de tipul funcie cu rezultatul tipul_valorii_ntoarse. n
declaraia anterioar trebuie remarcat rolul parantezelor, pentru a putea face distincie ntre
declaraia unei funcii care ntoarce un pointer i declaraia unui pointer de funcie:
tip_val_intoarse * nume_point (lista_declar_param_formali);
tip_val_intoarse (* nume_point)(lista_declar_param_formali);

Exemplu:
int f(double u, int v); //prototipul funciei f
int (*pf)(double, int); //declararea pointerului pf,ctre funcia f
int i, j; double d;
pf=f; //atribuie adresa codului executabil al funciei f pointerului pf
j=*pf(d, i); //apelul funciei f, folosind pointerul ctre funcie, pf

Exerciiul 1: S se implementeze exemplul urmtor, care ilustreaz modul de utilizare a
pointerilor ctre funcii.
#include <iostream.h>
#include <stdio.h>
void afis(float);
void afis1(float);
void afis_float(float);
void (*point_fc)(float); //declararea pointerului ctre funcie point_fct
int main()
{ float pi = 3.14159; float dublu_pi = 2.0 * pi;
afis(pi); // Aceasta este functia afis.
point_fc = afis; point_fc(pi); // Aceasta este functia afis.
point_fc = afis1; point_fc(dublu_pi); // Data de afisat este 6.283180
point_fc(13.0); // Data de afisat este 13.000000
point_fc = afis_float; point_fc(pi); // Functia afis_float 3.141590
afis_float(pi); // Functia afis_float 3.141590
}
void afis(float data_de_ignorat)
{ printf("Aceasta este functia afis.\n"); }
void afis1(float lista_data)
{ printf("Data de afisat este %f\n", lista_data);}
void afis_float(float date_de_afis)
{ printf("Functia afis_float %f\n", date_de_afis);}
Autor: Diana tefnescu
128
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

Exerciiul 2: S se implementeze un program care calculeaz o funcie a crei valoare este
integrala altei funcii. Pentru calculul integralei se va folosi metoda trapezelor.

h
a x
1
x
2
x
3
. . . . x
2 n
x
1 n
b
f(x)
Figura 6.9. Calculul integralei prin metoda
trapezelor
Relaia pentru calculul integralei prin metoda
trapezelor pentru este:

b
a
dx x f ) (
I = (f(a)+f(b))/2 +

=
+
1
1
) * (
n
k
h k a f

S se calculeze

+ + +
+
b
a
x
x
e
) 1 ln( 3 . 0 1
2 . 0
4
2
| |
dx,
cu o eroare mai mic dect eps (valoarea erorii introdus de la tastatur).


#include <conio.h>
#include <math.h>
#include <iostream.h>

double functie(double x)
{return sqrt(0.1+exp(0.5*fabs(x)))/(1+sqrt(0.3+log(1+pow(x,4))));
}

double intrap(double a, double b, long int n, double (*f)(double))
{double h,s=0; long k;
if (a>=b)
return 0;
if (n<=0)
n=1;
h=(b-a)/n;
for (k=1; k<n; k++)
s+=f(a+k*h);
return ((f(a)+f(b))/2+s)*h;
}

int main()
{long int j; double p,q;
double eps, d2;double dif;
cout<<"Marg. inf:";cin>>p;
cout<<"Marg. sup:";cin>>q;
cout<<"Eroare:";cin>>eps; j=1;
double d1=intrap(p, q, j, functie);
do{ j*=2;
if (j>MAXLONG || j<0)
break;
d2=intrap(p, q, j, functie);
dif=fabs(d1-d2); d1=d2;
cout<<"Nr.intervale "<<j<<" Val.integralei "<<d2<<'\n';
}while (dif>eps);
cout<<"\n\n-----------------------------------------------\n";
cout<<"Val. integralei: "<<d2<<" cu eroare de:"<<eps<<'\n';
}

Autor: Diana tefnescu
129
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

6.12. NTREBRI I PROBLEME
NTREBRI

1. Asemnri ntre transferul parametrilor
unei funcii prin pointeri i prin referin.
2. Caracteristicile modului de transfer a
parametrilor unei funcii prin pointeri.
3. Caracteristicile variabilelor globale.
4. Caracteristicile variabilelor locale.
5. Care este diferena ntre antetul unei
funcii i prototipul acesteia?
6. Care sunt modurile de alocare a
memoriei?
7. Care sunt modurile de transfer a
parametrilor unei funcii?
8. Care sunt operatorii din C++ care permit
alocarea/dealocarea dinamic a memoriei?
9. Ce clase de memorare cunoastei?
10. Ce este domeniul de vizibilitate a unei
variabile?
11. Ce este prototipul unei funcii?
12. Ce este timpul de via a unei variabile?
13. Ce loc ocup declaraiile variabilelor
locale n corpul unei funcii?
14. Ce reprezint antetul unei funcii?
15. Ce rol are declararea funciilor?
16. Ce se indic n specificatorul de format al
funciei printf ?
17. Ce sunt funciile cu numr variabil de
parametri? Exemple.
18. Ce sunt funciile cu parametri implicii?
19. Ce sunt pointerii ctre funcii?
20. Ce sunt variabilele referin?
21. Cine determin timpul de via i
domeniul de vizibilitate ale unei
variabile?
22. Comparaie ntre declararea i definirea
funciilor.
23. Diferene ntre modurile de transfer a
parametrilor prin valoare i prin referin.
24. Din apelul funciei printf se poate omite
specificatorul de format?
25. Din ce este format o funcie?
26. n ce zon de memorie se rezerv spaiu
pentru variabilele globale?
27. O funcie poate fi declarat n corpul altei
funcii?
28. O funcie poate fi definit n corpul unei
alte funcii?
29. Parametrii formali ai unei funcii sunt
variabile locale sau globale?
30. Transferul parametrilor prin valoare.
31. Ce rol au parametrii formali ai unei
funcii?
32. Ce reprezint suprancrcarea unei
funcii?
33. Prin ce se deosebesc variabilele cu clasa
de memorare register fa de cale cu clasa
de memorare auto?
34. Diferene ntre modurile de transfer a
parametrilor unei funcii prin pointeri i
prin referin.

PROBLEME

1. S se implementeze programele cu exemplele prezentate.

2. S se scrie programele pentru exerciiile rezolvate care au fost prezentate.

3. S se modularizeze programele din capitolul 4 (3.a.-3.g., 4.a.-4.i, 5.a.-5.h.), prin
implementarea unor funcii (funcii pentru: citirea elementelor unui vector, afiarea
vectorului, calculul sumei a doi vectori, calculul produsului scalar a doi vectori, aflarea
elementului minim din vector, citire a unei matrici, afiare a matricii, calculul transpusei
Autor: Diana tefnescu
130
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

unei matrici, calculul sumei a dou matrici, calculul produsului a dou matrici, calculul
produsului elementelor din triunghiul haurat, etc.).

4. S se rescrie programele care rezolv exerciiile din capitolul 3, folosind funcii (pentru
calculul factorialului, aflarea celui mai mare divizor comun, ordonarea lexicografic a
caracterelor, etc). Utilizai funciile de intrare/ieire printf i scanf.

5. S se scrie un program care citete cte dou numere, pn la ntlnirea perechii de
numere 0, 0 i afieaz, de fiecare dat, cel mai mare divizor comun al acestora, folosind o
funcie care l calculeaz.

6. Se introduce de la tastatura un numr ntreg. S se afieze toi divizorii numrului
introdus. Se va folosi o funcie de calcul a celui mai mare divizor comun a 2 numere.

7. Secvenele urmtoare sunt corecte din punct de vedere sintactic? Dac nu, identificai
sursele erorilor.
void a(int x, y) {cout<<"x="<<x<<" y="<<y<<'\n'; }
int main( ) { int b=9; a(6, 7); }
int main( ) {int x=8; double y=f(x); cout<<"y="<<y<<'\n';}
int f(int z) {return z+z*z;}

8. Scriei o funcie gsete_cifra care returneaz valoarea cifrei aflate pe poziia k n
cadrul numrului n, ncepnd de la dreapta (n i k vor fi argumentele funciei).

9. Implementai propriile versiuni ale funciile de lucru cu iruri de caractere.

10. S se calculeze valoarea funciei g, cu o eroare EPS (a, b, EPS citite de la tastatur):
g(x)=

+ +
b
a
x x ) 1 (
2
*ln a x + dx +

+
b
a
x b b arctg x )) ( ( * dx

11. Implementai funcii iterative i recursive pentru calculul valorilor polinoamelor Hermite
H (y), tiind c: H (y)=1, H
1
(y)=2y, H (x)=2yH (y)-2H (y) dac n>1.
Comparai timpul de execuie al celor dou funcii.
n 0 n 1 n 2 n

12. S se scrie un program care genereaz toate numerele palindrom, mai mici dect o valoare
dat, LIM. Un numr palindrom are cifrele simetrice egale (prima cu ultima, a doua cu
penultima, etc). Se va folosi o funcie care testeaz dac un numr este palindrom.

13. Fie matricea C (NXN), N<=10, ale crei elemente sunt date de relaia:
j! + , dac i<j

=
j
k
kx
0
) sin(
C = x
i
, dac i=j
j i,
i! + , dac i>j

=0
) cos(
k
kx i
, unde x[0,1], x introdus de la tastatur
a) S se implementeze urmtoarele funcii: de calcul a elementelor matricii; de afiare a
matricii; de calcul i de afiare a procentului elementelor negative de pe coloanele
impare (de indice 1, 3, etc).
b) S se calculeze i s se afieze matricea B, unde: B = C - C + C
3
- C + C .
2 4 5
Autor: Diana tefnescu
131
CAPITOLUL 6 Programarea n limbajele C/C++ Funcii

11. S se creeze o bibliotec de funcii pentru lucrul cu matrici, care s conin funciile
utilizate frecvent (citirea elementelor, afisarea matricii, adunare a dou matrici, etc). S se
foloseasc aceast bibliotec.

12. S se creeze o bibliotec de funcii pentru lucrul cu vectori, care s conin funciile
utilizate frecvent. S se foloseasc aceast bibliotec.

13. S se calculeze cel mai mare divizor comun a dou numere, folosind ntr-o funcie
recursiv relaia de recuren: cmmdc(a, b) = cmmdc(b, a%b).

14. Folosind o funcie recursiv, s se inverseze un ir de caractere terminat cu blanc.

15. S se scrie un program care determin cel mai mare divizor comun i cel mai mic multiplu
comun a n numere naturale, nenule. Se va utiliza calculul recurent.

16. S se calculeze S = C + C
1
+ C + C + . . . + C , unde n este un numr natural,
introdus de la tastatur. Se va folosi o funcie pentru calculul C .
0
n n
2
n
3
n
n
n
k
n

17. S se calculeze S = A + A
1
+ A + A + . . . + A , unde n este un numr natural,
introdus de la tastatur. Se va folosi o funcie pentru calculul A .
0
n n
2
n
3
n
n
n
k
n

18. S se calculeze S = 1! + 2! + 3! + . . . + n!, unde n este un numr natural, introdus de la
tastatur. Se va folosi o funcie pentru calculul factorialului.

19. Fie n natural, citit de la tastatur (n<100). S se determine toate tripletele de numere (x, y,
z) mai mici dect n, care sunt numere pitagorice (ndeplinesc relaia x + y = z ).
Numerele fiecrui triplet vor fi afiate n ordine cresctoare, pe cte o linie a ecranului.
2 2 2

20. S se calculeze valorile urmtoarelor expresii (n natural, citit de la tastatura), folosind o
funcie care calculeaz termenul general.
E(n)=1*(1+2)*(1+2+3)* . . . *(1+2+3+. . . +n)
E(n)=1*2 - 2*4 + 3*6 - 4*8 + . . . +(-1) *n*2*n
n

Autor: Diana tefnescu
132

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