Differences

This shows you the differences between two versions of the page.

Link to this comparison view

programare:laboratoare:lab02 [2025/10/10 12:49]
darius.neatu
programare:laboratoare:lab02 [2025/10/10 19:47] (current)
darius.neatu [PCLP Laborator02: Tipuri de date. Operatori. Instrucțiunile limbajului C]
Line 1: Line 1:
-Conținut mutat pe https://ocw.cs.pub.ro/courses/programare/laboratoare/suport-teoretic/​tipuri-de-date-si-operatori.+===== PCLP Laborator02:​ Tipuri de date. Operatori. Instrucțiunile limbajului C ===== 
 + 
 +**Responsabili:​** 
 +  * [[neatudarius@gmail.com|Darius Neațu (2019 - prezent)]] 
 +  * [[ion_dorinel.filip@cti.pub.ro|Dorinel Filip (2019 - prezent)]] 
 +  * [[teodor.matei.birleanu@gmail.com|Bîrleanu Teodor Matei (2025 - prezent)]] 
 +  * [[rares96cheseli@gmail.com|Rareș Cheșeli (2017)]] 
 +  * [[calin.cruceru@cti.pub.ro|Călin Cruceru (2015)]] 
 +  * [[emil.racec@gmail.com|Emil Racec (2014, 2012)]]  
 +  * [[bogdandrutu@gmail.com|Bogdan-Cristian Drutu (2010)]] 
 +  * [[octavian.rinciog@gmail.com|Octavian Rînciog (2010)]] 
 + 
 + 
 + 
 +==== Obiective ==== 
 + 
 +În urma parcurgerii acestui laborator studentul va fi capabil să: 
 +  * utilizeze în cadrul programelor variabile declarate cu tipurile standard (**built-in**) de date 
 +  * înțeleagă și utilizeze operatorii limbajului 
 +  * măsoare timpul de execuție al programelor scrise 
 +  * utilizeze funcțiile matematice din C 
 +  * scrie programe C utilizând structuri condiţionale si de repetiţie 
 + 
 + 
 +==== Tipuri fundamentale de date ==== 
 + 
 +Tipurile de date reprezintă tipul de informație care poate fi stocat într-o variabilă. Un tip de data definește atât gama de valori ​pe care o poate lua o variabilă de un anume tip cât și operațiile care se pot efectua asupra ei. În continuare sunt prezentate tipurile fundamentale ale limbajului C, împreună cu o scurtă descriere a acestora: 
 +  * ''​char''​ - reprezentat printr-un număr pe 8 biți (un byte). Poate fi echivalent fie cu ''​signed char'',​ fie cu ''​unsigned char''​. Vezi observația de mai jos cu privire la acest lucru. Este folosit în general pentru reprezentarea caracterelor ASCII. 
 +  * ''​int''​ - stochează numere întregi. Lungimea sa (și implicit plaja de valori) este dependentă de compilator si sistemul de operare considerat. **În general**, pe Linux, ''​int''​ se reprezintă pe 32 de biți (deci 4 bytes). În acest caz, poate memora numere din intervalul [–2.147.483.648;​ 2.147.483.647]. 
 +  * ''​float''​ - reprezintă un număr real stocat în virgulă mobilă, în gama de valori 3.4E+/-38. În **general** respectă formatul [[https://en.wikipedia.org/​wiki/​IEEE_floating_point|IEEE 754 single-precision]],​ ceea ce înseamnă că dimensiunea sa va fi 4 (octeți) și numărul va avea cel puțin 7 zecimale exacte. 
 +  * ''​double''​ - reprezinta un număr real stocat în virgulă mobilă, în gama de valori 1.7E+/-308. În **general** respectă formatul [[https://en.wikipedia.org/wiki/​IEEE_floating_point|IEEE 754 double-precision]],​ ceea ce înseamnă că dimensiunea sa va fi 8 (octeți) și numărul va avea cel puțin 15 zecimale exacte. 
 + 
 + 
 +Acestor tipuri fundamentale li se mai pot adăuga un număr de specificatori,​ după cum urmează: 
 +  * ''​short''​ - aplicabil doar pentru ''​int''​. Tipul rezultat are **cel puțin** 16 biți. 
 +  * ''​long''​ - aplicabil pentru ''​int''​ și ''​double''​. ''​long int''​ se garantează că are **cel puțin** 32 biți. Legat de ''​long double''​ se garantează doar că este mai mare sau egal ca dimensiune decât ''​double'',​ care la rândul lui este mai mare sau egal decât ''​float''​. 
 + 
 +și 
 +  * ''​signed''​ - aplicabil pentru ''​int''​ și ''​char''​. O variabilă declarată ''​int''​ este implicit ''​signed''​. Cuvântul cheie există în acest caz doar pentru cazuri în care vrem să spunem acest lucru explicit. Aplicat pe ''​char''​ (=> ''​signed char''​),​ ne garantează faptul că acea variabilă va putea avea orice valoare din intervalul [-128; 127]. 
 +  * ''​unsigned''​ - precizează faptul că valoarea variabilei este pozitivă. Aplicabil doar tipurilor întregi. 
 + 
 +Cei 4 specificatori au fost împărțiți în 2 grupuri de specificatori complementari. Asta înseamnă că expresia ''​long signed int a;''​ este corectă. La fel este și ''​unsigned short int b;''​. Definiția ''​short long int c;''​ nu este însă corectă. De asemenea, **nu** oricare specificator din prima categorie cu unul din a doua se pot combina. De exemplu, ''​long signed char d;''​ și ''​long unsigned double e;''​ nu sunt corecte. 
 + 
 +<spoiler Tipul char> 
 +**Observație!** 
 +În C există 3 "​tipuri de ''​char''":​ ''​char'',​ ''​signed char'',​ ''​unsigned char''​. Acest lucru este diferit față de ''​int'',​ spre exemplu, unde se garantează că ''​signed int''​ este **mereu** același tip ca ''​int''​. Pentru ''​char''​ acest lucru nu este adevărat: o variabilă declarată ''​char'',​ poate fi, în funcție de compilator/sistem de operare fie ''​signed char'',​ fie ''​unsigned char''​. Diferența este subtilă însă importantă atunci când vrem să scriem cod C **portabil**. Ca **best practice**, folosim: 
 +  * ''​char''​ - atunci când vrem să stocăm un caracter ASCII. 
 +  * ''​signed char''​ - atunci când vrem să stocăm un întreg din intervalul [-128; 127]. 
 +  * ''​unsigned char''​ - atunci când vrem să stocăm orice întreg din intervalul [0; 255]. 
 + 
 +**Observație!** 
 +În paragraful anterior, acolo unde s-a folosit sintagma //în general...//​ înseamnă că acel lucru nu este necesar adevărat atunci când compilăm codul cu compilatorul **X** (gcc, clang, MSVC, Intel, XL C, etc), pe sistemul de operare **Y** (Linux, Windows, SunOS, AIX, etc)  și pe arhitectura hardware **Z** (x86, ARM, PowerPC, Sparc, etc). În unele cazuri vrem să scriem cod **portabil**,​ deci nu vrem să facem prezumții cu privire la aceste lucruri. Pe parcurs o să devină clar de ce în **C** unele lucruri nu sunt exact specificate. 
 +</​spoiler>​ 
 + 
 + 
 +Uneori ne dorim să folosim ​tipuri ​a căror dimensiune este exact specificată (ca în cazul lucrului cu struct-uri, care va fi discutat într-un laborator viitor). Pentru asta, putem folosi tipurile definite în headerul ''<​stdint.h>''​.  
 + 
 +Câteva exemple sunt următoarele:​ ''​int8_t'',​ ''​int16_t'',​ ''​int64_t'',​ ''​uint32_t''​. Pentru o listă completă consultați [[http://​en.cppreference.com/​w/​c/​types/​integer|documentația]] **oficială** (online) a limbajului. 
 + 
 +<note warning>​ 
 +**Atenție!** 
 +Nu abuzați ​de aceste tipuri. Ele au fost introduse în limbaj în special pentru a permite efectuarea operațiile pe biți într-un mod **portabil**. Dacă aveți nevoie de un contor pentru o instrucțiune ''​for'',​ cel mai probabil tipul pe care îl vreți este ''​int''​. 
 +</​note>​ 
 + 
 +Determinarea corectă a tipurilor de date care vor fi folosite este esențială pentru securitatea și buna funcționare a aplicațiilor pe care le scrieți. În cazul în care valoarea conținută de o variabilă depașește limitele impuse de tipul de date folosit, se produce așa-numit-ul over-flow care poate cauza erori aparent inexplicabile. (//Ca o anecdotă, în fiecare an (până acum trei sau patru ani), Bill Gates primea de la FISC o scrisoare prin care era somat să iși platească taxele, deoarece apărea in evidențele lor ca având datorii însemnate. Asta deoarece valoarea averii lui (mult peste 4.000.000.000$) producea un overflow în softul folosit de către FISC. În final situația a fost soluționată,​ introducând un câmp special pentru el în softul folosit. (A modifica softul peste tot ar fi introdus un plus de stocare nejustificat pentru fiecare din cei aproximativ 300.000.000 de cetațeni ai SUA.)// ) 
 + 
 +==== Operatori ==== 
 + 
 +Operatorii limbajului C pot fi unari, binari sau ternari, fiecare având o precedenţă şi o asociativitate bine definite. Tabelul următor sintetizează operatorii limbajului C. Operatorii sunt prezentaţi în ordine descrescătoare a priorităţii. 
 + 
 +^  Precedenţă ​ ^  Operator ​ ^  Descriere ​ ^  Asociativitate ​ ^ 
 +|  **1**  |  **[]** ​ | Indexare |  stanga-dreapta ​ | 
 +| ::: |  **. şi %%->​%%** ​ | Selecţie membru (prin structură, respectiv pointer) |  stânga-dreapta ​ | 
 +| ::: |  **++ şi %%--%%** ​ | Postincrementare/​postdecrementare |  stânga-dreapta ​ | 
 +|  **2**  |  **!**  | Negare logică |  dreapta-stânga ​ | 
 +| ::: |  **~**  | Complement faţă de 1 pe biţi |  dreapta-stânga ​ | 
 +| ::: |  **++ şi %%--%%** ​ | Preincrementare/​predecrementare |  dreapta-stânga ​ | 
 +| ::: |  **+ şi -**  | + şi - unari |  dreapta-stânga ​ | 
 +| ::: |  *****  | Dereferenţiere |  dreapta-stânga ​ | 
 +| ::: |  **&​** ​ | Operator //adresă// |  dreapta-stânga ​ | 
 +| ::: |  **(tip)** ​ | Conversie de **tip** |  dreapta-stânga ​ | 
 +| ::: |  **sizeof()** ​ | Mărimea în octeţi |  dreapta-stânga ​ | 
 +|  **3**  |  *****  | Înmulţire |  stânga-dreapta ​ | 
 +| ::: |  **\/​** ​ | Împărţire |  stânga-dreapta ​ | 
 +| ::: |  **%**  | Restul împărţirii |  stânga-dreapta ​ | 
 +|  **4**  |  **+ şi -**  | Adunare/​scădere |  stânga-dreapta ​ | 
 +|  **5**  |  **%%<<​%% ​si %%>>​%%** ​ | Deplasare stânga/​dreapta a biţilor |  stânga-dreapta ​ | 
 +|  **6**  |  **<​** ​ | Mai mic |  stânga-dreapta ​ | 
 +| ::: |  **%%<​=%%** ​ | Mai mic sau egal |  stânga-dreapta ​ | 
 +| ::: |  **>​** ​ | Mai mare |  stânga-dreapta ​ | 
 +| ::: |  **>​=** ​ | Mai mare sau egal |  stânga-dreapta ​ | 
 +|  **7**  |  **==** ​ | Egal |  stânga-dreapta ​ | 
 +| ::: |  **!=** ​ | Diferit |  stânga-dreapta ​ | 
 +|  **8**  |  **&​** ​ | ŞI pe biţi |  stânga-dreapta ​ | 
 +|  **9**  |  **^**  | SAU-EXCLUSIV pe biţi |  stânga-dreapta ​ | 
 +|  **10** ​ |  **|**  | SAU pe biţi |  stânga-dreapta ​ | 
 +|  **11** ​ |  **&&​** ​ | ŞI logic |  stânga-dreapta ​ | 
 +|  **12** ​ |  **||** ​ | SAU logic |  stânga-dreapta ​ | 
 +|  **13** ​ |  **?:​** ​ | Operator condiţional |  dreapta-stânga ​ | 
 +|  **14** ​ |  **=**  | Atribuire |  dreapta-stânga ​ | 
 +| ::: |  **+= şi -=**  | Atribuire cu adunare/​scădere |  dreapta-stânga ​ | 
 +| ::: |  ***= şi /=**  | Atribuire cu multiplicare/​împărţire |  dreapta-stânga ​ | 
 +| ::: |  **%=** ​ | Atribuire cu modulo |  dreapta-stânga ​ | 
 +| ::: |  **&= si |=**  | Atribuire cu ŞI/SAU |  dreapta-stânga ​ | 
 +| ::: |  **^=** ​ | Atribuire cu SAU-EXCLUSIV |  dreapta-stânga ​ | 
 +| ::: |  **%%<<​= şi >>​=%%** ​ | Atribuire cu deplasare de biţi |  dreapta-stânga ​ | 
 +|  **15** ​ |  **,**  | Operator secvenţa |  stânga-dreapta ​ | 
 + 
 +Trebuie avută în vedere precedenţa operatorilor pentru obţinerea rezultatelor scontate. Dacă unele tipuri de precedenţă (cum ar fi cea a operatorilor artimetici) sunt evidente şi nu prezintă (aparent) probleme (şi datorită folosirii lor dese), altele pot duce la erori greu de găsit. De exemplu, următorul fragment de cod nu produce rezultatul dorit, deoarece: 
 + 
 +<code c> 
 +if (flags & MASK == 0) { 
 +  ... 
 +
 +</​code>​ 
 + 
 +se evaluează mai întai egalitatea care produce ca rezultat (0 pentru False, și 1 pentru True) după care se aplică Și pe biți între flags și 1. 
 + 
 +Pentru a obţine rezultatul dorit se vor folosi parantezele:​ 
 + 
 +<code c> 
 +if ((flags & MASK) == 0) { 
 +  ... 
 +
 +</​code>​ 
 + 
 +acum mai întâi se va face ȘI pe biți între flags și MASK, după care se verifică egalitatea. 
 + 
 +O expresie este o secventă de operanzi și operatori ​(validă din punct de vedere al sintaxei limbajului C) care realizează una din funcțiile: calculul unei valori, desemnarea unui obiect (variabilă) sau funcţii sau generarea unui efect lateral. 
 + 
 +O altă greşeală frecventă este utilizarea greşită a operatorilor **=** şi **==**. Primul reprezintă atribuire, al doilea comparaţie de egalitate. Apar deseori erori ca: 
 + 
 +<code c> 
 +if (a = 2) { 
 +  ... 
 +
 +</​code>​ 
 + 
 +Compilatorul consideră condiţia corectă, deoarece este o expresie validă în limbajul C care face atribuire, care se evaluează mereu la o valoare nenulă. 
 + 
 +==== Funcții matematice ==== 
 + 
 +Fișierul antet ''​math.h''​ conține un set de funcții matematice des utilizate în programe. Câteva dintre acestea sunt: 
 + 
 +^  Antet  ^  Descriere ​ ^ 
 +| //''​double asin(double arg);\\ double acos(double arg);''//​ | Calculează arcsinusul/​arccosinusul valorii **arg**; rezultatul este măsurat în radiani | 
 +| //''​double atan(double arg);\\ double atan2(double y, double x);''//​ | Calculează arctangenta valorii **arg**, respectiv a fracției y/x | 
 +| //''​double floor(double num);''//​ | Întoarce cel mai mare întreg mai mic sau egal cu **num** (partea întreagă inferioară) | 
 +| //''​double ceil(double num);''//​ | Întoarce cel mai mic întreg mai mare sau egal cu num (partea întreagă superioară) | 
 +| //''​double sin(double arg);​\\ ​ double cos(double arg);​\\ ​ double tan(double arg);''//​ | Calculează sinusul/​cosinusul/​tangenta parametrului **arg**, considerată în radiani | 
 +| //''​double sinh(double arg);\\ double cosh(double arg);\\ double tanh(double arg);''//​ |Calculează sinusul/​cosinusul/​tangenta hiperbolică a parametrului **arg** | 
 +| //''​double exp(double arg);''//​ | Întoarce valoarea ''​e''<​sup>''​arg''</​sup>​ | 
 +| //''​double pow(double base, double exp);''//​ | Întoarce valoarea ''​base''<​sup>''​exp''</​sup>​ | 
 +| //''​double log(double num);''//​ | Calculează logaritmul natural (de bază **e**) al valorii **num** | 
 +| //''​double log10(double num);''//​ | Calculează logaritmul în baza 10 al parametrului | 
 +| //''​double sqrt(double num);''//​ | Calculează radăcina pătrată a parametrului | 
 +| //''​double fmod(double x, double y);''//​ | Întoarce restul împarțirii lui **x** la **y** | 
 +| //''​double fabs(double arg);''//​ | Întoarce valoarea absolută a lui **arg** | 
 + 
 +=== Studiu de caz === 
 +<spoiler Măsurarea timpului de execuție a programelor>​ 
 + 
 +Uneori este utilă măsurarea timpului de execuție a unei anumite parți a unui program sau chiar a întregului program. În acest scop putem folosi funcția ''​clock()''​ din fișierul antet ''​time.h''​. Această funcție întoarce o aproximare a numărului de cicluri de ceas trecute de la pornirea programului. Pentru a obţine o valoare în secunde, împărțim această valoare la constanta **CLOCKS_PER_SEC**. Funcţia are antetul: 
 + 
 +<code c> 
 +clock_t clock(void);​ 
 +</​code>​ 
 + 
 +Următorul fragment este un exemplu de utilizare a acestei funcții: 
 + 
 +<code c> 
 +#include <​stdio.h>​ 
 +#include <​time.h>​ 
 +  
 +  
 +clock_t t_start, t_stop; 
 +float seconds; 
 +  
 +// Marcam momentul de inceput 
 +t_start = clock(); 
 +  
 +// Executam operatia pentru care masuram timpul de executie 
 +// [....] 
 +  
 +// Marcam momentul de sfarsit 
 +t_stop = clock(); 
 +  
 +seconds = ((float)(t_stop - t_start)) / CLOCKS_PER_SEC;​ 
 +  
 +printf("​Timp de executie: %.3f sec.\n",​ seconds); 
 +</​code>​ 
 + 
 +Următorul fragment este un exemplu de funcție care are ca scop oprirea programului pentru un anumit timp: 
 + 
 +<code c> 
 +void wait(int seconds){ 
 +  clock_t endwait; 
 +  endwait = clock () + seconds * CLOCKS_PER_SEC ; 
 +  while (clock() < endwait) {} 
 +
 +</​code>​ 
 +</​spoiler>​ 
 + 
 +<spoiler Generarea numerelor aleatoare>​ 
 + 
 +Valorile aleatoare (a căror valoare nu poate fi prezisă dinaintea rulării programului şi care diferă între 2 rulări) pot fi generate în C cu funcţia: 
 + 
 +<code c> 
 +int rand(void);​ 
 +</​code>​ 
 + 
 +care face parte din antetul ''​stdlib.h''​. Această întoarce o valoare cuprinsă între 0 și **RAND_MAX** (valoare care este dependenta de librariile folosite, dar care se garantează a fi minim 32767). 
 + 
 +Numerele generate nu sunt cu adevărat aleatoare, ci pseudo-aleatoare;​ aceste numere sunt uniform distribuite pe orice interval, dar șirul de numere aleatoare generate este dependent de prima valoare, care trebuie aleasă de utilizator sau programator. Această valoare, numită **seed**, se selectează cu funcţia: 
 + 
 +<code c> 
 +void srand(unsigned int seed); 
 +</​code>​ 
 + 
 +Cea mai întalnită utilizare a funcției de inițializare presupune setarea unui **seed** egal cu valoarea ceasului sistemului de la pornirea programului,​ prin instrucțiunea:​ 
 + 
 +<code c> 
 +srand((unsigned)time(NULL));​  
 +d = rand(); //​generează valori random. 
 +</​code>​ 
 + 
 +Funcția ''​time()''​ din fişierul antet ''​time.h''​ întoarce numărul de secunde trecute de la ora 00:00, din data de 1 ianuarie 1970. Funcția primește şi un parametru de tip pointer, care reprezintă adresa unei variabile în care se salvează valoarea returnată. Pentru laboratorul curent, parametrul va avea valoarea **NULL**. 
 + 
 +</​spoiler>​ 
 + 
 +==== Instrucţiuni ==== 
 + 
 +=== Instrucţiuni condiţionale === 
 + 
 +== If-else == 
 + 
 +''​if...else''​ este cea mai simplă instrucţiune condiţională. Poate fi folosită în mai multe forme: 
 + 
 +<code c> 
 +if (condition) { 
 +  // instructions 
 +  //... 
 +
 +</​code>​ 
 + 
 +<code c> 
 +if (condition) { 
 +  // instructions 
 +  // ... 
 +} else { 
 +  // other instructions 
 +  // ... 
 +
 +</​code>​ 
 + 
 +<code c> 
 +if (condition1) { 
 +  ... 
 +} else if (condition2) { 
 +  ... 
 +
 +  ... 
 +else if (conditionN) { 
 +  ... 
 +
 +</​code>​ 
 + 
 +Instrucţiunea evaluează expresia ''​condition''​ şi execută instrucţiunile dintre acolade doar dacă rezultatul este nenul. În varianta cu ''​else'',​ pentru rezultat nul este executat blocul de instrucţiuni aflat după ''​else''​. 
 + 
 +În al treilea caz, sunt evaluate pe rând condiţiile şi este executat blocul corespunzător primei condiţii adevărate. Un exemplu de folosire este: 
 + 
 +<code c> 
 +if (a == b) { 
 +  printf("​Numerele sunt egale"​);​ 
 +} else if (a > b) { 
 +  printf("​A este mai mare"​);​ 
 +
 +</​code>​ 
 + 
 +== Switch == 
 + 
 +''​switch''​ este o instrucţiune menită să simplifice structurile condiţionale cu mai multe condiţii. 
 + 
 +<code c> 
 +switch (expression) { 
 +  case constant1:​ 
 +    // instructions1 
 +  case constant2:​ 
 +    // instructions2 
 +  ... 
 +  default: 
 +    // instructions 
 +
 +</​code>​ 
 + 
 +Valoarea ''​expression''​ este evaluată la un tip intreg, apoi această valoare este comparată cu fiecare constantă; este rulat blocul de instrucţiuni al valorii găsite. În caz ca numărul nu este egal cu nici una dintre constante, este executat blocul aflat după ''​default''​. 
 + 
 +<note important>​ 
 +După executarea ultimei instrucţiuni dintr-un bloc ''​case'',​ execuţia nu continua după blocul ''​switch'',​ ci la inceputul următorului bloc ''​case //​constant//''​ sau ''​default''​. Pentru a ieşi din blocul ''​switch'',​ se foloseşte instrucţiunea ''​break''​. 
 +</​note>​ 
 + 
 +<code c> 
 +int main() { 
 +  char c; 
 +  printf("​Alegeţi o opţiune:​\n\t[a] afişare\n\t[s] ştergere\n\t[e] ieşire\n"​);​ 
 +  scanf("​%c",​ &c); 
 +  printf("​Aţi ales: "); 
 +  
 +  switch (c) { 
 +    case '​a':​ 
 +      printf("​afişare"​);​ 
 +      break; 
 +  
 +    case '​s':​ 
 +      printf("​ştergere"​);​ 
 +      break; 
 +  
 +    case '​e':​ 
 +      printf("​ieşire"​);​ 
 +      break; 
 +  
 +    default: 
 +      printf("​O opţiune inexistentă"​);​ 
 +      break; 
 +  } 
 +  return 0; 
 +
 +</​code>​ 
 + 
 +<code c> 
 +int main() { 
 +  int n, n2; 
 +  printf("​Introduceţi o valoare între 0 şi 5:"​);​ 
 +  scanf("​%d",​ &n); 
 +  n2 = 1; 
 +  switch (n) { 
 +    case 5: 
 +      n2 *= 2; 
 +      /* fără break, continuă la următoarea instrucţiune */ 
 +    case 4: 
 +      n2 *= 2; 
 +    case 3: 
 +      n2 *= 2; 
 +    case 2: 
 +      n2 *= 2; 
 +    case 1: 
 +      n2 *= 2; 
 +    case 0: 
 +      printf("​2 la puterea %d este %d\n", n, n2); 
 +      break; 
 +  
 +    default: 
 +      printf( "​Valoare invalidă\n"​ ); 
 +  } 
 +  return 0; 
 +
 +</​code>​ 
 + 
 +=== Instrucţiuni de repetiţie === 
 + 
 +== while == 
 + 
 +''​while''​ execută un bloc de instrucţiuni atâta timp cât o anumită condiţie este adevărată. Forma generală a unui ciclu while este: 
 + 
 +<code c> 
 +while (expression) { 
 +  // instructions 
 +
 +</​code>​ 
 + 
 +Câtă vreme ''​expression''​ are o valoare nenulă, instrucţiunile din blocul de după ''​while''​ sunt executate. Expresia este reevaluată după fiecare ciclu. Un astfel de ciclu poate să se execute o dată, de mai multe ori sau niciodată, în funcţie de valoarea la care se evaluează expresia. 
 + 
 +== do ... while == 
 + 
 +''​do ... while''​ este o instrucţiune repetitivă similara cu cea precedentă,​ singura diferenţa fiind că expresia este evaluată după executarea instrucţiunilor,​ nu înainte. Astfel, blocul va fi executat cel puţin o dată. 
 + 
 +<code c> 
 +do { 
 +  // instructions 
 +} while (expression);​ 
 +</​code>​ 
 + 
 +== for == 
 + 
 +''​for''​ reprezintă o formă mai simplă de a scrie un while însotit de o expresie iniţiala şi de o expresie de incrementare. Forma sa este: 
 + 
 +<code c> 
 +for (expression1;​ expression2;​ expression3) { 
 +  // instructions 
 +
 +</​code>​ 
 + 
 +Secvenţa de cod de mai sus este echivalentă cu: 
 + 
 +<code c> 
 +expression1 
 +while (expression2) { 
 +  // instructions 
 +  expression3 
 +
 +</​code>​ 
 + 
 +În cazul instrucţiunii ''​for'',​ oricare dintre cele 3 expresii poate lipsi. Lipsa expresiei condiţionale este echivalentă cu o buclă infinită, cum ar fi: 
 + 
 +<code c> 
 +for ( ; ; ) { 
 +  /* instrucţiunile de aici sunt intr-o buclă infinită */ 
 +
 +</​code>​ 
 + 
 +<note important>​ 
 +În acest caz, ieşirea din buclă trebuie făcută explicit, cu ajutorul instrucţiunii ''​break''​. 
 +</​note>​ 
 + 
 +Exemplul următor prezintă un ciclu cu funcţionalitate identică (tipărirea primelor 10 numere naturale), folosind cele 3 instrucţiuni repetitive:​ 
 + 
 +<code c> 
 +int main() { 
 +  short i; 
 +  printf("​Ciclu for\n"​);​ 
 +  
 +  for (i = 1; i <= 10; i++) { 
 +    printf("​i=%d\n",​ i); 
 +  } 
 +  
 +  printf("​Ciclu while\n"​);​ 
 +  i = 1; 
 +  while (i <= 10) { 
 +    printf("​i=%d\n",​ i); 
 +    i++; 
 +  } 
 +  
 +  printf("​Ciclu do while\n"​);​ 
 +  i = 0; 
 +  do { 
 +    i++; 
 +    printf("​i=%d\n",​ i); 
 +  } while(i < 10); 
 +
 +</​code>​ 
 + 
 +Pentru blocuri de o singură instrucţiune (cum este si cazul instructiunii executate de for in exemplul de mai sus) nu este nevoie sa folosim acolade. Totusi, folosirea acoladelor, chiar si in aceasta situatie, este recomandata pentru o depanare mai usoara si o lizibilitate mai buna a programelor. 
 + 
 +=== Instrucţiuni speciale === 
 + 
 +== break == 
 + 
 +''​break'',​ pe lângă utilizarea descrisă la instrucţiunea switch, poate fi folosită pentru a ieşi forţat dintr-o instrucţiune de repetiţie. Secventa următoare este echivalentă cu cele de mai sus: 
 + 
 +<code c> 
 +i = 0; 
 +for( ; ; ) { 
 +  i++; 
 +  if (i > 10) { 
 +    break; /* ieşire forţată din bucla */ 
 +  } 
 +  printf( "​i=%d\n",​ i ); 
 +
 +</​code>​ 
 + 
 +=== continue === 
 + 
 +''​continue''​ forţează terminarea iteraţiei curente a buclei si trecerea la iteraţia următoare. În cazul instrucţiunii ''​for'',​ acest lucru presupune executarea instrucţiunii de incrementare;​ apoi se evaluează condiţia de continuare a buclei. Exemplul următor demonstrează implementarea unei bucle infinite cu ajutorul instrucţiunii ''​continue'':​ 
 + 
 +<code c> 
 +for (i = 0; i < 10; ) { 
 +  if (i == 0) { 
 +    continue; 
 +  } 
 +  i++; 
 +
 +</​code>​ 
 + 
 +=== return === 
 + 
 +''​return''​ este instrucţiunea de terminare a funcţiei curente. Aceasta poate fi apelată in forma ''​return'';​ în cazul funcţiilor care returnează ''​void''​ şi în forma ''​return //​result//'';​ pentru funcţiile care întorc o valoare. 
 + 
 +=== goto === 
 + 
 +''​goto''​ este o instrucţiune de salt a execuţiei. Instrucţiunea primeşte ca parametru o etichetă; următoarea instrucţiune executată după ''​goto''​ este cea de la eticheta dată. 
 + 
 +<code c> 
 +int main() { 
 +  goto et;  
 +  printf("​Asta nu apare la executie\n"​);​ 
 +  
 +et: 
 +  printf("​Asta apare la rulare\n"​);​ 
 +  return 0; 
 +
 +</​code>​ 
 + 
 +<note important>​ 
 +În majoritatea cazurilor, utilizarea instrucţiunii ''​goto''​ nu este recomandată şi poate fi evitată folosind alte instrucţiuni de control şi funcţii. Programele care folosesc această instrucţiune pentru a sări între secvenţe îndepărtate de cod sunt dificil de depanat şi analizat. 
 +</​note>​ 
 + 
 + 
 +==== Exerciții ==== 
 +Exercițiile pentru laborator se găsesc pe [[https://​acs-pclp.github.io/​laboratoare/​02 | PCLP Laborator02 - Tipuri de date. Operatori. Instrucțiunile limbajului C]]. 
 + 
 +==== Referinţe ==== 
 + 
 +  * [[https://​en.wikipedia.org/​wiki/​C_data_types|Wikipedia - C data types]] 
 +  * [[http://​en.wikipedia.org/​wiki/​Operators_in_C_and_C%2B%2B|Wikipedia - Operators in C and C++]] 
 +  * [[http://​en.wikipedia.org/​wiki/​C_mathematical_functions|Wikipedia - C mathematical functions]] 
 +  * [[http://​www.tutorialspoint.com/​ansi_c/​c_control_statements.htm|C - Control Statements]] 
 + 
 + 
programare/laboratoare/lab02.1760089743.txt.gz · Last modified: 2025/10/10 12:49 by darius.neatu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0