#include <iostream> //Подключаем заголовочный файл для работы со стандартными потоками cin и cout #include <iomanip> //Подключаем заголовочный файл для работы с потоковыми манипуляторами #include <fstream> //Подключаем заголовчный файл для работы с потоковыми файловыми классами #include <string.h> //Подключаем заголовочный файл для работы со строками using namespace std; // Константы const int MAX_NAME_LENGTH = 100; //Максимальная длина названия const int MAX_PRINT_COUNT = 1000; //Максимальное количество принтеров в массиве const char* FILE_NAME = "printer.txt"; //Имя файла для хранения записей о принтерах //Заголовочная константная строка, используемая при выводе записей const char* HEADER = " Index Name Type Razreshenie Speed Cena "; //Разделительная линия const char* SEPARATING_LINE = "---------------------------------------------------------------------"; //Перечисление, описывающее тип принтера // skNone - вид принтера не указан; // skStry - струйный, // skLazer - лазерный, enum PrinterType {skNone, skStry, skLazer}; //Структура, описывающая запись о принтере struct Printer { char Name[MAX_NAME_LENGTH + 1]; //Наименование PrinterType TypeOfPrint; //Тип принтера char Razreshenie [MAX_NAME_LENGTH + 1]; // Разрешение float Speed; // скорость принтера float Cena; // цена принтера }; //Вспомогательная функция, осуществляющая преобразование //Тип принтера, содержашегося в параметре Type в строку Str, //т.е. тип принтера, представленное в виде строки void PrinterTypeToStr(PrinterType Type, char Str[]) { //В зависимости от значения Type switch (Type) { case skStry: strcpy(Str, "stry"); //Копируем в Str название вида спорта "stryinij" break; case skLazer: strcpy(Str, "laz"); //Копируем в Str название вида спорта "Lazer" break; default: strcpy(Str, "unknown"); //Случай, когда задан тип skNone } } //Вспомогательная функция, которая по типу принтера, содержащемся в строке Str, //возвращает его тип PrinterType StrToPrinterType(char Str[]) { strlwr(Str); //Переводим строку Str к нижнему регистру if (!strcmp(Str, "stry") ) //Если строка Str равна "stryinij", то возвращаем skStry return skStry; if (!strcmp(Str, "laz")) //Если строка Str равна "lazer", то возвращаем skLazer return skLazer; //Если в строке недопустимое название типа принтера, то возвращаем skNone return skNone; } //Функция, осуществляющая ввод записи о принтере с консоли. //Введенная запись возвращается в параметре Pri, передаваемом по ссылке void InputPrinter(Printer & Pri) { char Buf[MAX_NAME_LENGTH]; //Вспомогательная строка для ввода данных bool IsValidTypeOfPrint; //Логическая переменная, определяющая правильно ли введен тип принтера //Читаем символ перевода строки cin.get(); cout << endl; cout << "Enter printer info" << endl; //Вводим имя cout << "Name : "; cin.getline( Pri.Name, sizeof Pri.Name); //Цикл с постусловием для повторного ввода строки типа принтера, //если она отличная от "stry" и "laz" do { IsValidTypeOfPrint = true; //Полагаем, что вид спорта правильный cout << "Type of printer (stry or laz) : "; //Читаем в Buf строку типа принтера cin.getline(Buf, sizeof Buf); //Преобразовывем введенную строку в переменную типа PrinterType Pri.TypeOfPrint = StrToPrinterType(Buf); if (Pri.TypeOfPrint == skNone) //Если была введена недопустимая строка { //Выдаем сообщение, что строка неправильная cout << endl << "Invalid! Enter stry or laz" << endl << endl; //Устанавливаем логической перменной правильности ввода типа лож IsValidTypeOfPrint = false; } //Цикл повторяется до тех пор, пока введенная строка типа не будет правильной } while (!IsValidTypeOfPrint); //Вводим разрешение принтера; cout << "Vvedite razreshenie : "; cin>>Pri.Razreshenie; //Вводим скорость печати; cout << "Enter speed : "; cin >> Pri.Speed; //Вводим цену принтера; cout << "Enter cena : "; cin >> Pri.Cena; } //Функция вывода на консоль полей записи (структуры) Pri, имеющей индекс Index void PrintPrinter(Printer Pri, 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) << Pri.Name << " "; //Возвращаем пробел в качестве символа-заполнителя cout << setfill(' '); //Осуществляем перевод типа принтера в строку Buf PrinterTypeToStr(Pri.TypeOfPrint, Buf); //Выводим строку тип принтера, разрешение, скорость, цену cout << setw(7) << Buf << " " << setw(16) << Pri.Razreshenie << " "; cout << setw(11) << Pri.Speed << " " << setw(11) << Pri.Cena << endl; } //Функция, добавляющая запись о принтере, Pri в конец массива принтеров PrintArray, //PrintCount - количество записей-элементов в массиве PrintArray void AddPrint(Printer PrintArray[], int& PrintCount, Printer Pri) { PrintArray[PrintCount++] = Pri; } //Функция, удаляющая в массиве PrintArray запись-элемент с индексом RemovingIndex, //PrintCount - количество записей-элементов в массиве SportsmenArray. //Функция возвращает истину, если RemovingIndex лежит в допустимом диапазоне от 0 до PrintCount-1, //иначе функция возвращает ложь bool RemovePrinter(Printer PrintArray[], int& PrintCount, int RemovingIndex) { //Если индекс удаляемого элемента задан неправильно, то возвращаем ложь if (RemovingIndex < 0 || RemovingIndex >= PrintCount) { return false; } //Данный цикл осуществляет сдвиг элементов // PrintArray[RemovingIndex], PrintArray[RemovingIndex], ..., PrintArray[PrintCount - 1] //на один элемент влево и тем самым затирает удаляемый элемент for (int i = RemovingIndex; i < PrintCount - 1; i++) { PrintArray[i] = PrintArray[i + 1]; } //Уменьшаем количество элементов-записей на 1 PrintCount--; //Возвращаем истину return true; } //Функция, осуществляющая поиск и вывод на консоль элементов-записей о принтерах массива PrintArray, //фамилия которых совпадает со строкой KeyName (ключом для поиска). //PrintCount - количество записей-элементов в массиве PrintArray. void SearchAndPrintPrinter(Printer PrintArray[], int PrintCount, char KeyName[]) { //Переменная для подсчета количества найденных записей, вначале равна 0 int FoundRecordsCount = 0; cout << endl; //Выводим заголовок cout << SEPARATING_LINE << endl; cout << HEADER << endl; cout << SEPARATING_LINE << endl; //Пробегаемся по все элементам массива PrintArray for (int i = 0; i < PrintCount; i++) { //Если фамилия очередного элемента-записи совпадает с KeyName, то if (!strcmp(PrintArray[i].Name, KeyName)) { //выводим сам элемент PrintPrinter(PrintArray[i], i); //выводим разделительную линию cout << SEPARATING_LINE << endl; //Увеличиваем на 1 количество найденных записей FoundRecordsCount++; } } //Выводим количество найденных записей cout << FoundRecordsCount << " records were found." << endl; } //Функция, осуществляющая сортировку массива принтеров по возрастанию цены. //PrintArray - массив элементов-записей о принтерах; //PrintCount - количество принтеров-записей в массиве. void SortPrinterByCena(Printer PrintArray[], int PrintCount) { int MaxIndex; Printer Tmp; for (int i = 0; i < PrintCount - 1; i++) { MaxIndex = i; for (int j = i + 1; j < PrintCount; j++) { if (PrintArray[j].Cena > PrintArray[MaxIndex].Cena) { MaxIndex = j; } } Tmp = PrintArray[i]; PrintArray[i] = PrintArray[MaxIndex]; PrintArray[MaxIndex] = Tmp; } } //Функция, осуществляющая вывод на консоль всех элеменов-записей о принтерах, //содержащихся в массиве PrintArray размера PrintCount void PrintAllPrinter(Printer PrintArray[], int PrintCount) { cout << endl; //Выводим заголовок cout << SEPARATING_LINE << endl; cout << HEADER << endl; cout << SEPARATING_LINE << endl; //Пробегаемя по всем элементам for (int i = 0; i < PrintCount; i++) { //Выводим очердной элемент-запись PrintPrinter(PrintArray[i], i); //Выводим разделительную линию cout << SEPARATING_LINE << endl; } } //Функция, осуществляющая чтение массива PrintArray и его размера PrintCount //из бинарного файла с именем PrintCount void LoadFromFile(Printer PrintArray[], int& PrintCount, const char* FileName) { //Объявлем файловый поток ввода inp, передаем ему имя открываемого файла FileName ifstream inp(FileName); //Читаем из файла количество элементов в массиве inp >> PrintCount; //Читаем из файла целиком весь массив inp.read((char *)PrintArray, PrintCount * sizeof(PrintArray[0])); } //Фуникция, осуществляющая сохранение массива PrintArray и его размера PrintCount //в бинарный файл FileName void SaveToFile(Printer PrintArray[], int PrintCount, const char* FileName) { //Объявляем файловый поток вывода out, передаем ему имя открываемого файла FileName ofstream out(FileName); //Записываем в файл количество спорстменов out << PrintCount; //Записываем в файл весь массив целиком out.write((char *)PrintArray, PrintCount * sizeof(PrintArray[0])); } //Функция, реализующая главное меню программы. В зависимости от выбора пользователя, //осуществляет вызов соответствующих функций. //Параметры: //PrintArray - массив элементов-записей о принтерах; //PrintCount - количество элементов в массиве. void MainMenu(Printer PrintArray[], int& PrintCount) { //Переменная, которая будет хранить номер выбранного пользователем пункта меню int UserChoise; //Переменная-запись о принтерах Printer Pri; //Переменная для хранения индекса удаляемого элемента int RemovingIndex; //Массив символов для хранения строки наименования для поиска char KeyName[MAX_NAME_LENGTH]; //Цикл с постусловием, осуществляющий вывод меню, ввод выбора пользователя и //выполнение соответстующих этому выбору действий до тех пор, пока пользователь //не выберет выход из программы do { //Отображаем меню cout << endl; cout << " MENU" << endl; cout << "=========================" << endl; cout << " [1] Add printer" << endl; cout << " [2] Remove printer" << endl; cout << " [3] Search printer" << endl; cout << " [4] Sort printer" << endl; cout << " [5] Show all printer" << endl; cout << " [6] Exit" << endl; cout << "=========================" << endl; cout << "Your choice : "; //Вводим выбранный пользователем пункт меню cin >> UserChoise; //С помощью конструкции выбора анализируем этот выбор //и осуществляем соответствующие действия switch (UserChoise) { //Добавление новой записи о принтере в массив case 1: InputPrinter(Pri); AddPrint(PrintArray, PrintCount, Pri); break; //Удаление записи о принтере с указанным индексом из массива case 2: cout << endl << "Enter index of printer to delete : "; //Вводим индекс удаляемого элемента-записи cin >> RemovingIndex; //Удаляем элемент. Если результат удаления ложь, то if (!RemovePrinter(PrintArray, PrintCount, RemovingIndex)) { //Выдаем ошибку cout << endl << "Invalid index! Try again." << endl; } break; //Поиск всех записей о принтерах, имеющих указанное наименование case 3: cout << endl << "Enter name for search : "; //Вводим символ перевода строки cin.get(); //Вводим фамилию для поиска cin.getline(KeyName, sizeof KeyName); //Вызываем функцию поиска и вывода найденных элементов SearchAndPrintPrinter(PrintArray, PrintCount, KeyName); break; //Сортировка всех записей о принтерах в порядке возрастания цены case 4: SortPrinterByCena(PrintArray, PrintCount); break; //Печать всех записей о принтерах case 5: PrintAllPrinter(PrintArray, PrintCount); break; //Выход case 6: cout << "Bye-bye..." << endl; break; //Ошибка, пользователь выбрал несуществующий пункт меню default: cout << endl << "Invalid choice! Try again." << endl; } //цикл выполняется до тех пор, пока пользователь не выберет выход } while (UserChoise != 6); } int main() { //Описание массива записей (структур) о принтере Printer PrintArray[MAX_PRINT_COUNT]; //Переменная для хранения количества записей в массиве int PrintCount = 0; //Загружаем все записи из файла LoadFromFile(PrintArray, PrintCount, FILE_NAME); //Выдаем меню и осуществляем операции MainMenu(PrintArray, PrintCount); //Перед выходом из программы сохраняем все записи в файл SaveToFile(PrintArray, PrintCount, FILE_NAME); return 0; }
07 октября 2010, 02:50