Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Структура программы. Таблица базы данных со сведениями о рейсах авиакомпании «Сибирь» и наличии билетов на массиве структур имеет следующие поля:




Таблица базы данных

Таблица базы данных со сведениями о рейсах авиакомпании «Сибирь» и наличии билетов на массиве структур имеет следующие поля:

· номер рейса,

· пункт назначения,

· время вылета,

· время в пути,

· наличие свободных мест.

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

 

Рисунок 1– Однонаправленный список

 

В качестве поля Data структуры подставляется запись базы данных, а указатель p содержит ссылку на следующую запись базы.

Рассмотрим более подробно содержимое поля Data. В данном случае в нем содержится полная информация об авиарейсе: номер рейса (целочисленное значение), пункт назначения (строка), время вылета (структура, в которой две целочисленных переменных задают часы и минуты вылета), время в пути (целочисленное значение, время полета в минутах) и наличие свободных мест также задается целочисленной переменной.

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

База данных хранится в текстовом формате в файле flights.txt. В каждой строке этого файла приведена запись базы данных. Пример организации данных в файле приведен ниже.

 

7 Moscow 12 25 150 100

9 Vienna 15 45 300 23

10 Antalya 3 30 280 200

2 Samara 23 50 90 100

3 Paris 8 20 500 20

90 Moscow 0 45 155 100

34 Samara 2 10 90 22

 

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

2.1. Запись базы данных в файл

Как уже было отмечено в предыдущем разделе, база данных последовательно записывается в файл flights.txt, который находится в той же папке, что и исполняемый файл программы. Имя файла фиксировано и задано в тексте программы. Среда программирования допускает возможность организации пользовательского ввода имени файла, когда имя записываемого файла и полный путь к нему задаются в виде строковой переменной (например, в качестве аргумента командной строки). В рамках данной курсовой работы данная возможность не реализована.

При сохранении данных в файл, он открывается для перезаписи, и в него последовательно заносятся все данные из всех элементов односвязного списка, начиная с головы.

 

2.2. Загрузка базы данных из файла

База данных хранится в текстовом файле flights.txt. Каждая запись содержит последовательно: число, соответствующее номеру рейса, название пункта назначения на английском языке, время отправления (часы и минуты через пробел), длительность полета в минутах и количество свободных мест в самолете.

Загрузка данных из файла производится сразу после запуска программы. При этом из указанного файла считываются все записи, пока не достигнут конец файла. Как и при записи данных имя файла фиксировано и задается в тексте программы.

 

2.3. Инициализация базы данных

Инициализация базы данных происходит при каждом запуске программы. При этом происходит построчное считывание данных из файла flights.txt и занесение информации в элементы списка. Каждый элемент добавляется в хвост списка.

Так, каждая запись базы данных представляется следующей структурой

 

struct Flight{

int Num; //номер рейса

char Destination [cF];//пункт назначения

Time Dep; //время вылета

int way; //время в пути

int FreePlace; //наличие свободных мест

Flight *Next; //Указатель на следующий элемент списка

};

 

Здесь константа cF представляет максимально возможную длину строки

 

const int cF=30;//Максимальная длина строки

 

Структура Time для хранения данных о времени вылета задается следующим образом

 

//Структура для хранения данных о времени

struct Time{

int hr; //часы

int min; //минуты

};

 

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

Объявим указатель на головной элемент списка

 

Flight *head; //Указатель на голову списка

 

При инициализации базы данных происходит вызов функции чтения информации из файла. Если чтение из файла произошло с ошибками (например, не удалось открыть файл или корректно считать из него данные), завершить выполнение программы

 

Flight * head=ReadBase("flights.txt"); //Считать базу из файла flights.txt

if (!head){//Если база не существует, завершить выполнение программы

cout<<"Невозможно сформировать список\n";

system("PAUSE");

return 1;

}

 

Алгоритм чтения данных из файла заключается в последовательном считывании информации в статическую переменную Flight f и последующее добавление элемента списка с помощью функции Add (подробное описание функции см. в следующем разделе). После завершения операции чтения из файла, функция ReadBase возвращает указатель на голову списка.

 

Flight * ReadBase (char *FileName){

//Открыть файл с именем, хранящимся в переменной FileName для чтения.

//Будем работать с входным потоком

ifstream in;

Flight f, *head=0;

in.open(FileName);

//Если не удалось открыть файл - сообщить об ошибке

if (!in){

cout<<"Ошибка открытия файла\n";

return 0;

}

//Считать данные из файла в переменную f (имеющую тип Flight) и вызвать

//функцию добавления соответствующего элемента в список

while (in>>(f.Num)>>(f.Destination)>>(f.Dep.hr)>>(f.Dep.min)>>(f.way)>>(f.FreePlace)){

head=Add(head,f);

}

//Закрыть файл

in.close();

//Вернуть указатель на головной элемент списка

return head;

}

 

2.4. Ввод новой записи в базу данных

Ввод новой записи осуществляется посредством добавления новой записи в конец уже созданного списка.

Добавление в конец списка (рис. 2) является одной из простейших операций добавления, т.к. в этом случае необходимо знать только указатель на конец списка. В функцию добавления этот указатель передается с двумя операциями взятия адреса **, т.к. в результате работы этой функции указатель модифицируется: последним элементом станет вставляемый.

Рисунок 2 – Добавление элемента в конец списка

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

 

Flight* Add(Flight * head, const Flight& fl){

//Формирование нового элемента

Flight * pv=new Flight;

*pv=fl;

pv->Next=0;

if (head){ //Если список не пуст

Flight* tmp=head;

while(tmp->Next)

tmp=tmp->Next;//Поиск конца списка

tmp->Next=pv;

//Присоединение нового элемента

}else

head=pv;

return head;

}

 

2.5. Удаление записи из базы данных

Для того, чтобы удалить некоторую запись из базы данных, необходимо ее найти. Очевидно, что удаляется только существующая запись базы.

Рассмотрим функцию поиска элемента по ключу. Под ключом будем понимать некоторую комбинацию полей базы, которая позволяет найти требуемую запись (или множество записей). Поиск элемента по ключу осуществляется с начала списка, указатель на который передается в данную функцию и до конца списка. Если элемент найден, функция возвращает указатель на него, если не найден – нулевой указатель.

Функция поиска для рассматриваемой базы данных выглядит следующим образом. Будем осуществлять поиск по полю «Номер рейса», т.к. существует единственный рейс с указанным номером. Приведенная ниже функция выполняет поиск, выводит сведения об авиарейсе и возвращает указатель на найденный элемент или ноль, если элемент не найден. Кроме того, в список параметров этой функции добавляется указатель на элемент, предшествующий найденному. Он передается по адресу (как указатель на указатель), т.к. он формируется внутри функции. Этот указатель понадобится в функции удаления, когда потребуется связать предыдущий и последующий по отношению к удаляемому элементы.

Функция возвращает указатель на последний найденный элемент списка, ключ которого совпадает с заданным.

 

Flight *FindNum(Flight * pv, int Num, Flight **prev){

*prev=0;

while (pv){ // Пока не достигли конца списка...

if (pv->Num==Num){ //Если номер рейса текущего элемента совпадает с искомым...

// Вывести информацию о найденном рейсе на экран

cout<<(pv->Destination)<<" "<<(pv->Dep.hr)<<" "<<(pv->Dep.min);

cout<<" "<<(pv->way)<<" "<<(pv->FreePlace)<<"\n";

//Возврат из функции: может быть только одна запись с указанным номером рейса

return pv;

}

// Переход к следующему элементу списка

*prev=pv;

pv=pv->Next;

}

//Если список просмотрен, но ничего не выведено на экран, значит,

//рейса с заданным номером нет в базе

cout<<"Рейс с номером "<<Num<<" не найден\n";

return 0;

}

 

Удаление из списка происходит следующим образом.

Шаг 1. Ввести номер удаляемого рейса.

Шаг 2. Если рейс с введенным номером существует (найден), перейти на шаг 3, иначе завершить выполнение функции.

Шаг 3. Если найденный элемент находится в голове списка, сдвинуть указатель на голову списка к следующему элементу. Вернуть указатель на голову и завершить выполнение алгоритма. В противном случае перейти на шаг 4.

Шаг 4. Взять предыдущий элемент списка и модифицировать его указатель (чтобы предыдущий элемент ссылался на последующий). Завершить выполнение алгоритма.

Текст функции удаления приведен ниже:

 

Flight *Remove(Flight **head){

int N=GetNumFlight();//Ввод номера удаляемого рейса

Flight *prev;

Flight *pv=FindNum(head,N, &prev);

if (pv){ //Если удаляемый элемент найден

if (pv==head)

//Если удаление из начала списка

head=head->Next;

else

//Удаление из середины или конца списка

prev->Next=pv->Next;

delete pv;

//Освобождение памяти из-под элемента

}

return head;

}

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

 

2.6. Распечатка базы данных

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

При выводе на экран используется форматированный вывод. Сначала выводится шапка таблицы, в которой задано количество символов в каждом поле. Далее с помощью метода setw(int) указывается ширина каждого поля. Если данный метод не указывается, то ширина поля таблицы равна количеству выводимых символов. С помощью специального символа “\t” осуществляется табуляция (переход) к следующему полю записи базы данных. Количество символов, указанное в каждом частном случае вызова метода setw(int) посчитано в соответствии с количеством символов в шапке таблицы.

 

// ******************* Вывод базы на экран *************************************

void Print (Flight *head){

//Перейти в голову списка

Flight* pv=head;

//Вывести шапку таблицы БД

cout<<"----------------------------------------------------------------------------\n";

cout<<"|Номер |\t Направление |\t Вылет |\t В пути (мин) |\t Своб.мест |\n";

cout<<"----------------------------------------------------------------------------\n";

//Просмотреть последовательно весь список и вывести его на экран построчно

//функция setw(N) используется, чтобы установить ширину табличного поля (в символах)

// символ - "\t" - табуляция

while (pv){

cout<<"|"<<setw(5)<<(pv->Num)<<"|\t"<<setw(20)<<(pv->Destination);

cout<<"|\t"<<(pv->Dep.hr)<<":"<<(pv->Dep.min);

cout<<"\t|"<<setw(20)<<(pv->way)<<"|\t"<<(pv->FreePlace)<<"\t|\n";

cout<<"----------------------------------------------------------------------------\n";

pv=pv->Next;

}

}

 

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

 

//****************** Вывод базы в файл *****************************************

void FilePrint (char *FileName, Flight *head){

//Открыть файл с именем, хранящимся в переменной FileName для перезаписи.

//Будем работать с выходным потоком

ofstream out;

out.open(FileName);

//Если не удалось открыть файл - сообщить об ошибке

if (!out){

cout<<"Ошибка открытия файла\n";

return;

}

//Перейти в голову списка

Flight* pv=head;

//Вывести последовательно все записи из списка в файл. Оформление отсутствует

while (pv){

out<<(pv->Num)<<"\t"<<(pv->Destination)<<"\t"<<(pv->Dep.hr)<<" "<<(pv->Dep.min);

out<<"\t"<<(pv->way)<<"\t"<<(pv->FreePlace)<<"\n";

pv=pv->Next;

}

//Закрыть файл

out.close();

}

 

2.7. Извлечение информации из базы данных по критерию

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

// ************** Поиск рейса по месту назначения ******************************

void FindDestination (Flight *pv, char *Place){

cout<<"\n Найденные рейсы:\n";

while (pv){// Пока не достигли конца списка...

//Если название направления совпадает с тем, которое необходимо найти

if (strstr(pv->Destination,Place)){

// Вывести информацию на экран. Возврат из функции не осуществляется

// так как в одном направлении может быть несколько рейсов

cout<<(pv->Num)<<" "<<(pv->Destination)<<" "<<(pv->Dep.hr)<<" "<<(pv->Dep.min);

cout<<" "<<(pv->way)<<" "<<(pv->FreePlace)<<"\n";

}

// Переход к следующему элементу списка

pv=pv->Next;

}

}

// *************** Поиск рейса по месту назначения и времени вылета ************

void FindTimeAndDestination (Flight *pv, char *Place, Time t){

while (pv){// Пока не достигли конца списка...

//Если название направления и время вылета совпадает с тем, что необходимо найти

if (strstr(pv->Destination,Place)&&(pv->Dep.hr==t.hr && pv->Dep.min==t.min)){

// Вывести информацию на экран. Возврат из функции не осуществляется

// так как в одном направлении может быть несколько рейсов в одно и то же время

//(хотя и маловероятно ^_^)

cout<<(pv->Num)<<" "<<(pv->Destination)<<" "<<(pv->Dep.hr)<<" "<<(pv->Dep.min);

cout<<" "<<(pv->way)<<" "<<(pv->FreePlace)<<"\n";

}

// Переход к следующему элементу списка

pv=pv->Next;

}

}

 

Для удобства работы с программой создана пользовательская функция, позволяющая выбрать критерий для поиска в базе данных. Эта функция выводит на экран меню, где пользователю предлагается выбрать один из ключей поиска. Далее в соответствии с пользовательским выбором вызывается одна из описанных выше функций поиска по ключу либо осуществляется выход из меню.

// ******************** Функция поиска *****************************************

void FindFlight (Flight *head){

char B[cF]; //Временная переменная для ввода места назначения

//Объявляется в начале функции, т.к. она искользуется в 2 ветках switch

Time t; //Временная переменная для ввода времени вылета

int option; //Переменная, в которой сохраняется номер выбранного пункта меню

 

//Вывод меню на экран

cout<<"Выберите режим поиска:\n";

cout<<"1 - Поиск по месту назначения\n";

cout<<"2 - Поиск по месту назначения и времени вылета\n";

cout<<"0 - Выход из меню\n";

//Ввод с клавиатуры выбранного пункта

cin>>option;

//Обработка ввода и вызов соответствующих функций

switch (option){

case 0:{return;}

case 1: {

cout<<"Введите место назначения\n";

cin>>B;

FindDestination(head,B);

break;

}

case 2:{

cout<<"Введите место назначения\n";

cin>>B;

do{

cout<<"Введите время вылета\n";

cin>>t.hr>>t.min;

}while(t.hr>23||t.min>59);

FindTimeAndDestination(head,B,t);

break;

}

default: cout<<"Неверный режим\n";

}//switch

}

2.8. Изменение значений записей, существующих в базе данных

Программа позволяет осуществлять корректировку сведений двух типов:

1) покупка авиабилетов группой лиц;

2) корректировка времени вылета.

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

//****************** Покупка билета ********************************************

int BuyTicket(Flight * head){

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

int s; //Количество покупаемых билетов

N=GetNumFlight(); //Ввод номера рейса

// Поиск рейса по номеру

Flight *prev;

Flight *pv=FindNum(head,N,&prev);

//Если рейс не найден, прекратить выполнение функции

if (!pv) return 1;

//Оформление покупки билетов

cout<<"Сколько билетов куплено?\n";

cin>>s;

//Если количество приобретаемых билетов больше, чем количество свободных мест,

//сообщить клиенту о невозможности совершения покупки

if (s>pv->FreePlace)

cout<<"К сожалению, недостаточно свободных мест на рейсе.\n";

else{

//Оформить покупку и уменьшить количество доступных для продажи мест

cout<<"Поздравляем с покупкой!";

pv->FreePlace-=s;

}

return 0;

}

 

Для корректировки времени вылета необходимо ввести номер редактируемого рейса. Если в базе данных существует запись с указанным номером рейса, то для нее предлагается ввести новое время вылета. После корректного ввода информации (часа и минут вылета) найденная запись модифицируется. Текст функции редактирования времени вылета приведен ниже.

 

//****************** Корректировка сведений ************************************

int EditFlight(Flight * head){

int N=GetNumFlight(); //Ввести номер рейса

Time B; //Время вылета

//Поиск рейса по номеру

Flight *prev;

Flight *pv=FindNum(head,N,&prev);

//Если рейс не найден, прекратить выполнение функции

if (!pv) return 1;

//Корректировка времени вылета рейса

//Значения вводятся в цикле do...while до тех пор, пока они не будут введены

//корректно: часы <24, а минуты <60.

do{

cout<<"Введите новое время вылета\n";

cin>>B.hr>>B.min;

}while(B.hr>23||B.min>59);

//Сохранить введенные значения в соответствующее поле найденного элемента

pv->Dep=B;

return 0;

}




Поделиться с друзьями:


Дата добавления: 2014-11-25; Просмотров: 745; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.18 сек.