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

  • Вид работы:
    Курсовая работа (т)
  • Предмет:
    Информационное обеспечение, программирование
  • Язык:
    Русский
    ,
    Формат файла:
    MS Word
    894,71 Кб
  • Опубликовано:
    2012-06-21
Вы можете узнать стоимость помощи в написании студенческой работы.
Помощь в написании работы, которую точно примут!

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

ВВЕДЕНИЕ

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Внешние данные, используемые в программе, хранятся в трёх файлах..dat - файл с информацией об авиарейсах. Состоит из записей - полей класса flight:

int number //Номеррейсаdays[7]// ДнинеделиDeparturePoint[50]//ПунктотправленияDestinationPoint[50] //Пунктназначения

charDepartureTime[10]//Времяотправления[3]//Количествоместпоклассам[3]//Цена на места по классам;// Количество списков бронирования.dat - файл с информацией о занятых местах по дням, в которые совершаются рейсы. Состоит из записей - полей класса reservation:[3]; // Количество занятых мест по классам[30]; // Дата.dat - файл со списком людей, которые забронировали места. Состоит из записей - полей класса person:name[50]; // Полноеимя; // Тип забронированного места

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

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

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

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

template<class ListType>class list

{

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

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

// спискаl_iterator<ListType> iterator;

int size(); // Возвращает количество элементов спискаpush_back (const ListType &val);// Сохранение элемента в конец списка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); // Удаляет элемент, на который ссылается итератор delbegin(); // Возвращает итератор на начало спискаend(); // Возвращает итератор на элемент за последнимclear();();

~list();

};

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

template<class ListType>class l_iterator

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

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

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

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

l_iterator operator=(l_iterator &ptr);_iterator operator=(Object ^ ptr);==(l_iterator &ptr) { return cur==ptr.cur ? 1: 0;}!=(l_iterator &ptr) { return cur!=ptr.cur ? 1: 0;}getNumber(); // Номер элемента по итератору

};

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

template<class ListType>class element

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

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

// следующий элементы*val; // Указатель на объект

public:();

~element();

};

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

{<sType> ^top; // Вершина стекаcount;// Количество элементов в стеке

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

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

returnElement^ pop();// Достать из стекаreduce();// Удалить лишние элементы стека при превышении макс.

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

};

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

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

class flight

{number; // Номер рейсаdays[7]; // Дни неделиDeparturePoint[50]; // Пункт отправленияDestinationPoint[50]; // Пункт назначения

char DepartureTime[10]; // Время отправленияclassType[3]; // Количество по классамprice[3]; // Цена на места по классамreservNum; // Количество списков бронирования для рейса<reservation> reserv; // Списки забронированных местна разные даты

public:

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

void reducePeopleLists();// Удаление забронированных мест на прошедшие датыfromFile(ifstream &in);// Прочитать из файлового потокаtoFile(ofstream &out);// Записать в файловый поток

// Get- и Set-методы<reservation>& getReserv(); // Получить ссылку на спискиgetNumber(); & СlassType(int i);setClassType(String^ cl1, String^ cl2, String^ cl3);& Price(int i);setPrice(String^ pr1, String^ pr2, String^ pr3);getReservNum();setReservNum(int n);setNumber(int n);& Day(int i);^ getDeparturePoint();^ getDestinationPoint();^ getDepartureTime();setDeparturePoint (String^ s);(String^ s);

void setDepartureTime (String^ s);

};

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

class reservation

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

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

char date[30]; // Дата :();

~reservation();

// Get- и Set-методы& Reserved(int i);^ getDate();setDate (String^ s);<person>& getPeople();fromFile(ifstream &in); // Прочитать из файлового потока

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

};

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

class person

{name[50]; // Полное имяplaceType;:();(String^ s, char t);

// Get- и Set-методы^ getName();getPlaceType();setName(String^ s);setPlaceType (int t)

};

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

class data

{:list<flight> lst; // Список авиарейсовlist<flight>::iterator iter; // Итератор для спискаflight currentFlight;// Объект класса flightautosaveInterval;// Период автосохранения (мин)loadFromFile(); // Загрузить данные из файла

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

};

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

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

class baseException

{:* code; // Код ошибки* description; // описание ошибки:(char* code, char* description);

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

};

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

class fileError: public baseException

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

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

};

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

class fillException: public baseException

{:(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 г.

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

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

. Библиотека MSDN[Электронный ресурс] /Microsoft Corp. - 2012 - Режим доступа: #"551761.files/image001.gif">

ПРИЛОЖЕНИЕ Б

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

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

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

ПРИЛОЖЕНИЕ В

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




ПРИЛОЖЕНИЕ Г

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

.h

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

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

{>Rows[idx]->Cells[0]->Value = flt.getNumber();>Rows[idx]->Cells[1]->Value = flt.getDeparturePoint();>Rows[idx]->Cells[2]->Value = flt.getDestinationPoint();<String^> ^days = gcnewarray<String^> {"пн","вт","ср","чт","пт","сб","вс"};^ s; int count=0;(int i=0; i<7; i++)(flt.Day(i)) { if(!s) s+=days[i]; else s+=", "+days[i]; count++;}(count==7) s="Ежедневно";>Rows[idx]->Cells[3]->Value = s;>Rows[idx]->Cells[4]->Value = flt.getDepartureTime();

}

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

private: void setAllButtonsState()

{(!flightsView->RowCount)

{>Enabled = false; toolStripDeleteButton->Enabled = false; >Enabled = false;>Enabled = false; toolStripEditButton->Enabled = false;>Enabled = false;>Enabled = false; toolStripInfoButton->Enabled = false;

}

{>Enabled = true; toolStripDeleteButton->Enabled = true; >Enabled = true;>Enabled = true; toolStripEditButton->Enabled = true; >Enabled = true;>Enabled = true; toolStripInfoButton->Enabled = true;

}

}

// Поведение главной формы при запуске: System::Void MainForm_Load(System::Object^ sender, System::EventArgs^ e)

{::loadFromFile(); // Загрузка из файла>timer1->Interval = data::autosaveInterval; // Установка периода  // автосохранения::iter = data::lst.begin();(int i=0; i<data::lst.size(); i++)

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

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

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

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

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

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

}

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

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

{_Click(sender,e);

}

// Кнопка "Изменить" в меню : System::Void EditToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)

{_Click(sender,e);

}

// Кнопка "Удалить" в меню: System::Void DeleteToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)

{_Click(sender,e);

}

// Добавление рейса: System::Void AddButton_Click(System::Object^ sender, System::EventArgs^ e)

{^form = gcnew EditForm();::Windows::Forms::DialogResult dr;

dr=form->ShowDialog();

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

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

{>Enabled = true; UndoToolStripMenuItem->Enabled = true;>Rows->Add();// Добавляем строку таблицыidx = flightsView->RowCount;// Количество строк(data::currentFlight,idx-1); // Загружаем строку в таблицу::lst.push_back(data::currentFlight); // Добавляем рейс в конец списка

// Добавление в стек отмены::flightStack->push(1,data::lst.size()-1, -1, >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)

{idx = flightsView->CurrentRow->Index;// Текущая строка::iter = flightsView->Rows[idx]->Cells[5]->Value; // Итератор на элемент,

// соотв. строке::currentFlight = *data::iter;^form = gcnew EditForm(true, flightsView->Rows[idx]);::Windows::Forms::DialogResult dr;=form->ShowDialog();(dr==System::Windows::Forms::DialogResult::OK)// Если результат диалога OK

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

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

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

}

}

//Удаление авиарейса: System::Void DeleteButton_Click(System::Object^ sender, System::EventArgs^ e)

{>Enabled = true; UndoToolStripMenuItem->Enabled = true;idx = flightsView->CurrentRow->Index; // Текущая строка::iter = flightsView->CurrentRow->Cells[5]->Value; // Итератор на элемент,

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

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

StaticUndoStack::flightStack->push(3,data::iter.getNumber(), -1, >Rows[idx],*(data::iter));::lst.erase(data::iter); // Удаляем элемент из списка>Rows->RemoveAt(idx); // Удаляем из таблицы

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

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

}

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

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

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

// соотв. строке ^f = gcnew ReservationForm();

f->ShowDialog();

}

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

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

{>Close();

}

// "Сохранить" в меню: System:: Void сохранитьToolStripMenuItem_Click (System::Object^ sender, System::EventArgs^ e)

{::saveToFile();

}

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

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

{_Click(sender, e);

}

// Поиск: System::Void toolStripSearchButton_Click(System::Object^ sender, System::EventArgs^ e)

{^ f = gcnew SearchForm(flightsView);

f->ShowDialog();

}

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

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

{_Click(sender,e);

}

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

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

{_Click(sender,e);

}

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

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

{_Click(sender,e);

}

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

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

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

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

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

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

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

flightsView->Rows->Insert(temp->index,1); // Вставляем пустую строку(int i=0; i < temp->Row->Cells->Count; i++)>Rows[temp->index]->Cells[i]->Value = >Row->Cells[i]->Value; // Копируем содержимое строки

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

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

}

// Действия при закрытии формы: System::Void MainForm_FormClosed(System::Object^ sender, System::Windows::Forms::FormClosedEventArgs^ e)

{::saveToFile();

}

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

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

{_Click(sender,e);

}

// Автосохранение: System::Void timer1_Tick(System::Object^ sender, System::EventArgs^ e)

{::saveToFile();

}

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

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

{^form = gcnew About;>ShowDialog();

}

// Кнопка "О программе" в меню: System::Void AboutToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)

{^form = gcnew About;>ShowDialog();

}

// Кнопка "Настройки" в меню: System::Void SettingsToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e)

{^form = gcnew Settings(timer1);

form->ShowDialog();

}.h

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

private: void loadFromPeople()

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

// Количество человек на данную датуsize = (*data::iter).getReserv()[listBox1->SelectedIndex].getPeople().size();(!size)

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

}{ DeleteButton->Enabled = true; EditButton->Enabled = true; }(int i=0; i<size; i++)

{>Rows->Add();// Добавляем строку таблицы>Rows[i]->Cells[0]->Value = i+1;// Номер с единицы

// Заполняем ячейки таблицы>Rows[i]->Cells[1]->Value =(*data::iter).getReserv()

[listBox1->SelectedIndex].getPeople()[i].getName();>Rows[i]->Cells[2]->Value = (*data::iter).getReserv()

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

}

}

// Установка состояния клавиши "Добавить": void setAddReservedButtonState()

{((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; }{AddReservedButton->Enabled = true; }

}

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

private: void UpdateFreeLabels(int SelectedItem)

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

(*data::iter).getReserv()[SelectedItem].Reserved(0);->Text = Convert::ToString(free);// Обновление на форме= (*data::iter).СlassType(1) -

(*data::iter).getReserv()[SelectedItem].Reserved(1);->Text = Convert::ToString(free);= (*data::iter).СlassType(2) -

(*data::iter).getReserv()[SelectedItem].Reserved(2);->Text = Convert::ToString(free);

}

// Поведение формы при загрузке: System::Void ReservationForm_Load(System::Object^ sender, System::EventArgs^ e)

{

(*data::iter).restoreDays(); // Добавляем/Удаляем необходимые дни>Text = "Рейс № " + (*data::iter).getNumber() + ". Информация и бронирование

мест";(int i=0; i<(*data::iter).getReserv().size(); i++)->Items->Add((*data::iter).getReserv()[i].getDate());

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

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

}

// Добавление человека:System::Void AddReservedButton_Click(System::Object^sender,System::EventArgs^e)

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

// Установка состояний конопок>Enabled = true; DeleteButton->Enabled = true; >Enabled = true;>Rows->Add();// Добавляем строку таблицы

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

// Установка номеров по порядку(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’ов>Rows[idx]->Cells[1]->Value = textBox1->Text;>Rows[idx]->Cells[2]->Value = ->SelectedItem->ToString();classN = (char)comboBox1->SelectedIndex+1;//Выбранный тип места

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

(*data::iter).getReserv()[listBox1->SelectedIndex].().push_back(person(textBox1->Text,classN));

(*data::iter).getReserv()[listBox1->SelectedIndex].(comboBox1->SelectedIndex)++;<person>::iterator itr =

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

// Добавление в стек отмены::personStack->push (1, idx, listBox1->SelectedIndex, >Rows[idx], *itr);

// Установка текущей строки>CurrentCell = reservedView->Rows[idx]->Cells[0]; _SelectionChanged(sender,e);// Обработка изменения текущей

// строки();// Состояние клавиши «Добавить»(listBox1->SelectedIndex); // Обновляем количество

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

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

}

// Изменение выделения даты: System::Void listBox1_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e)

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

// свободных местах();// Загрузка списка в таблицу ();// Состояние клавиши «Добавить»_SelectionChanged(sender,e);// Обработка изменения выделения

StaticUndoStack::personStack->~lastActionStack(); // Очистка стека>Enabled = false;// Отключение отмены

}

// Выделение новой строки в таблице: System::Void reservedView_SelectionChanged(System::Object^ sender, System::EventArgs^ e)

{(!reservedView->RowCount) return;// Если таблица пуста(Convert::ToString(reservedView->Rows[0]->Cells[1]->Value)=="") return;idx = reservedView->CurrentRow->Index; // Текущая строка

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

textBox1->Text = Convert::ToString(reservedView->Rows[idx]->Cells[1]->Value);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)

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

getPeople()[i].getPlaceType();

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

i = Convert::ToInt32(reservedView->Rows[i]->Cells[0]->Value);<person>::iterator itr = (*data::iter).// Итератор на удалемого человека()[listBox1->SelectedIndex].getPeople().begin() + i-1;

// Добавление в стек отмены::personStack->push (3, i-1, listBox1->SelectedIndex, >CurrentRow, *(itr));

(*data::iter).getReserv()[listBox1->SelectedIndex].Reserved(prevType-1)--;(listBox1->SelectedIndex); // Обновляем количество свободных мест

// Удаляем из таблицы и вектора>Rows->RemoveAt(reservedView->CurrentRow->Index);

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

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

if(!reservedView->RowCount)

{DeleteButton->Enabled = false; EditButton->Enabled = false;}(i=0; i<reservedView->RowCount; i++)>Rows[i]->Cells[0]->Value = i+1;();>Enabled = true;

}

// Изменение информации о человеке: System::Void EditButton_Click(System::Object^ sender, System::EventArgs^ e)

{{(textBox1->Text=="") throw fillException("4","Необходимо ввести имя пассажира!");// Если поле имени пустоidx = reservedView->CurrentRow->Index;// Номер текущей строкиprevType = (*data::iter).getReserv()[listBox1->SelectedIndex].getPeople()[idx].getPlaceType();// Тип места до изменения((prevType-1)!=comboBox1->SelectedIndex) // Если не совпадают типы мест

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

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

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

Reserved(comboBox1->SelectedIndex)++;

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

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

textBox1->Text) ;

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

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

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

// Добавление в стек отмены::personStack->push (2, idx, listBox1->SelectedIndex, reservedView->Rows[idx], *(itr+idx));

// Изменение ячеек в таблице>Rows[idx]->Cells[1]->Value = textBox1->Text;>Rows[idx]->Cells[2]->Value = comboBox1->SelectedItem->ToString();classN = (int)comboBox1->SelectedIndex+1;// Тип выбранного места

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

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

(*data::iter).getReserv()[listBox1->SelectedIndex].getPeople()[idx].setPlaceType(classN);(listBox1->SelectedIndex);// Установка свободных мест

// Установка состояний кнопок();>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 - предыдущий тип места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))->SelectedIndex = prevType-1;// Устанавливаем предыдущий тип

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

}

// Отмена последнего действия: System::Void UndoButton_Click(System::Object^ sender, System::EventArgs^ e)

{// Извлечение элемента из стека^ temp = StaticUndoStack::personStack->pop();

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

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

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

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

{// Вставляем пустую строку>Rows->Insert(temp->index,1); (int i=0; i<reservedView->RowCount; i++) // Перенумеровка>Rows[i]->Cells[0]->Value = i+1;

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

{prevType = Convert::ToString(reservedView->Rows[temp->index]->Cells[2]->Value)[0] - 49;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)++;

}

}(int i=0; i < temp->Row->Cells->Count; i++)>Rows[temp->index]->Cells[i]->Value = temp->Row->Cells[i]->Value; // Копируем содержимое строки

}();// Установка состояния кнопки «Добавить»(listBox1->SelectedIndex); // Обновляем количество свободных мест

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

if (!StaticUndoStack::personStack->Count()) >Enabled = false; (!reservedView->RowCount)

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

}

// Отмена через Ctrl+Z: System::Void ReservationForm_KeyDown(System::Object^ sender, System::Windows::Forms::KeyEventArgs^ e)

{>Handled = true;(e->KeyData==(Keys::Control | Keys::Z) && StaticUndoStack:: personStack->Count())_Click(sender,e);

}.h

// Поиск: System::Void FindButton_Click(System::Object^ sender, System::EventArgs^ e)

{flag;>Rows->Clear();// Очищаем таблицу(textBox1->Text==""&& textBox2->Text==""&& textBox3->Text==""&& !checkedListBox1->CheckedItems->Count)// Если условия поиска не заданы;(int i=0; i<dataGridMain->RowCount; i++)

{=0;((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==""))// Если заполнено хотя бы одно из полей и элемент найден

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

{// Итератор на элемент, соотв. строке::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)

{<Object^> ^rowData = gcnewarray<Object^>(dataGridMain->Rows[i]->Cells->Count);// Копируем строку из основной таблицы(int j=0; j<rowData->Length; j++)rowData[j] = dataGridMain->Rows[i]->Cells[j]->Value;>Rows->Add(rowData);// Добавляем строку

}

}

}

}

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

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

{(e->KeyChar >= '0'&& e->KeyChar <= '9' || e->KeyChar==8)>Handled = false;e->Handled = true;

}

// Двойной щелчок на строке таблицы: System::Void foundFlightsView_CellDoubleClick(System::Object^ sender, System::Windows::Forms::DataGridViewCellEventArgs^ e)

{::iter = foundFlightsView->CurrentRow->Cells[5]->Value; // Итератор на // элемент, соотв. строке ^f = gcnew ReservationForm();>ShowDialog();

}.h

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

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

{>Close();

}

// Нажатие кнопки «OK»: System::Void OkButton_Click(System::Object^ sender, System::EventArgs^ e)

{

// Изменение максимального количества отменяемых действий::MaxActionsNum = (int)numericUpDown1->Value;

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

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

// в главной форме::autosaveInterval = (int) timer1->Interval;// Период автосохранения>Close();

}

// Загрузка формы «Настройки»: System::Void Settings_Load(System::Object^ sender, System::EventArgs^ e)

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

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

}.h

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

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

{

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

if(editingMode)

{

// Заполняем TextBox'ы->Text = Convert::ToString(data::currentFlight.getNumber());->Text = data::currentFlight.getDeparturePoint();->Text = data::currentFlight.getDestinationPoint();->Text = Convert::ToString(data::currentFlight.СlassType(0));->Text = Convert::ToString(data::currentFlight.Price(0));->Text = Convert::ToString(data::currentFlight.СlassType(1));->Text = Convert::ToString(data::currentFlight.Price(1));->Text = Convert::ToString(data::currentFlight.СlassType(2));->Text = Convert::ToString(data::currentFlight.Price(2));

// Устанавливаем дни недели(int i=0; i<checkedListBox1->Items->Count; i++)->SetItemCheckState(i,(CheckState)data::currentFlight.Day(i));

// Устанавливаем время отправления->Value =

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

}

}

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

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

{(e->KeyChar >= '0'&& e->KeyChar <= '9' || e->KeyChar==8)>Handled = false;e->Handled = true;

}

// Проверка на дубликаты рейсов: bool checkCopy(int number)

{<flight>::iterator iterator;(iterator = data::lst.begin(); iterator!=data::lst.end(); iterator++)

{// Если указан уже существующий рейс((number==(*iterator).getNumber() && !editingMode) || (number==(*iterator).getNumber() && (*data::iter).getNumber()!=number && editingMode));

};

}

// Нажатие ОК: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)

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

StaticUndoStack::flightStack->push(2,data::iter.getNumber(),-1,Row,data::currentFlight);// Добавляем в стек отмены(int i=1; i<10; i++)// Проверяем заполненность textBox’ов

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

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

}

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

if(checkCopy(Convert::ToInt32(textBox1->Text))) throw fillException("4","Данный рейс уже существует");(checkedListBox1->CheckedItems->Count==0) throw fillException("3","Выберите дни, по которым совершается рейс!");// Добавляем в текущий рейс информацию из полей формы::currentFlight.setNumber(Convert::ToInt32(textBox1->Text)); ::currentFlight.setDeparturePoint(textBox2->Text);::currentFlight.setDestinationPoint(textBox3->Text);::currentFlight.setClassType(textBox4->Text, textBox6->Text, textBox8->Text);::currentFlight.setPrice(textBox5->Text, textBox7->Text, textBox9->Text);

// Копируем время отправления::currentFlight.setDepartureTime(dateTimePicker1->Value.ToShortTimeString());

// Устанавливаем выбранные дни недели(int i=0; i<checkedListBox1->Items->Count; i++)

{((int)checkedListBox1->GetItemCheckState(i)) ::currentFlight.Day(i)=1;data::currentFlight.Day(i)=0;

}>DialogResult=System::Windows::Forms::DialogResult::OK;>Close();

}(baseException &e)

{ e.showException();}

}.h<class ListType>class list;<class ListType>class element;<class ListType>class l_iterator;

// Шаблон класса "Список"<class ListType>class list

{<ListType> *start, *last, *after_last; // Указатели на начало и конец спискаnumber;// Количество элементов списка

public:<class ListType>friendclass l_iterator;<class ListType>friendclass element;l_iterator<ListType> iterator;

int size() { return number; }// Возвращает количество элементов спискаpush_back (const ListType &val); // Сохранение элемента в конец спискаpush_front (const ListType &val); // Сохранение элемента в начало списка

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

// который ссылается итератор ierase (iterator start, iterator end); // Удаляет элементы из диапазона

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

// ссылается итератор delbegin() // Возвращает итератор на начало

// списка

{iterator p;(start) p.cur=start;p.cur = after_last;p;

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

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

{while(start) {last=start->next; delete[] start; start=last;}=last=0; number=0;_last=new element<ListType>[1];_last->next=0;

}() { start=0; last=0; number=0;_last=new element<ListType>[1];

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

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

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

};

// Шаблон элемента списка<class ListType>class element

{<class ListType>friendclass list;<class ListType>friendclass l_iterator;*prev, *next;*val;:() {val=new ListType;}

~element() {delete val;}

};

// Шаблон итератора списка<class ListType>class l_iterator

{<class ListType>friendclass list;<class ListType>friendclass element;<ListType> *cur;:() {returnreinterpret_cast<longlong>(cur);}&operator*() const { return *cur->val; } // Доступ к элементу списка

// через итератор_iterator operator++(int x){ cur==0 ? cur: cur=cur->next; return *this; }_iterator operator--(int x) { cur==0 ? cur: cur=cur->prev; return *this; }_iterator operator=(l_iterator &ptr) { cur=ptr.cur; return *this;}_iterator operator=(Object ^ ptr) { longlong tmp = Convert::ToInt64(ptr);cur=reinterpret_cast<element<ListType> *>(tmp); return *this;}==(l_iterator &ptr) { return cur==ptr.cur ? 1: 0;}!=(l_iterator &ptr) { return cur!=ptr.cur ? 1: 0;}getNumber()

{num = 0;<ListType> *temp = cur;(temp->prev!=0)

{= temp->prev;

num++;

}num;

}

};

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

template<class ListType>list<ListType>::push_back(const ListType &val)

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

{

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

}

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

// Связываем элемент с остальными>next->prev=last;

last=last->next;

}>next=after_last;_last->prev=last;

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

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

}

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

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

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

{

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

start=last;

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

last->next=after_last;_last->prev=last;

}

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

// Связываем элемент с остальными>prev->next=start;

start=start->prev;

}>prev=0;

*start->val=val; // Заполняем элемент++;// Увеличиваем счётчик элементов списка

}

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

template<class ListType>_iterator<ListType> list<ListType>::insert(iterator i, const ListType &val)

{(!i.cur) return i;<ListType> *n;(i.cur==after_last && !start) // Если список пуст

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

start=last;

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

last->next=after_last;_last->prev=last;>prev=0;

}

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

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

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

// Связываем элемент с остальными>next->prev=last;

last=last->next;>next=after_last;_last->prev=last;

}

{

n = new element<ListType>[1];

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

n->next=i.cur;>prev=i.cur->prev;.cur->prev=n;(n->prev) n->prev->next=n;start = n;

}

}

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

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

temp.cur=i.cur->prev;

return temp;

}

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

template<class ListType>_iterator<ListType> list<ListType>::erase(iterator start, iterator end)

{(!start.cur) return end;(!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)// Удаление элементов в диапазоне

{= start.cur->next; [] start.cur; .cur = temp;-;

} (!t_start && t_end==after_last) // Если границы - начало и конец списка<ListType>::start=last=0;

{

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

{<ListType>::start=t_end;<ListType>::start->prev=0;

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

{=t_start;>next=after_last;

}

}tmp;.cur=t_end;

return tmp;

}

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

template<class ListType>_iterator<ListType> list<ListType>::erase(iterator del)

{<ListType> *temp;(!start) return del;(del.cur == after_last) return del;// Если удаляемый элемент после последнего

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

{[] del.cur;= 0; last = 0;_last->prev = 0;

}

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

{= del.cur->next;[] del.cur;>prev = 0;= start;

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

{= del.cur->prev;[] del.cur;>next = after_last;= last;

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

{= del.cur->next;

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

}

}-;tmp;.cur = temp;tmp;

}.hbaseException

{:* code; // Код ошибки* description; // Описание ошибки:(char* code, char* description)

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

}showException() = 0; // Сообщение об исключительной ситуации~baseException() {delete code; delete description;}

};

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

{:(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

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

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

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

};.h<class sType>refclass lastAction;<class sType>refclass lastActionStack;returnElement;StaticUndoStack;

// Описание последнего действия<class sType>refclass lastAction

{

public:opType;// Тип операции (1 - добавление, 2- изменение, 3 - удаление)index;// Индекс в спискеdayIndex;// Индекс выбранного дня^ Row; // Строка из таблицы (для отмены удаления и изменения)^ prev;// Ссылка на предыдущее действие^ next;// Ссылка на следующее действие

sType *savedObject;// Сохранённый рейс(int opType, int index, int dayIndex, DataGridViewRow^ Row, sType &savedObject);

~lastAction() {delete savedObject;}

};

// Стек последних действий<class sType>refclass lastActionStack

{

lastAction<sType> ^top; // Вершина стекаcount;// Количество элементов в стеке

lastAction<sType> ^bottom; // Дно стека :Count() {return count;}() { count=0; }

~lastActionStack()

{ while(count)

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

}

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

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

};

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

refclass returnElement

{:(int opType, int index, int dayIndex, DataGridViewRow^ Row)

{>opType = opType;>Row = Row; >index = index;>dayIndex = dayIndex;

}opType;index;dayIndex;

DataGridViewRow^ Row;

};

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

refclass StaticUndoStack

{:lastActionStack<flight>^ flightStack = gcnew lastActionStack<flight>;lastActionStack<person>^ personStack = gcnew lastActionStack<person>;

staticint MaxActionsNum = 1;

};

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

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

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

{>Row =(DataGridViewRow^) Row->Clone(); // Копируем строку(int i=0;i<Row->Cells->Count;i++)>Row->Cells[i]->Value = Row->Cells[i]->Value;

}>opType = opType; this->index = index; this->dayIndex = dayIndex;>savedObject = new sType(savedObject);

}

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

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

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

{ (count==1) delete bottom;

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

}-;

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

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

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

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

}bottom = New;// Запоминаем дно стека= New;// Обновляем вершину стека++;

}

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

template<>inline^ lastActionStack<flight>::pop()

{^ bufRow;^ buf;(!top) return buf;<flight>::iterator l_iter = data::lst.begin(); // Итератор в списке авиарейсов(int i=0; i<top->index; i++)

l_iter++; // Устанавливаем итератор на требуемый индекс(top->opType == 1) // Отмена добавления::lst.erase(l_iter); // Удаляем добавленный рейс в списке lst// Отмена удаления или изменения

{

bufRow = (DataGridViewRow^)top->Row->Clone();// Копия строки(int i=0; i < top->Row->Cells->Count; i++)

// Копируем содержимое строки>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

// Обновляем итератор в скрытом столбце>Cells[5]->Value = (longlong) l_iter;

}

// Элемент для возврата= gcnew returnElement(top->opType, top->index, top->dayIndex, bufRow); <flight>^ old;= top;

top = top->prev; // Изменение вершины стекаold;// Удаление старой вершины-;// Уменьшение количества элементов в стекеbuf;

}

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

template<>inline^ lastActionStack<person>::pop()

{^ bufRow;^ buf;(!top) return buf;placeType = top->savedObject->getPlaceType() - 1;// Тип забронированного места<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)--;

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

{

bufRow = (DataGridViewRow^)top->Row->Clone();// Копия строки(int i=0; i < top->Row->Cells->Count; i++)

// Копируем содержимое строки>Cells[i]->Value = top->Row->Cells[i]->Value;(top->opType == 3) // Отмена удаления

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

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

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

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

// reserv

}

// Элемент для возврата= gcnew returnElement(top->opType, top->index, top->dayIndex, bufRow); <person>^ old;= top;

top = top->prev; // Изменение вершины стекаold;// Удаление старой вершины-;// Уменьшение количества элементов в стекеbuf;

}

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

template<class sType>lastActionStack<sType>::reduce()

{dif = count - StaticUndoStack::MaxActionsNum;(dif > 0)

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

{= bottom->next; // Обновляем дно стекаbottom->prev; count--; // Удаляем элемент со дна стека,

}

}

}.hperson;reservation;flight;data;

// Рейсflight

{number;// Номер рейсаdays[7];// Дни неделиDeparturePoint[50]; // Пункт отправленияDestinationPoint[50]; // Пункт назначения

char DepartureTime[10]; // Время отправленияclassType[3];// Количество по классамprice[3];// Цена на места по классамreservNum;// Количество списков бронирования для рейса<reservation> reserv;// Списки забронированных мест на данный рейс на

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

~flight() {reserv.clear();}() {reservNum=0;}restoreDays(); // Пересборка дней

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

// необходимостиfromFile(ifstream &in);toFile(ofstream &out);

// Get- и Set-методы<reservation>& getReserv() {return reserv;}getNumber() {return number;}& СlassType(int i) {return classType[i];}setClassType(String^ cl1, String^ cl2, String^ cl3);& Price(int i) {return price[i];}setPrice(String^ pr1, String^ pr2, String^ pr3);getReservNum() {return reservNum;}setReservNum(int n) {reservNum = n;}setNumber(int n) {number = n; }& Day(int i) {return days[i];}^ getDeparturePoint() { returngcnew String(DeparturePoint); }^ getDestinationPoint() { returngcnew String(DestinationPoint); }^ getDepartureTime() { returngcnew String(DepartureTime); }setDeparturePoint (String^ s) { strcpy(DeparturePoint,

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

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

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

};

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

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

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

char date[30];// Дата :() {reserved[0]=0; [1]=0; [2]=0;}

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

// Get- и Set-методы& Reserved(int i) {return reserved[i];}^ getDate() { returngcnew String(date); }setDate (String^ s) { strcpy(date,(char*)(void*)Marshal::StringToHGlobalAnsi(s)); }<person>& getPeople() {return people;}fromFile(ifstream &in);toFile(ofstream &out);

};

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

{name[50]; // Полное имяplaceType;// Тип места:(){name[0]='\0'; placeType=0; }(String^ s, char t) { strcpy(name,(char*)(void*)Marshal::StringToHGlobalAnsi(s)); placeType=t; }

// Get- и Set-методы^ getName() { returngcnew String(name); }getPlaceType() {return placeType;}setName(String^ s) { strcpy(name,(char*)(void*)Marshal::StringToHGlobalAnsi(s)); }setPlaceType (int t) {placeType = t;}

};data

{:list<flight> lst; // Список авиарейсовlist<flight>::iterator iter; // Итератор контейнера listflight currentFlight;// Объект класса flightautosaveInterval;// Период автосохранения (мин)loadFromFile();// Загрузить данные из файла

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

};.cpp

#define Month 31

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

{flightsIn;daysIn;peopleIn;{.open("flights.dat", ios::in | ios::binary);.open("days.dat", ios::in | ios::binary);.open("people.dat", ios::in | ios::binary);(!flightsIn.is_open() || !daysIn.is_open() || !peopleIn.is_open()) throw fileError("1","Ошибка открытия файла");.read((char*)&autosaveInterval, sizeof(int)); // Чтение периода

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

// отменяемых действий::MaxActionsNum = num;// Утановка макс.

// количества отменяемых действий<flight>::iterator iterator;.read((char*)&num, sizeof(int)); // Чтение количества авиарейсов(int k=0; k<num; k++)

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

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

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

// Загрузка дней(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);(int j=0; j<num; j++)

{

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

}

}

}

} catch (baseException &e)

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

// Закрытие файлов при необходимости(flightsIn.is_open()) flightsIn.close();

if(daysIn.is_open()) daysIn.close();(peopleIn.is_open()) peopleIn.close();

}

}

// Записать в файлdata::saveToFile()

{flightsOut;daysOut;peopleOut;{.open("flights.dat", ios::out | ios::binary);.open("days.dat", ios::out | ios::binary);.open("people.dat", ios::out | ios::binary);(!flightsOut.is_open() || !daysOut.is_open() || !peopleOut.is_open()) throw fileError("1","Ошибка открытия файла");.write((char*)&autosaveInterval, sizeof(int)); // Запись периода

// автосохраненияnum = StaticUndoStack::MaxActionsNum;// Макс. количество отменяемых

// действий.write((char*)&num, sizeof(int));// Запись макс. количества

// отменяемых действий<flight>::iterator iterator;= lst.size();// Количество авиарейсов.write((char*)&num, sizeof(int)); // Читаем количество авирейсов из

// файла

// Запись авиарейсов(iterator=lst.begin(); iterator!=lst.end(); iterator++)

{

(*iterator).toFile(flightsOut); // Записываем рейс в файл

// Запись информации о днях

for(unsignedint i=0; i<(*iterator).getReserv().size(); i++)

{

(*iterator).getReserv()[i].toFile(daysOut);

// Запись информации о забронированных местах(unsignedint j=0;j<(*iterator).getReserv()[i].

getPeople().size(); j++).write((char*)&(*iterator).getReserv()[i].getPeople()[j], sizeof(person)); // Записываем информацию о человеке

}

}

} catch (baseException &e)

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

// Закрытие файлов при необходимости(flightsOut.is_open()) flightsOut.close();(daysOut.is_open()) daysOut.close();(peopleOut.is_open()) peopleOut.close();

}

}

// Пересборка днейflight::restoreDays()

{dateValue = DateTime::Now; // Текущая дата

int day;// Номер дня недели

// Удаление дат до сегодняшнего дня и лишних дней

vector<reservation>::iterator itr = reserv.begin(); // Итератор на начало списка

// дней(itr!=reserv.end())

{

// Очередная дата из списка= Convert::ToDateTime((*itr).getDate());

if(dateValue.Date < DateTime::Now.Date)// Если дата до сегодняшнего дня

{= reserv.erase(itr); // Удаляем запись-;// Уменьшаем количество дней;

}

(int) dateValue.DayOfWeek == 0 ? day = 6: day = (int)dateValue.DayOfWeek-1; // Получаем ноиер дня недели из списка(!days[day]) // Если рейс не летает в данный день недели

{= reserv.erase(itr); // Удаляем запись-;// Уменьшаем количество дней

}itr++;

}(reserv.size()) // Если список дней не пуст

{= reserv.begin();= Convert::ToDateTime((*itr).getDate());

// Если первая в списке дата - сегодня,то удаляем её

if(dateValue.Date == DateTime::Now.Date) reserv.erase(itr);

}

// Добавление недостающих дат= DateTime::Now.AddDays(1);// Начальная дата

DateTime dateValueMax = DateTime::Now.AddDays(Month); // Максимальная датаnewDate;= reserv.begin();^s="";(dateValue.Date <= dateValueMax.Date)

{

(int) dateValue.DayOfWeek == 0 ? day = 6: day = (int)dateValue.DayOfWeek-1; // Номер дня недели очередной даты

// Если в этот день недели рейс выполняется(days[day])

{(itr!=reserv.end()) // Если не достигнут конец списка дней

{ String^ s= (*itr).getDate(); =DateTime::Parse(s);} // Очередная дата из списка

// Если достигнут конец списка дней, или следующая дата не совпадает

// с датой из списка(itr==reserv.end() || dateValue.Date != newDate.Date)

{

// вставляем элемент в список дней= reserv.insert(itr,reservation());

// устанавливаем данную дату

(*itr).setDate(dateValue.Date.ToShortDateString()); ++;// увеличиваем количество дней для данного рейса

}++;

}= dateValue.AddDays(1); // Переходим к следующей дате

}

}

// Уменьшение списка забронированных мест при уменьшении их максимального количества

void flight::reducePeopleLists()

{(int i = 0; i < reserv.size(); i++) // Проход по списку дней

{(int cl=0; cl<3; cl++)// Для каждого типа места

// Если забронировано больше мест, чем возможно

if(reserv[i].Reserved(cl) > classType[cl])

// Проход по списку мест с конца

for (int j = reserv[i].getPeople().size()-1; j>=0; j--)

// Если место рассматриваемого типа(reserv[i].getPeople()[j].getPlaceType()==cl+1) {[i].getPeople().erase(reserv[i].getPeople().begin()+j); // Удаляем его

reserv[i].Reserved(cl)--;

// Если количество уменьшено до максимального,

// то прекращаем цикл(reserv[i].Reserved(cl) == classType[cl])

break;

}

}

}

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

void flight::toFile(ofstream &out)

{.write((char*)&number,sizeof(int));.write((char*)&days,sizeof(days));.write((char*)&DeparturePoint,sizeof(DeparturePoint));.write((char*)&DestinationPoint,sizeof(DestinationPoint));.write((char*)&DepartureTime,sizeof(DepartureTime));.write((char*)&classType,sizeof(classType));.write((char*)&price,sizeof(price));.write((char*)&reservNum,sizeof(int));

}

// Чтение необходимых полей класса из файлового потока

void flight::fromFile(ifstream &in)

{.read((char*)&number,sizeof(int));.read((char*)&days,sizeof(days));.read((char*)&DeparturePoint,sizeof(DeparturePoint));.read((char*)&DestinationPoint,sizeof(DestinationPoint));.read((char*)&DepartureTime,sizeof(DepartureTime));.read((char*)&classType,sizeof(classType));.read((char*)&price,sizeof(price));.read((char*)&reservNum,sizeof(int));

}

// Установка типов местflight::setClassType(String^ cl1, String^ cl2, String^ cl3)

{[0] = Convert::ToInt32(cl1);[1] = Convert::ToInt32(cl2);

classType[2] = Convert::ToInt32(cl3);

}

// Установка стоимости мест в зависимости от типа

void flight::setPrice(String^ pr1, String^ pr2, String^ pr3)

{[0] = Convert::ToInt32(pr1);[1] = Convert::ToInt32(pr2);

price[2] = Convert::ToInt32(pr3);

}

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

void reservation::toFile(ofstream &out)

{.write((char*)&reserved,sizeof(reserved));.write((char*)&date,sizeof(date));

}

// Чтение необходимых полей класса из файлового потока

void reservation::fromFile(ifstream &in)

{.read((char*)&reserved,sizeof(reserved));.read((char*)&date,sizeof(date));

}

Похожие работы на - Программный модуль управления авиарейсами

 

Не нашли материал для своей работы?
Поможем написать уникальную работу
Без плагиата!