Страница 1 из 2
Дайте примеры циклов с иттераторами
Добавлено: 14 янв 2016, 11:05
Сионист
Дайте примеры циклов с иттераторами и самописных контейнеров с иттераторами.
и требуется вывести в консоль список, начиная с указателя Start и до конца. На указателях это будет
Код: Выделить всё
struct TList
{
int Data;
TList *Next;
};
TList *Start;
...
TList *p;
for (p=Start; p!=nullptr; p=p->Next)
{
std::cout<<p->Data<<std::endl;
}
. А как это будет на иттераторах? Как создавать типы иттераторов для своих контейнеров? Как правильно писать условие завершения цикла?
Re: Дайте примеры циклов с иттераторами
Добавлено: 14 янв 2016, 11:29
WinMain
Примерно так используется шаблон списка из стандартной библиотеки STL...
Код: Выделить всё
#include <list>
typedef struct _MYDATA_
{
// Some fields...
} MYDATA;
int main(int argc, char* argv[])
{
MYDATA md1 = {/*init fields*/};
MYDATA md2 = {/*init fields*/};
MYDATA md3 = {/*init fields*/};
std::list<MYDATA> mdl;
std::list<MYDATA>::iterator it;
mdl.push_back(md1);
mdl.push_back(md2);
mdl.push_back(md3);
for (it = mdl.begin(); it != mdl.end(); ++it)
{
MYDATA& md = *it;
// TODO: use md
}
return 0;
}
Re: Дайте примеры циклов с иттераторами
Добавлено: 14 янв 2016, 11:58
Сионист
А так:
Код: Выделить всё
#include <iostream>
class TList
{
public:
class TItem;
class TItterator
{
private:
friend class TList;
friend class TItem;
TItem *Pointer;
TItterator (TItem *Pointer)
{
this->Pointer=Pointer;
}
public:
TItterator ()
{
}
TItterator operator ++()
{
if (Pointer!=nullptr)
{
Pointer=Pointer->Next;
}
}
TItem & operator * ()
{
return *Pointer;
}
bool operator != (const TItterator &Right)
{
return (Pointer!=Right.Pointer);
}
};
class TItem
{
friend class TList;
friend class TItterator;
private:
TItem *Next;
public:
int Data;
};
private:
TItem *Start;
TItem *Last;
public:
TList()
{
Start=nullptr;
Last =nullptr;
}
void Add(int Data)
{
TItem *Item;
Item=new TItem;
Item->Data=Data;
Item->Next=nullptr;
if (Last!=nullptr)
{
Last->Next=Item;
}
Last=Item;
if (Start==nullptr)
{
Start=Item;
}
}
TItterator Begin()
{
return TItterator(Start);
}
TItterator End ()
{
return TItterator(nullptr);
}
};
int main()
{
TList List;
TList::TItterator Itterator;
List.Add(2);
List.Add(21);
List.Add(3);
List.Add(4);
List.Add(8);
List.Add(5);
List.Add(1);
for (Itterator=List.Begin(); Itterator!=List.End(); ++Itterator)
{
std::cout<<(*Itterator).Data<<std::endl;
}
return 0;
}
правильно? End должен указывать за конец? Куда должен указывать иттератор, созданный конструктором по умолчанию? В него надо завернуть nullptr? Или как? А оператор -> в классе иттератора должен быть? Как его правильно написать?
Re: Дайте примеры циклов с иттераторами
Добавлено: 14 янв 2016, 13:33
WinMain
Вообще по-хорошему метод end() не должен возвращать нулевой указатель.
Лучше вместо nullptr объявить внутри класса некий пустой элемент итератора, который всегда будет являться завершающим.
По аналогии с текстовой строкой, которая завершается нулевым символом. Даже если ты объявишь в коде пустую строку, в ней всё равно будет присутствовать один завершающий символ.
Так же и в списке. Пока в нём ещё нет элементов, методы begin() и end() будут возвращать указатель на этот пустой элемент итератора.
Re: Дайте примеры циклов с иттераторами
Добавлено: 14 янв 2016, 13:36
Сионист
То есть пустоту проверять по полю Data. Ну просто прекрасно. А если это не char и не действительное число? Или действительное, но nan должен поддерживаться, как обычный, а не терминальный элемент? Специальное флаговое поле заводить? И вообще это внутренности, а вопрос был об интерфейсе, за исключением оператора ->. End указывает за конец? Или на конец? Оператор -> надо поддерживать? Какой у него синтаксис перегрузки? Как его реализовать?
Re: Дайте примеры циклов с иттераторами
Добавлено: 14 янв 2016, 14:08
WinMain
Пустоту завершающего элемента проверять не нужно. Тебе нужен лишь указатель на этот элемент.
А метод end() всегда должен возвращать именно этот указатель.
Re: Дайте примеры циклов с иттераторами
Добавлено: 14 янв 2016, 15:10
Сионист
А так:
Код: Выделить всё
#include <iostream>
class TList
{
public:
class TItem;
class TItterator
{
private:
friend class TList;
friend class TItem;
TItem *Pointer;
TItterator (TItem *Pointer)
{
this->Pointer=Pointer;
}
public:
TItterator ()
{
Pointer=nullptr;
}
TItterator operator ++()
{
if (Pointer!=nullptr)
{
Pointer=Pointer->Next;
}
}
TItem &operator * ()
{
return *Pointer;
}
TItem *operator -> ()
{
return Pointer;
}
bool operator != (const TItterator &Right)
{
return (Pointer!=Right.Pointer);
}
};
class TItem
{
friend class TList;
friend class TItterator;
private:
TItem *Next;
public:
int Data;
};
private:
TItem *Start;
TItem *Last;
public:
TList()
{
Start=nullptr;
Last =nullptr;
}
TItterator Insert(const TItterator &Itterator, const int &Data)
{
TItem *Item;
Item=new TItem;
Item->Data=Data;
if (Itterator.Pointer==nullptr)
{
if (Start==nullptr)
{
Start=Item;
Last =Item;
}
else
{
Last->Next=Item;
Last=Item;
}
Item->Next=nullptr;
}
else
{
Item->Next=Itterator.Pointer->Next;
Itterator.Pointer->Next=Item;
}
return TItterator(Item->Next);
}
TItterator Begin()
{
return TItterator(Start);
}
TItterator End ()
{
return TItterator(nullptr);
}
};
int main()
{
TList List;
TList::TItterator Itterator;
Itterator=List.Begin();
Itterator=List.Insert(Itterator, 2);
Itterator=List.Insert(Itterator, 21);
Itterator=List.Insert(Itterator, 3);
Itterator=List.Insert(Itterator, 4);
Itterator=List.Insert(Itterator, 8);
Itterator=List.Insert(Itterator, 5);
Itterator=List.Insert(Itterator, 1);
for (Itterator=List.Begin(); Itterator!=List.End(); ++Itterator)
{
std::cout<<Itterator->Data<<std::endl;
}
return 0;
}
? Не касаясь внутренностей End().
WinMain писал(а):Пустоту завершающего элемента проверять не нужно. Тебе нужен лишь указатель на этот элемент.
А метод end() всегда должен возвращать именно этот указатель.
Не понял. Но реализацию End прошу пока отложить. Скажите, куда он должен указывать.
На конец, или
за конец? А потом уже реализацию End, как для настоящего (

) американца.
Re: Дайте примеры циклов с иттераторами
Добавлено: 14 янв 2016, 16:12
WinMain
Вот как я это сделал.
Для простоты понимания в моём примере нет полей для хранимых пользовательских данных списка, но сути это не меняет...
Код: Выделить всё
class TSimpleList
{
public:
class Node
{
public:
Node(): Prev(nullptr), Next(nullptr)
{
}
Node *Prev;
Node *Next;
};
class Iterator
{
public:
Iterator() : m_node(nullptr)
{
}
Iterator(Node *n)
{
m_node = n;
}
void operator++()
{
if (m_node != nullptr)
{
m_node = m_node->Next;
}
}
bool operator!=(const Iterator& it)
{
return (m_node != it.m_node);
}
private:
Node *m_node;
};
TSimpleList() : m_pBegin(&m_end)
{
}
~TSimpleList()
{
// удаление элементов списка
while (m_end.Prev != nullptr)
{
Node *Last = m_end.Prev;
m_end.Prev = Last->Prev;
delete Last;
}
}
Iterator Begin()
{
return m_pBegin;
}
Iterator End()
{
return &m_end;
}
void Add()
{
if (&m_end != m_pBegin)
{
Node *it = new Node();
Node *Last = m_end.Prev;
Last->Next = it;
m_end.Prev = it;
it->Next = &m_end;
} else
{
m_pBegin = new Node();
m_pBegin->Next = &m_end;
m_end.Prev = m_pBegin;
}
}
private:
Node m_end;
Node* m_pBegin;
};
int _tmain(int argc, _TCHAR* argv[])
{
TSimpleList sl;
TSimpleList::Iterator it;
sl.Add();
sl.Add();
sl.Add();
for (it = sl.Begin(); it != sl.End(); ++it)
{
_puttch('.');
}
_gettch();
return 0;
}
Re: Дайте примеры циклов с иттераторами
Добавлено: 14 янв 2016, 17:04
Сионист
Издеваетесь? Куда должен указывать метод End()? На конец, или за конец? Объясните, как гурону с каменным тамогавком, который ружья то не видел и парсить Ваш код будет долго.
Re: Дайте примеры циклов с иттераторами
Добавлено: 14 янв 2016, 17:32
Romeo
Эндовый итератор всегда должен указывать "за конец" (в твоей терминологии).
А что сложного, что том, чтобы "распарсить" код WinMain'а, я не понимаю. Код прозрачен и читается сразу. А вот твой код тяжело читать.