Vreau sa scriu cod fara sa ma repet!
Obiectivul lectiei
Imagineaza-ti ca ai un program cu aceleasi 5 linii copiate in 3 locuri diferite. Apoi gasesti un bug... si trebuie sa-l repari in toate cele 3 locuri. Asta e un cosmar!
Dupa aceasta lectie vei putea:
- Sa explici ce este o functie si de ce ai nevoie de ea
- Sa implementezi de ce repetarea codului e o problema grava
- Sa aplici ce inseamna void
- Sa aplici apelarea = chemarea functiei
- Sa aplici fiecare functie face un singur lucru
Testeaza inainte sa inveti!
Nu trebuie sa intelegi totul acum. Doar copiaza, ruleaza si observa ce se intampla.
afiseazaLinie() este apelata de 3 ori, dar scrisa o singura data. Ce apare pe ecran?
"********************" cu "====================" . Ruleaza din nou. Ce observi? Cate linii ai modificat?
void salut() care afiseaza "Buna ziua!". Apeleaz-o din main inainte de prima linie.
void afiseazaCaseta() care afiseaza o caseta completa (linie, text, linie) si apeleaz-o de 2 ori!
Ai modificat o singura linie (cea din interiorul functiei), dar efectul se vede in toate cele 3 locuri unde e apelata. Asta e puterea functiilor!
Fara functie, ai fi trebuit sa modifici 3 linii separate. Cu functia, modifici una singura.
Scrie noua functie deasupra lui main (la fel ca afiseazaLinie):
void salut() {
cout << "Buna ziua!" << endl;
}
Apoi, in main(), scrie salut(); pe prima linie (inainte de afiseazaLinie();).
Poti chema o functie din alta functie! Scrie:
void afiseazaCaseta() {
afiseazaLinie();
cout << " Mesaj important!" << endl;
afiseazaLinie();
}
Pune aceasta functie dupa afiseazaLinie si inainte de main.
Ce este o functie si de ce ai nevoie de ea?
O functie (sau subprogram) este un bloc de cod cu un nume pe care il poti apela (chema) ori de cate ori ai nevoie, fara sa rescrii codul.
Gandeste-te asa: in loc sa copiezi aceleasi linii de cod in 5 locuri, le scrii o singura data intr-o functie, si apoi doar chemi functia de 5 ori.
Cand vrei sa faci prajituri, nu inventezi reteta de fiecare data. O scrii o data pe o foaie si apoi o folosesti ori de cate ori vrei sa gatesti. Reteta este functia. A gati dupa reteta este apelarea functiei.
Daca vrei sa schimbi cantitatea de zahar, modifici doar reteta, nu toate prajiturile pe care le-ai facut vreodata!
De ce repetarea codului e o problema grava
Cand copiezi acelasi cod in mai multe locuri, se intampla 3 lucruri rele:
| Problema | Ce se intampla concret |
|---|---|
| Bug multiplicat | Gasesti un bug intr-o copie. Il repari. Dar ai uitat ca exista inca 2 copii cu acelasi bug. Programul tot nu merge. |
| Cod greu de citit | 200 de linii de cod cu blocuri repetate vs. 50 de linii cu functii clare. Care e mai usor de inteles? |
| Timp pierdut | Orice modificare trebuie facuta in N locuri. Cu o functie, o faci o singura data. |
Ce inseamna void?
Cuvantul void inseamna "nimic" sau "gol". O functie void este o functie care face ceva (afiseaza text, deseneaza pe ecran, etc.) dar nu returneaza un rezultat.
Gandeste-te la reteta din analogia de mai sus: void afiseazaLinie() este ca un bucatar care executa un pas din reteta (afiseaza linia) dar nu iti da nimic inapoi — ti-a facut treaba, atat. In schimb, o functie fara void (cu tip returnat) este ca un bucatar care executa pasul si iti da rezultatul: "am calculat suma, uite: 42". Lectia 4 acopera functiile cu valoare returnata.
Apelarea = chemarea functiei
Ca sa "chemi" o functie, scrii numele ei urmat de paranteze si punct si virgula:
Definirea functiei = scrierea "retetei" (o faci o singura data).
Apelarea functiei = folosirea "retetei" (o faci de cate ori vrei).
O functie pe care o definesti dar nu o apelezi niciodata este ca o reteta pe care o scrii dar nu o gatesti niciodata - codul din ea nu se va executa.
Fiecare functie face UN singur lucru
Un program bine scris este ca o echipa: fiecare membru (functie) are un rol clar. Nu pui un singur om sa faca totul!
Regula: daca poti descrie ce face functia intr-o singura propozitie, atunci e bine definita.
Regula de plasare: functia INAINTE de apel
In C++, functia trebuie sa fie definita inainte de locul unde o apelezi. De obicei, scriem functiile deasupra lui main().
Exercitii practice
Exercitiul 1 (Nivel minim) - Analiza conceptelor
Raspunde la urmatoarele intrebari despre functii:
- Explica in cuvintele tale ce inseamna principiul DRY si de ce este important in programare. Da un exemplu concret de situatie in care l-ai aplica.
- Care este diferenta intre definirea unei functii si apelarea ei? De ce trebuie sa le facem pe amandoua?
- Un coleg a scris o functie
void salut() { cout << "Buna!"; }dar programul nu afiseaza nimic. Ce a uitat sa faca? Explica.
Raspunde numerotat: 1. ... 2. ... 3. ...
Exercitiul 2 (Nivel standard) - Programeaza cu functii
Cerinta: Scrie un program C++ care contine 3 functii void:
void separator()- afiseaza o linie de 30 de caractere '-'void antet()- apeleaza separator(), afiseaza "MAGAZIN ONLINE", apoi apeleaza separator() din nouvoid produse()- afiseaza o lista de 3 produse (ex: "1. Laptop - 2500 lei")
In main(), apeleaza: antet(), produse(), separator().
Exemplu output:
------------------------------
MAGAZIN ONLINE
------------------------------
1. Laptop - 2500 lei
2. Mouse - 50 lei
3. Tastatura - 150 lei
------------------------------
Indicii:
- Defineste toate cele 3 functii deasupra lui
main() - Functia
antet()poate apelaseparator()- dar separator trebuie definit inainte de antet! - Ordinea definirii conteaza: separator → antet → produse → main
Exercitiul 3 (Nivel performanta) - Refactorizeaza si extinde
Cerinta: Mai jos este un program C++ care afiseaza 3 raporturi identice (fara functii). Codul este repetitiv si greu de modificat.
#include <iostream>
using namespace std;
int main() {
cout << "========================" << endl;
cout << " RAPORT SCOALA" << endl;
cout << "========================" << endl;
cout << "Clasa: 8A" << endl;
cout << "========================" << endl;
cout << "========================" << endl;
cout << " RAPORT SCOALA" << endl;
cout << "========================" << endl;
cout << "Clasa: 8B" << endl;
cout << "========================" << endl;
cout << "========================" << endl;
cout << " RAPORT SCOALA" << endl;
cout << "========================" << endl;
cout << "Clasa: 8C" << endl;
cout << "========================" << endl;
return 0;
}
- Scrie o functie
void separator()care afiseaza linia"========================"si o functievoid antetRaport()care afiseaza separatorul, titlul si separatorul. Rescriemain()sa foloseasca aceste functii pentru toate cele 3 rapoarte (clasele 8A, 8B, 8C). Programul trebuie sa produca acelasi output ca inainte. - Extinde: adauga o a treia functie
void raport(string clasa)care primeste numele clasei si afiseaza intregul raport (antet + clasa + separator de inchidere). Rescriemain()sa apelezeraport("8A"),raport("8B"),raport("8C"). Ai nevoie de#include <string>. - Reflecta si scrie: daca directorul iti cere sa schimbi titlul din "RAPORT SCOALA" in "SITUATIE CLASE", cate linii modifici in versiunea cu functii vs. versiunea originala? Noteaza raspunsul intr-un comentariu C++ in cod (
// ...).
Indicii:
- Functia
raport(string clasa)poate apelaantetRaport()— functia ta poate apela alte functii! - Ordinea de definire conteaza:
separator→antetRaport→raport→main - Pentru a afisa un
string:cout << clasa << endl;
Cuvinte cheie de folosit: void, functie, apel, parametru, string, DRY, refactorizare
Ce ai invatat astazi
- Ai invatat ce este o functie si de ce ai nevoie de ea
- Acum stii de ce repetarea codului e o problema grava
- Ai descoperit ce inseamna void
- Ai explorat apelarea = chemarea functiei
- Ai inteles fiecare functie face un singur lucru
- Ai invatat regula de plasare: functia inainte de apel