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

Дек символов - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.93
Ded_Vasilij
 Аватар для Ded_Vasilij
229 / 211 / 15
Регистрация: 01.09.2012
Сообщений: 2,103
15.02.2013, 20:23     Дек символов #1
Доброго времени суток всем.
У меня такая проблема: есть задача -
Реализовать класс "Дек символов" (на базе списка).

Реализовать класс "Массив деков". Длина массива определяется во время
инициализации и в дальнейшем не меняется. Массив должен хранить сами деки,
а не указатели на них. Доступ к элементам массива осуществляется с помощью
квадратных скобок.
Начал делать, но поскольку с классами работаю впервые, то не совсем разобрался как это делать.
вот моя реализация:
файл L2.h
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
#pragma once
class L2_elem
{
    char el;
    L2_elem* next;
    L2_elem* prev;
public:
    L2_elem();                                      //занулить указатели
    L2_elem (char c, L2_elem* n,L2_elem* p);        //пприсваивание значений
    char get_el();
    L2_elem* get_n();
    L2_elem* get_p();
};
class L2
{
    L2_elem* head;
    
public:
    L2();                               // инициализация
    ~L2();                              // деструктор
    L2(const L2 &List);                 // копирование
    L2& operator = (const L2& List);    // оператор перегрузки
    char get_el (int i);                // получить элемент
    void put (char el);                 // добавить элемент
    void del();                         // удалить элемент
    void print (L2 List);               // печать
    int size (L2 List);                 // размер списка
};
файл L2.cpp
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
#include <iostream>
#include "L2.h"
L2_elem :: L2_elem()
{
    L2_elem.next = 0;// error C2143: синтаксическая ошибка: отсутствие ";" перед "."
 
    L2_elem.prev = 0;
}
char L2_elem :: get_el()
{
    return el;
}
 
L2_elem*  L2_elem :: get_n()
{
    return L2_elem.next ;
}
 
 
 
L2 :: L2()
{
    head = new L2_elem;                             // по умолчанию вызывается конструктор без параметров L2_elem
}
Я понимаю, что я сделал чего-то не так, но пока не могу понять чего, ошибка мелкая, из=за нее вся работа встала. Подскажите пожалуйста чего я не так делаю
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.02.2013, 20:23     Дек символов
Посмотрите здесь:

C++ Вектор, дек, список
Полный дек C++
дек C++
дек через список C++
Очередь и дек С++ C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ya_noob
_
200 / 144 / 9
Регистрация: 08.10.2011
Сообщений: 432
15.02.2013, 20:50     Дек символов #2
Цитата Сообщение от Ded_Vasilij Посмотреть сообщение
L2_elem.next = 0;// error C2143: синтаксическая ошибка: отсутствие ";" перед "."
элемент данных next не статический. его можно взять только через объект

Добавлено через 1 минуту
Цитата Сообщение от Ded_Vasilij Посмотреть сообщение
Реализовать класс "Дек символов" (на базе списка).
Реализовать класс "Массив деков".
Эмм, так что же надо то?

Добавлено через 2 минуты
как я понял, L2 - класс двусвязных списков, но как вы из него собираетесь сделать дек. Что такое дек в вашем понимании?
Ded_Vasilij
 Аватар для Ded_Vasilij
229 / 211 / 15
Регистрация: 01.09.2012
Сообщений: 2,103
15.02.2013, 23:54  [ТС]     Дек символов #3
С этим вроде разобрался, благодарю. Теперь другая проблема - не могу написать деструктор, точнее говоря получить доступ к полям класса L2_elem, даже после того, как L2 объявил его наследником, а поля объявил как protected. Подскажите где ошибка пожалуйста. Вот код:
C++
1
2
3
4
5
6
7
8
9
10
L2 :: ~L2()
{
    L2_elem* p = head->next;
    while (p != head)
    {
        p = p->next;//это набросок, мне сейчас главное доступ получить
        delete p->prev;
    }
 
}
ya_noob
_
200 / 144 / 9
Регистрация: 08.10.2011
Сообщений: 432
16.02.2013, 05:35     Дек символов #4
покажите, что у вас получилось (и .h и .cpp). в вашем первом посте в реализации была серьезная проблема с пониманием связных структур. если вы ее не исправили, то не о чем говорить дальше
Ded_Vasilij
 Аватар для Ded_Vasilij
229 / 211 / 15
Регистрация: 01.09.2012
Сообщений: 2,103
16.02.2013, 19:03  [ТС]     Дек символов #5
Вот файл L2.h
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
#pragma once
 
class L2_elem
{
    friend class L2;
    char el;
    L2_elem* next;
    L2_elem* prev;
public:
    L2_elem();                                      //занулить указатели
    L2_elem (char c, L2_elem* n,L2_elem* p);        //присваивание значений
    char get_el();
    L2_elem* get_n();
    L2_elem* get_p();
};
class L2 :  public L2_elem
{
 
    L2_elem* head;
    L2
public:
    L2();                               // инициализация
    ~L2();                              // деструктор
    L2(const L2 &List);                 // копирование
    L2& operator = (const L2& List);    // оператор перегрузки
    char get_el (int i);                // получить элемент
    void put (char el);                 // добавить элемент
    void del();                         // удалить элемент
    void print (L2 List);               // печать
    int size (L2 List);                 // размер списка
};
вот L2.cpp

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
#include <iostream>
#include "L2.h"
L2_elem :: L2_elem()
    : prev(0), next(0)
{
    
}
char L2_elem :: get_el()
{
    return el;
}
 
L2_elem*  L2_elem :: get_p()
{
    return prev;
}
 
L2_elem :: L2_elem (char c, L2_elem* n,L2_elem* p)      //присваивание значений
{
    el = c;
    next = n;
    prev = p;
}
//реализация L2
L2 :: L2()
{
    head = new L2_elem;                             // по умолчанию вызывается конструктор без параметров L2_elem
}
 
L2 :: ~L2()
{
    L2_elem* p = head->next;//это набросок, не уверен, что это будет работать
    while (p != head)
    {
        p = p->next;
        delete p;
    }
 
}
Попробую ответить на ваш вопрос: что такое дек в моем понимании. Насколько я понял, дек отличается от стекас возможностью добавления и удаления элементов с обеих сторон, преподаватель сказал что после реализации двунаправленного списка реализовать дек - пара пустяков. буду благодарен, если вы направите меня на путь истинный, если я чего не так понял

Добавлено через 27 минут
Да, и еще у дека, в отличии от стека ссылки указывают не только на следующий элемент. но и на предыдущий
ya_noob
_
200 / 144 / 9
Регистрация: 08.10.2011
Сообщений: 432
16.02.2013, 19:59     Дек символов #6
Итак, по пунктам:
1. класс L2_elem описывает узел списка. Дружественность с классом L2 тут не нужна, лучше перенесите el, next и prev в public.
Этот класс всё равно используется только для поддержки списка.
2. Дек поддерживает операции вставки/удаления в начале и в конце, так что в классе L2 наряду с head нужен элемент:
C++
1
L2_elem* tail;
для быстрого доступа к концу списка.
Также в L2 нужны функции для вставки/удаления в начале и в конце списка (чего я у вас не вижу):
C++
1
2
3
4
void pushHead( char ); // скорее всего у вас эту функцию выполняет void put( char );
void pushTail( char );
char popHead(); // скорее всего эту функцию выполняет void del();
char popTail();
3. конструктор копирования, деструктор и операция присваивания это конечно хорошо, но они не так важны для вас сейчас, так что закомментируйте их пока не реализуете вставки и удаления и не протестируете их.
4. ну а реализаций важных функций я не вижу (я имею ввиду push'и и pop'ы)
Удачи!
Ded_Vasilij
 Аватар для Ded_Vasilij
229 / 211 / 15
Регистрация: 01.09.2012
Сообщений: 2,103
16.02.2013, 23:18  [ТС]     Дек символов #7
попробовал реализовать puush'и. Получилось как-то так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void L2 :: pushHead (char c)            // добавить элемент в начало списка
{
    L2_elem* NewEl = new L2_elem;
    NewEl->prev = 0;
    NewEl->next = head;
    NewEl->el = c;
    if (head) head->prev  = NewEl;
    if (! tail) tail = head;
}
void L2 :: pushTail (char c)            // добавить элемент в конец списка  
{
    L2_elem* NewEl = new L2_elem;
    NewEl->next = 0;
    NewEl->prev = tail;
    NewEl->el = c;
    if (tail) tail->next  = NewEl;
    if (! head) head = tail;
}
единственно, я еще не совсем разобрался с классами, посмотрите пожалуйста. я пока удаление попробую сделать
Kuzia domovenok
 Аватар для Kuzia domovenok
1883 / 1738 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
16.02.2013, 23:46     Дек символов #8
строки 8 и 17 однозначно ошибочны. зачем приравнивать хвост к голове и голову к хвосту? Чтобы они на один и тот же элемент указывали вместо первого и последнего?
А вот после добавления в голову приравнять голову к новому элементу
И вот после добавления в хвост приравнять хвост к новому элементу
ты забыл
но так, вроде понимаешь, что такое списки.
Kuzia domovenok
 Аватар для Kuzia domovenok
1883 / 1738 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
16.02.2013, 23:59     Дек символов #9
Цитата Сообщение от Kuzia domovenok Посмотреть сообщение
строки 8 и 17 однозначно ошибочны. зачем приравнивать хвост к голове и голову к хвосту? Чтобы они на один и тот же элемент указывали вместо первого и последнего?
Ну да, если список был пуст (!head, !tail) и элемент добавляется первый это справедливо, пардон.
ya_noob
_
200 / 144 / 9
Регистрация: 08.10.2011
Сообщений: 432
17.02.2013, 08:43     Дек символов #10
1. У вас список получается с головой, судя по этому:
C++
1
2
3
4
L2 :: L2()
{
    head = new L2_elem;
}
Я предлагаю сделать его без головы, т.к. это будет легче понять:
C++
1
2
3
4
5
L2 :: L2()
{
    head = 0;
    tail = 0;
}
2. давайте добавим в список L2 элемент-функцию проверки на пустоту списка:
C++
1
2
3
4
bool L2 :: isEmpty ()
{
    return head == 0;
}
Эта функция в дальнейшем будет полезна

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

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
void L2 :: pushHead (char c) 
{
    L2_elem* NewEl = new L2_elem;
    NewEl->prev = 0;
    NewEl->next = head;
    NewEl->el = c;
 
    if ( isEmpty() ) // если список пуст
    {
        head = NewEl; // делаем новый элемент головой
        tail = head;
    }
    else
    {
        head->prev = NewEl;
        head = NewEl;
    }
}
char L2 :: popTail () 
{
    if ( isEmpty() ) return 0; // хотя так делать нехорошо, лучше выкинуть исключение, но пока оставим это
 
    char c = tail->el;
    
    if ( tail->prev == 0 ) // если в списке всего 1 элемент
    {
        delete tail; // удаляем его
        head = 0; // и говорим, что список пуст
        tail = 0;
    }
    else // иначе
    {
        tail = tail->prev; // сдвигаем tail на предыдущий элемент
        delete ( tail->next ); // и удаляем старый последний элемент
        tail->next = 0;
    }
 
    return c;
}
Оставшиеся функции добавления в хвост и удаление из головы реализуются аналогично. Если не догадаешься как, то смотри спойлер
Кликните здесь для просмотра всего текста
просто в соответствующих функциях замени слова head на tail, а tail на head, то же самое сделай с prev и next
Ded_Vasilij
 Аватар для Ded_Vasilij
229 / 211 / 15
Регистрация: 01.09.2012
Сообщений: 2,103
19.02.2013, 19:08  [ТС]     Дек символов #11
Цитата Сообщение от ya_noob Посмотреть сообщение
У вас список получается с головой, судя по этому:

C++
1
2
3
4
L2 :: L2()
{
      head = new L2_elem;
}
Я предлагаю сделать его без головы, т.к. это будет легче понять:
понять это действительно легче, но не уверен, что это пройдет по требованиям. И еще вопросик - в чем моя принципиальная ошибка?

Добавлено через 1 час 31 минуту
ну вот как - то так получилось.
не тестировал еще правда.
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
#include <iostream>
#include "L2.h"
L2_elem :: L2_elem()
    : prev(0), next(0)
{
    
}
char L2_elem :: get_el()
{
    return el;
}
 
L2_elem*  L2_elem :: get_p()
{
    return prev;
}
 
L2_elem :: L2_elem (char c, L2_elem* n,L2_elem* p)      //присваивание значений
{
    el = c;
    next = n;
    prev = p;
}
//реализация L2
L2 :: L2()
{
    head = 0;//new L2_elem;                             // по умолчанию вызывается конструктор без параметров L2_elem
    tail = 0;//new L2_elem;
}
 
bool L2 :: isEmpty ()
{
    return head == 0;
} 
 
 
 
void L2 :: pushHead (char c)            // добавить элемент в начало списка
{
    L2_elem* NewEl = new L2_elem;
    NewEl->prev = 0;
    NewEl->next = head;
    NewEl->el = c;
    if ( isEmpty() )                    // если список пуст
    {
        head = NewEl;                   // делаем новый элемент головой
        tail = head;
    }
    else
    {
        head->prev = NewEl;
        head = NewEl;
    }
}
void L2 :: pushTail (char c)            // добавить элемент в конец списка  
{
    L2_elem* NewEl = new L2_elem;
    NewEl->next = 0;
    NewEl->prev = tail;
    NewEl->el = c;
    if ( isEmpty() )                    // если список пуст
    {
        tail = NewEl;                   // делаем новый элемент хвостом
        head = tail;
    }
    else
    {
        tail->next = NewEl;
        tail = NewEl;
    }
}
 
char L2 :: popHead () 
{
    if ( isEmpty() ) return 0; 
 
    char c = head->el;
    
    if ( head->next == 0 )              // если в списке всего 1 элемент
    {
        delete head;                    // удаляем его
        head = 0;                       // и говорим, что список пуст
        tail = 0;
    }
    else 
    {
        head = head->next; // сдвигаем tail на предыдущий элемент
        delete ( head->prev ); // и удаляем старый последний элемент
        head->prev = 0;
    }
 
    return c;
}
 
char L2 :: popTail () 
{
    if ( isEmpty() ) return 0; 
 
    char c = tail->el;
    
    if ( tail->prev == 0 )              // если в списке всего 1 элемент
    {
        delete tail;                    // удаляем его
        head = 0;                       // и говорим, что список пуст
        tail = 0;
    }
    else 
    {
        tail = tail->prev;              // сдвигаем tail на предыдущий элемент
        delete ( tail->next );          // и удаляем старый последний элемент
        tail->next = 0;
    }
 
    return c;
}
я так понимаю для списка еще нужно реализовать функции поиска, вставки элемента после указанного и удаления заданного элемента. Или это лишнее?
ya_noob
_
200 / 144 / 9
Регистрация: 08.10.2011
Сообщений: 432
19.02.2013, 20:10     Дек символов #12
Цитата Сообщение от Ded_Vasilij Посмотреть сообщение
понять это действительно легче, но не уверен, что это пройдет по требованиям.
голова здесь не дает никаких преимуществ, только занимает лишнюю память
Цитата Сообщение от Ded_Vasilij Посмотреть сообщение
И еще вопросик - в чем моя принципиальная ошибка?
??? если вы имеете ввиду реализацию списка, то вы просто еще не разобрались как работают связные структуры,
или уточните вопрос
Цитата Сообщение от Ded_Vasilij Посмотреть сообщение
я так понимаю для списка еще нужно реализовать функции поиска, вставки элемента после указанного и удаления заданного элемента. Или это лишнее?
Функция поиска может и пригодиться, а вот операций вставки и удаления в середину в деке нет.
Ded_Vasilij
 Аватар для Ded_Vasilij
229 / 211 / 15
Регистрация: 01.09.2012
Сообщений: 2,103
19.02.2013, 20:44  [ТС]     Дек символов #13
позволю себе с вами не согласиться - со связными списками я разобрался довольно таки неплохо - в прошлом году ради хорошей оценки на экзамене перекопал кучу литературы, правда там паскаль был, но это роли не играет. А в предыдущем сообщении несколько неправильно сформулировал вопрос - согласен.
по определению дек - это упорядоченные набор элементов, в котором добавление новых и удаление существующих элементов разрешено с обеих концов. Для дека разрешены следующие операции:
1) добавление элемента в начало; (pushHead)
2) добавление элемента в конец; (pushTail)
3) удаление элемента из начала; // вот здесь вопрос - нужно ли добавлять эти функции
4) удаление элемента с конца. // или ограничиться pop'ами?
Другой вопрос, что я не совсем разобрался с языком, и с ООП в частности, но надеюсь что разберусь.
И еще вот набросал вывод и получение размера, посмотрите пожалуйста, вроде это самое легкое, и тем не менее

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void L2 :: print(L2 List)
{
    L2_elem* temp = head;
    
    while (!isEmpty())
    {
        cout << temp->el << endl;
        temp = temp->next;
    }
}
 
int L2 :: size(L2 List)
{
    L2_elem* temp = head;
    int size = 0;
    while (!isEmpty())
    {       
        temp = temp->next;
        size++;
    }
    return size;
}
ya_noob
_
200 / 144 / 9
Регистрация: 08.10.2011
Сообщений: 432
19.02.2013, 20:58     Дек символов #14
неверно. isEmpty проверяет список на пустоту и здесь не нужен, вам в обоих функциях надо сравнивать указатель temp с нулем

Добавлено через 2 минуты
а и еще его 4 пункт: pop'ы итак удаляют элементы из списка
Ded_Vasilij
 Аватар для Ded_Vasilij
229 / 211 / 15
Регистрация: 01.09.2012
Сообщений: 2,103
19.02.2013, 23:07  [ТС]     Дек символов #15
согласен, с этим я грубо тупанул. Это конечно обидно, ну да ладно. Вроде теперь все робит. Теперь надо бы с конструктором копирования разобраться, деструктором и перегруженным оператором присваивания - если честно - пока не понимаю, что сие значит (оператор). на всякий случай выкладываю весь имеющийся на данный момент код

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
//файл L2.cpp
#include <iostream>
#include "L2.h"
using namespace std;
L2_elem :: L2_elem()
    : prev(0), next(0)
{
    
}
char L2_elem :: get_el()
{
    return el;
}
 
L2_elem*  L2_elem :: get_p()
{
    return prev;
}
 
L2_elem :: L2_elem (char c, L2_elem* n,L2_elem* p)      //присваивание значений
{
    el = c;
    next = n;
    prev = p;
}
//реализация L2
L2 :: L2()
{
    head = 0;//new L2_elem;                             // по умолчанию вызывается конструктор без параметров L2_elem
    tail = 0;//new L2_elem;
}
 
bool L2 :: isEmpty ()
{
    return head == 0;
} 
 
void L2 :: pushHead (char c)            // добавить элемент в начало списка
{
    L2_elem* NewEl = new L2_elem;
    NewEl->prev = 0;
    NewEl->next = head;
    NewEl->el = c;
    if ( isEmpty() )                    // если список пуст
    {
        head = NewEl;                   // делаем новый элемент головой
        tail = head;
    }
    else
    {
        head->prev = NewEl;
        head = NewEl;
    }
}
void L2 :: pushTail (char c)            // добавить элемент в конец списка  
{
    L2_elem* NewEl = new L2_elem;
    NewEl->next = 0;
    NewEl->prev = tail;
    NewEl->el = c;
    if ( isEmpty() )                    // если список пуст
    {
        tail = NewEl;                   // делаем новый элемент хвостом
        head = tail;
    }
    else
    {
        tail->next = NewEl;
        tail = NewEl;
    }
}
 
char L2 :: popHead () 
{
    if ( isEmpty() ) return 0; 
 
    char c = head->el;
    
    if ( head->next == 0 )              // если в списке всего 1 элемент
    {
        delete head;                    // удаляем его
        head = 0;                       // и говорим, что список пуст
        tail = 0;
    }
    else 
    {
        head = head->next; // сдвигаем tail на предыдущий элемент
        delete ( head->prev ); // и удаляем старый последний элемент
        head->prev = 0;
    }
 
    return c;
}
 
char L2 :: popTail () 
{
    if ( isEmpty() ) return 0; 
 
    char c = tail->el;
    
    if ( tail->prev == 0 )              // если в списке всего 1 элемент
    {
        delete tail;                    // удаляем его
        head = 0;                       // и говорим, что список пуст
        tail = 0;
    }
    else 
    {
        tail = tail->prev;              // сдвигаем tail на предыдущий элемент
        delete ( tail->next );          // и удаляем старый последний элемент
        tail->next = 0;
    }
 
    return c;
}
 
void L2 :: print(L2 List)
{
    L2_elem* temp = head;
    
    while (temp)
    {
        cout << temp->el << " ";
        temp = temp->next;
    }
    cout << endl;
}
 
void L2 :: print1(L2 List)
{
    L2_elem* temp = tail;
    while (temp)
    {
        cout << temp->el << " ";
        temp = temp->prev;
    }
    cout << endl;
}
 
int L2 :: size(L2 List)
{
    L2_elem* temp = head;
    int size = 0;
    while (temp)
    {       
        temp = temp->next;
        size++;
    }
    return size;
}
ya_noob
_
200 / 144 / 9
Регистрация: 08.10.2011
Сообщений: 432
20.02.2013, 11:36     Дек символов #16
1. деструктор - это легко: это функция, которая прибирает за объектом перед его удалением. Просто пробегись циклом и удали все узлы списка.
2. конструктор копирования - слегка посложнее: надо создать копию списка на основе уже имеющегося экземпляра. Объявление конструктора копирование такое:
C++
1
L2( L2 &x );
Здесь надо пробежаться циклом по списку x и на основе информации в его узлах сформировать новый список (для добавления узлов в новый список можно воспользоваться уже имеющейся функцией pushTail)
3. оператор присваивания - (в данной ситуации) это комбинация деструктора и конструктора копирования, т.е. сначала удаляешь все узлы из списка, а потом создаешь новый список на основе списка правого операнда.
Объявление такое:
C++
1
L2 &operator=( L2 &x );
Ded_Vasilij
 Аватар для Ded_Vasilij
229 / 211 / 15
Регистрация: 01.09.2012
Сообщений: 2,103
20.02.2013, 20:33  [ТС]     Дек символов #17
С конструктором копирования и деструктором понятно. а вот для чего нужен оператор присваивания? Хотелось бы знать не только что делать, но и зачем.
ya_noob
_
200 / 144 / 9
Регистрация: 08.10.2011
Сообщений: 432
22.02.2013, 11:15     Дек символов #18
Цитата Сообщение от Ded_Vasilij Посмотреть сообщение
для чего нужен оператор присваивания? Хотелось бы знать не только что делать, но и зачем.
Чтобы делать вот так, например:
C++
1
2
3
4
5
L2 list1;
L2 list2;
 
for ( char c = 'a'; c <= 'z'; ++c ) list1.pushTail( c ); // формируем список list1
list2 = list1;
Здесь мы хотим скопировать содержимое списка list1 в список list2. Как видно, это выполняется в одну строку (list2 = list1; ) с помощью перегруженной операции присваивания. А теперь представь, как бы усложнилось чтение этого кода, если бы вместо одной этой строки ты расписал бы всё определение operator=. Следовательно, перегруженные операторы помогают писать более лаконичный код. Но основным назначением перегрузки операторов является возможность обращаться с пользовательскими типами данных как со встроенными.
Ded_Vasilij
 Аватар для Ded_Vasilij
229 / 211 / 15
Регистрация: 01.09.2012
Сообщений: 2,103
23.02.2013, 14:33  [ТС]     Дек символов #19
Благодарю, уже разобрался - на лекции объяснили.
У меня теперь другая проблема. написал конструктор копирования и деструктор - по хожу дела очень коряво. При завершении работы пишет "Необработанное исключение в "0x00a020bc" в "task3.exe": 0xC0000005: Нарушение прав доступа при записи "0x00000004"."
Посмотрите пожалуйста, чего я не так опять сделал.
вот код
файл L2.h
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
#pragma once
 
class L2_elem
{
public: 
    char el;
    L2_elem* next;
    L2_elem* prev;
    L2_elem();                                      //занулить указатели
    L2_elem (char c, L2_elem* n,L2_elem* p);        //присваивание значений
    char get_el();
    L2_elem* get_n();
    L2_elem* get_p();
};
class L2 
{
 
    L2_elem* head;                              // голова
    L2_elem* tail;                              // хвост
public:
    L2();                                       // инициализация
    ~L2();                                      // деструктор
    L2(const L2 &List);                     // копирование
    //L2& operator = (const L2& List);          // оператор перегрузки
    bool isEmpty ();
    char popHead ();                            // получить элемент из начала списка
    char popTail ();                            // получить элемент из конца списка
    void pushHead (char c);                     // добавить элемент в начало списка
    void pushTail (char c);                     // добавить элемент в конец списка  
    void printHead ();                      // печать с головы
    void printTail();                   // печать с хвоста
    int size ();                            // размер списка
    void makeEmpty();
};
файл L2.cpp
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
#include <iostream>
#include "L2.h"
using namespace std;
L2_elem :: L2_elem()
    : prev(0), next(0)
{
    
}
char L2_elem :: get_el()
{
    return el;
}
 
L2_elem*  L2_elem :: get_p()
{
    return prev;
}
 
L2_elem :: L2_elem (char c, L2_elem* n,L2_elem* p)      //присваивание значений
{
    el = c;
    next = n;
    prev = p;
}
//реализация L2
L2 :: L2()
{
    head = 0;                                           // по умолчанию вызывается конструктор без параметров L2_elem
    tail = 0;
}
 
bool L2 :: isEmpty ()
{
    return head == 0;
} 
void L2 :: makeEmpty()
{   
    while (head !=0)
    {
        head = head->next;          
        delete head->prev;
    }
    head->next = 0;
}
 
L2 :: ~L2()
{
    makeEmpty();
}
L2 :: L2 (const L2 &List)
{
    L2_elem* temp = List.head;
    while (temp)
    {
        char c = temp->el;
        temp = temp->next;
        pushHead(c);
    }
}
void L2 :: pushHead (char c)                            // добавить элемент в начало списка
{
    L2_elem* NewEl = new L2_elem(c, head, 0);
    if ( isEmpty() )                                    // если список пуст
    {
        head = NewEl;                                   // делаем новый элемент головой
        tail = head;
    }
    else
    {
        head->prev = NewEl;
        head = NewEl;
    }
}
void L2 :: pushTail (char c)                            // добавить элемент в конец списка  
{
    L2_elem* NewEl = new L2_elem(c,0,tail); 
    if ( isEmpty() )                                    // если список пуст
    {
        tail = NewEl;                                   // делаем новый элемент хвостом
        head = tail;
    }
    else
    {
        tail->next = NewEl;
        tail = NewEl;
    }
}
 
char L2 :: popHead () 
{
    if ( isEmpty() ) return 0;  
    char c = head->el;    
    if ( head->next == 0 )                              // если в списке всего 1 элемент
    {
        delete head;                                    // удаляем его
        head = 0;                                       // и говорим, что список пуст
        tail = 0;
    }
    else 
    {
        head = head->next;                              // сдвигаем tail на предыдущий элемент
        delete  head->prev;                             // и удаляем старый последний элемент
        head->prev = 0;
    }
 
    return c;
}
 
char L2 :: popTail () 
{
    if ( isEmpty() ) return 0; 
 
    char c = tail->el;
    
    if ( tail->prev == 0 )                              // если в списке всего 1 элемент
    {
        delete tail;                                    // удаляем его
        head = 0;                                       // и говорим, что список пуст
        tail = 0;
    }
    else 
    {
        tail = tail->prev;                              // сдвигаем tail на предыдущий элемент
        delete ( tail->next );                          // и удаляем старый последний элемент
        tail->next = 0;
    }
 
    return c;
}
 
void L2 :: printHead()
{
    L2_elem* temp = head;
    
    while (temp)
    {
        cout << temp->el << " ";
        temp = temp->next;
    }
    cout << endl;
}
 
void L2 :: printTail()
{
    L2_elem* temp = tail;
    while (temp)
    {
        cout << temp->el << " ";
        temp = temp->prev;
    }
    cout << endl;
}
 
int L2 :: size()
{
    L2_elem* temp = head;
    int size = 0;
    while (temp)
    {       
        temp = temp->next;
        size++;
    }
    return size;
}
на всякий случай оставил все функции, может еще где косяки есть
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.02.2013, 14:36     Дек символов
Еще ссылки по теме:

C++ Простой дек
C++ Дек в виде массива
C++ Дек-шаблон

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

Или воспользуйтесь поиском по форуму:
Kuzia domovenok
 Аватар для Kuzia domovenok
1883 / 1738 / 116
Регистрация: 25.03.2012
Сообщений: 5,907
Записей в блоге: 1
23.02.2013, 14:36     Дек символов #20
Попытка записи по какому-то указателю, по которому не была выделена память.

Добавлено через 2 минуты
Цитата Сообщение от Ded_Vasilij Посмотреть сообщение
head->next = 0;
строка 43.
уже сам head равен NULL
нельзя значит ни к одному его полю обращаться: ни к next ни к pre ни el
Yandex
Объявления
23.02.2013, 14:36     Дек символов
Ответ Создать тему
Опции темы

Текущее время: 00:24. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru