Модераторы: JackYF, bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Класс List 
:(
    Опции темы
шарлотта
Дата 15.5.2017, 01:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 1.3.2017

Репутация: нет
Всего: нет



Здравствуйте! Требуется создать шаблонный класс List для двусвязного списка.
Код

template <class _DataType> class List {
    class  Node {
    public:
        _DataType  data;
        Node *next, *prev;
        Node(_DataType  data = 0)
            : data(data), next(nullptr), prev(nullptr)
        {}
        Node(const Node &node)
            : data(node.data), next(node.next), prev(node.prev) {
            Node *next = new Node(node.next);
            Node *prev = new Node(node.prev);
        }
        ~Node() {
            delete next;
            delete prev;
        }
    };
    Node *begin;
    Node *end;
public:
    List();
    List(int size);
    List(int size, _DataType val);
    ~List() {
        Clear();
    }
    void Clear();
    void PushBack(Node *elem);


Код

template <class _DataType>
List <_DataType>::List()
    :begin(nullptr), end(nullptr) {
    Node *elem = new Node;
    PushBack(elem);
}

template <class _DataType>
List <_DataType>::List(int size) {
    for (int i = 0; i < size; i++) {
        Node *elem = new Node;
        PushBack(elem);
    }
}

template <class _DataType>
List <_DataType>::List(int size, _DataType val) {
    for (int i = 0; i < size; i++) {
        Node *elem = new Node(val);
        PushBack(elem);
    }
}

template <class _DataType>
void List<_DataType>::PushBack(Node *elem) {
    Node *tmp = new Node(elem);
    tmp->next = nullptr;
    if (end != nullptr) {
        end->next = tmp;
        tmp->prev = end;
    } else {
        tmp->prev = nullptr;
    }
    end = tmp;
}

template <class _DataType>
void List <_DataType>::Clear() {
    Node *cur;
    while (begin != nullptr) {
        cur = begin;
        begin = begin->next;
        delete cur;
    }
    begin = end = nullptr;
}


При создании объекта List<int> list; выдает ошибки
1>main.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall List<int>::List<int>(void)" (??0?$List@H@@QAE@XZ) в функции _main
1>main.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: void __thiscall List<int>::Clear(void)" (?Clear@?$List@H@@QAEXXZ) в функции "public: __thiscall List<int>::~List<int>(void)"
С чем это связано и как исправить? Буду очень благодарна за помощь!

Это сообщение отредактировал(а) шарлотта - 15.5.2017, 01:56
PM MAIL   Вверх
volatile
Дата 15.5.2017, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2101
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(шарлотта @  15.5.2017,  01:52 Найти цитируемый пост)
 error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall List<int>::List<int>(void

Судя по всему вы не подключили к проекту 2-ю часть вашего кода.

Добавлено через 6 минут и 7 секунд
вообще темплейтные функции лучше включать в *.h
PM MAIL   Вверх
шарлотта
Дата 15.5.2017, 17:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 1.3.2017

Репутация: нет
Всего: нет



То есть нужно подключить к main cpp-файл?
PM MAIL   Вверх
volatile
Дата 15.5.2017, 17:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2101
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Я не знаю что у вас в .cpp, но включая экстрасенсорные способности, догадываюсь что второй ваш файл это cpp.
рекомендую перенести из него все в .h, и его уже подключать в main (#include имя.h)
все.

Добавлено @ 17:38
Второй вариант, оставить все в .cpp, и явно инстанцировать для использумых типов, в данном случае int
Код

template class List<int>;
ну и этот .cpp должен быть подключен к проекту. (не путать с #include в main)


Это сообщение отредактировал(а) volatile - 15.5.2017, 17:48
PM MAIL   Вверх
шарлотта
Дата 15.5.2017, 17:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 1.3.2017

Репутация: нет
Всего: нет



Спасибо!
PM MAIL   Вверх
шарлотта
Дата 19.5.2017, 21:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 1.3.2017

Репутация: нет
Всего: нет



Здравствуйте!
Прошу помочь с классом Итератор для списка.
Код

#include "ListIterator.h"

template <class _DataType> class ListIterator;

template <class _DataType> class List {
public:
    class  Node {
    public:
        _DataType  data;
        Node *next, *prev;
        Node(_DataType  data = _DataType())
            : data(data), next(nullptr), prev(nullptr)
        {}

        Node(const Node &node)
            : data(node.data) {
            next = new Node(*node.next);
            prev = new Node(*node.prev);
        }
    };
private:
    Node *begin = nullptr;
    Node *end = nullptr;
public:
    List() = default;

    List(int size, _DataType elem) {
        for (int i = 0; i < size; i++) {
            PushBack(elem);
        }
    }

    List(const List &list) {
        Node *pos = list.begin;
        while (pos) {
            PushBack(pos->data);
            pos = pos->next;
        }
    }

    typedef ListIterator<_DataType> Iterator;

    Iterator Begin() {
        Iterator iter(*this, begin);
        return iter;
    }

    Iterator End() {
        return end->next;
    }

    void PushBack(_DataType elem = 0) {
        Node *tmp = new Node(elem);
        tmp->next = nullptr;
        if (end != nullptr) {
            end->next = tmp;
            tmp->prev = end;
        } else {
            begin = tmp;
            tmp->prev = nullptr;
        }
        end = tmp;
    }

    void Clear() {
        Node *cur;
        while (begin != nullptr) {
            cur = begin;
            begin = begin->next;
            delete cur;
        }
        begin = end = nullptr;
    }

    void PrintfBeginEnd() {
        Node *pos = begin;
        while (pos) {
            std::cout << pos->data << " ";
            pos = pos->next;
        }
        std::cout << std::endl;
    }
};

#endif


Код

#include "List.h"

template <class _DataType> class List;

template <class _DataType> class ListIterator {
private:
    List<_DataType>& container;
    typename List<_DataType>::Node* cur_pos;
public:
    ListIterator(List<_DataType>& ref, typename List<_DataType>::Node* ptr)
    : container(ref), cur_pos(ptr) {}

    ListIterator(const ListIterator &iter)
        :container(iter.container), cur_pos(iter.cur_pos) 
    {}

    ~ListIterator() {
        delete[] cur_pos;
    }

    typename List<_DataType>::Iterator& operator++() {
        cur_pos = cur_pos->next;
        return (*this);
    }

    typename List<_DataType>::Iterator& operator--() {
        cur_pos = cur_pos->prev;
        return (*this);
    }

    _DataType operator*() {
        return *cur_pos->data;
    }



В main пишу 
List<int> list1(4, 5);
List<int>::Iterator iter = list1.Begin();
list1.PrintfBeginEnd();
Ошибка возникает, если я верно поняла, из-за того, что в функции Begin() меняется begin в вызвавшем объекте. Мне кажется, ошибка возникает при возврате значения из этой функции и скорее всего из-за конструктора копирования для элемента Node(const Node &node).
Большое спасибо за помощь!

Это сообщение отредактировал(а) шарлотта - 19.5.2017, 22:11
PM MAIL   Вверх
xvr
Дата 20.5.2017, 15:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 6899
Регистрация: 28.8.2007
Где: Химки, Московская обл

Репутация: 34
Всего: 221



Код

    ~ListIterator() {
        delete[] cur_pos;
    }
Вот этого делать нельзя. cur_pos принадлежит листу, а не итератору на него, и удалять его должен сам лист.

PS. Кстати, он этого не делает, хотя и должен.

PM MAIL   Вверх
шарлотта
Дата 20.5.2017, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 1.3.2017

Репутация: нет
Всего: нет



Спасибо!

Это сообщение отредактировал(а) шарлотта - 20.5.2017, 17:18
PM MAIL   Вверх
шарлотта
Дата 24.5.2017, 19:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 1.3.2017

Репутация: нет
Всего: нет



Добрый вечер! Требуется в классе List реализовать метод Erase, удаляющий элемент в позиции итератора.
Код

#include "ListIterator.h"
template <class _DataType> class ListIterator;
template <class _DataType> class List {
public:
    class  Node {
    public:
        _DataType  data;
        Node *next, *prev;
        Node(_DataType  data = _DataType())
            : data(data), next(nullptr), prev(nullptr)
        {}
        Node(const Node &node)
            : data(node.data) {
            next = new Node(*node.next);
            prev = new Node(*node.prev);
        }
    };
private:
    Node *begin = nullptr;
    Node *end = nullptr;
public:
    List() = default;
    List(int size, _DataType elem) {
        for (int i = 0; i < size; i++) {
            PushBack(elem);
        }
    }
    List(const List &list) {
        Node *pos = list.begin;
        while (pos) {
            PushBack(pos->data);
            pos = pos->next;
        }
    }
    typedef ListIterator<_DataType> Iterator;
    Iterator Begin() {
        Iterator iter(*this, begin);
        return iter;
    }
    Iterator End() {
        return end->next;
    }
    void PushBack(_DataType elem = 0) {
        Node *tmp = new Node(elem);
        tmp->next = nullptr;
        if (end != nullptr) {
            end->next = tmp;
            tmp->prev = end;
        } else {
            begin = tmp;
            tmp->prev = nullptr;
        }
        end = tmp;
    }
    void Clear() {
        Node *cur;
        while (begin != nullptr) {
            cur = begin;
            begin = begin->next;
            delete cur;
        }
        begin = end = nullptr;
    }
    void PrintfBeginEnd() {
        Node *pos = begin;
        while (pos) {
            std::cout << pos->data << " ";
            pos = pos->next;
        }
        std::cout << std::endl;
    }

    void Erase(Iterator &pos) {
        Node *l_prev, *l_next, *cur;
        cur = pos;
        l_prev = cur->prev;
        l_next = cur->next;
        if (l_prev) {
            1_prev->next = cur->next;
        }
        if (l_next) {
            1_next->prev = cur->prev;
        }
        delete cur;
        }

};



Код

#include "List.h"

template <class _DataType> class List;

template <class _DataType> class ListIterator {
private:
    List<_DataType>& container;
    typename List<_DataType>::Node* cur_pos;
public:
    ListIterator(List<_DataType>& ref, typename List<_DataType>::Node* ptr)
    : container(ref), cur_pos(ptr) {}

    ListIterator(const ListIterator &iter)
        :container(iter.container), cur_pos(iter.cur_pos) 
    {}

    ~ListIterator() {}

    typename List<_DataType>::Iterator& operator++() {
        cur_pos = cur_pos->next;
        return (*this);
    }

    typename List<_DataType>::Iterator& operator--() {
        cur_pos = cur_pos->prev;
        return (*this);
    }

    _DataType operator*() {
        return cur_pos->data;
    }

    typename List<_DataType>::Iterator& operator=(const typename List<_DataType>::Iterator& iter) {
        if (this == &iter) {
            return (*this);
        }
        container = iter.container;
        cur_pos = iter.cur_pos;
        return (*this);
    }

    operator typename List<_DataType>::Node*() {
        return cur_pos;
    }

};


Выдает ошибки: error C2227: выражение слева от "->next" должно указывать на тип класса, структуры или объединения либо на универсальный тип error C3688: недопустимый литеральный суффикс "next"; не удалось найти литеральный оператор или шаблон литерального оператора "operator ""next".
Буду очень благодарна, если подскажете правильную реализацию.


Это сообщение отредактировал(а) шарлотта - 24.5.2017, 20:45
PM MAIL   Вверх
volatile
Дата 25.5.2017, 13:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2101
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Вы не привели main.cpp, приходится телепатировать
Скорей всего файлы .h вы включли не в том порядке.

Сделайте так, тогда не будет зависеть от порядка включния:
Цитата(шарлотта @  24.5.2017,  19:55 Найти цитируемый пост)
#pragma once
#include "ListIterator.h"
template <class _DataType> class ListIterator;
template <class _DataType> class List {
public:
    ...

Цитата(шарлотта @  24.5.2017,  19:55 Найти цитируемый пост)
#pragma once
#include "List.h"

template <class _DataType> class List;

template <class _DataType> class ListIterator {
private:
    ...


Добавлено @ 13:41
и еще, случайно заметил
Цитата(шарлотта @  24.5.2017,  19:55 Найти цитируемый пост)
        Node(const Node &node)
            : data(node.data) {
            next = new Node(*node.next);
            prev = new Node(*node.prev);
        }

имхо, бред какой-то.
зачем при создании Node создавать еще следующий элемент и предыдущий?


Это сообщение отредактировал(а) volatile - 25.5.2017, 13:44
PM MAIL   Вверх
шарлотта
Дата 25.5.2017, 19:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 1.3.2017

Репутация: нет
Всего: нет



Вы правы, написала бред. Спасибо!

Код

template <class _DataType> class ListIterator;
template <class _DataType> class List {
public:
    class  Node {
    public:
        _DataType  data;
        Node *next, *prev;
        Node(_DataType  data = _DataType())
            : data(data), next(nullptr), prev(nullptr)
        {}
        Node(const Node &node)
            : data(node.data), next(node.next), prev(node.prev) {}
    };
private:
    Node *begin = nullptr;
    Node *end = nullptr;
public:
    List() = default;
    List(int size, _DataType elem) {
        for (int i = 0; i < size; i++) {
            PushBack(elem);
        }
    }
    List(std::initializer_list <_DataType> list) {
        for (auto it = list.begin(); it != list.end(); it++) {
            PushBack(*it);
        }
       }
    List(const List &list) {
        Node *pos = list.begin;
        while (pos) {
            PushBack(pos->data);
            pos = pos->next;
        }
    }
    typedef ListIterator<_DataType> Iterator;
    Iterator Begin() {
        Iterator iter(*this, begin);
        return iter;
    }
    Iterator End() {
        return end->next;
    }
    void PushBack(_DataType elem = 0) {
        Node *tmp = new Node(elem);
        tmp->next = nullptr;
        if (end != nullptr) {
            end->next = tmp;
            tmp->prev = end;
        } else {
            begin = tmp;
            tmp->prev = nullptr;
        }
        end = tmp;
    }
    void Clear() {
        Node *cur;
        while (begin != nullptr) {
            cur = begin;
            begin = begin->next;
            delete cur;
        }
        begin = end = nullptr;
    }
    void PrintfBeginEnd() {
        Node *pos = begin;
        while (pos) {
            std::cout << pos->data << " ";
            pos = pos->next;
        }
        std::cout << std::endl;
    }
    void Erase(Iterator &pos) {
        Node *l_prev, *l_next, *cur;
        cur = pos;
        l_prev = cur->prev;
        l_next = cur->next;
        if (l_prev) {
            1_prev->next = cur->next;
        }
        if (l_next) {
            1_next->prev = cur->prev;
        }
        delete cur;
        }
};


Код

#include "List.h"
template <class _DataType> class ListIterator {
private:
    List<_DataType>& container;
    typename List<_DataType>::Node* cur_pos;
public:
    ListIterator(List<_DataType>& ref, typename List<_DataType>::Node* ptr)
    : container(ref), cur_pos(ptr) {}
    ListIterator(const ListIterator &iter)
        :container(iter.container), cur_pos(iter.cur_pos) 
    {}
    ~ListIterator() {}
    typename List<_DataType>::Iterator& operator++() {
        cur_pos = cur_pos->next;
        return (*this);
    }
    typename List<_DataType>::Iterator& operator--() {
        cur_pos = cur_pos->prev;
        return (*this);
    }
    _DataType operator*() {
        return cur_pos->data;
    }
    typename List<_DataType>::Iterator& operator=(const typename List<_DataType>::Iterator& iter) {
        if (this == &iter) {
            return (*this);
        }
        container = iter.container;
        cur_pos = iter.cur_pos;
        return (*this);
    }
    operator typename List<_DataType>::Node*() {
        return cur_pos;
    }
};


Код

#include <conio.h>
#include <iostream>

#include "List.h"
#include "ListIterator.h"

int main() {
List<int> list4{1,2,3,-7};
    List<int>::Iterator iter4 = list4.Begin();
    iter4++;
    list4.Erase(iter4);
    list4.PrintfBeginEnd();
    list4.PrintfEndBegin();
getch();
    return 0;
}


Поправила порядок включения, все равно возникают те же ошибки...



Это сообщение отредактировал(а) шарлотта - 25.5.2017, 19:17
PM MAIL   Вверх
volatile
Дата 25.5.2017, 21:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2101
Регистрация: 7.1.2011

Репутация: 16
Всего: 85



Цитата(шарлотта @  25.5.2017,  19:02 Найти цитируемый пост)
        if (l_prev) {
            1_prev->next = cur->next;
        }
        if (l_next) {
            1_next->prev = cur->prev;
        }

а это что?

Добавлено через 2 минуты и 46 секунд
и сообщайте номера строк на которых компилятор выдает ошибку.

PM MAIL   Вверх
шарлотта
Дата 25.5.2017, 21:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 1.3.2017

Репутация: нет
Всего: нет



Извините! Спасибо большое!
Самая лучшая ошибка...
PM MAIL   Вверх
vol4ek
Дата 25.5.2017, 22:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


конь в пальто
**


Профиль
Группа: Участник
Сообщений: 289
Регистрация: 1.5.2011
Где: Минск

Репутация: нет
Всего: 0



Цитата(volatile @ 25.5.2017,  21:13)
Цитата(шарлотта @  25.5.2017,  19:02 Найти цитируемый пост)
        if (l_prev) {
            1_prev->next = cur->next;
        }
        if (l_next) {
            1_next->prev = cur->prev;
        }

а это что?

Добавлено @ 21:16
и сообщайте номера строк на которых компилятор выдает ошибку.

копипаст  smile 
PM MAIL ICQ   Вверх
шарлотта
Дата 26.5.2017, 22:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 1.3.2017

Репутация: нет
Всего: нет



Добрый вечер!
Требуется написать 3 алгоритма.
Написала алгоритм ForEach
Код

template <class Iterator, class  Pred>
void ForEach(Iterator &beg, Iterator &end, Pred op) {
    for (; beg != end; ++beg) {
        op(*beg);
    }
}

вызываю в main
Код

ForEach(list4.Begin(), list4.End(), 
        [](int x) {
        return x * 2;
    });

Не изменяет значения контейнера. Подскажите, пожалуйста, как поправить!

Алгоритм CopyIf
Код

template <class Iterator, class  Pred>
Iterator CopyIf(Iterator source_beg, Iterator source_end, Iterator& dest_beg, Pred pred) {
    for (; source_beg != source_end; ++source_beg) {
        if (pred(*source_beg)) {
            //здесь надо копировать, но не очень понимаю, как это сделать.
            dest_beg++;
        }
    }
    return dest_beg;
}

Так вызываю
Код

List<int>::Iterator iter_copy = CopyIf(list4.Begin(), list4.End(), iter_copy,
        [](int x) {
        return x > 0 == 1;
    });


И алгоритм сортировки вообще не понимаю, как реализовать. Буду очень благодарна за помощь!

Это сообщение отредактировал(а) шарлотта - 29.5.2017, 19:23
PM MAIL   Вверх
Google
  Дата 23.11.2017, 14:19 (ссылка)  





  Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1084 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.