Цель состоит в том, чтобы получить доступ к "энному" элементу вектора строк вместо [] оператор или "в" методе. Из того, что я понимаю, итераторы могут использоваться для навигации через контейнеры, но я никогда не использовал итераторы прежде, и что я читаю, сбивает с толку.
Если кто-либо мог бы дать мне некоторую информацию о том, как достигнуть этого, я буду ценить ее.Спасибо.
Вам необходимо использовать begin
и end
методы класса vector
которые возвращают итератор, ссылающийся на первый и последний элемент соответственно.
using namespace std;
vector<string> myvector; // a vector of stings.
// push some strings in the vector.
myvector.push_back("a");
myvector.push_back("b");
myvector.push_back("c");
myvector.push_back("d");
vector<string>::iterator it; // declare an iterator to a vector of strings
int n = 3; // nth element to be found.
int i = 0; // counter.
// now start at from the beginning
// and keep iterating over the element till you find
// nth element...or reach the end of vector.
for(it = myvector.begin(); it != myvector.end(); it++,i++ ) {
// found nth element..print and break.
if(i == n) {
cout<< *it << endl; // prints d.
break;
}
}
// other easier ways of doing the same.
// using operator[]
cout<<myvector[n]<<endl; // prints d.
// using the at method
cout << myvector.at(n) << endl; // prints d.
Обычно итераторы используются для линейного доступа к элементам контейнера; однако с помощью «итераторов произвольного доступа» можно получить доступ к любому элементу так же, как operator []
.
Чтобы получить доступ к произвольным элементам в векторе vec
, вы можете использовать следующее:
vec.begin() // 1st
vec.begin()+1 // 2nd
// ...
vec.begin()+(i-1) // ith
// ...
vec.begin()+(vec.size()-1) // last
Ниже приводится пример типичного шаблона доступа (более ранние версии C ++):
int sum = 0;
using Iter = std::vector<int>::const_iterator;
for (Iter it = vec.begin(); it!=vec.end(); ++it) {
sum += *it;
}
Преимущество использования итератора заключается в том, что вы можете применить тот же шаблон к другим контейнерам :
sum = 0;
for (Iter it = lst.begin(); it!=lst.end(); ++it) {
sum += *it;
}
По этой причине очень легко создать код шаблона, который будет работать так же независимо от типа контейнера . Еще одно преимущество итераторов состоит в том, что он не предполагает, что данные находятся в памяти; например, можно создать прямой итератор, который может считывать данные из входного потока или просто генерирует данные на лету (например, генератор диапазона или случайных чисел).
Другой вариант с использованием std :: for_each
и лямбда-выражений:
sum = 0;
std::for_each(vec.begin(), vec.end(), [&sum](int i) { sum += i; });
Начиная с C ++ 11, вы можете использовать auto
, чтобы не указывать очень длинное и сложное имя типа итератора. как было показано ранее (или даже более сложно):
sum = 0;
for (auto it = vec.begin(); it!=vec.end(); ++it) {
sum += *it;
}
И, кроме того, есть более простой вариант для каждого:
sum = 0;
for (auto value : vec) {
sum += value;
}
И, наконец, есть также std :: accumulate
, где вы должны быть будьте осторожны при добавлении целых чисел или чисел с плавающей запятой.
Итераторы Vector являются итераторами с произвольным доступом, что означает, что они выглядят как простые указатели.
Вы можете получить доступ к n-му элементу, добавив n к итератору, возвращаемому методом контейнера begin ()
, или вы можете использовать оператор []
.
std::vector<int> vec(10);
std::Vector<int>::iterator it = vec.begin();
int sixth = *(it + 5);
int third = *(2 + it);
int second = it[1];
В качестве альтернативы вы можете использовать функцию advance , которая работает со всеми видами итераторов. (Вам следует подумать, действительно ли вы хотите выполнять «произвольный доступ» с итераторами, не являющимися произвольными, поскольку это может быть дорогостоящим делом.)
std::vector<int> vec(10);
std::vector<int>::iterator it = vec.begin();
std::advance(it, 5);
int sixth = *it;