Funcții - noțiuni de bază
Până acum, tot codul nostru a fost scris în funcția main(). Dar pe măsură ce programele devin mai complexe, avem nevoie să împărțim codul în bucăți mai mici, fiecare cu un rol clar.
Aceste bucăți se numesc funcții (sau subprograme).
De ce avem nevoie de funcții?
Imaginează-ți că ai un program care verifică dacă un număr e prim în 5 locuri diferite. Fără funcții, copiezi aceleași 10 linii de 5 ori. Cu funcții, le scrii o singură dată și le apelezi de câte ori vrei.
Funcțiile ne ajută să:
- Evităm repetarea codului
- Organizăm programul în bucăți logice
- Testăm fiecare parte separat
- Citim codul mai ușor
Primul exemplu
#include <iostream>
using namespace std;
void salut() {
cout << "Buna ziua!" << endl;
}
int main()
{
salut();
salut();
salut();
return 0;
}Output:
Buna ziua!
Buna ziua!
Buna ziua!Ce se întâmplă?
- Am definit funcția
salut()- un bloc de cod cu un nume. - În
main(), am apelat funcția de 3 ori. - La fiecare apel, programul “sare” la codul funcției, îl execută, apoi revine.
Structura unei funcții
tip_returnat nume_functie(parametri) {
// corpul funcției
}
| Parte | Ce înseamnă |
|---|---|
tip_returnat |
Ce tip de valoare returnează funcția (void dacă nu returnează nimic) |
nume_functie |
Numele pe care îl alegem (ca la variabile) |
parametri |
Datele pe care le primește funcția (opțional) |
corpul |
Instrucțiunile care se execută la apel |
Funcții void (fără valoare returnată)
O funcție void face ceva dar nu întoarce un rezultat. E ca un ordin: “afișează asta”, “desenează aia”.
void afiseazaLinie() {
cout << "-------------------" << endl;
}
int main()
{
afiseazaLinie();
cout << "Titlu" << endl;
afiseazaLinie();
return 0;
}Output:
-------------------
Titlu
-------------------Funcții cu parametri
Parametrii sunt datele pe care le trimitem funcției. Funcția le folosește în corpul ei.
void afiseazaNume(char nume[]) {
cout << "Salut, " << nume << "!" << endl;
}
int main()
{
afiseazaNume("Ana");
afiseazaNume("Mihai");
afiseazaNume("Elena");
return 0;
}Output:
Salut, Ana!
Salut, Mihai!
Salut, Elena!Mai mulți parametri
void afiseazaSuma(int a, int b) {
cout << a << " + " << b << " = " << a + b << endl;
}
int main()
{
afiseazaSuma(3, 5);
afiseazaSuma(10, 20);
return 0;
}Output:
3 + 5 = 8
10 + 20 = 30Funcții care returnează o valoare
O funcție poate calcula ceva și întoarce rezultatul cu return.
int dublu(int x) {
return x * 2;
}
int main()
{
int a = dublu(5);
cout << a << endl;
cout << dublu(13) << endl;
return 0;
}Output:
10
26Cum funcționează return?
return valoare;oprește funcția și trimitevaloareînapoi la locul apelului.- Tipul valorii trebuie să corespundă cu tipul declarat al funcției (
intreturneazăint).
int maxim(int a, int b) {
if (a > b)
return a;
else
return b;
}
int main()
{
cout << maxim(7, 12) << endl;
cout << maxim(100, 3) << endl;
return 0;
}Output:
12
100Funcții care returnează bool
Foarte utile pentru verificări:
bool estePar(int n) {
if (n % 2 == 0)
return true;
else
return false;
}
int main()
{
if (estePar(8))
cout << "8 este par" << endl;
if (!estePar(7))
cout << "7 nu este par" << endl;
return 0;
}Output:
8 este par
7 nu este parPrescurtare: funcția estePar se poate scrie și return n % 2 == 0; - expresia n % 2 == 0 este deja true sau false.
Ordinea în program
Funcțiile trebuie definite înainte de a fi apelate. De obicei le punem deasupra lui main():
#include <iostream>
using namespace std;
// Funcțiile aici, deasupra lui main
int patrat(int x) {
return x * x;
}
int main()
{
cout << patrat(5);
return 0;
}Declarare vs Definire
Alternativ, putem pune doar declarația (prototipul) deasupra și definiția dedesubt:
int patrat(int x); // declarație (prototip)
int main()
{
cout << patrat(5);
return 0;
}
int patrat(int x) { // definiție
return x * x;
}Ambele variante sunt corecte. La concursuri, cel mai simplu e să pui funcțiile deasupra lui main.
Exemplu complet: verificare număr prim
#include <fstream>
using namespace std;
ifstream fin("date.in");
ofstream fout("date.out");
bool estePrim(int n) {
if (n < 2) return false;
for (int d = 2; d * d <= n; d++) {
if (n % d == 0) return false;
}
return true;
}
int main()
{
int n;
fin >> n;
for (int i = 2; i <= n; i++) {
if (estePrim(i))
fout << i << " ";
}
return 0;
}date.in:
30date.out:
2 3 5 7 11 13 17 19 23 29Funcția estePrim ascunde complexitatea verificării. main rămâne curat și ușor de citit.
Greșeli frecvente
1. Apelarea funcției fără paranteze
salut; // GREȘIT - nu apelează funcția
salut(); // CORECT2. Uitarea lui return într-o funcție non-void
int dublu(int x) {
int rez = x * 2;
// lipsește: return rez;
}Funcția nu întoarce nimic - rezultatul e imprevizibil.
3. Tipul parametrilor nu corespunde
int suma(int a, int b) { return a + b; }
suma(3.5, 2.1); // trimitem double, funcția așteaptă int - se pierd zecimalele4. Funcția definită după main()
int main()
{
salut(); // EROARE - salut nu e definit încă
return 0;
}
void salut() { cout << "Salut"; }Pune funcțiile deasupra lui main.
Ce să reții
- O funcție este un bloc de cod cu un nume, pe care îl putem apela de mai multe ori.
void- funcție care nu returnează nimic.return- trimite o valoare înapoi la locul apelului.- Parametrii sunt datele pe care funcția le primește.
- Funcțiile se definesc deasupra lui
main(). - Cu funcții, codul devine mai curat, mai organizat și mai ușor de citit.