Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
igor921
Заблокирован
#1

Итераторы (пример использования итератора для шаблона, к примеру списка) - C++

01.06.2013, 14:23. Просмотров 3072. Ответов 17
Метки нет (Все метки)

Доброго времени суток. Форумчани, приведите пожалуйста пример использования итератора для шаблона, к примеру списка. Зараннее благодарен. И если не трудно, разъяснить что это такое и с чем его едят
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.06.2013, 14:23
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Итераторы (пример использования итератора для шаблона, к примеру списка) (C++):

Написание итератора для списка - C++
Приветствую. Вот собственно реализация списка: #include "stdafx.h" #include <iostream> #include <cstring> using namespace std; ...

Реализовать итераторы для списка - C++
Нужно реализовать итераторы для списка вида: p++ постфиксный инкремент q-p q-это указатель,который стоит справа от p. то есть q-p...

Реализовать итераторы begin() и end() для списка - C++
Есть список. и операции для него 1)разыменование 2)инкремент (префиксный и постфиксный) 3) == 4) != Для того,чтобы проверить...

Пример использования генератора случайных чисел для демонстрации динамического полиморфизма - C++
Пример использования генератора случайных чисел для демонстрации динамического полиморфизма.Я в шоке не могу не где найти может тут кто...

Удаление елемента списка с использованием итератора. STL - C++
Надо удалить из списка елементы, значение которых входит в некий диапазон. Я хочу использовать для етого итератор(если такое вообще...

Исправить ошибку компиляции "для использования класса шаблон требуется список аргументов шаблона" - C++
Решил создать класс List для задания двусвязного списка, и в самом начале компилятор начал ругаться на шаблон класса: error C2955:...

17
Убежденный
Системный программист
Эксперт С++
15688 / 7198 / 1137
Регистрация: 02.05.2013
Сообщений: 11,634
Записей в блоге: 1
Завершенные тесты: 1
01.06.2013, 16:08 #2
Итератор - это указатель на элемент контейнера.
Нужен он для того, чтобы работать с элементами контейнера и алгоритмами обобщенно,
независимо от того, какой именно контейнер используется.

Дело в том, что разные контейнеры STL по-разному реализуют доступ к своим элементам.
У vector они расположены последовательно в памяти, у list они связаны через указатели и т.д.
А итератор маскирует эти различия за обобщенным фасадом указателя.
Благодаря итераторам, можно использовать один и тот же алгоритм для разных контейнеров,
не меняя при этом ни строчки кода. Простейший пример:
C++
1
2
3
4
for (container_t::iterator it = Con.begin(); it != Con.end(); ++it)
{
    // ...
}
Этот код последовательно проходит по элементам контейнера Con.
Его тип (container_t) может быть любым: вставьте сюда vector, list, set, map или
queue - код останется работоспособным. В этом основной смысл итераторов.
Тип container и, соответственно, объект Con, может быть любым STL-контейнером.
2
igor921
Заблокирован
01.06.2013, 16:51  [ТС] #3
Спасибо, а можно если не тяжело в кратце описать сам контейнер Con в слечае списка... Точнее как там устроить итератор
0
Убежденный
Системный программист
Эксперт С++
15688 / 7198 / 1137
Регистрация: 02.05.2013
Сообщений: 11,634
Записей в блоге: 1
Завершенные тесты: 1
01.06.2013, 17:00 #4
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <list>
 
int main()
{
    std::list<int> List;
 
    List.push_back(123);
    List.push_back(456);
    List.push_back(789);
 
    for (std::list<int>::iterator it = List.begin(); it != List.end(); ++it)
    {
        std::cout << *it << std::endl;
    }
 
    return 0;
}
>123
>456
>789
1
igor921
Заблокирован
01.06.2013, 17:04  [ТС] #5
Спасибо, я понял это...я имел ввиду что я буду разрабатывать свой шаблон, по типу листа...и как вот это там прикрутить
0
Убежденный
Системный программист
Эксперт С++
15688 / 7198 / 1137
Регистрация: 02.05.2013
Сообщений: 11,634
Записей в блоге: 1
Завершенные тесты: 1
01.06.2013, 17:47 #6
Цитата Сообщение от igor921 Посмотреть сообщение
я имел ввиду что я буду разрабатывать свой шаблон, по типу листа...и как вот это там прикрутить
А зачем ? Вы хотите использовать свой контейнер в стандартных алгоритмах STL ?
0
igor921
Заблокирован
02.06.2013, 12:46  [ТС] #7
Да, именно так нужно
0
stima
487 / 339 / 39
Регистрация: 22.03.2011
Сообщений: 1,084
Завершенные тесты: 2
02.06.2013, 13:09 #8
Section 23.2 Container Requirements
Effective STL by Scott Meyers
The C++ Standard Library: A Tutorial and Reference by Nicolai Josutils
1
Убежденный
Системный программист
Эксперт С++
15688 / 7198 / 1137
Регистрация: 02.05.2013
Сообщений: 11,634
Записей в блоге: 1
Завершенные тесты: 1
02.06.2013, 13:30 #9
Если вкратце: Вам нужно определить свой класс итератора внутри своего класса-контейнера.
И в этом классе итератора (их будет несколько - iterator, const_iterator, reverse_iterator и
const_reverse_iterator) определить необходимые методы и typedef-ы. Как именно это делается -
зависит от особенностей работы контейнера. Пример реализации итератора можно найти в
книге "C++. Стандартная библиотека" (Н. Джосьютис). Не менее полезным будет заглянуть в
соответствующую главу Стандарта С++ про типы итераторов и требования к ним:
"C++ 2003 (ISO/IEC 14882, "24. Iterators Library").
2
igor921
Заблокирован
02.06.2013, 14:36  [ТС] #10
Спасибо за помощь, буду разбираться)
0
kitworker
0 / 0 / 0
Регистрация: 02.05.2016
Сообщений: 6
18.09.2017, 12:29 #11
Здравствуйте!
И у меня возникла подобная(обратная) задача. Я хочу использовать stl контейнер в собственной коллекции ( коллекция = итератор[GoF] + контейнер[stl, или самописный, и т.д.])
Для пояснения приведу рабочий код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include <assert.h>
#include <iostream>
#include <string>
#include <stdexcept>
#include <list>
 
using namespace std;
 
template<class Item>
class Iterator {
public:
    virtual ~Iterator();
    virtual void First() = 0;
    virtual void Next() = 0;
    virtual bool IsDone() const = 0;
    virtual Item * CurrentItem() const = 0;
protected:
    Iterator();
};
 
template<class Item>
Iterator<Item>::Iterator() {
}
 
template<class Item>
Iterator<Item>::~Iterator() {
}
//------------------------------------------------------------------------------
 
struct A {
    A(string mark) :
            mMark(mark) {
    }
    string mMark;
};
 
//------------------------------------------------------------------------------
 
template<class T>
class IteratorList: public Iterator<T> {
    typename list<T>::iterator curr;
    typename list<T>::iterator first;
    typename list<T>::iterator last;
public:
    virtual ~IteratorList() {}
    IteratorList(typename list<T>::iterator c, typename list<T>::iterator f,
            typename list<T>::iterator l) :
                curr(c), first(f), last(l) {
    }
        
// Функция костыль: по сули дублирует код конструктора, но без нее не получатся связать итератор с контейнером внутри коллекции.   
    void  Init(typename list<T>::iterator c, typename list<T>::iterator f, typename list<T>::iterator l ) {
        curr = c;
        first = f;
        last = l;
    }
 
    // By GoF
    virtual void First();
    virtual void Next();
    virtual bool IsDone() const;
    virtual T* CurrentItem() const;
 
    // Стратуструп
    T& operator*() {
        return *curr;
    }
    const T& operator*() const {
        return *curr;
    }
    T* operator->() {
        return &(*curr);
    }
 
 
    IteratorList& operator++();
    IteratorList& operator--();
};
 
template<typename T>
class ContainerList {
public:
    ContainerList() {
    }
    void PushBack(T car) {
        Cares.push_back(car);
    }
 
    typename list<T>::iterator Begin() {
        return Cares.begin();
    }
 
    typename list<T>::iterator End() {
        return Cares.end();
    }
private:
    list<T> Cares;
};
 
template<typename T>
class CollectionList {
public:
    CollectionList() :
        containList(), itList(containList.Begin(), containList.Begin(), containList.End()) { // my пустой itList тоже инит. копиями пустых итераторов
        // идея связать containList и itList на этапе создания коллекции (заранее)
    }
    void Add(T item) {
        containList.PushBack(item);
    }
    T* Get() {
        return itList.CurrentItem();
    }
 
    void First() {
        itList.Init(containList.Begin(), containList.Begin(), containList.End()); // хотелось бы без этой строки 
        itList.First();
    }
 
    void Next() {
        itList.Next();
    }
 
    bool IsDone() {
        return itList.IsDone();
    }
 
private:
    ContainerList<T> containList;
    IteratorList<T> itList;
};
 
//------------------------------------------------------------------------------
 
int main() {
    try {
 
        A* a1 = new A("bmw");
        A* a2 = new A("honda");
        A* a3 = new A("mazda");
 
        CollectionList<A*> coll;
        coll.Add(a1);
        coll.Add(a2);
        coll.Add(a3);
 
        cout  << " collection : \n";
 
        for(coll.First(); !coll.IsDone(); coll.Next()){
            A *a = *coll.Get();
            cout << a->mMark << "\n";
        }
//       coll.Next(); //  assert error
 
    }
 
    catch (exception& e) {
        cerr << "exception: " << e.what() << endl;
    }
    catch (...) {
        cerr << "exception\n";
    }
}
 
//------------------------------------------------------------------------------
 
template<class T>
IteratorList<T>& IteratorList<T>::operator++() {
    ++curr;
    if (curr == last)
        assert(!"iterator past end of list");
    return *this;
}
 
template<class T>
IteratorList<T>& IteratorList<T>::operator--() {
    if (curr == first)
        assert(!"iterator before begin of list");
    --curr;
    return *this;
}
 
//------------------------------------------------------------------------------
 
template<class T>
void IteratorList<T>::First() {
    curr = first;
}
 
template<class T>
void IteratorList<T>::Next() {
 
    if (curr != last)
        ++curr;
    else
        assert(!"iterator past end of list");
}
 
template<class T>
bool IteratorList<T>::IsDone() const {
    return curr == last;
}
 
template<class T>
T* IteratorList<T>::CurrentItem() const {
    return &(*curr);
}
(на github https://github.com/kitworker/MyStdContainer.git )

Вопрос в следующем: Как в функции CollectionList::First() обойтись без метода Init()?

C++
1
2
3
4
    void CollectionList::First() {
        itList.Init(containList.Begin(), containList.Begin(), containList.End());
        itList.First();
    }
Пробовал передавать итераторы в конструктор контейнера параметры по ссылке:
C++
1
2
3
4
       IteratorList::IteratorList(typename list<T>::iterator & c, typename list<T>::iterator & f,
            typename list<T>::iterator & l) :
                curr(c), first(f), last(l) {
    }
Но в таком случае не удается инкрементировать/декрементировать итераторы curr, first, last.
0
DrOffset
7351 / 4451 / 1009
Регистрация: 30.01.2014
Сообщений: 7,292
18.09.2017, 13:17 #12
Цитата Сообщение от kitworker Посмотреть сообщение
Как в функции CollectionList::First() обойтись без метода Init()?
Чуть-чуть поправил твой код:
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#include <cassert>
#include <iostream>
#include <string>
#include <stdexcept>
#include <list>
 
using namespace std;
 
template<class Item>
class Iterator {
public:
    virtual ~Iterator();
    virtual void First() = 0;
    virtual void Next() = 0;
    virtual bool IsDone() const = 0;
    virtual Item * CurrentItem() const = 0;
protected:
    Iterator();
};
 
template<class Item>
Iterator<Item>::Iterator() {
}
 
template<class Item>
Iterator<Item>::~Iterator() {
}
//------------------------------------------------------------------------------
 
struct A {
    A(string mark) :
            mMark(mark) {
    }
    string mMark;
};
 
//------------------------------------------------------------------------------
template<typename T>
class ContainerList ;
 
template<class T>
class IteratorList: public Iterator<T> {
    ContainerList<T> & container;
    typename ContainerList<T>::iterator curr;
 
public:
    virtual ~IteratorList() {}
    IteratorList(ContainerList<T> & c)
        : container(c), curr(c.Begin())
    { }
 
    // By GoF
    virtual void First();
    virtual void Next();
    virtual bool IsDone() const;
    virtual T* CurrentItem() const;
 
    // Стратуструп
    T& operator*() {
        return *curr;
    }
    const T& operator*() const {
        return *curr;
    }
    T* operator->() {
        return &(*curr);
    }
 
 
    IteratorList& operator++();
    IteratorList& operator--();
};
 
template<typename T>
class ContainerList {
public:
    typedef typename list<T>::iterator iterator;
 
    ContainerList() {
    }
    void PushBack(T car) {
        Cares.push_back(car);
    }
 
    iterator Begin() {
        return Cares.begin();
    }
 
    iterator End() {
        return Cares.end();
    }
private:
    list<T> Cares;
};
 
template<typename T>
class CollectionList {
public:
    CollectionList() :
        containList(), itList(containList)
    {
    }
    void Add(T item) {
        containList.PushBack(item);
    }
    T* Get() {
        return itList.CurrentItem();
    }
 
    void First() {
        itList.First();
    }
 
    void Next() {
        itList.Next();
    }
 
    bool IsDone() {
        return itList.IsDone();
    }
 
private:
    ContainerList<T> containList;
    IteratorList<T> itList;
};
 
//------------------------------------------------------------------------------
 
int main() {
    try {
 
        A* a1 = new A("bmw");
        A* a2 = new A("honda");
        A* a3 = new A("mazda");
 
        CollectionList<A*> coll;
        coll.Add(a1);
        coll.Add(a2);
        coll.Add(a3);
 
        cout  << " collection : \n";
 
        for(coll.First(); !coll.IsDone(); coll.Next()){
            A *a = *coll.Get();
            cout << a->mMark << "\n";
        }
 
//       coll.Next(); //  assert error
 
    }
 
    catch (exception& e) {
        cerr << "exception: " << e.what() << endl;
    }
    catch (...) {
        cerr << "exception\n";
    }
}
 
//------------------------------------------------------------------------------
 
template<class T>
IteratorList<T>& IteratorList<T>::operator++() {
    assert(curr != container.End() && "iterator past end of list");
    ++curr;
    return *this;
}
 
template<class T>
IteratorList<T>& IteratorList<T>::operator--() {
    assert(curr != container.Begin() && "iterator before begin of list");
    --curr;
    return *this;
}
 
//------------------------------------------------------------------------------
 
template<class T>
void IteratorList<T>::First() {
    curr = container.Begin();
}
 
template<class T>
void IteratorList<T>::Next() {
 
    if (curr != container.End())
        ++curr;
    else
        assert(!"iterator past end of list");
}
 
template<class T>
bool IteratorList<T>::IsDone() const {
    return curr == container.End();
}
 
template<class T>
T* IteratorList<T>::CurrentItem() const {
    return &(*curr);
}
2
kitworker
0 / 0 / 0
Регистрация: 02.05.2016
Сообщений: 6
18.09.2017, 13:46 #13
Спасибо за быстрый ответ и красивое решение! =)
0
DrOffset
7351 / 4451 / 1009
Регистрация: 30.01.2014
Сообщений: 7,292
18.09.2017, 13:50 #14
kitworker, я там в одном месте еще забыл assert у тебя исправить. Хоть это и не относится к теме, но все же.
C++
1
2
3
4
5
template<class T>
void IteratorList<T>::Next() {
    assert(curr != container.End() && "iterator past end of list");
    ++curr;
}
Весь смысл ассертов в том, что это отладочный инструмент для программиста, чтобы помочь ему не нарушать контракты функций.
И в релизной сборке обычно их полностью отключают (есть специальный макро для этого NDEBUG).
А в твоем коде так не получилось бы. Проверки вынесены из ассерта в отдельные if`ы, которые никуда в релизе не денутся.
1
kitworker
0 / 0 / 0
Регистрация: 02.05.2016
Сообщений: 6
18.09.2017, 13:56 #15
Ага, спасибо, учту!
0
18.09.2017, 13:56
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.09.2017, 13:56
Привет! Вот еще темы с ответами:

Подскажите кросспратформенный пример для вывода списка файлов - C++
Есть ли какой нибудь кроссплатформенный пример для вывода списка файлов в директории C++.

Привести пример реализации любого линейного списка списка с использованием лишь структур - C++
Буду благодарен, если кто-нибудь сможет привести пример реализации любого линейного списка списка с использованием лишь структур (то есть...

Пример использования спецификатора volatile - C++
В приложенной картинке (из книги Г.С. Шилдта по C++) есть пример использования спецификатора volatile. Есть три вопроса. Первый: что...

Пример использования функции extern - C++
Доброго времени суток форумчане! Пытаюсь закрыть долг по программированию, но препод очень жесткий и просто так ставить ставить зачет мне...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru