Documente Academic
Documente Profesional
Documente Cultură
Problema 1: Se dau două numere naturale n și m. Să se determine suma dintre oglinditul
lui n și oglinditul lui m.
Până acum, pentru a rezolva această problemă, trebuia să determinăm, folosind două secvențe
de program aproape identice, oglinditele celor două numere, iar apoi să facem suma. O
soluție mai simplă este să construim un subprogram care determină oglinditul unui număr
natural oarecare, să-l apelăm de două ori pentru a determina oglinditul lui n și al lui m, apoi
să facem suma rezultatelor.
Putem rezolva această problemă, în mai multe moduri, folosind cunoștințe pe care le avem
deja. Dacă dorim să o rezolvăm folosind subprograme, vom construi trei subprograme:
Astfel, programul care rezolvă problema constă în apelul celor trei subprograme, în odinea
potrivită. Am reușit să descompunem rezolvarea unei probleme complexe în mai multe
subprobleme, mai simple, care pot fi rezolvate de mai multe persoane, dacă este cazul.
În limbajul C/C++, există doar subprograme de tip funcție. Pentru proceduri se folosește o
formă particulară a funcțiilor.
#include <iostream>
using namespace std;
int ogl(int x)
{
int r = 0;
do
{
r = 10 * r + x % 10;
x /= 10;
}
while(x != 0);
return r;
}
int main(){
int n , m;
cin >> n >> m;
cout << ogl(n) + ogl(m);
return 0;
}
Funcția care calculează oglinditul unui număr este int ogl(int x).
int main(){
int k, v[1005];
citire(k , v);
sortare(k , v);
afisare(k , v);
return 0;
}
Față de cele de mai sus, putem observa următoarele:
void F(){
cout << "Salut";
}
int main(){
F();
return 0;
}
void F(){
cout << "Salut";
}
reprezintă definirea funcției F(), dar tot aici are loc și declararea. Dacă schimbăm ordinea
funcțiilor F() și main() obținem:
#include <iostream>
int main(){
F();
return 0;
}
void F(){
cout << "Salut";
}
De data aceasta programul nu mai este corect; la compilare obținem următoarea eroare:
#include <iostream>
void F();
int main(){
F();
return 0;
}
void F(){
cout << "Salut";
}
Observăm că prototipul (declararea) este o instrucțiune C++ obișnuită, care se termină cu ;!!
Declararea variabilelor
După cum știm, în C++ variabilele despre care am învățat până acum trebuie declarate și
odată cu declararea li se alocă în memorie spațiu în conformitate cu tipul lor. Întrebarea este:
“Unde putem declara variabile și prin ce diferă acestea?”.
Sistemul de operare alocă fiecărui program, în memoria RAM, trei zone în care putem
memora variabile:
zona de date
zona de stivă
zona liberă (heap)
1. clasa de memorare
2. vizibilitate
3. durata de viață
4. tipul variabilei
Vizibilitatea unei variabile precizează zona din codul sursă (liniile programului C++) unde
se poate folosi respectiva variabilă și poate fi:
Durata de viață reprezintă timpul în care variabilei îi este alocat spațiu în memorie și poate
fi:
durată statică – variabila are alocat spațiu pe tot parcursul execuției programului
durata locală – variabila are alocat spațiu numai pe parcursul execuției instrucțiunilor
dintr-un bloc
durata dinamică – variabila se creează (i se alocă spațiu) și se distruge de către
programator, în timpul executării programului
În C++ variabile pot fi: locale, globale și dinamice. Variabile dinamice vor fi prezentate într-
un alt articol, iar cele statice și dinamice în continuare.
Variabile locale
Variabilele locale se declară într-un anumit bloc al programului, în corpul unei funcții. Fie
programul de mai jos:
#include <iostream>
using namespace std;
void F(){
int x;
x = 5;
cout << x << endl;
}
int main(){
int y = 10;
F();
cout << y << endl;
return 0;
}
Variabilele x și y declarate în programul de mai sus sunt locale. Variabila x poate fi utilizată
numai în funcție F(), iar variabila y numai în funcția main(). Mai mult, cele două variabile ar
fi putut avea același nume și nu ar fi fost nicio confuzie.
Variabile globale
Variabilele globale se declară în afara oricărei funcții. La declarare, ele sunt inițializate cu 0.
#include <iostream>
using namespace std;
int x;
void F(){
cout << x << endl;
x = 10;
}
int y;
int main(){
cout << x << " " << y << endl;
x = 5; y = 15;
F();
cout << x << " " << y << endl;
return 0;
}
În programul de mai sus variabilele x și y sunt globale. Variabila x poate fi utilizată atât în
funcția main() cât și in F(), iar variabila y numai în main().
#include <iostream>
using namespace std;
int x;
void F(){
cout << x << endl; //5, variabila globala
int x = 10;
cout << x << endl; //10, variabila locala in F()
{
int x = 20;
cout << x << endl; //20, variabila locala în F(), blocul interior
}
cout << x << endl; //10, variabila locala in F()
}
int y;
int main(){
cout << x << endl; //0, variabila globală
x = 5;
cout << x << endl; //5, variabila globala
F();
cout << x << endl; //5, variabila globala
int x = 100;
cout << x << endl; //100, variabila locala in main()
return 0;
}
Transmiterea parametrilor
Să ne amintim că parametri din antetul unei funcții se numesc parametri formali, iar cei din
apelul funcției se numesc parametri efectivi.
#include <iostream>
using namespace std;
1. numărul parametrilor formali și cel al parametrilor actuali trebuie să fie același (există
și o excepție care depășește cadrul acestui articol)
2. tipul parametrilor formali trebuie să fie același cu cel al parametrilor actuali, sau să se
poată face o conversie implicită:
o cmmdc(x , y) – parametri actuali sunt variabile de tip int
o cmmdc(x, y + 2) – un parametru actual este variabilă de tip int, celălalt este o
expresie al cărei rezultat este de tip int
o cmmdc(26 , 39) – parametri actuali sunt constante de tip int
o cmmdc(8.5 , 12.56) – parametri actuali sunt constante de tip double. Înainte de
apel valorile parametrilor actuali vor fi convertite la tipul int, apelul fiind
similar cu cmmdc(8 , 12).
3. numele parametrilor formali nu trebuie să fie aceiași cu numele parametrilor actuali
corespunzători
parametri actuali pot fi expresii ale căror valori corespund ca tip cu parametri formali
(sau pot fi convertite implicit la tipul parametrilor formali).
pe stivă se memorează valoare expresiei (sau variabilei) date ca parametru actual.
la ieșirea din apelul funcției modificările realizate în funcție asupra parametrilor
formali nu au efect asupra parametrilor actuali. Parametrii actuali sunt nemodificați!
acesta este modul implicit de transmitere a parametrilor.
Exemplu:
#include <iostream>
using namespace std;
int main(){
int x = 24, y = 18;
cout << cmmdc(x , y) << endl;
cout << "După apelul functiei cmmdc, x = " << x << " si y = " << y << endl;
return 0;
}
parametri actuali pot fi doar variabile, sau expresii ale căror rezultate sunt similare
variabilelor: elemente de tablou, câmp al unei structuri, pointer dereferențiat, etc.
pe stivă se memorează adresa variabilei date ca parametru actual.
toate modificările realizate în apelul funcției asupra parametrilor formali se fac de fapt
asupra parametrilor actuali. Parametrii actuali sunt modificați la ieșirea din apel!
pentru a preciza că un parametru este transmis prin referință va fi precedat de
caracterul & în antetul funcției.
Exemplu:
#include <iostream>
using namespace std;
int main(){
int x = 24;
cout << "x = " << x << endl;
dublare(x);
cout << "x = " << x << endl;
return 0;
}
Constatăm că, la ieșirea din apel, valoarea variabilei x este modificată. Mai mult, un apel de
forma dublare(10); reprezintă o eroare de sintaxă, deoarece parametrul actual trebuie să fie
variabilă.
Transmiterea ca parametri a tablourilor
Tablourile au un comportament special în ceea ce privește transferul parametrilor. Mai precis:
Tablourile se transmit prin valoare, dar orice modificare a valorilor elementelor tabloului dat
ca parametru formal va afecta elementul corespunzător al tabloului dat ca parametru actual.
Exemplu:
#include <iostream>
using namespace std;
int main(){
int n = 5, v[5];
for(int i = 0 ; i < n ; i ++)
v[i] = i;
afisare(n , v); // tabloul memorează {0, 1, 2, 3, 4}
transf(n, v);
afisare(n , v); // tabloul memorează {0, 2, 4, 6, 8}
return 0;
}
sau
Următoare secvență este însă greșită, deoarece a doua dimensiune a parametrului actual
(numărul de coloane) nu corespunde cu cea a parametrului formal:
Pentru exemplificare să vedem câteva variante pentru o funcție care determină oglinditul unui
număr natural, precum și modul de apelare:
Parametri de intrare – funcția are un singur parametru, de intrare, transmis prin valoare,
prin care primește un număr pentru care determină oglinditul. Rezultatul va fi returnat de
către funcție, iar apelul se va face într-o expresie.
int ogl(int n)
{
int r = 0;
while(n)
r = 10 * r + n % 10, n /= 10;
return r;
}
int main(){
int a;
cin >> a;
cout << ogl(a);
return 0;
}
Parametri de intrare ieșire – funcția are un singur parametru, transmis prin referință, prin
care primește un număr natural. Funcția determină oglinditul acestuia și îl întoarce prin
intermediul aceluiași parametru. Funcția se apelează într-o instrucțiune de sine stătătoare.