Continut extra-curricular — peste programa OMEN 3393/2017 Functiile (subprogramele) nu fac parte din programa oficiala de gimnaziu (cls. V–VIII). Continutul acestui modul depaseste cerintele OMEN 3393/2017, care acopera pentru clasa a VIII-a: calcul tabelar, pagini web si siruri de valori numerice. Lectia aceasta este aprofundare/extindere — potrivita pentru elevi curioși sau care se pregatesc pentru liceu/olimpiada.
Invatare Atomica

Vreau sa construiesc un calculator profesional!

Progres lectie:
0%
🎯

Obiectivul lectiei

Ai invatat totul despre functii. Acum e momentul sa pui totul cap la cap intr-un proiect real: un calculator interactiv cu meniu!

Dupa aceasta lectie vei putea:

  • Sa explici de ce organizam codul in functii (principiul DRY si modularitate)
  • Sa recunosti tipurile de functii: void, float, bool si cand le folosesti
  • Sa aplici transmiterea datelor prin parametri catre o functie
  • Sa folosesti instructiunea return pentru a returna un rezultat din functie
  • Sa respecti ordinea corecta de declarare a functiilor inainte de apel

Incearca singur!

🔧 CONSTRUIESTE

Construieste pas cu pas!

Nu scrie tot odata. Urmeaza pasii: fiecare pas adauga o parte noua la calculator. Testeaza dupa fiecare pas!

Pasul 1: Scheletul programului + Meniul

Incepe cu structura de baza. Copiaza codul, ruleaza-l si verifica ca meniul apare.

#include <iostream> using namespace std; // Functia care afiseaza meniul void afiseazaMeniu() { cout << "\n============================" << endl; cout << " CALCULATOR PROFESIONAL" << endl; cout << "============================" << endl; cout << "1. Adunare (+)" << endl; cout << "2. Scadere (-)" << endl; cout << "3. Inmultire (*)" << endl; cout << "4. Impartire (/)" << endl; cout << "5. Ridicare la putere (^)" << endl; cout << "6. Iesire" << endl; cout << "============================" << endl; } int main() { int optiune; do { afiseazaMeniu(); cout << "Alege operatia: "; cin >> optiune; if (optiune != 6) { cout << "Ai ales optiunea " << optiune << endl; // TODO: Aici vom adauga operatiile } } while (optiune != 6); cout << "La revedere!" << endl; return 0; }
▶ Deschide OneCompiler
Verifica: Meniul apare? Daca alegi 6, programul se opreste? Daca alegi altceva, se repeta?
Pasul 2: Prima operatie - Adunarea

Adauga functia aduna si conecteaz-o cu meniul. Adauga INAINTE de main():

Adauga deasupra lui main()
// Functia de adunare float aduna(float a, float b) { return a + b; }
Inlocuieste TODO-ul din main() cu:
float num1, num2, rezultat; if (optiune >= 1 && optiune <= 5) { cout << "Primul numar: "; cin >> num1; cout << "Al doilea numar: "; cin >> num2; switch (optiune) { case 1: rezultat = aduna(num1, num2); cout << "Rezultat: " << num1 << " + " << num2 << " = " << rezultat << endl; break; // TODO: case 2, 3, 4, 5 } } else if (optiune != 6) { cout << "Optiune invalida! Alege 1-6." << endl; }
Verifica: Alege 1, introdu doua numere. Apare rezultatul corect?
Pasul 3: Restul operatiilor

Dupa ce adunarea merge, adauga celelalte functii. Scrie-le pe toate deasupra lui main():

float scade(float a, float b) { return a - b; } float inmulteste(float a, float b) { return a * b; } float imparte(float a, float b) { return a / b; } float ridicaLaPutere(float baza, int n) { float rezultat = 1; for (int i = 0; i < n; i++) { rezultat = rezultat * baza; } return rezultat; }

Apoi completeaza cazurile din switch:

case 2: rezultat = scade(num1, num2); cout << "Rezultat: " << num1 << " - " << num2 << " = " << rezultat << endl; break; case 3: rezultat = inmulteste(num1, num2); cout << "Rezultat: " << num1 << " * " << num2 << " = " << rezultat << endl; break; case 4: if (num2 != 0) { rezultat = imparte(num1, num2); cout << "Rezultat: " << num1 << " / " << num2 << " = " << rezultat << endl; } else { cout << "Eroare: Nu se poate imparti la 0!" << endl; } break; case 5: // Atentie: num2 este convertit la int (ex: 2.5 devine 2). // Functia ridicaLaPutere accepta doar exponenti intregi. rezultat = ridicaLaPutere(num1, (int)num2); cout << "Rezultat: " << num1 << " ^ " << (int)num2 << " = " << rezultat << endl; break;
Verifica: Testeaza fiecare operatie. Testeaza si impartirea la 0!
Pasul 4: Validare cu functie bool

In loc sa verificam num2 != 0 direct in main, cream o functie dedicata. Adaug-o deasupra lui main():

// Verifica daca impartirea e valida // Regula: o functie bool doar VERIFICA si returneaza true/false. // Afisarea mesajului de eroare e responsabilitatea apelantului. bool esteValidaImpartirea(float numitor) { return numitor != 0; }

Apoi modifica case 4 din switch sa foloseasca aceasta functie. Mesajul de eroare e afisat de apelant, nu de functia bool:

Noul case 4
case 4: if (esteValidaImpartirea(num2)) { rezultat = imparte(num1, num2); cout << "Rezultat: " << num1 << " / " << num2 << " = " << rezultat << endl; } else { cout << "Eroare: Nu se poate imparti la 0!" << endl; } break;
💡 De ce o functie separata? Si de ce fara cout inauntru?

Validarea e reutilizabila — daca mai ai si alte operatii care nu pot fi facute cu 0 (modulo, de exemplu), folosesti aceeasi functie.

Regula importanta: o functie bool trebuie sa faca un singur lucru — sa verifice si sa returneze true/false. Afisarea mesajelor apartine apelantului (codul din case 4). Daca bagi cout in functia de validare, incalci principiul "o functie, un rol" predat in Lectia 1, atom 5.

Pasul 5: Programul complet!

Dupa ce ai urmat toti pasii, programul tau complet ar trebui sa arate asa. Compara cu versiunea ta!

Click aici sa vezi programul complet
#include <iostream> using namespace std; // ========== FUNCTIILE DE CALCUL ========== float aduna(float a, float b) { return a + b; } float scade(float a, float b) { return a - b; } float inmulteste(float a, float b) { return a * b; } float imparte(float a, float b) { return a / b; } float ridicaLaPutere(float baza, int n) { float rezultat = 1; for (int i = 0; i < n; i++) { rezultat = rezultat * baza; } return rezultat; } // ========== FUNCTIA DE VALIDARE ========== // Regula: functia bool doar verifica si returneaza true/false. // Mesajul de eroare e afisat de apelant (case 4), nu de functia bool. bool esteValidaImpartirea(float numitor) { return numitor != 0; } // ========== FUNCTIA MENIU ========== void afiseazaMeniu() { cout << "\n============================" << endl; cout << " CALCULATOR PROFESIONAL" << endl; cout << "============================" << endl; cout << "1. Adunare (+)" << endl; cout << "2. Scadere (-)" << endl; cout << "3. Inmultire (*)" << endl; cout << "4. Impartire (/)" << endl; cout << "5. Ridicare la putere (^)" << endl; cout << "6. Iesire" << endl; cout << "============================" << endl; } // ========== PROGRAMUL PRINCIPAL ========== int main() { int optiune; float num1, num2, rezultat; cout << "Bine ai venit la Calculator!" << endl; do { afiseazaMeniu(); cout << "Alege operatia: "; cin >> optiune; if (optiune >= 1 && optiune <= 5) { cout << "Primul numar: "; cin >> num1; cout << "Al doilea numar: "; cin >> num2; switch (optiune) { case 1: rezultat = aduna(num1, num2); cout << "Rezultat: " << num1 << " + " << num2 << " = " << rezultat << endl; break; case 2: rezultat = scade(num1, num2); cout << "Rezultat: " << num1 << " - " << num2 << " = " << rezultat << endl; break; case 3: rezultat = inmulteste(num1, num2); cout << "Rezultat: " << num1 << " * " << num2 << " = " << rezultat << endl; break; case 4: if (esteValidaImpartirea(num2)) { rezultat = imparte(num1, num2); cout << "Rezultat: " << num1 << " / " << num2 << " = " << rezultat << endl; } else { cout << "Eroare: Nu se poate imparti la 0!" << endl; } break; case 5: // Atentie: num2 este convertit la int (ex: 2.5 devine 2). // Functia ridicaLaPutere accepta doar exponenti intregi. rezultat = ridicaLaPutere(num1, (int)num2); cout << "Rezultat: " << num1 << " ^ " << (int)num2 << " = " << rezultat << endl; break; } } else if (optiune != 6) { cout << "Optiune invalida! Alege 1-6." << endl; } } while (optiune != 6); cout << "La revedere!" << endl; return 0; }
▶ Ruleaza pe OneCompiler
☑ Lista de verificare - Bifeaza fiecare test:
1

De ce functii? (DRY, modularitate)

De ce functii? (DRY, modularitate)

Fara functii, tot codul ar fi in main() - un bloc imens, greu de citit. Cu functii, fiecare operatie are un "loc" al ei. Daca vrei sa schimbi cum functioneaza adunarea, modifici doar functia aduna(), nu cauti prin sute de linii.

🏠 In proiect:

Avem 7 functii separate. Fiecare face un singur lucru. main() doar coordoneaza - nu calculeaza nimic direct.

2

Declararea functiilor

Declararea functiilor

Fiecare functie are o semnatura clara: tip returnat, nume, parametri. In proiect avem 3 tipuri diferite:

Functie Tip returnat Parametri Ce face
aduna(a, b) float 2 x float Returneaza suma
afiseazaMeniu() void niciunul Doar afiseaza
esteValidaImpartirea(b) bool 1 x float Returneaza true/false
ridicaLaPutere(baza, n) float float + int Calculeaza baza^n
3

Parametri (transmiterea datelor)

Parametri (transmiterea datelor)

In proiect, toate functiile primesc date prin parametri prin valoare. Functia primeste o copie a valorii - originalul ramane neschimbat.

Exemplu din proiect
// num1 si num2 din main() sunt COPIATE in a si b float aduna(float a, float b) { return a + b; // a si b sunt copii locale } // In main(): rezultat = aduna(num1, num2); // num1 si num2 raman neschimbate!
💡 Extensie: Parametri prin referinta

Am putea adauga o functie citesteNumere(float &a, float &b) care citeste ambele numere si le salveaza direct in variabilele din main() prin referinta. Asta ar elimina duplicarea codului de citire!

void citesteNumere(float &a, float &b) { cout << "Primul numar: "; cin >> a; // modifica direct num1 din main! cout << "Al doilea numar: "; cin >> b; // modifica direct num2 din main! } // In main(): citesteNumere(num1, num2);
4

Return (rezultatul functiei)

Return (rezultatul functiei)

Functiile de calcul folosesc return pentru a trimite rezultatul inapoi. Fara return, main() nu ar avea ce afisa!

Fluxul datelor
// 1. main() trimite num1=15 si num2=7 la aduna() rezultat = aduna(15, 7); // 2. aduna() calculeaza 15 + 7 = 22 // 3. aduna() returneaza 22 cu "return" // 4. Valoarea 22 este stocata in "rezultat" // Functia bool returneaza true sau false: if (esteValidaImpartirea(num2)) { ... } // Se evalueaza la: if (true) sau if (false)
🔑 void vs. return

void = functia face ceva (afiseaza, modifica) dar nu trimite un rezultat inapoi.
float/int/bool = functia calculeaza ceva si il trimite inapoi cu return.

5

Apelarea functiilor si ordinea declararii

Apelarea functiilor si ordinea declararii

In proiect, toate functiile sunt declarate inainte de main(). Aceasta este regula de baza: o functie trebuie declarata (sau cel putin anuntata cu un prototip) inainte de a fi apelata.

Ordinea in program
// 1. #include-uri #include <iostream> // 2. Functiile de calcul (aduna, scade, ...) float aduna(...) { ... } float scade(...) { ... } // ... etc // 3. Functia de validare bool esteValidaImpartirea(...) { ... } // 4. Functia meniu void afiseazaMeniu() { ... } // 5. main() - ULTIMA! Apeleaza tot ce e deasupra int main() { // Apelam: afiseazaMeniu(), aduna(), etc. }
⚠ Greseala frecventa

Daca pui o functie dupa main(), compilatorul va spune: "error: 'aduna' was not declared in this scope". Solutie: muta functia deasupra lui main() sau adauga un prototip.

6

do-while + switch = meniu interactiv

do-while + switch = meniu interactiv

Combinatia do-while + switch este un pattern clasic pentru meniuri:

Patternul meniu
do { afiseazaMeniu(); // 1. Afiseaza optiunile cin >> optiune; // 2. Citeste alegerea switch (optiune) { // 3. Executa actiunea case 1: ... break; case 2: ... break; // ... } } while (optiune != 6); // 4. Repeta pana la "Iesire"
🍔 Analogie: Restaurantul

Chelnerul (meniul) vine la masa ta, iti arata optiunile, tu alegi, el aduce ce ai cerut, apoi intreaba din nou daca mai vrei ceva. Se repeta pana ceri nota (iesire).

Exercitii practice

Exercitiul 1 (Nivel minim) - Extinde calculatorul

Adauga doua functii noi la calculatorul tau, folosind doar ce ai invatat in lectiile 1-5:

  1. Adauga functia absolut(float x) - returneaza valoarea absoluta a lui x (fara biblioteca, doar cu if)
  2. Adauga functia estePozitiv(float x) de tip bool - returneaza true daca x > 0, altfel false
  3. Adauga in meniu o optiune noua: "7. Valoare absoluta"
  4. In main(), la case 7: citeste un singur numar, apeleaza absolut() si afiseaza rezultatul

Indicii:

  • Absolut: if (x < 0) return -x; else return x; — asta e tot! Nu ai nevoie de nicio biblioteca.
  • La case 7 citesti UN singur numar, nu doua — ai grija sa schimbi si logica de citire din main().
  • Testeaza cu: absolut(-5) trebuie sa dea 5; absolut(3) trebuie sa dea 3.

Exercitiul 2 (Nivel standard) - Contor de operatii

Cerinta: Adauga un contor care numara cate operatii ai efectuat in sesiunea curenta. Afiseaza-l in meniu si printr-o functie separata.

Exemplu de afisare dorita:

============================
CALCULATOR PROFESIONAL
Operatii efectuate: 3
============================
1. Adunare (+)
...
  1. Declara o variabila int nrOperatii = 0; in main()
  2. Creeaza functia void afiseazaStatistici(int nr) — primeste contorul si afiseaza: "Ai efectuat X operatii in aceasta sesiune."
  3. Dupa fiecare calcul reusit (case 1–5), incrementeaza contorul: nrOperatii++;
  4. Modifica afiseazaMeniu() sa primeasca int nr ca parametru si sa afiseze contorul in antet
  5. Adauga optiunea "7. Statistici" in meniu — la alegere, apeleaza afiseazaStatistici(nrOperatii)

Indicii:

  • Nu ai nevoie de tablouri sau biblioteci noi — doar int, functii cu parametri si return (toate din lectiile 1-5).
  • Cand modifici afiseazaMeniu() sa primeasca un parametru, actualizeaza si apelul din do-while: afiseazaMeniu(nrOperatii);
  • Testeaza: efectueaza 3 operatii, alege optiunea 7 — trebuie sa apara "Ai efectuat 3 operatii".

Exercitiul 3 (Nivel performanta) - Gandire critica

Cerinta: Calculatorul nostru lucreaza doar cu float. Explica ce probleme ar aparea daca am vrea sa lucram si cu numere intregi mari (de exemplu, milioane). Cum ai rezolva problema? Propune o arhitectura cu functii supraincarcate (overloaded).

Indicii:

  • Float are precizie limitata (6-7 cifre semnificative)
  • C++ permite doua functii cu acelasi nume dar parametri diferiti
  • Gandeste-te la aduna(float a, float b) si aduna(long long a, long long b)

Cuvinte cheie de folosit: precizie, float vs int, supraincarcarea functiilor, overloading, long long

Ce ai invatat astazi

  • Ai invatat de ce organizam codul in functii (DRY, modularitate)
  • Acum stii sa declari functii cu tipuri diferite: void, float, bool
  • Ai descoperit cum se transmit datele prin parametri
  • Ai explorat cum returnezi un rezultat cu instructiunea return
  • Ai inteles ordinea corecta de declarare a functiilor inainte de apel
  • Ai invatat patternul do-while + switch pentru meniuri interactive

Urmatoarea lectie

Continua cu lectia urmatoare pentru a aprofunda cunostintele.

Continua →