Сравните два последовательных элемента в std :: list - PullRequest
6 голосов
/ 04 ноября 2008

Я бы хотел сравнить два последовательных элемента в std :: list, просматривая список. Как правильно получить доступ к элементу i + 1, когда мой итератор находится на элементе i? Спасибо Коб

Ответы [ 5 ]

12 голосов
/ 04 ноября 2008

STL предоставляет алгоритм adj_find (), который можно использовать для поиска двух последовательных равных элементов. Существует также версия с пользовательским предикатом.

Это прототипы:

template <class ForwardIterator>
   ForwardIterator adjacent_find ( ForwardIterator first, ForwardIterator last );

template <class ForwardIterator, class BinaryPredicate>
   ForwardIterator adjacent_find ( ForwardIterator first, ForwardIterator last,
                                   BinaryPredicate pred );
10 голосов
/ 04 ноября 2008

Boost имеет утилиту под названием next (и ее обратное, prior) только для этой цели.

*itr == *next(itr)

Редактировать: Но, если мы отступим, чтобы посмотреть на лес, вопрос real заключается в том, зачем писать свою функцию adjacent_find на заказ? (Я рекомендую принять ответ Никола Бонелли.) Это часть STL, и он не требует использования Boost, если ваш код не использует Boost (спасибо комментаторам за указание на это).

8 голосов
/ 04 ноября 2008

Простейшим способом было бы удерживать два итератора (так как вам все равно придется остановиться на предпоследнем).

std::list<int>::const_iterator second = list.begin(),
                               end = list.end();

if ( second != end ) // Treat empty list
    for(std::list<int>::const_iterator first = second++; // Post-increment 
        second != end; 
        ++first, ++second)
    {
        //...
    }

Обратите внимание, что first инициализируется с постинкрементом из second, поэтому при запуске цикла first равно list.begin(), а секунда list.begin()+1.

Крис Джестер-Янг указывает , что у буста есть функции next и prior, хотя я не знаком с этими функциями (из-за моих грехов), их реализация тривиальна (особенно учитывая, что list имеет двунаправленные итераторы).

template <class Iterator>
Iterator next(Iterator i) // Call by value, original is not changed
{ 
    return ++i;
}
// Implementing prior is left as an exercise to the reader ;o) 

Мне кажется, что использование next не решает эту проблему, а также поддерживает оба итератора, так как вы должны помнить, что next(i) не равен end() при каждом использовании.


редактирует:

  • Исправлена ​​ошибка, если список пуст, благодаря комментарию Luc Touraille .
  • Добавьте ссылку на next и почему я думаю, что она не подходит для этого варианта использования.
1 голос
/ 04 ноября 2008

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

if (!l.empty()) {
    for (list<T>::const_iterator i = l.begin();;) {
        const T &a = *i;
        ++i;
        if (i == l.end()) break;
        do_comparison(a, *i);
    }
}

Вы не могли бы сделать это с Итератором ввода, потому что с этими значениями только «существуют», пока у вас есть итератор. Но вы можете использовать прямой итератор.

0 голосов
/ 20 ноября 2015
for (list<int>::iterator it = test.begin(); it!=test.end(); it++) {
        cout<<*it<<":\t";
        list<int>::iterator copy = it;
        for( list<int>::iterator it2 =  ++copy; it2!=test.end();it2++){
            cout<<*it2<<"\t";
        }
        cout<<endl;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...