Как вывести последний элемент вектора c
Перейти к содержимому

Как вывести последний элемент вектора c

  • автор:

Доступ к последнему элементу вектора векторов в c++

Есть вектор векторов vector vec . Он заполняется в методе. Поэтому размерность внутренних векторов бывает разная. Например ,, > . Мне нужно получить последний элемент последнего вектора. Я хотел так:

 double a = vec.back().back(); 

Компилятор не ругается, но программа на этой строке вылетает. Как можно получить этот элемент?
Отслеживать
задан 1 сен 2022 в 12:46
83 8 8 бронзовых знаков

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

Вам еще надо бы учесть, что вектор может быть пустым — тогда программа будет вылетать на такой строке (хоть формально, она и верная).

Можно поступить так:

if( !vec.empty() && !vec.back().empty() )

Отслеживать
ответ дан 1 сен 2022 в 12:52
22.2k 2 2 золотых знака 33 33 серебряных знака 53 53 бронзовых знака
Это и правда помогло! Спасибо)
1 сен 2022 в 13:27

В дополнение к ответу gbg: Я бы вынес всё это в функцию и добавил бы исключение при неправильном параметре.

#include #include #include using namespace std; double get_last_of_last(vector>& vec) < if (vec.empty() || vec.back().empty()) < throw runtime_error("unvalid parameter"); >return vec.back().back(); > int main() < vector> vec = < , , >; cout

Отслеживать
ответ дан 1 сен 2022 в 13:28
583 2 2 серебряных знака 14 14 бронзовых знаков
Нехороший конструктор исключения, принимающий строку. И почему код возврата такой?
1 сен 2022 в 14:02

std::exception не имеет конструктора от строки, это самодеятельность студии. Нужно std::runtime_error или что-то такое.

1 сен 2022 в 17:30

@HolyBlackCat, исправил. Спасибо за разъяснение. Всё время мне про плохой конструктор говорили, я думал, что нужно какой-то другой конструктор использовать.. Только вот их всего 4 (visual studio 2019), а нужный мне только 1 и он принимает строку. Наконец-то понял.

Как вывести последний элемент вектора c

Для добавления элементов в вектор применяется функция push_back() , в которую передается добавляемый элемент:

#include #include int main() < std::vectornumbers; // пустой вектор numbers.push_back(5); numbers.push_back(3); numbers.push_back(10); for(int n : numbers) cout << n << "\t"; // 5 3 10 std::cout

Векторы являются динамическими структурами в отличие от массивов, где мы скованы его заданым размером. Поэтому мы можем динамически добавлять в вектор новые данные.

Функция emplace_back() выполняет аналогичную задачу — добавляет элемент в конец контейнера:

std::vector numbers< 1, 2, 3, 4, 5 >; numbers.emplace_back(8); // numbers = < 1, 2, 3, 4, 5, 8 >;

Добавление элементов на определенную позицию

Ряд функций позволяет добавлять элементы на определенную позицию.

  • emplace(pos, value) : вставляет элемент value на позицию, на которую указывает итератор pos
  • insert(pos, value) : вставляет элемент value на позицию, на которую указывает итератор pos, аналогично функции emplace
  • insert(pos, n, value) : вставляет n элементов value начиная с позиции, на которую указывает итератор pos
  • insert(pos, begin, end) : вставляет начиная с позиции, на которую указывает итератор pos, элементы из другого контейнера из диапазона между итераторами begin и end
  • insert(pos, values) : вставляет список значений начиная с позиции, на которую указывает итератор pos
std::vector numbers< 1, 2, 3, 4, 5 >; auto iter = numbers.cbegin(); // константный итератор указывает на первый элемент numbers.emplace(iter + 2, 8); // добавляем после второго элемента numbers = < 1, 2, 8, 3, 4, 5>;
std::vector numbers1< 1, 2, 3, 4, 5 >; auto iter1 = numbers1.cbegin(); // константный итератор указывает на первый элемент numbers1.insert(iter1 + 2, 8); // добавляем после второго элемента //numbers1 = < 1, 2, 8, 3, 4, 5>; std::vector 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 values < 10, 20, 30, 40, 50 >; std::vector numbers3 < 1, 2, 3, 4, 5 >; auto iter3 = numbers3.cbegin(); // константный итератор указывает на первый элемент // добавляем после первого элемента три первых элемента из вектора values numbers3.insert(iter3 + 1, values.begin(), values.begin() + 3); //numbers3 = < 1, 10, 20, 30, 2, 3, 4, 5>; std::vector numbers4 < 1, 2, 3, 4, 5 >; auto iter4 = numbers4.cend(); // константный итератор указывает на позицию за последним элементом // добавляем в конец вектора numbers4 элементы из списка < 21, 22, 23 >numbers4.insert(iter4, < 21, 22, 23 >); //numbers4 = < 1, 2, 3, 4, 5, 21, 22, 23>;

Удаление элементов

Если необходимо удалить все элементы вектора, то можно использовать функцию clear :

std::vector v < 1,2,3,4 >; v.clear();

Функция pop_back() удаляет последний элемент вектора:

std::vector v < 1,2,3,4 >; v.pop_back(); // v =

Если нужно удалить элемент из середины или начала контейнера, применяется функция std::erase() , которая имеет следующие формы:

  • erase(p) : удаляет элемент, на который указывает итератор p. Возвращает итератор на элемент, следующий после удаленного, или на конец контейнера, если удален последний элемент
  • erase(begin, end) : удаляет элементы из диапазона, на начало и конец которого указывают итераторы begin и end. Возвращает итератор на элемент, следующий после последнего удаленного, или на конец контейнера, если удален последний элемент

std::vector numbers1 < 1, 2, 3, 4, 5, 6 >; auto iter = numbers1.cbegin(); // указатель на первый элемент numbers1.erase(iter + 2); // удаляем третий элемент // numbers1 = < 1, 2, 4, 5, 6 >std::vector numbers2 = < 1, 2, 3, 4, 5, 6 >; auto begin = numbers2.cbegin(); // указатель на первый элемент auto end = numbers2.cend(); // указатель на последний элемент numbers2.erase(begin + 2, end — 1); // удаляем с третьего элемента до последнего // numbers2 =

Также начиная со стандарта С++20 в язык была добавлена функция std::erase() . Она не является частью типа vector. В качестве первого параметра она принимает вектор, а в качестве второго — элемент, который надо удалить:

std::vector numbers3 < 1, 2, 3, 1, 5, 6 >; std::erase(numbers3, 1); // numbers3 =

В данном случае удаляем из вектора numbers3 все вхождения числа 1.

Размер вектора

С помощью функции size() можно узнать размер вектора, а с помощью функции empty() проверить, путой ли вектор:

#include #include int main() < std::vectornumbers; if(numbers.empty()) std::cout

С помощью функции resize() можно изменить размер вектора. Эта функция имеет две формы:

  • resize(n) : оставляет в векторе n первых элементов. Если вектор содержит больше элементов, то его размер усекается до n элементов. Если размер вектора меньше n, то добавляются недостающие элементы и инициализируются значением по умолчанию
  • resize(n, value) : также оставляет в векторе n первых элементов. Если размер вектора меньше n, то добавляются недостающие элементы со значением value

std::vector numbers1 < 1, 2, 3, 4, 5, 6 >; numbers1.resize(4); // оставляем первые четыре элемента — numbers1 = numbers1.resize(6, 8); // numbers1 =

Важно учитывать, что применение функции resize может сделать некорректными все итераторы, указатели и ссылки на элементы.

Изменение элементов вектора

Функция assign() позволяет заменить все элементы вектора определенным набором:

std::vector langs = < "Java", "JavaScript", "C">; langs.assign(4, «C++»); // langs =

В данном случае элементы вектора заменяются набором из четырех строк «C++».

Также можно передать непосредственно набор значений, который заменит значения вектора:

std::vector langs< "Java", "JavaScript", "C">; langs.assign(< "C++", "C#", "C">); // langs =

Еще одна функция — swap() обменивает значения двух контейнеров:

std::vector clangs < "C++", "C#", "Java" >; std::vector ilangs < "JavaScript", "Python", "PHP">; clangs.swap(ilangs); // clangs = < "JavaScript", "Python", "PHP">; for(std::string lang : clangs)

Сравнение векторов

Векторы можно сравнивать — они поддерживают все операции сравнения: , =, ==, !=. Сравнение контейнеров осуществляется на основании сравнения пар элементов на тех же позициях. Векторы равны, если они содержат одинаковые элементы на тех же позициях. Иначе они не равны:

std::vector v1 ; std::vector v2 ; std::vector v3 ; bool v1v2 = v1 == v2; // true bool v1v3 = v1 != v3; // true bool v2v3 = v2 == v3; // false

C++. Класс vector. Методы, обеспечивающие доступ к элементам массива

Класс vector . Методы, обеспечивающие доступ к элементам массива. Методы at() , front() , back() , data() , begin() , end() , cbegin() , cend() , rbegin() , rend() , crbegin() , crend()

Перед изучением данной темы рекомендуется ознакомиться со следующей темой:

Поиск на других ресурсах:

1. Метод at() . Получить элемент вектора по его позиции

Метод at() используется для доступа к конкретному элементу массива на основе заданного индекса. Метод имеет 2 перегруженные реализации

const T& at(const size_t _Pos) const T& at(const size_t _Pos)

здесь T – тип элементов массива.

Первая реализация используется для чтения элемента из массива. Вторая реализация используется для изменения элемента массива.

Пример.

. // Метод at() - получить элемент вектора по его позиции vectordouble> A(5); // Создать массив из 5 элементов типа double // Заполнить произвольными значениями A[0] = 2.8; A[1] = 3.3; A[2] = 4.5; A[3] = 7.3; A[4] = 8.8; // Считать элемент по индексу 2 double x = A.at(2); // x = 4.5 // Изменить значение элемента по индексу 2 A.at(2) = 3.7; .
2. Метод front() . Возвращает ссылку на первый элемент вектора

С помощью метода front() можно получить ссылку на первый элемент массива. Синтаксис объявления двух перегруженных реализаций метода следующий

const T& front() const T& front()

Первая реализация метода позволяет считывать значение первого элемента массива. Вторая реализация позволяет записывать значения в первый элемент массива.

Пример.

. // Метод front() - получить значение первого элемента массива. // 1. Объявить массив из 5 элементов типа float vectorfloat> A(5); // 2. Заполнить массив данными A[0] = 2.88f; A[1] = 3.8f; A[2] = 4.4f; A[3] = 4.9f; A[4] = 5.5f; // 3. Считать и вывести на экран значение первого элемента вектора float x = A.front(); cout // 2.88 .
3. Метод back() . Возвращает ссылку на последний элемент вектора

Чтобы получить доступ к последнему элементу вектора используется метод back() . Этот метод имеет 2 перегруженных реализации, синтаксис объявления которых следующий

const T& back() const T& back()

Первая реализация используется, когда нужно считать значение из последнего элемента вектора. Вторая реализация используется, когда нужно записать значение в последний элемента вектора.

Пример.

. // Метод back() - получить значение последнего элемента массива. // 1. Объявить массив из 5 элементов типа float vectorfloat> A(5); // 2. Заполнить массив данными A[0] = 2.88f; A[1] = 3.8f; A[2] = 4.4f; A[3] = 4.9f; A[4] = 5.5f; // 3. Считать и вывести на экран значение последнего элемента массива float x = A.back(); cout // 5.5 // 4. Изменить последний элемент массива A.back() = 7.9f; // A[4] = 7.9 cout // 7.9 .
4. Метод data() . Получить указатель на вектор

Метод data() позволяет получить указатель на динамический массив. С помощью этого указателя можно иметь доступ к элементам вектора как к обычному массиву.

Синтаксис объявления метода следующий:

T* vectorT>::data()

тут T – тип элементов вектора.

Пример.

. // Метод data() - получить указатель на вектор. // 1. Объявить вектор из 10 элементов типа short. vectorshort> A(10); // 2. Заполнить массив данными for (int i = 0; i < A.size(); i++) A.at(i) = i; // 3. Получить указатель на вектор short* p = A.data(); // 4. С помощью указателя p вывести элементы вектора на экран for (int i=0; i" "; // 5. Вывести элемент вектора с индексом 2 cout // 2 .
5. Метод begin() . Вернуть итератор, указывающий на первый элемент вектора

Метод begin() возвращает итератор, указывающий на первый элемент динамического массива. Метод имеет следующую общую форму:

vectorT>::iterator vectorT>::begin()

здесь T – тип элементов массива.

Пример.

. // Метод begin() - возвращает итератор, установленный на первый элемент вектора // 1. Объявить вектор из 5 элементов типа char vectorchar> A(5); // 2. Заполнить массив данными A[0] = 'a'; A[1] = 'b'; A[2] = 'c'; A[3] = 'd'; A[4] = 'e'; // 3. Объявить итератор на массив элементов типа char vectorchar>::iterator pA; // 4. Установить итератор на начало массива и вывести первый элемент pA = A.begin(); // *pA = 'a' cout 
6. Метод end() . Вернуть итератор, указывающий на последний элемент массива

Метод end() устанавливает итератор на конец массива. Это означает, что итератор установлен на элемент, следующий за последним элементом массива.

C++. STL. Класс vector. Установка итераторов методами begin() и end()

Рисунок 1. Установка итераторов методами begin() и end() . Размер массива size()

Синтаксис объявления метода следующий

vectorT>::iterator vectorT>::end()

Пример.

. // Метод end() - возвращает итератор, установленный на конец массива. // 1. Объявить вектор из 5 элементов типа char. vectorchar> A(5); // 2. Заполнить массив данными A[0] = 'a'; A[1] = 'b'; A[2] = 'c'; A[3] = 'd'; A[4] = 'e'; // 3. Объявить итератор на массив элементов типа char vectorchar>::iterator pA; // 4. Установить итератор на конец массива pA = A.end(); // pA указывает на позицию установленную за последним элементом массива // 5. Перейти на последний элемент массива pA--; // *pA = 'e' cout 
7. Методы cbegin(), cend() . Установить константный итератор на начало и конец массива

При работе с итераторами, кроме обычных итераторов различают константные итераторы. В библиотеке STL стандартный итератор объявляется с использованием типа iterator

vectorT>::iterator It;

Константный итератор объявляется с использованием типа constant_iterator

vectorT>::constant_iterator ConstIt;
  • T – тип элементов массива;
  • constant_iterator – тип, определяющий константный итератор;
  • ConstIt – имя константного итератора.

В отличие от обычного (стандартного) итератора, невозможно изменить значение элемента массива с константным итератором. То есть, присваивание константному итератору некоторого значения value

*ConstIt = value;

вызовет ошибку компиляции.

Методы cbegin() и cend() предназначены для получения константного итератора, который указывает соответственно на начало и конец массива. Общая форма объявления методов следующая

vectorT>::const_iterator cbegin() const vectorT>::const_iterator cend() const

здесь T – тип элементов массива.

Метод cend() возвращает итератор, указывающий на элемент, следующий за последним элементом массива.

Пример.

. // Константный итератор const_iterator // 1. Создать массив целых чисел на основе списка инициализации initializer_listint> L = < 1, 2, 3, 4, 5 >; vectorint> A1(L); // A1 = // 2. Объявить константный итератор it на начало вектора A1 vectorint>::const_iterator it = A1.cbegin(); // 3. С помощью константного итератора вывести элементы вектора A1 cout "A1 color: #0000ff;">while (it != A1.cend()) cout // 4. Попытка изменения значения по константному итератору вызовет ошибку компиляции it = A1.cbegin(); //*it = 8; // ошибка компиляции .
8. Методы rbegin() , rend() . Доступ к элементам массива с помощью реверсного итератора

Реверсный итератор отличается от обычного итератора тем, что порядок следования элементов рассматривается от конца к началу. С этой точки зрения вносятся все возможные изменения в методах обработки и операциях над итераторами. Так, например, операция приращения итератора it++ осуществляет переход к предыдущему элементу итератора, а не к следующему, как в обычном итераторе.

Реверсный итератор объявляется с использованием ключевого слова reverse_iterator

vectorT>::reverse_iterator itReverse;
  • T – тип элементов вектора;
  • itReverse – имя итератора.

Методы rbegin() rend () работают с реверсными итераторами. Они позволяют получить итераторы, указывающие соответственно на начало ( rbegin ) и конец ( rend ) массива. Методы имеют следующие перегруженные реализации

reverse_iteratorvectorT>::iterator> rbegin() reverse_iteratorvectorT>::const_iterator> rbegin() const reverse_iteratorvectorT>::iterator> rend() reverse_iteratorvectorT>::const_iterator> rend() const

Одна из реализаций методов rbegin() и rend() позволяет работать как обычный итератор, допускающий чтение/запись. Вторая реализация этих методов работает как константный итератор, допускающий только чтение.

Пример.

#include iostream> #include vector> using namespace std; void main() < // Реверсный итератор const_iterator // 1. Создать массив вещественных чисел на основе списка инициализации initializer_listdouble> L = < 1.5, 2.2, 3.4, 4.1, 5.8 >; vectordouble> A1(L); // A1 = < 1.5, 2.2, 3.4, 4.1, 5.8 >; // 2. Объявить реверсный итератор itReverse на тип double vectordouble>::reverse_iterator itReverse; // 3. Установить реверсный итератор на начало вектора A1 itReverse = A1.rbegin(); // 4. Вывести первый элемент массива cout "begin: " // 5. С помощью реверсного итератора вывести элементы всего вектора A1. // Важно: элементы выводятся в обратном порядке cout "A1 color: #0000ff;">while (itReverse != A1.rend()) < cout << *itReverse " "; itReverse++; // прирост итератора смещается от конца к началу > cout // 6. Изменить значение элемента с индексом 3 itReverse = A1.rbegin() + 3; // индексация элементов идет от конца *itReverse = 8.5; // Ок! cout "A1[3] color: #333300;">⇑ 
9. Методы crbegin(), crend(). Установить на начало и конец массива константный реверсный итератор

Кроме константного итератора constant_iterator, в библиотеке STL введён константный реверсный итератор, который рассматривает массив от конца до начала. Такой итератор объявляется следующим образом

vectorT>::const_reverse_iterator itConstReverse;
  • T – тип элементов массива;
  • itConstReverse – имя константного реверсного итератора.

Изменить значение элементов массива с помощью константного реверсного итератора не удастся.

Методы crbegin() , crend() предназначены для работы с типом константного реверсного итератора constant_reverse_iterator и имеют следующие объявления

Пример.

#include iostream> #include vector> using namespace std; void main() < // Константный реверсный итератор const_reverse_iterator // 1. Создать массив символов списка инициализации initializer_listchar> L = < 'a', 'b', 'c', 'd' >; vectorchar> A1(L); // A1 = < 'a', 'b', 'c', 'd' >; // 2. Объявить константный реверсный итератор itConstReverse на тип char vectorchar>::const_reverse_iterator itConstReverse; // 3. Установить константный реверсный итератор на начало вектора A1 itConstReverse = A1.crbegin(); // 4. Вывести первый элемент массива cout "begin: " // 5. С помощью константного реверсного итератора вывести элементы всего вектора A1. // Важно: элементы выводятся в обратном порядке cout "A1 color: #0000ff;">while (itConstReverse != A1.crend()) < cout << *itConstReverse " "; itConstReverse++; > cout // 6. Изменить значение элемента с индексом 3 не удастся itConstReverse = A1.crbegin() + 3; //*itConstReverse = 8.5; // ошибка компиляции >

Результат выполнения программы

begin: d A1 = d c b a

Связанные темы

  • Общие сведения о классе vector . Обзор методов. Создание динамического массива. Способы доступа к элементам вектора
  • Методы, определяющие и изменяющие общие характеристики массива: size() , max_size() , capacity() , empty() , shrink_to_fit() , resize() , reserve()
  • Методы, изменяющие данные в массиве. Методы push_back() , pop_back() , clear() , swap() , operator=() , erase() , insert() , assign()

Операции с векторами в STL

Размер вектора можно узнать при помощи универсального метода size() , возвращающего для всех контейнеров в STL их размер. Также есть метод empty() , возвращающий логическое значение ( true , если вектор пустой).

Размер вектора можно изменить в любой момент, при помощи метода resize . У этого метода может быть один или два параметра. Вызов метода resize(n) изменяет размер вектора до n элементов (длина вектора может как уменьшится, так и увеличиться). Вызов метода resize(n, val) изменяет размер вектора до n элементов, и если при этом размер вектора увеличивается, то новые элементы получают значение, равное val.

Очень часто бывает полезно добавлять элементы в конец вектора по одному и удалять элементы из конца вектора по одному. Для добавления нового элемента, равного val в конец вектора используется метод push_back(val) . Для удаления последнего элемента вектора используется метод pop_back() — он не возвращает значения.

Добавление элемента в конец вектора осуществляется в среднем за O(1). Это реализовано за счет того, что память для хранения элементов вектора выделяется “с запасом”, то есть можно будет добавлять элементы по одному, пока не кончится запас памяти. Если запас памяти исчерпан, выделяется новая память, при этом "запас" размера вектора удваивается.

Очистить вектор можно при помощи метода clear() .

Вставка и удаление элементов в середину вектора

Для удаления и вставки элементов в середину вектора используются методы erase и insert . В качестве параметра им нужно передавать итератор, поэтому просто покажем на примере, как их использовать.

Итератор — специальный объект, указывающий на элемент вектора (или другой структуры данных). Итератор на элемент с индексом i можно получить при помощи выражения a.begin() + i . Кроме того, можно при помощи итератора a.end() “отсчитывать” элементы, начиная с конца. При этом a.end() будет итератором на элемент, следующий за последним, a.end() будет итератором на последний элемент, то есть то же самое, что a.begin() + a.size() - 1 , a.end() - 2 — второй элемент с конца и т.д.

Удаление элементов: метод erase

Метод erase позволяет удалять из середины вектора один или несколько элементов. Если вызвать метод erase с одним параметром–итератором, то будет удален соответствующий элемент из вектора, то есть для удаления элемента с индексом i из вектора a нужно вызвать метод следующим образом:

a.erase(a.begin() + i);

Методу erase передать два итератора на начало и конец удаляемого фрагмента, например:

a.erase(a.begin() + i, a.begin() + j);

В этом случае будут удалены элементы с индексами от i (включительно) до j не включительно, то есть элементы a[i] , a[i + 1] , . a[j - 1] . Всего будет удалено j - i элементов.

Методу erase можно передавать и итераторы, полученные относительно итератора end . Например, удалить из вектора три последних элемента можно так:

a.erase(a.end() - 3, a.end());

Подробней про его использование можно прочитать в документации.

Вставка элементов: метод insert

Метод insert позволяет вставлять в середину вектора новый элемент, или несколько равных элементов, или другой вектор, или фрагмент другого вектора. Этот метод также работает с итераторами и про его использование можно прочитать в документации.

Примеры использования метода insert :

Вставка одного элемента со значением val в позицию с индексом i :

a.insert(a.begin() + i, val);

Вставка нескольких равных (количеством count ) элементов со значением val в позицию с индексом i :

a.insert(a.begin() + i, count, val);

Вставка в вектор a в позицию с индексом i фрагмент вектора b с индексами от start включительно до finish не включительно:

a.insert(a.begin() + i, b.begin() + start, b.begin() + finish);

В качестве параметром могут использоваться произвольные итераторы. Рассмотрим несколько примеров:

Весь вектор b добавить в конец вектора a :

a.insert(a.end(), b.begin(), b.end());

Последние 5 элементов вектора b вставить в начало вектора a :

a.insert(a.begin(), b.end() - 5, b.end());

Поскольку вставка и удаление элементов требуют сдвига других элементов вектора, эти операции имеют линейную сложность, то есть выполняются за время, пропорциональное длине вектора.

Присваивание и сравнение векторов

Содержимое одного вектора можно целиком скопировать в другой вектор при помощи операции присваивания. При этом размер вектора A автоматически изменится и будет равен размеру вектора B . A = B .

Также векторы можно сравнивать на равенство и неравенство ( A == B , A != B ), и сравнивать их содержимое в лексикографическом порядке ( A < B , A B , A >= B ).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *