Operații cu vectori
Adăugarea elementelor în vector
Pentru a adăuga elemente într-un vector se folosește funcția push_back(), căreia i se transmite elementul de adăugat:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> numbers; // vector gol
numbers.push_back(5);
numbers.push_back(3);
numbers.push_back(10);
for(int n : numbers)
std::cout << n << "\t"; // 5 3 10
std::cout << std::endl;
}
Vectorii sunt structuri dinamice, spre deosebire de tablouri (array-uri), unde suntem limitați de dimensiunea prestabilită. De aceea putem adăuga dinamic date noi în vector.
Funcția emplace_back() are un comportament similar — adaugă un element la sfârșitul containerului:
std::vector<int> numbers{ 1, 2, 3, 4, 5 };
numbers.emplace_back(8); // numbers = { 1, 2, 3, 4, 5, 8 };
Adăugarea elementelor pe o anumită poziție
Mai multe funcții permit adăugarea elementelor într-o poziție anume:
- emplace(pos, value): inserează value la poziția indicată de iteratorul pos
- insert(pos, value): inserează value la poziția indicată de pos, similar cu emplace
- insert(pos, n, value): inserează n elemente de tip value începând cu pos
- insert(pos, begin, end): inserează intervalul [begin, end) într-o anumită poziție
- insert(pos, values): inserează o listă de valori în poziția pos
Exemple:
std::vector<int> numbers{ 1, 2, 3, 4, 5 };
auto iter = numbers.cbegin();
numbers.emplace(iter + 2, 8); // numbers = { 1, 2, 8, 3, 4, 5 }
std::vector<int> numbers1{ 1, 2, 3, 4, 5 };
auto iter1 = numbers1.cbegin();
numbers1.insert(iter1 + 2, 8); // numbers1 = { 1, 2, 8, 3, 4, 5 }
std::vector<int> numbers2{ 1, 2, 3, 4, 5 };
auto iter2 = numbers2.cbegin();
numbers2.insert(iter2 + 1, 3, 4); // numbers2 = { 1, 4, 4, 4, 2, 3, 4, 5 }
std::vector<int> values{ 10, 20, 30, 40, 50 };
std::vector<int> numbers3{ 1, 2, 3, 4, 5 };
auto iter3 = numbers3.cbegin();
numbers3.insert(iter3 + 1, values.begin(), values.begin() + 3); // { 1, 10, 20, 30, 2, 3, 4, 5 }
std::vector<int> numbers4{ 1, 2, 3, 4, 5 };
auto iter4 = numbers4.cend();
numbers4.insert(iter4, { 21, 22, 23 }); // numbers4 = { 1, 2, 3, 4, 5, 21, 22, 23 }
Ștergerea elementelor
Pentru a șterge toate elementele din vector se folosește funcția clear():
std::vector<int> v{ 1, 2, 3, 4 };
v.clear();
Funcția pop_back() șterge ultimul element:
std::vector<int> v{ 1, 2, 3, 4 };
v.pop_back(); // v = { 1, 2, 3 }
Pentru a șterge un element din mijlocul containerului se folosește erase():
- erase(p): șterge elementul de la poziția iteratorului p
- erase(begin, end): șterge elementele din intervalul [begin, end)
Aplicarea funcției:
std::vector<int> numbers1 { 1, 2, 3, 4, 5, 6 };
auto iter = numbers1.cbegin(); // iterator spre primul element
numbers1.erase(iter + 2); // ștergem al treilea element
// numbers1 = { 1, 2, 4, 5, 6 }
std::vector<int> numbers2 = { 1, 2, 3, 4, 5, 6 };
auto begin = numbers2.cbegin(); // iterator spre primul element
auto end = numbers2.cend(); // iterator spre ultimul element
numbers2.erase(begin + 2, end - 1); // ștergem de la al treilea element până la penultimul
// numbers2 = {1, 2, 6}
De asemenea, începând cu standardul C++20, a fost adăugată funcția std::erase(). Ea nu face parte din tipul vector. Ca prim parametru primește un vector, iar ca al doilea — elementul care trebuie șters:
std::vector<int> numbers3 { 1, 2, 3, 1, 5, 6 };
std::erase(numbers3, 1); // numbers3 = { 2, 3, 4, 5, 6 }
În acest caz, sunt șterse din vectorul numbers3 toate aparițiile valorii 1.
Dimensiunea vectorului
Cu ajutorul funcției size() putem afla dimensiunea vectorului, iar cu empty() putem verifica dacă vectorul este gol:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> numbers{1, 2, 3};
if(numbers.empty())
std::cout << "Vector is empty" << std::endl;
else
std::cout << "Vector has size " << numbers.size() << std::endl;
}
Cu funcția resize() putem modifica dimensiunea vectorului. Această funcție are două forme:
- resize(n): păstrează primele n elemente. Dacă vectorul are mai multe, le elimină. Dacă are mai puține, adaugă elemente noi inițializate implicit
- resize(n, value): la fel, dar elementele noi vor avea valoarea value
Aplicarea funcției:
std::vector<int> numbers1 { 1, 2, 3, 4, 5, 6 };
numbers1.resize(4); // păstrăm primele patru elemente - numbers1 = {1, 2, 3, 4}
numbers1.resize(6, 8); // numbers1 = {1, 2, 3, 4, 8, 8}
Este important de reținut că utilizarea funcției resize poate invalida toți iteratorii, pointerii și referințele către elemente.
Modificarea elementelor vectorului
Funcția assign() permite înlocuirea tuturor elementelor vectorului cu un nou set:
std::vector<std::string> langs = { "Java", "JavaScript", "C"};
langs.assign(4, "C++"); // langs = {"C++", "C++", "C++", "C++"}
În acest caz, elementele vectorului sunt înlocuite cu un set de patru șiruri "C++".
De asemenea, putem transmite direct o listă de valori care va înlocui conținutul vectorului:
std::vector<std::string> langs{ "Java", "JavaScript", "C"};
langs.assign({ "C++", "C#", "C"}); // langs = { "C++", "C#", "C"}
O altă funcție — swap() — schimbă conținutul a două containere:
std::vector<std::string> clangs { "C++", "C#", "Java" };
std::vector<std::string> ilangs { "JavaScript", "Python", "PHP"};
clangs.swap(ilangs); // clangs = { "JavaScript", "Python", "PHP"};
for(std::string lang : clangs)
{
std::cout << lang << std::endl;
}
Compararea vectorilor
Vectorii pot fi comparați — aceștia suportă toate operațiile de comparație: <, >, <=, >=, ==, !=. Compararea se face pe baza comparației perechilor de elemente de pe aceleași poziții. Vectorii sunt egali dacă au aceleași elemente pe aceleași poziții. În caz contrar, nu sunt egali:
std::vector<int> v1 {1, 2, 3};
std::vector<int> v2 {1, 2, 3};
std::vector<int> v3 {3, 2, 1};
bool v1v2 = v1 == v2; // true
bool v1v3 = v1 != v3; // true
bool v2v3 = v2 == v3; // false