1. Introducere și motivare
Ce este un vector?
Un tablou unidimensional (vector) este o colecție de elemente de același tip, memorate unul după altul în memorie și accesate prin număr de ordine numit indice. Tot vectorul are un singur nume, iar fiecare element are propria poziție.
De ce avem nevoie de el?
Imaginează-ți un bloc cu 5 apartamente: nu îi dai fiecărui apartament un nume diferit, ci le numeri: ap. 0, ap. 1, ap. 2... Sau un rând de dulăpioare numerotate: știi exact la care să mergi.
Fără vectori, pentru 5 note ar trebui variabile separate. Pentru 100 de note, 100 de variabile ar fi imposibil de scris și de parcurs:
// Fără vectori: greoi, nu se poate parcurge cu o buclă
int a, b, c, d, e;
cin >> a >> b >> c >> d >> e;
// Cu vector: un nume, mai multe elemente, parcurgere cu for
int v[5];
for (int i = 0; i < 5; i++)
cin >> v[i];
2. Declarare și memorie
Sintaxa declarării
Forma generală este tip nume[dimensiune];, unde dimensiunea este numărul de elemente (o constantă întreagă pozitivă).
int v[5]; // 5 numere întregi
float medii[30]; // 30 de numere reale
char litere[26]; // 26 de caractere
int w[5] = {12, 7, 3, 25, 9}; // declarare cu valori inițiale
Indexare de la 0 la N-1
Într-un vector cu N elemente, indicii sunt 0, 1, ..., N-1. Primul element este v[0], iar ultimul este v[N-1]. Accesarea elementului cu indicele i se scrie v[i].
int v[5]; indicii valizi sunt 0–4. Elementul v[5] nu există: este în afara vectorului.Vectorul în memorie
Mai jos, int w[5] = {12, 7, 3, 25, 9};. Elementele sunt vecine în memorie. Un int ocupă de obicei 4 octeți, deci adresele cresc din 4 în 4 (valorile adreselor sunt doar ilustrative). Celula punctată este w[5]: nu aparține vectorului.
int w[5] = {12, 7, 3, 25, 9};
cout << w[0]; // afișează 12 (primul element)
cout << w[4]; // afișează 25 (ultimul element, N-1 = 4)
w[2] = 100; // modificăm elementul de indice 2: acum 3 devine 100
cout << w[1] + w[3]; // 7 + 25 = 32
3. Citirea elementelor unui vector
Un vector se citește element cu element. Folosim o buclă for cu indicele i de la 0 până la n-1, adică i < n.
#include <iostream>
using namespace std;
int main() {
int n, v[100]; // v poate avea cel mult 100 de elemente
cin >> n; // câte elemente citim (n <= 100)
for (int i = 0; i < n; i++) // i ia valorile 0, 1, ..., n-1
cin >> v[i]; // citim elementul de pe poziția i
return 0;
}
- Declarăm vectorul cu o dimensiune suficient de mare (aici 100) și variabila
npentru numărul real de elemente. - Citim
n. - Bucla pornește de la
i = 0și continuă cât timpi < n. - La fiecare pas,
cin >> v[i]citește o valoare și o pune pe pozițiai.
Pentru intrarea 4 urmată de 10 20 30 40, rezultă v[0]=10, v[1]=20, v[2]=30, v[3]=40. În C se scrie scanf("%d", &v[i]);.
4. Afișarea elementelor unui vector
Parcurgem la fel, cu același for, dar scriem valorile în loc să le citim. Putem separa elementele prin spațiu sau prin linie nouă.
// Afișare pe același rând, separate prin spațiu
for (int i = 0; i < n; i++)
cout << v[i] << " ";
cout << endl;
// Afișare câte un element pe linie
for (int i = 0; i < n; i++)
cout << v[i] << "\n";
10 20 30 40
Fără spațiul din " ", numerele ar apărea lipite (10203040) și nu s-ar mai distinge.
5. Algoritmi elementari de bază
În exemplele de mai jos presupunem că vectorul v cu n elemente întregi a fost deja citit.
Suma și media aritmetică
Ținem o variabilă acumulator s, pornită de la 0, la care adăugăm fiecare element. Media este suma împărțită la numărul de elemente. Pentru media cu zecimale, facem împărțirea în numere reale.
int s = 0; // acumulator: ÎNTOTDEAUNA inițializat cu 0
for (int i = 0; i < n; i++)
s = s + v[i]; // adăugăm elementul curent (sau s += v[i];)
double media = (double)s / n; // (double) evită împărțirea întreagă
cout << "Suma: " << s << "\n";
cout << "Media: " << media << "\n";
Pentru 10 20 30 40: Suma: 100 Media: 25
Numărarea elementelor cu o proprietate
Folosim un contor pornit de la 0 și îl mărim doar când elementul îndeplinește condiția. Un număr x este par dacă x % 2 == 0.
int nr = 0; // contor, pornit de la 0
for (int i = 0; i < n; i++)
if (v[i] % 2 == 0) // elementul este par?
nr++; // da: mărim contorul cu 1
cout << "Numere pare: " << nr;
Pentru 3 8 5 6 10: Numere pare: 3
Valoarea minimă și maximă
Pornim cu presupunerea că primul element este și minim, și maxim. Apoi comparăm cu restul elementelor (de la indicele 1) și actualizăm când găsim ceva mai bun.
int mini = v[0], maxi = v[0]; // pornim cu primul element
for (int i = 1; i < n; i++) { // i începe de la 1, v[0] e deja luat
if (v[i] < mini) mini = v[i]; // am găsit un element mai mic
if (v[i] > maxi) maxi = v[i]; // am găsit un element mai mare
}
cout << "Minim: " << mini << ", Maxim: " << maxi;
Pentru 7 2 9 4: Minim: 2, Maxim: 9
v[0] este mereu corectă.6. Greșeli frecvente și bune practici
Accesarea în afara limitelor (Out of Bounds)
C/C++ nu verifică automat indicii. Dacă folosești un indice invalid, programul nu se oprește mereu cu eroare: poate afișa valori ciudate sau se poate bloca, iar comportamentul este nedefinit.
int v[5] = {1, 2, 3, 4, 5};
// GREȘIT: i ajunge la 5, dar ultimul indice valid este 4
for (int i = 0; i <= 5; i++)
cout << v[i] << " ";
// CORECT
for (int i = 0; i < 5; i++)
cout << v[i] << " ";
n elemente scrie i < n, nu i <= n. Verifică și dacă n nu depășește dimensiunea declarată.Neinițializarea variabilelor de acumulare
O variabilă locală neinițializată conține o valoare aleatoare rămasă în memorie. Dacă uiți s = 0, suma pornește de la o valoare necunoscută.
int s; // GREȘIT: s are o valoare necunoscută
for (int i = 0; i < n; i++) s += v[i]; // rezultat incorect
int suma = 0; // CORECT: pornim de la 0
int nr = 0; // la fel și pentru contoare
Lista de verificare
- Indicii merg de la 0 la n-1.
- Acumulatorii și contoarele se inițializează înainte de buclă.
- Minimul și maximul pornesc de la
v[0]. - Pentru medie, convertește la
doubleînainte de împărțire.