Советы, трюки и секреты для Blogger.com блоггеров. Все для Blogspot. Советы, трюки и секреты для Blogger.com блоггеров. Все для Blogspot.

Работа с записями, удаление, добавление, поиск, сортировка, печать, сохранение, чтение (С++)

07 октября 2010, 02:50

Каждая запись представляется собой экземпляр структуры. Все записи хранятся в массиве. 
 
Функциональность программы должна включать:
•Добавление записи, введенной с клавиатуры
•Удаление указанной записи
•Поиск записей по некоторому критерию
•Сортировку записей
•Печать всех записей
•Сохранение всех записей в файл*
•Чтение всех записей из файла*
 
Записи о принтерах. Каждый принтер характеризуется названием, типом (струйный или лазерный),вертикальным и горизонтальным разрешением, скоростью печати, ценой.
 
Code:
 
#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;
}

 
Так же смотрите другие лабораторные по программированию на блоге ЭВМщик.
Работа с записями, удаление, добавление, поиск, сортировка, печать, сохранение, чтение (С++)