This shows you the differences between two versions of the page.
|
poo-is-ab:laboratoare:01 [2025/09/30 10:20] razvan.cristea0106 [Asemănări C/C++] |
poo-is-ab:laboratoare:01 [2026/09/29 10:44] (current) razvan.cristea0106 [Asemănări C/C++] |
||
|---|---|---|---|
| Line 9: | Line 9: | ||
| * recunoască asemănările dintre limbajele C și C++ | * recunoască asemănările dintre limbajele C și C++ | ||
| * scrie un program simplu în limbajul C++ | * scrie un program simplu în limbajul C++ | ||
| - | * creeze un repository pe GitHub | ||
| * utilizeze comenzi elementare de git în terminal | * utilizeze comenzi elementare de git în terminal | ||
| + | * creeze un repository pe contul personal de GitHub | ||
| ==== Introducere ==== | ==== Introducere ==== | ||
| Line 26: | Line 26: | ||
| În continuare, vom descoperi asemănările dintre cele două limbaje de programare, ilustrând similaritățile dintre acestea prin exemple de cod concrete. | În continuare, vom descoperi asemănările dintre cele două limbaje de programare, ilustrând similaritățile dintre acestea prin exemple de cod concrete. | ||
| - | === Declararea și initializarea variabilelor === | + | === Declararea și inițializarea variabilelor === |
| Modul de declarare și de inițializare a variabilelor în cele 2 limbaje este același, avem aceleași tipuri de date precum: **int**, **float**, **char**, **double**, **unsigned int**, **long**, **unsigned long** etc. | Modul de declarare și de inițializare a variabilelor în cele 2 limbaje este același, avem aceleași tipuri de date precum: **int**, **float**, **char**, **double**, **unsigned int**, **long**, **unsigned long** etc. | ||
| Line 33: | Line 33: | ||
| int main() | int main() | ||
| { | { | ||
| - | int x = 3; // variabila de tip intreg | + | int x = 3; // variabila de tip intreg |
| - | float nr = 3.5f; // variabila de tip float | + | float nr = 3.5f; // variabila de tip float |
| - | double y = 10.6; // variabila de tip double | + | double y = 10.6; // variabila de tip double |
| - | char c = 'q'; // variabila de tip caracter | + | char c = 'q'; // variabila de tip caracter |
| - | long w = 1000000000; // variabila de tip long | + | long w = 1000000000; // variabila de tip long |
| - | return 0; | + | return 0; |
| } | } | ||
| </code> | </code> | ||
| Line 50: | Line 50: | ||
| int main() | int main() | ||
| { | { | ||
| - | int a = 8; | + | int a = 8; |
| - | int b = 5; | + | int b = 5; |
| - | int suma = a + b; | + | int suma = a + b; |
| - | int produs = a * b; | + | int produs = a * b; |
| - | int diferenta = a - b; | + | int diferenta = a - b; |
| - | float impartire = (float) a / b; // va avea valoarea 1.6 | + | float impartire = (float)a / b; // va avea valoarea 1.6 |
| - | int rest = a % b; // calculam restul impartirii lui a la b | + | int rest = a % b; // calculam restul impartirii lui a la b |
| - | return 0; | + | return 0; |
| } | } | ||
| </code> | </code> | ||
| Line 75: | Line 75: | ||
| <code cpp> | <code cpp> | ||
| - | if (conditie1) | + | if (conditie1) |
| { | { | ||
| - | // bloc de cod | + | // bloc de cod |
| } | } | ||
| else if (conditie2) | else if (conditie2) | ||
| { | { | ||
| - | // bloc de cod | + | // bloc de cod |
| } | } | ||
| else if (conditie3) | else if (conditie3) | ||
| { | { | ||
| - | // bloc de cod | + | // bloc de cod |
| } | } | ||
| ... | ... | ||
| else | else | ||
| { | { | ||
| - | // bloc de cod | + | // bloc de cod |
| } | } | ||
| </code> | </code> | ||
| - | Să luăm ca exemplu verificarea parității unui număr. Sțim că un număr este par dacă restul împărțirii lui la 2 este egal cu 0. | + | Să luăm ca exemplu verificarea parității unui număr. Știm că un număr este par dacă restul împărțirii lui la 2 este egal cu 0. |
| <code cpp> | <code cpp> | ||
| int main() | int main() | ||
| { | { | ||
| - | int x = 13; | + | int x = 13; |
| - | int estePar = -1; // variabila care are valoarea 0 daca numarul este impar si 1 daca este par | + | int estePar = -1; // variabila care are valoarea 0 daca numarul este impar si 1 daca este par |
| - | if (x % 2 == 0) | + | if (x % 2 == 0) |
| - | { | + | { |
| - | estePar = 1; | + | estePar = 1; |
| - | } | + | } |
| - | else | + | else |
| - | { | + | { |
| - | estePar = 0; | + | estePar = 0; |
| - | } | + | } |
| - | return 0; | + | return 0; |
| } | } | ||
| </code> | </code> | ||
| Line 117: | Line 117: | ||
| Instrucțiunea **switch** poate fi o alternativă mult mai elegantă atunci când vrem să înlocuim o secvență de instrucțiuni de forma **if -> else if -> ... -> else**. Deși pare o instrucțiune "demodată" aceasta este extrem de eficientă și de utilă atunci când ne dorim un cod rapid și ușor de citit. | Instrucțiunea **switch** poate fi o alternativă mult mai elegantă atunci când vrem să înlocuim o secvență de instrucțiuni de forma **if -> else if -> ... -> else**. Deși pare o instrucțiune "demodată" aceasta este extrem de eficientă și de utilă atunci când ne dorim un cod rapid și ușor de citit. | ||
| - | Forma generală a instrucțiunii swicth | + | Forma generală a instrucțiunii switch |
| <code cpp> | <code cpp> | ||
| Line 139: | Line 139: | ||
| int main() | int main() | ||
| { | { | ||
| - | int n = 4; | + | int n = 4; |
| - | switch (n) | + | switch (n) |
| - | { | + | { |
| - | case 0: | + | case 0: |
| - | n++; | + | n++; |
| - | break; | + | break; |
| - | case 1: | + | case 1: |
| - | n = n * 5 + 1; | + | n = n * 5 + 1; |
| - | break; | + | break; |
| - | case 2: | + | case 2: |
| - | n--; | + | n--; |
| - | break; | + | break; |
| - | case 3: | + | case 3: |
| - | n *= 5; | + | n *= 5; |
| - | break; | + | break; |
| - | case 4: | + | case 4: |
| - | n = n - 2 + n++ + n * 2; | + | n = n - 2 + n++ + n * 2; |
| - | break; | + | break; |
| - | default: | + | default: |
| - | n = 0; | + | n = 0; |
| - | break; | + | break; |
| - | } | + | } |
| - | return 0; | + | return 0; |
| } | } | ||
| </code> | </code> | ||
| Line 181: | Line 181: | ||
| for (start; conditie de continuare; pas) | for (start; conditie de continuare; pas) | ||
| { | { | ||
| - | // bloc de cod care se execută | + | // bloc de cod care se execută |
| } | } | ||
| </code> | </code> | ||
| Line 190: | Line 190: | ||
| int main() | int main() | ||
| { | { | ||
| - | int vector[10] = { 2, 4, 1, -4, 8, 10, 3, -5 }; | + | int nrElemente = 8; |
| - | int nrElemente = 8; | + | int vector[10] = { 2, 4, 1, -4, 8, 10, 3, -5 }; |
| - | for (int index = 0; index < nrElemente; index++) | + | for (int index = 0; index < nrElemente; index++) |
| - | { | + | { |
| - | vector[index] += 5; // echivalent cu a scrie vector[index] = vector[index] + 5; | + | vector[index] += 5; // echivalent cu a scrie vector[index] = vector[index] + 5; |
| - | } | + | } |
| - | return 0; | + | return 0; |
| } | } | ||
| </code> | </code> | ||
| Line 211: | Line 211: | ||
| while (expresie) | while (expresie) | ||
| { | { | ||
| - | // bloc de cod care se execută | + | // bloc de cod care se execută |
| } | } | ||
| </code> | </code> | ||
| Line 220: | Line 220: | ||
| int main() | int main() | ||
| { | { | ||
| - | int vector[10] = { 2, 4, 1, -4, 8, 10, 3, -5 }; | + | int nrElemente = 8; |
| - | int nrElemente = 8; | + | int vector[10] = { 2, 4, 1, -4, 8, 10, 3, -5 }; |
| - | int index = 0; | + | int index = 0; |
| - | while (index != nrElemente) | + | while (index != nrElemente) |
| - | { | + | { |
| - | vector[index] += 5; | + | vector[index] += 5; |
| - | index++; | + | index++; |
| - | } | + | } |
| - | return 0; | + | return 0; |
| } | } | ||
| </code> | </code> | ||
| - | Instrucțiunea **do-while** este o variantă a buclei **while**, cu o diferență esențială: în bucla **do-while**, condiția de verificare este evaluată **după** ce codul din interiorul buclei a fost executat, **nu** înainte. Aceasta înseamnă că blocul de cod din bucla **do-while** va fi executat cel puțin **o dată**, indiferent de valoare de adevăr a expresiei din clauza while. | + | Instrucțiunea **do-while** este o variantă a buclei **while**, cu o diferență esențială: în bucla **do-while**, condiția de verificare este evaluată **după** ce codul din interiorul buclei a fost executat, **nu** înainte. Aceasta înseamnă că blocul de cod din bucla **do-while** va fi executat cel puțin **o dată**, indiferent de valoarea de adevăr a expresiei din clauza while. |
| Forma generală a instrucțiunii do-while | Forma generală a instrucțiunii do-while | ||
| Line 251: | Line 251: | ||
| int main() | int main() | ||
| { | { | ||
| - | int vector[10] = { 2, 4, 1, -4, 8, 10, 3, -5 }; | + | int nrElemente = 8; |
| - | int nrElemente = 8; | + | int vector[10] = { 2, 4, 1, -4, 8, 10, 3, -5 }; |
| - | int index = 0; | + | int index = 0; |
| - | do | + | do |
| - | { | + | { |
| - | vector[index] += 5; | + | vector[index] += 5; |
| - | index++; | + | index++; |
| - | } while (index != nrElemente); | + | } while (index != nrElemente); |
| - | return 0; | + | return 0; |
| } | } | ||
| </code> | </code> | ||
| <note>Puteți folosi oricare din cele 3 instrucțiuni repetitive, important este ca efectul codului scris de voi să fie cel dorit și să fiți atenți la cum puneți condițiile.</note> | <note>Puteți folosi oricare din cele 3 instrucțiuni repetitive, important este ca efectul codului scris de voi să fie cel dorit și să fiți atenți la cum puneți condițiile.</note> | ||
| - | |||
| - | <note warning>Trebuie menționat faptul că șansele de a intra într-o **buclă infinită** sunt mai mari atunci când folosim instrucțiunea **while**, deoarece putem omite să modificăm **pasul** la fiecare iterație. Instrucțiunea **for** este mai sigură din acest punct de vedere, dar trebuie menționat că putem avea un **infinite loop** chiar și dacă folosim cum nu trebuie for-ul. | ||
| - | </note> | ||
| Pentru a avea un program care rulează la infinit utilizând bucla **for** putem să nu specificăm nimic între parantezele rotunde ale instrucțiunii. | Pentru a avea un program care rulează la infinit utilizând bucla **for** putem să nu specificăm nimic între parantezele rotunde ale instrucțiunii. | ||
| Line 277: | Line 274: | ||
| int main() | int main() | ||
| { | { | ||
| - | int x = 8; | + | int x = 8; |
| - | for ( ; ; ) | + | for ( ; ; ) |
| - | { | + | { |
| - | x = x * 10; | + | x = x * 10; |
| - | } | + | } |
| - | return 0; | + | return 0; |
| } | } | ||
| </code> | </code> | ||
| Astfel programul nu va mai ieși din bucla **for** și va multiplica valoarea lui x de 10 ori la infinit. | Astfel programul nu va mai ieși din bucla **for** și va multiplica valoarea lui x de 10 ori la infinit. | ||
| + | |||
| + | <note warning>Trebuie menționat faptul că șansele de a intra într-o **buclă infinită** sunt mai mari atunci când folosim instrucțiunea **while**, deoarece putem omite să modificăm **pasul** la fiecare iterație. Instrucțiunea **for** este mai sigură din acest punct de vedere, dar trebuie menționat că putem avea un **infinite loop** chiar și dacă folosim cum nu trebuie for-ul. | ||
| + | </note> | ||
| === Utilizarea pointerilor === | === Utilizarea pointerilor === | ||
| Line 294: | Line 294: | ||
| C++, la fel ca C-ul, are tipuri de date speciale denumite **pointeri**, care sunt utile atunci când vrem să modificăm o valoare de la o anumită adresă din memorie. | C++, la fel ca C-ul, are tipuri de date speciale denumite **pointeri**, care sunt utile atunci când vrem să modificăm o valoare de la o anumită adresă din memorie. | ||
| - | **Un pointer** este un tip de date care stochează **o adresă** din memorie la un anumit moment de timp în program. Să luam spre exemplu următoarea secvență de cod. | + | **Un pointer** este un tip de date care stochează **o adresă** din memorie la un anumit moment de timp în program. Să luăm spre exemplu următoarea secvență de cod. |
| <code cpp> | <code cpp> | ||
| int main() | int main() | ||
| { | { | ||
| - | int x = 10; | + | int x = 10; |
| - | int* ptr = &x; | + | int* ptr = &x; |
| - | return 0; | + | return 0; |
| } | } | ||
| </code> | </code> | ||
| - | Se poate observa că avem o varibilă de **tip int** care a fost inițializată cu valoarea 10 și un **pointer la int** care a fost inițializat cu adresa lui x. Într-o ilustrare simplificată putem înțelege efectiv ce s-a întâmplat pe lina a doua de cod. | + | Se poate observa că avem o variabilă de **tip int** care a fost inițializată cu valoarea 10 și un **pointer la int** care a fost inițializat cu adresa lui x. Într-o ilustrare simplificată putem înțelege efectiv ce s-a întâmplat pe linia a doua de cod. |
| {{ :poo-is-ab:laboratoare:pointer_logic.jpg |}} | {{ :poo-is-ab:laboratoare:pointer_logic.jpg |}} | ||
| Line 317: | Line 317: | ||
| int main() | int main() | ||
| { | { | ||
| - | int x = 10; | + | int x = 10; |
| - | int y = 2; | + | int y = 2; |
| - | int* ptr = &x, & y; // eroare de compilare un pointer nu poate arata catre 2 adrese simultan | + | int* ptr = &x, & y; // eroare de compilare un pointer nu poate arata catre 2 adrese simultan |
| - | return 0; | + | return 0; |
| } | } | ||
| </code> | </code> | ||
| Line 330: | Line 330: | ||
| {{ :poo-is-ab:laboratoare:incorrect_pointer_logic.jpg |}} | {{ :poo-is-ab:laboratoare:incorrect_pointer_logic.jpg |}} | ||
| - | Trebuie însă înțeles faptul că această situație **nu** este permisă și **nu** are sens. E ca și cum ați vrea să arătați **simultan** cu **același deget** spre două persoane **diferite** ceea ce este fizic **imposibil**. | + | Trebuie însă înțeles faptul că această situație **nu** este permisă și **nu** are sens. E ca și cum vă doriți să arătați **simultan** cu **același deget** spre două persoane **diferite** ceea ce este fizic **imposibil**. |
| În schimb situația următoare este permisă și complet validă. | În schimb situația următoare este permisă și complet validă. | ||
| Line 347: | Line 347: | ||
| </code> | </code> | ||
| - | Dacă un pointer arată către adresa de memorie a unei variabile, cum putem accesa totuși valoarea de la acea adresă spre care pointează pointerul nostru? Răspunsul este unul foarte simplu și anume printr-o operație specifică pointerilor cunoscută sub numele de __**dereferențiere**__. | + | Dacă un pointer arată către adresa de memorie a unei variabile, cum putem accesa totuși valoarea de la acea adresă spre care pointează pointerul nostru? Răspunsul este unul foarte simplu și anume printr-o operație specifică pointerilor cunoscută sub numele de **dereferențiere**. |
| <code cpp> | <code cpp> | ||
| int main() | int main() | ||
| { | { | ||
| - | int x = 10; | + | int x = 10; |
| - | int* ptr = &x; // declararea unei variabile de tip pointer la int si initializarea acesteia cu adresa lui x | + | int* ptr = &x; // declararea unei variabile de tip pointer la int si initializarea acesteia cu adresa lui x |
| + | int y = *ptr; // dereferentierea pointerului ptr si stocarea valorii in variabila y (echivalent cu a scrie direct int y = x;) | ||
| - | int y = *ptr; // dereferentierea pointerului ptr si stocarea valorii in variabila y (echivalent cu a scrie direct int y = x;) | + | return 0; |
| - | + | ||
| - | return 0; | + | |
| } | } | ||
| </code> | </code> | ||
| Line 368: | Line 367: | ||
| int main() | int main() | ||
| { | { | ||
| - | int x = 10; | + | int x = 10; |
| - | int* ptr = &x; | + | int* ptr = &x; |
| - | *ptr = 4; | + | *ptr = 4; |
| - | x -= 2; | + | x -= 2; |
| - | *ptr *= 2; | + | *ptr *= 2; |
| - | *ptr += 10; | + | *ptr += 10; |
| - | // care este valoarea lui x dupa ce s-au executat toate liniile de mai sus | + | // care este valoarea lui x dupa ce s-au executat toate liniile de mai sus |
| - | return 0; | + | return 0; |
| } | } | ||
| </code> | </code> | ||
| Line 387: | Line 386: | ||
| int main() | int main() | ||
| { | { | ||
| - | int* ptr = NULL; | + | int* ptr = NULL; |
| - | + | return 0; | |
| - | return 0; | + | |
| } | } | ||
| </code> | </code> | ||
| - | <note tip>Vom folosi foarte mult pointerii în acest semestru, iar pentru cei mai puțini familiarizați puteți urmări tutorialul urmator: [[https://youtu.be/zuegQmMdy8M?si=kxUOPspywfF5gR00|C++ Pointers]] | + | <note tip>Vom folosi foarte mult pointerii în acest semestru, iar pentru cei mai puțini familiarizați puteți urmări tutorialul următor: [[https://youtu.be/zuegQmMdy8M?si=kxUOPspywfF5gR00|C++ Pointers]] |
| </note> | </note> | ||
| Line 410: | Line 408: | ||
| <note>A **doua** componentă împreună cu cea de a **treia** sunt cunoscute și sub denumirea de **semnătură a funcției**.</note> | <note>A **doua** componentă împreună cu cea de a **treia** sunt cunoscute și sub denumirea de **semnătură a funcției**.</note> | ||
| - | Dacă îmbinăm cele 3 componente putem constata ca forma generală a unei funcții în C/C++ va arăta în felul următor -> **return_type name(parameters)**. | + | Dacă îmbinăm cele 3 componente putem constata că forma generală a unei funcții în C/C++ va arăta în felul următor -> **return_type name(parameters)**. |
| În continuare vom vedea câteva exemple de declarări pentru funcții definite de către programator. | În continuare vom vedea câteva exemple de declarări pentru funcții definite de către programator. | ||
| Line 469: | Line 467: | ||
| int dif = diferenta(x, y); | int dif = diferenta(x, y); | ||
| - | |||
| return 0; | return 0; | ||
| } | } | ||
| </code> | </code> | ||
| - | Variabilelor **x** și **y** li se face la fiecare câte o copie atunci când se apelează funcția **diferenta**. Nu doar că aceste copii sunt pierdute la încheierea execuției acestei funcții ba chiar și rezultatul întors de această funcție este transmis prin valoare. Deci în total avem 3 copii care s-au făcut în momentul în care linia de cod ''int dif = diferenta(x, y);'' a fost executată. | + | Variabilelor **x** și **y** li se face câte o copie atunci când se apelează funcția **diferenta**. Nu doar că aceste copii sunt pierdute la încheierea execuției acestei funcții ba chiar și rezultatul întors de această funcție este transmis prin valoare. Deci în total avem 3 copii care s-au făcut în momentul în care linia de cod ''int dif = diferenta(x, y);'' a fost executată. |
| Pentru a vedea efectiv dezavantajul transmiterii parametrilor prin valoare vom implementa o funcție care realizează interschimbarea valorilor a două variabile întregi. | Pentru a vedea efectiv dezavantajul transmiterii parametrilor prin valoare vom implementa o funcție care realizează interschimbarea valorilor a două variabile întregi. | ||
| Line 492: | Line 489: | ||
| interschimbare(x, y); // interschimbarea se realizeaza doar la nivelul functiei (x = 5, y = 21) | interschimbare(x, y); // interschimbarea se realizeaza doar la nivelul functiei (x = 5, y = 21) | ||
| - | |||
| return 0; | return 0; | ||
| } | } | ||
| Line 499: | Line 495: | ||
| Deși parametrii **a** și **b** ai funcției **interschimbare** sunt copii ale variabilelor **x** și **y** din programul principal, aceștia sunt doar variabile locale care există doar în interiorul funcției. Astfel, valoarea lui **a** va deveni 21 și cea a lui **b** va fi 5, însă aceste modificări se aplică doar la nivel local. După terminarea execuției funcției, variabilele originale **x** și **y** nu vor fi afectate și vor păstra valorile inițiale, deoarece modificările din interiorul funcției nu se propagă în afara ei. | Deși parametrii **a** și **b** ai funcției **interschimbare** sunt copii ale variabilelor **x** și **y** din programul principal, aceștia sunt doar variabile locale care există doar în interiorul funcției. Astfel, valoarea lui **a** va deveni 21 și cea a lui **b** va fi 5, însă aceste modificări se aplică doar la nivel local. După terminarea execuției funcției, variabilele originale **x** și **y** nu vor fi afectate și vor păstra valorile inițiale, deoarece modificările din interiorul funcției nu se propagă în afara ei. | ||
| - | Vom soluționa problema de mai sus utilizând un alt mod de transmitere a parametrilor și anume cea prin intermediul pointerilor. | + | Vom soluționa problema de mai sus utilizând un alt mod de transmitere a parametrilor și anume cel prin intermediul pointerilor. |
| __**Transmiterea parametrilor prin pointer**__ | __**Transmiterea parametrilor prin pointer**__ | ||
| Line 526: | Line 522: | ||
| interschimbare(&x, &y); // modificarile se vor rasfrange asupra lui x si y (x = 21, y = 5) | interschimbare(&x, &y); // modificarile se vor rasfrange asupra lui x si y (x = 21, y = 5) | ||
| - | |||
| return 0; | return 0; | ||
| } | } | ||
| </code> | </code> | ||
| - | Deși parametrii **a** și **b** sunt tot variabile locale în funcția **interschimbare**, faptul că aceștia sunt pointeri schimbă modul în care subrogramul funcționează. În loc să fie doar copii ale valorilor lui **x** și **y**, acești pointeri conțin adresele de memorie ale variabilelor originale. Astfel, orice modificare efectuată asupra variabilelor accesate prin intermediul pointerilor va afecta **direct** valorile lui **x** și **y**. Acest mecanism permite funcției să modifice variabilele din programul principal, deoarece nu lucrează cu copii ale acestora, ci direct cu locațiile lor din memorie. | + | Deși parametrii **a** și **b** sunt tot variabile locale în funcția **interschimbare**, faptul că aceștia sunt pointeri schimbă modul în care subprogramul funcționează. În loc să fie doar copii ale valorilor lui **x** și **y**, acești pointeri conțin adresele de memorie ale variabilelor originale. Astfel, orice modificare efectuată asupra variabilelor accesate prin intermediul pointerilor va afecta **direct** valorile lui **x** și **y**. Acest mecanism permite funcției să modifice variabilele din programul principal, deoarece nu lucrează cu copii ale acestora, ci direct cu locațiile lor din memorie. |
| - | <note>Putem folosi transmiterea prin pointer atunci când vrem sa facem anumite modificări asupra variabilelor, dar se poate utiliza și atunci când ne dorim doar să **evităm** copierea inutilă a valorilor, spre exemplu afisarea valorilor unui vector de numere întregi.</note> | + | <note>Putem folosi transmiterea prin pointer atunci când vrem să facem anumite modificări asupra variabilelor, dar se poate utiliza și atunci când ne dorim doar să **evităm** copierea inutilă a valorilor, spre exemplu afișarea valorilor unui vector de numere întregi.</note> |
| <code cpp> | <code cpp> | ||
| Line 540: | Line 535: | ||
| void afisareVector(int* v, int* n) | void afisareVector(int* v, int* n) | ||
| { | { | ||
| - | for (int index = 0; index < *n; index++) | + | for (int index = 0; index < *n; index++) |
| - | { | + | { |
| - | std::cout << v[index] << " "; | + | std::cout << v[index] << " "; |
| - | } | + | } |
| } | } | ||
| int main() | int main() | ||
| { | { | ||
| - | int nrElemente = 10; | + | int nrElemente = 10; |
| - | int vec[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; | + | int vec[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; |
| - | afisareVector(vec, &nrElemente); // sau un apel echivalent afisareVector(&vec[0], &nrElemente); | + | afisareVector(vec, &nrElemente); // sau un apel echivalent afisareVector(&vec[0], &nrElemente); |
| - | + | return 0; | |
| - | return 0; | + | |
| } | } | ||
| </code> | </code> | ||
| Line 570: | Line 564: | ||
| void func() | void func() | ||
| { | { | ||
| - | // bloc de cod | + | // bloc de cod |
| } | } | ||
| int main() | int main() | ||
| { | { | ||
| - | std::cout << func << '\n'; | + | std::cout << func << '\n'; |
| - | + | return 0; | |
| - | return 0; | + | |
| } | } | ||
| </code> | </code> | ||
| Line 592: | Line 585: | ||
| void func() | void func() | ||
| { | { | ||
| - | // bloc de cod | + | // bloc de cod |
| } | } | ||
| int main() | int main() | ||
| { | { | ||
| - | void (*functionPtr)() = func; // declararea si initializarea unui function pointer cu adresa functiei func | + | void (*functionPtr)() = func; // declararea si initializarea unui function pointer cu adresa functiei func |
| - | std::cout << func << '\n'; | + | std::cout << func << '\n'; |
| - | std::cout << functionPtr << '\n'; // afiseaza aceeasi adresa cu cea de la linia anterioara | + | std::cout << functionPtr << '\n'; // afiseaza aceeasi adresa cu cea de la linia anterioara |
| - | return 0; | + | return 0; |
| } | } | ||
| </code> | </code> | ||
| Line 617: | Line 610: | ||
| void interschimbare(int* a, int* b) | void interschimbare(int* a, int* b) | ||
| { | { | ||
| - | if (a == NULL || b == NULL) | + | if (a == NULL || b == NULL) |
| - | { | + | { |
| - | return; | + | return; |
| - | } | + | } |
| - | int auxiliar = *a; | + | int auxiliar = *a; |
| - | *a = *b; | + | *a = *b; |
| - | *b = auxiliar; | + | *b = auxiliar; |
| } | } | ||
| void sortareVectorCrescator(int* vector, int* nrElemente) | void sortareVectorCrescator(int* vector, int* nrElemente) | ||
| { | { | ||
| - | for (int i = 0; i < *nrElemente - 1; i++) | + | for (int i = 0; i < *nrElemente - 1; i++) |
| - | { | + | { |
| - | for (int j = i + 1; j < *nrElemente; j++) | + | for (int j = i + 1; j < *nrElemente; j++) |
| - | { | + | { |
| - | if (vector[i] > vector[j]) | + | if (vector[i] > vector[j]) |
| - | { | + | { |
| - | interschimbare(&vector[i], &vector[j]); | + | interschimbare(&vector[i], &vector[j]); |
| - | } | + | } |
| - | } | + | } |
| - | } | + | } |
| } | } | ||
| void sortareVectorDescrescator(int* vector, int* nrElemente) | void sortareVectorDescrescator(int* vector, int* nrElemente) | ||
| { | { | ||
| - | for (int i = 0; i < *nrElemente - 1; i++) | + | for (int i = 0; i < *nrElemente - 1; i++) |
| - | { | + | { |
| - | for (int j = i + 1; j < *nrElemente; j++) | + | for (int j = i + 1; j < *nrElemente; j++) |
| - | { | + | { |
| - | if (vector[i] < vector[j]) | + | if (vector[i] < vector[j]) |
| - | { | + | { |
| - | interschimbare(&vector[i], &vector[j]); | + | interschimbare(&vector[i], &vector[j]); |
| - | } | + | } |
| - | } | + | } |
| - | } | + | } |
| } | } | ||
| void afisareVector(int* vector, int* nrElemente) | void afisareVector(int* vector, int* nrElemente) | ||
| { | { | ||
| - | for (int index = 0; index < *nrElemente; index++) | + | for (int index = 0; index < *nrElemente; index++) |
| - | { | + | { |
| - | std::cout << vector[index] << ' '; | + | std::cout << vector[index] << ' '; |
| - | } | + | } |
| - | std::cout << '\n'; | + | std::cout << '\n'; |
| } | } | ||
| int main() | int main() | ||
| { | { | ||
| - | int vector[10] = { 2, 1, 4, -3, 0, 5, -1, 8, 10, 9 }; | + | int nrElemente = 10; |
| - | int nrElemente = 10; | + | int vector[10] = { 2, 1, 4, -3, 0, 5, -1, 8, 10, 9 }; |
| - | std::cout << "Vectorul sortat crescator este: "; | + | std::cout << "Vectorul sortat crescator este: "; |
| - | sortareVectorCrescator(vector, &nrElemente); | + | sortareVectorCrescator(vector, &nrElemente); |
| - | afisareVector(vector, &nrElemente); | + | afisareVector(vector, &nrElemente); |
| - | std::cout << "\nVectorul sortat descrescator este: "; | + | std::cout << "\nVectorul sortat descrescator este: "; |
| - | sortareVectorDescrescator(vector, &nrElemente); | + | sortareVectorDescrescator(vector, &nrElemente); |
| - | afisareVector(vector, &nrElemente); | + | afisareVector(vector, &nrElemente); |
| - | + | return 0; | |
| - | return 0; | + | |
| } | } | ||
| </code> | </code> | ||
| Line 692: | Line 684: | ||
| void interschimbare(int* a, int* b) | void interschimbare(int* a, int* b) | ||
| { | { | ||
| - | if (a == NULL || b == NULL) | + | if (a == NULL || b == NULL) |
| - | { | + | { |
| - | return; | + | return; |
| - | } | + | } |
| - | int auxiliar = *a; | + | int auxiliar = *a; |
| - | *a = *b; | + | *a = *b; |
| - | *b = auxiliar; | + | *b = auxiliar; |
| } | } | ||
| bool ordonareCrescatoare(int a, int b) | bool ordonareCrescatoare(int a, int b) | ||
| { | { | ||
| - | return a < b; | + | return a < b; |
| } | } | ||
| bool ordonareDescrescatoare(int a, int b) | bool ordonareDescrescatoare(int a, int b) | ||
| { | { | ||
| - | return a > b; | + | return a > b; |
| } | } | ||
| void sortareVector(int* vector, int* nrElemente, bool (*comparator)(int, int)) | void sortareVector(int* vector, int* nrElemente, bool (*comparator)(int, int)) | ||
| { | { | ||
| - | for (int i = 0; i < *nrElemente - 1; i++) | + | for (int i = 0; i < *nrElemente - 1; i++) |
| - | { | + | { |
| - | for (int j = i + 1; j < *nrElemente; j++) | + | for (int j = i + 1; j < *nrElemente; j++) |
| - | { | + | { |
| - | if (comparator(vector[i], vector[j]) == false) | + | if (comparator(vector[i], vector[j]) == false) |
| - | { | + | { |
| - | interschimbare(&vector[i], &vector[j]); | + | interschimbare(&vector[i], &vector[j]); |
| - | } | + | } |
| - | } | + | } |
| - | } | + | } |
| } | } | ||
| void afisareVector(int* vector, int* nrElemente) | void afisareVector(int* vector, int* nrElemente) | ||
| { | { | ||
| - | for (int index = 0; index < *nrElemente; index++) | + | for (int index = 0; index < *nrElemente; index++) |
| - | { | + | { |
| - | std::cout << vector[index] << ' '; | + | std::cout << vector[index] << ' '; |
| - | } | + | } |
| - | std::cout << '\n'; | + | std::cout << '\n'; |
| } | } | ||
| int main() | int main() | ||
| { | { | ||
| - | int vector[10] = { 2, 1, 4, -3, 0, 5, -1, 8, 10, 9 }; | + | int nrElemente = 10; |
| - | int nrElemente = 10; | + | int vector[10] = { 2, 1, 4, -3, 0, 5, -1, 8, 10, 9 }; |
| - | std::cout << "Vectorul sortat crescator este: "; | + | std::cout << "Vectorul sortat crescator este: "; |
| - | sortareVector(vector, &nrElemente, ordonareCrescatoare); | + | sortareVector(vector, &nrElemente, ordonareCrescatoare); |
| - | afisareVector(vector, &nrElemente); | + | afisareVector(vector, &nrElemente); |
| - | std::cout << "\nVectorul sortat descrescator este: "; | + | std::cout << "\nVectorul sortat descrescator este: "; |
| - | sortareVector(vector, &nrElemente, ordonareDescrescatoare); | + | sortareVector(vector, &nrElemente, ordonareDescrescatoare); |
| - | afisareVector(vector, &nrElemente); | + | afisareVector(vector, &nrElemente); |
| - | + | return 0; | |
| - | return 0; | + | |
| } | } | ||
| </code> | </code> | ||
| - | Se poate observa cât de elegant am evitat acum codul duplicat prin construirea a doi comparatori (cele două funcții care întorc o valoare booleană) pentru a decide ordinea de sortare și trimiterea adreselor acestora ca al treilea parametru de la funcția de sortare. Așadar prin utilizarea function pointer-ului ca parametru beneficiem de flexibilitate și eleganță în cod chiar dacă sintaxa nu este cea mai prietenoasă. Acesta este doar un simplu exemplu demonstrativ de utilizare a pointerilor la funcții. Pentru mai multe exemple de cum pot fi folosți pointerii la funcții puteți citi de [[https://www.geeksforgeeks.org/function-pointer-in-c/|aici]]. | + | Se poate observa cât de elegant am evitat acum codul duplicat prin construirea a doi comparatori (cele două funcții care întorc o valoare booleană) pentru a decide ordinea de sortare și trimiterea adreselor acestora ca al treilea parametru de la funcția de sortare. Așadar prin utilizarea function pointer-ului ca parametru beneficiem de flexibilitate și eleganță în cod chiar dacă sintaxa nu este cea mai prietenoasă. Acesta este doar un simplu exemplu demonstrativ de utilizare a pointerilor la funcții. Pentru mai multe exemple de cum pot fi folosiți pointerii la funcții puteți citi de [[https://www.geeksforgeeks.org/function-pointer-in-c/|aici]]. |
| <note important>Tipul de date **bool** în C++ este un **tip de bază**, care simplifică exprimarea condițiilor în programare. O variabilă booleană poate avea doar două valori: **true** sau **false**, făcând astfel codul mai clar și mai ușor de înțeles. Se recomandă utilizarea tipului **bool** în locul tipului **int** atunci când rezultatul unei comparații este strict **adevărat** sau **fals**. În C, pentru a folosi acest tip de date, este necesară includerea antetului **stdbool.h** prin directiva ''#include <stdbool.h>'' la începutul programului.</note> | <note important>Tipul de date **bool** în C++ este un **tip de bază**, care simplifică exprimarea condițiilor în programare. O variabilă booleană poate avea doar două valori: **true** sau **false**, făcând astfel codul mai clar și mai ușor de înțeles. Se recomandă utilizarea tipului **bool** în locul tipului **int** atunci când rezultatul unei comparații este strict **adevărat** sau **fals**. În C, pentru a folosi acest tip de date, este necesară includerea antetului **stdbool.h** prin directiva ''#include <stdbool.h>'' la începutul programului.</note> | ||
| Line 762: | Line 753: | ||
| === Variabile constante === | === Variabile constante === | ||
| - | La fel ca în C, în C++ putem declara variabile constante folosind cuvântul cheie **const**. Așa cum le spune și numele variabilele constante sunt cele care odată inițializate cu o valoare **nu** mai pot fi modificate. | + | La fel ca în C, în C++ putem declara variabile constante folosind cuvântul cheie **const**. Așa cum le spune și numele variabilele constante sunt acea categorie de variabile care odată ce au fost inițializate cu o valoare **nu** mai pot fi modificate ulterior. |
| - | <note warning>O **variabilă constantă** se ințializează pe linia unde a fost **declarată** altfel va genera o eroare de compilare.</note> | + | <note warning>O **variabilă constantă** se inițializează pe linia unde a fost **declarată** altfel va genera o eroare de compilare.</note> |
| == Utilizarea keyword-ului const pe variabile obișnuite == | == Utilizarea keyword-ului const pe variabile obișnuite == | ||
| Line 773: | Line 764: | ||
| int main() | int main() | ||
| { | { | ||
| - | const float pi = 3.14f; // variabila constanta corect declarata | + | const float pi = 3.14f; // variabila constanta corect declarata |
| - | const double k; // eroare de compilare variabila constanta este neinitializata | + | /* float const pi = 3.14f // era de asemenea corect, fiind doar o alta forma de scriere */ |
| + | const double k; // eroare de compilare variabila constanta este declarata dar neinitializata | ||
| - | int a = 2; | + | int a = 2; |
| - | int b = 3; | + | int b = 3; |
| - | const int suma = a + b; // corect | + | const int suma = a + b; // corect |
| + | suma = 20; // incorect, o variabila constanta nu mai poate fi modificata dupa ce a fost declarata si initializata | ||
| - | suma = 20; // incorect, o variabila constanta nu mai poate fi modificata dupa declarare si initializare | + | return 0; |
| - | + | ||
| - | return 0; | + | |
| } | } | ||
| </code> | </code> | ||
| Line 796: | Line 787: | ||
| int a = 2; | int a = 2; | ||
| int b = 3; | int b = 3; | ||
| + | |||
| + | // Situatia 1 | ||
| // Pointer la un int, dar pointerul nu poate modifica valoarea la care pointeaza | // Pointer la un int, dar pointerul nu poate modifica valoarea la care pointeaza | ||
| Line 804: | Line 797: | ||
| // P2 este un pointer la un int constant (valoarea la care pointeaza nu poate fi modificata prin intermediul lui p2) | // P2 este un pointer la un int constant (valoarea la care pointeaza nu poate fi modificata prin intermediul lui p2) | ||
| int const* p2 = &b; | int const* p2 = &b; | ||
| + | |||
| + | // Situatia 2 | ||
| + | |||
| + | // Pointer constant la un int | ||
| + | // P3 este un pointer constant la un int (pointerul in sine nu poate fi schimbat, dar valoarea la care pointeaza poate fi modificata) | ||
| + | int* const p3 = &a; | ||
| + | |||
| + | // Situatia 3 | ||
| // Pointer constant la un int constant | // Pointer constant la un int constant | ||
| - | // P3 este un pointer constant la un int constant si pointerul în sine nu poate fi schimbat (nu poate pointa catre alta adresa) | + | // P4 este un pointer constant la un int constant si pointerul in sine nu poate fi schimbat (nu poate pointa catre alta adresa) |
| - | const int* const p3 = &a; | + | const int* const p4 = &a; |
| - | // Efectiv aceeași declaratie ca p3, dar cu sintaxa diferita | + | // Efectiv aceeași declaratie ca p4, dar cu sintaxa diferita |
| - | // P4 este un pointer constant la un int constant si pointerul în sine nu poate fi schimbat | + | // P5 este un pointer constant la un int constant si pointerul in sine nu poate fi schimbat |
| - | int const* const p4 = &a; | + | int const* const p5 = &a; |
| *p1 = 5; // eroare de compilare | *p1 = 5; // eroare de compilare | ||
| - | p1 = &b; // corect | + | p1 = &b; // valid |
| *p2 = *p1; // eroare de compilare | *p2 = *p1; // eroare de compilare | ||
| p2 = p1; // valid | p2 = p1; // valid | ||
| - | *p3 = 50; // eroare de compilare | + | *p3 = *p2; // valid |
| - | p3 = p2; // eroare de compilare | + | p3 = &b; // eroare de compilare |
| + | |||
| + | *p4 = 50; // eroare de compilare | ||
| + | p4 = p2; // eroare de compilare | ||
| - | p4 = p1; // eroare de compilare | + | p5 = p1; // eroare de compilare |
| - | *p4 = 10; // eroare de compilare | + | *p5 = 10; // eroare de compilare |
| return 0; | return 0; | ||
| Line 843: | Line 847: | ||
| * **Istoricul modificărilor** – putem reveni oricând la o versiune anterioară. | * **Istoricul modificărilor** – putem reveni oricând la o versiune anterioară. | ||
| * **Gestionarea branch-urilor** – dezvoltare paralelă și integrare prin **merge**. | * **Gestionarea branch-urilor** – dezvoltare paralelă și integrare prin **merge**. | ||
| - | * **Integrare cu unelte moderne** – paltforma GitHub permite **code review**, **issue tracking** și **CI/CD**. | + | * **Integrare cu unelte moderne** – platforma GitHub permite **code review**, **issue tracking** și **CI/CD**. |
| === Termeni specifici === | === Termeni specifici === | ||
| Line 903: | Line 907: | ||
| git branch -a # afișează toate branch-urile (locale și remote) | git branch -a # afișează toate branch-urile (locale și remote) | ||
| git checkout nume_branch # schimbă branch-ul curent | git checkout nume_branch # schimbă branch-ul curent | ||
| - | git branch -b nou_branch # creează un branch nou și trece pe el | + | git branch -b nou_branch # creează un branch nou și se mută pe el |
| git merge branch_modificari # unirea unui branch în branch-ul curent | git merge branch_modificari # unirea unui branch în branch-ul curent | ||
| </code> | </code> | ||
| Line 937: | Line 941: | ||
| === Ce ar trebui să facem? === | === Ce ar trebui să facem? === | ||
| - | - Să instalăm Git pe mașinile noastre | + | - Să instalăm **Git** pe mașinile noastre |
| - Să avem sau să ne facem un cont pe platforma **GitHub** | - Să avem sau să ne facem un cont pe platforma **GitHub** | ||
| - | - La **prima** utilizare după ce am instalat Git-ul trebuie să rulăm comenzile **git config %%--%%global user_name** și **git config %%--%%global user_email** | + | - La **prima** utilizare după ce am instalat Git-ul trebuie să rulăm comenzile **git config %%--%%global user.name** și **git config %%--%%global user.email** |
| - Să ne setăm o cheie **ssh** conform instrucțiunilor de [[https://www.youtube.com/watch?v=2kuG9ElVMhM|aici]]. | - Să ne setăm o cheie **ssh** conform instrucțiunilor de [[https://www.youtube.com/watch?v=2kuG9ElVMhM|aici]]. | ||
| + | - Să ne facem cont pe [[https://rezultate.eu/|rezultate.eu]] pentru a putea accesa exercițiile de laborator. | ||
| ==== ==== | ==== ==== | ||
| <note tip> | <note tip> | ||
| - | * Pentru descărcare git accesați site-ul următor: [[https://git-scm.com/downloads|Download git]] | + | * Pentru a descărca git-ul accesați site-ul următor: [[https://git-scm.com/downloads|Download Git]] |
| - | * Pentru instalare git urmăriți acest tutorial: [[https://www.youtube.com/watch?v=iYkLrXobBbA|Tutorial instalare git]] | + | * Pentru instalare git urmăriți acest tutorial: [[https://www.youtube.com/watch?v=iYkLrXobBbA|Tutorial instalare Git]] |
| * Pentru a vă crea un cont pe GitHub puteți urmări indicațiile de [[https://youtu.be/Gn3w1UvTx0A|aici]] | * Pentru a vă crea un cont pe GitHub puteți urmări indicațiile de [[https://youtu.be/Gn3w1UvTx0A|aici]] | ||
| </note> | </note> | ||
| + | |||
| ==== Concluzii ==== | ==== Concluzii ==== | ||
| - | În cadrul acestui laborator am explorat asemănările dintre **C** și **C++** și am observat că ambele limbaje folosesc **aceeași sintaxă** de bază pentru **variabile**, **funcții** și **instrucțiuni**. De asemenea, am înțeles în mare ce sunt **Git** și **GitHub** și am învățat să **inițializăm** și să **clonăm** repository-uri, să lucrăm cu **branch-uri**, să facem **commit-uri** și să folosim comenzi precum **push** sau **pull**. În esență laboratorul și-a propus trecerea lină de la **C** la **C++** cât și pregătirea mediului de lucru pe partea de **Git** și **Github**. | + | În cadrul acestui laborator am explorat asemănările dintre **C** și **C++** și am observat că ambele limbaje folosesc **aceeași sintaxă** de bază pentru **variabile**, **funcții** și **instrucțiuni**. De asemenea, am înțeles în mare ce sunt **Git** și **GitHub** și am învățat să **inițializăm** și să **clonăm** repository-uri, să lucrăm cu **branch-uri**, să facem **commit-uri** și să folosim comenzi precum **push** sau **pull**. În esență laboratorul și-a propus trecerea lină de la **C** la **C++** cât și pregătirea mediului de lucru pe partea de **Git** și **GitHub**. |