constk

LR13_Classes_Var_2 for Nikita

Sep 16th, 2020 (edited)
116
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. #include "windows.h"
  5.  
  6. using namespace std;
  7.  
  8. int sizeofFile(ifstream * file); // Подсчитывает количесво строк в файле
  9.  
  10.  
  11. struct STUDENT
  12. {
  13.     string name; // Фамилия
  14.     int yearOfBirth; // Год рождения
  15.     double academicPerformance; // Успеваемость (средняя оценка)
  16. };
  17.  
  18.  
  19. class Student
  20. {
  21. public:
  22.     // Конструктор для инициализации с клавиатуры
  23.     Student()
  24.     {
  25.         SetConsoleCP(1251);
  26.         SetConsoleOutputCP(1251);
  27.  
  28.         while (read() == 1) // Не удалось считать данные с клавиатуры
  29.         {
  30.             cerr << "Ошибка при инициализации. Попробовать ввести данные ещё раз? (y/n) ";
  31.             char choice = 0;
  32.             cin >> choice;
  33.             if (choice == 'n')
  34.             {
  35.                 cout << "Завершение работы программы" << endl;
  36.                 system("pause>nul");
  37.                 exit(1);
  38.             }
  39.         }
  40.     }
  41.  
  42.     // Конструктор для инициализации из файла
  43.     Student(string fileName)
  44.     {
  45.         SetConsoleCP(1251);
  46.         SetConsoleOutputCP(1251);
  47.  
  48.         if (loadFromFile(fileName) == 1) // Не удалось загрузить данные из файла
  49.         {
  50.             cerr << "Ошибка при инициализации. Не удаётся считать данные из файла.";
  51.             cout << "Завершение работы программы" << endl;
  52.             system("pause>nul");
  53.             exit(1);
  54.         }
  55.     }
  56.  
  57.     // Деструктор
  58.     ~Student()
  59.     {
  60.         clear(); // Удаляем все данные
  61.     }
  62.  
  63.     // Удалить данные
  64.     void clear()
  65.     {
  66.         if (students == NULL) // Если данные уже удалены или ещё не записаны
  67.             return;
  68.            
  69.         // Освобождаем память
  70.         delete[] students;
  71.         students = NULL;
  72.         size = 0;
  73.     }
  74.  
  75.     // Ввод данных с клавиатуры
  76.     int read()
  77.     {
  78.         cout << "Сколько студентов записать? "; // Запрашиваем число записей
  79.         int n = 0;
  80.         cin >> n;
  81.  
  82.         if (n <= 0) // Число записей введено некорректно
  83.         {
  84.             cerr << "Нельзя записать " << n << " студентов! Количество должно быть больше или равно нулю!" << endl;
  85.             return 1;
  86.         }
  87.  
  88.         clear(); // Очищаем старые данные
  89.  
  90.         size = n; // Выделяем память под новые
  91.         students = new STUDENT[size];
  92.  
  93.         for (int i = 0; i < size; ++i) // Осуществляем запись
  94.         {
  95.             cout << "Студент № " << i + 1 << ": " << endl;
  96.             cin.ignore(32767, '\n');
  97.             cout << "Фамилия:      "; getline(cin, students[i].name);
  98.             cout << "Год рождения: "; cin >> students[i].yearOfBirth;
  99.             cout << "Успеваемость: "; cin >> students[i].academicPerformance;
  100.         }
  101.         cout << "Данные записаны!" << endl;
  102.  
  103.         return 0;
  104.     }
  105.  
  106.     // Загрузить данные из файла
  107.     int loadFromFile(string fileName)
  108.     {
  109.         ifstream file(fileName); // Открываем файл на чтение
  110.  
  111.         if (!file.is_open()) // Ошибка при открытии файла
  112.         {
  113.             cerr << "Ошибка: Файл не может быть открыт!" << endl;
  114.             return 1;
  115.         }
  116.         if (file.peek() == -1 || file.peek() == 0) // Файл пуст
  117.         {
  118.             cerr << "Ощибка: Файл пуст!" << endl;
  119.             return 1;
  120.         }
  121.  
  122.         // Начинаем загрузку данных
  123.         cout << "Считываю данные из файла..." << endl;
  124.  
  125.         // Очищаем старые данные
  126.         clear();
  127.  
  128.         // Вычисляем, сколько памяти потребуется выделить для загрузки содержимого файла (сколько будет записей в массиве)
  129.         size = sizeofFile(&file) / 3;
  130.  
  131.         students = new STUDENT[size]; // Выделяем память
  132.         for (int i = 0; i < size; ++i) // Загружаем данные
  133.         {
  134.             getline(file, students[i].name);
  135.             file >> students[i].yearOfBirth;
  136.             file >> students[i].academicPerformance;
  137.             file.ignore(32767, '\n');
  138.         }
  139.  
  140.         file.close(); // Закрываем файл
  141.         cout << "Данные успешно загружены!" << endl;
  142.         return 0;
  143.     }
  144.  
  145.     // Вывод данных на экран
  146.     void show()
  147.     {
  148.         cout << "Вывод данных на экран..." << endl;
  149.  
  150.         if (students == NULL) // Если данных нет
  151.         {
  152.             cerr << "Пусто!" << endl;
  153.             return;
  154.         }
  155.  
  156.         // Выводим данные на жкран
  157.         for (int i = 0; i < size; ++i)
  158.         {
  159.             cout << students[i].name << endl;
  160.             cout << students[i].yearOfBirth << endl;
  161.             cout << students[i].academicPerformance << endl;
  162.         }
  163.     }
  164.  
  165.     // Сохранить данные в файл
  166.     int saveToFile(string fileName)
  167.     {
  168.         ofstream file(fileName); // Открываем файл на перезапись
  169.  
  170.         if (!file.is_open()) // Ошибка при открытии файла
  171.         {
  172.             cerr << "Файл не может быть открыт!\n" << endl;
  173.             return 1;
  174.         }
  175.         if (students == NULL) // Если данных нет
  176.         {
  177.             cerr << "Пусто!" << endl;
  178.             return 1;
  179.         }
  180.  
  181.         // Сохраняем данные
  182.         cout << "Сохраняю данные..." << endl;
  183.         for (int i = 0; i < size; i++)
  184.         {
  185.             file << students[i].name << endl;
  186.             file << students[i].yearOfBirth << endl;
  187.             if (i == size - 1)
  188.                 file << students[i].academicPerformance;
  189.             else
  190.                 file << students[i].academicPerformance << endl;
  191.         }
  192.         cout << "Данные сохранены." << endl << endl;
  193.         file.close(); // Закрываем файл
  194.     }
  195.  
  196.     // Перегруженные методы для поиска
  197.     int find(string nameToFind) // По фамилии (строка)
  198.     {
  199.         cout << "Поиск по фамилии..." << endl;
  200.         if (students == NULL) // Если данных нет
  201.         {
  202.             cerr << "Пусто!" << endl;
  203.             return 1;
  204.         }
  205.  
  206.         // Изначально считаем, что ничего не найдено
  207.         bool foundSomething = false;
  208.  
  209.         for (int i = 0; i < size; ++i)
  210.         {
  211.             if (students[i].name.find(nameToFind) != string::npos) // Нашли частичное совпадение
  212.             {
  213.                 // Выводим найденную запись
  214.                 cout << students[i].name << endl;
  215.                 cout << students[i].yearOfBirth << endl;
  216.                 cout << students[i].academicPerformance << endl;
  217.                 foundSomething = true; // Меняем значение флага
  218.             }
  219.         }
  220.  
  221.         if (foundSomething == false) // Если так ничего и не нашли
  222.             cout << "Ничего не найдено!" << endl;
  223.  
  224.         return 0;
  225.     }
  226.     int find(int yearToFind) // По году рождения (целое число)
  227.     {
  228.         cout << "Поиск по году рождения..." << endl;
  229.         if (students == NULL) // Если данных нет
  230.         {
  231.             cerr << "Пусто!" << endl;
  232.             return 1;
  233.         }
  234.  
  235.         // Изначально считаем, что ничего не найдено
  236.         bool foundSomething = false;
  237.  
  238.         for (int i = 0; i < size; ++i)
  239.         {
  240.             if (students[i].yearOfBirth == yearToFind) // Нашли полное совпадение
  241.             {
  242.                 // Выводим найденную запись
  243.                 cout << students[i].name << endl;
  244.                 cout << students[i].yearOfBirth << endl;
  245.                 cout << students[i].academicPerformance << endl;
  246.                 foundSomething = true; // Меняем значение флага
  247.             }
  248.         }
  249.  
  250.         if (foundSomething == false) // Если так ничего и не нашли
  251.             cout << "Ничего не найдено!" << endl;
  252.  
  253.         return 0;
  254.     }
  255.     int find(double performanceToFind) // По успеваемости (дробное число)
  256.     {
  257.         cout << "Поиск по успеваемости..." << endl;
  258.         if (students == NULL) // Если данных нет
  259.         {
  260.             cerr << "Пусто!" << endl;
  261.             return 1;
  262.         }
  263.  
  264.         // Изначально считаем, что ничего не найдено
  265.         bool foundSomething = false;
  266.  
  267.         for (int i = 0; i < size; ++i)
  268.         {
  269.             if (students[i].academicPerformance == performanceToFind) // Нашли полное совпадение
  270.             {
  271.                 // Выводим найденную запись
  272.                 cout << students[i].name << endl;
  273.                 cout << students[i].yearOfBirth << endl;
  274.                 cout << students[i].academicPerformance << endl;
  275.                 foundSomething = true; // Меняем значение флага
  276.             }
  277.         }
  278.  
  279.         if (foundSomething == false) // Если так ничего и не нашли
  280.             cout << "Ничего не найдено!" << endl;
  281.  
  282.         return 0;
  283.     }
  284.  
  285.     // Метод для сортировки
  286.     void sort()
  287.     {
  288.         cout << "Сортировка..." << endl;
  289.         if (students == NULL) // Если данных нет
  290.         {
  291.             cerr << "Пусто!" << endl;
  292.             return;
  293.         }
  294.  
  295.         int choice = 0; // Уточняем у пользователя критерий сортировки
  296.         cout << "Отсортировать по фамилии(1), году рождения(2) или по успеваемости(3)? (1/2/3)" << endl;
  297.         do {
  298.             cin >> choice;
  299.  
  300.             // Изначально считаем, что данные не отсортированы
  301.             bool isSorted = false;
  302.  
  303.             switch (choice)
  304.             {
  305.             case 1: // Сортировка по фамилии (в алфавитном порядке)
  306.                 while (isSorted == false) // Пока данные не отсортированы
  307.                 {
  308.                     isSorted = true; // Предполагаем, что данные упорядочены
  309.                     for (int i = 0; i < size - 1; ++i)
  310.                     {
  311.                         string left = students[i].name;
  312.                         string right = students[i + 1].name;
  313.                         if (left > right) // Если оказывается, что данные неупорядочены
  314.                         {
  315.                             isSorted = false; // Изменяем значение флага
  316.  
  317.                             // Меняем записи местами
  318.                             STUDENT tmp = students[i];
  319.                             students[i] = students[i + 1];
  320.                             students[i + 1] = tmp;
  321.                         }
  322.                     }
  323.                 }
  324.                 break;
  325.  
  326.             case 2: // Сортировка по году рождения (по возрастанию)
  327.                 while (isSorted == false) // Пока данные не отсортированы
  328.                 {
  329.                     isSorted = true; // Предполагаем, что данные упорядочены
  330.                     for (int i = 0; i < size - 1; ++i)
  331.                     {
  332.                         int left = students[i].yearOfBirth;
  333.                         int right = students[i + 1].yearOfBirth;
  334.                         if (left > right) // Если оказывается, что данные неупорядочены
  335.                         {
  336.                             isSorted = false; // Изменяем значение флага
  337.  
  338.                             // Меняем записи местами
  339.                             STUDENT tmp = students[i];
  340.                             students[i] = students[i + 1];
  341.                             students[i + 1] = tmp;
  342.                         }
  343.                     }
  344.                 }
  345.                 break;
  346.  
  347.             case 3: // Сортировка по успеваемости (по возрастанию)
  348.                 while (isSorted == false) // Пока данные не отсортированы
  349.                 {
  350.                     isSorted = true; // Предполагаем, что данные упорядочены
  351.                     for (int i = 0; i < size - 1; ++i)
  352.                     {
  353.                         double left = students[i].academicPerformance;
  354.                         double right = students[i + 1].academicPerformance;
  355.                         if (left > right) // Если оказывается, что данные неупорядочены
  356.                         {
  357.                             isSorted = false; // Изменяем значение флага
  358.  
  359.                             // Меняем записи местами
  360.                             STUDENT tmp = students[i];
  361.                             students[i] = students[i + 1];
  362.                             students[i + 1] = tmp;
  363.                         }
  364.                     }
  365.                 }
  366.                 break;
  367.  
  368.             default: // Пользователь ввёл неожиданное число
  369.                 cout << endl << endl;
  370.                 break;
  371.             }
  372.         // Не отпускаем пользователя, пока он корректно не выберет тип сортировки
  373.         } while (choice < 0 || choice > 3);
  374.  
  375.         cout << "Данные отсортированы!" << endl;
  376.     }
  377.  
  378.     // Добавить элемент в конец
  379.     void add()
  380.     {
  381.         if (students == NULL) // Если данных нет
  382.         {
  383.             cerr << "Пусто! Введите данные с нуля! (пункт 1 или 2)" << endl;
  384.             return;
  385.         }
  386.  
  387.         cout << "Добавление элемента..." << endl;
  388.  
  389.         // Создаём временный массив для хранения существующих данных
  390.         STUDENT * tmp = new STUDENT[size];
  391.         for (int i = 0; i < size; ++i)
  392.             tmp[i] = students[i];
  393.  
  394.         // Очищаем старый массив
  395.         delete [] students;
  396.         ++size; // Инкрементируем счётчик размера
  397.         students = new STUDENT[size]; // Выделяем память под старые данные и один дополнительный элемент
  398.  
  399.         // Копируем старые данные обратно
  400.         for (int i = 0; i < size-1; ++i)
  401.             students[i] = tmp[i];
  402.        
  403.         // Очищаем временный массив
  404.         delete [] tmp;
  405.         tmp = NULL;
  406.  
  407.         // Осуществляем ввод нового элемента
  408.         cout << "Студент № " << size  << ": " << endl;
  409.         cin.ignore(32767, '\n');
  410.         cout << "Фамилия:      "; getline(cin, students[size - 1].name);
  411.         cout << "Год рождения: "; cin >> students[size - 1].yearOfBirth;
  412.         cout << "Успеваемость: "; cin >> students[size - 1].academicPerformance;
  413.  
  414.         cout << "Элемент добавлен" << endl;
  415.     }
  416.  
  417.     // Удалить последний элемент
  418.     void remove()
  419.     {
  420.         if (students == NULL) // Если данных нет
  421.         {
  422.             cerr << "Пусто!" << endl;
  423.             return;
  424.         }
  425.  
  426.         cout << "Удаление элемента..." << endl;
  427.         size--; // Декрементируем счётчик размеры
  428.         if (size <= 0) // Если удалённая запись была последней
  429.             clear(); // Безопасно удаляем все данные
  430.         cout << "Элемент номер "<< size + 1 <<" удалён!" << endl;
  431.     }
  432.  
  433. private:
  434.     STUDENT * students = NULL; // Указатель на динамический массив структур
  435.     int size = 0; // Размер динамического массива
  436. };
  437.  
  438.  
  439.  
  440. void showMenu(); // Объявление функции для вывода меню на экран
  441.  
  442. // Точка входа
  443. int main()
  444. {
  445.     SetConsoleCP(1251);
  446.     SetConsoleOutputCP(1251);
  447.  
  448.     const string fileName = "data.txt";
  449.     Student * students = NULL;
  450.  
  451.  
  452.     int choice = 0;
  453.     cout << "Инициализация..." << endl;
  454.     cout << "Ввести данные из файла (1) или вручную (2)? (1/2)" << endl;
  455.     do {
  456.         cin >> choice;
  457.  
  458.         switch (choice)
  459.         {
  460.         case 1:
  461.             students = new Student(fileName);
  462.             break;
  463.  
  464.         case 2:
  465.             students = new Student();
  466.             break;
  467.            
  468.         default:
  469.             break;
  470.         }
  471.  
  472.         cout << endl << endl;
  473.     } while (students == NULL);
  474.  
  475.  
  476.     choice = 0;
  477.     showMenu();
  478.     do {
  479.         cin >> choice;
  480.  
  481.         string nameToFind = "";
  482.         int yearToFind = 0;
  483.         double performanceToFind = 0.0;
  484.  
  485.         switch (choice)
  486.         {
  487.         case 1:
  488.             students->loadFromFile(fileName);
  489.             break;
  490.        
  491.         case 2:
  492.             students->read();
  493.             break;
  494.  
  495.         case 3:
  496.             students->saveToFile(fileName);
  497.             break;
  498.  
  499.         case 4:
  500.             students->show();
  501.             break;
  502.  
  503.         case 5:
  504.             cout << "Введите фамилию и инициалы: ";
  505.             cin.ignore(32767, '\n');
  506.             getline(cin, nameToFind);
  507.             students->find(nameToFind);
  508.             break;
  509.  
  510.         case 6:
  511.             cout << "Введите год рождения: ";
  512.             cin >> yearToFind;
  513.             students->find(yearToFind);
  514.             break;
  515.  
  516.         case 7:
  517.             cout << "Введите успеваемость: ";
  518.             cin >> performanceToFind;
  519.             students->find(performanceToFind);
  520.             break;
  521.  
  522.         case 8:
  523.             students->sort();
  524.             break;
  525.  
  526.         case 9:
  527.             students->add();
  528.             break;
  529.  
  530.         case 10:
  531.             students->remove();
  532.             break;
  533.  
  534.         case 11:
  535.             showMenu();
  536.             break;
  537.  
  538.         case 12:
  539.             delete students;
  540.             students = NULL;
  541.             cout << "Завершение работы..." << endl;
  542.  
  543.         default:
  544.             cout << endl << endl;
  545.             break;
  546.         }
  547.  
  548.         cout << "============================================================" << endl << endl;
  549.     } while (choice != 12);
  550.  
  551.     delete students;
  552.     students = NULL;
  553.     system("pause>nul");
  554.     return 0;
  555. }
  556.  
  557. int sizeofFile(ifstream * file)
  558. {
  559.     SetConsoleCP(1251);
  560.     SetConsoleOutputCP(1251);
  561.  
  562.     int n = 0;
  563.     string tmp;
  564.     while (!file->eof())
  565.     {
  566.         *file >> tmp;
  567.         ++n;
  568.     }
  569.  
  570.     file->seekg(0); // Возвращаем курсор в начало файла
  571.     return n;
  572. }
  573.  
  574. // Описание функции для вывода меню на экран
  575. void showMenu()
  576. {
  577.     cout << "=========================== Меню ===========================" << endl;
  578.     cout << "Введите 1,  чтобы загрузить данные." << endl;
  579.     cout << "Введите 2,  чтобы ввести данные." << endl;
  580.     cout << "Введите 3,  чтобы сохранить данные." << endl;
  581.     cout << "Введите 4,  чтобы вывести данные." << endl << endl;
  582.  
  583.     cout << "Введите 5,  чтобы найти студентов по фамилии." << endl;
  584.     cout << "Введите 6,  чтобы найти студентов по году рождения." << endl;
  585.     cout << "Введите 7,  чтобы найти студентов по успеваемости." << endl << endl;
  586.  
  587.     cout << "Введите 8   чтобы отсортировать данные." << endl << endl;
  588.  
  589.     cout << "Введите 9, чтобы добавить элемент в конец." << endl;
  590.     cout << "Введите 10, чтобы удалить последний элемент." << endl << endl;
  591.  
  592.     cout << "Введите 11, чтобы показать меню." << endl;
  593.     cout << "Введите 12, чтобы выйти." << endl;
  594.     cout << "============================================================" << endl;
  595.     cout << endl;
  596. }
  597.  
RAW Paste Data