Ce vei învăța astăzi?
După această lecție, vei înțelege conceptul de vector și vei putea declara, citi și afișa vectori în C++.
Ce este un vector?
Definiție: Un vector (array) este o colecție ordonată de elemente de același tip, stocate în memorie una lângă alta.
Exemplu: Dacă avem 5 note de elev, le putem stoca într-un vector note[5].
Dimensiunea vectorului
Indici de la 0 la 4
Declarare în C++
Analogii pentru a înțelege vectorii:
Raft de cărți
Fiecare cărțuță este numerotată (0, 1, 2...). Poți lua cartea de pe poziția 3 fără să te uiți la celelalte.
Cutii poștale
Fiecare cutie are un număr. Poți pune sau lua scrisori doar din cutia cu numărul pe care îl știi.
Listă de cumpărături
Produsele sunt în ordine pe listă. Poți să te uiți la al treilea produs fără să parcurgi primele două.
Hotel cu camere
Camerele sunt numerotate (101, 102...). Poți merge direct la camera 105 fără să verifici camerele anterioare.
Declararea vectorilor în C++
Regula de aur: Indicele primului element este întotdeauna 0, nu 1! Ultimul element are indicele dimensiune-1.
Exemplu: Note elev
int note[5]; // 5 note pentru un elev note[0] = 9; // Prima notă note[1] = 8; // A doua notă note[2] = 10; // A treia notă note[3] = 7; // A patra notă note[4] = 9; // A cincea notă
Exemplu: Temperaturi
float temp[7]; // Temperaturi pentru 7 zile temp[0] = 22.5; // Luni temp[1] = 23.1; // Marți temp[2] = 21.8; // Miercuri // ... până la temp[6] - Duminică
Important: Initializarea directă se face doar la declarare. Dacă vrei să schimbi valorile mai târziu, trebuie să atribui fiecare element individual.
int numere[5] = {10, 20, 30, 40, 50};
| Situație | Declarare corectă | Declarare greșită | Explicație |
|---|---|---|---|
| 5 numere întregi | int v[5]; |
int v[5.5]; |
Dimensiunea trebuie să fie număr întreg |
| Initializare directă | int v[] = {1,2,3}; |
int v[3]; v = {1,2,3}; |
Initializarea doar la declarare |
| Vector cu 0 | int v[10] = {0}; |
int v[10] = 0; |
Folosește acolade pentru initializare |
| Dimensiune variabilă | const int n=5; int v[n]; |
int n=5; int v[n]; |
Dimensiunea trebuie constantă |
Sfaturi practice pentru începători:
- Folosește constante pentru dimensiuni:
const int MAX = 100; - Verifică întotdeauna că indicele este între 0 și dimensiune-1
- Nume descriptive pentru vectori:
note,temperaturi,numeElevi - Testează cu dimensiuni mici înainte să treci la dimensiuni mari
Modelul standard de parcurgere
Când ai un vector și vrei să lucrezi cu toate elementele lui, folosești aproape mereu aceeași idee: o buclă care pornește de la 0 și se oprește la n-1.
Asta înseamnă: primul element este v[0], iar ultimul este v[n-1].
for (int i = 0; i < n; i++) {
// aici lucrezi cu v[i]
}
Regula de aur: dacă ai dubii, scrie întâi bucla corectă. Apoi completezi ce trebuie în interior.
| Ce vreau să fac | Ce scriu în interiorul buclei |
|---|---|
| Afișez elementele | cout << v[i] << " "; |
| Le citesc | cin >> v[i]; |
| Le dublez | v[i] = v[i] * 2; |
| Număr câte sunt pare | if (v[i] % 2 == 0) cnt++; |
Ce înseamnă n și cum aleg dimensiunea
În probleme, n este de obicei câte valori citim.
În C++ putem lucra în două moduri:
fie folosim un tablou cu o dimensiune maximă, fie folosim un vector cu dimensiune exactă.
De ce putem scrie int v[MAX]; înainte de cin >> n;?
Pentru că MAX este o limită maximă (un „raft” cu multe locuri).
Chiar dacă tu ai raft de 1000 locuri, nu înseamnă că îl umpli pe tot.
câte locuri are raftul (capacitatea)
câte locuri folosim azi (câte valori citim)
valoarea de pe locul i (doar pentru i=0..n-1)
Regula practică: după ce ai citit n, lucrezi doar cu
v[0], v[1], ..., v[n-1]. Restul locurilor există, dar nu te interesează.
Exemplu complet (clasic): „MAX + n”
| Ce înseamnă | În program |
|---|---|
| Stabilesc capacitatea maximă | const int MAX = 1000; |
| Declar „raftul” | int v[MAX]; |
| Citesc câte valori am în problemă | cin >> n; |
| Folosesc doar primele n locuri | for(i=0;i<n;i++) cin>>v[i]; |
#include <iostream>
using namespace std;
int main() {
const int MAX = 1000;
int v[MAX];
int n;
cin >> n;
if (n > MAX) {
cout << "n prea mare (max " << MAX << ")\n";
return 0;
}
for (int i = 0; i < n; i++) cin >> v[i];
// aici lucrezi doar cu v[0..n-1]
for (int i = 0; i < n; i++) cout << v[i] << " ";
return 0;
}
Ideea-cheie: vectorul are MAX locuri, dar noi folosim doar n. Asta e tot.
A doua metodă: „vector care crește” (push_back)
Uneori vrei să construiești vectorul pas cu pas. Atunci folosești std::vector
și adaugi elemente cu push_back.
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> v; // începe gol
v.reserve(n); // (opțional) rezerv loc pentru n elemente
for (int i = 0; i < n; i++) {
int x;
cin >> x;
v.push_back(x);
}
for (int i = 0; i < (int)v.size(); i++) {
cout << v[i] << " ";
}
return 0;
}
| Metodă | Când o folosesc | Ce trebuie să știu |
|---|---|---|
int v[MAX]; |
Probleme clasice, rapid și simplu | n ≤ MAX, lucrezi cu v[0..n-1] |
vector<int> v(n); |
Ai n din start și vrei dimensiune exactă | Vectorul are deja n elemente: v[0..n-1] |
vector<int> v; push_back |
Construiești treptat | Dimensiunea e v.size() |
Diferența de reținut:
vector<int> v(n) creează n locuri,
iar vector<int> v; începe gol și îl umpli cu push_back.
const int MAX = 1000; int v[MAX]; int n; cin >> n; // n trebuie să fie ≤ MAX
#include <vector> int n; cin >> n; vector<int> v(n);
În modulul acesta puteți lucra fără probleme cu varianta clasică (MAX).
Varianta modernă e un bonus util și o vom folosi din ce în ce mai des.
DE CE începem de la 0?
Regula fundamentală a indexării
În C++ (și majoritatea limbajelor de programare), vectorii încep de la indicele 0.
Parter = etaj 0
Etaj 1 = de fapt etajul 2 din viața reală
La lift apăsăm "0" pentru parter, nu "1"!
Deci: indice = distanța de la începutul vectorului
Vector cu 5 elemente - cum funcționează indexarea:
Cel mai frecvent bug la începători: Accesarea elementului v[5] într-un vector de 5 elemente. Corect este v[0] până la v[4]!
Exercițiu de completare - Declarare vector:
Completează codul C++ pentru declararea și utilizarea unui vector:
Bancă de cuvinte:
Test de înțelegere: Care este valoarea corectă?
Test rapid - indexarea vectorilor:
Avem declararea: int v[5] = {10, 20, 30, 40, 50};
Vectorul în memorie:
Care este valoarea lui v[3]?
Care este indicele ultimului element?
Sfaturi practice pentru lucrul cu vectori
const int MAX = 100; int v[MAX]; - este mai ușor de modificat și mai sigur.
Accesarea v[5] într-un vector de 5 elemente (v[0]...v[4]) dă eroare!
for (int i = 0; i < n; i++) este modelul standard pentru parcurgere.
noteElevi este mai bun decât v sau arr.
Greșeli frecvente și corectarea lor
| Greșit | De ce? | Corect |
|---|---|---|
for (int i = 1; i <= n; i++) |
Indexarea începe de la 0 | for (int i = 0; i < n; i++) |
v[n] |
Ultimul element este la n-1 |
v[n-1] |
int v[n]; |
n nu e constant la compilare |
const int MAX = 1000; int v[MAX]; |
Dacă îți iese „un element în plus” sau „lipsește primul element”, verifică imediat limita buclei:
i < n, nu i <= n.
Capcane comune și soluții pentru vectori
Greșeli frecvente la lucrul cu vectori:
Soluție: Întotdeauna începe de la 0 și folosește i < dimensiune.
În C++ standard, dimensiunea unui vector trebuie să fie constantă la compilare.
Nu poți folosi acolade pentru a atribui valori unui vector după declarare.
Best Practices pentru vectori:
const int N = 100;
for (int i = 0; i < n; i++)
noteElevi nu v
Încălzire (2 minute)
Test rapid - declarații vectori: Care sunt corecte și care sunt greșite?
int vector[5];→ verificăfloat temp[];→ verificăchar litere[10] = {'a', 'b', 'c'};→ verifică
Hint: vectorul trebuie să aibă dimensiune specificată (cu excepția cazului când este inițializat).
Fără să scrii program complet, răspunde:
- Dacă
n = 7, care este indicele ultimului element? - Ce afișează:
cout << v[0];? - Ce indice are al treilea element (ca poziție) din vector?
Scopul este să nu mai existe confuzie între „al treilea element” și „indice 3”.
PbInfo #158 - Citire și afișare vector
Enunț:
Cerință: Se citește un număr n și apoi n numere naturale. Să se afișeze elementele vectorului în ordinea citirii.
Date de intrare:
Programul citește de la tastatură numărul n, apoi n numere naturale.
Date de ieșire:
Programul va afișa pe ecran cele n numere, separate prin spații.
Exemplu:
Intrare:
5 10 20 30 40 50
Ieșire:
10 20 30 40 50
Explicație: Vectorul este afișat exact în ordinea citirii
Cum gândim soluția:
- Citim numărul n (dimensiunea vectorului)
- Declarăm un vector cu dimensiunea n (sau cu dimensiune maximă)
- Citim cele n elemente într-o buclă for:
for (int i = 0; i < n; i++)cin >> v[i];
- Afișăm elementele în aceeași ordine:
for (int i = 0; i < n; i++)cout << v[i] << " ";
Execuție pentru n=3 cu valori 7, 8, 9:
Ce trebuie să verifici mereu?
- Dimensiunea vectorului să fie suficient de mare
- Indicele să înceapă de la 0 și să se termine la n-1
- Să nu uiți să afișezi spații între elemente
- Să nu afișezi spațiu după ultimul element (dar PbInfo e tolerant)
Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
// Declarăm vectorul cu dimensiune maximă 1000
// (sau cu dimensiunea exactă n dacă folosim alocare dinamică mai târziu)
const int MAX = 1000;
int v[MAX];
// Citim cele n elemente
for (int i = 0; i < n; i++) {
cin >> v[i];
}
// Afișăm elementele în ordinea citirii
for (int i = 0; i < n; i++) {
cout << v[i] << " ";
}
return 0;
}
Varianta cu dimensiune exactă (BONUS - std::vector):
#include <iostream>
#include <vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> v(n); // dimensiune exactă
for (int i = 0; i < n; i++) {
cin >> v[i];
}
for (int i = 0; i < n; i++) {
cout << v[i] << " ";
}
return 0;
}
Ce învățăm din această problemă:
- Citirea unui vector: folosind o buclă for de la 0 la n-1
- Afișarea unui vector: aceeași structură ca la citire
- Indexarea corectă: începând de la 0, până la n-1
- Dimensiune vector: folosirea constantei MAX pentru siguranță
- Spații la afișare: separator între elemente
PbInfo #159 - Afișare inversă a unui vector
Problemă care afișează elementele vectorului în ordine inversă
Enunț:
Cerință: Se citește un număr n și apoi n numere naturale. Să se afișeze elementele vectorului în ordine inversă față de ordinea citirii.
Date de intrare:
Programul citește de la tastatură numărul n, apoi n numere naturale.
Date de ieșire:
Programul va afișa pe ecran cele n numere în ordine inversă, separate prin spații.
Exemplu:
Intrare:
5 10 20 30 40 50
Ieșire:
50 40 30 20 10
Explicație: Elementele sunt afișate de la ultimul la primul
Cum gândim soluția:
- Citim n și cele n elemente (ca la problema anterioară)
- Pentru afișare inversă, parcurgem vectorul de la sfârșit la început:
- Primul element afișat: v[n-1] (ultimul)
- Ultimul element afișat: v[0] (primul)
- Bucla:
for (int i = n-1; i >= 0; i--)
- Atenție la condiția din buclă:
i >= 0(nui > 0)
Cum funcționează pentru n=3 cu valori 7, 8, 9:
De ce i >= 0 și nu i > 0?
Pentru că vrem să afișăm și primul element (v[0]). Dacă am folosi i > 0, bucla s-ar opri la i=1 și nu am afișa v[0].
Formula cheie pentru parcurgere inversă: for (int i = n-1; i >= 0; i--)
Scrie soluția în C++:
Soluție corectă:
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
const int MAX = 1000;
int v[MAX];
// Citire elemente
for (int i = 0; i < n; i++) {
cin >> v[i];
}
// Afișare inversă
for (int i = n - 1; i >= 0; i--) {
cout << v[i] << " ";
}
return 0;
}
Varianta cu verificare dimensiune:
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
// Verificăm ca n să fie pozitiv și mai mic decât dimensiunea maximă
if (n <= 0) {
cout << "n trebuie sa fie pozitiv!";
return 0;
}
const int MAX = 1000;
if (n > MAX) {
cout << "n este prea mare!";
return 0;
}
int v[MAX];
for (int i = 0; i < n; i++) {
cin >> v[i];
}
for (int i = n - 1; i >= 0; i--) {
cout << v[i] << " ";
}
return 0;
}
Ce învățăm din această problemă:
- Parcurgere inversă: de la n-1 la 0 cu decrementare (i--)
- Condiția corectă:
i >= 0pentru a include primul element - Primul și ultimul element:
- Primul: v[0] (index minim)
- Ultimul: v[n-1] (index maxim)
- Verificare date de intrare: bună practică pentru programe robuste
- Parcurgeri diferite: crescătoare vs descrescătoare
Exercițiul Practic: Primii pași cu vectori
Sarcini de lucru
Completează următoarele sarcini pentru a-ți consolida cunoștințele despre vectori
Sarcina 1: Analiză și corectare cod
Analizează următorul cod și găsește greșelile:
#include <iostream>
using namespace std;
int main() {
int n = 5;
int vector[5];
// Citire
for (int i = 1; i <= n; i++) {
cin >> vector[i];
}
// Afișare
for (int i = 0; i <= n; i++) {
cout << vector[i];
}
return 0;
}
Soluție pentru Sarcina 1:
Greșeli identificate și corecții:
- 1. Indexare greșită la citire:
for (int i = 1; i <= n; i++)este greșit.
Corect:for (int i = 0; i < n; i++) - 2. Accesare element inexistent la citire:
Când
i = 5, se încearcă accesareavector[5], dar vectorul are doar elementele 0-4. - 3. Indexare greșită la afișare:
for (int i = 0; i <= n; i++)este greșit (merge până la 5).
Corect:for (int i = 0; i < n; i++) - 4. Lipsă spații la afișare:
cout << vector[i];va afișa numerele lipite.
Corect:cout << vector[i] << " ";
Cod corectat:
#include <iostream>
using namespace std;
int main() {
int n = 5;
int vector[5];
// Citire CORECTĂ
for (int i = 0; i < n; i++) {
cin >> vector[i];
}
// Afișare CORECTĂ
for (int i = 0; i < n; i++) {
cout << vector[i] << " ";
}
return 0;
}
Sarcina 2: Implementare completă
Cerință: Scrie un program care citește n, apoi n numere. Programul afișează: 1. Elementele în ordinea citirii 2. Elementele în ordine inversă 3. Doar elementele de pe poziții pare (0, 2, 4...)
Soluție pentru Sarcina 2:
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
const int MAX = 1000;
int v[MAX];
// 1. Citire elemente
for (int i = 0; i < n; i++) {
cin >> v[i];
}
cout << "Elementele in ordinea citirii: ";
// 2. Afișare ordine citire
for (int i = 0; i < n; i++) {
cout << v[i] << " ";
}
cout << endl;
cout << "Elementele in ordine inversa: ";
// 3. Afișare ordine inversă
for (int i = n - 1; i >= 0; i--) {
cout << v[i] << " ";
}
cout << endl;
cout << "Elementele de pe pozitii pare (0, 2, 4...): ";
// 4. Afișare poziții pare
for (int i = 0; i < n; i++) {
if (i % 2 == 0) { // i este par
cout << v[i] << " ";
}
}
cout << endl;
return 0;
}
Explicații importante:
- Poziții pare: Indicele 0 este considerat par, 1 impar, 2 par, etc.
- Condiția pentru par:
i % 2 == 0 - Afisare clară: Adăugăm mesaje explicative înainte de fiecare afișare
- Endl după fiecare secvență: Pentru o afișare mai ordonată
- Teste recomandate:
- n=5, valori: 1 2 3 4 5
- n=3, valori: 10 20 30
- n=1, valori: 100