În lucru: lecțiile se refac de la capăt. Lecțiile noi ale clasei: lecțiile noi ale clasei a VIII-a →
Invatare Atomica

Vreau sa fac functii care accepta date diferite de fiecare data!

Progres lectie:
0%
🎯

Obiectivul lectiei

Ai invatat sa creezi functii, dar pana acum ele faceau mereu acelasi lucru. Cum le faci sa fie flexibile?

Dupa aceasta lectie vei putea:

  • Sa explici ce sunt parametrii
  • Sa explici doua nume, doua roluri
  • Sa aplici functii cu mai multi parametri
  • Sa aplici functia primeste o copie
  • Sa aplici functia lucreaza cu originalul - semnul &

Incearca singur!

🎯 INCEARCA

Testeaza inainte sa inveti!

Nu trebuie sa intelegi totul acum. Doar copiaza, ruleaza si observa ce se intampla.

Misiunea ta (5 minute):
1
Copiaza codul de mai jos si lipeste-l pe OneCompiler. Apasa Run.
#include <iostream> #include <string> using namespace std; void afiseazaSalut(string nume, int varsta) { cout << "Salut, " << nume << "! Ai " << varsta << " ani." << endl; } int main() { afiseazaSalut("Ana", 14); afiseazaSalut("Ion", 15); afiseazaSalut("Maria", 13); return 0; }
▶ Deschide OneCompiler
2
Adauga inca un apel cu numele tau si varsta ta. Ce observi? Functia se comporta diferit de fiecare data!
3
Acum inverseaza ordinea argumentelor: scrie afiseazaSalut(14, "Ana"); (numarul inainte de text). Ce se intampla? De ce?
4
Incearca sa apelezi functia cu un singur argument: afiseazaSalut("Test"); - fara al doilea parametru. Ce spune compilatorul?
🌟 BONUS: Adauga un al treilea parametru string clasa la functie si modifica mesajul sa afiseze si clasa elevului!
▶ Blocat la pasul 3? Click aici pentru un indiciu

Compilatorul da eroare! Ordinea conteaza: primul argument merge la primul parametru, al doilea la al doilea. Daca pui 14 (un int) unde asteapta string, tipurile nu se potrivesc.

Regula: argumentele trebuie sa fie in aceeasi ordine si de acelasi tip ca parametrii din declaratie.

▶ Blocat la pasul 4? Click aici

Compilatorul spune ceva de genul: "too few arguments" (prea putine argumente).

Functia asteapta 2 valori (nume SI varsta), dar i-ai dat doar una. Trebuie sa dai exact cate argumente are functia parametri!

▶ Blocat la BONUS? Click aici

Modifica declaratia asa: void afiseazaSalut(string nume, int varsta, string clasa)

In corpul functiei adauga: cout << " din clasa " << clasa;

La apel: afiseazaSalut("Ana", 14, "8A");

1

Ce sunt parametrii?

Ce sunt parametrii?

Parametrii sunt variabile speciale declarate in parantezele unei functii. Ele primesc valori din exterior atunci cand functia este apelata, permitandu-i sa lucreze cu date diferite de fiecare data.

Fara parametri, o functie face mereu acelasi lucru. Cu parametri, functia devine flexibila - ca un sablon care se adapteaza la datele pe care le primeste.

🍔 Analogie: Comanda la restaurant

Imaginati-va un chelner (functia). Fara parametri, chelnerul aduce mereu aceeasi mancare. Cu parametri, ii spui: "Vreau pizza si suc de portocale" - el primeste comanda ta (parametrii) si serveste exact ce ai cerut.

Acelasi chelner (aceeasi functie) serveste clienti diferiti cu comenzi diferite (argumente diferite)!

2

Doua nume, doua roluri

Doua nume, doua roluri

Exista doi termeni importanti care se confunda des:

Declaratie - aici avem PARAMETRI FORMALI
// parametru formal parametru formal // | | void salut(string nume, int varsta) { cout << "Salut, " << nume << "! Ai " << varsta << " ani."; }
Apel - aici avem ARGUMENTE (parametri actuali)
// argument argument // | | salut("Ana", 14); // "Ana" -> nume, 14 -> varsta salut("Ion", 15); // "Ion" -> nume, 15 -> varsta
💡 Rezumat simplu

Parametru formal = variabila din declaratia functiei (e ca un "loc gol" care asteapta o valoare).
Argument (parametru actual) = valoarea concreta pe care o trimiti la apel (e valoarea care "umple" locul gol).

In practica, multi programatori folosesc "parametru" si "argument" interschimbabil. Important e sa intelegi mecanismul.

3

Functii cu mai multi parametri

Functii cu mai multi parametri

O functie poate avea oricat de multi parametri, separati prin virgula. Fiecare parametru trebuie sa aiba tipul si numele lui.

Functie cu 2 parametri
int suma(int a, int b) { return a + b; } // Apel: int rez = suma(5, 3); // a=5, b=3 -> rez = 8 int rez2 = suma(10, 20); // a=10, b=20 -> rez2 = 30
Functie cu 3 parametri de tipuri diferite
void afiseazaElev(string nume, int varsta, float medie) { cout << nume << ", " << varsta << " ani, media: " << medie << endl; } // Apel corect: afiseazaElev("Ana", 14, 9.75); // OK! afiseazaElev("Ion", 15, 8.50); // OK!
⚠ Ordinea argumentelor trebuie sa fie aceeasi!
// GRESIT - ordine inversata: afiseazaElev(14, "Ana", 9.75); // EROARE! 14 nu e string! // GRESIT - prea putine argumente: afiseazaElev("Ana", 14); // EROARE! lipseste medie! // GRESIT - prea multe argumente: afiseazaElev("Ana", 14, 9.75, "8A"); // EROARE! 4 argumente la 3 parametri!
4

Functia primeste o COPIE

Functia primeste o COPIE

In mod implicit (fara &), cand trimiti o variabila ca argument, functia primeste o copie a valorii. Orice modificare in functie afecteaza doar copia - variabila originala ramane neschimbata!

Exemplu: modificarea NU se propaga inapoi
void dubleaza(int x) { x = x * 2; // modifica doar COPIA cout << "In functie: x = " << x << endl; } int main() { int nr = 5; dubleaza(nr); // trimite COPIA lui nr (valoarea 5) cout << "In main: nr = " << nr << endl; return 0; }
Output
In functie: x = 10 In main: nr = 5 // nr NU s-a schimbat!
5

Functia lucreaza cu ORIGINALUL - semnul &

Functia lucreaza cu ORIGINALUL - semnul &

Daca adaugi & dupa tipul parametrului, functia primeste variabila originala, nu o copie. Orice modificare in functie se reflecta si in afara ei!

Exemplu: cu & - modificarea SE propaga
void dubleaza(int &x) { // & = referinta! x = x * 2; // modifica ORIGINALUL cout << "In functie: x = " << x << endl; } int main() { int nr = 5; dubleaza(nr); // trimite ORIGINALUL (referinta la nr) cout << "In main: nr = " << nr << endl; return 0; }
Output
In functie: x = 10 In main: nr = 10 // nr S-A SCHIMBAT!
6

De ce swap NECESITA referinta

De ce swap NECESITA referinta

Functia swap trebuie sa interschimbe valorile a doua variabile. Fara &, schimba doar copiile - nu se intampla nimic util!

GRESIT - fara & (nu functioneaza!)
void swap_gresit(int a, int b) { int temp = a; a = b; b = temp; // a si b sunt COPII - originalele nu se schimba! } int main() { int x = 3, y = 7; swap_gresit(x, y); cout << x << " " << y; // afiseaza: 3 7 (neschimbate!) }
CORECT - cu & (functioneaza!)
void swap_corect(int &a, int &b) { int temp = a; a = b; b = temp; // a si b sunt ORIGINALELE - schimbarea persista! } int main() { int x = 3, y = 7; swap_corect(x, y); cout << x << " " << y; // afiseaza: 7 3 (interschimbate!) }
7

Valori implicite - cand nu dai un argument ★ BONUS / AVANSAT

Valori implicite - cand nu dai un argument
★ Atom avansat — aprofundare

Acest concept depaseste curricula standard de clasa a VIII-a. Daca stapanesti bine atomii 1-6, continua. Daca nu, este complet normal sa revii dupa ce exersezi mai mult.

Poti da unui parametru o valoare implicita (default). Daca nu furnizezi acel argument la apel, se foloseste valoarea implicita. Daca furnizezi, se foloseste valoarea ta.

Exemplu cu valoare implicita
void salut(string nume = "elev") { cout << "Buna, " << nume << "!" << endl; } int main() { salut("Ana"); // Buna, Ana! salut("Ion"); // Buna, Ion! salut(); // Buna, elev! (foloseste valoarea implicita) }
Regula: valorile implicite merg de la dreapta la stanga!
// CORECT: parametrii cu default sunt la sfarsit void elev(string nume, int varsta = 14, string clasa = "8A"); // GRESIT: parametru fara default DUPA unul cu default // void elev(string nume = "?", int varsta); // EROARE!
💡 De ce de la dreapta la stanga?

La apel, argumentele se completeaza de la stanga. Daca omiti un argument, compilatorul nu stie pe care l-ai omis decat daca cele optionale sunt toate la sfarsit. Asa, poti omite ultimul, ultimele doua, etc.

Exercitii practice

Exercitiul 1 (Nivel minim) - Analiza parametrilor

Raspunde la urmatoarele intrebari despre parametri:

  1. Care este diferenta dintre un parametru formal si un argument? Da un exemplu cu o functie care calculeaza aria unui dreptunghi.
  2. De ce urmatorul cod NU interschimba valorile?
    void swap(int a, int b) { int t = a; a = b; b = t; }
    int x = 5, y = 10; swap(x, y);
    Cum il repari sa functioneze?
  3. Ce se intampla daca apelezi void f(int a, int b = 5) cu f(10)? Dar cu f(10, 20)? De ce nu poti scrie void f(int a = 5, int b)?

Raspunde numerotat: 1. ... 2. ... 3. ...

Vezi rezolvarea
  1. Parametrul formal e variabila din declaratia functiei (locul gol); argumentul e valoarea concreta trimisa la apel. Exemplu: float aria(float lungime, float latime) { return lungime * latime; } - lungime si latime sunt parametri formali; la apelul aria(5.0, 3.0), 5.0 si 3.0 sunt argumentele.
  2. Fara &, swap(a,b) primeste COPII ale lui x si y; interschimbarea se face doar pe copii, iar x si y raman neschimbate. Se repara cu void swap(int &a, int &b).
  3. f(10): a=10, b=5 (valoarea implicita). f(10,20): a=10, b=20 (argumentul dat inlocuieste implicitul). Nu poti scrie void f(int a=5, int b) pentru ca valorile implicite trebuie sa fie la SFARSITUL listei - un parametru fara default nu poate veni dupa unul cu default.

Exercitiul 2 (Nivel standard) - Programeaza cu parametri

Cerinta: Scrie un program C++ cu urmatoarele functii:

  1. int maxim(int a, int b) - returneaza maximul dintre doua numere
  2. void citeste(int &x) - citeste un numar de la tastatura si il pune in x (foloseste referinta!)
  3. void afiseazaRezultat(string mesaj, int valoare, string unitate = "") - afiseaza mesajul, valoarea si unitatea (optional)

Exemplu output:

Introdu primul numar: 15
Introdu al doilea numar: 8
Maximul: 15
Diferenta: 7 puncte

Indicii:

  • Pentru citeste, parametrul trebuie sa fie int &x (cu &) ca sa se salveze valoarea citita
  • Pentru maxim, foloseste un if simplu sau operatorul ternar ?:
  • Apeleaza afiseazaRezultat("Maximul", m) fara unitate si afiseazaRezultat("Diferenta", d, "puncte") cu unitate
Vezi rezolvarea

Program complet:

int maxim(int a, int b) { if (a > b) return a; return b; } void citeste(int &x) { cin >> x; } void afiseazaRezultat(string mesaj, int valoare, string unitate = "") { cout << mesaj << ": " << valoare << " " << unitate << endl; } int main() { int n1, n2; cout << "Introdu primul numar: "; citeste(n1); cout << "Introdu al doilea numar: "; citeste(n2); afiseazaRezultat("Maximul", maxim(n1,n2)); afiseazaRezultat("Diferenta", n1 > n2 ? n1-n2 : n2-n1, "puncte"); return 0; }

Exercitiul 3 (Nivel performanta) - Depaneaza si extinde

Cerinta: Codul de mai jos contine doua erori care fac ca valorile sa nu se schimbe corect. Gaseste erorile, repara-le, apoi extinde programul cu o noua functie.

#include <iostream>
using namespace std;

void triplica(int x) {
x = x * 3;
}

void swap(int a, int b) {
int t = a;
a = b;
b = t;
}

int main() {
int nr = 4;
triplica(nr);
cout << "nr triplicat: " << nr << endl; // asteptat: 12

int x = 10, y = 20;
swap(x, y);
cout << "dupa swap: " << x << " " << y << endl; // asteptat: 20 10
return 0;
}

Pasi:

  1. Copiaza codul pe OneCompiler si ruleaza-l. Ce afiseaza in loc de valorile asteptate?
  2. Identifica de ce triplica si swap nu functioneaza corect. (Indiciu: ce lipseste din parametri?)
  3. Repara ambele functii adaugand & acolo unde este necesar.
  4. Extindere: Adauga o a treia functie void reseteaza(int &a, int &b, int val) care pune ambele variabile la valoarea val si demonstreaz-o in main().

Criterii de evaluare: ambele erori gasite si explicate, cod corectat care produce output asteptat, functia reseteaza implementata si apelata corect.

Vezi rezolvarea

Doua erori de gasit (nu iti dam codul final):

  1. triplica(int x) primeste o COPIE - adauga &: void triplica(int &x).
  2. swap(int a, int b) la fel - adauga & la ambii parametri: void swap(int &a, int &b).

Extindere: scrie void reseteaza(int &a, int &b, int val) care pune ambele variabile pe val (foloseste referinta la ambele!) si apeleaz-o in main cu doua variabile de test.

Criterii: cele 2 erori explicate corect, output final "nr triplicat: 12" si "dupa swap: 20 10", plus reseteaza() functionala si demonstrata.

Ce ai invatat astazi

  • Ai invatat ce sunt parametrii
  • Acum stii doua nume, doua roluri
  • Ai descoperit functii cu mai multi parametri
  • Ai explorat functia primeste o copie
  • Ai inteles functia lucreaza cu originalul - semnul &
  • Ai invatat de ce swap necesita referinta
  • Acum stii valori implicite - cand nu dai un argument

Vrei mai mult?

Provocare: Scrie o functie rotesteTrei(int &a, int &b, int &c) care roteste 3 variabile astfel: a primeste valoarea lui b, b primeste valoarea lui c, iar c primeste valoarea originala a lui a. Foloseste referinte (&). Testeaz-o cu 3 seturi diferite de valori si verifica de fiecare data ca rotatia e corecta.

De gandit: Functia swap_gresit (fara &) compileaza perfect, fara nicio eroare, desi nu face NIMIC util in main(). Ce iti spune asta despre increderea pe care o poti avea in "compileaza fara erori" ca dovada ca un cod functioneaza corect?

Deschidere: Trimiterea prin referinta (&) e motivul pentru care cin >> x functioneaza - cin trebuie sa modifice direct variabila x, nu o copie a ei, altfel n-ai putea citi niciodata nimic de la tastatura. De cate ori ai scris cin >> nr, ai folosit deja acest mecanism fara sa stii.

Urmatoarea lectie

Continua cu lectia urmatoare pentru a aprofunda cunostintele.

Continua →