Vreau sa construiesc un calculator profesional!
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 pas cu pas!
Nu scrie tot odata. Urmeaza pasii: fiecare pas adauga o parte noua la calculator. Testeaza dupa fiecare pas!
Incepe cu structura de baza. Copiaza codul, ruleaza-l si verifica ca meniul apare.
Adauga functia aduna si conecteaz-o cu meniul. Adauga INAINTE de main():
Dupa ce adunarea merge, adauga celelalte functii. Scrie-le pe toate deasupra lui main():
Apoi completeaza cazurile din switch:
In loc sa verificam num2 != 0 direct in main, cream o functie dedicata. Adaug-o deasupra lui main():
Apoi modifica case 4 din switch sa foloseasca aceasta functie. Mesajul de eroare e afisat de apelant, nu de functia bool:
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.
Dupa ce ai urmat toti pasii, programul tau complet ar trebui sa arate asa. Compara cu versiunea ta!
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.
Avem 7 functii separate. Fiecare face un singur lucru. main() doar coordoneaza - nu calculeaza nimic direct.
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 |
Parametri (transmiterea datelor)
In proiect, toate functiile primesc date prin parametri prin valoare. Functia primeste o copie a valorii - originalul ramane neschimbat.
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!
Return (rezultatul functiei)
Functiile de calcul folosesc return pentru a trimite rezultatul inapoi. Fara return, main() nu ar avea ce afisa!
void = functia face ceva (afiseaza, modifica) dar nu trimite un rezultat inapoi.
float/int/bool = functia calculeaza ceva si il trimite inapoi cu return.
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.
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.
do-while + switch = meniu interactiv
Combinatia do-while + switch este un pattern clasic pentru meniuri:
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:
- Adauga functia
absolut(float x)- returneaza valoarea absoluta a lui x (fara biblioteca, doar cuif) - Adauga functia
estePozitiv(float x)de tipbool- returneazatruedaca x > 0, altfelfalse - Adauga in meniu o optiune noua: "7. Valoare absoluta"
- In
main(), lacase 7: citeste un singur numar, apeleazaabsolut()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.
Vezi rezolvarea
Adaugi 2 functii si o optiune noua in meniu:
float absolut(float x) { if (x < 0) return -x; return x; } bool estePozitiv(float x) { return x > 0; }
In afiseazaMeniu() adaugi linia "7. Valoare absoluta". In switch, adaugi: case 7: { float n; cout << "Numarul: "; cin >> n; cout << "Valoarea absoluta: " << absolut(n) << endl; break; }
Test: absolut(-5) trebuie sa dea 5; absolut(3) trebuie sa dea 3. Poti folosi si estePozitiv() pentru un mesaj suplimentar ("numarul e pozitiv/negativ").
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 (+)
...
- Declara o variabila
int nrOperatii = 0;inmain() - Creeaza functia
void afiseazaStatistici(int nr)— primeste contorul si afiseaza: "Ai efectuat X operatii in aceasta sesiune." - Dupa fiecare calcul reusit (case 1–5), incrementeaza contorul:
nrOperatii++; - Modifica
afiseazaMeniu()sa primeascaint nrca parametru si sa afiseze contorul in antet - 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 sireturn(toate din lectiile 1-5). - Cand modifici
afiseazaMeniu()sa primeasca un parametru, actualizeaza si apelul dindo-while:afiseazaMeniu(nrOperatii); - Testeaza: efectueaza 3 operatii, alege optiunea 7 — trebuie sa apara "Ai efectuat 3 operatii".
Vezi rezolvarea
Pasi concreti:
- Declara
int nrOperatii = 0;inmain(), inainte dedo-while. - Modifica
void afiseazaMeniu()invoid afiseazaMeniu(int nr)si adauga in antetcout << "Operatii efectuate: " << nr << endl;. Actualizeaza apelul:afiseazaMeniu(nrOperatii);. - Dupa fiecare
casede calcul reusit (1-5), adauganrOperatii++;inainte debreak;. - Scrie
void afiseazaStatistici(int nr) { cout << "Ai efectuat " << nr << " operatii in aceasta sesiune." << endl; }si adaugacase 7: afiseazaStatistici(nrOperatii); break;.
Test: fa 3 calcule, alege optiunea 7 (fara sageata) - 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)siaduna(long long a, long long b)
Cuvinte cheie de folosit: precizie, float vs int, supraincarcarea functiilor, overloading, long long
Vezi rezolvarea
Nu-ti dam codul supraincarcat gata scris - gandeste singur pe aceasta schita:
- Explica limita lui
float: are doar 6-7 cifre semnificative precise; la milioane, ultimele cifre pot fi rotunjite gresit. - Propune 2 versiuni ale fiecarei functii de calcul, cu ACELASI nume dar tipuri diferite de parametri - de exemplu
float aduna(float a, float b)silong long aduna(long long a, long long b). Aceasta tehnica se numeste supraincarcarea functiilor (overloading): compilatorul alege versiunea potrivita dupa tipul argumentelor trimise la apel. - Gandeste-te ce s-ar intampla la meniu: ar trebui sa intrebi userul ce tip de date vrea, sau sa alegi automat dupa marimea numarului introdus.
Criterii: mentionarea corecta a limitei de precizie a lui float, propunerea a cel putin o pereche de functii supraincarcate cu tipuri diferite, si o observatie despre cum s-ar alege intre ele la citirea datelor.
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
Vrei mai mult?
Provocare: Adauga o functie noua float scade(float a, float b) la calculatorul din proiect. Integreaz-o corect: prototip deasupra lui main(), definitie dupa main(), un nou case in switch si o linie noua in afiseazaMeniu(). Ruleaza calculatorul si testeaza optiunea noua.
De gandit: Proiectul foloseste 3 tipuri de return diferite (float, void, bool) pentru 3 scopuri diferite. De ce crezi ca esteValidaImpartirea() e bool si nu tot float, ca celelalte functii de calcul?
Deschidere: Tiparul "meniu + o functie separata pe operatie + validare separata de calcul" e exact structura oricarei aplicatii reale cu meniu - un ATM sau o casa de marcat: fiecare optiune apeleaza o functie dedicata, iar validarea (bani suficienti? cod corect?) e mereu separata de calculul in sine.