Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.76/55: Рейтинг темы: голосов - 55, средняя оценка - 4.76
2 / 2 / 0
Регистрация: 10.12.2010
Сообщений: 29
1

Итератор для своего контейнерного класса-списка

10.12.2010, 08:06. Показов 10700. Ответов 9
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте.
Есть класс List, и мне надо помимо стандартных методов приделать к нему итератор.
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
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
 
template <typename universum> class List{
    
    public:
        List(){
            root = new node;
            root->next = 0;
            root->prev = 0;
            root->empty = true;
            cur = root;
            };
            
        void append(universum value){
            node *current,*prev;
            current = root;
            prev = root;
            
            if (root->empty){
                root->value = value;
                root->empty = false;
                return;}
                
            while (current){
                prev = current;
                current = current->next;}
                      
            current = new node;
            current->next = 0;
            current->prev = prev;
            prev->next = current;
            current->value = value;
            current->empty = false;
            //cout << "C = " << current<< " "<< current->prev <<  endl;
        };
        
        bool empty(){
            if ((root->next==0) && (root->empty)) return true;
            else return false;
        }
        
        int size(){
            int count;
            node *current;
            current = root;
            while(current){
                count++;
                current = current->next;}
            return count;
        }
        
        universum *begin(){
            int s = size();
            
            //static universum m[s];
            static int *ptr;
            ptr = new int[s];
            node *current;
            current = root;
            // m = &current->value;
            for (int i=0;i<s;i++){
                ptr[i] = current->value;
                current = current->next;}
            return ptr;}
            
        universum *end(){
            node *current;
            current = root;
            while(current->next){
                current = current->next;}
            return &current->value;
        }
        
        void tst(){
            cout << root << " " << root->next << endl;
            };
 
    private:        
        typedef struct node{
            node *next;
            node *prev;
            bool empty;
            universum value;
        };
        node *cur;
        node *root;
 
};
 
 
 
int main()
{
    List <int> list;
    List <string> str;
    int r;
    
    cout << "List empty = "<< list.empty() <<endl;
    
    for (int i=0;i<10;i++) {
        r = rand()%50;
        cout << r << " ";
        list.append(r);}
    
    int *s,*e;
    s = list.begin();
    e = list.end();
    
    cout<< endl << "List empty = "<< list.empty()<< endl;
    cout<< endl << "List size = "<< list.size()<< endl;
  
    for (int i = 0;i<list.size()+1;i++){
        cout << (s+i) << " " << *(s+i) << endl;
    }
    cout<< endl<< endl;
    cout<< endl << s << " " << *s << endl;
    cout<< endl << e << " " << *e << endl;
    
    system("PAUSE");
    return EXIT_SUCCESS;
}
Но в таком виде как сейчас - работает, а если попробовать вызывать begin / end в форе (в смысле в объявлении) то вылетает. Также, кстати, совершенно непонятно поччему вылетает если вставить cout << endl; между первым фором и объяалением указателей.
Так же у меня есть код встраиваемого итератора,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class myiterator : public iterator<bidirectional_iterator_tag, universum>
{
  universum* p;
public:
  myiterator(universum* x) :p(x) {}
  myiterator(const myiterator& mit) : p(mit.p) {}
  myiterator& operator++() {++p;return *this;}
  myiterator& operator++(int) {static myiterator tmp(*this); operator++(); return tmp;}
  myiterator& operator--() {--p;return *this;}
  myiterator& operator--(int) {static myiterator tmp(*this); operator--(); return tmp;}
  bool operator==(const myiterator& rhs) {return p==rhs.p;}
  bool operator!=(const myiterator& rhs) {return p!=rhs.p;}
  const universum& operator*() {return *p;}
  const universum& operator$() {return *p;}
};
Но я не понимаю как его прицепить к списку который на указателях а не в непрерывном куске памяти.

Не по теме:

Помогите, пожалуйста. Мой язык - Питон, а Си я, откровенно говоря, ненавижу. Но сейчас припёрло.

0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.12.2010, 08:06
Ответы с готовыми решениями:

Реализовать двусвязный список (list), итератор (iterator) и константный итератор (сonst_iterator) для списка
не могу понять что должно быть результатом. может подскажете примеры? пожалуйста. Задание:...

Конструктор для контейнерного класса
Такой код: #include &lt;iostream&gt; #include &lt;string&gt; #include &quot;stdlib.h&quot; #include &quot;stdio.h&quot;...

Свой итератор для своего шаблона
Доброго дня всем. Долго разбираюсь, никак не разберусь. Написал свой шаблонный класс. Написал к...

Создание своего Event для своего класса
как создать событие для своего класса? У C# нужно создать свое делегат, потом создать экземпляр...

9
373 / 287 / 97
Регистрация: 17.12.2009
Сообщений: 567
10.12.2010, 08:25 2
ну типа если есть двунаправленный список:
C++
1
2
3
4
5
6
7
8
9
10
11
12
template <typename T> class List{
    struct node{
       T value;
       node *next;
       node *prev;
    };
    struct iterator {
        node *nodeptr;
    };
    node *head;
    node *tail;
};
то двунаправленный итератор реализовать можно так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
class iterator{
    iterator &operator++(int i)
    {
        nodeptr = nodeptr->next;
        return *this;
    }
    iterator &operator--(int i)
    {
        nodeptr = nodeptr->prev;
        return *this;
    }
};
ну и все остальное.
0
2 / 2 / 0
Регистрация: 10.12.2010
Сообщений: 29
10.12.2010, 08:46  [ТС] 3
Спасибо.
Этот класс-итератор надо встроить в класс-список и объявлять так же как обычный итератор?
C++
1
2
3
        for (List<int>:iterator it=s.begin(); it!=s.end(); it++) {
            cout << *it << " ";
        }
Методы, создающие итераторы:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
        myiterator begin(){
            static iterator b(head); 
            return b;
        }
        
        myiterator end(){
            node *current;
            current = root;
            while(current->next){
                                      current = current->next;}
            staticyiterator e(current); 
            return e;
        }
0
373 / 287 / 97
Регистрация: 17.12.2009
Сообщений: 567
10.12.2010, 09:46 4
абсолютно верно, только в методе iterator end() надо возвращать поле tail, потому что это ссылка на последний элемент списка. Конструирование списка должно быть устроено так, чтобы при доступе к последнему элементу не приходилось проходить весь список. И не забыть унарный оператор *
C++
1
2
3
4
T &iterator::operator*()
{
    return nodeptr->value;
}
Добавлено через 32 минуты
что то я не заметил, а почему временная переменная e в посте №3 объявлена static? Если так то метод будет всегда одно и тоже возвращать (то что было при первом вызове метода).
1
2 / 2 / 0
Регистрация: 10.12.2010
Сообщений: 29
10.12.2010, 10:07  [ТС] 5
Ура! Работает.

Если ещё кому понадобится (или я что неправильно сделал, хотя работает):
До public:
C++
1
2
3
4
5
6
7
8
9
    private:
        typedef struct node{
            node *next;
            node *prev;
            bool empty;
            universum value;
        };
        node *root;
        node *last;
Сразу после конструктора:
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
        class scanner{
            node *nodeptr;
            public:
                scanner(node* ptr):nodeptr(ptr) {}
                scanner &operator++(int i)
                {   
                    nodeptr = nodeptr->next;
                    return *this;
                }
                scanner &operator--(int i)
                {
                    nodeptr = nodeptr->prev;
                    return *this;
                }
                universum &operator*()
                {
                    return nodeptr->value;
                }
                bool operator==(const scanner& ptr) 
                {   
                    return nodeptr==ptr.nodeptr;
                }
                bool operator!=(const scanner& ptr) 
                {   
                    return nodeptr!=ptr.nodeptr;
                }
        };
        
        scanner begin(){
            scanner b(root); 
            return b;
        }
        
        scanner end(){
            scanner e(last); 
            return e;
        }
last = current->next; в методе, добавляющем узлы.

C++
1
2
3
    for (List<int>::scanner it=list.begin(); it!=list.end(); it++) {
                cout << *it << " ";
        }
Но один вопрос остался:
C++
1
scanner(node* ptr):nodeptr(ptr) {}
А что это за странный конструктор? В смысле зачем одинарное двоеточие и почему он пустой?

Статики убрал. Работает.
Но когда я встраивал готовый итератор, тот что в <iterator> , компилятор выдавал что возвращается адрес локальной переменной.
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
10.12.2010, 13:04 6
Eliont, Список инициализации конструктора. Работает быстрее + лучше делать именно так.

Советую в самом списке написать
C++
1
typedef /*typename*/ scanner iterator
1
2 / 2 / 0
Регистрация: 10.12.2010
Сообщений: 29
10.12.2010, 15:09  [ТС] 7
Тут ещё вопрос возник...
А чтобы сделать простой и константный итераторы надо повторить класс или можно как-то в одном?
0
В астрале
Эксперт С++
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
10.12.2010, 17:34 8
Eliont, По сути можно сделать так.
C++
1
typedef const scanner const_iterator
вроде бы.
А вот по концепции лучше сделать еще один.
0
146 / 27 / 13
Регистрация: 21.09.2015
Сообщений: 62
26.09.2017, 21:19 9
Вы написали такой цикл:
C++
1
2
3
4
 
for (List<int>::scanner it=list.begin(); it!=list.end(); it++) {
                cout << *it << " ";
        }
Прошу заметить, что при таком подходе последний элемент списка не выведется, поскольку ваша реализация метода end(), такова:

C++
1
2
3
4
scanner end(){
            scanner e(last); 
            return e;
        }
Он вернет последний элемент списка, и когда итератор в цикле будет равен ему(посл. элементу) цикл завершиться, так и не выведя последний элемент.

Для решения ситуации можно поступить так(если nullptr у Вас "конечный" указатель в списке):

C++
1
scanner end(){return nullptr;}
Или завести какую то константу "конец" и ссылаться на нее вместо nullptr.

Поправьте меня, если я не прав.
В том же std::vector метод end() возвращает указатель на некий специальный "закрывающий" элемент(формально) но никак не на последний.

Не по теме:

Тема старая, но ошибка есть ошибка

0
192 / 166 / 82
Регистрация: 01.07.2016
Сообщений: 943
26.09.2017, 22:05 10
У тебя есть ошибка но я покажу её тебе только через 7 лет ЖДИ!
0
26.09.2017, 22:05
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.09.2017, 22:05
Помогаю со студенческими работами здесь

ООП. Создание списка из своего класса
Задача - Создать список из готового класса. Примерный код класса: public class mFiles { ...

Итератор для списка
#include &lt;iostream&gt; using namespace std; template &lt;class T&gt; class Link { public: T value;...

Итератор для класса
Здравствуйте! Имеется определенный класс HashMap, необходимо определить для него...

Создать итератор для списка
:- //ListNode.h #ifndef LISTNODE_H #define LISTNODE_H template &lt;typename NODETYPE&gt; class List;...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru