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 l1 - de ce functii? (dry, modularitate)
  • Sa explici l2 - declararea functiilor
  • Sa aplici l3 - paRAMetri (transmiterea datelor)
  • Sa aplici l4 - return (rezultatul functiei)
  • Sa aplici l5 - apelarea functiilor si ordinea declararii

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: 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 bool esteValidaImpartirea(float numitor) { if (numitor == 0) { cout << "Eroare: Nu se poate imparti la 0!" << endl; return false; } return true; }

Apoi modifica case 4 din switch sa foloseasca aceasta functie:

Noul case 4
case 4: if (esteValidaImpartirea(num2)) { rezultat = imparte(num1, num2); cout << "Rezultat: " << num1 << " / " << num2 << " = " << rezultat << endl; } break;
💡 De ce o functie separata?

Acum validarea e reutilizabila! Daca mai ai si alte operatii care nu pot fi facute cu 0 (modulo, de exemplu), folosesti aceeasi functie. Plus ca esteValidaImpartirea(num2) este mult mai clar decat num2 != 0.

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 ========== bool esteValidaImpartirea(float numitor) { if (numitor == 0) { cout << "Eroare: Nu se poate imparti la 0!" << endl; return false; } return true; } // ========== 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; } break; case 5: 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

L1 - De ce functii? (DRY, modularitate)

L1 - 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

L2 - Declararea functiilor

L2 - 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

L3 - Parametri (transmiterea datelor)

L3 - 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

L4 - Return (rezultatul functiei)

L4 - 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

L5 - Apelarea functiilor si ordinea declararii

L5 - 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) - Calculator stiintific

Extinde calculatorul cu functii stiintifice:

  1. Adauga functia modulo(int a, int b) - restul impartirii (validare: b != 0)
  2. Adauga functia radical(float x) - foloseste sqrt(x) din <cmath> (validare: x >= 0)
  3. Adauga functia absolut(float x) - valoarea absoluta (fara biblioteca, cu if)
  4. Actualizeaza meniul cu noile optiuni

Indicii:

  • Radical are un singur parametru - citeste doar un numar!
  • Modulo functioneaza doar cu int, nu float
  • Absolut: daca x < 0, returneaza -x; altfel returneaza x

Exercitiul 2 (Nivel standard) - Istoric operatii

Cerinta: Adauga o optiune in meniu care afiseaza ultimele operatii efectuate. Salveaza fiecare operatie ca text intr-un tablou.

Exemplu:

Istoric operatii:
1. 15 + 7 = 22
2. 10 * 3 = 30
3. 20 / 4 = 5

Indicii:

  • Declara string istoric[20]; si un contor int nrOperatii = 0;
  • Dupa fiecare operatie, construieste un string cu rezultatul si salveaza-l in istoric[nrOperatii]
  • Vei avea nevoie de #include <string> si to_string()

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 l1 - de ce functii? (dry, modularitate)
  • Acum stii l2 - declararea functiilor
  • Ai descoperit l3 - parametri (transmiterea datelor)
  • Ai explorat l4 - return (rezultatul functiei)
  • Ai inteles l5 - apelarea functiilor si ordinea declararii
  • Ai invatat do-while + switch = meniu interactiv

Urmatoarea lectie

Continua cu lectia urmatoare pentru a aprofunda cunostintele.

Continua →