Логика работы программы. Схема алгоритма функции main().
Исходя из того, что в программе необходимо предусмотреть запись базы в файл, вытекает следующее:
- у пользователя должна быть возможность изначально выбрать один из двух вариантов: либо работать с базой, записанной в файл, либо создать новую базу и работать с ней;
- меню для работы с базой, собственно как и все действия над ней, должно быть одинаковым вне зависимости от того, работает пользователь с вновь созданной базой, или же с базой из файла.
Исходя из этого, следует, что нам необходимо минимум 2 меню:
№1 - выбор варианта работы с базой;
№2 - выбор действия над базой.
Меню №1 можно оформить в функции «main()».Второе меню логичнее оформить в виде отдельной функции, т. к. его вызов происходит как минимум из двух точек программы.
Схема меню №1:
--------------------------------
МЕНЮ
--------------------------------
1: Создать новую базу сотрудников;
2: Открыть существующую базу;
3: Выход из программы
--------------------------------
Данное меню организовано в функции “main()”. В начале программы объявляются массивы структур и указателей. Далее вызывается следующая функция:
void NullWork(Worker work[],Worker *loc_number[],const int n).
Данная функция присваивает нулевые значения полям структур, массив которых создается в начале программы, а также связывает массив указателей и массив структур. В качестве параметров принимает массив структур, массив указателей на структуры и целое число, которое является размером массива.
Далее пользователю предлагается выбрать один из 3-х пунктов меню №1. Корректность ввода пользователя проверяет следующая функция:
int EnterMenu(const int size_menu).
Принимает целое число - соответствующее последнему пункту меню, из которого вызывается. Возвращает целое число – соответствующее пункту меню, или 0 в случае некорректного ввода.
В случае выбора пункта №3 меню №1происходит выход из программы.
В случае выбора пункта №2 меню №1вначале происходит вызов функции:
bool ExtMm(Worker work[],Worker *loc_number[],const int n).
Данная функция запрашивает пользователя ввести имя файла, в котором сохранена база. Далее ведется поиск файла. В случае успеха, функция копирует содержимое файла в массив структур, созданный в начале программы, и сортирует массив указателей в соответствии с фамилиями сотрудников. Возвращаемое значение – true. В случае неудачного поиска возвращаемое значение – false. В качестве параметров принимает массив структур, массив указателей на структуры и целое число, которое является размером массива.
В случае выбора пункта №1 или пункта №2 меню №1 управление в конечном итоге передается функции:
void MainMenu(Worker[],Worker *[],const int).
Данная функция выводит на экран и обрабатывает меню №2. В качестве параметров принимает массив структур, массив указателей на структуры и целое число, которое является размером массива. Из этой функции происходит вызов функций, соответствующих определенным пунктам меню. В конце этой функции происходит «обнуление» полей массива структур, чтобы можно было использовать его для создания новой базы.
Схема алгоритма функции int main():
Схема алгоритма функции void NullWork(Worker[],Worker *[],const int ):
Схема алгоритма функции int EnterMenu(const int):
Схема алгоритма функции bool ExtMm(Worker[],Worker[],const int ):
Схема алгоритма void MainMenu(Worker[],Worker *[],const int):
Схема меню №2:
------------------------------
ОСНОВНОЕ МЕНЮ
------------------------------
1: Добавить сотрудника в базу;
2: Удалить сотрудника из базы;
3: Информация о сотрудниках;
4: Сохранить базу сотрудников;
5: Назад;
------------------------------
1: Добавить сотрудника в базу – вызов функции:
void AddMm(Worker work[],Worker *loc_number[],const int n).
Принимаемые параметры: массив структур, массив указателей на структуры и целое число, которое является размером массива. Функция ищет свободное место в массиве структур. В случае удачного поиска, функция запрашивает ввод фамилии и зарплаты сотрудника, после чего записывает данные в соответствующие поля свободной структуры. Если же поиск положительного результата не дал, то выводится соответствующее сообщение, после чего функция заканчивает свою работу. После записи функция производит сортировку массива указателей. Для этого вызывается дополнительная функция:
bool SortWork(char str1[],char str2[]).
В качестве параметров – две строки (фамилии сотрудников) которые необходимо сравнить. Возвращает «true», если str1[] > str2[],или «false», если str1[] <= str2[].
2: Удалить сотрудника из базы – вызов функции:
void DelMm(Worker *loc_number[],const int n).
Принимаемые параметры: массив указателей на структуры и целое число, которое является размером массива. Функция предлагает пользователю ввести фамилию сотрудника, которого он хочет удалить из базы, и ищет его в массиве структур. В случае удачного поиска, функция удаляет информацию из соответствующих полей структуры, а полю “bе” присваивает значение “false”. Если же поиск положительного результата не дал, то выводится соответствующее сообщение, после чего функция заканчивает свою работу.
4: Сохранить базу сотрудников – вызов функции:
void SaveMm(Worker work[],const int n).
Принимаемые параметры: массив структур и целое число, которое является размером массива. Функция запрашивает пользователя ввести имя файла, после чего записывает в него массив структур. Если файл существует, он переписывается, если не существует – создается.
5: Назад - вызов функции:
bool ExitMm(bool save).
Суть данной функции в том, чтобы убедиться: сохранял ли пользователь базу в файл, или нет. Таким образом, можно предупредить потерю данных. Дополнительная переменная “bool save” принимает значение “true” лишь в том случае, когда непосредственно перед выходом из меню №2 был выбран пункт меню “4: Сохранить базу сотрудников”. В противном случае ее значение “false”. В зависимости от того, какое значение имеет переменная “bool save”, происходит либо выход из меню, либо вывод сообщения о том, что база не сохранена и предложение либо “назад” в меню, либо“ выход” из меню:
------------------
1: Назад;
2: Выход;
------------------
3: Информация о сотрудниках – вызов функции:
void InformMm(Worker *loc_number[],const int n).
Данная функция выводит на экран и обрабатывает следующее меню:
-----------------------------------
МЕНЮ
-----------------------------------
1: Вывод сотрудников на экран;
2: Суммарный заработок сотрудников;
3: Сотрудник с наибольшей зарплатой;
4: Назад;
-----------------------------------
Возможности этой функции таковы:
- вывод отсортированного по фамилиям списка сотрудников с их зарплатами на экран;
- вывод на экран суммарного заработка сотрудников;
- вывод на экран сотрудника с наибольшей зарплатой.
Схема алгоритма void AddMm(Worker[],Worker *[],const int ):
Схема алгоритма bool SortWork(char str1[],char str2[]):
Схема алгоритма void DelMm(Worker *[],const int ):
Схема алгоритма void SaveMm(Worker [],const int):
Схема алгоритма bool ExitMm(bool save):
Схема алгоритма void InformMm(Worker *[],const int ):
Руководство пользователя
Для запуска программы необходимо выбрать файл “Курсовой проект.exe”. После запуска программы пользователю открывается МЕНЮ и предоставляется возможность либо создать новую базу сотрудников (пункт 1), либо открыть существующую базу, записанному в некотором файле (пункт 2). Также пользователь может выйти из программы (пункт 3).
Для выбора определенного пункта меню необходимо ввести с клавиатуры соответствующую цифру и нажать ENTER. При вводе с клавиатуры недопустимых символов, на экран выводится соответствующее сообщение. Если при вводе, первой была нажата допустимая цифра, а после недопустимые символы, то ввод будет обработан успешно.
После выбора пункта 2, пользователю необходимо ввести имя файла, в котором ранее была сохранена база сотрудников. Файл должен находиться в том же каталоге, что и программа, иначе он не будет найден.
После открытия файла с базой сотрудников, или же после выбора пункта 1 пользователь попадает в ОСНОВНОЕ МЕНЮ, которое предоставляет следующие возможности для работы с базой:
- (пункт 1) – добавить сотрудника в базу;
- (пункт 2) – удалить сотрудника из базы;
- (пункт 3) – просмотреть информацию о сотрудниках;
- (пункт 4) – сохранить базу сотрудников в файл;
- (пункт 5) – назад в МЕНЮ.
Добавление сотрудников в базу возможно лишь в том случае, если в базе есть место (база может содержать до ста элементов). Если свободного места нет, на экран выводится соответствующее сообщение и происходит возврат в ОСНОВНОЕ МЕНЮ.
Имеется возможность сохранения базы сотрудников в файл. Для этого необходимо выбрать пункт 4, после чего ввести имя файла.
Выбрав пункт 5, производится проверка: имело ли место сохранение базы в файл непосредственно перед выходом в МЕНЮ.Если непосредственно перед выходом в МЕНЮсохранение базы сотрудников в файл не производилось, на экран выводится соответствующее сообщение и предлагается выбор:
- (пункт 1) – назад в ОСНОВНОЕ МЕНЮ;
- (пункт 2) – выход в МЕНЮ.
Таким образом, предотвращается потеря данных.
Выбрав пункт 3 ОСНОВНОГО МЕНЮ можно выполнить следующие действия:
- (пункт 1) – вывод информации о сотрудниках на экран;
- (пункт 2) – вывод на экран суммарной зарплаты сотрудников;
- (пункт 3) – вывод на экран сотрудника с наибольшей зарплатой;
- (пункт 4) – назад в ОСНОВНОЕ МЕНЮ.
Заключение
Тестирование программы показало ее надежную работоспособность. Все пункты меню работают правильно. Вывод информации о сотрудниках на экран производится в соответствии с заданием. Запись в файл и чтение из файла происходит без ошибок.
Учитывая то, что практически вся работа в программе возложена на функции, программа имеет хороший потенциал для дальнейшей модернизации.
Литература
1. С/С++. Программирование на языке высокого уровня / Т. А. Павловская. – СПб.: Питер, 2012. – 461с.: ил.
2. Объектно- ориентированное программирование в С++ 4-е изд. / Р. Лафоре. – СПб.: Питер, 2012. - 928с.: ил.
Приложение 1. Листинг программы
“stdafx.h”
#include<conio.h>
#include<fstream>
#include<iostream>
#include<iomanip>
using namespace std;
struct Worker{
char surname[20]; //фамилия
double salary; //зарплата
bool be; //дополнительное поле. по нему будем определять
//существует ли структура
};
//функция выводит на экран и обрабатывает основное меню
void MainMenu(Worker work[],Worker *loc_number[],const int n);
//функция проверяет является ли символ, введенный пользователем, пунктом меню
//const int size_menu максимальное значение, предусмотренное меню
int EnterMenu(const int size_menu);
//функция добавляет в базу нового сотрудника
void AddMm(Worker work[],Worker *loc_number[],const int n);
//функция удаляет из базы сотрудника
void DelMm(Worker *loc_number[],const int n);
//выводит на экран информацию о сотрудниках
void InformMm(Worker *loc_number[],const int n);
//сохраняет базу сотрудников в файл
void SaveMm(Worker work[],const int n);
//извлекает базу сотрудников из файл
bool ExtMm(Worker work[],Worker *loc_number[],const int n);
//сравнивает фамилии сотрудников для сортировки по фамилии
bool SortWork(char str1[],char str2[]);
//функция проверяет была ли база сохранена в файл. возвращает истину,
//если ее необходимо повторно сохранить
bool ExitMm(bool save);
//массиву Worker присваиваем нулевые значения
void NullWork(Worker work[],Worker *loc_number[],const int n);
“stdafx.cpp”
#include "stdafx.h"
void MainMenu(Worker work[],Worker *loc_number[],const int n){
bool save=false; //для определения имело ли место сохранение базы
enum CHOISE_MM {add_mm=1,del_mm,inform_mm,save_mm,exit_mm};
int point_mm;
do{
cout<<"------------------------------"<<endl;
cout<<" ОСНОВНОЕ МЕНЮ "<<endl;
cout<<"------------------------------"<<endl<<endl;
cout<<"1: Добавить сотрудника в базу;"<<endl<<endl;
cout<<"2: Удалить сотрудника из базы;"<<endl<<endl;
cout<<"3: Информация о сотрудниках;"<<endl<<endl;
cout<<"4: Сохранить базу сотрудников;"<<endl<<endl;
cout<<"5: Назад;"<<endl<<endl;
cout<<"------------------------------"<<endl<<endl;
point_mm=EnterMenu(exit_mm);
switch(point_mm){
case 0:
break;
case add_mm:
AddMm(work,loc_number,n);
save=false;
break;
case del_mm:
DelMm(loc_number,n);
save=false;
break;
case inform_mm:
InformMm(loc_number,n);
break;
case save_mm:
save=true;
SaveMm(work,n);
break;
case exit_mm:
if(ExitMm(save)) point_mm=0;
break;
}
}while(point_mm!=exit_mm);
NullWork(work,loc_number,n);
system("cls");
return;
}
int EnterMenu(const int size_menu){
int i=0;
char ent[20];
//необходимо обработать не все символы, введенные пользователем, а лишь первый, для даль- //нейшего определения,
// является ли он цифрой
cin>>ent;
i=atoi(&ent[0]);
if ((i<1)||(i>size_menu)){
cout<<ent<<" -не является пунктом меню. Для продолжения нажмите любую клавишу ";
_getch();
i=0;
}
system("cls");
return i;
}
void AddMm(Worker work[],Worker *loc_number[],const int n){
Worker *work_buf=0;
//введем переменную типа bool для определения есть ли свободное место в базе данных
bool place=false;
int i=0,k=0;
for(i=0;i<n;i++){
if (work[i].be==false){
place=true; //место есть
break;
}
}
//по итогу цикла for переменная place = true в том случае если в базе есть места //или база совсем пуста.
//в этом случае условие будет loc_number[0]==0
if (!place){
cout<<"Добавление сотрудника невозможно. База переполненна!"<<endl;
_getch();
system("cls");
return;
}
//-----------------------------------------------------------------------------
cout<<"Введите фамилию работника: ";
cin>>work[i].surname;
cout<<"Введите зарплату работника: ";
cin>>work[i].salary;
work[i].be=true;
//производим сортировку массива указателей
for(i=1;i<n-1;i++){
for(k=0;k<n-i;k++){
if(SortWork((*loc_number[k]).surname,(*loc_number[k+1]).surname) && ((*loc_number[k+1]).be==true)){
work_buf=loc_number[k];
loc_number[k]=loc_number[k+1];
loc_number[k+1]=work_buf;
}
}
}
system("cls");
return;
}
bool SortWork(char str1[],char str2[]){
int i=0;
do{
if(str1[i]>str2[i]) {
return true;
break;
}else if(str1[i]<str2[i]) break;
i++;
}while((str1[i]!='\0')&&(str2[i]!='\0'));
return false;
}
void DelMm(Worker *loc_number[],const int n){
bool is=false;
char del_surname[20];
unsigned int i=0,k=0;
cout<<"Введите фамилию сотрудника, которого хотите удалить из базы: ";
cin>>del_surname;
do{
if((*loc_number[i]).be){ //ведем поиск сотрудника по фамилии
for(k=0;k<strlen(del_surname);k++){
if(del_surname[k]!=(*loc_number[i]).surname[k]){
is=false; //в случае несовпадения одной буквы
break;
}else is=true; //is=true - фамилии совпали
}
if(is) break;
}
i++;
}while(static_cast<int>(i)<n);
if(!is){
cout<<"Сотрудника по фамилии "<<del_surname<<" в базе не существует ";
_getch();
cout<<endl;
}
if(is){
strcpy_s((*loc_number[i]).surname,"0");
(*loc_number[i]).salary=0;
(*loc_number[i]).be=false;
}
system("cls");
}
void SaveMm(Worker work[],const int n){
char name[20];
cout<<"Введите имя файла в котором вы хотите сохранить базу сотрудников: ";
cin>>name;
ofstream fptr(name);
for(int i=0;i<n;i++){
if(work[i].be){
fptr.write(reinterpret_cast<char*>(&work[i].be),sizeof(bool));
fptr.write(work[i].surname,20);
fptr.write(reinterpret_cast<char*>(&work[i].salary),sizeof(double));
}
}
fptr.close();
system("cls");
return;
}
bool ExtMm(Worker work[],Worker *loc_number[],const int n){
Worker *work_buf=0;
char data_base[20];
cout<<"Введите имя файла в котором содержится база сотрудников: ";
cin>>data_base;
ifstream fptr;
fptr.open(data_base);
if(!fptr){
cout<<"Базы сотрудников с именем \""<<data_base<<"\" не существует! "<<endl;
_getch();
system("cls");
return false;
}
for(int i=0;i<n;i++){
fptr.read(reinterpret_cast<char*>(&work[i].be),sizeof(bool));
fptr.read(work[i].surname,20);
fptr.read(reinterpret_cast<char*>(&work[i].salary),sizeof(double));
}
fptr.close();
//производим сортировку массива указателей
for(int i=1;i<n-1;i++){
for(int k=0;k<n-i;k++){
if(SortWork((*loc_number[k]).surname,(*loc_number[k+1]).surname) && ((*loc_number[k+1]).be==true)){
work_buf=loc_number[k];
loc_number[k]=loc_number[k+1];
loc_number[k+1]=work_buf;
}
}
}
system("cls");
return true;
}
bool ExitMm(bool save){
if(!save){
enum CHOISE_EM{back_em=1,output_em};
int point_em;
cout<<"База сотрудников не была сохранена в файл."<<
endl<<" При выходе из программы Вы можете потерять данные!"<<endl<<endl;
do{
cout<<"------------------"<<endl<<endl;
cout<<"1: Назад; "<<endl<<endl;
cout<<"2: Выход; "<<endl<<endl;
cout<<"------------------"<<endl<<endl;
point_em=EnterMenu(output_em);
switch(point_em){
case 0:
break;
case back_em:
return true; //назад
case output_em:
return false; //выход
}
}while(!point_em);
}
return false;
}
void InformMm(Worker *loc_number[],const int n){
double total=0,max=0;
int k;
enum CHOISE_MM {out_im=1,total_im,max_im,exit_im};
int point_im;
do{
cout<<"-----------------------------------"<<endl;
cout<<" МЕНЮ "<<endl;
cout<<"-----------------------------------"<<endl<<endl;
cout<<"1: Вывод сотрудников на экран;"<<endl<<endl;
cout<<"2: Суммарный заработок сотрудников;"<<endl<<endl;
cout<<"3: Сотрудник с наибольшей зарплатой;"<<endl<<endl;
cout<<"4: Назад;"<<endl<<endl;
cout<<"-----------------------------------"<<endl<<endl;
point_im=EnterMenu(exit_im);
switch(point_im){
case 0:
break;
case out_im:
cout<<endl<<endl<<"---------------------------------------"<<endl;
cout<<" Фамилия | Зарплата "<<endl;
cout<<"---------------------------------------"<<endl<<endl;
for(int i=0;i<n;i++){
if((*loc_number[i]).be==false) continue;
cout.setf(ios::left);
cout<<setw(20)<<(*loc_number[i]).surname<<setw(20)<<(*loc_number[i]).salary<<endl;
}
cout<<"---------------------------------------"<<endl<<endl;
_getch();
break;
case total_im:
for(int i=0;i<n;i++){
if((*loc_number[i]).be==false) continue;
total+=(*loc_number[i]).salary;
}
cout<<endl<<endl<<"--------------------------------------------"<<endl;
cout<<" Суммарный заработок сотрудников = "<<total<<endl;
cout<<"--------------------------------------------"<<endl;
total=0;
_getch();
break;
case max_im:
for(int i=0;i<n;i++){
if((*loc_number[i]).be==false) continue;
if((*loc_number[i]).salary > max) {
max=(*loc_number[i]).salary;
k=i;
}
}
cout<<endl<<endl<<"---------------------------------------"<<endl;
cout<<" Сотрудник с наибольшей зарплатой: "<<endl;
cout<<"---------------------------------------"<<endl;
cout<<" Фамилия | Зарплата "<<endl;
cout<<"---------------------------------------"<<endl;
for(int i=0;i<n;i++){
if((*loc_number[i]).salary==max){
cout.setf(ios::left);
cout<<setw(20)<<(*loc_number[i]).surname<<setw(20)<<(*loc_number[i]).salary<<endl;
}
}
cout<<"---------------------------------------"<<endl;
_getch();
break;
case exit_im:
break;
}
system("cls");
}while(point_im!=exit_im);
return;
}
void NullWork(Worker work[],Worker *loc_number[],const int n){
//объявленному массиву Worker присваиваем нулевые значения
for(int i=0;i<n;i++){
strcpy_s(work[i].surname,"0");
work[i].salary=0;
work[i].be=false;
loc_number[i]=&work[i];
}
return;
}
“Курсовой проект.cpp”
// Лакотка Ю. В. Курсовой проект.cpp. Вариант №5.
#include "stdafx.h"
int main()
{
system("chcp 1251");
system("cls");
const int n=100;
//объявляем массив структур типа Worker
Worker work[n];
//объявляем массив указателей на структуры типа Worker для последующей
//сортировки миссива структур Worker
Worker *number[n];
//объявленному массиву Worker присваиваем нулевые значения
NullWork(work,number,n);
enum CHOISE_MMD {create_mmd=1,extract_mmd,exit_mmd};
int point_mmd;
do{
cout<<"----------------------------------"<<endl;
cout<<" МЕНЮ "<<endl;
cout<<"----------------------------------"<<endl<<endl;
cout<<"1: Создать новую базу сотрудников;"<<endl<<endl;
cout<<"2: Открыть существующую базу;"<<endl<<endl;
cout<<"3: Выход из программы;"<<endl<<endl;
cout<<"----------------------------------"<<endl<<endl;
point_mmd=EnterMenu(exit_mmd);
switch(point_mmd){
case 0:
break;
case create_mmd: //создаем новую базу
MainMenu(work, number,n);
break;
case extract_mmd: //извлекаем существующую базу из файла
if(!ExtMm(work,number,n))break;
MainMenu(work, number,n);
break;
case exit_mmd:
break;
}
}while(point_mmd!=exit_mmd);
return 0;
}