Як стежити за поточним і попереднім ітератором на векторі c ++?

У мене є один векторний контейнер, і я хотів би зробити операцію віднімання від значень його вмісту за допомогою поточного ітератора проти попереднього ітератора, будь-яка допомога буде дуже вдячна

0
@ Махеш, прикидайтеся, що це карта або встановлений замість вектора. Питання є гарним.
додано Автор Mark Ransom, джерело
Просто цікаво, чому б не просто скористатись оператором [] і робити операції на основі індексу?
додано Автор Mahesh, джерело

10 Відповіді

vector::iterator itPrevious = my_vec.begin();
vector::iterator itCurrent = itPrevious;
if (itCurrent != my_vec.end())
{
    for (++itCurrent;  itCurrent != my_vec.end();  ++itCurrent)
    {
       //do something with itPrevious and itCurrent
        itPrevious = itCurrent;
    }
}
6
додано
@ Edward, що має два ітератори, більш гнучкі, якщо ви не знаєте точних операцій, які будуть виконуватися в циклі.
додано Автор Mark Ransom, джерело
@TooTone, тепер я розумію. Це хороша пропозиція, я складу цю зміну.
додано Автор Mark Ransom, джерело
@TooTone, я не знав, що поставити в першій частині циклу for , оскільки в цьому випадку насправді не потрібно нічого. Я думав, що це буде виглядати занадто дивно, залишаючи його порожнім, тому я просто кинув в неї положення про "нічого".
додано Автор Mark Ransom, джерело
Я думав, що ви можете поставити там ++ itCurrent , а потім мати for як тіло if ?
додано Автор TooTone, джерело
Ви мали на увазі itCurrent в для (itCurrent; ?
додано Автор TooTone, джерело
Чи є якісь причини для того, щоб зберегти окремі "поточні" та "попередні" ітератори, коли арифметика ітератора може отримати покажчик на попереднє значення на місці?
додано Автор Edward, джерело

Якщо ви запитали вектор, ви можете використовувати арифметику ітератора:

#include 
#include 

int main() {
    std::vector v{ 1, 2, 3, 4 };
    for ( auto i = v.begin(); i != v.end(); ++i ) {
        if ( i != v.begin() )
            *i = *i - *(i-1);
    }
    for ( auto i : v )
        std::cout << i << std::endl;
}
2
додано
if(v.size() < 2)
   return;
auto curr = v.begin();
auto next = curr;
++next;
do
{
  whatever(*next - *curr );
  curr = next++;
} while( next != v.end() )
2
додано
if(v.size() < 2)
   return;
auto curr = v.begin();
auto next = curr;
++next;
do
{
  whatever(*next - *curr );
  curr = next++;
} while( next != v.end() )
2
додано

std::vector's iterator is a RandomAccessIterator, so you can perform integer arithmetic on it. Thus, you don't need a separate "current" and "previous" pointer, as long as you start your iteration from begin() + 1:

vector myVec = ...;
if(myVec.size() > 1) { 
    for(vector::iterator iter = myVec.begin()+1; iter != myVec.end(); iter++) {
        Foo current = *iter;
        Foo previous = *(iter - 1);
        Foo subtraction = current - previous;
        ...
    }
}

Звичайно, ви не можете відняти поточний і попередній елемент, якщо в вашому векторі є менше двох елементів. Перевірка розміру може бути зайвою, якщо ви знаєте, що вхідний вектор завжди матиме принаймні два елементи, але я включив його просто для того, щоб бути в безпеці.

2
додано
Якщо myVec.begin() == myVec.end() ви маєте невизначену поведінку
додано Автор Nicola Musatti, джерело
Влучне зауваження. Я думаю, я вважаю, що вектор OP завжди буде не порожнім, оскільки він хоче відняти поточний елемент з попереднього елемента, але я можу виправити це, щоб переконатися, що він не розбивається на порожні вектори.
додано Автор Edward, джерело

std::vector's iterator is a RandomAccessIterator, so you can perform integer arithmetic on it. Thus, you don't need a separate "current" and "previous" pointer, as long as you start your iteration from begin() + 1:

vector myVec = ...;
if(myVec.size() > 1) { 
    for(vector::iterator iter = myVec.begin()+1; iter != myVec.end(); iter++) {
        Foo current = *iter;
        Foo previous = *(iter - 1);
        Foo subtraction = current - previous;
        ...
    }
}

Звичайно, ви не можете відняти поточний і попередній елемент, якщо в вашому векторі є менше двох елементів. Перевірка розміру може бути зайвою, якщо ви знаєте, що вхідний вектор завжди матиме принаймні два елементи, але я включив його просто для того, щоб бути в безпеці.

2
додано
Якщо myVec.begin() == myVec.end() ви маєте невизначену поведінку
додано Автор Nicola Musatti, джерело
Влучне зауваження. Я думаю, я вважаю, що вектор OP завжди буде не порожнім, оскільки він хоче відняти поточний елемент з попереднього елемента, але я можу виправити це, щоб переконатися, що він не розбивається на порожні вектори.
додано Автор Edward, джерело

std::vector's iterator is a RandomAccessIterator, so you can perform integer arithmetic on it. Thus, you don't need a separate "current" and "previous" pointer, as long as you start your iteration from begin() + 1:

vector myVec = ...;
if(myVec.size() > 1) { 
    for(vector::iterator iter = myVec.begin()+1; iter != myVec.end(); iter++) {
        Foo current = *iter;
        Foo previous = *(iter - 1);
        Foo subtraction = current - previous;
        ...
    }
}

Звичайно, ви не можете відняти поточний і попередній елемент, якщо в вашому векторі є менше двох елементів. Перевірка розміру може бути зайвою, якщо ви знаєте, що вхідний вектор завжди матиме принаймні два елементи, але я включив його просто для того, щоб бути в безпеці.

2
додано
Якщо myVec.begin() == myVec.end() ви маєте невизначену поведінку
додано Автор Nicola Musatti, джерело
Влучне зауваження. Я думаю, я вважаю, що вектор OP завжди буде не порожнім, оскільки він хоче відняти поточний елемент з попереднього елемента, але я можу виправити це, щоб переконатися, що він не розбивається на порожні вектори.
додано Автор Edward, джерело

Альтернатива:

for (auto previous = v.begin(), current = previous + 1, end = v.end();
    previous != end && current != end;
    ++previous, ++current)
{
    std::cout << *current << " - " << *previous << " = " << *current - *previous << std::endl;
}
0
додано
@MarkRansom: дякую Виправлено.
додано Автор Johnsyweb, джерело
Помилка при попередньому завершенні ==.
додано Автор Mark Ransom, джерело

Альтернатива:

for (auto previous = v.begin(), current = previous + 1, end = v.end();
    previous != end && current != end;
    ++previous, ++current)
{
    std::cout << *current << " - " << *previous << " = " << *current - *previous << std::endl;
}
0
додано
@MarkRansom: дякую Виправлено.
додано Автор Johnsyweb, джерело
Помилка при попередньому завершенні ==.
додано Автор Mark Ransom, джерело

Існує три ще більш-менш елегантні способи вирішення вашої проблеми.

Визначте новий функтор

І використовуйте його в ітерації for_each

template
struct substractor {
    substractor() : last(nullptr) {}
    void operator()(T& item) const
    {
        if(last != nullptr)
            *last -= item;
        last = &item;
    }
    mutable T* last;
};
...
vector v = {3, 2, 1};
for_each(v.begin(), v.end(), substractor());

Визначте новий алгоритм

Деякі види пари на місці трансформуються тут

template
void pair_transform(It begin, It end, Op op){
    while(begin != end)
    {
        It next = std::next(begin);
        if(next == end) break;
        *begin = op(*begin, *next);
        ++begin;
    }
}
...
vector w = {3, 2, 1};
pair_transform(w.begin(), w.end(), std::minus());

Зберігайте стандарт, використовуйте перетворення

ІМХО найкращий :) Короткий, стандартний, ніде більше не шукати, щоб зрозуміти цей код.

vector z = {3, 2, 1};
std::transform(z.begin(), z.end() - 1, z.begin() + 1, z.begin(), 
    std::minus());
0
додано
IT KPI C/С++ новым годом
IT KPI C/С++ новым годом
747 учасників

Чат обсуждения С/С++. - Вопросы "напишите за меня лабу" - это оффтоп. - Оффтоп, флуд, оскорбления и вбросы здесь не приняты. - За нарушение - предупреждение или mute на неделю. - За спам и рекламу - ban. Все чаты IT KPI: https://t.me/itkpi/1147