Sunteți pe pagina 1din 10

Subprograme C++

Structura unui subprogram C++


Subprogramele sunt părţi ale unui program, identificabile prin nume, care se pot activa la cerere prin
intermediul acestor nume. Prezenţa subprogramelor implică funcţionarea în strânsă legătură a două
noţiuni: definiţia unui subprogram şi apelul unui subprogram.

Definiţia unui subprogram reprezintă de fapt descrierea unui proces de calcul cu ajutorul variabilelor
virtuale (parametri formali) iar apelul unui subprogram nu este altceva decât execuţia procesului de
calcul pentru cazuri concrete (cu ajutorul parametrilor reali, (efectivi, actuali)).

Forma generală
tip_returnat nume_functie (lista_parametrilor_formali) {
instructiune; // corpul functiei
}

Item Descriere
Reprezintă tipul rezultatului calculat şi returnat de funcţie şi poate fi: int,
char, long long, float, void, etc.
În cazul în care tipul rezultatului este diferit de void, corpul funcţiei trebuie
tip_returnat
să conţină cel puţin o instrucţiune return. Înstrucţiunea return va specifica
valoarea calculată şi returnată de funcţie care trebuie să fie de acelaşi tip
ca şi tip_returnat.
Reprezintă numele dat funcţiei de către cel ce o defineşte, pentru a o putea
nume_functie
apela.
Reprezintă o listă de declaraţii de variabile separate prin virgulă. Această
lista_parametrilor_formali
listă poate să fie şi vidă.
Este o instrucţiune vidă sau o instrucţiune simplă sau o instrucţiune
intructiune
compusă.

Necesitatea folosirii subprogramelor:


 o secvenţă de instrucţiuni se repetă
 rezolvarea unei sarcini este necesară în mai multe subprograme
 descompunerea programului în module (subprobleme care se rezolvă cu subprograme)
 depanarea şi actualizarea aplicaţie se face mai uşor

Clasificarea în funcţie de modalitatea de apel


Procedura sau funcţia procedurală este subprogramul care returnează una, mai multe sau nici o
valoare. Valorile se returnează prin intermediul parametrilor. Dacă parametrii lipsesc atunci
subprogramul modifică variabile globale sau execută alte operaţii. Tipul lui este totdeauna void.

Exemplu
#include <iostream>
using namespace std;
int a;

void patrat() {
cout << a * a << endl;
}

int main() {
a = 5; patrat();
return 0;
}

1
Funcţia sau funcţia operand este un subprogram care returnează un rezultat prin chiar numele său, şi
eventual şi alte rezultate, prin intermediul parametrilor. Tipul lui este totdeauna diferit de void.

Exemplu
#include <iostream>
using namespace std;
int a;

int patrat() {
return a * a;
}

int main() {
a = 5;
cout << patrat() << endl;
cout << 5 + patrat() / 5 << endl;
return 0;
}

Apelul unei funcţii. Revenirea dintr-o funcţie


O funcţie care returnează o valoare poate fi apelată fie printr-o instrucţiune de apel simplă (cazul
funcţiilor care nu returnează valori) şi în plus poate fi apelată ca operand al unei expresii. În cazul în
care funcţia se apelază print-o instrucţiune de apel simplă, rezultatul funcţiei se pierde. Când funcţia se
apelează ca operand, valoarea returnată va fi utilizată în expresie.

În momentul în care se întâlneşte un apel de funcţie, controlul execuţiei programul este transferat
primei instrucţiuni din funcţie, urmând a se executa secvenţial instrucţiunile funcţiei.

Revenirea dintr-o funcţie se face în unul din următoarele cazuri:


 după execuţia ultimei instrucţiuni din corpul funcţiei
 la întâlnirea unei instrucţiuni return

Exemplu
#include <iostream>
using namespace std;
int a;

int patrat() {
a = a * 2;
cout << a << endl;
return a * a;
}

int main() {
a = 5;
patrat();
cout << patrat() << endl;
return 0;
}

Explicaţie: primul apel afişează 10 da nu mai returnează 100, al doilea apel afişează atât 20 cât
returnează şi 400.

Elementele unui subprogram. Prototipul unui subprogram


Un subprogram se compune din următoarele părţi:
 antetul funcţiei (subprogramului)
 partea declarativă (declarările variabilelor locale)
 partea executabilă sau procedurală (secvenţa de instrucţiuni pe care le execută)

2
În limbajul C++ există trei elemente implicate în utilizarea unui subprogram:
 prototipul subprogramului
 apelul subprogramului
 definiţia subprogramului

Exemplu
#include <iostream>
using namespace std;
int n;
void scrie(); //prototipul subprogramului

int main() {
n = 10;
scrie(); //apelul subprogramului
return 0;
}

//definitia subprogramului
void scrie() { //antetul subprogramului
int i; //partea declarativa
//partea executabila
for (i = 0; i < n; i++)
cout << i << " ";
cout << endl;
}

Explicaţie: prototipul subprogramului se foloseşte pentru declarea acestuia, desigur acesta poate lipsii
dacă este declarată în faţa modului care o apelează, în cazul de faţă programul pricipal.

Variabile locale şi variabile globale


În C++, numele de funţie main determină prima instrucţiune pe care o va executa programul. Acesta
este unica diferenţă dintre main şi celelalte funcţii.

La fel cum se declară variabilele în cadrul funcţiei main, la fel se pot declara varibile în cadrul celorlalte
funcţii. Aceste variabile se numesc locale şi sunt accesibile doar de funcţia care le-a declarat. La fel în
cadrul unei funcţii se pot apela şi alte funcţii, ca şi în main, dacă acestea au fost definite înaintea
eventualului apel sau dacă este prezent un prototip de funcţie înaintea funcţiei apelante şi o definiţie de
funcţie în cadrul programului respectiv sau în fişierele incluse în programului respectiv.

Variabilele globale sunt declarate înafara oricărei funcţii şi pot sunt vizibile (pot fi utilizate) în tot
programul (în programul principal şi în subprograme) din momentul declarării lor.

Exemplu
#include <iostream>
using namespace std;
int n; //variabila globala
void f() {
int x = 5; //variabila locala
n = 10; //variabila globala poate fi accesata din orice subprogram
cout << n << endl;
cout << x << endl;
}

int main() {
n = 5;
f();
cout << x << endl; //gresala, variabila locala este vizibila doar in functia f
return 0;
}

3
Regula de omonimie
În cazul în care există o variabilă locală care are acelaşi nume cu o variabilă globală, aceste două
variabile se numesc variabile omonime. Variabilele locale sunt prioritare (ascund) variabilele globale
omonime.

Variabilelor globale li se rezervă spaţiu de memorare la începutul execuţiei programului, într-o zonă de
memorie numită „zonă de date”. Acest spaţiu va fi ocupat până la încheierea execuţiei programului.

Variabilelor locale li se rezervă spaţiu într-o zonă specială de memorie numită „stiva”. La încheierea
execuţiei subprogramului, conţinutul stivei este eliberat. Din acest motiv, variabilele locale sunt vizibile
doar în interiorul subprogramului în care au fost declarate.

Exemplu
#include <iostream>
using namespace std;
int n = 10; //variabila globala

void f() {
int n = 5; //variabila locala
cout << n << endl;
}

int main() {
f();
cout << n << endl;
return 0;
}

Parametri formali şi parametri actuali


Parametrii formali şi actuali se numesc şi parametrii de comunicare.

Parametri formali apar în antetul subprogramului şi sunt utilizaţi de subprogram pentru descrierea
abstractă a unui proces de calcul.

Parametri actuali apar în instrucţiunea de apelare a unui subprogram şi sunt folosiţi la execuţia unui
proces de calcul pentru valori concrete. La activarea subprogramului parametrilor de comunicare se vor
atribui valori concrete cu care se va executa subprogramul la acel apel. Comunicarea trebuie să
respecte aceeaşi succesiune, tipuri de date şi numări de parametrii ca şi în lista de parametrilor
formali! Aceasta este regula de corespondenţă.

Observaţii:
 numărul parametrilor formali poate să fie diferit de numărul parametrilor actuali în două cazuri:
funcţii cu număr variabil de parametrii şi supraîncărcarea funcţiilor
 tipul parametrilor formali poate să fie diferit de tipul parametrilor actuali în două cazuri: când
parametrii efectivi pot fi convertiţi în tipul parametrilor formali şi în cazul supraîncărcării
funcţiilor
 numele parametrilor formali poate să fie diferit de numele parametrilor actuali

Apel prin valoare si prin referinţă


Apel prin valoare
Valorile transmise la apelul unui subprogram sunt memorate în stivă. Datorită faptului că, după
terminarea execuţiei unui subprogram, stiva este eliberată, în cazul apelului prin valoare parametrul
actual nu se modifică (se operează asupra unei copii a parametrului efectiv) Aceste transfer se
foloseşte numai pentru parametrii de intrare, pentru că valoarea acestei variabile se poate modifica în
subprogram, dar această modificare nu se va reflecta şi în modulul apelant.

4
Exemplu
int prim(int x) {
int nr_div = 0;
if (x == 1)
nr_div = 1;
for (int i = 2; i * i <= x; i++)
if (x % i == 0)
nr_div++;
if (nr_div == 0)
return 1;
else
return 0;
}

Explicaţie: prin parametrul formal putem transmite o valore subprogramului, care va returna valoarea
1, dacă această valoare este număr prim respectiv 0 în caz contrar.

Exemplu
int prim(int x) {
if (x == 1)
return 0;
for (int i = 2; i * i <= x; i++)
if (x % i == 0)
return 0;
return 1;
}

Explicaţie: în cazul în care se întâlneşte un divizor a lui x sau x=1 se execută instrucţiunea return 0.
Astfel apelul funcţiei se încheie. Dacă x este număr prim, instrucţiunea return 0 nu se execută
niciodată şi în acest caz, după terminarea execuţiei instrucţiunii for, se execută instrucţiunea return 1
(care determină încheierea execuţiei funcţiei).

Apel prin referinţă


În cazul apelului prin referinţă, subprogramul, cunoscând adresa parametrului actual, acţionează direct
asupra locaţiei de memorie indicată de aceasta, modificând valoarea parametrului actual. În C++,
implicit apelul este prin valoare. Pentru a specifica un apel prin referinţă, în lista parametrilor formali,
numele parametrului formal va trebui precedat de simbolul &, operatorul de adresare.

Exemplu
#include <iostream>
using namespace std;
int x, y;

void schimba1(int a, int b) {


int aux = a;
a = b;
b = aux;
}

void schimba2(int &a, int &b) {


int aux = a;
a = b;
b = aux;
}

int main() {
x = 5; y = 10; schimba1(x, y);
cout << x << y << endl; //se va afisa 5 si 10
schimba2(x, y);
cout << x << y << endl; //se va afisa 10 si 5
return 0;
}

Explicaţie: în cazul funcţiei schimba2 a si b sunt parametrii de intrare-iesire în care se preiau adresele
variabilelor globale x si y, deci subprogramul prin variabilele a si b, de fapt are acces la x si y.
5
Exemplu apel prin valoare si prin referinţă
Cu toate că se recomandă folosirea funcţiilor operand atunci când subprogramul furnizează un singur
rezultat, respectiv folosirea funcţiilor procedurale atunci când subprogramul nu furnizează un rezultat
sau furnizează mai multe (prin internediul parametrilor), maioritatea problemelor se pot rezolva si cu
funcţii (apel prin valoare) cât si cu proceduri (apel prin referinţă).

Enunţ problemă: Să se calculeze valoarea combinărilor definite astfel: C(n,k)=n!/(k!*(n-k)!).

Exemplu: fără subprogram


#include <iostream>
using namespace std;
long long p1, p2, p3;
int n, k, i;

int main() {
cin >> n >> k;
p1 = p2 = p3 = 1;
for (i = 1; i <= n; i++)
p1 *= i;
for (i = 1; i <= k; i++)
p2 *= i;
for (i = 1; i <= n - k; i++)
p3 *= i;
cout << p1 / (p2 * p3) << endl;
return 0;
}

Exemplu: cu subprogram procedural


#include <iostream>
using namespace std;
long long p1, p2, p3;
int n, k;

void fact(int n, long long &p) {


p = 1;
for (int i = 1; i <= n; i++)
p *= i;
}

int main() {
cin >> n >> k;
fact(n, p1); fact(k, p2); fact(n - k, p3);
cout << p1 / (p2 * p3) << endl;
return 0;
}

Exemplu: cu subprogram tip funcţie operand


#include <iostream>
using namespace std;
int n, k;

long long fact(int n) {


long long p = 1;
for (int i = 1; i <= n; i++)
p *= i;
return p;
}
int main() {
cin >> n >> k;
cout << fact(n) / (fact(k) * fact(n - k)) << endl;
return 0;
}

6
Supraîncărcarea funcţiilor
Limbajul C++ permite folosirea în acelasi program a mai multor funcţii cu acelasi nume.

Când două functii au acelasi nume atunci ele trebuie să se deosebească prin:
 număr diferit de parametri
 în cazul când functiile au acelasi număr de parametri, acestia trebuie să fie de tipuri diferite

Folosind subproramele fact definite anterior putem construi următorul program, prima variantă
returnează void si are două parametrii (primul de tip int transmis prin valoarea, iar cea dea doua de tip
long long transmis prin referinţă), iar cea dea doua returnează long long si are un singur parametru de
tip int (transmis prin valoare):

Exemplu
#include <iostream>
using namespace std;
long long p1, p2, p3;
int n, k;

void fact(int n, long long &p) {


p = 1;
for (int i = 1; i <= n; i++)
p *= i;
}

long long fact(int n) {


long long p = 1;
for (int i = 1; i <= n; i++)
p *= i;
return p;
}

int main() {
cin >> n >> k;
fact(n, p1); fact(k, p2); fact(n - k, p3);
cout << p1 / (p2 * p3) << endl;
cout << fact(n) / (fact(k) * fact(n - k)) << endl;
return 0;
}

Tablourile de memorie și subprogramele


În limbajul C++ numele unui tablou reprezintă adresa primului element din tablou, celelalte elemente
fiind memorate la adresele următoare de memorie. Din acest motiv, în cazul transmiterii unui tablou
unei funcţii se transmite de fapt o adresă, realizându-se un apel numit pointer care determină
modificarea parametrului actual.

Exemplu
void generare(int x, int v[]) {
for (int i = 1; i <= x; i++)
v[i] = rand();
}

Atunci când transmiteti o matrice ca parmetru nu trebuie să precizati numărul de rânduri, dar trebuie
să precizaţi numărul de coloane.

Exemplu
void generare(int x, int w[][50]) {
for (int i = 0; i < x; i++)
for (int j = 0; j < x; j++)
w[i][j] = rand();
}

7
Explicaţie: functia rand() generează un număr pseudoaleator între 0 si RAND_MAX (32767). Atunci
când transmitem un vector ca parametru este posibil să nu precizăm lungimea lui, parantezele pătrate
care urmează numele vectorului sunt suficiente.

Exemplu
#include <iostream>
#include <cstdlib>
using namespace std;
int a[100], n;
void generare(int x, int v[100]) {
for (int i = 1; i <= x; i++)
v[i] = rand();
}

void afisare(int x, int v[100]) {


for (int i = 1; i <= x; i++)
cout << v[i] << " ";
cout << endl;
}

int main() {
cin >> n;
generare(n, a);
afisare(n, a);
return 0;
}

Subprograme de sistem
Funcţia rand()
Funcţia rand() generează un număr pseudoaleator între 0 si RAND_MAX (32767). Pentru utilizarea ei
trebuie să includem fişierul antet <cstdlib>. Dacă dorim să generăm numere într-un interval dat
trebuie să folosim operatorul %.

Exemplu
void generare(int x, int a, int b, int w[]) {
for (int i = 0; i < x; i++)
w[i] = a + rand() % (b – a + 1);
}

void generare(int x, int a, int w[]) {


for (int i = 0; i < x; i++)
w[i] = -rand() % (a + 1) + rand() % (a + 1);
}

Explicaţie: prima procedură generează un vector cu x elemente (numere naturale) în intervalul [a, b],
a doua procedură generează un vector cu x elemente (numere întregi) în intervalul [-a, a].

Funcţia srand()
Ca generarea numerelor să pară si mai aleatoare recomandăm folosirea funcţiei srand() înaintea
folosirii lui rand(). Pentru utilizarea ei împreună cu functia time trebuie să includem <ctime>.

Exemplu
void generare(int x, int a, int b, int w[]) {
srand(time(NULL));
for (int i = 0; i < x; i++)
w[i] = a + rand() % (b – a + 1);
}

8
Funcţia sqrt()
Funcţia sqrt() extrage radicalul dintr-un număr dat de tip double, returnând tot un număr de tip
double. Pentru utilizarea ei trebuie să includem fişierul antet <cmath>.

Funcţia pow()
Funcţia pow() ridică un un număr dat de tip double, la putera dată, tot un număr de tip double,
returnând un număr de tip double. Pentru utilizarea ei trebuie să includem fişierul antet <cmath>.
Prototipul funcţie este: double pow(double baza, double exponent).

Funcţia abs()
Funcţia abs() returnază un număr de tip int reprezentând valoare absolută (modulul) numărului întreg
transmis prin parametru. Pentru utilizarea ei trebuie să includem fişierul antet <cmath>. Prototipul
funcţie este: int abs(int numar).

Exemplu
#include <iostream>
#include <cmath>
using namespace std;
int n;
double x;

int main() {
n = 81;
cout << sqrt(n) << endl;
x = pow(45.89, 2);
cout << sqrt(x) << endl;
cout << sqrt(abs(4-20)) << endl;
return 0;
}

Funcţia ceil()
Funcţia ceil() returnază cel mai mic număr „întreg” care este mai mare ca numărul transmis prin
parametru. Necesită fişierul antet <cmath>. Prototipul funcţiei este: double ceil(double nr).

Funcţia floor()
Funcţia floor() returnază cel mai mare număr întreg care este mai mic ca numărul transmis prin
parametru. Necesită fişierul antet <cmath>. Prototipul funcţiei este: double floor(double nr).

Exemplu
#include <iostream>
#include <cmath>
using namespace std;
double x;

int main() {
x = 6.04;
cout << ceil(x) << endl; //afiseaza 7
x = 7.00;
cout << ceil(x) << endl; //afiseaza 7
x = 6.04;
cout << floor(x) << endl; //afiseaza 6
x = 7.00;
cout << floor(x) << endl; //afiseaza 7
return 0;
}

9
Conţinut
Structura unui subprogram C++ .................................................................................... 1
Clasificarea în funcţie de modalitatea de apel................................................................... 1
Apelul unei funcţii. Revenirea dintr-o funcţie .................................................................... 2
Elementele unui subprogram. Prototipul unui subprogram ................................................. 2
Variabile locale şi variabile globale ................................................................................. 3
Regula de omonimie ..................................................................................................... 4
Parametri formali şi parametri actuali ............................................................................. 4
Apel prin valoare si prin referinţă ................................................................................... 4
Apel prin valoare ....................................................................................................... 4
Apel prin referinţă ..................................................................................................... 5
Exemplu apel prin valoare si prin referinţă .................................................................... 6
Supraîncărcarea funcţiilor .............................................................................................. 7
Tablourile de memorie si subprogramele ......................................................................... 7
Subprograme de sistem ................................................................................................ 8
Funcţia rand() ........................................................................................................... 8
Funcţia srand() ......................................................................................................... 8
Funcţia sqrt() ............................................................................................................ 9
Funcţia pow() ........................................................................................................... 9
Funcţia abs() ............................................................................................................ 9
Funcţia ceil() ............................................................................................................ 9
Funcţia floor() ........................................................................................................... 9

10

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