Differences

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

Link to this comparison view

programare:laboratoare:suport_teoretic:tipuri-de-date-si-operatori [2025/10/10 14:35]
darius.neatu
programare:laboratoare:suport_teoretic:tipuri-de-date-si-operatori [2025/10/10 16:42] (current)
darius.neatu
Line 1: Line 1:
-===== TablouriParticularizare - vectori. Aplicaţii ​=====+===== PCLP Suport Teoretic pentru Laborator: Tipuri de dateOperatori ​=====
  
-==== Obiective ==== 
  
-În urma parcurgerii acestui laborator, studentul va fi capabil: 
  
-  * să declare şi să iniţializeze vectori (din declaraţie şi prin structuri iterative) +==== Tipuri fundamentale ​de date ====
-  * să implementeze algoritmi simpli ​de sortare şi căutare pe vectori +
-  * să folosească practici recunoscute şi recomandate pentru scrierea de cod sursă care implică lucrul cu vectori +
-  * să recunoască şi să evite erorile comune de programare legate de aceste structuri +
-  * să aplice lucrul cu vectori pentru rezolvarea unor probleme cu dificultate medie+
  
-==== Noţiuni teoretice ====+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.
  
-=== Vectori === 
  
-Printr-un vector ​se înţelege ''​o colecţie liniară şi omogenă'' ​de date. Un vector este liniar pentru că datele(elementele) pot fi accesate în mod unic printr-un ''​index''​. ​Un vector este, de asemenea, omogen, ​pentru ​că toate elementele sunt de acelaşi ''​tip''​. ​În limbajul C, indexul este un număr întreg pozitiv şindexarea ​se face începând cu 0+Acestor tipuri fundamentale li se mai pot adăuga un numă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''​.
  
-Declaraţia unei variabile de tip vector se face în felul următor:+ș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.
  
-<code bash> +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.
-<​tip_elemente>​ <​nume_vector>​[<​dimensiune>​]; +
-</​code>​+
  
-De exemplu, ​avem următoarele declaraţii ​de vectori:+<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].
  
-<code c> +**Observație!** 
-int a[100]; +În paragraful anterior, acolo unde s-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. 
-float vect[50];+</​spoiler>​
  
-#define MAX 100 
-... 
-unsigned long numbers[MAX];​ 
-</​code>​ 
  
-Este de remarcat că vectorul este o ''​structură statică'':​ dimensiunea acestuia trebuie ​să fie o constantă la compilare şi nu poate fi modificată în cursul execuţiei programului. Astfel, programatorul trebuie să estimeze o dimensiune ​maximă pentru vector, şi aceasta va fi o limitare a programului. De obicei, se folosesc constante simbolice ​(ca în ultimul exemplu) pentru aceste dimensiuni maximepentru ca ele să poată ​fi ajustate uşor la nevoie +Uneori ne dorim să folosim tipuri a căror dimensiune ​este exact specificată (ca în cazul lucrului cu struct-uricare va fi discutat într-un laborator viitor)Pentru astaputem folosi tipurile definite ​în headerul ''<​stdint.h>''​
-De asemenea, în cadrul unei declaraţii,​ se pot iniţializa cu valori constante componente ale vectorului, iar în acest caz, dimensiunea vectorului poate rămâne neprecizată (compilatorul o va determina din numărul elementelor din listă)De exemplu:+
  
-<code c> +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.
-int a[3] = {156};                     // Toate cele 3 elemente sunt initializate  +
-float num[] = {1.5, 2.3, 0.2, -1.3};      ​// Compilatorul determina dimensiunea - 4 - a vectorului +
-unsigned short vect[1000] = {0, 2, 4, 6}; // Sunt initializate doar primele 4 elemente, iar toate celelalte sunt initializate cu valoarea 0 +
-</​code>​+
  
-În cazul special ​în care specificăm dimensiunea şdoar un singur element la initializareprimul element va fi cel specificat, iar toate celelalte elemente ale vectorului vor fi iniţializate la ''​0''​:+<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țnevoie de un contor pentru o instrucțiune ''​for''​, cel mai probabil tipul pe care îl vreți este ''​int''​
 +</​note>​
  
-<code c> +Determinarea corectă a tipurilor de date care vor fi folosite este esențială pentru securitatea și buna funcționare ​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.)// )
-char string[100] = {97}; // Sirul va fi initializat cu: 97 (caracterul 'a'​) ​pe prima poziţie ş99 de +
-int v[100] = {0};        ​// Vectorul va fi umplut cu 0. +
-</code>+
  
-Este important de remarcat faptul că elementele **neiniţializate** pot avea valori **oarecare**. La alocarea unui vector, compilatorul nu efectuează nici un fel de iniţializare şi nu furnizează nici un mesaj de eroare dacă un element este folosit înainte de a fi iniţializat. **Un program corect va iniţializa**,​ în orice caz, fiecare element înainte de a-l folosi. +==== Operatori ====
-Elementele se accesează prin expresii de forma ''<​nume_vector>​[<​indice>​]''​. De exemplu, putem avea:+
  
-<code c> +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.
-char vect[100];​ +
-vect[0] = 1; +
-vect[5] = 10;+
  
-int i = 90; +^  Precedenţă ​ ^  Operator ​ ^  Descriere ​ ^  Asociativitate ​ ^ 
-vect[i= 15; +|  **1**  |  **[]**  | Indexare |  stanga-dreapta ​ | 
-vect[i + 1] = 20; +| ::: |  **. ş%%->​%%** ​ | Selecţie membru (prin structură, respectiv pointer) |  stânga-dreapta ​ | 
-</code>+| ::: |  **++ şi %%--%%** ​ | Postincrementare/​postdecrementare |  stânga-dreapta ​ | 
 +|  **2**  |  **!**  | Negare logică |  dreapta-stânga ​ | 
 +| ::: |  **~**  | Complement faţă de 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 ​ |
  
-==== Stil de programare ==== +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:
- +
-=== Exemple ​de programe === +
- +
-Citirea unui vector ​de intregi de la tastatura:+
  
 <code c> <code c>
-int main()  +if (flags MASK == 0) { 
-+  ​...
-  int a[100], n, i; /* vectorul a are maxim 100 de intregi */ +
- +
-  scanf("​%d", ​&n); /* citeste nr de elemente vector */ +
- +
-  for (i 0; i < n; i++) { +
-    scanf("​%d",​ &a[i]); /* citire elemente vector */ +
-  } +
- +
-  for (i = 0; i < n; i++) { +
-    printf("​%d ", a[i]); /* scrie elemente vector */ +
-  ​+
-   +
-  return 0;+
 } }
 </​code>​ </​code>​
  
-Generarea unui vector cu primele n numere Fibonacci:+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> <code c>
-#include <​stdio.h>​ +if ((flags MASK) == 0) { 
-int main()  +  ​...
-+
-  long fib[100] = {1, 1}; +
-  int n, i; +
- +
-  printf("n = ");  +
-  scanf("​%d", ​&n)+
-   +
-  for (i 2; i < n; i++) { +
-    fib[i] = fib[i - 1] + fib[i - 2]; +
-  } +
-  for (i = 0; i < n; i++) { +
-    printf("​%ld ", fib[i]); +
-  ​+
- +
-  return 0;+
 } }
 </​code>​ </​code>​
  
-<note warning>​ +acum mai întâi se va face ȘI pe bițîntre flags și MASK, după care se verifică egalitatea.
-Deşmodul în care se manifestă erorile din program poate fi surprinzător şi imprevizibil,​ cauzele care produc aceste erori sunt destul de comune şi pot fi grupate în mai multe categoriiCâteva dintre acestea sunt prezentate mai jos +
-</​note>​+
  
-  * Depăşirea limitelor indicilor (index out of bounds) ​este o eroare frecventă, ce poate duce la blocarea programului sau a sistemului şpoate fi evitată prin verificarea încadrării în intervalul valid.  +O expresie ​este o secventă de operanzi ș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.
-  * Indici folosiţi greşit în bucle imbricate ​(index cross-talk). Sunt multe cazuri în care pe un nivel al buclei se foloseşte, de exemplu vect[i], şi pe nivelul imbricat vect[j], când de fapt se dorea folosirea lui i. Mare atenţie şi în astfel de cazuri!+
  
-<note tip> +O altă greşeală frecventă este utilizarea greşită a operatorilor **=** şi **==**. Primul reprezintă atribuire, al doilea comparaţie de egalitateApar deseori erori ca:
-Definiţi dimensiunile prin constante ​şi folosiţi-le pe acestea în locul tastării explicite a valorilor în codul sursă. Astfel veţi evita neconcordanţe în cod dacă doriţi ulterior să modificaţi dimensiunile ​şi uitaţi să modificaţi peste tot prin cod. +
-</​note>​+
  
 <code c> <code c>
-#define MAX   100 +if (a = 2) { 
- +  ... 
-int vect[MAX];​ +}
-</​code>​ +
-va fi de preferat în locul lui +
-<code c> +
-int vect[100];+
 </​code>​ </​code>​
  
-<note tip> +Compilatorul consideră condiţia corectă, deoarece este o expresie validă în limbajul C care face atribuire, care se evaluează mereu la o valoare nenulă.
-Verificaţi că indicii se încadrează între marginile superioară şi inferioară a intervalului de valori valide. Acest lucru trebuie în general făcut în cazul în care datele provin dintr-o sursă externă: citite de la tastatură sau pasate ca parametri efectivi unei funcţii, de exemplu. +
-</​note>​+
  
-Exemplu:+==== Funcții matematice ====
  
-<code c> +Fișierul antet ''​math.h''​ conține un set de funcții matematice des utilizate în programe. Câteva dintre acestea sunt:
-// program care citeşte un index şi o valoare, şi atribuie valoarea elementului din vector care se găseşte la poziţia respectivă +
-#include <stdio.h+
-#define N 10+
  
-int main()  +^  Antet  ^  Descriere ​ ^ 
-{ +| //''​double asin(double arg);\\ double acos(double arg);''//​ | Calculează arcsinusul/​arccosinusul valorii **arg**; rezultatul este măsurat în radiani | 
-  ​int ival+| //''​double atan(double arg);\\ double atan2(double y, double x);''//​ | Calculează arctangenta valorii **arg**, respectiv a fracției y/x | 
-  int v[N];+| //''​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** |
  
-  scanf("​%d%d",​ &i, &val);+=== Studiu de caz === 
 +<spoiler Măsurarea timpului de execuție a programelor>​
  
-  /* !!! Verific daca indexul ​este valid */ +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:
-  if (i >= 0 && i < N+
-   v[i] = val; +
-  } else { +
-    printf("​Introduceti un index >= 0 si < %d\n"N); +
-  }+
  
-  return 0; +<code c> 
-}+clock_t clock(void);​
 </​code>​ </​code>​
  
-<note tip> +Următorul fragment este un exemplu ​de utilizare a acestei funcții:
-Folosiţi comentarii pentru a explica ce reprezintă diverse variabile. Acest lucru vă va ajuta atât pe voi să nu încurcaţi indici, ​de exemplu, cât şi pe ceilalţi care folosesc sau extind codul vostru. +
-</​note>​ +
- +
-Exemplu:+
  
 <code c> <code c>
 #include <​stdio.h>​ #include <​stdio.h>​
-#define N 100+#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>​
  
-int main()  +Următorul fragment este un exemplu de funcție care are ca scop oprirea programului ​pentru ​un anumit timp:
-+
-  int v[N]; +
-  int i, j; /* indecsii elementelor ce vor fi interschimbate */ +
-  int aux;  /* variabila ajutatoare ​pentru ​interschimbare */+
  
-  /*... initializari */ +<code c> 
-   +void wait(int seconds){ 
-  ​/* Interschimb */ +  ​clock_t endwait
-  aux = v[i]+  ​endwait ​clock () + seconds * CLOCKS_PER_SEC ​
-  ​v[i] v[j]+  ​while (clock() < endwait) {}
-  ​v[j] = aux; +
- +
-  return 0;+
 } }
 </​code>​ </​code>​
 +</​spoiler>​
  
-==== Aplicaţii cu vectori ====+<spoiler Generarea numerelor aleatoare>​
  
-=== Căutări ===+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:
  
-== Căutare secvenţială ==+<code c> 
 +int rand(void);​ 
 +</​code>​
  
-Când avem de a face cu un vector nesortat (şi nu numai în acest caz), cea mai simplă abordare pentru a găsi o valoareeste căutarea secvenţială. Cu alte cuvinte, se compară, la rând, fiecare valoare din vector cu valoarea căutată. Dacă valoarea ​fost găsită, căutarea se poate opri (nu mai are sens să parcugem vectorul până la capăt, dacă nu se cere acest lucru explicit). +care face parte din antetul ''​stdlib.h''​. Această întoarce ​o valoare ​cuprinsă între 0 și **RAND_MAX** (valoare care este dependenta de librariile folositedar care se garantează a fi minim 32767).
  
-''​Exemplu''​:+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> <code c>
- +void srand(unsigned ​int seed);
-#define MAX 100 +
- +
-... +
- +
-int v[MAX], x, i; +
- +
-/* initializari */ +
-... +
- +
-int found = 0; +
-for (i = 0; i < MAX; i++) { +
-  if (x == v[i]) { +
-    found = 1; +
-    break; +
-  } +
-+
- +
-if (found) { +
-   ​printf("​Valoarea %d a fost gasita in vector\n",​ x); +
-} else {  +
-   ​printf("​Valoarea %d nu a fost gasita in vector\n",​ x); +
-+
-...+
 </​code>​ </​code>​
  
-== Căutare binară iterativă == +Cea mai întalnită utilizare a funcției ​de inițializare presupune setarea unui **seed** egal cu valoarea ​ceasului sistemului ​de la pornirea programuluiprin instrucțiunea:
- +
-Dacă vectorul pe care se face căutarea este sortat, algoritmul mai eficient ​de folosit în acest caz este căutarea binară. Presupunem că vectorul este sortat crescător (pentru vectori sortaţi descrescător,​ raţionamentul este similar). +
- +
-Valoarea căutată, ''​x'',​ se compară ​cu valoarea ​cu indexul N/2 din vector, unde N este numărul ​de elemente. Dacă ''​x''​ este mai mic decât valoarea din vector, se caută în prima jumătate a vectorului, iar dacă este mai mare, în cea de-a doua jumătate. Căutarea în una dintre cele două jumătăţi se face după acelaşi algoritm.  +
- +
-Conceptual, căutarea binară este un algoritm recursiv, dar poate fi implementat ​la fel de bine într-un mod iterativfolosind indecşii corespunzători bucăţii din vector în care se face căutarea. Aceşti indecşi se modifică pe parcursul algoritmului,​ într-o buclă, în funcţie de comparaţiile făcute. Evoluţia algoritmului este ilustrată în imaginea de mai jos.  +
- +
-Pseudocodul pentru căutarea binară:+
  
 <code c> <code c>
-// cauta elementul x in vectorul sortat v, intre pozitiile 0 si n-1  si returneaza pozitia gasita sau -1 +srand((unsigned)time(NULL));  
-int binary_search(int n, int v[NMAX], int x) { +rand(); //generează valori random.
-  int low = 0, high = n - 1; +
- +
-  while (low <= high+
-    // De ce preferăm această formă față de (low + high/ 2 ? +
-    int middle = low + (high - low/ 2+
- +
-    if (v[middle] ​== x) { +
-      // Am gasit elementul, returnam pozitia sa +
-      return middle; +
-    } +
- +
-    if (v[middle] < x+
-      // Elementul cautat este mai mare decat cel curent, ne mutam in jumatatea +
-      // cu elemente mai mari +
-      low = middle + 1; +
-    } else { +
-      ​// Elementul cautat este mai mic decat cel curent, ne mutam in jumatatea +
-      // cu elemente mai mici +
-      high = middle - 1; +
-    } +
-  } +
- +
-  // Elementul nu a fost gasit +
-  return -1; +
-}+
 </​code>​ </​code>​
  
-<note tip> +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 1970Funcția primește ​şi un parametru ​de tip pointer, care reprezintă adresa unei variabile ​în care se salvează valoarea returnată. Pentru laboratorul curentparametrul va avea valoarea **NULL**.
-Preferăm calcularea mijlocului intervalului [low, high] folosind formula ​''​x = low + (high - low/ 2'' ​deoarece formula perfect analogă ​''​x = (low + high) / 2'' ​poate da overflow pentru valori mari ale low si high. De altfel, acest bug a existat în biblioteca Java timp de de ani. Puteți citi mai mult despre asta în [[http://​googleresearch.blogspot.ro/​2006/​06/​extra-extra-read-all-about-it-nearly.html | acest articol]]. +
-</​note>​ +
- +
-=== Sortări === +
- +
-== Bubble Sort == +
- +
-Metoda bulelor este cea mai simplă modalitate ​de sortare a unui vector, dar şi cea mai ineficientăEa funcţionează pe principiul parcurgerii vectorului ​şi comparării elementului curent cu elementul următor. Dacă cele două nu respectă ordinea, sunt interschimbate. Această parcurgere este repetată ​de suficiente ori până când nu mai există nici o interschimbare în vector.  +
- +
-== Sortarea prin selecţie == +
- +
-Sortarea prin selecţie oferă unele îmbunătăţiri în ceea ce priveşte complexitateaînsă este departe de a fi considerat un algoritm eficient. Presupunând că se doreşte sortarea crescătoare a vectorului, se caută minimul din vector, şi se interschimbă cu primul element - cel cu indexul 0. Apoi se reia acelaşi procedeu pentru restul vectorului. Motivul pentru ​care algoritmul de sortare prin selecţie este mai eficient este acela că vectorul ​în care se caută minimul devine din ce în ce mai mic, şi, evident, căutarea se face mai repede la fiecare pas. +
- +
-Studiul unor algoritmi mai avansaţi de sortareprecum şi studiul complexităţii lor nu constituie obiectul acestui laborator. Acestea se vor relua mai detaliat în cadrul altor cursuri (AA/PA)+
  
 +</​spoiler>​
  
-===== Referinţe ====+==== Referinţe ====
-  * [[https://​github.com/​cs-pub-ro/​ComputerProgramming/​blob/​master/​Laboratories/​Lab5/​Lab5.pdf| Cheatsheet vectori]] +
-  * [[http://​en.wikipedia.org/​wiki/​Binary_search | Wikipedia - Căutare binară]] +
-  * [[http://​en.wikipedia.org/​wiki/​Sorting_algorithm |Wikipedia - Algoritmi de sortare]]+
  
 +  * [[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]]
  
programare/laboratoare/suport_teoretic/tipuri-de-date-si-operatori.1760096159.txt.gz · Last modified: 2025/10/10 14:35 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