Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.62/47: Рейтинг темы: голосов - 47, средняя оценка - 4.62
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517

Покритикуйте код

02.10.2011, 23:28. Показов 10448. Ответов 116
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть класс Студенты (реализован через односвязный список), хотел бы услышать критику по поводу его улучшения, если кому не лень разбираться в столь поздний час Сам код естественно полностью рабочий и предупреждений тоже компилятор не выдаёт (если не считать в 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++);
}
Комментариев только в коде совсем мало, но функции и переменные несут смысловую нагрузку так что надеюсь код не очень сложный в чтении получился.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
02.10.2011, 23:28
Ответы с готовыми решениями:

Покритикуйте код
Покритикуйте код, я точно знаю, что он нубовский но все же. Это моя первая программа на с++ которая делает , что то полезное и типо мой...

Графы. Покритикуйте код
Нужно помощь тех кто работает и пишет хороший и красивый код. У меня построено три матрицы, подскажите как улучшить код. Где можно...

Пожалуйста, покритикуйте код
Стиль, логика, реализация, все что угодно. Заранее благодарен за любые замечания или советы. Делал в VS 2015 Задача 1, вывод даты...

116
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
11.10.2011, 23:53  [ТС]
Студворк — интернет-сервис помощи студентам
Кстати, как Вы заметили у меня задание с односвязным списком, а ведь есть и на другие структуры у этого препода: лучше всего это на двумерный динамический массив где он хочет чтобы использовали realoc (и конструкторы же конечно не вызываются для новых элементов так как си-стиль), в общем у меня ещё задание ничего так.
0
 Аватар для talis
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
11.10.2011, 23:54
Правда, я не уверен на счёт компилябильности подобных извращений.

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

Не по теме:


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

0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
12.10.2011, 01:24
Gepar, Дико подозреваю что препод желает чтобы класс итератора был отдельно, а в самом классе Students(List) был typedef на этот итератор.

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

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

Так же замечу, что в реализации STL от gcc в том же списке _List_iterator<T>, _List_const_iterator не является nested типом, для мапы, для вектора олсо.
2
 Аватар для talis
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
12.10.2011, 01:45
Да, и правда. В 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 и других современных расширениях. Старые книги остаются лучшими только ввиду отсутствия хороших новых. Литература всегда должна быть современной.
1
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
12.10.2011, 09:21
Цитата Сообщение от Gepar Посмотреть сообщение
Я что-то не понял как это я дефайном его должен там влеплять
Может все таки typedef?
0
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
12.10.2011, 09:35  [ТС]
Цитата Сообщение от talis Посмотреть сообщение
Ничего лучше не знаю. Основы-то не изменились, добавились только всякие WCHAR'ы и прочие совремённости. А книжка сама по себе - отличная.
Хорошо, значит с него и начну.

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

Цитата Сообщение от fasked Посмотреть сообщение
Может все таки typedef?
Ну судя по логике нет, но мне почему-то запомнилось что препод говорил дефайном что меня и завело в ступор.
0
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
12.10.2011, 09:42
Цитата Сообщение от Gepar Посмотреть сообщение
Кстати там дальше интерфейсы идут так вот преподаватель советует читать Петзольда - программирование под win95, говорит что мол функции winapi с того времени не менялись, собственно он прав или нет?
Петцольд - классика. Это как Страуструп о C++, K&R о Си. Так и Петцольд о Win API.
Цитата Сообщение от Gepar Посмотреть сообщение
Так у нас же универ государственный следовательно апгрейд пк раз в 100 лет, хотя как по мне то vs 2005 там как-бы дышала ещё, ну да ладно.
Скажите спасибо, что не Borland C++ 3.1
Цитата Сообщение от Gepar Посмотреть сообщение
но мне почему-то запомнилось что препод говорил дефайном что меня и завело в ступор.
Одно из двух, либо ошибся преподаватель, либо Вы. Но однозначно то, что макросам здесь не место. Надо сделать с typedef, как сказал господин ForEveR.
1
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
12.10.2011, 10:18  [ТС]
Цитата Сообщение от fasked Посмотреть сообщение
Скажите спасибо, что не Borland C++ 3.1
Первые пол года были с расчётом на него (половина курсовых были на граф. интерфейс, а интерфейс конечно же борландовский).

Цитата Сообщение от fasked Посмотреть сообщение
Одно из двух, либо ошибся преподаватель, либо Вы. Но однозначно то, что макросам здесь не место. Надо сделать с typedef, как сказал господин ForEveR.
Да, так и сделаю, исправлю только немного код для начала под нужды преподавателя (пара set и get методов и прочие мелочи) для начала.
0
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
15.10.2011, 18:10  [ТС]
Очередная реинкарнация списка студентов Собственно в сей раз добавил 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 Кб, 9 просмотров)
0
Каратель
Эксперт С++
6610 / 4029 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
15.10.2011, 23:52
Цитата Сообщение от Gepar Посмотреть сообщение
if(Head=NULL)
- List.cpp - 39-я строка
1
 Аватар для talis
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
16.10.2011, 00:09
Цитата Сообщение от 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 у вас больше не шаблонный? Зря, очень зря.
0
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
16.10.2011, 14:05  [ТС]
Цитата Сообщение от 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 минуты
Ошибки кстати если и есть то вероятнее всего они могут быть в списке так как там все эти обращения через указатели, а так остальные классы типа итератора и элемента списка довольно простенькие.
0
 Аватар для talis
794 / 546 / 61
Регистрация: 11.05.2010
Сообщений: 1,298
Записей в блоге: 1
16.10.2011, 14:14
Цитата Сообщение от Gepar Посмотреть сообщение
но функцию что принимает информационную часть и удаляет если найдёт такой элемент придётся оставить (пожелание преподавателя).
А если внутри неё использовать findElement и erase? :-)
0
Каратель
Эксперт С++
6610 / 4029 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
16.10.2011, 14:24
Цитата Сообщение от Gepar Посмотреть сообщение
Эээ, а что не так?
C++
1
if(Head=NULL) //это присвоение, а не сравнение
1
 Аватар для Gepar
1186 / 543 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
16.10.2011, 16:01  [ТС]
Jupiter, а, тьфу, тогда лучше было писать мне if(!Head) Странно что компилятор не выдал предупреждение, он ведь обычно меня предупреждал если в if идёт присваивание, а в этот раз не предупредил.

Добавлено через 3 минуты
talis, ну да, так тоже можно, но это ведь уже после создания такой функции можно, изначально делал как он попросил - без итератора просто поиск информационной части.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
16.10.2011, 16:01

Покритикуйте код финкции нахождения интеграла
typedef double(*tfunc)(double); double integral(double start, end, func f, double dx) { double left, right, result; for (x=start,...

Покритикуйте и помогите улучшить код моей игры
Здравствуйте, недавно начал писать игру и собственно пишу потихоньку, но не в этом суть, просто я только сегодня понял, что мой код может...

Покритикуйте пожалуйста программу
Student.h#ifndef _STUDENT_H #define _STUDENT_H class Student { public: Student(); void del(); ...

Покритикуйте мою игру
Выкладываю код своей первой игры. Она готова процентов на 90, но уже работает. Интересно узнать мнение людей, что в ней можно улучшить,...

Шифратор пароля. Покритикуйте пожалуйста.
Это моя первая программка на С++, если кому не лень, натычте меня носом в ляпы. Чтобы не топтаться по граблям. :) #include...


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

Или воспользуйтесь поиском по форуму:
117
Ответ Создать тему
Новые блоги и статьи
Оказывается, Unreal Engine позволяет качество на порядки выше, чем было в Lineedge
Etyuhibosecyu 05.07.2026
Жаль, конечно, что я не узнал об этом, пока Lineedge существовала, а то бы Noname2331 написал, что волки превращаются в пиксельную кашу, а я бы его попросил скачать какую-нибудь бриллиантовую или Pro. . .
Doom для терминала без стрельбы и монстров. 3D Raycasting на ascii.
dcc0 05.07.2026
Попросил нейронную сеть deepai. org написать рейкастинг 3D с библиотекой ncurses для Linux. Чтобы можно было ходить на стрелочки. Чтобы стены были отрисованы символами. Справилась. Первый вариант. . .
Установка статуса документа по условию
Maks 05.07.2026
Алгоритм из решения ниже реализован на нетиповом документе "НарядПутевка" разработанного в КА2. Задача: в табличной части "Материалы" документа при записи автоматически устанавливать статус. . .
Сезонность и суточность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет. Но обычно это 50 лет и более. Наверное, закисление почвы происходит сезонно в средней. . .
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи. Через несколько переработок от PHP кода к C89 (надеюсь, 89). Но довольно запутанно получилось. Код для Linux. Но если убрать time и то, что с ним. . .
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru