fbpx

Functii si parametrii in C++

0

Refactorizarea

Refactorizarea (sau code refactoring) este un proces prin care codul este restructurat (pentru a putea fi reutilizat mai departe in alte contexte), fara a schimba in esenta, ceea ce el face. Definitia este cam lunga, dar mai pe scurt: restructuram codul astfel incat sa il facem mai usor de organizat.

Avem doua metode prin care putem face asta:

  • Folosind functii
    • Cu parametrii pasati printr-o valoare
    • Cu parametrii pasati printr-o referinta constanta
    • Cu parametrii pasati printr-o referinta non-constanta
  • Folosind fisiere separate
    • Fisiere sursa si headere

Functii in C++

#include    <iostream>
#include    <vector>
#include    <algorithm>

using namespace std;

vector < int > V;

int main()
{
    int N;
    cin >> N;

    for(int i = 1; i <= N; i++)
    {
        int val;
        cin >> val;
        V.push_back(val);
    }

    //Suma numerelor
    int sum = 0;
    for(unsigned int i = 0; i < V.size(); i++)
        sum = sum + V[i];
    cout << "Suma este: " << sum << "\n";

    //Media numerelor
    cout << "Media este: " <<  float(sum / V.size()) << "\n";

    //Elementul din mijloc
    unsigned int elemente = V.size();
    sort(V.begin(), V.end());
    int mijloc = elemente / 2;
    if (elemente % 2 == 1) // daca numarul de elemente este impar
        cout << V[mijloc];
    else // daca numarul de elemente este par
        cout << (V[mijloc-1] + V[mijloc])/2;

    return 0;
}

Sa ne imaginam un program care calculeaza suma si media elementelor dintr-un vector. De asemenea dorim sa aflam si elementul median. Anumite parti din acest program pot sa fie separate si reutilizate pe viitor:

  • Citirea vectorului
  • Calcularea sumei
  • Calcularea mediei aritmetice

Functiile pentru calcularea sumei si a mediei aritmetice nu efectueaza nici o operatie de citire sau scrierere, ceea ce le face sa fie mai de ajutor, in general.

Daca nu sunteti stapani pe bibleoteca <vector> puteti sa citii mai multe despre ea pe cppreference.com.

Evitati copierea

#include    <iostream>
#include    <vector>
#include    <algorithm>

using namespace std;

int suma(const vector < int > &V)
{
    const unsigned int elemente = V.size();
    if(elemente == 0)
        throw domain_error("Vectorul nu are elemente");

    int sum = 0;
    for(unsigned int i = 0; i < V.size(); i++)
        sum = sum + V[i];
    return sum;
}

float media(const vector < int > &V)
{
    const unsigned int elemente = V.size();
    if(elemente == 0)
        throw domain_error("Vectorul nu are elemente");

    int sum = 0;
    for(unsigned int i = 0; i < V.size(); i++)
        sum = sum + V[i];
    return float(sum / V.size());
}

int median(vector < int > V)
{
    const unsigned int elemente = V.size();
    if(elemente == 0)
        throw domain_error("Vectorul nu are elemente");

    sort(V.begin(), V.end());
    const int mijloc = elemente / 2;
    if (elemente%2 == 1) // daca numarul de elemente este impar
        return V[mijloc];
    else // daca numarul de elemente este par
        return (V[mijloc-1] + V[mijloc])/2;
}

void citire(int &N, vector < int > &V)
{
    cin >> N;
    for(int i = 1; i <= N; i++)
    {
        int val;
        cin >> val;
        V.push_back(val);
    }
}
int main()
{
    vector < int > Vector;
    int N;

    citire(N, Vector);

    //Suma numerelor
    cout << "Suma este: " << suma(Vector) << "\n";

    //Media numerelor
    cout << "Media este: " <<  media(Vector) << "\n";

    //Elementul din mijloc
    cout << "Elementul din mijloc este: " << median(Vector);

    return 0;
}

In functia noastra “median” este normal sa facem o copie a vectorului deoarece functia noastra schimba vectorul in sine (prin sortarea lui), dar poate in alte parti ale programului vom avea nevoie de vector asa cum a fost el introdus initial.

Din pacate copierea parametrilor mari este costisitoare si in general dorim sa o evitam. Uneori poate dorim sa returnam ceea ce am obtinut tot prin parametru, insa daca operam pe o copie, acest lucru este mai dificil.

O solutie in C++ (Pascal, C#, etc) o reprezinta parametrii prin referinta (sau reference parameters). In C++ acesti parametrii de referinta se marcheaza prin simbolul &.

Daca functia nu schimba parametrii, poate fi declarata ca si const (constanta).

Parametrii pasati printr-o referinta constanta

Parametrul “V” este doar o alta denumire pentru “Vector” (nu se copiaza).

Cuvantul “const” promite ca functia nu va schimba vectorul nostru “V” si compilatorul verifica acest lucru.

Alte utilizari alte const

Cuvantul “const” poate fi folosit si altfel:

  • Pentru a declara variabile constante (un fel de “#define”)
  • Pentru a declara parametrii si variabile locale cu valori fixe

Sfat: folositi const de fiecare data cand este posibil.

Alte exemple ale folosirii const

Pentru eficienta putem utiliza “const” atunci cand salvam variabila “V.size()” prin variabila “elemente”, care pe urma nu urmeaza sa se schimbe.

Functia de citire

Aceasta functie lucreaza de asemenea cu vectorul original (fara a-l copia), dar il schimba (pentru ca il umple cu elemente), asa ca parametrul “V” este apelat prin “&”, fara “const”.

Trei tipuri de parametrii

  • Parametrii pasati prin valoare:

int median(vector < int > V)

Parametrul este o noua variabila, initializandu-se ca si o copie a parametrului.

  • Parametrii pasati printr-o referinta:

float media(const vector < int > &V)

Parametrul este doar o alta denumire pentru parametrul nostru, dar functia l-ar putea schimba.

  • Parametrii pasati printr-o referinta constanta:

void citire(int &N, vector < int > &V)

Parametrul este doar o alta denumire pentru parametrul nostru, si functia nu il va schimba.

Alte folosiri ale accesarii prin &

Putem sa accesam prin referinta si atunci cand dorim sa refolosim aceeasi locatie din memorie (mult mai bine decat sa refolosim o valoare). De exemplu:

vector < int > v;
//...citirea...
int &x = v[3];
x = 1 + 2 * x;

 

Aici x nu este o noua variabila, ci o alta denumire pentru v[3]. Totul este schimbat prin x, dar orice schimbare este aplicata lui v[3].

Comentarii
Se incarca comentariile...

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More