Рефераты - Афоризмы - Словари
Русские, белорусские и английские сочинения
Русские и белорусские изложения

Программный модуль управления авиарейсами

Работа из раздела: «Программирование, компьютеры и кибернетика»

/

ВВЕДЕНИЕ

В качестве средств для написания программы были выбраны язык программирования C++/CLI и компилятор MicrosoftVisual C++ 2010.

Язык С++ является языком программирования общего назначения. Естественная для него область применения - системное программирование, понимаемое в широком смысле этого слова. Кроме того, С++ успешно используется во многих областях, далеко выходящих за указанные рамки. Реализации С++ теперь есть на всех машинах, начиная с самых скромных микрокомпьютеров - до самых больших супер-ЭВМ, и практически для всех операционных систем.

Язык С++ был задуман для того, чтобы настоящие программисты получили удовольствие от самого процесса программирования. За исключением второстепенных деталей он содержит язык С как подмножество. Язык С расширяется введением гибких и эффективных средств, предназначенных для построения новых типов. Программист структурирует свою задачу, определив новые типы, которые точно соответствуют понятиям предметной области задачи. Такой метод построения программы обычно называют абстракцией данных. Информация о типах содержится в некоторых объектах типов, определенных пользователем. С такими объектами можно работать надежно и просто даже в тех случаях, когда их тип нельзя установить на стадии трансляции. Программирование с использованием таких объектов обычно называют объектно-ориентированным. Если этот метод применяется правильно, то программы становятся короче и понятнее, а их сопровождение упрощается.

C++/CLI - привязка языка программирования С++ к среде программирования .NET фирмы Microsoft. Она интегрирует С++ стандарта ISO с Объединённой системой типов (UnifiedTypeSystem, UTS), рассматриваемой как часть Общей языковой инфраструктуры (CommonLanguageInfrastructure, CLI). Она поддерживает и исходный уровень, и функциональную совместимость исполняемых файлов, скомпилированных с родного и управляемого C++. C++/CLI представляет собой эволюцию С++. C++/CLI стандартизирован в ECMA как ECMA-372.

MicrosoftVisual C++ 2010 предоставляет мощную и гибкую среду разработки, позволяющую создавать приложения для MicrosoftWindows и приложения, основанные на Microsoft .NET. Эту среду можно использовать в качестве интегрированной среды разработки, так и в качестве отдельных средств.

1. ПОСТАНОВКА ЗАДАЧИ

Целью данной работы является реализация приложения для работы с базой данных авиарейсов. Ядром любой базы данных является модель данных. С помощью модели данных могут быть представлены объекты предметной области и взаимосвязи между ними. Существуют три основных типа моделей данных: иерархическая, сетевая и реляционная. В данной работе используется иерархическая модель, которая строится по принципу иерархии типов объектов, то есть один тип объекта является главным, а остальные, находящиеся на низших уровнях иерархии, - подчиненными. Например, для авиарейса подчинёнными являются дни, по которым он летает, а для дней - люди, забронировавшие места на данный день.

В программе реализуются:

возможность добавления, редактирования и удаления авиарейса;

возможность добавления, удаления и редактирования записи о бронировании места на определённый день, в который совершается рейс;

поиск авиарейсов по нескольким полям;

наглядный вывод информации на экран в виде таблиц;

отмена последних действий.

Кроме всего вышеперечисленного в программе реализованы дополнительные возможности. К ним относится автосохранение данных, возможность изменения размера буфера, хранящего совершенные действия над данными.

В данной работе для хранения информации используются бинарные файлы. Вся работа с данными производится в оперативной памяти, то есть чтение из файлов производится только при запуске программы, следовательно больших затрат по времени не будет, даже если файлы довольно большие. К тому же такой ход позволяет увеличить срок службы жесткого диска, т.к. он используется только в начале и в конце работы с программой. Объем, же, оперативной памяти на современных компьютерах позволяет вполне успешно оперировать с файлами такого размера.

2. СТРУКТУРА ВХОДНЫХ И ВЫХОДНЫХ ДАННЫХ

Внешние данные, используемые в программе, хранятся в трёх файлах.

flights.dat - файл с информацией об авиарейсах. Состоит из записей - полей класса flight:

int number //Номеррейса

char days[7]// Днинедели

char DeparturePoint[50]//Пунктотправления

char DestinationPoint[50] //Пунктназначения

charDepartureTime[10]//Времяотправления

intclassType[3]//Количествоместпоклассам

intprice[3]//Цена на места по классам

intreservNum;// Количество списков бронирования

days.dat - файл с информацией о занятых местах по дням, в которые совершаются рейсы. Состоит из записей - полей класса reservation:

intreserved[3]; // Количество занятых мест по классам

chardate[30]; // Дата

people.dat - файл со списком людей, которые забронировали места. Состоит из записей - полей класса person:

char name[50]; // Полноеимя

intplaceType; // Тип забронированного места

Для хранения и работы с авиарейсами в программе реализован контейнер list, а также итератор для него. Для работы со списком объектов классов reservationи personиспользуется STL-контейнер vector.

3. ОПИСАНИЕ КЛАССОВ

3.1 Классы управления данными

Шаблонный класс-контейнер list. Используется для хранения объектов различных типов.

template<class ListType>class list

{

element<ListType> *start, *last, *after_last; // Указатели на начало и конец списка

int number; // Количество элементов списка

public:

template<class ListType>friendclass l_iterator;// Дружественный класс-итератор

template<class ListType>friendclass element;// Дружественный класс-элемент

// списка

typedef l_iterator<ListType> iterator;

int size(); // Возвращает количество элементов списка

void push_back (const ListType &val);// Сохранение элемента в конец списка

void push_front (const ListType &val);// Сохранение элемента в начало списка

// Вставка перед элементом, на который ссылается итератор i

iterator insert (iterator i, const ListType &val);

// Удаляет элементы из диапазона [start;end]

iterator erase (iterator start, iterator end);

iterator erase (iterator del); // Удаляет элемент, на который ссылается итератор del

iterator begin(); // Возвращает итератор на начало списка

iterator end(); // Возвращает итератор на элемент за последним

void clear();

list();

~list();

};

Шаблонный класс-итератор l_iterator. Является итератором для класса-контейнера list.

template<class ListType>class l_iterator

{

template<class ListType>friendclass list;// Дружественный класс-контейнер

template<class ListType>friendclass element;// Дружественный класс-элемент списка

element<ListType> *cur; // Указатель на хранимый элемент

public:

operatorlonglong ();

ListType&operator*() const;// Доступ к элементу списка через итератор

l_iterator operator++(int x);// Переход к следующему элементу списка

l_iterator operator--(int x);// Переход к предыдущему элементу списка

l_iterator operator=(l_iterator &ptr);

l_iterator operator=(Object ^ ptr);

booloperator==(l_iterator &ptr) { return cur==ptr.cur ? 1: 0;}

booloperator!=(l_iterator &ptr) { return cur!=ptr.cur ? 1: 0;}

int getNumber(); // Номер элемента по итератору

};

Шаблонный класс element. Является элементом класса-контейнера list и служит для хранения одного объекта.

template<class ListType>class element

{

template<class ListType>friendclass list; // Дружественный класс-контейнер

template<class ListType>friendclass l_iterator; // Дружественный класс-итератор

element *prev, *next; // Указатели на предыдущий и

// следующий элементы

ListType *val; // Указатель на объект

public:

element();

~element();

};

Класс-контейнерlastActionsStack. Стек, содержащий объекты класса lastAction. Предназначен для реализации функции отмены последних действий.

template<class sType>refclass lastActionStack

{

lastAction<sType> ^top; // Вершина стека

int count;// Количество элементов в стеке

lastAction<sType> ^bottom; // Дно стека

public:

int Count();

lastActionStack();

~lastActionStack();

void push(int opType, int index, int dayIndex, DataGridViewRow^ Row, sType &savedObject);// Добавить в стек

returnElement^ pop();// Достать из стека

void reduce();// Удалить лишние элементы стека при превышении макс.

// количества

};

3.2 Классы данных

Класс flight - хранит данные об авиарейсах.

class flight

{

int number; // Номер рейса

char days[7]; // Дни недели

char DeparturePoint[50]; // Пункт отправления

char DestinationPoint[50]; // Пункт назначения

char DepartureTime[10]; // Время отправления

int classType[3]; // Количество по классам

int price[3]; // Цена на места по классам

int reservNum; // Количество списков бронирования для рейса

vector<reservation> reserv; // Списки забронированных местна разные даты

public:

~flight();

flight();

void restoreDays();// Пересборка дней

void reducePeopleLists();// Удаление забронированных мест на прошедшие даты

void fromFile(ifstream &in);// Прочитать из файлового потока

void toFile(ofstream &out);// Записать в файловый поток

// Get- и Set-методы

vector<reservation>& getReserv(); // Получить ссылку на списки

int getNumber();

int& СlassType(int i);

void setClassType(String^ cl1, String^ cl2, String^ cl3);

int& Price(int i);

void setPrice(String^ pr1, String^ pr2, String^ pr3);

int getReservNum();

void setReservNum(int n);

void setNumber(int n);

char& Day(int i);

String^ getDeparturePoint();

String^ getDestinationPoint();

String^ getDepartureTime();

void setDeparturePoint (String^ s);

voidsetDestinationPoint (String^ s);

void setDepartureTime (String^ s);

};

Класс reservation - хранит данные о занятых местах по дням, в которые совершаются рейсы.

class reservation

{

vector<person> people; // Список людей на данный рейс

int reserved[3]; // Количество занятых мест по классам

char date[30]; // Дата

public:

reservation();

~reservation();

// Get- и Set-методы

int& Reserved(int i);

String^ getDate();

void setDate (String^ s);

vector<person>& getPeople();

void fromFile(ifstream &in); // Прочитать из файлового потока

void toFile(ofstream &out); // Записать в файловый поток

};

Класс person - хранит данные человеке, забронировавшем место.

class person

{

char name[50]; // Полное имя

int placeType;

public:

person();

person(String^ s, char t);

// Get- и Set-методы

String^ getName();

int getPlaceType();

void setName(String^ s);

void setPlaceType (int t)

};

Статический класс data. Хранит объекты, используемые во всей программе в единственном экземпляре.

class data

{

public:

static list<flight> lst; // Список авиарейсов

static list<flight>::iterator iter; // Итератор для списка

static flight currentFlight;// Объект класса flight

staticint autosaveInterval;// Период автосохранения (мин)

staticvoid loadFromFile(); // Загрузить данные из файла

staticvoid saveToFile(); // Сохранить данные в файл

};

3.3 Классы исключений

Класс baseException - абстрактный базовый класс исключений.

class baseException

{

protected:

char* code; // Код ошибки

char* description; // описание ошибки

public:

baseException(char* code, char* description);

virtualvoid showException() = 0; // Сообщение об исключительной ситуации

virtual ~baseException();

};

Класс fileError. Используется при возникновении файловых ошибок.

class fileError: public baseException

{

public:

fileError(char* code, char* description): baseException(code, description);

void showException(); // Сообщение об исключительной ситуации

};

Класс fillException. Используется, еслинеправильно заполнены поля в некоторых формах.

class fillException: public baseException

{

public:

fillException(char* code, char* description): baseException(code, description);

void showException() // Сообщение об исключительной ситуации

};

3.4 Структура таблиц, используемых в программе

Таблица flightsView - список авиарейсов.

№ авиарейса.

Пункт отправления.

Пункт назначения.

Дни.

Время отправления.

(скрытый столбец) Итератор, указывающий на данный авиарейс в контейнере list.

Таблица reservedView - список забронированныхмест.

№ п/п.

Имя.

Тип места.

4. ОПИСАНИЕ АЛГОРИТМОВ РЕШЕНИЯ ЗАДАЧИ

Начало.

Объявление переменной idxтипа int для хранения значения количества строк в таблице flightsView.

Объявление объекта типа EditForm^.

Запуск диалогового окна EditForm.

Если результат диалога EditForm положительный, то переход к шагу 6,иначепереход к шагу 12.

Добавление пустой строки в таблицу flightsView.

Присвоение переменной idx значения количества строк в таблице flightsView.

Выполнение функции loadFromFlight(data::currentFlight,idx-1), которая загружает в последнюю строку таблицы, заполненные в диалоге поля об авиарейсе.

Выполнение функции data::lst.push_back(data::currentFlight), которая добавляет авиарейс в контейнер list.

Выполнение функции UndoStack->push() - добавления данного действия в стек последних действий.

Присвоение скрытой ячейке таблицы flightsView итератора на последний элемент списка list.

Конец.

ФункцияSystem::Void DeleteButton_Click(System::Object^ sender, System::EventArgs^ e) - удаление авиарейса

Начало.

Объявление переменной idxтипа int и присвоение ей номера текущей строки в таблице flightsView.

Присвоение статической переменной data::iter значения итератора, указывающего на элемент в контейнере list, соответствующий строке таблицы flightsView.

Выполнение функции UndoStack->push() - добавления данного действия в стек последних действий.

Выполнение функции data::lst.erase(data::iter), которая удаляет авиарейс из контейнера list.

Удаление строки из таблицы по её номеру idx.

Конец.

ЗАКЛЮЧЕНИЕ

В результате работы создана программа для управления авиарейсами,в которой реализованы функции добавления, удаления, изменения, поиска. Так же хочется отметить, что присутствует возможность отмены последнего действия, поэтому в случае удаления информации её можно вернуть без потерь.

Программный продукт выполнен в системе MicrosoftVisual C++ 2010 с использованиеминтерфейса программирования приложенийWindows Forms.

В качестве расширения можно реализовать более удобный интерфейс, сортировку по полям, улучшить качество поиска.

ЛИТЕРАТУРА

1. Шилдт Г. Полный справочник по С++. 4-е издание - Издательский дом «Вильямс», Москва, Санкт-Петербург, Киев, 2006 г.

2. Луцик Ю.А., Ковальчук А.М., Лукьянова И.А - Учебное пособие покурсу «Основы алгоритмизации и программирования» - БГУИР, Минск, 2007.

3. Лафоре Р., - «Объектно-ориентированное программирование вС++» - Издательство «Питер», Санкт-Петербург, 2011.

4. Библиотека MSDN[Электронный ресурс] /Microsoft Corp. - 2012 - Режим доступа: http://msdn.microsoft.com/ru-ru/library/, свободный. - Загл. с экрана.

ПРИЛОЖЕНИЕ А

Диаграмма классов

ПРИЛОЖЕНИЕ Б

Блок-схемы алгоритмов

управление данные таблица программа алгоритм

Функция System::VoidUndoButton_Click(System::Object^ sender, System::EventArgs^ e) - отмена последнего действия с рейсами

ПРИЛОЖЕНИЕ В

Скриншоты с результатами работы

ПРИЛОЖЕНИЕ Г

Листинг программы

MainForm.h

// Загрузка из объекта класса flight в строку таблицы

private: void loadFromFlight(flight &flt,int idx)

{

flightsView->Rows[idx]->Cells[0]->Value = flt.getNumber();

flightsView->Rows[idx]->Cells[1]->Value = flt.getDeparturePoint();

flightsView->Rows[idx]->Cells[2]->Value = flt.getDestinationPoint();

array<String^> ^days = gcnewarray<String^> {'пн','вт','ср','чт','пт','сб','вс'};

String^ s; int count=0;

for (int i=0; i<7; i++)

if(flt.Day(i)) { if(!s) s+=days[i]; else s+=', '+days[i]; count++;}

if(count==7) s='Ежедневно';

flightsView->Rows[idx]->Cells[3]->Value = s;

flightsView->Rows[idx]->Cells[4]->Value = flt.getDepartureTime();

}

// Установка состояний всех кнопок в зависимости от наличия строк в таблице

private: void setAllButtonsState()

{

if(!flightsView->RowCount)

{

DeleteButton->Enabled = false; toolStripDeleteButton->Enabled = false;

DeleteToolStripMenuItem->Enabled = false;

EditButton->Enabled = false; toolStripEditButton->Enabled = false;

EditToolStripMenuItem->Enabled = false;

InfoButton->Enabled = false; toolStripInfoButton->Enabled = false;

}

else

{

DeleteButton->Enabled = true; toolStripDeleteButton->Enabled = true;

DeleteToolStripMenuItem->Enabled = true;

EditButton->Enabled = true; toolStripEditButton->Enabled = true;

EditToolStripMenuItem->Enabled = true;

InfoButton->Enabled = true; toolStripInfoButton->Enabled = true;

}

}

// Поведение главной формы при запуске

private: System::Void MainForm_Load(System::Object^ sender, System::EventArgs^ e)

{

data::loadFromFile(); // Загрузка из файла

this->timer1->Interval = data::autosaveInterval; // Установка периода // автосохранения

data::iter = data::lst.begin();

for(int i=0; i<data::lst.size(); i++)

{

flightsView->Rows->Add();// Добавляем строку таблицы

// Добавляем итератор на последний элемент в скрытый столбец таблицы

flightsView->Rows[i]->Cells[5]->Value = (longlong) data::iter;

loadFromFlight(*data::iter,i); // Загружаем информацию в строку

data::iter++;

}

setAllButtonsState(); // Установка состояний всех кнопок в зависимости от

// наличия строк в таблице

}

// Кнопка 'Добавить' в меню

private: System::Void AddToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)

{

AddButton_Click(sender,e);

}

// Кнопка 'Изменить' в меню

private: System::Void EditToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)

{

EditButton_Click(sender,e);

}

// Кнопка 'Удалить' в меню

private: System::Void DeleteToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)

{

DeleteButton_Click(sender,e);

}

// Добавление рейса

private: System::Void AddButton_Click(System::Object^ sender, System::EventArgs^ e)

{

EditForm ^form = gcnew EditForm();

System::Windows::Forms::DialogResult dr;

dr=form->ShowDialog();

// Если результат диалога положителен, то новй рейс в data::currentFlight

if(dr==System::Windows::Forms::DialogResult::OK)

{

UndoButton->Enabled = true; UndoToolStripMenuItem->Enabled = true;

flightsView->Rows->Add();// Добавляем строку таблицы

int idx = flightsView->RowCount;// Количество строк

loadFromFlight(data::currentFlight,idx-1); // Загружаем строку в таблицу

data::lst.push_back(data::currentFlight); // Добавляем рейс в конец списка

// Добавление в стек отмены

StaticUndoStack::flightStack->push(1,data::lst.size()-1, -1,

flightsView->Rows[idx-1],data::currentFlight);

// Добавляем итератор на последний элемент в скрытый столбец таблицы

flightsView->Rows[idx-1]->Cells[5]->Value = (longlong) data::lst.end()--;

setAllButtonsState(); // Установка состояний всех кнопок в зависимости от

// наличия строк в таблице

}

}

// Изменение авиарейса

private: System::Void EditButton_Click(System::Object^ sender, System::EventArgs^ e)

{

int idx = flightsView->CurrentRow->Index;// Текущая строка

data::iter = flightsView->Rows[idx]->Cells[5]->Value; // Итератор на элемент,

// соотв. строке

data::currentFlight = *data::iter;

EditForm ^form = gcnew EditForm(true, flightsView->Rows[idx]);

System::Windows::Forms::DialogResult dr;

dr=form->ShowDialog();

if(dr==System::Windows::Forms::DialogResult::OK)// Если результат диалога OK

{

UndoButton->Enabled = true; UndoToolStripMenuItem->Enabled = true;

data::currentFlight.reducePeopleLists(); // Подправляем списки людейloadFromFlight(data::currentFlight,idx); // Загружаем строку в таблицу

*data::iter = data::currentFlight; // Присваиваем редактируемому элементу

// списка изменённую версию

}

}

//Удаление авиарейса

private: System::Void DeleteButton_Click(System::Object^ sender, System::EventArgs^ e)

{

UndoButton->Enabled = true; UndoToolStripMenuItem->Enabled = true;

int idx = flightsView->CurrentRow->Index; // Текущая строка

data::iter = flightsView->CurrentRow->Cells[5]->Value; // Итератор на элемент,

// соотв. строке

// Добавление в стек отмены

StaticUndoStack::flightStack->push(3,data::iter.getNumber(), -1,

flightsView->Rows[idx],*(data::iter));

data::lst.erase(data::iter); // Удаляем элемент из списка

flightsView->Rows->RemoveAt(idx); // Удаляем из таблицы

setAllButtonsState();// Установка состояний всех кнопок

// в зависимости от наличия строк в таблице

}

// Кнопка 'Информация об авирейсе и бронирование билетов'

private: System::Void InfoButton_Click(System::Object^ sender, System::EventArgs^ e)

{

data::iter = flightsView->CurrentRow->Cells[5]->Value; // Итератор на элемент,

// соотв. строке

ReservationForm ^f = gcnew ReservationForm();

f->ShowDialog();

}

// Кнопка 'Выход' в меню

private: System::Void выходToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)

{

this->Close();

}

// 'Сохранить' в меню

private: System:: Void сохранитьToolStripMenuItem_Click (System::Object^ sender, System::EventArgs^ e)

{

data::saveToFile();

}

// 'Добавить' в панели инструментов

private: System::Void toolStripAddButton_Click(System::Object^ sender, System::EventArgs^ e)

{

AddButton_Click(sender, e);

}

// Поиск

private: System::Void toolStripSearchButton_Click(System::Object^ sender, System::EventArgs^ e)

{

SearchForm^ f = gcnew SearchForm(flightsView);

f->ShowDialog();

}

// 'Удалить' в панели инструментов

private: System::Void toolStripDeleteButton_Click(System::Object^ sender, System::EventArgs^ e)

{

DeleteButton_Click(sender,e);

}

// 'Изменить' в панели инструментов

private: System::Void toolStripEditButton_Click(System::Object^ sender, System::EventArgs^ e)

{

EditButton_Click(sender,e);

}

// 'Бронирование билетов и информация об авиарейсе' в панели инструментов

private: System::Void toolStripInfoButton_Click(System::Object^ sender, System::EventArgs^ e)

{

InfoButton_Click(sender,e);

}

// Отмена последних действий

private: System::Void UndoButton_Click(System::Object^ sender, System::EventArgs^ e)

{

returnElement^ temp = StaticUndoStack::flightStack->pop();

if(temp->opType == 1) // Если отмена добавления

flightsView->Rows->RemoveAt(temp->index);

else// Если отмена удаления или изменения

{

if(temp->opType == 3) // Если отмена удаления

flightsView->Rows->Insert(temp->index,1); // Вставляем пустую строку

for(int i=0; i < temp->Row->Cells->Count; i++)

flightsView->Rows[temp->index]->Cells[i]->Value =

temp->Row->Cells[i]->Value; // Копируем содержимое строки

}

if (!StaticUndoStack::flightStack->Count()) { UndoButton->Enabled = false; UndoToolStripMenuItem->Enabled = false;}

setAllButtonsState(); // Установка состояний всех кнопок в зависимости от // наличия строк в таблице

}

// Действия при закрытии формы

private: System::Void MainForm_FormClosed(System::Object^ sender, System::Windows::Forms::FormClosedEventArgs^ e)

{

data::saveToFile();

}

// Кнопка отмены в меню

private: System::Void UndoToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)

{

UndoButton_Click(sender,e);

}

// Автосохранение

private: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e)

{

data::saveToFile();

}

// Кнопка 'О программе' в панели инструментов

private: System::Void toolStripAbout_Click(System::Object^ sender, System::EventArgs^ e)

{

About ^form = gcnew About;

form->ShowDialog();

}

// Кнопка 'О программе' в меню

private: System::Void AboutToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)

{

About ^form = gcnew About;

form->ShowDialog();

}

// Кнопка 'Настройки' в меню

private: System::Void SettingsToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)

{

Settings ^form = gcnew Settings(timer1);

form->ShowDialog();

}

ReservationForm.h

// Загрузка из списка забронированных мест в таблицу

private: void loadFromPeople()

{

reservedView->Rows->Clear(); // Очищаем таблицу

// Количество человек на данную дату

int size = (*data::iter).getReserv()[listBox1->SelectedIndex].getPeople().size();

if(!size)

{

DeleteButton->Enabled = false; EditButton->Enabled = false;

return;

}

else { DeleteButton->Enabled = true; EditButton->Enabled = true; }

for (int i=0; i<size; i++)

{

reservedView->Rows->Add();// Добавляем строку таблицы

reservedView->Rows[i]->Cells[0]->Value = i+1;// Номер с единицы

// Заполняем ячейки таблицы

reservedView->Rows[i]->Cells[1]->Value =(*data::iter).getReserv()

[listBox1->SelectedIndex].getPeople()[i].getName();

reservedView->Rows[i]->Cells[2]->Value = (*data::iter).getReserv()

[listBox1->SelectedIndex].getPeople()[i].getPlaceType() + ' класс';

}

}

// Установка состояния клавиши 'Добавить'

private: void setAddReservedButtonState()

{

if((comboBox1->SelectedIndex==0 && (*data::iter).getReserv()[listBox1->SelectedIndex].Reserved(0) >= (*data::iter).СlassType(0))

|| (comboBox1->SelectedIndex==1 && (*data::iter).getReserv()[listBox1->SelectedIndex].Reserved(1) >= (*data::iter).СlassType(1))

|| (comboBox1->SelectedIndex==2 && (*data::iter).getReserv()[listBox1->SelectedIndex].Reserved(2) >= (*data::iter).СlassType(2)))

{AddReservedButton->Enabled = false; }

else {AddReservedButton->Enabled = true; }

}

// Установка количества свободных мест на форме

private: void UpdateFreeLabels(int SelectedItem)

{

int free = (*data::iter).СlassType(0) -// Кол-во свободных мест

(*data::iter).getReserv()[SelectedItem].Reserved(0);

label17->Text = Convert::ToString(free);// Обновление на форме

free = (*data::iter).СlassType(1) -

(*data::iter).getReserv()[SelectedItem].Reserved(1);

label18->Text = Convert::ToString(free);

free = (*data::iter).СlassType(2) -

(*data::iter).getReserv()[SelectedItem].Reserved(2);

label19->Text = Convert::ToString(free);

}

// Поведение формы при загрузке

private: System::Void ReservationForm_Load(System::Object^ sender, System::EventArgs^ e)

{

(*data::iter).restoreDays(); // Добавляем/Удаляем необходимые дни

this->Text = 'Рейс № ' + (*data::iter).getNumber() + '. Информация и бронирование

мест';

for(int i=0; i<(*data::iter).getReserv().size(); i++)

listBox1->Items->Add((*data::iter).getReserv()[i].getDate());

// Заполнение на форме информации о местах

label4->Text = Convert::ToString((*data::iter).СlassType(0));

label9->Text = Convert::ToString((*data::iter).Price(0));

label10->Text = Convert::ToString((*data::iter).СlassType(1));

label11->Text = Convert::ToString((*data::iter).Price(1));

label12->Text = Convert::ToString((*data::iter).СlassType(2));

label13->Text = Convert::ToString((*data::iter).Price(2));

listBox1->SelectedIndex = 0;

comboBox1->SelectedIndex = 0;

}

// Добавление человека

private:System::Void AddReservedButton_Click(System::Object^sender,System::EventArgs^e)

{

try{

if(textBox1->Text=='') throw fillException('4','Введите имя!');

// Установка состояний конопок

EditButton->Enabled = true; DeleteButton->Enabled = true;

UndoButton->Enabled = true;

reservedView->Rows->Add();// Добавляем строку таблицы

int idx = reservedView->RowCount-1; // Индекс последней добавленной строки

// Установка номеров по порядку

if(idx == 0) reservedView->Rows[idx]->Cells[0]->Value = 1;

else reservedView->Rows[idx]->Cells[0]->Value =

((int) reservedView->Rows[idx-1]->Cells[0]->Value)+1;

// Заполнение строки таблицы значениями TextBox'ов

reservedView->Rows[idx]->Cells[1]->Value = textBox1->Text;

reservedView->Rows[idx]->Cells[2]->Value =

comboBox1->SelectedItem->ToString();

char classN = (char)comboBox1->SelectedIndex+1;//Выбранный тип места

// Добавление в вектор

(*data::iter).getReserv()[listBox1->SelectedIndex].

getPeople().push_back(person(textBox1->Text,classN));

(*data::iter).getReserv()[listBox1->SelectedIndex].

Reserved(comboBox1->SelectedIndex)++;

vector<person>::iterator itr =

(*data::iter).getReserv()[listBox1->SelectedIndex].getPeople().end() - 1;

// Добавление в стек отмены

StaticUndoStack::personStack->push (1, idx, listBox1->SelectedIndex,

reservedView->Rows[idx], *itr);

// Установка текущей строки

reservedView->CurrentCell = reservedView->Rows[idx]->Cells[0];

reservedView_SelectionChanged(sender,e);// Обработка изменения текущей

// строки

setAddReservedButtonState();// Состояние клавиши «Добавить»

UpdateFreeLabels(listBox1->SelectedIndex); // Обновляем количество

// свободных мест

} catch(baseException &e) {e.showException();}

}

// Изменение выделения даты

private: System::Void listBox1_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e)

{

UpdateFreeLabels(listBox1->SelectedIndex);// Обновление информации о

// свободных местах

loadFromPeople();// Загрузка списка в таблицу

setAddReservedButtonState();// Состояние клавиши «Добавить»

reservedView_SelectionChanged(sender,e);// Обработка изменения выделения

StaticUndoStack::personStack->~lastActionStack(); // Очистка стека

UndoButton->Enabled = false;// Отключение отмены

}

// Выделение новой строки в таблице

private: System::Void reservedView_SelectionChanged(System::Object^ sender, System::EventArgs^ e)

{

if(!reservedView->RowCount) return;// Если таблица пуста

elseif (Convert::ToString(reservedView->Rows[0]->Cells[1]->Value)=='') return;

int idx = reservedView->CurrentRow->Index; // Текущая строка

// Заполнение textBox'а и comboBox'а именем и типом места

textBox1->Text = Convert::ToString(reservedView->Rows[idx]->Cells[1]->Value);

int classN = Convert::ToString(reservedView->Rows[idx]->Cells[2]->Value)[0];

comboBox1->SelectedIndex = classN - 49;

}

// Удаление человека из списка

private: System::Void DeleteButton_Click(System::Object^ sender, System::EventArgs^ e)

{

int i = reservedView->CurrentRow->Index;

int prevType = (*data::iter).getReserv()[listBox1->SelectedIndex].

getPeople()[i].getPlaceType();

//i - номер удаляемого человека (если считать с 1)

i = Convert::ToInt32(reservedView->Rows[i]->Cells[0]->Value);

vector<person>::iterator itr = (*data::iter).// Итератор на удалемого человека

getReserv()[listBox1->SelectedIndex].getPeople().begin() + i-1;

// Добавление в стек отмены

StaticUndoStack::personStack->push (3, i-1, listBox1->SelectedIndex,

reservedView->CurrentRow, *(itr));

(*data::iter).getReserv()[listBox1->SelectedIndex].Reserved(prevType-1)--;

UpdateFreeLabels(listBox1->SelectedIndex); // Обновляем количество свободных мест

// Удаляем из таблицы и вектора

reservedView->Rows->RemoveAt(reservedView->CurrentRow->Index);

(*data::iter).getReserv()[listBox1->SelectedIndex].getPeople().erase(itr);

// Установка состояний кнопок в зависимости от наличия строк в таблице

if(!reservedView->RowCount)

{DeleteButton->Enabled = false; EditButton->Enabled = false;}

for (i=0; i<reservedView->RowCount; i++)

reservedView->Rows[i]->Cells[0]->Value = i+1;

setAddReservedButtonState();

UndoButton->Enabled = true;

}

// Изменение информации о человеке

private: System::Void EditButton_Click(System::Object^ sender, System::EventArgs^ e)

{

try{

if(textBox1->Text=='') throw fillException('4','Необходимо ввести имя пассажира!');// Если поле имени пусто

int idx = reservedView->CurrentRow->Index;// Номер текущей строки

int prevType = (*data::iter).getReserv()[listBox1->SelectedIndex].getPeople()[idx].getPlaceType();// Тип места до изменения

if((prevType-1)!=comboBox1->SelectedIndex) // Если не совпадают типы мест

{// до изменеия и после

(*data::iter).getReserv()[listBox1->SelectedIndex].

Reserved(prevType-1)--;

(*data::iter).getReserv()[listBox1->SelectedIndex].

Reserved(comboBox1->SelectedIndex)++;

}

else// Если содержимое полей не изменено, то выход из функции

if(Convert::ToString(reservedView->Rows[idx]->Cells[1]->Value) ==

textBox1->Text)

return;

// Итератор на начало вектора забронированных мест

vector<person>::iterator itr = (*data::iter).getReserv()

[listBox1->SelectedIndex].getPeople().begin();

// Добавление в стек отмены

StaticUndoStack::personStack->push (2, idx, listBox1->SelectedIndex, reservedView->Rows[idx], *(itr+idx));

// Изменение ячеек в таблице

reservedView->Rows[idx]->Cells[1]->Value = textBox1->Text;

reservedView->Rows[idx]->Cells[2]->Value = comboBox1->SelectedItem->ToString();

int classN = (int)comboBox1->SelectedIndex+1;// Тип выбранного места

// Изменение в элементе вектора

(*data::iter).getReserv()[listBox1->SelectedIndex].getPeople()[idx].setName(textBox1->Text);

(*data::iter).getReserv()[listBox1->SelectedIndex].getPeople()[idx].setPlaceType(classN);

UpdateFreeLabels(listBox1->SelectedIndex);// Установка свободных мест

// Установка состояний кнопок

setAddReservedButtonState();

UndoButton->Enabled = true;

} catch(baseException &e) { e.showException(); }

}

// Изменение типа места в выпадающем списке

private: System::Void comboBox1_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e)

{

// Если список забронированных мест не пуст

if((*data::iter).getReserv()[listBox1->SelectedIndex].getPeople().size())

{

//prevType - предыдущий тип места

int prevType = (*data::iter).getReserv()[listBox1->SelectedIndex].getPeople()[reservedView->CurrentRow->Index].getPlaceType();

// Если мест выбранного типа не осталось

if((*data::iter).getReserv()[listBox1->SelectedIndex].Reserved(comboBox1->SelectedIndex) == (*data::iter).СlassType(comboBox1->SelectedIndex))

comboBox1->SelectedIndex = prevType-1;// Устанавливаем предыдущий тип

}

setAddReservedButtonState();// Установка состояния кнопки «Добавить»

}

// Отмена последнего действия

private: System::Void UndoButton_Click(System::Object^ sender, System::EventArgs^ e)

{// Извлечение элемента из стека

returnElement^ temp = StaticUndoStack::personStack->pop();

if(temp->opType == 1) // Если отмена добавления

reservedView->Rows->RemoveAt(temp->index);

else// Если отмена удаления или изменения

{

if(temp->opType == 3) // Если отмена удаления

{// Вставляем пустую строку

reservedView->Rows->Insert(temp->index,1);

for (int i=0; i<reservedView->RowCount; i++) // Перенумеровка

reservedView->Rows[i]->Cells[0]->Value = i+1;

}

else// Если отмена изменения

{

int prevType = Convert::ToString(reservedView->Rows[temp->index]->Cells[2]->Value)[0] - 49;

int newType = Convert::ToString(temp->Row->Cells[2]->Value)[0] - 49;

if(prevType!=newType)// Если прердыдущий тип места не равен новому

{

(*data::iter).getReserv()[listBox1->SelectedIndex].Reserved(prevType)--;

(*data::iter).getReserv()[listBox1->SelectedIndex].Reserved(newType)++;

}

}

for(int i=0; i < temp->Row->Cells->Count; i++)

reservedView->Rows[temp->index]->Cells[i]->Value = temp->Row->Cells[i]->Value; // Копируем содержимое строки

}

setAddReservedButtonState();// Установка состояния кнопки «Добавить»

UpdateFreeLabels(listBox1->SelectedIndex); // Обновляем количество свободных мест

// Установка состояний кнопок «Отменить» и «Удалить»

if (!StaticUndoStack::personStack->Count())

UndoButton->Enabled = false;

if(!reservedView->RowCount)

{ DeleteButton->Enabled = false; EditButton->Enabled = false; }

else { DeleteButton->Enabled = true; EditButton->Enabled = true; }

}

// Отмена через Ctrl+Z

private: System::Void ReservationForm_KeyDown(System::Object^ sender, System::Windows::Forms::KeyEventArgs^ e)

{

e->Handled = true;

if(e->KeyData==(Keys::Control | Keys::Z) && StaticUndoStack:: personStack->Count())

UndoButton_Click(sender,e);

}

SearchForm.h

// Поиск

private: System::Void FindButton_Click(System::Object^ sender, System::EventArgs^ e)

{

char flag;

foundFlightsView->Rows->Clear();// Очищаем таблицу

if(textBox1->Text==''&& textBox2->Text==''&& textBox3->Text==''&& !checkedListBox1->CheckedItems->Count)// Если условия поиска не заданы

return;

for(int i=0; i<dataGridMain->RowCount; i++)

{

flag=0;

if((textBox1->Text=='' || Convert::ToInt32(dataGridMain->Rows[i]->Cells[0]->Value) == Convert::ToInt32(textBox1->Text)) && ((Convert::ToString(dataGridMain->Rows[i]->Cells[1]->Value) == textBox2->Text) || textBox2->Text=='') && ((Convert::ToString(dataGridMain->Rows[i]->Cells[2]->Value) == textBox3->Text)|| textBox3->Text==''))// Если заполнено хотя бы одно из полей и элемент найден

{

for(int j=0; j<checkedListBox1->Items->Count; j++)

{// Итератор на элемент, соотв. строке

data::iter = dataGridMain->Rows[i]->Cells[5]->Value;// Если рейс не летает по выбранным дням

if(checkedListBox1->GetItemCheckState(j) == CheckState::Checked && !(*data::iter).Day(j))

{ flag = 1; break; } // Флаг несовпадения дней

}

// Если дни не выбраны или выбранные дни совпадают

if(!checkedListBox1->CheckedItems->Count || flag==0)

{

array<Object^> ^rowData = gcnewarray<Object^>(dataGridMain->Rows[i]->Cells->Count);// Копируем строку из основной таблицы

for (int j=0; j<rowData->Length; j++)rowData[j] = dataGridMain->Rows[i]->Cells[j]->Value;

foundFlightsView->Rows->Add(rowData);// Добавляем строку

}

}

}

}

// Контроль на ввод только цифр в номер рейса

private: System::Void textBox1_KeyPress(System::Object^ sender, System::Windows::Forms::KeyPressEventArgs^ e)

{

if (e->KeyChar >= '0'&& e->KeyChar <= '9' || e->KeyChar==8)

e->Handled = false;

else e->Handled = true;

}

// Двойной щелчок на строке таблицы

private: System::Void foundFlightsView_CellDoubleClick(System::Object^ sender, System::Windows::Forms::DataGridViewCellEventArgs^ e)

{

data::iter = foundFlightsView->CurrentRow->Cells[5]->Value; // Итератор на // элемент, соотв. строке

ReservationForm ^f = gcnew ReservationForm();

f->ShowDialog();

}

Settings.h

// Нажатие кнопки «Отмена»

private: System::Void CancelButton_Click(System::Object^ sender, System::EventArgs^ e)

{

this->Close();

}

// Нажатие кнопки «OK»

private: System::Void OkButton_Click(System::Object^ sender, System::EventArgs^ e)

{

// Изменение максимального количества отменяемых действий

StaticUndoStack::MaxActionsNum = (int)numericUpDown1->Value;

StaticUndoStack::flightStack->reduce(); // Изменение размера стека при // необходимости

timer1->Interval = (int)numericUpDown2->Value*60000; // Изменяем интервал таймера

// в главной форме

data::autosaveInterval = (int) timer1->Interval;// Период автосохранения

this->Close();

}

// Загрузка формы «Настройки»

private: System::Void Settings_Load(System::Object^ sender, System::EventArgs^ e)

{

numericUpDown1->Value = StaticUndoStack::MaxActionsNum;// Максимальное количество

// отменяемых действий

numericUpDown2->Value = timer1->Interval/60000;// Период автосохранения

}

EditForm.h

// Загрузка формы добавления/редактирования

private: System::Void EditForm_Load(System::Object^ sender, System::EventArgs^ e)

{

// Если в вызывающей форме нажата кнопка 'Изменить', а не добавить

if(editingMode)

{

// Заполняем TextBox'ы

textBox1->Text = Convert::ToString(data::currentFlight.getNumber());

textBox2->Text = data::currentFlight.getDeparturePoint();

textBox3->Text = data::currentFlight.getDestinationPoint();

textBox4->Text = Convert::ToString(data::currentFlight.СlassType(0));

textBox5->Text = Convert::ToString(data::currentFlight.Price(0));

textBox6->Text = Convert::ToString(data::currentFlight.СlassType(1));

textBox7->Text = Convert::ToString(data::currentFlight.Price(1));

textBox8->Text = Convert::ToString(data::currentFlight.СlassType(2));

textBox9->Text = Convert::ToString(data::currentFlight.Price(2));

// Устанавливаем дни недели

for(int i=0; i<checkedListBox1->Items->Count; i++)

checkedListBox1->SetItemCheckState(i,(CheckState)data::currentFlight.Day(i));

// Устанавливаем время отправления

dateTimePicker1->Value =

DateTime::Parse(data::currentFlight.getDepartureTime());

}

}

// Проверка ввода только цифр в TextBox'ы

private: void numberOnlyControl(System::Windows::Forms::KeyPressEventArgs^ e)

{

if (e->KeyChar >= '0'&& e->KeyChar <= '9' || e->KeyChar==8)

e->Handled = false;

else e->Handled = true;

}

// Проверка на дубликаты рейсов

private: bool checkCopy(int number)

{

list<flight>::iterator iterator;

for(iterator = data::lst.begin(); iterator!=data::lst.end(); iterator++)

{// Если указан уже существующий рейс

if((number==(*iterator).getNumber() && !editingMode) || (number==(*iterator).getNumber() && (*data::iter).getNumber()!=number && editingMode))

returntrue;

}

returnfalse;

}

// Нажатие ОК

private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)

{

try{

if(editingMode) // Если режим редактирования

StaticUndoStack::flightStack->push(2,data::iter.getNumber(),-1,Row,data::currentFlight);// Добавляем в стек отмены

for(int i=1; i<10; i++)// Проверяем заполненность textBox'ов

{

TextBox^ t = (TextBox^)this->Controls['textBox'+i.ToString()];

if(t->Text=='') throw fillException('2','Необходимо заполнить все поля!');

}

// Если рейс уже существует и/или не выбраны дни

if(checkCopy(Convert::ToInt32(textBox1->Text))) throw fillException('4','Данный рейс уже существует');

if(checkedListBox1->CheckedItems->Count==0) throw fillException('3','Выберите дни, по которым совершается рейс!');// Добавляем в текущий рейс информацию из полей формы

data::currentFlight.setNumber(Convert::ToInt32(textBox1->Text));

data::currentFlight.setDeparturePoint(textBox2->Text);

data::currentFlight.setDestinationPoint(textBox3->Text);

data::currentFlight.setClassType(textBox4->Text, textBox6->Text, textBox8->Text);

data::currentFlight.setPrice(textBox5->Text, textBox7->Text, textBox9->Text);

// Копируем время отправления

data::currentFlight.setDepartureTime(dateTimePicker1->Value.ToShortTimeString());

// Устанавливаем выбранные дни недели

for(int i=0; i<checkedListBox1->Items->Count; i++)

{

if((int)checkedListBox1->GetItemCheckState(i))

data::currentFlight.Day(i)=1;

else data::currentFlight.Day(i)=0;

}

this->DialogResult=System::Windows::Forms::DialogResult::OK;

this->Close();

}

catch(baseException &e)

{ e.showException();}

}

myList.h

template<class ListType>class list;

template<class ListType>class element;

template<class ListType>class l_iterator;

// Шаблон класса 'Список'

template<class ListType>class list

{

element<ListType> *start, *last, *after_last; // Указатели на начало и конец списка

int number;// Количество элементов списка

public:

template<class ListType>friendclass l_iterator;

template<class ListType>friendclass element;

typedef l_iterator<ListType> iterator;

int size() { return number; }// Возвращает количество элементов списка

void push_back (const ListType &val); // Сохранение элемента в конец списка

void push_front (const ListType &val); // Сохранение элемента в начало списка

iterator insert (iterator i, const ListType &val); // Вставка перед элементом, на

// который ссылается итератор i

iterator erase (iterator start, iterator end); // Удаляет элементы из диапазона

// [start;end]

iterator erase (iterator del);// Удаляет элемент, на который

// ссылается итератор del

iterator begin() // Возвращает итератор на начало

// списка

{iterator p;

if(start) p.cur=start;

else p.cur = after_last;

return p;

}

iterator end() {iterator p; p.cur=after_last; return p;} // Возвращает итератор на

// элемент списка, следующий за последним

void clear()

{while(start) {last=start->next; delete[] start; start=last;}

start=last=0; number=0;

after_last=new element<ListType>[1];

after_last->next=0;

}

list() { start=0; last=0; number=0;

after_last=new element<ListType>[1];

after_last->next=0;} // Инициализируем список

// Удаляем весь список

~list() {while(start) { last=start->next; delete[] start; start=last;} }

};

// Шаблон элемента списка

template<class ListType>class element

{

template<class ListType>friendclass list;

template<class ListType>friendclass l_iterator;

element *prev, *next;

ListType *val;

public:

element() {val=new ListType;}

~element() {delete val;}

};

// Шаблон итератора списка

template<class ListType>class l_iterator

{

template<class ListType>friendclass list;

template<class ListType>friendclass element;

element<ListType> *cur;

public:

operatorlonglong () {returnreinterpret_cast<longlong>(cur);}

ListType&operator*() const { return *cur->val; } // Доступ к элементу списка

// через итератор

l_iterator operator++(int x){ cur==0 ? cur: cur=cur->next; return *this; }

l_iterator operator--(int x) { cur==0 ? cur: cur=cur->prev; return *this; }

l_iterator operator=(l_iterator &ptr) { cur=ptr.cur; return *this;}

l_iterator operator=(Object ^ ptr) { longlong tmp = Convert::ToInt64(ptr);cur=reinterpret_cast<element<ListType> *>(tmp); return *this;}

booloperator==(l_iterator &ptr) { return cur==ptr.cur ? 1: 0;}

booloperator!=(l_iterator &ptr) { return cur!=ptr.cur ? 1: 0;}

int getNumber()

{

int num = 0;

element<ListType> *temp = cur;

while (temp->prev!=0)

{

temp = temp->prev;

num++;

}

return num;

}

};

// Вставка элемента в конец списка

template<class ListType>

void list<ListType>::push_back(const ListType &val)

{

if(!last) // Если список пуст

{

last = new element<ListType>[1]; // Создаём новый элемент списка

start=last;

start->prev=0;

}

else

{

last->next= new element<ListType>[1]; // Создаём новый элемент списка

// Связываем элемент с остальными

last->next->prev=last;

last=last->next;

}

last->next=after_last;

after_last->prev=last;

*last->val=val; // Заполняем элемент

number++;// Увеличиваем счётчик элементов списка

}

// Вставка элемента в начало списка

template<class ListType>

void list<ListType>::push_front(const ListType &val)

{

if(!start) // Если список пуст

{

last = new element<ListType>[1]; // Создаём новый элемент списка

start=last;

// Связываем элемент с остальными

last->next=after_last;

after_last->prev=last;

}

else

{

start->prev= new element<ListType>[1]; // Создаём новый элемент списка

// Связываем элемент с остальными

start->prev->next=start;

start=start->prev;

}

start->prev=0;

*start->val=val; // Заполняем элемент

number++;// Увеличиваем счётчик элементов списка

}

// Вставка элемента перед элементом, на который указывает iterator i

template<class ListType>

l_iterator<ListType> list<ListType>::insert(iterator i, const ListType &val)

{

if(!i.cur) return i;

element<ListType> *n;

if(i.cur==after_last && !start) // Если список пуст

{

last = new element<ListType>[1]; // Создаём новый элемент списка

start=last;

// Связываем элемент с остальными

last->next=after_last;

after_last->prev=last;

start->prev=0;

}

else

{

if(i.cur==after_last) // Если итератор указывает на элемент после

// последнего

{

last->next= new element<ListType>[1]; // Создаём новый элемент списка

// Связываем элемент с остальными

last->next->prev=last;

last=last->next;

last->next=after_last;

after_last->prev=last;

}

else

{

n = new element<ListType>[1];

// Связываем элемент с остальными

n->next=i.cur;

n->prev=i.cur->prev;

i.cur->prev=n;

if(n->prev) n->prev->next=n;

else start = n;

}

}

*i.cur->prev->val=val; // Заполняем элемент

number++;// Увеличиваем счётчик элементов списка

iterator temp;

temp.cur=i.cur->prev;

return temp;

}

// Удаление элементов в диапазоне [start,end]

template<class ListType>

l_iterator<ListType> list<ListType>::erase(iterator start, iterator end)

{

if(!start.cur) return end;

if(!end.cur) return start;

element<ListType> *temp,

*t_end,// Элемент после удаляемой последовательности

*t_start=start.cur->prev; // Элемент перед удаляемой последовательностью

end.cur==after_last ? t_end=after_last: t_end=end.cur->next;

while(start.cur!=t_end)// Удаление элементов в диапазоне

{

temp = start.cur->next;

delete[] start.cur;

start.cur = temp;

number--;

}

if(!t_start && t_end==after_last) // Если границы - начало и конец списка

list<ListType>::start=last=0;

else

{

if(!t_start)// Если первая граница - начало списка

{

list<ListType>::start=t_end;

list<ListType>::start->prev=0;

}

if(t_end==after_last)// Если вторая граница - конец списка

{

last=t_start;

last->next=after_last;

}

}

iterator tmp;

tmp.cur=t_end;

return tmp;

}

// Удаление элемента, на который указывает итератор del

template<class ListType>

l_iterator<ListType> list<ListType>::erase(iterator del)

{

element<ListType> *temp;

if(!start) return del;

if (del.cur == after_last) return del;// Если удаляемый элемент после последнего

if(del.cur == start && number==1)// Если удаляемый элемент в начале списка и единственный

{

delete[] del.cur;

start = 0; last = 0;

after_last->prev = 0;

}

else

{

if(del.cur == start)// Если удаляемый элемент в начале списка

{

start = del.cur->next;

delete[] del.cur;

start->prev = 0;

temp = start;

}

elseif (del.cur == last)// Если удаляемый элемент в конце списка

{

last = del.cur->prev;

delete[] del.cur;

last->next = after_last;

temp = last;

}

else// В общем случае

{

temp = del.cur->next;

del.cur->next->prev = del.cur->prev;

del.cur->prev->next = del.cur->next;

delete[] del.cur;

}

}

number--;

iterator tmp;

tmp.cur = temp;

return tmp;

}

Exception.h

class baseException

{

protected:

char* code; // Код ошибки

char* description; // Описание ошибки

public:

baseException(char* code, char* description)

{

this->code = newchar[strlen(code)+1]; strcpy(this->code, code);

this->description = newchar[strlen(description)+1];

strcpy(this->description, description);

}

virtualvoid showException() = 0; // Сообщение об исключительной ситуации

virtual ~baseException() {delete code; delete description;}

};

// Ошибки при работе с файлами

class fileError: public baseException

{

public:

fileError(char* code, char* description): baseException(code, description) {}

void showException() // Сообщение об исключительной ситуации

{ MessageBox::Show(gcnew String(description), 'Файловая ошибка. Код ' + gcnew String(code), MessageBoxButtons::OK, MessageBoxIcon::Error); }

};

// Ошибки при заполнении полей в формах

class fillException: public baseException

{

public:

fillException(char* code, char* description): baseException(code, description) {}

void showException() // Сообщение об исключительной ситуации

{ MessageBox::Show(gcnew String(description),'Ошибка заполнения. Код ' + gcnew String(code),MessageBoxButtons::OK, MessageBoxIcon::Warning);}

};

Undo.h

template<class sType>refclass lastAction;

template<class sType>refclass lastActionStack;

refclass returnElement;

refclass StaticUndoStack;

// Описание последнего действия

template<class sType>refclass lastAction

{

public:

int opType;// Тип операции (1 - добавление, 2- изменение, 3 - удаление)

int index;// Индекс в списке

int dayIndex;// Индекс выбранного дня

DataGridViewRow^ Row; // Строка из таблицы (для отмены удаления и изменения)

lastAction^ prev;// Ссылка на предыдущее действие

lastAction^ next;// Ссылка на следующее действие

sType *savedObject;// Сохранённый рейс

lastAction(int opType, int index, int dayIndex, DataGridViewRow^ Row, sType &savedObject);

~lastAction() {delete savedObject;}

};

// Стек последних действий

template<class sType>refclass lastActionStack

{

lastAction<sType> ^top; // Вершина стека

int count;// Количество элементов в стеке

lastAction<sType> ^bottom; // Дно стека

public:

int Count() {return count;}

lastActionStack() { count=0; }

~lastActionStack()

{ while(count)

{ if(count!=1) { top=top->prev; delete top->next; }

elsedelete top;

count--;

}

}

void push(int opType, int index, int dayIndex, DataGridViewRow^ Row, sType &savedObject);

returnElement^ pop();

void reduce();// Удалить лишние элементы стека при превышении макс. количества

};

// Элемент, возвращаемый стеком при отмене последнего действия

refclass returnElement

{

public:

returnElement(int opType, int index, int dayIndex, DataGridViewRow^ Row)

{

this->opType = opType;

this->Row = Row;

this->index = index;

this->dayIndex = dayIndex;

}

int opType;

int index;

int dayIndex;

DataGridViewRow^ Row;

};

// Класс со стеком последних действий

refclass StaticUndoStack

{

public:

static lastActionStack<flight>^ flightStack = gcnew lastActionStack<flight>;

static lastActionStack<person>^ personStack = gcnew lastActionStack<person>;

staticint MaxActionsNum = 1;

};

// Конструктор для последнего действия

template<class sType>

lastAction<sType>::lastAction(int opType, int index, int dayIndex, DataGridViewRow^ Row, sType &savedObject)

{

if(opType!=1) // Если удаление или изменение

{

this->Row =(DataGridViewRow^) Row->Clone(); // Копируем строку

for(int i=0;i<Row->Cells->Count;i++)

this->Row->Cells[i]->Value = Row->Cells[i]->Value;

}

this->opType = opType; this->index = index; this->dayIndex = dayIndex;

this->savedObject = new sType(savedObject);

}

// Добавление в стек последнего действия

template<class sType>

void lastActionStack<sType>::push(int opType, int index, int dayIndex, DataGridViewRow^ Row, sType &savedObject)

{

if(count == StaticUndoStack::MaxActionsNum) // если достигнуто макс. количество

{

if(count==1) delete bottom;

else

{

bottom = bottom->next; // Обновляем дно стека

delete bottom->prev;

}

count--;

}

lastAction<sType>^ New = gcnew lastAction<sType>(opType, index, dayIndex, Row, savedObject);

if(count!=0)

{

New->prev = top;// Обновляем ссылку на предыдущий элемент

New->prev->next = New; // Обновляем ссылку на следующий элемент

// предыдущего

}

else bottom = New;// Запоминаем дно стека

top = New;// Обновляем вершину стека

count++;

}

// Извлечение рейса из стека последнего действия

template<>inline

returnElement^ lastActionStack<flight>::pop()

{

DataGridViewRow^ bufRow;

returnElement^ buf;

if(!top) return buf;

list<flight>::iterator l_iter = data::lst.begin(); // Итератор в списке авиарейсов

for(int i=0; i<top->index; i++)

l_iter++; // Устанавливаем итератор на требуемый индекс

if(top->opType == 1) // Отмена добавления

data::lst.erase(l_iter); // Удаляем добавленный рейс в списке lst

else// Отмена удаления или изменения

{

bufRow = (DataGridViewRow^)top->Row->Clone();// Копия строки

for(int i=0; i < top->Row->Cells->Count; i++)

// Копируем содержимое строки

bufRow->Cells[i]->Value = top->Row->Cells[i]->Value;

if(top->opType == 3) // Отмена удаления

// Вставляем сохранённый рейс в списке lst

l_iter = data::lst.insert(l_iter, *(top->savedObject));

else// Если отмена изменения

*l_iter = *(top->savedObject); // Восстанавливаем объект в списке lst

// Обновляем итератор в скрытом столбце

bufRow->Cells[5]->Value = (longlong) l_iter;

}

// Элемент для возврата

buf = gcnew returnElement(top->opType, top->index, top->dayIndex, bufRow);

lastAction<flight>^ old;

old = top;

top = top->prev; // Изменение вершины стека

delete old;// Удаление старой вершины

count--;// Уменьшение количества элементов в стеке

return buf;

}

// Извлечение забронированного места из стека последнего действия

template<>inline

returnElement^ lastActionStack<person>::pop()

{

DataGridViewRow^ bufRow;

returnElement^ buf;

if(!top) return buf;

int placeType = top->savedObject->getPlaceType() - 1;// Тип забронированного места

vector<person>::iterator v_iter = (*data::iter).getReserv()[top->dayIndex].getPeople().begin() + top->index;

if(top->opType == 1) // Отмена добавления

{

(*data::iter).getReserv()[top->dayIndex].getPeople().erase(v_iter);

(*data::iter).getReserv()[top->dayIndex].Reserved(placeType)--;

}

else// Отмена удаления или изменения

{

bufRow = (DataGridViewRow^)top->Row->Clone();// Копия строки

for(int i=0; i < top->Row->Cells->Count; i++)

// Копируем содержимое строки

bufRow->Cells[i]->Value = top->Row->Cells[i]->Value;

if(top->opType == 3) // Отмена удаления

{

v_iter = (*data::iter).getReserv()[top->dayIndex].getPeople().insert(v_iter, *(top->savedObject)); // Вставляем сохранённую

// запись

(*data::iter).getReserv()[top->dayIndex].Reserved(placeType)++;

}

else// Если отмена изменения

*v_iter = *(top->savedObject); // Восстанавливаем объект в векторе

// reserv

}

// Элемент для возврата

buf = gcnew returnElement(top->opType, top->index, top->dayIndex, bufRow);

lastAction<person>^ old;

old = top;

top = top->prev; // Изменение вершины стека

delete old;// Удаление старой вершины

count--;// Уменьшение количества элементов в стеке

return buf;

}

// Удалить лишние элементы стека при превышении макс. количества

template<class sType>

void lastActionStack<sType>::reduce()

{

int dif = count - StaticUndoStack::MaxActionsNum;

if(dif > 0)

{

for(int i=0; i<dif; i++)

{

bottom = bottom->next; // Обновляем дно стека

delete bottom->prev; count--; // Удаляем элемент со дна стека,

}

}

}

data.h

class person;

class reservation;

class flight;

class data;

// Рейс

class flight

{

int number;// Номер рейса

char days[7];// Дни недели

char DeparturePoint[50]; // Пункт отправления

char DestinationPoint[50]; // Пункт назначения

char DepartureTime[10]; // Время отправления

int classType[3];// Количество по классам

int price[3];// Цена на места по классам

int reservNum;// Количество списков бронирования для рейса

vector<reservation> reserv;// Списки забронированных мест на данный рейс на

// разные даты

public:

~flight() {reserv.clear();}

flight() {reservNum=0;}

void restoreDays(); // Пересборка дней

void reducePeopleLists(); // Уменьшение списка забронированных мест при

// необходимости

void fromFile(ifstream &in);

void toFile(ofstream &out);

// Get- и Set-методы

vector<reservation>& getReserv() {return reserv;}

int getNumber() {return number;}

int& СlassType(int i) {return classType[i];}

void setClassType(String^ cl1, String^ cl2, String^ cl3);

int& Price(int i) {return price[i];}

void setPrice(String^ pr1, String^ pr2, String^ pr3);

int getReservNum() {return reservNum;}

void setReservNum(int n) {reservNum = n;}

void setNumber(int n) {number = n; }

char& Day(int i) {return days[i];}

String^ getDeparturePoint() { returngcnew String(DeparturePoint); }

String^ getDestinationPoint() { returngcnew String(DestinationPoint); }

String^ getDepartureTime() { returngcnew String(DepartureTime); }

void setDeparturePoint (String^ s) { strcpy(DeparturePoint,

(char*)(void*)Marshal::StringToHGlobalAnsi(s)); }

void setDestinationPoint (String^ s) { strcpy(DestinationPoint,

(char*)(void*)Marshal::StringToHGlobalAnsi(s)); }

void setDepartureTime (String^ s) { strcpy(DepartureTime,

(char*)(void*)Marshal::StringToHGlobalAnsi(s)); }

};

// Список бронирования

class reservation

{

vector<person> people; // Список людей на данный рейс

int reserved[3];// Количество занятых мест по классам

char date[30];// Дата

public:

reservation() {reserved[0]=0;

reserved[1]=0;

reserved[2]=0;}

~reservation() { people.clear();}

// Get- и Set-методы

int& Reserved(int i) {return reserved[i];}

String^ getDate() { returngcnew String(date); }

void setDate (String^ s) { strcpy(date,(char*)(void*)Marshal::StringToHGlobalAnsi(s)); }

vector<person>& getPeople() {return people;}

void fromFile(ifstream &in);

void toFile(ofstream &out);

};

// Информация о человеке, бронировавшем место

class person

{

char name[50]; // Полное имя

int placeType;// Тип места

public:

person(){name[0]=' '; placeType=0; }

person(String^ s, char t) { strcpy(name,(char*)(void*)Marshal::StringToHGlobalAnsi(s)); placeType=t; }

// Get- и Set-методы

String^ getName() { returngcnew String(name); }

int getPlaceType() {return placeType;}

void setName(String^ s) { strcpy(name,(char*)(void*)Marshal::StringToHGlobalAnsi(s)); }

void setPlaceType (int t) {placeType = t;}

};

class data

{

public:

static list<flight> lst; // Список авиарейсов

static list<flight>::iterator iter; // Итератор контейнера list

static flight currentFlight;// Объект класса flight

staticint autosaveInterval;// Период автосохранения (мин)

staticvoid loadFromFile();// Загрузить данные из файла

staticvoid saveToFile();// Сохранить данные в файл

};

data.cpp

#define Month 31

// Загрузить из файла

void data::loadFromFile()

{

ifstream flightsIn;

ifstream daysIn;

ifstream peopleIn;

try {

flightsIn.open('flights.dat', ios::in | ios::binary);

daysIn.open('days.dat', ios::in | ios::binary);

peopleIn.open('people.dat', ios::in | ios::binary);

if(!flightsIn.is_open() || !daysIn.is_open() || !peopleIn.is_open()) throw fileError('1','Ошибка открытия файла');

flightsIn.read((char*)&autosaveInterval, sizeof(int)); // Чтение периода

// автосохранения

int num;

flightsIn.read((char*)&num, sizeof(int));// Чтение макс. количества

// отменяемых действий

StaticUndoStack::MaxActionsNum = num;// Утановка макс.

// количества отменяемых действий

list<flight>::iterator iterator;

flightsIn.read((char*)&num, sizeof(int)); // Чтение количества авиарейсов

for(int k=0; k<num; k++)

{

lst.push_back(currentFlight); // Заполняем контейнер lst

// объектом класса flight

iterator = lst.end()--; // Итератор на последний элемент lst

(*iterator).fromFile(flightsIn); // Читаем рейс из файла

// Загрузка дней

for(int i=0; i<(*iterator).getReservNum(); i++)

{

// Увеличиваем размерность вектора reserv на 1

(*iterator).getReserv().resize((*iterator).getReserv().size()+1);(*iterator).getReserv()[i].fromFile(daysIn); // Читаем информацию о

// вылете рейса по дням

// Загрузка информации о забронированных местах для каждого дня

int num = (*iterator).getReserv()[i].Reserved(0) + (*iterator).getReserv()[i].Reserved(1) + (*iterator).getReserv()[i].Reserved(2);

for (int j=0; j<num; j++)

{

(*iterator).getReserv()[i].getPeople().resize((*iterator).getReserv()[i].getPeople().size()+1);

peopleIn.read((char*)&(*iterator).getReserv()[i].getPeople()[j], sizeof(person)); // Читаем информацию о человеке

}

}

}

} catch (baseException &e)

{

e.showException(); // Вывод исключения

// Закрытие файлов при необходимости

if(flightsIn.is_open()) flightsIn.close();

if(daysIn.is_open()) daysIn.close();

if(peopleIn.is_open()) peopleIn.close();

}

}

// Записать в файл

void data::saveToFile()

{

ofstream flightsOut;

ofstream daysOut;

ofstream peopleOut;

try {

flightsOut.open('flights.dat', ios::out | ios::binary);

daysOut.open('days.dat', ios::out | ios::binary);

peopleOut.open('people.dat', ios::out | ios::binary);

if(!flightsOut.is_open() || !daysOut.is_open() || !peopleOut.is_open()) throw fileError('1','Ошибка открытия файла');

flightsOut.write((char*)&autosaveInterval, sizeof(int)); // Запись периода

// автосохранения

int num = StaticUndoStack::MaxActionsNum;// Макс. количество отменяемых

// действий

flightsOut.write((char*)&num, sizeof(int));// Запись макс. количества

// отменяемых действий

list<flight>::iterator iterator;

num = lst.size();// Количество авиарейсов

flightsOut.write((char*)&num, sizeof(int)); // Читаем количество авирейсов из

// файла

// Запись авиарейсов

for(iterator=lst.begin(); iterator!=lst.end(); iterator++)

{

(*iterator).toFile(flightsOut); // Записываем рейс в файл

// Запись информации о днях

for(unsignedint i=0; i<(*iterator).getReserv().size(); i++)

{

(*iterator).getReserv()[i].toFile(daysOut);

// Запись информации о забронированных местах

for(unsignedint j=0;j<(*iterator).getReserv()[i].

getPeople().size(); j++)

peopleOut.write((char*)&(*iterator).getReserv()[i].getPeople()[j], sizeof(person)); // Записываем информацию о человеке

}

}

} catch (baseException &e)

{

e.showException(); // Вывод исключения

// Закрытие файлов при необходимости

if(flightsOut.is_open()) flightsOut.close();

if(daysOut.is_open()) daysOut.close();

if(peopleOut.is_open()) peopleOut.close();

}

}

// Пересборка дней

void flight::restoreDays()

{

DateTime dateValue = DateTime::Now; // Текущая дата

int day;// Номер дня недели

// Удаление дат до сегодняшнего дня и лишних дней

vector<reservation>::iterator itr = reserv.begin(); // Итератор на начало списка

// дней

while(itr!=reserv.end())

{

// Очередная дата из списка

dateValue = Convert::ToDateTime((*itr).getDate());

if(dateValue.Date < DateTime::Now.Date)// Если дата до сегодняшнего дня

{

itr = reserv.erase(itr); // Удаляем запись

reservNum--;// Уменьшаем количество дней

continue;

}

(int) dateValue.DayOfWeek == 0 ? day = 6: day = (int)dateValue.DayOfWeek-1; // Получаем ноиер дня недели из списка

if(!days[day]) // Если рейс не летает в данный день недели

{

itr = reserv.erase(itr); // Удаляем запись

reservNum--;// Уменьшаем количество дней

}

else itr++;

}

if(reserv.size()) // Если список дней не пуст

{

itr = reserv.begin();

dateValue = Convert::ToDateTime((*itr).getDate());

// Если первая в списке дата - сегодня,то удаляем её

if(dateValue.Date == DateTime::Now.Date) reserv.erase(itr);

}

// Добавление недостающих дат

dateValue = DateTime::Now.AddDays(1);// Начальная дата

DateTime dateValueMax = DateTime::Now.AddDays(Month); // Максимальная дата

DateTime newDate;

itr = reserv.begin();

String ^s='';

while(dateValue.Date <= dateValueMax.Date)

{

(int) dateValue.DayOfWeek == 0 ? day = 6: day = (int)dateValue.DayOfWeek-1; // Номер дня недели очередной даты

// Если в этот день недели рейс выполняется

if(days[day])

{

if (itr!=reserv.end()) // Если не достигнут конец списка дней

{ String^ s= (*itr).getDate();

newDate=DateTime::Parse(s);} // Очередная дата из списка

// Если достигнут конец списка дней, или следующая дата не совпадает

// с датой из списка

if(itr==reserv.end() || dateValue.Date != newDate.Date)

{

// вставляем элемент в список дней

itr = reserv.insert(itr,reservation());

// устанавливаем данную дату

(*itr).setDate(dateValue.Date.ToShortDateString());

reservNum++;// увеличиваем количество дней для данного рейса

}

itr++;

}

dateValue = dateValue.AddDays(1); // Переходим к следующей дате

}

}

// Уменьшение списка забронированных мест при уменьшении их максимального количества

void flight::reducePeopleLists()

{

for(int i = 0; i < reserv.size(); i++) // Проход по списку дней

{

for(int cl=0; cl<3; cl++)// Для каждого типа места

// Если забронировано больше мест, чем возможно

if(reserv[i].Reserved(cl) > classType[cl])

// Проход по списку мест с конца

for (int j = reserv[i].getPeople().size()-1; j>=0; j--)

// Если место рассматриваемого типа

if(reserv[i].getPeople()[j].getPlaceType()==cl+1) {

reserv[i].getPeople().erase(reserv[i].getPeople().begin()+j); // Удаляем его

reserv[i].Reserved(cl)--;

// Если количество уменьшено до максимального,

// то прекращаем цикл

if(reserv[i].Reserved(cl) == classType[cl])

break;

}

}

}

// Запись необходимых полей класса в файловый поток

void flight::toFile(ofstream &out)

{

out.write((char*)&number,sizeof(int));

out.write((char*)&days,sizeof(days));

out.write((char*)&DeparturePoint,sizeof(DeparturePoint));

out.write((char*)&DestinationPoint,sizeof(DestinationPoint));

out.write((char*)&DepartureTime,sizeof(DepartureTime));

out.write((char*)&classType,sizeof(classType));

out.write((char*)&price,sizeof(price));

out.write((char*)&reservNum,sizeof(int));

}

// Чтение необходимых полей класса из файлового потока

void flight::fromFile(ifstream &in)

{

in.read((char*)&number,sizeof(int));

in.read((char*)&days,sizeof(days));

in.read((char*)&DeparturePoint,sizeof(DeparturePoint));

in.read((char*)&DestinationPoint,sizeof(DestinationPoint));

in.read((char*)&DepartureTime,sizeof(DepartureTime));

in.read((char*)&classType,sizeof(classType));

in.read((char*)&price,sizeof(price));

in.read((char*)&reservNum,sizeof(int));

}

// Установка типов мест

void flight::setClassType(String^ cl1, String^ cl2, String^ cl3)

{

classType[0] = Convert::ToInt32(cl1);

classType[1] = Convert::ToInt32(cl2);

classType[2] = Convert::ToInt32(cl3);

}

// Установка стоимости мест в зависимости от типа

void flight::setPrice(String^ pr1, String^ pr2, String^ pr3)

{

price[0] = Convert::ToInt32(pr1);

price[1] = Convert::ToInt32(pr2);

price[2] = Convert::ToInt32(pr3);

}

// Запись необходимых полей класса в файловый поток

void reservation::toFile(ofstream &out)

{

out.write((char*)&reserved,sizeof(reserved));

out.write((char*)&date,sizeof(date));

}

// Чтение необходимых полей класса из файлового потока

void reservation::fromFile(ifstream &in)

{

in.read((char*)&reserved,sizeof(reserved));

in.read((char*)&date,sizeof(date));

}

ref.by 2006—2025
contextus@mail.ru