Sunteți pe pagina 1din 11

Programarea Calculatoarelor

Laborator VIII
Anamaria Rădoi, Adrian Liţă, Ovidiu Grigore
2015

1 Scopul laboratorului
Laboratorul VIII al materiei Programarea Calculatoarelor are ca scop utilizarea
funcţiilor.
În acest laborator se parcurg următoarele puncte:
• declararea şi definirea unei funcţii
• aria de influenţă a unei funcţii

• apelarea prin valoarea a unei funcţii


• apelarea prin referinţă a unei funcţii
• funcţia main()

• pointeri către funcţii


• funcţii cu un număr variabil de parametrii
• supraîncărcarea funcţiilor

2 Desfăşurarea lucrării
Odată cu creşterea complexităţii programelor scrise, este nevoie de divizarea
unui program în funcţie de sarcinile executate astfel încât implementarea pro-
gramelor şi verificarea lor să fie mai uşor de efectuat. În acest sens, limbajul de
programare C++ oferă posibilitatea utilizării funcţiilor.
Utilizarea unei funcţii presupune mai întâi declararea şi apoi definirea sa.
Declararea funcţiei este obligatorie dacă funcţia este utilizată înainte de definirea
sa. O altă posibilitate este de a defini funcţia înainte de utilizarea sa, evitând
astfel o declarare a prototipului acesteia.
Prin declarare, sunt specificate numele funcţiei, tipul valorii returnate şi
parametrii funcţiei. Dacă tipul unui parametru nu este specificat, atunci para-
metrul este de tip double în mod implicit.

1
Definirea unei funcţii are două părţi: antetul şi corpul. Antetul este acelaşi
cu prototipul folosit în declararea funcţiei, fără adăugarea unui “;” la final.
Corpul funcţiei constă într-un set de instrucţiuni cuprins între acolade { }.
În general, o funcţie este definită în modul următor:
1 t i p _ r e t u r n a t nume_functie ( t i p 1 param1 , t i p 2 param2 , . . . , tipN
paramN )
2 {
3 instructiune 1;
4 instructiune 2;
5 ....
6 instructiune n;
7 // a t e n t i e ! t i p u l v a r i a b i l e i r e t u r n a t e t r e b u i e s a f i e
8 // t i p _ r e t u r n a t
9 return valoare ;
10 }

O funcţie poate returna orice tip de dată sau pointer (de exemplu, un po-
inter către primul element al unui tablou). Returnarea unui rezultat se face
cu ajutorul sintaxei return valoare, aceasta fiind ultima intrucţiuni din corpul
funcţiei. Când funcţia nu returnează nimic, acest lucru este marcat prin tipul
void la declararea funcţiei.
tip1 param1, tip2 param2,..., tipN paramN reprezintă o listă de variabile şi
tipuri asociate acestor variabile. Variabilele din această listă primesc valori la
apelarea funcţiei. O funcţie poate să nu aibă parametrii, însă, şi în acest caz,
sunt necesare parantezele.
În interiorul unei funcţii pot fi definite şi alte variabile, numite variabile
locale. Ele sunt create la intrarea în funcţie şi vor fi distruse la momentul
ieşirii din funcţie. Singura excepţie constă în folosirea variabilelor statice (de
exemplu, static int n), care îşi păstrează valorile modificate la apelări succesive
ale funcţiei, neffind totuşi vizibile în exteriorul funcţiei.
Ca o regulă generală, o funcţie nu poate fi definită în interiorul altei funcţii.
Atunci când o funcţie se apelează pe ea însăşi, atunci funcţia se numeşte
recursivă. Pentru a evita ca o funcţie să se autoapeleze la nesfîrşit, se foloseşte
o intrucţiune condiţionată (de exemplu, if, while, do...while) care determină
ieşirea din buclă.

2.1 Funcţia main()


Funcţia main() reprezintă funcţia de bază a oricărui proiect C++ şi este definită
astfel:
1 i n t main ( i n t a r g c , c h a r ∗ a r g v [ ] )
2 {
3 ...
4 return 1;
5 }

În acest caz, funcţia returnează o valoare întreagă. Există şi posibilitatea ca


funcţia să nu returneze nimic, însă în acest caz tipul variabilei returnate este
void, şi nu int.

2
2.2 Apelul prin valoare
Un parametru poate fi transmis prin valoare unei funcţii, dar, în acest caz,
modificările care se efectuează asupra lui nu sunt păstrate la ieşirea din funcţia
respectivă.
Exemplu. Următorul program utilizează o funcţie în care apelul parame-
trilor este efectuat prin valoare. i este trasferat funcţiei prin valoare, adică x va
primi iniţial valoarea lui i, însă, după aceea, nu va mai exista nicio legătură înre
variabile. La sfârşit, i va lua valoarea 7, iar j va lua valoarea 21 (verificaţi).
1 #i n c l u d e <i o s t r e a m >
2 u s i n g namespace s t d ;
3
4 int triplu ( int x)
5 {
6 x = x∗3;
7 return x ;
8 }
9
10 i n t main ( )
11 {
12 i =7;
13 int j = triplu ( i )
14 }

2.3 Apelul prin referinţă


Dacă un parametru este transmis prin referinţă, funcţia va avea acces la adresa
acestui argument şi, astfel, modificările efectuate asupra parametrului vor fi
păstrate şi la ieşirea din funcţie.
Exemplu. Următorul program utilizează o funcţie în care apelul parame-
trilor este efectuat prin referinţă. În acest exemplu, x reprezintă un alias pentru
variabila i din functia main(). După apelarea funcţiei triplu, i şi j vor avea
ambele valoarea 21 (verificaţi).
1 #i n c l u d e <i o s t r e a m >
2 u s i n g namespace s t d ;
3
4 i n t t r i p l u ( i n t& x )
5 { // o b s e r v a t i ampersand−u l de mai s u s
6 x = x∗3;
7 return x ;
8 }
9
10 i n t main ( )
11 {
12 i =7;
13 int j = triplu ( i )
14 }

2.4 Pointeri către funcţii


Un pointer poate fi definit folosind următoarea sintaxă:

3
1 t i p _ r e t u r n a t ( ∗ nume_functie ) ( t i p 1 param1 , t i p 2 param2 , . . . , tipN
paramN ) ;

Pointerii la funcţii funcţionează pe acelaşi principiu ca şi pointerii la orice alt


tip de date. Pentru a accesa adresa din memorie asociată funcţiei se foloseşte
operatorul &.
Exemplu. Următorul program utilizează pointeri către funcţii.
1 #i n c l u d e <i o s t r e a m >
2 u s i n g namespace s t d ;
3
4 /∗ Definim doua f u n c t i i cu d o i p a r a m e t r i
5 de t i p i n t s i c a r e r e t u r n e a z a v o i d . ∗/
6 void o_functie ( i n t a , i n t b)
7 {
8 p r i n t f ( "Eu s u n t o f u n c t i e cu d o i p a r a m e t r i de t i p i n t : %d s i %
d . \ n" , a , b ) ;
9 }
10
11 i n t main ( v o i d )
12 {
13 /∗ Definim un p o i n t e r l a f u n c t i i cu d o i p a r a m e t r i de t i p i n t
14 s i care returneaza void .
15 Numele p a r a m e t r i l o r nu e s t e r e l e v a n t , c o n t e a z a doar t i p u l
lor .
16 O b s e r v a t i ca a i c i am s c r i s "y" s i " z " , i a r l a f u n c t i i am
scris
17 " a " s i "b " , r e s p e c t i v " c " s i "d " . ∗/
18 v o i d ( ∗ un_pointer ) ( i n t y , i n t z ) ;
19
20 /∗ Atribuim p o i n t e r u l u i a d r e s a p r i m e i f u n c t i i . ∗/
21 un_pointer = &o _ f u n c t i e ;
22
23 /∗ Invocam prima f u n c t i e d i r e c t . ∗/
24 o_functie (11 , 22) ;
25
26 /∗ Invocam prima f u n c t i e p r i n i n t e r m e d i u l p o i n t e r u l u i .
27 I n l o c de numele f u n c t i e i f o l o s i m o p e r a t o r u l ∗ .
28 F o l o s i m p a r a n t e z e p e n t r u a ne a s i g u r a de o r d i n e a o p e r a t i i l o r
. ∗/
29 ( ∗ un_pointer ) ( 1 2 , 2 3 ) ;
30
31 /∗ Atribuim p o i n t e r u l u i a d r e s a c e l e i de−a doua f u n c t i i . ∗/
32 un_pointer = &a l t a _ f u n c t i e ;
33
34 return 0;
35 }

2.5 Asamblarea fişierelor în proiecte


Funcţiile pot fi definite fie împreună cu funcţia main() din proiect într-un singur
fişier, fie în fişiere separate. Acest lucru este dorit în special în cazul progra-
melor mai mari pentru a reduce timpul de depistare a eventualelor erori, dar şi
pentru o mai bună vizualizare şi separare a codului. Pentru a adauga noi fişiere

4
proiectului C++, se face click dreapta pe folderul Source şi se selectează Add
item....
În cel de-al doilea caz, este necesară includerea unui fişier în cadrul celuilalt
fişier în care este folosită funcţia din primul fişier. Acest lucru se face prin:
1 # include " f i s i e r " ;

2.6 Funcţii cu un număr variabil de parametrii


Limbajul C++ ne permite să scriem funcţii cu un număr variabil de parametri.
Totuşi câteva restricţii există, şi anume:
• primul parametru trebuie să apară obligatoriu în lista de parametri
• pentru parametri variabili, antetul va conţine “...”:
1 int functie ( int n , ...)

Parametri vor fi înscrişi în stiva de memorie, la adrese de succesive. Acest


lucru este arătat în exemplul următor.
Exemplu. Programul următor conţine o funcţie ce calculează suma pa-
rametrilor variabili care apar în antet. Parametru fix (primul parametru) va
indica numărul de elemente pentru care se calculează suma.
1 #i n c l u d e <i o s t r e a m >
2 u s i n g namespace s t d ;
3
4 i n t suma ( i n t n , . . . )
5 {
6 int s = 0;
7 f o r ( i n t i = 0 ; i < n ; i ++)
8 {
9 s += ∗(&n+i ) ;
10 /∗ &n+i e s t e a d r e s a l u i n l a c a r e s e adauga i p a s i i n s t i v a de
memorie . C o n t i n u t u l i n f o r m a t i o n a l de l a a c e a a d r e s a e s t e
adaugat i n v a r i a b i l a s , c a r e s t o c h e a z a suma p a r a m e t r i l o r . ∗/
11 }
12 return s ;
13 }
14
15 i n t main ( )
16 {
17 p r i n t f ( "Suma e s t e : %d \n" , suma ( 3 , 1 , 2 , 4 ) ) ;
18 p r i n t f ( "Suma e s t e : %d \n" , suma ( 5 , 1 , 2 , 4 , 3 , 2 ) ) ;
19 system ( " pause " ) ;
20 return 0;
21 }

2.7 Supraîncărcarea funcţiilor


În C++, există posibilitatea ca mai multe funcţii să poarte acelaşi nume, di-
ferenţierea lor fiind făcută cu ajutorul numărului de parametri sau al tipului
parametrilor folosiţi. Un exemplu în acest sens este dat mai jos.

5
1
2 #i n c l u d e <i o s t r e a m >
3
4 void f u n c t i a ( i n t n)
5 {
6 p r i n t f ( "Eu s u n t f u n c t i a cu un parametru de t i p i n t \n" ) ;
7 }
8
9 v o i d f u n c t i a ( i n t m, i n t n )
10 {
11 p r i n t f ( "Eu s u n t f u n c t i a cu d o i p a r a m e t r i de t i p i n t \n" ) ;
12 }
13
14 v o i d f u n c t i a ( i n t ∗n )
15 {
16 p r i n t f ( "Eu s u n t f u n c t i a cu un parametru de t i p i n t ∗ \n" ) ;
17 }
18
19 i n t main ( )
20 {
21 int n = 2;
22 functia (2) ;
23 f u n c t i a (2 , 3) ;
24 f u n c t i a (&n ) ;
25 system ( " pause " ) ;
26 return 0;
27 }

Cu toate acestea, compilatorul nu poate face distincţie între funcţii cu pa-


rametri pentru care conversia se poate face explicit. De exemplu:
1 void f u n c t i a ( i n t n)
2 {
3 p r i n t f ( "Eu s u n t f u n c t i a cu un parametru de t i p i n t \n" ) ;
4 }
5

1 void f u n c t i a ( f l o a t n)
2 {
3 p r i n t f ( "Eu s u n t f u n c t i a cu un parametru de t i p f l o a t \n" ) ;
4 }
5

Pentru moment, supraîncarcarea funcţiilor poate nu este esenţială, însă rolul


ei devine extrem de important mai târziu, în cazul programării orientate pe
obiect, mecanism studiat în semestrul următor.

3 Probleme rezolvate
1. Calculul expresiilor Se citeşte numărul natural n. Să se scrie progra-
mele care tipăresc valoarea calculată a expresiilor:
1 1 1
E1 = 1 + + + ... +
2 3 n

6
 n
1 1 1
E2 = 1 + + + ... +
2 3 n

Soluţie: În primul rând, se observă că cea de-a doua expresie se obţine


din prima prin ridicarea la puterea n, E2 = E1n . Din acest motiv, putem
calcula prima expresie folosind un subprogram care are ca parametru de
intrare, variabila n, în timp ce pentru a calcula cea de-a doua expresie
putem folosi direct rezultatul anterior.
1 #i n c l u d e <i o s t r e a m >
2 #i n c l u d e <s t r i n g >
3
4 u s i n g namespace s t d ;
5
6 d o u b l e E1 ( i n t n )
7 {
8 double s = 0 . 0 ;
9 f o r ( i n t i = 1 ; i <= n ; i ++)
10 s += 1 . 0 / i ;
11 return s ;
12 }
13
14 d o u b l e E2 ( d o u b l e e1 , i n t n )
15 {
16 d o u b l e prod = 1 . 0 ;
17 f o r ( i n t i = 1 ; i <= n ; i ++)
18 prod ∗= e1 ;
19 r e t u r n prod ;
20 }
21
22 i n t main ( )
23 {
24 int n;
25 d o u b l e e1 ;
26
27 c o u t << " I n t r o d u c e t i un numar n a t u r a l : " ;
28 c i n >> n ;
29
30 e1 = E1 ( n ) ;
31
32 c o u t << " E x p r e s i a 1 e s t e e g a l a cu : " << e1 << e n d l ;
33 c o u t << " E x p r e s i a 2 e s t e e g a l a cu : " << E2 ( e1 , n ) << e n d l ;
34
35 system ( " pause " ) ;
36 return 0;
37 }

2. Suma cuburilor cifrelor


Se citeşte un număr natural n. Să se calculeze suma cuburilor cifrelor
sale. De exemplu, dacă se citeşte n = 25, se calculează 23 + 53 = 133.
Cu numărul obţinut se procedează la fel: 13 + 33 + 33 = 55. Se repetă
procedeul, formându-se o serie de numere, până se întâlneşte un număr
care deja a fost introdus în serie. În exemplul prezentat:
25 133 55 250 133

7
Soluţie: Putem calcula suma cuburilor cifrelor unui număr cu ajutorul unei
funcţii, denumita suma. Numărul n va fi memorat în prima componentă
a vectorului seria. Apoi suma cuburilor cifrelor sale vor fi memorate în a
doua componentă ş.a.m.d. După ce este calculată o nouă valoare, aceasta
este afişată şi comparată cu toate valorile reţinute anterior în şirul seria.
Dacă valoarea este regăsită, programul se opreşte.
1 # i n c l u d e <i o s t r e a m >
2 u s i n g namespace s t d ;
3
4 i n t suma ( i n t n )
5 {
6 i n t tmp , c , s = 0 ;
7 tmp = n ;
8 w h i l e ( tmp != 0 )
9 {
10 c = tmp % 1 0 ;
11 s = s + c∗c∗c ;
12 tmp = tmp / 1 0 ;
13 }
14 return s ;
15 }
16
17 i n t main ( )
18 {
19 i n t i =0 , n , s e r i a [ 4 0 0 ] ;
20 bool g a s i t = 0;
21 p r i n t f ( " C i t e s t e un numar de l a tastatura : ") ;
22 c i n >> n ;
23 seria [0] = n;
24 p r i n t f ( " \n%d" , s e r i a [ 0 ] ) ;
25 do
26 {
27 s e r i a [ i + 1 ] = suma ( s e r i a [ i ] ) ;
28 for ( int ik = 0; ik < i + 1; i k ++){
29 i f ( s e r i a [ i k ] == s e r i a [ i + 1]) gasit = 1;
30 }
31 p r i n t f ( " %d" , s e r i a [ i + 1 ] ) ;
32 i = i + 1;
33 } w h i l e ( g a s i t != 1 ) ;
34
35 system ( " pause " ) ;
36 return 0;
37 }

3. Triunghi special
Se citesc 2 numere naturale m şi n, mai mici decât 10. Să se scrie un
program care afişează un triunghi, după regulile următoare:

• m = 6; n = 1
1
23
456
7891

8
23456
789123
• m = 7; n = 9
9
12
345
6789
12345
678912
3456789

Soluţie: Problema este de a număra începând de la n până la 9, dacă


această valoare este depăşită numărătoarea reporneşte de la 1. Numărul
de linii ale triunghiului este dat de m. Pentru a rezolva problema se vor
folosi două funcţii, una calculează elementul următor (urmatorul), iar
cealaltă va afişa triunghiul creat (triunghi) pornind de la numerele m şi
n. Funcţia triunghi conţine 2 cicluri for, unul este pentru numărătoare,
celălalt este pentru a contoriza numărul de linii ale triunghiului.
1 #i n c l u d e <i o s t r e a m >
2 u s i n g namespace s t d ;
3
4 i n t urmatorul ( i n t x )
5 {
6 int y ;
7 y = ( x+1) % 1 0 ;
8 i f ( y == 0 ) r e t u r n y +1;
9 e l s e return y ;
10 }
11
12 v o i d t r i u n g h i ( i n t m, i n t n )
13 {
14 int s = n;
15 f o r ( i n t i = 0 ; i < m+1; i ++)
16 {
17 f o r ( i n t j = 0 ; j < i ; j ++)
18 {
19 p r i n t f ( "%d " , s ) ;
20 s = urmatorul ( s ) ;
21 }
22 p r i n t f ( " \n" ) ;
23 }
24
25 }
26
27 i n t main ( )
28 {
29 i n t m, n ;
30 p r i n t f ( "m = " ) ;
31 c i n >> m;
32 p r i n t f ( "n = " ) ;
33 c i n >> n ;
34

9
35 t r i u n g h i (m, n ) ;
36
37 system ( " pause " ) ;
38 return 0;
39 }

4 Probleme propuse
1. Să se scrie un program care tipăreşte numerele întregi găsite între două
valori citire de la tastatură care se divid la suma cifrelor lor. Programul
va utiliza o funcţie care returnează suma cifrelor unui număr întreg primit
ca parametru.
2. Să se scrie o funcţie care returnează ultima cifră a unui număr întreg citit
de la tastatură.
3. Să se scrie un program care permută două linii i şi j ale unei matrice.
Programul se va realiza astfel:
• se scrie o funcţie pentru citirea de la tastatură a unei matrice;
• se scrie o funcţie pentru afişarea unei matrice;
• se scrie o funcţie care permută două linii;
• funcţia main() rezultă din apelul funcţilor de mai sus.
4. Să se scrie un program care calculeaza transpusa unei matrice. Programul
se va realiza astfel:
• se scrie o funcţie pentru citirea de la tastatură a unei matrice;
• se scrie o funcţie pentru afişarea unei matrice;
• se scrie o funcţie care calculează transpunsa unei matrice;
• funcţia main() rezultă din apelul funcţilor de mai sus.
5. Să se citească două matrice şi să se facă suma lor. Programul se va realiza
astfel:
• se scrie o funcţie de citire a unei matrice cu m linii şi n coloane;
• se scrie o funcţie de tipărire a unei matrice cu m linii şi n coloane;
• se scrie o funcţie care adună două matrice;
• funcţia main() rezultă din apelul funcţilor de mai sus.
6. Să se scrie un program care afişează valoarile maxime, pe linii, ale unei
matrice. Rezultatul va fi stocat într-un vector având lungimea dată de
numărul de linii ale matricei şi, apoi afişat pe ecran. Programul se va
realiza astfel:
• se scrie o funcţie de citire a unei matrice cu m linii şi n coloane;

10
• se scrie o funcţie de tipărire a unei vector cu m elemente;
• se scrie o funcţie care returnează minimul dintre 2 numere;
• funcţia main() rezultă din apelul funcţilor de mai sus.

11

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