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

Покритикуйте код - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 46, средняя оценка - 4.80
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,512
02.10.2011, 23:28     Покритикуйте код #1
Есть класс Студенты (реализован через односвязный список), хотел бы услышать критику по поводу его улучшения, если кому не лень разбираться в столь поздний час Сам код естественно полностью рабочий и предупреждений тоже компилятор не выдаёт (если не считать в main в условии while, но там всё ок) так что хотелось бы услышать Ваши замечания если что можно сделать лучше.

Students.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
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
#ifndef STUDENTS_H
#define STUDENTS_H
 
#include <string>
using std::string;
 
#include <iostream>
using std::cout;
using std::cerr;
 
#include <iomanip>
using std::setw;
using std::left;
using std::right;
 
#include <stdexcept>
using std::out_of_range;
 
class Students
{
    struct ListItem
    {
        string fullname;
        string group;
        int year;
        int average;
        ListItem *Next;
        ListItem(string ="",int =0,int =0,string ="",ListItem* =0);
    };
 
    ListItem *Head;
    ListItem *Tail;
    ListItem *Current; //указатель на текущий элемент
    int count; // всего элементов
 
public:
    class iterator
    {
        Students::ListItem* current;
 
        //функция для проверки что current инициализирован
        void correct(){if(!*this) throw Students::Exception("access denied");}
 
        public:
        string first(){correct();return current->fullname;}
        string second(){correct();return current->group;}
        int third(){correct();return current->year;}
        int four(){correct();return current->average;}
 
        iterator() {current=0;}
 
        iterator(const Students &right){*this=right;}
        iterator(Students::ListItem* right){*this=right;}
        iterator& operator=(Students &right);
        iterator operator=(Students::ListItem* right);
 
        iterator& operator++();
        iterator operator++(int);
        bool operator==(const iterator& right) const;
        bool operator!=(const iterator& right) const;
        iterator* operator*(){return this;}
        operator bool(){return current!=0;}
    };
 
    class Exception
    {
        string str;
        public:
        Exception(string data) :str(data){};
        string what(){return str;}
    };
 
 
 
    Students(): Head(0), Tail(0), Current(0), count(0) {}
    Students(string data, int y, int a, string g);
    ~Students(){this->deleteAll();}
 
 
    void addToTail(string data, int y, int a, string g);
    void addToHead(string data, int y, int a, string g);
 
 
    void deleteFromHead(bool mode=1);//1 - с предупреждением(исключением) если список пуст
    void deleteFromTail();
    void deleteAll();
 
    //сортировка, принимает функцию для сравнения элементов
    void sort(bool cmp(string&,string&));
 
    //методы возвращающие итераторы
    iterator begin(){return Head;}
    iterator end(){return iterator(0);}
};
 
 
#endif
Students.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
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
#include "Students.h"
 
//////////////////////STUDENTS/////////////////
 
Students::ListItem::ListItem(string name,int y,int aver,string gr,ListItem* next)
{
    fullname=name;
    group=gr;
    average=(aver>=0 && aver<=100 ? aver : -1);
    year=(y>=1950 && y<=2012 ? y : -1);
 
    if(average==-1 || year==-1)
     throw Exception("wrong data");
    Next=next;
}
 
Students::Students(string data, int y, int a, string g)
{
    Head=Tail=new ListItem(data,y,a,g);
    Current=0;
    count=1;
}
 
 
void Students::addToTail(string data, int y, int a, string g)
{
    if (Head)
    {
        Tail->Next=new ListItem(data,y,a,g,0);
        Tail=Tail->Next;
        count++;
    }
    else
        Head=Tail=new ListItem(data,y,a,g);
}
 
 
void Students::addToHead(string data, int y, int a, string g)
{
    if (Head)
    {
        ListItem* temp=Head;
        Head=new ListItem(data,y,a,g);
        Head->Next=temp;
        count++;
    }
    else
        Head=Tail=new ListItem(data,y,a,g);
}
 
void Students::deleteFromHead(bool mode)
{
    if(Head->Next)
    {
        ListItem *temp=Head;
        Head=Head->Next;
        count--;
        delete temp;
    }
 
    else if (Head)
    {
        ListItem *temp=Head;
        Head=Tail=Current=0;
        delete temp;
        count=0;
    }
 
    else if(mode)
     throw Exception("list is empty");
}
 
void Students::deleteFromTail()
{
    if(Tail != Head)
    {
        ListItem *temp=Head;
        while(temp->Next!=Tail)
            temp=temp->Next;
 
    ListItem *toDelete=temp->Next;
    Tail=temp;
    temp->Next=0;
 
    delete toDelete;
    count--;
    }
 
    else if(Tail==0)
     throw Exception("list is empty");
 
    else
     Head=Tail=0;
}
 
 
void Students::deleteAll()
{
    while (Head)
     deleteFromHead(0);
 
    count=0;
}
 
void Students:: sort(bool cmp(string&,string&))
{
    ListItem* new_begin=NULL;
    ListItem* new_end=NULL;
    ListItem* sprev=NULL;
 
    for(ListItem *scur=this->Head;scur!=NULL;scur=this->Head)
    {
        ListItem *smin=NULL;
        ListItem *sminprev=scur;
        string min_name=scur->fullname;
        for(ListItem *gp=scur->Next;gp!=NULL;gp=gp->Next)
        {
            if(cmp(gp->fullname,min_name))
            {
                min_name=gp->fullname;
                smin=gp;
                sprev=sminprev;
            }
            sminprev=gp;
        }
        if(smin==NULL)
        {
            smin=scur;
        }
        else if(smin==scur->Next)
        {
            scur->Next=scur->Next->Next;
        }
        else
        {
            sprev->Next=smin->Next;
        }
        if(new_begin!=NULL)
        {
            new_end->Next=smin;
            new_end=smin;
        }
        else
        {
            new_begin=smin;
            new_end=smin;
        }
        if(smin==this->Head)
         this->Head=smin->Next;
    }
    this->Head=new_begin;
    this->Tail=new_end;
 
}
 
 
//////////////////////ITERATOR/////////////////
Students::iterator& Students::iterator::operator++()
{
    current=current->Next;
     return *this;
}
 
Students::iterator Students::iterator::operator++(int)
{
    iterator temp(*this);
    current=current->Next;
     return temp;
}
 
bool Students::iterator::operator==(const iterator& right) const
{
    return (current==right.current);
}
 
bool Students::iterator::operator!=(const iterator& right) const
{
    return !(*this==right);
}
 
Students::iterator Students::iterator::operator=(Students::ListItem* right)
{
    current=right;
    return *this;
}
 
Students::iterator& Students::iterator::operator=(Students &right)
{
    current=right.Current;
    return *this;
}
main.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
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
using std::string;
#include <windows.h>
#include <string>
#include "Students.h"
#include "StudentsIterator.h"
#include "algorithm"
using std::for_each;
 
 
bool cmp( string &str1, string &str2 )
{
    return strcmp( str1.c_str(), str2.c_str() ) < 0;
}
 
 
void print(Students::iterator *ita)
{
    cout<<setw(15)<<left<<ita->first()
     <<setw(7)<<ita->second()
     <<setw(5)<<ita->third()
     <<setw(7)<<ita->four()<<"\n";
 
}
 
Students::iterator findElement(string toFind, Students::iterator begin, Students::iterator end)
{
    for(;begin!=end;++begin)
    {
        if (begin.first().find(toFind)!=(size_t)-1)
         return begin;
    }
    //если ничего не найдено - вернуть итератор указывающий за конец списка ( на NULL)
    return 0;
}
 
 
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
 
 
    Students test("Иванов Иван",1992,100,"КС-09");
    test.addToTail("ЛЛЛ ФФ",1991,100,"КС-09");
    test.addToTail("БББ ВВ",1992,100,"КС-09");
    test.addToHead("Иванов Василий",1993,100,"КС-08");
    test.addToHead("Иванов Петр", 1990,100,"КС-07");
    test.addToHead("ЯЯЯ ММ",1993,100,"КС-08");
    test.addToTail("ЮЮЮ ЛЛЛ",1994,100,"КС-07");
    test.sort(cmp);
 
    cout<<"All list(after sort):\n";
    for_each(test.begin(),test.end(),print);
    test.deleteFromHead();
    test.deleteFromTail();
    cout<<endl<<"After delFromHead + delFromTail:\n";
    for_each(test.begin(),test.end(),print);
 
    cout<<endl<<"All Students with name \"Иванов\" (searching from begin to end of list):\n";
    Students::iterator it=test.begin();
    while(it=findElement("Иванов",it,test.end()))
     print(*it++);
}
Комментариев только в коде совсем мало, но функции и переменные несут смысловую нагрузку так что надеюсь код не очень сложный в чтении получился.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,512
11.10.2011, 23:53  [ТС]     Покритикуйте код #101
Кстати, как Вы заметили у меня задание с односвязным списком, а ведь есть и на другие структуры у этого препода: лучше всего это на двумерный динамический массив где он хочет чтобы использовали realoc (и конструкторы же конечно не вызываются для новых элементов так как си-стиль), в общем у меня ещё задание ничего так.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.10.2011, 23:54     Покритикуйте код #102
Правда, я не уверен на счёт компилябильности подобных извращений.

Добавлено через 1 минуту
А вот использовать сишное выделение памяти для C++-объектов, это свинство, маразм и преступление против человечности.
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,512
11.10.2011, 23:58  [ТС]     Покритикуйте код #103
Цитата Сообщение от talis Посмотреть сообщение
Скажите вашему Гудвину, что где-то там, за горами и пустыней, уже приняли C++11. Это к слову о vs6.
Так у нас же универ государственный следовательно апгрейд пк раз в 100 лет, хотя как по мне то vs 2005 там как-бы дышала ещё, ну да ладно.
Кстати там дальше интерфейсы идут так вот преподаватель советует читать Петзольда - программирование под win95, говорит что мол функции winapi с того времени не менялись, собственно он прав или нет?
Ато у меня по программе до конца декабря MFC + winapi получается изучение (может и не глубокое, пока не знаю), так вот стоит начинать с той книги Петзольда или что поновее найти, а потом, в случае если заводится лаба на VS 6.0 не будет, притащить ноутбук и с него в 2010 сдавать, как считаете? Ато как-то не хочется закончить универ имея знания которые устарели на десяток лет, хотя вот в случае с asm'ом старые книги вполне подходили, а вот какая ситуация здесь?
aeshes
12.10.2011, 00:35
  #104

Не по теме:


Та же ситуация про компы и ПО - такое старье, что поражаюсь как оно работает. Половина группы ходит с ноутами, преподы только рады, потому что в компьютерных аудиториях не хватает на всех машин. Так что, если есть ноутбук - ходи с ним не только лабу сдавать, но и просто писать в нем на парах

ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
12.10.2011, 01:24     Покритикуйте код #105
Gepar, Дико подозреваю что препод желает чтобы класс итератора был отдельно, а в самом классе Students(List) был typedef на этот итератор.

Итого получится.

C++
1
List<CStudent>::iterator iter = lst.begin();
Собственно как и в STL сделано.

Так же замечу, что в реализации STL от gcc в том же списке _List_iterator<T>, _List_const_iterator не является nested типом, для мапы, для вектора олсо.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
12.10.2011, 01:45     Покритикуйте код #106
Да, и правда. В gcc так, как говорит ForEveR:

C++
1
2
3
4
5
6
7
  template<typename _Tp, typename _Alloc = std::allocator<_Tp> >
    class list : protected _List_base<_Tp, _Alloc>
    {
      // ...
    public:
      // ... 
      typedef _List_iterator<_Tp>                        iterator; /* вот он */

Цитата Сообщение от Gepar Посмотреть сообщение
преподаватель советует читать Петзольда - программирование под win95, говорит что мол функции winapi с того времени не менялись, собственно он прав или нет?
Ничего лучше не знаю. Основы-то не изменились, добавились только всякие WCHAR'ы и прочие совремённости. А книжка сама по себе - отличная.

Добавлено через 3 минуты
Цитата Сообщение от Gepar Посмотреть сообщение
Ато как-то не хочется закончить универ имея знания которые устарели на десяток лет, хотя вот в случае с asm'ом старые книги вполне подходили, а вот какая ситуация здесь?
А найдите мне в старых книгах информацию об инструкциях вроде movups, addps, xorps и других современных расширениях. Старые книги остаются лучшими только ввиду отсутствия хороших новых. Литература всегда должна быть современной.
fasked
Эксперт C++
 Аватар для fasked
4925 / 2505 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
12.10.2011, 09:21     Покритикуйте код #107
Цитата Сообщение от Gepar Посмотреть сообщение
Я что-то не понял как это я дефайном его должен там влеплять
Может все таки typedef?
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,512
12.10.2011, 09:35  [ТС]     Покритикуйте код #108
Цитата Сообщение от talis Посмотреть сообщение
Ничего лучше не знаю. Основы-то не изменились, добавились только всякие WCHAR'ы и прочие совремённости. А книжка сама по себе - отличная.
Хорошо, значит с него и начну.

ForEveR, после ваших слов вроде понял как нужно сделать, я только ещё каюсь в прошлый раз не смог вытащить сам класс итератор из определения чтобы потом функция begin() и end() возвращающая итератор понимала где он и что он собой представляет, ну да сейчас уже класс значительно изменился и итератор не столь привязан к тонкостям класса и всё должно получиться имея нормальный вид.

Цитата Сообщение от fasked Посмотреть сообщение
Может все таки typedef?
Ну судя по логике нет, но мне почему-то запомнилось что препод говорил дефайном что меня и завело в ступор.
fasked
Эксперт C++
 Аватар для fasked
4925 / 2505 / 180
Регистрация: 07.10.2009
Сообщений: 4,306
Записей в блоге: 1
12.10.2011, 09:42     Покритикуйте код #109
Цитата Сообщение от Gepar Посмотреть сообщение
Кстати там дальше интерфейсы идут так вот преподаватель советует читать Петзольда - программирование под win95, говорит что мол функции winapi с того времени не менялись, собственно он прав или нет?
Петцольд - классика. Это как Страуструп о C++, K&R о Си. Так и Петцольд о Win API.
Цитата Сообщение от Gepar Посмотреть сообщение
Так у нас же универ государственный следовательно апгрейд пк раз в 100 лет, хотя как по мне то vs 2005 там как-бы дышала ещё, ну да ладно.
Скажите спасибо, что не Borland C++ 3.1
Цитата Сообщение от Gepar Посмотреть сообщение
но мне почему-то запомнилось что препод говорил дефайном что меня и завело в ступор.
Одно из двух, либо ошибся преподаватель, либо Вы. Но однозначно то, что макросам здесь не место. Надо сделать с typedef, как сказал господин ForEveR.
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,512
12.10.2011, 10:18  [ТС]     Покритикуйте код #110
Цитата Сообщение от fasked Посмотреть сообщение
Скажите спасибо, что не Borland C++ 3.1
Первые пол года были с расчётом на него (половина курсовых были на граф. интерфейс, а интерфейс конечно же борландовский).

Цитата Сообщение от fasked Посмотреть сообщение
Одно из двух, либо ошибся преподаватель, либо Вы. Но однозначно то, что макросам здесь не место. Надо сделать с typedef, как сказал господин ForEveR.
Да, так и сделаю, исправлю только немного код для начала под нужды преподавателя (пара set и get методов и прочие мелочи) для начала.
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,512
15.10.2011, 18:10  [ТС]     Покритикуйте код #111
Очередная реинкарнация списка студентов Собственно в сей раз добавил set/get методов классу CStudent, вытащил итератор из списка, переименовал список в List, разбил CStudent на два файла (с одним .h не получалось - получал ошибку при линковке), добавил кое-где const, убрал свой класс-исключения (теперь в одном случае выбрасывается число - так захотел препод) и сделал итератор шаблонным и принимающим два параметра(если создавать через List то за счёт typedef параметры указывать не надо) ну и получилось что получилось. Собственно всё работает, но просьба просмотреть если у кого есть желание, и указать на места где можно что поправить.

Элементы списка
CStudent.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
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
#ifndef CSTUDENT_H
#define CSTUDENT_H
 
#include <iostream>
using std::ostream;
using std::istream;
 
#include <iomanip>
using std::setw;
using std::left;
 
#include <string>
using std::string;
 
class CStudent
{
    friend ostream &operator<<(ostream& os,const CStudent& stud);
    friend istream &operator>>(istream& is,CStudent& stud);
    void swap(CStudent &_v);
 
    //сравнивание на основании фамилии (sname)
    int cmp(const CStudent&, const CStudent&) const;
 
 
    string fname;
    string sname;
    string tname;
    string group;
    int year;
    float average;
 
 
public:
    CStudent(string ="",string ="",string ="",string ="",int =0,float =0);
    CStudent& operator=(const CStudent &_v);
 
    void setFname(string s){fname=s;}
    string getFname() const{return fname;}
    void setSname(string s){sname=s;}
    string getSname() const {return sname;}
    void setTname(string s){tname=s;}
    string getTname() const{return tname;}
    void setGroup(string g){group=g;}
    string getGroup() const{return group;}
    void setYear(int y){year=(y>=1950 && y<=2012 ? y : -1);}
    int getYear() const{return year;}
    void setAverage(float aver){average=(aver>=0 && aver<=100 ? aver : -1);}
    float getAverage() const{return average;}
 
 
    bool operator==(const CStudent &right) const;
    bool operator!=(const CStudent &right) const;
    bool operator>(const CStudent &right) const;
    bool operator>=(const CStudent &right) const;
    bool operator<(const CStudent &right) const;
    bool operator<=(const CStudent &right) const;
};
 
#endif


CStudent.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
#include "CStudent.h"
 
CStudent::CStudent(string f,string s,string t,string gr,int y,float aver)
{
    fname=f;
    sname=s;
    tname=t;
    group=gr;
    setAverage(aver);
    setYear(y);
}
 
void CStudent::swap(CStudent &_v)
{
    std::swap(fname,_v.fname);
    std::swap(sname,_v.sname);
    std::swap(tname,_v.tname);
    std::swap (group,_v.group);
    std::swap(year,_v.year);
    std::swap(average,_v.average);
}
 
int CStudent::cmp(const CStudent &s1, const CStudent &s2) const
{
    return (s1.fname.compare(s2.fname));
}
 
 
 
///////////////////////operator's/////////////////////////
 
CStudent& CStudent::operator=(const CStudent &_v)
{
    if(this != &_v)
     CStudent(_v).swap(*this);
    return *this;
}
 
bool CStudent::operator==(const CStudent &right) const
{
    return (cmp(*this,right)==0);
 
}
 
bool CStudent::operator!=(const CStudent &right) const
{
    return (cmp(*this,right)!=0);
 
}
 
bool CStudent::operator>(const CStudent &right) const
{
    return (cmp(*this,right)>0);
}
 
bool CStudent::operator>=(const CStudent &right) const
{
    return (cmp(*this,right)>=0);
}
 
bool CStudent::operator<(const CStudent &right) const
{
    return (cmp(*this,right)<0);
}
 
bool CStudent::operator<=(const CStudent &right) const
{
    return (cmp(*this,right)<=0);
}
 
ostream& operator<<(ostream& os,const CStudent& stud)
{
    os<<setw(8)<<left<<stud.fname
     <<setw(10)<<left<<stud.sname
     <<setw(12)<<left<<stud.tname
     <<setw(7)<<stud.group
     <<setw(5)<<stud.year
     <<setw(7)<<stud.average<<"\n";
 
     return os;
}
 
istream &operator>>(istream& is,CStudent& stud)
{
    int year, average;
    is>>stud.fname>>stud.sname>>stud.tname
     >>stud.group>>year>>average;
    if(is.fail())
     year=average=-1,is.clear();
 
    stud.setYear(year);
    stud.setAverage(average);
 
    return is;
}


Сам список
List.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
35
36
37
38
39
40
41
42
43
44
45
46
47
#ifndef LIST_H
#define LIST_H
#include "CStudent.h"
#include "ListIterator.h"
 
class List
{
    struct ListItem
    {
        CStudent data;
        ListItem *Next;
        ListItem(const CStudent& first,ListItem *next=0){data=first;Next=next;};
    };
 
    ListItem *Head;
    ListItem *Tail;
 
public:
    friend class ListIterator<ListItem, CStudent>;
 
    typedef ListIterator<ListItem, CStudent> iterator;
 
    List(): Head(0), Tail(0){}
    List(const CStudent& stud);
    ~List(){this->deleteAll();}
 
 
    void addToTail(const CStudent&);
    void addToHead(const CStudent&);
 
 
    bool deleteFromHead();
    bool deleteFromTail();
    void deleteAll();
 
    void sort();
    ListIterator<ListItem,CStudent> findElement(CStudent &what); //поиск по всему списку
    ListIterator<ListItem,CStudent> findElement(CStudent &what, ListIterator<ListItem,CStudent> begin, ListIterator<ListItem,CStudent> end);//поиск с границами
    bool findAndDestroy(const CStudent& stud);
 
 
    ListIterator<ListItem,CStudent> begin()const {return ListIterator<ListItem,CStudent>(Head);}
    ListIterator<ListItem,CStudent> end() const {return ListIterator<ListItem,CStudent>(0);}
};
 
 
#endif


List.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
165
166
167
168
169
170
171
172
173
174
175
176
#include "List.h"
 
List::List(const CStudent& stud)
{
    Head=Tail=new ListItem(stud, 0);
}
 
void List::addToTail(const CStudent& right)
{
    if (Tail)
    {
        Tail->Next=new ListItem(right,0);
        Tail=Tail->Next;
    }
    else
     Head=Tail=new ListItem(right,0);
}
 
 
void List::addToHead(const CStudent& right)
{
    if (Head)
    {
        ListItem* temp=Head;
        Head=new ListItem(right,temp);
        Head->Next=temp;
    }
    else
        Head=Tail=new ListItem(right,0);
}
 
bool List::deleteFromHead()
{
    if(!Head) //удалять нечего
     return false;
 
    ListItem *temp=Head;
    Head=Head->Next;
    if(Head=NULL)
     Tail=NULL;
    delete temp;
    return true;
}
 
bool List::deleteFromTail()
{
    if(!Tail)//удалять нечего
     return false;
 
    else if(Tail==Head)//только один элемент
    {
        delete Tail;
        Head=Tail=NULL;
        return true;
    }
    ListItem *temp=Head;
    while(temp->Next!=Tail)//найти новый хвост
     temp=temp->Next;
 
    ListItem *toDelete=Tail;
    Tail=temp;
    temp->Next=0;
    delete toDelete;
    return true;
}
 
 
void List::deleteAll() // освободить память
{
    ListItem* temp;
    while(Head)
    {
        temp=Head;
        Head=Head->Next;
        delete temp;
    }
    Tail=Head=NULL;
}
 
void List:: sort()
{
    ListItem* new_begin=NULL;
    ListItem* new_end=NULL;
    ListItem* sprev=NULL;
 
    for(ListItem *scur=this->Head;scur!=NULL;scur=this->Head)
    {
        ListItem *smin=NULL;
        ListItem *sminprev=scur;
        CStudent min_elem=scur->data;
        for(ListItem *gp=scur->Next;gp!=NULL;gp=gp->Next)
        {
            if((gp->data)<=min_elem)
            {
                min_elem=gp->data;
                smin=gp;
                sprev=sminprev;
            }
            sminprev=gp;
        }
        if(smin==NULL)
        {
            smin=scur;
        }
        else if(smin==scur->Next)
        {
            scur->Next=scur->Next->Next;
        }
        else
        {
            sprev->Next=smin->Next;
        }
        if(new_begin!=NULL)
        {
            new_end->Next=smin;
            new_end=smin;
        }
        else
        {
            new_begin=smin;
            new_end=smin;
        }
        if(smin==this->Head)
         this->Head=smin->Next;
    }
    this->Head=new_begin;
    this->Tail=new_end;
 
}
 
bool List::findAndDestroy(const CStudent& stud)
{
    if(!Head)
     return false;
 
    ListItem *temp=Head;
    if(temp->data==stud) //если это первый элемент
    {
        this->deleteFromHead();
        return true;
    }
 
    ListItem* beforeTemp=temp;
    temp=temp->Next;
 
    while(temp)
    {
        if((temp->data==stud))
        {
             beforeTemp->Next=temp->Next;
             delete temp;
             return true;
        }
 
        beforeTemp=temp;
        temp=temp->Next;
    }
 
    return false;//такого элемента нет в списке
}
 
ListIterator<List::ListItem,CStudent> List::findElement(CStudent &what, ListIterator<ListItem,CStudent> begin, ListIterator<ListItem,CStudent> end)
{
    for(;begin!=end;++begin)
    {
        if ((*begin)==what)
         return begin;
    }
    //если ничего не найдено - вернуть итератор указывающий за конец списка (на NULL)
    return ListIterator<ListItem,CStudent>(NULL);
}
 
ListIterator<List::ListItem,CStudent> List::findElement(CStudent &what)
{
    return (this->findElement(what,this->begin(),this->end()));
}


Итератор для списка
ListIterator.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
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
#ifndef LISTITERATOR_H
#define LISTITERATOR_H
 
 
template<typename T, typename E>
class ListIterator
{
    T* current;
    public:
 
    ListIterator() {current=0;}
    ListIterator(T *elem){current=elem;}
    ListIterator(const ListIterator& right){current=right.current;}
 
    ListIterator& operator=(const ListIterator& ref);
    ListIterator& operator++();
    ListIterator operator++(int);
    bool operator==(const ListIterator& right) const;
    bool operator!=(const ListIterator& right) const;
    E& operator*();
    operator bool(){return current!=0;}
};
 
 
 
 
 
 
 
template<typename T, typename E>
ListIterator<T,E>& ListIterator<T,E>::operator++()
{
    if(*this)
     current=current->Next;
     return *this;
}
 
template<typename T, typename E>
ListIterator<T,E> ListIterator<T,E>::operator++(int)
{
    if(!(*this))
     return NULL;
     ListIterator<T,E> temp(*this);
    current=current->Next;
     return temp;
}
 
template<typename T, typename E>
bool ListIterator<T,E>::operator==(const ListIterator& right) const
{
    return (current==right.current);
}
 
template<typename T, typename E>
bool ListIterator<T,E>::operator!=(const ListIterator& right) const
{
    return !(*this==right);
}
 
template<typename T, typename E>
ListIterator<T,E>& ListIterator<T,E>::operator=(const ListIterator<T,E>& ref)
{
    current=ref.current;
    return *this;
}
 
template<typename T, typename E>
E& ListIterator<T,E>::operator*()
{
    if(*this)
     return current->data;
    else
     throw -1;
}
 
#endif


Ну и собственно main
main.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
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
 
#include <windows.h>
#include "List.h"
 
 
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    CStudent i("Иван","Иванов","Иванович","КС-09",1990,100);
    CStudent p("Петр","Петров","Петрович","КС-09",1991,99);
    CStudent s("Василий","Васильев","Васильевич","КС-09",1990,100);
    CStudent y("Ярослав","Ярый","Ярославович","КС-09",1990,100);
    List test;
 
    test.addToTail(p);
    test.addToHead(i);
    test.addToHead(s);
    test.addToHead(y);
    test.findAndDestroy(i);
    List::iterator it=test.findElement(i);
    if(it)
     cout<<*it;
 
    cout<<"Введите нового студента(имя, фамилия, отчество, группа, год, балл):\n";
    CStudent stud;
    cin>>stud;
    cout<<"Созданный студент:\n";
    cout<<stud;
    cout<<"добавлен в тестовый список.\n\n";
 
    test.addToHead(stud);
    test.sort();
    cout<<"Полный список студентов:\n";
    it=test.begin();
    while(it)
     cout<<*it++;
 
}
Вложения
Тип файла: zip Students.zip (5.0 Кб, 8 просмотров)
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
15.10.2011, 23:52     Покритикуйте код #112
Цитата Сообщение от Gepar Посмотреть сообщение
if(Head=NULL)
- List.cpp - 39-я строка
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
16.10.2011, 00:09     Покритикуйте код #113
Цитата Сообщение от Gepar Посмотреть сообщение
ListIterator<ListItem,CStudent> findElement(CStudent &what); //поиск по всему списку ListIterator<ListItem,CStudent> findElement(CStudent &what, ListIterator<ListItem,CStudent> begin, ListIterator<ListItem,CStudent> end);//поиск с границами bool findAndDestroy(const CStudent& stud);
Мне кажется, лучше было бы сделать функцию iterator erase( iterator ), которая бы принимала итератор на элемент списка, который нужно удалить из списка, и в неё при надобности передавать результат findElement. В этом случае функция поиска была бы написана один раз и повторно использовалась везде, где нужен поиск элемента. При необходимости внесения изменений в процесс поиска вы бы просто изменили бы эту функцию.

class List у вас больше не шаблонный? Зря, очень зря.
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,512
16.10.2011, 14:05  [ТС]     Покритикуйте код #114
Цитата Сообщение от talis Посмотреть сообщение
class List у вас больше не шаблонный?
Нет, он шаблонный, я выложил обычную версию чтобы не запутывать, задание ведь сдать сначала обычную версию,а потом шаблонную показать. Шаблонная версия кстати теперь компилируется нормально и в vs 6.0 (пока итератор был внутри класса List(а в прошлом Students) vs 6.0 с линковкой не справлялась).

Цитата Сообщение от talis Посмотреть сообщение
Мне кажется, лучше было бы сделать функцию iterator erase( iterator ), которая бы принимала итератор на элемент списка, который нужно удалить из списка, и в неё при надобности передавать результат findElement.
Тоже неплохая идея, можно в принципе и такой вариант добавить, но функцию что принимает информационную часть и удаляет если найдёт такой элемент придётся оставить (пожелание преподавателя).

Добавлено через 3 минуты
Цитата Сообщение от Jupiter Посмотреть сообщение
- List.cpp - 39-я строка
Эээ, а что не так? Прокомментирую код
C++
1
2
3
4
5
6
7
8
9
10
11
12
bool List::deleteFromHead() //удаление элемента с головы списка
{
    if(!Head) //удалять нечего
     return false;//ничего не удалено
 
    ListItem *temp=Head; // сохранить указатель на память что нужно освободить
    Head=Head->Next; //сделать так чтобы голова указывала на след. элемент
    if(Head=NULL) //если голова стала NULL значит был только один элемент и теперь список пуст
     Tail=NULL; //поэтому сделаем и Tail= NULL
    delete temp;//освободим память
    return true;//удаление прошло успешно
}
Ну можно ещё писать
C++
1
if (!Head)
что сути не меняет.

Добавлено через 2 минуты
Ошибки кстати если и есть то вероятнее всего они могут быть в списке так как там все эти обращения через указатели, а так остальные классы типа итератора и элемента списка довольно простенькие.
talis
 Аватар для talis
789 / 541 / 37
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
16.10.2011, 14:14     Покритикуйте код #115
Цитата Сообщение от Gepar Посмотреть сообщение
но функцию что принимает информационную часть и удаляет если найдёт такой элемент придётся оставить (пожелание преподавателя).
А если внутри неё использовать findElement и erase? :-)
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
16.10.2011, 14:24     Покритикуйте код #116
Цитата Сообщение от Gepar Посмотреть сообщение
Эээ, а что не так?
C++
1
if(Head=NULL) //это присвоение, а не сравнение
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.10.2011, 16:01     Покритикуйте код
Еще ссылки по теме:

C++ Покритикуйте код
Покритикуйте мою игру C++
C++ Графы. Покритикуйте код

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

Или воспользуйтесь поиском по форуму:
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,512
16.10.2011, 16:01  [ТС]     Покритикуйте код #117
Jupiter, а, тьфу, тогда лучше было писать мне if(!Head) Странно что компилятор не выдал предупреждение, он ведь обычно меня предупреждал если в if идёт присваивание, а в этот раз не предупредил.

Добавлено через 3 минуты
talis, ну да, так тоже можно, но это ведь уже после создания такой функции можно, изначально делал как он попросил - без итератора просто поиск информационной части.
Yandex
Объявления
16.10.2011, 16:01     Покритикуйте код
Ответ Создать тему
Опции темы

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