Declarare, definire și apelul funcțiilor
O funcție este ca o rețetă: o scriem o singură dată și o putem folosi (apela) de ori câte ori vrem. Are ingrediente (parametri de intrare) și produce un rezultat (valoarea returnată). Scopul principal este să evităm duplicarea codului.
Structura unei funcții
// tip_returnat nume_functie(parametri) { corp } int suma(int a, int b) { // parametri prin valoare return a + b; // valoarea returnată } bool estePar(int n) { return n % 2 == 0; // true dacă n este par } void afiseazaLinie() { // void = nu returnează nimic cout << "----------------" << endl; } int main() { int rezultat = suma(3, 7); // apel funcție → rezultat = 10 cout << rezultat << endl; if (estePar(4)) cout << "4 este par" << endl; afiseazaLinie(); // apel funcție void return 0; }
int suma(int a, int b); — linie înainte de main, corp după.
Anunță existența: int suma(int, int);
Corpul complet cu { ... }
Execuție: suma(3, 7)
Parametri prin valoare
Când transmitem un parametru prin valoare, funcția primește o copie a argumentului. Modificările din funcție nu afectează variabila originală.
void dublu(int x) { x = x * 2; // modificăm copia, nu originalul cout << x << endl; // afișează 10 } int main() { int a = 5; dublu(a); // trimitem valoarea 5, nu variabila cout << a << endl; // afișează 5 — a nu s-a modificat! }
Parametru cu valoare implicită (C++)
int putere(int baza, int exp = 2) { // exp implicit = 2 int rez = 1; for (int i = 0; i < exp; i++) rez *= baza; return rez; } cout << putere(3, 3); // 27 — folosim exp=3 cout << putere(5); // 25 — folosim exp implicit=2
Parametri prin referință
Parametrii prin referință (marcați cu &) permit funcției să modifice direct variabila originală. Nu se creează copie.
void dublu(int &x) { // & = referință la variabila originală x = x * 2; } int main() { int a = 5; dublu(a); // a devine 10 cout << a << endl; // 10 — a s-a modificat! }
Cazul clasic: funcție de schimbare (swap)
void schimba(int &a, int &b) { int temp = a; a = b; b = temp; } int x = 3, y = 7; schimba(x, y); // acum x=7, y=3
Citire în funcție — referință la n
void citesteVector(int v[], int &n) { // n prin referință cin >> n; for (int i = 1; i <= n; i++) cin >> v[i]; } int v[100001], n; citesteVector(v, n); // n se actualizează în main
& pentru vectori.
Copie. Funcția nu modifică originalul. Mai sigur.
Alias. Funcția modifică originalul. Mai eficient.
Tipul returnat — void vs non-void
Funcții care returnează o valoare
int maxim(int a, int b) { return a > b ? a : b; // returnează int } bool ePrim(int n) { if (n < 2) return false; for (int i = 2; i * i <= n; i++) if (n % i == 0) return false; return true; // returnează bool } double medie(int v[], int n) { int s = 0; for (int i = 1; i <= n; i++) s += v[i]; return (double)s / n; // returnează double }
Funcții void (fără valoare returnată)
void afiseazaVector(int v[], int n) { for (int i = 1; i <= n; i++) cout << v[i] << " "; cout << endl; } // nu există return (sau return; fără valoare) void sorteaza(int v[], int n) { for (int i = 1; i < n; i++) for (int j = 1; j <= n-i; j++) if (v[j] > v[j+1]) swap(v[j], v[j+1]); }
return în orice punct al funcției pentru a ieși mai devreme — util pentru validare la început.
Variabile locale și globale
int n; // variabilă GLOBALĂ — vizibilă în tot programul int v[100001]; // inițializat automat cu 0 (global) void calcul() { int suma = 0; // variabilă LOCALĂ — există doar în calcul() for (int i = 1; i <= n; i++) suma += v[i]; // accesează globalele n și v cout << suma; } // suma e distrusă la ieșirea din calcul() int main() { cin >> n; for (int i = 1; i <= n; i++) cin >> v[i]; calcul(); }
- Declarate în afara oricărei funcții
- Vizibile în tot fișierul
- Inițializate automat cu 0
- Rămân în memorie pe toată durata programului
- Declarate în interiorul unei funcții
- Vizibile doar în acea funcție
- Nu sunt inițializate automat!
- Distruse la ieșirea din funcție
int v[100001]) se declară global, nu local în main(). Variabilele locale sunt pe stivă (limitat la ~1 MB), globalele în segment de date (mai mult spațiu).
Subprograme predefinite — biblioteci standard
C++ oferă o serie de funcții gata scrise pe care le poți folosi incluzând header-ul corespunzător.
<algorithm> — cel mai util la BAC
#include <algorithm> sort(v + 1, v + n + 1); // sortare crescătoare O(n log n) sort(v + 1, v + n + 1, greater<int>()); // sortare descrescătoare int mx = *max_element(v+1, v+n+1); // maximul din vector int mn = *min_element(v+1, v+n+1); // minimul din vector reverse(v+1, v+n+1); // inversează vectorul int m = max(a, b); // maximul a doi scalari int mn2 = min(a, b);
<cmath> — funcții matematice
#include <cmath> sqrt(16.0) // → 4.0 (rădăcina pătrată) pow(2, 10) // → 1024 (2 la puterea 10) abs(-5) // → 5 (valoare absolută) floor(3.7) // → 3 (rotunjire în jos) ceil(3.2) // → 4 (rotunjire în sus)
<string> — metode pe string
#include <string> string s = "Hello"; s.length() // 5 — lungimea s.substr(1, 3) // "ell" — subsecvență de la 1, lungime 3 s.find("ll") // 2 — poziția primei apariții s + " World" // "Hello World" — concatenare s[0] // 'H' — acces caracter la indice 0
Probleme tip BAC — funcții și subprograme
Scrieți o funcție int cmmdc(int a, int b) care returnează cel mai mare divizor comun al lui a și b, folosind algoritmul lui Euclid.
int cmmdc(int a, int b) { while (b != 0) { int r = a % b; a = b; b = r; } return a; // O(log min(a,b)) } // cmmmc(a, b) = a / cmmdc(a, b) * b
Scrieți o funcție void citeste(int v[], int &n) și o funcție void afiseaza(int v[], int n), apoi un subprogram void elimina(int v[], int &n, int p) care elimină elementul de la poziția p.
void citeste(int v[], int &n) { cin >> n; for (int i = 1; i <= n; i++) cin >> v[i]; } void afiseaza(int v[], int n) { for (int i = 1; i <= n; i++) cout << v[i] << " "; cout << endl; } void elimina(int v[], int &n, int p) { for (int i = p; i < n; i++) v[i] = v[i+1]; n--; } int main() { int v[100001], n; citeste(v, n); elimina(v, n, 3); // elimină elem. de la poziția 3 afiseaza(v, n); }
Scrieți o funcție bool verificaPrimalitate(int n) care verifică dacă n este număr prim, fără a folosi ciurul.
bool verificaPrimalitate(int n) { if (n < 2) return false; for (int i = 2; (long long)i * i <= n; i++) if (n % i == 0) return false; return true; } // Complexitate: O(√n)
- Scrieți subprogramul
void citire(int v[], int &n)și apelați-l în main - Scrieți subprogramul care modifică vectorul (prin referință sau direct)
- Scrieți subprogramul care returnează un scalar (cmmdc, verificare, calcul)
- Structurați programul: citire → prelucrare → afișare (funcții separate)