- •Содержание
- •1 Постановка задачи
- •2 Анализ задачи, выбор способа представления данных
- •3 Алгоритмы решения задачи
- •4 Реализация программы
- •4.1 Именованные константы
- •4.2 Пользовательские типы данных
- •4.3 Функции
- •5 Руководство пользователя
- •Список использованных источников
- •Приложение а – Текст программы (обязательное)
5 Руководство пользователя
Сразу же после запуска программы на экране компьютера отобразится консольное окно, приведенное на рисунке 1.
Рисунок 1 – Консольное окно программы
Программа выводит на экран текстовое меню поддерживаемых команд и ожидает, чтобы пользователь ввел номер выбранного им пункта меню.
Меню программы включает следующие пункты:
Добавление сведений о спортсмене. Программа запросит фамилию, имя, отчество, дату рождения, вид спорта и количество сыгранных спортсменом игр.
Удаление сведений о спортсмене. Программа запросит номер удаляемой записи и удалит ее. Если будет указан номер несуществующей записи, то программа сообщит об этом.
Поиск записей по фамилии. Программа запросит фамилию спортсмена и отобразит таблицу, содержащую сведения о спортсменах, имеющих данную фамилию.
Сортировка записей о спортсменах в порядке не возрастания количества сыгранных игр.
Вывод в виде таблицы записей обо всех спортсменах.
Выход из программы.
Если пользователь укажет несуществующий пункт меню, то программа сообщит об этом.
Данная программа хранит все сведения о спортсменах в файле Sportsmen.dat, загружая их в память при запуске и сохраняя их при выходе из программы.
Список использованных источников
Павовская, Т.А. Программирование на языке высокого уровня. – СПб.: Питер, 2004 г.
Окулов, С.М. Программирование в алгоритмах: Учеб. изд / С.М. Окулов . - М. : БИНОМ : Лаборатория знаний, 2002.
Кормен, Т. Алгоритмы: построение и анализ. – М.: МЦНМО, 2002.
Приложение а – Текст программы (обязательное)
//Подключаем заголовочный файл для работы со стандартными потоками cin и cout
#include <iostream>
//Подключаем заголовочный файл для работы с потоковыми манипуляторами
// (см. Павловская "Программирование на языке высокого уровня", с. 271 )
#include <iomanip>
//Подключаем заголовчный файл для работы с потоковыми файловыми классами
#include <fstream>
//Подключаем заголовочный файл для работы со строками
#include <string.h>
using namespace std;
// Константы
const int MAX_NAME_LENGTH = 100; //Максимальная длина фамилии, имени, отчества
const int MAX_SPORTSMEN_COUNT = 1000; //Максимальное количество спортсменов в массиве
const char* FILE_NAME = "sportsmen.dat"; //Имя файла для хранения записей о спортсменах
//Заголовочная константная строка, используемая при выводе записей
const char* HEADER = "Index Surname Name Patronymic Birth date Sport Games count";
//Разделительная линия
const char* SEPARATING_LINE = "-------------------------------------------------------------------------------";
//Перечисление, описывающее вид спорта
// skNone - вид спорта не указан;
// skTennis - теннис,
// skChess - шахматы,
// skSprint - бег
enum SportKind {skNone, skTennis, skChess, skSprint};
//Стуктура, описывающая дату
struct Date
{
unsigned short int Year; //Год
unsigned short int Month; //Месяц
unsigned short int Day; //День
};
//Структура, описывающая запись о спортсмене
struct Sportsman
{
char Surname[MAX_NAME_LENGTH + 1]; //Фамилия
char Name[MAX_NAME_LENGTH + 1]; //Имя
char Patronymic[MAX_NAME_LENGTH + 1]; //Отчество
Date DateOfBirth; //Дата рождения
SportKind KindOfSport; //Вид спорта
int GamesCount; //Количество сыгранных игр
};
//Вспомогательная функция, осуществляющая преобразование
//вида спорта, содержашегося в параметре Type в строку Str,
//т.е. в назваие спорта, представленное в виде строки
void SportKindToStr(SportKind Type, char Str[])
{
//В зависимости от значения Type
switch (Type)
{
case skTennis:
strcpy(Str, "tennis"); //Копируем в Str название вида спорта "tennis"
break;
case skChess:
strcpy(Str, "chess"); //Копируем в Str название вида спорта "chess"
break;
case skSprint:
strcpy(Str, "sprint"); //Копируем в Str название вида спорта "sprint"
break;
default:
strcpy(Str, "unknown"); //Случай, когда задан тип skNone
}
}
//Вспомогательная функция, которая по названию спорта, содержащемся в строке Str,
//возвращает его тип
SportKind StrToSportKind(char Str[])
{
//Переводим строку Str к нижнему регистру
strlwr(Str);
//Если строка Str равна "tennis", то возвращаем skTennis
if (!strcmp(Str, "tennis"))
return skTennis;
//Если строка Str равна "chess", то возвращаем skСhess
if (!strcmp(Str, "chess"))
return skChess;
//Если строка Str равна "sprint", то возвращаем skSprint
if (!strcmp(Str, "sprint"))
return skSprint;
//Если в строке недопустимое название вида спорта, то возвращаем skNone
return skNone;
}
//Функция, осуществляющая ввод записи о спортсмене с консоли.
//Введенная запись возвращается в параметре Man, передаваемом по ссылке
void InputSportsman(Sportsman& Man)
{
//Про потоковые классы (в частности про объект cin) можно почитать в
//Павловской "Программирование на языке высокого уровня" c. 265 - 285
//В частности про функции get() и getline() стандартного объекта ввода cin можно почитать на с. 273
// cin.get() - читает один символ с консоли;
// cin.getline(buf, num) - читает с консоли num-1 или пока не встретится символ перевода строки и
// помещает их в строку buf. Причем, если встретился символ перевода строки, то
// он тоже помещается в buf
char Buf[MAX_NAME_LENGTH]; //Вспомогательная строка для ввода данных
bool IsValidKindOfSport; //Логическая переменная, определяющая правильно ли введен вид спорта
//Читаем символ перевода строки
cin.get();
cout << endl;
cout << "Enter sportsman info" << endl;
//Вводим фамилию
cout << "Surname : ";
cin.getline(Man.Surname, sizeof Man.Surname);
//Вводим имя
cout << "Name : ";
cin.getline(Man.Name, sizeof Man.Name);
//Вводим отчество
cout << "Patronymic : ";
cin.getline(Man.Patronymic, sizeof Man.Patronymic);
//Вводим год рождения
cout << "Year of birth : ";
cin >> Man.DateOfBirth.Year;
//Вводим месяц рождения.
// <== Сюда можно добавить цикл с постусловием для проверки корректности ввода номера месяца
cout << "Month of birth (1-12) : ";
cin >> Man.DateOfBirth.Month;
//Вводим день рождения
// <== Сюда можно добавить цикл с постусловием для проверки корректности ввода дня
cout << "Day of birth (1-31) : ";
cin >> Man.DateOfBirth.Day;
// <== Сюда можно добавить корректность вводимой даты, т.е. проверки допустима ли введенная дата
//Читаем символ перевода строки
cin.get();
//Цикл с постусловием для повторного ввода строки вида спорта,
//если она отличная от "tennis", "chess" и "sprint"
do
{
//Полагаем, что вид спорта правильный
IsValidKindOfSport = true;
cout << "Kind of sport (tennis, chess or sprint) : ";
//Читаем в Buf строку вида спорта
cin.getline(Buf, sizeof Buf);
//Преобразовывем введенную строку в переменную типа SportKind
Man.KindOfSport = StrToSportKind(Buf);
//Если была введена недопустимая строка
if (Man.KindOfSport == skNone)
{
//Выдаем сообщение, что строка неправильная
cout << endl << "Invalid! Enter tennis, chess or sprint" << endl << endl;
//Устанавливаем значение лжи для флага правильности строки вида спорта
IsValidKindOfSport = false;
}
//Цикл повторяется до тех пор, пока введенная строка вида спорта не будет правильной
} while (!IsValidKindOfSport);
//Вводим количество сыгранных игр
cout << "Games count : ";
cin >> Man.GamesCount;
}
//Функция вывода на консоль полей записи (структуры) Man, имеющей индекс Index
void PrintSportsman(Sportsman Man, int Index)
{
//В данной функции используются специальные манипуляторы, осуществляющие форматирование
//выводимых данных. Для их использования необходимо подключить заголовочный файл iomanip.h
// setw(int) - устанавливает максимальную ширину поля вывода;
// setfill(char) - устанавливает символ-заполнитель для случая, если выводимые данные занимают не всю ширину
// поля вывода. По умолчанию символом-заполнителем является пробел
//Пример. Строка
// cout << setfill('+') << setw(5) << 44;
//выдаст на консоль
//+++44
//Подробности см. в Павловской "Программирование на языке высокого уровня" c. 271
char Buf[MAX_NAME_LENGTH]; //Строковая переменная для строкового представления вида спорта
//Выводим индекс в поле максимальной ширины 5
cout << setw(5) << Index << " ";
//Выводим фамилию, имя, отчество. Каждое в своем поле максимальной ширины 13
cout << setw(13) << Man.Surname << " " << setw(13) << Man.Name << " "<< setw(13) << Man.Patronymic << " ";
//Меняем символ-заполнитель с пробела на 0. Использование заполнителя 0 позволит выдавать даты в формате ДД.ММ.ГГГГ
cout << setfill('0');
//Выдаем день, месяц и год даты рождение. Каждая компонента даты выводися в своем поле
cout << setw(2) << Man.DateOfBirth.Day << "." << setw(2) << Man.DateOfBirth.Month << "." << setw(4) << Man.DateOfBirth.Year << " ";
//Возвращаем пробел в качестве символа-заполнителя
cout << setfill(' ');
//Осуществляем перевод вида спорта в строку Buf
SportKindToStr(Man.KindOfSport, Buf);
//Выводим строку вида спорта и количество сыгрнанных игр
cout << setw(6) << Buf << " " << setw(7) << Man.GamesCount << endl;
}
//Функция, добавляющая запись о спортсмене Man в конец массива спортсменов SportsmenArray,
//SportsmenCount - количество записей-элементов в массиве SportsmenArray
void AddSportsman(Sportsman SportsmenArray[], int& SportsmenCount, Sportsman Man)
{
SportsmenArray[SportsmenCount++] = Man;
}
//Функция, удаляющая в массиве SportsmenArray запись-элемент с индексом RemovingIndex,
//SportsmenCount - количество записей-элементов в массиве SportsmenArray.
//Функция возвращает истину, если RemovingIndex лежит в допустимом диапазоне от 0 до SportsmenCount-1,
//иначе функция возвращает ложь
bool RemoveSportsman(Sportsman SportsmenArray[], int& SportsmenCount, int RemovingIndex)
{
//Если индекс удаляемого элемента задан неправильно, то возвращаем ложь
if (RemovingIndex < 0 || RemovingIndex >= SportsmenCount)
{
return false;
}
//Данный цикл осуществляет сдвиг элементов
// SportsmenArray[RemovingIndex], SportsmenArray[RemovingIndex], ..., SportsmenArray[SportsmenCount - 1]
//на один элемент влево и тем самым затирает удаляемый элемент
for (int i = RemovingIndex; i < SportsmenCount - 1; i++)
{
SportsmenArray[i] = SportsmenArray[i + 1];
}
//Уменьшаем количество элементов-записей на 1
SportsmenCount--;
//Возвращаем истину
return true;
}
//Функция, осуществляющая поиск и вывод на консоль элементов-записей о спортсменах массива SportsmenArray,
//фамилия которых совпадает со строкой KeySurname (ключом для поиска).
//SportsmenCount - количество записей-элементов в массиве SportsmenArray.
void SearchAndPrintSportsmen(Sportsman SportsmenArray[], int SportsmenCount, char KeySurname[])
{
//Переменная для подсчета количества найденных записей, вначале равна 0
int FoundRecordsCount = 0;
cout << endl;
//Выводим заголовок
cout << SEPARATING_LINE << endl;
cout << HEADER << endl;
cout << SEPARATING_LINE << endl;
//Пробегаемся по все элементам массива SportsmenArray
for (int i = 0; i < SportsmenCount; i++)
{
//Если фамилия очередного элемента-записи совпадает с KeySurname, то
if (!strcmp(SportsmenArray[i].Surname, KeySurname))
{
//выводим сам элемент
PrintSportsman(SportsmenArray[i], i);
//выводим разделительную линию
cout << SEPARATING_LINE << endl;
//Увеличиваем на 1 количество найденных записей
FoundRecordsCount++;
}
}
//Выводим количество найденных записей
cout << FoundRecordsCount << " records were found." << endl;
}
//Функция, осуществляющая сортировку массива спортсменов по не возрастанию количества сыгранных игр.
//SportsmenArray - массив элементов-записей о спортсменах;
//SportsmenCount - количество спорстменов-записей в массиве.
void SortSportsmenByGamesCount(Sportsman SportsmenArray[], int SportsmenCount)
{
int MaxIndex;
Sportsman Tmp;
for (int i = 0; i < SportsmenCount - 1; i++)
{
MaxIndex = i;
for (int j = i + 1; j < SportsmenCount; j++)
{
if (SportsmenArray[j].GamesCount > SportsmenArray[MaxIndex].GamesCount)
{
MaxIndex = j;
}
}
Tmp = SportsmenArray[i];
SportsmenArray[i] = SportsmenArray[MaxIndex];
SportsmenArray[MaxIndex] = Tmp;
}
}
//Функция, осуществляющая вывод на консоль всех элеменов-записей о спорстменах,
//содержащихся в массиве SportsmenArray размера SportsmenCount
void PrintAllSportsmen(Sportsman SportsmenArray[], int SportsmenCount)
{
cout << endl;
//Выводим заголовок
cout << SEPARATING_LINE << endl;
cout << HEADER << endl;
cout << SEPARATING_LINE << endl;
//Пробегаемя по всем элементам
for (int i = 0; i < SportsmenCount; i++)
{
//Выводим очердной элемент-запись
PrintSportsman(SportsmenArray[i], i);
//Выводим разделительную линию
cout << SEPARATING_LINE << endl;
}
}
//Функция, осуществляющая чтение массива SportsmenArray и его размера SportsmenCount
//из файла с именем SportsmenCount
void LoadFromFile(Sportsman SportsmenArray[], int& SportsmenCount, const char* FileName)
{
//Объявлем файловый поток ввода inp, передаем ему имя открываемого файла FileName
ifstream inp(FileName);
//Читаем из файла количество элементов в массиве
inp >> SportsmenCount;
//Читаем из файла целиком весь массив
inp.read((char *)SportsmenArray, SportsmenCount * sizeof(SportsmenArray[0]));
}
//Функция, осуществляющая сохранение массива SportsmenArray и его размера SportsmenCount
//в файл FileName
void SaveToFile(Sportsman SportsmenArray[], int SportsmenCount, const char* FileName)
{
//Объявляем файловый поток вывода out, передаем ему имя открываемого файла FileName
ofstream out(FileName);
//Записываем в файл количество спорстменов
out << SportsmenCount;
//Записываем в файл весь массив целиком
out.write((char *)SportsmenArray, SportsmenCount * sizeof(SportsmenArray[0]));
}
//Функция, реализующая главное меню программы. В зависимости от выбора пользователя,
//осуществляет вызов соответствующих функций.
//Параметры:
//SportsmenArray - массив элементов-записей о спорстменах;
//SportsmenCount - количество элементов в массиве.
void MainMenu(Sportsman SportsmenArray[], int& SportsmenCount)
{
//Переменная, которая будет хранить номер выбранного пользователем пункта меню
int UserChoise;
//Переменная-запись о спорстмене
Sportsman Man;
//Переменная для хранения индекса удаляемого элемента
int RemovingIndex;
//Массив символов для хранения строки фамилии для поиска
char KeySurname[MAX_NAME_LENGTH];
//Цикл с постусловием, осуществляющий вывод меню, ввод выбора пользователя и
//выполнение соответстующих этому выбору действий до тех пор, пока пользователь
//не выберет выход из программы
do
{
//Отображаем меню
cout << endl;
cout << " MENU" << endl;
cout << "=========================" << endl;
cout << " [1] Add sportsman" << endl;
cout << " [2] Remove sportsman" << endl;
cout << " [3] Search sportsman" << endl;
cout << " [4] Sort sportsmen" << endl;
cout << " [5] Show all sportsmen" << endl;
cout << " [6] Exit" << endl;
cout << "=========================" << endl;
cout << "Your choice : ";
//Вводим выбранный пользователем пункт меню
cin >> UserChoise;
//С помощью конструкции выбора анализируем этот выбор
//и осуществляем соответствующие действия
switch (UserChoise)
{
//Добавление новой записи о спортсмене в массив
case 1:
InputSportsman(Man);
AddSportsman(SportsmenArray, SportsmenCount, Man);
break;
//Удаление записи о спортсмене с указанным индексом из массива
case 2:
cout << endl << "Enter index of sportsman to delete : ";
//Вводим индекс удаляемого элемента-записи
cin >> RemovingIndex;
//Удаляем элемент. Если результат удаления ложь, то
if (!RemoveSportsman(SportsmenArray, SportsmenCount, RemovingIndex))
{
//Выдаем ошибку
cout << endl << "Invalid index! Try again." << endl;
}
break;
//Поиск всех записей о спорстменах, имеющих указанную фамилию
case 3:
cout << endl << "Enter surname for search : ";
//Вводим символ перевода строки
cin.get();
//Вводим фамилию для поиска
cin.getline(KeySurname, sizeof KeySurname);
//Вызываем функцию поиска и вывода найденных элементов
SearchAndPrintSportsmen(SportsmenArray, SportsmenCount, KeySurname);
break;
//Сортировка всех записей о спортсменах в порядке не возрастания
//количества сыгранных игр
case 4:
SortSportsmenByGamesCount(SportsmenArray, SportsmenCount);
break;
//Печать всех записей о спортсменах
case 5:
PrintAllSportsmen(SportsmenArray, SportsmenCount);
break;
//Выход
case 6:
cout << "Bye-bye..." << endl;
break;
//Ошибка, пользователь выбрал несуществующий пункт меню
default:
cout << endl << "Invalid choice! Try again." << endl;
}
//цикл выполняется до тех пор, пока пользователь не выберет выход
} while (UserChoise != 6);
}
int main()
{
//Описание массива записей (структур) о спортсменах
Sportsman SportsmenArray[MAX_SPORTSMEN_COUNT];
//Переменная для хранения количества записей в массиве
int SportsmenCount = 0;
//Загружаем все записи из файла
LoadFromFile(SportsmenArray, SportsmenCount, FILE_NAME);
//Выдаем меню и осуществляем операции
MainMenu(SportsmenArray, SportsmenCount);
//Перед выходом из программы сохраняем все записи в файл
SaveToFile(SportsmenArray, SportsmenCount, FILE_NAME);
return 0;
}