3.3.10 Описание работы основной программы
В основной программе происходит обращение к пользовательским функциям. Также основная программа обеспечивает вывод главного меню.
4. Инструкция по пользованию программой
При запуске программы на экране появляется графический интерфейс (главное меню программы). У пользователя появляется выбор в формировании списка: либо загрузить список авторов книг из файла (для чего выбирается пункт меню "2" – "Загрузить списки из файлов"), либо самостоятельно ввести его с клавиатуры (для чего выбирается пункт "1" главного меню). В первом случае должен иметься предварительный надел (заранее составленная база данных, записанная в файл). Во втором случае пользователю будет предложено ввести фамилию и инициалы автора книги, её название, год издания и количество в прокате. При завершении составления одной записи появляется строка, в которой пользователю предлагается заполнить ещё один элемент списка или выйти в главное меню. Для этого пользователь должен ввести соответственно слова "yes" или "no".
После выполнения операций создания списка пользователь может приступить к действиям над составленным списком.
Если пользователь выберет пункт "3" главного меню, то произойдёт сортировка базы данных по именам авторов в алфавитном порядке. В этом можно убедиться при выборе пункта "4", после чего на экран выводится содержимое всей базы данных.
Также пользователь может выдать книгу определённого автора на руки, вследствие чего количество книг в общей базе данных уменьшается на единицу. Это происходит при выборе пункта "8" главного меню. При выборе данной опции пользователю предлагается ввести фамилию и инициалы автора, а также название его книги. Если данная книга по картотеке не числится, то соответствующая строка упоминает об этом. При выборе пункта "5" на печать выводится список книг, которые были выписаны из картотеки. Книгу можно возвратить в библиотеку посредством пункта "9" главного меню. При выполнении данной операции пользователю предлагается ввести фамилию и инициалы автора, а также название книги. В случае неверного ввода программа извещает пользователя об этом.
Кроме того, пользователь может добавить новый элемент в список и записать полученные изменения в основную (файловую) базу данных. Достигается это посредством пунктов меню "6" и "10" соответственно. В первом случае будет предложено ввести фамилию и инициалы автора, наименование его книги, дату издания и количество доступных экземпляров, после чего выводится главное меню. Во втором случае появляется строка, уведомляющая о том, что запись в файл проведена успешно или нет в противном случае.
Помимо этого, пользователь может удалить все книги автора. Достигается это путём выбора пункта "7" главного меню. Предлагается ввести фамилию автора, а после ввода сообщается об удалении всех книг данного автора и приводится число таковых.
В заключение стоит отметить, что если ввести новые данные, а затем вызвать пункт 2 главного меню, то последние введённые данные будут безвозмездно потеряны.
При выборе пункта "11" графический интерфейс исчезает, процесс компиляции завершается.
5. Анализ результатов
В результате работы программы был сформирован список сведений о книгах картотеки, состоящий из фамилии автора, названия книги, года её выпуска и количества экземпляров в библиотеке. Полученный список был отсортирован методом простого выбора по фамилиям авторов.
Были добавлены новые элементы в основной список, при этом не был нарушен алфавитный порядок. Помимо основного списка был сформирован список с книгами, выданными на руки. При выдаче книги на руки количество книг в библиотеки сокращалось на 1. Оба эти списка были занесены в файлы. Кроме того, было реализовано решение задачи по возвращению взятой на руки книги.
Также была реализована возможность удаления всех книг автора из картотеки по его фамилии.
Блок-схемы алгоритмов программы и основных подпрограмм представлены в приложениях А, Б, В, Г. Листинг программы представлен в приложении Д, а результаты работы программы в приложении Е.
Заключение
В процессе выполнения индивидуального задания и отчета по курсовой работе я ознакомился со способами обработки динамических структур данных.
Анализируя полученное задание, я выбрал метод решения поставленной задачи, на основе которого получил алгоритмы в виде блок-схем (приложения А, Б, В, Г, Д). Преимущество блок-схем состоит в их наглядности. Кодирование алгоритмов осуществлено на языке программирования С. Листинг программы представлен в приложении Д.
Преимущество программы состоит в простой организации пользовательского интерфейса, в удобстве ввода сведений авторах и книгах. Программа сортирует список по имени автора в алфавитном порядке, позволяет выдать книгу на руки, вернуть её назад в библиотеку и удалить все книги выбранного автора из картотеки. Возможно, что применение данной программы на практике (в существенно более доработанной форме) может оптимизировать работу персонала библиотек или учреждений, в которых требуется работа с большими базами данных.
Недостатки программы:
- на разных ЭВМ работа с файлами осуществляется по-разному. То есть при работе на одном ЭВМ задача может идеально реализовываться, а на другом выполняться, но с ошибками. Скорее всего, это вызвано разницей в версиях ТС или недоработкой разработчиков.
- при вводе в командной строке меню некорректных данных, для которых не предусмотрены действия, программа работать не будет, а в некоторых случаях возможно зацикливание, что может привести как к выходу из процесса компиляции, так и к полному выходу из интегрированной среды программирования с потерей текущих данных, что нежелательно.
Список литературы
1. Н. Б. Культин, С/С++ в задачах и примерах, СПб: БХВ-Петербург, 2001.
2. А. Б. Крупник, Изучаем С++, Спб: Питер, 2003.
3. С. Р. Дэвис, С++ для "чайников", М.: "Вильямс", 2004.
4. Т.А. Павловская, С/С++. Программирование на языке высокого уровня, Спб: Питер, 2005.
Приложение А
Листинг программы
#include <stdio.h>
#include <alloc.h>
#include <conio.h>
#include <string.h>
typedef struct AsFalonour //создание нового типа запись для хранения информационных полей элемента списка
{
int kol; //количество книг в картотеке
char nazv[20]; //название книги
int god; //год издания
char avt[20]; //фамилия автора книги
} book; //имя созданного типа
typedef struct spisok //создание нового типа запись для хранения информации элемента списка
{
book inf; //информационные поля
struct spisok* next; //указатель на следующий элемент списка
struct spisok* pred; //указатель на предыдущий элемент списка
} el; //имя созданного нового типа
//-------------------------------------------------------------\\
el* vvodSp(el **top2) //создание списка
{
char s[3]={'y','e','s'}; //переменная для хранения ответа на вопрос о продолжении ввода списка
el *cur,*pr,*top,*tail,*tail2,*cur2; //указатель
clrscr();
*top2=top=tail=tail2=NULL; //обнуление указателей на начало и хвост списков
printf("Введите первую запись\n");
while(strcmp(strlwr(s),"no")!=0) //пока ответ не равен no
{
cur=(el*)malloc(sizeof(el)); //выделяем память под новый элемент (далее текущий)
cur->next=NULL; //обнуление указателя на следующий элемент текущего элемента
cur->pred=tail; //указатель на предыдущий элемент текущего элемента присваивается хвосту списка
if(top==NULL) top=cur; //если указатель на начало списка пуст то указателем на начало списка становится текущий элемент
else tail->next=cur; //если нет, то указателем на хвост списка становится текущий элемент
tail=cur; //указатель на хвост приравнивается текущему элементу
cur2=(el*)malloc(sizeof(el)); //выделяется память под новый элемент второго списка, выполняются те же действия
cur2->next=NULL;
cur2->pred=tail2;
if((*top2)==NULL) (*top2)=cur2; // *top2 это указатель на указатель
else tail2->next=cur2;
tail2=cur2;
printf("Введите фамилию и инициалы автора:\n"); //ввод информационных полей
scanf("%s",cur->inf.avt);
printf("Введите название книги:\n");
scanf("%s",cur->inf.nazv);
printf("Введите год издания книги:\n");
scanf("%d",&cur->inf.god);
while(cur->inf.god<0)
{
printf("Год издания не может быть отрицательным числом! Введите повторно!\n"); //проверяется, положителен ли год
scanf("%d",&cur->inf.god); //повторный ввод
}
printf("Введите количество экземпляров книги:\n"); //аналогичное с количеством
scanf("%d",&cur->inf.kol);
while(cur->inf.kol<0)
{
printf("Количество книг не может быть отрицательным числом! Введите повторно!\n");
scanf("%d",&cur->inf.kol);
}
cur2->inf=cur->inf; //копировние информационных полей элемента первого списка в элемент второго списка
cur2->inf.kol=0; //количество выданных книг в начале равно 0
printf("Введете еще одну запись?(для выхода напишите no; для продолжения-yes)\n");
scanf("%s",s);
while(strcmp(strlwr(s),"no")!=0&&strcmp(strlwr(s),"yes")!=0) //пока не введён правильный вариант
{
printf("Вы неверно ввели свой выбор, введите, пожалуйста, его еще раз\n");
scanf("%s",s); //повторный ввод
}
}
return top; //возвращение указателя на начало первого списка
}
//-----------------------------------------------------\\
void vivodSp(el *cur) //вывод списка
{
clrscr();
printf("Текущий список:\n");
if(cur==NULL) printf("Перед тем, как выводить список, необходимо его создать!");
else
{
printf("Фамилия автора\tНазвание книги\tГод издания\tКоличество экземпляров\n");
while(cur!=NULL) //печать списка пока не достигнут конец списка, если количество книг больше нуля (нужно для второго списка)
{
if(cur->inf.kol>0) printf(" %s\t\t\t%s\t %d\t\t\t %d\n",cur->inf.avt,cur->inf.nazv,cur->inf.god,cur->inf.kol);
cur=cur->next; //переход к следующему элементу
}
}
getch();
}
//--------------------------------------------------------------\\
void vidacha(el *cur,el *cur2)
{
char iskA[10],iskN[10];
int n=0; //результат поиска
clrscr();
if(cur==NULL) printf("Перед тем, как производить выдачу книг, необходимо создать список!");
else
{
printf("Введите интересующего Вас автора:\n"); //ввод искомого автора и книги
scanf("%s",iskA);
printf("Введите интересующую Вас книгу:\n");
scanf("%s",iskN);
while(cur!=NULL) //пока не конец списка
{
if((strcmp(cur->inf.avt,iskA)==0)&&(strcmp(cur->inf.nazv,iskN)==0)&&cur->inf.kol>0) //если элемент содержит сведения о нужной книге и есть свободные в наличии
{
cur->inf.kol--; //уменьшаем количество в первом списке
cur2->inf.kol++; //и увеличиваем во втором
n++; //поиск успешен
printf("Книга выдана на руки!");
break; //конец поиска
}
else if((strcmp(cur->inf.avt,iskA)==0)&&(strcmp(cur->inf.nazv,iskN)==0)&&cur->inf.kol==0) //если свободных нет
{
printf("Все книги находятся на руках!");
n++; //поиск успешен
break; //конец поиска
}
cur=cur->next; //переход к следующем элементу
}
if(n==0) printf("Такой книги вообще нет!");
}
getch();
}
//---------------------------------------------------------------------\\
void dobEl(el *cur, el *cur2) //добавление нового элемента
{el *x,*x2;
clrscr();
if(cur==NULL) printf("Перед тем, как добавлять элементы в список, необходимо его создать!");
else
{
while(cur->next!=NULL) cur=cur->next; //поиск конца списка
while(cur2->next!=NULL) cur2=cur2->next; //аналогично со вторым
x=(el*)malloc(sizeof(el)); //выделение памяти под новый элемент
x2=(el*)malloc(sizeof(el)); //аналогичный действия для второго списка
printf("Введите данные на новый элемент:\n"); //ввод информационных полей
printf("Введите фамилию и инициалы автора:\n");
scanf("%s",x->inf.avt);
printf("Введите название книги:\n");
scanf("%s",x->inf.nazv);
printf("Введите год издания книги:\n");
scanf("%d",&x->inf.god);
while(x->inf.god<0)
{
printf("Год издания не может быть отрицательным числом! Введите повторно!\n");
scanf("%d",&x->inf.god);
}
printf("Введите количество экземпляров книги:\n");
scanf("%d",&x->inf.kol);
while(x->inf.kol<0)
{
printf("Количество книг не может быть отрицательным числом! Введите повторно!\n");
scanf("%d",&x->inf.kol);
}
x2->inf=x->inf; //копирование информационных полей
x2->inf.kol=0; //в начале количество выданных книг-0
printf("Новый элемент добавлен!\n");
x->next=NULL; //обнуление указателя на следующий элемент добавляемого элемента
cur->next=x; //последний (пока что последний)элемент списка указывает на следующий элемент (добавляемый)
x->pred=cur; //указатель на предыдущий элемент нового элемента равен последнему
cur=x; //теперь добавленный элемент-последний
x2->next=NULL; //аналогично для второго списка
cur2->next=x2;
x2->pred=cur2;
cur2=x2;
}
}
//---------------------------------------------------------------------\\
void delel(el **top,el **top2) //удаление элементов
{
el *cur=*top,*cur2=*top2; //текущие указатели списков равны указателям на вершины списков
int n=0; //результат поиска
char isk[20]; //фамилия искомого автора
clrscr();
if(cur==NULL) printf("Перед тем, как удалять элементы из списка, создайте его!\n");
else
{
printf("Введите фамилию автора, книги которого должны быть удалены:\n");
scanf("%s",isk); //ввод фамилии искомого автора(он же удаляемый)
while(cur!=NULL) //пока не конец списка
{
if(strcmp(cur->inf.avt,isk)==0) //если фамилия автора у элемента совпадает с введенной
{
n++; //поиск успешен
if(cur==*top) //если удаляемый элемент-вершина
{
*top=(*top)->next; //вершиной становится следующий элемент
cur->next->pred=NULL;и //обнуление указателя новой вершины на предыдущий элемент
free(cur); //освобождение памяти под старую вершину
*top2=(*top2)->next; //по аналогии для второго
cur2->next->pred=NULL;
free(cur2);
}
else if(cur->next==NULL) //если это-последний элемент списка
{
cur->pred->next=NULL; //ссылка предпоследнего элемента на следующий обнуляется
free(cur); //память под старый конец списка освобождается
cur2->pred->next=NULL; //аналогично для второго
free(cur2);
}
else {
cur->next->pred=cur->pred; //ссылка на следующий элемент у предыдущего элемента (относительно удаляемого) приравнивается следующем элементу
cur->pred->next=cur->next; //ссылка на предыдущий элемент у следующего элемента (относительно удаляемого) приравнивается предыдущему элементу
free(cur); //память освобождается
cur2->next->pred=cur2->pred; //то же для второго
cur2->pred->next=cur2->next;
free(cur2);
}
}
cur=cur->next; //переход к следующему элементу
cur2=cur2->next; //аналогично
}
printf("Было удалено %d книг данного автора",n);
}
getch();
}
//---------------------------------------------------------------------\\
void vozvrat(el *cur,el *cur2) //возвращение элемента
{
char iskA[10],iskN[10];
int n=0;
clrscr();
if(cur==NULL) printf("Перед тем, как производить поиск в списке, необходимо его создать!");
else
{
printf("Введите интересующего Вас автора:\n");
scanf("%s",iskA);
printf("Введите интересующую Вас книгу:\n");
scanf("%s",iskN);
while(cur!=NULL)
{
if((strcmp(cur->inf.avt,iskA)==0)&&(strcmp(cur->inf.nazv,iskN)==0)&&cur2->inf.kol>0) //если есть книги на руках (кол-во>0)
{
cur->inf.kol++; //увеличивается в первом списке количество
cur2->inf.kol--; //уменьшается во втором
n++;
printf("Книга возвращена!");
break;
}
else if((strcmp(cur->inf.avt,iskA)==0)&&(strcmp(cur->inf.nazv,iskN)==0)&&cur2->inf.kol<=0) //если книг на руках нет
{
printf("Все свои книги дома! Чужих нам не надо)))");
n++;
break;
}
cur=cur->next;
cur2=cur2->next;
}
if(n==0) printf("К сожалению, ни одной такой книги не найдено!\n");
}
getch();
}
//---------------------------------------------------------------------\\
void sort(el *top) //сортировка
{
int k=1; //вспомогательный элемент, показывает были ли перестановки или нет
el* cur; //указатель на текущий элемент
book dop; //переменная для временного хранения данных (используется при сортировке)
clrscr();
if(top==NULL) printf("Перед тем, как сортировать список, необходимо его создать!");
else
{
while(k!=0) //пока не будет перестановок
{
k=0; //перстановок нет
for(cur=top;cur->next!=NULL;cur=cur->next) //пока указатель на следующий элемент у текущего не равен NULL
if(strcmp(cur->inf.avt,cur->next->inf.avt)>0) //если следующий элемент меньше, чем текущий
{
dop=cur->inf; //занесение в буфер данных текущего элемента
cur->inf=cur->next->inf; //переписывание в текущий данные следующего
cur->next->inf=dop; //переписывание в следующий данные из буфера
k=1; //перестановки есть
}
}
}
}
//---------------------------------------------------------------------\\
void saveIT(el *cur,el *cur2) //сохранение в файл
{
FILE *f1,*f2; //файлы
f1=fopen("Base.txt","wb"); //файл для первого списка
f2=fopen("Out.txt","wb"); //для второго
if(f1==NULL||f2==NULL) printf("Чтоё-то не грузится: глюк)");
else
{
while(cur!=NULL) //пока не конец списка
{
fwrite(&cur->inf,sizeof(el),1,f1); //запись данных текущего элемента в файл
fwrite(&cur2->inf,sizeof(el),1,f2); //то же
cur=cur->next; //переход к следующему элементу
cur2=cur2->next; //то же
}
printf("Списки сохранены успешно!");
fcloseall(); //закрытие файлов
}
getch();
}
//---------------------------------------------------------------------\\
void loadIT(el **top,el **top2) //чтение файлов
{
el *cur,*pr,*tail,*tail2,*cur2; //указатели
FILE *f1,*f2; //файлы
clrscr();
*top2=*top=tail=tail2=NULL; //обнуление ссылок на хвост и вершину
f1=fopen("Base.txt","rb"); //открытие файла Base.txt
f2=fopen("Out.txt","rb"); //открытие файла Out.txt
if(f1==NULL||f2==NULL) printf("Чтоё-то не грузится: глюк)");//если файлов нет
else
{
while(!feof(f1)) //пока не конец файла
{
cur=(el*)malloc(sizeof(el)); //выделение памяти под новый элемент (далее текущий)
cur->next=NULL; //обнуление указателя на следующий элемент текущего элемента
cur->pred=tail; //присваивание указателя на предыдущий элемент текущего элемента хвосту списка
if((*top)==NULL) (*top)=cur; //если указатель на начало списка пуст, то указателем на начало списка становится текущий элемент
else tail->next=cur; //если нет, то указателем на хвост списка становится текущий элемент
tail=cur; //указатель на хвост становится приравнивается текущему элементу
cur2=(el*)malloc(sizeof(el)); //аналогично для второго элемента
cur2->next=NULL;
cur2->pred=tail2;
if((*top2)==NULL) (*top2)=cur2;
else tail2->next=cur2;
tail2=cur2;
fread(&cur->inf,sizeof(el),1,f1); //считывание с файла
fread(&cur2->inf,sizeof(el),1,f2);
}
fcloseall(); //закрываем файлы
printf("Списки успешно загружены из файлов!");
}
getch();
}
//---------------------------------------------------------------------\\
void main() //основная программа
{
int n=0;
el *top=NULL,*top2=NULL;
while(n!=11)
{
clrscr();
printf("Введите номер пункта для выполнения:\n");
printf("1.Заполнить список\n");
printf("2.Загрузить списки из файлов\n");
printf("3.Отсортировать текущий список\n");
printf("4.Вывести текущий список\n");
printf("5.Вывести текущий список выданных на руки книг\n");
printf("6.Добавить новый элемент\n");
printf("7.Удалить из списка книги заданного автора\n");
printf("8.Выдать книгу на руки\n");
printf("9.Вернуть книгу в библиотеку\n");
printf("10.Сохранить списки в файл\n");
printf("11.Выход из программы\n");
printf("Ваш выбор:\n");
scanf("%d",&n);
while(n>11||n<1)
{
printf("Такого пункта нет! Введите повторно:\n");
scanf("%d",&n);
}
if(n==1) top=vvodSp(&top2);
else if(n==2) loadIT(&top,&top2);
else if(n==3) {sort(top); sort(top2);}
else if(n==4) vivodSp(top);
else if(n==5) vivodSp(top2);
else if(n==6) {dobEl(top,top2); sort(top); sort(top2);}
else if(n==7) delel(&top,&top2);
else if(n==8) vidacha(top,top2);
else if(n==9) vozvrat(top,top2);
else if(n==10) saveIT(top,top2);
}
}
Приложение Б
Результаты работы программы
... "nсреднее целое равно " << MidInt / double(NMax) << "n"; cout << "среднее вещественное равно: " << MidReal / n << "n"; fclose(t); } Списки Обсудим вопрос о том, как в динамической памяти можно создать структуру данных переменного размера. Разберем следующий пример. В процессе физического эксперимента многократно снимаются показания прибора (допустим, термометра) ...
... . Несет информацию об адресе текущего элемента однонаправленного динамического списка. q – указатель на структуру news. Несет информацию об адресе последнего созданного элемента однонаправленного динамического списка. news *un,*p,*q; i – переменная типа int. Несет информацию о количестве элементов однонаправленного динамического списка. int i; 4 2) Локальные переменные процедуры ...
... ; очистка памяти от стека; вывод на экран всех значений списка; проверка о переполнении стек; вывод сообщения на экран о переполнении стека. 1.1 Описание структуры данных "стек" Стеком называется динамическая структура данных, добавление компоненты в которую и исключение компоненты из которой производится из одного конца, называемого вершиной стека. Стек работает по принципу LIFO (Last ...
... с адресом р. В повседневной практике средства работы с адресами используются довольно редко. Основное назначение указателей состоит в том, чтобы обеспечить механизм использования в программе динамических переменных. Этот механизм мы и будем обсуждать подробно в следующих разделах. 1.2. Описание указателей В Pascal имеются два различных вида указателей: типизированные и нетипизированные. ...
0 комментариев