Advertisement
coplantie

laba6.13

Dec 4th, 2019
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.25 KB | None | 0 0
  1. #define _CRTDBG_MAP_ALLOC
  2. #define _CRT_SECURE_NO_WARNINGS
  3. #include <crtdbg.h>
  4. #include <memory.h>
  5. #include <stdio.h>
  6. #include <clocale>
  7. #include <cstdlib>
  8. #include <string>
  9. #include <conio.h>
  10. #include <windows.h>
  11.  
  12. //Из 5 лабы
  13. void CopyString(char*& tmp, char*& String, int lenght, bool Creating)
  14. {
  15.     if (Creating)
  16.     {
  17.         tmp = new char[lenght];
  18.     }
  19.     for (int index = 0; index < lenght; index++)
  20.     {
  21.         tmp[index] = String[index];
  22.     }
  23. }
  24.  
  25. void PushString(int& sizeString, char*& String, char last)
  26. {
  27.     char* tmpStr = new char[sizeString + 1];
  28.     CopyString(tmpStr, String, sizeString, false);
  29.     delete[] String;
  30.     String = tmpStr;
  31.     sizeString++;
  32.     String[sizeString - 1] = last;
  33. }
  34.  
  35. void PopString(int& sizeString, char*& String)
  36. {
  37.     if (sizeString > 0)
  38.     {
  39.         sizeString--;
  40.         char* tmpStr;
  41.         CopyString(tmpStr, String, sizeString, true);
  42.         delete[] String;
  43.         String = tmpStr;
  44.     }
  45. }
  46.  
  47. void EnterString(int& sizeString, char*& String)
  48. {
  49.     char buf = 0; //Введенный символ (ввод до enter)
  50.  
  51.     while (true)
  52.     {
  53.         buf = _getch();
  54.         switch (buf)
  55.         {
  56.         case 13:
  57.         {
  58.             PushString(sizeString, String, '\0');
  59.             printf("\n");
  60.             return;
  61.         }
  62.         case 8:
  63.         {
  64.             if (sizeString > 0)//Чтобы не стереть фразу (до) на той же строке, где и ввод
  65.             {
  66.                 printf("\b");
  67.                 printf(" ");
  68.                 printf("\b");
  69.             }
  70.             PopString(sizeString, String);
  71.             break;
  72.         }
  73.         default:
  74.         {
  75.             PushString(sizeString, String, buf);
  76.             printf("%c", buf); // Так как нет эхо
  77.             break;
  78.         }
  79.         }
  80.     }
  81. }
  82.  
  83. void EnterFileString(FILE* inputFile, int& sizeString, char*& String)
  84. {
  85.     char buf = 0; //Введенный символ (ввод до enter)
  86.  
  87.     while (true)
  88.     {
  89.         buf = fgetc(inputFile);
  90.         switch (buf)
  91.         {
  92.         case EOF:
  93.         case ' ':
  94.         case 10:
  95.         {
  96.             if ((buf == 10) && (sizeString == 0))
  97.             {
  98.                 continue; //Лишние enter
  99.             }
  100.             PushString(sizeString, String, '\0');
  101.             return;
  102.         }
  103.         default:
  104.         {
  105.             PushString(sizeString, String, buf);
  106.             break;
  107.         }
  108.         }
  109.     }
  110. }
  111.  
  112. void PushVector(int& sizeVector, int*& Vector, int num)
  113. {
  114.     int* tmp = new int[sizeVector + 1];
  115.     for (int index = 0; index < sizeVector; index++)
  116.     {
  117.         tmp[index] = Vector[index];
  118.     }
  119.     delete[] Vector;
  120.     Vector = tmp;
  121.     sizeVector++;
  122.     Vector[sizeVector - 1] = num;
  123. }
  124. //Здесь заканчиваются функции из 5 лабы
  125.  
  126. //Функция для ввода значения, с проверкой принадлежности заданному диапазону
  127. //const char*, так как заранее заданная строка
  128.  
  129. int correctScanf(int min, int max, const char* text)
  130. {
  131.     int ret = 0;
  132.     while (true)
  133.     {
  134.         printf("%s: ", text);
  135.         scanf_s("%d", &ret);
  136.         if (ret < min)
  137.         {
  138.             printf("\nВведённые данные слишком малы\n");
  139.             continue; // начать с начала цикла (заново вводим)
  140.         }
  141.  
  142.         if (ret > max)
  143.         {
  144.             printf("\nВведённые данные слишком большие\n");
  145.             continue; // начать с начала цикла (заново вводим)
  146.         }
  147.         break;
  148.     }
  149.     return ret;
  150. }
  151.  
  152. int correctFileScanf(FILE* inputFile, int min, int max)
  153. {
  154.     int ret;
  155.     fscanf_s(inputFile, "%d", &ret);
  156.     if (ret < min) return min;
  157.     if (ret > max) return max;
  158.     return ret;
  159. }
  160.  
  161. struct Auto
  162. {
  163.     char* brand = nullptr;//марка
  164.     int sizeBrand = 0;// Размер строки, куда вводится название марки
  165.  
  166.     int date = 0;//дата выпуска
  167.     int volume = 0;//объем двигателя
  168.     int mileage = 0;//пробег
  169.      //+ есть поле сумма налога, которое вычисляется при необходимости
  170. };
  171.  
  172. struct Data
  173. {
  174.     Auto* cars = nullptr;
  175.     int size = 0;
  176. };
  177.  
  178. //Вычисляемое поле, налог на транспортное средство
  179. //[0;100] -> 7 | (100;250] -> 14 | (250;..) -> 30
  180. //Я написала формулы не сокращая, чтобы было понятно, откуда взялись числа
  181.  
  182. int getTax(int volume)
  183. {
  184.     int res = 0;
  185.     if (volume <= 100)
  186.         res = volume * 7;
  187.     else if (volume <= 250)
  188.         res = volume * 14;
  189.     else
  190.         res = 30 * volume;
  191.     return res;
  192. }
  193.  
  194. bool isEqual(Auto left, Auto right)
  195. {
  196.     if (strcmp(left.brand, right.brand) != 0) return false;
  197.     if (left.date != right.date) return false;
  198.     if (left.mileage != right.mileage) return false;
  199.     if (left.volume != right.volume) return false;
  200. }
  201.  
  202. bool comparisonAuto(Auto left, Auto right, int field)
  203. {
  204.     switch (field)
  205.     {
  206.     case 1:
  207.         if (left.date < right.date) return false;
  208.         break;
  209.     case 2:
  210.         if (left.volume < right.volume) return false;
  211.         break;
  212.     case 3:
  213.         if (left.mileage < right.mileage)   return false;
  214.         break;
  215.     case 4:
  216.         //Можно было бы и отсортировать по объему двигателя, так как чем он больше, тем больше и налог
  217.         //Функция налога строго возрастает
  218.         if (getTax(left.volume) < getTax(right.volume)) return false;
  219.         break;
  220.     default: // По умолчанию будет сортировка по марке
  221.  
  222.         if (strcmp(left.brand, right.brand) == -1) return false;
  223.         break;
  224.     }
  225.     return true;
  226. }
  227.  
  228. void CopyData(Data& buf, Data data, bool Creating)
  229. {
  230.     if (Creating)
  231.     {
  232.         buf.cars = new Auto[data.size];
  233.         buf.size = data.size;
  234.     }
  235.  
  236.     for (int index = 0; index < data.size; ++index)
  237.     {
  238.         buf.cars[index] = data.cars[index];
  239.         CopyString(buf.cars[index].brand, data.cars[index].brand, data.cars[index].sizeBrand, true);
  240.     }
  241. }
  242.  
  243. void deleteAuto(Auto& cars)
  244. {
  245.     delete[] cars.brand;
  246.     cars.brand = nullptr;
  247.     cars.sizeBrand = 0;
  248.     cars.date = 0;
  249.     cars.mileage = 0;
  250.     cars.volume = 0;
  251. }
  252.  
  253. void deleteData(Data& data)
  254. {
  255.     for (int i = 0; i < data.size; ++i)
  256.     {
  257.         deleteAuto(data.cars[i]);
  258.     }
  259.     delete[] data.cars;
  260.     data.cars = nullptr;
  261.     data.size = 0;
  262. }
  263.  
  264. void deleteAllPosition(Data& data, int sizeVector, int* Vector)
  265. {
  266.     if (sizeVector == data.size)//Удаляем всё
  267.     {
  268.         deleteData(data);
  269.         return;
  270.     }
  271.     if (sizeVector == 0)
  272.     {
  273.         return; //Не нашли, что удалять
  274.     }
  275.     Data buf;
  276.     buf.size = data.size - sizeVector;
  277.     buf.cars = new Auto[buf.size];
  278.  
  279.     int j = 0;
  280.     int l = 0;
  281.     for (int i = 0; i < data.size; ++i)
  282.     {
  283.         if (i != Vector[j])
  284.         {
  285.             buf.cars[l] = data.cars[i];
  286.             CopyString(buf.cars[l].brand, data.cars[i].brand, data.cars[i].sizeBrand, true);
  287.             ++l;
  288.         }
  289.         else
  290.         {
  291.             ++j;
  292.         }
  293.  
  294.     }
  295.     deleteData(data);
  296.     data = buf;
  297. }
  298.  
  299. Auto inputOne(FILE* inputFile) //Если FILE* равен nullptr, будем считать, что работаем с консолью
  300. {
  301.     Auto ret;
  302.     if (inputFile != nullptr)
  303.     {
  304.  
  305.         EnterFileString(inputFile, ret.sizeBrand, ret.brand);
  306.         ret.date = correctFileScanf(inputFile, 1800, 2019);
  307.         ret.volume = correctFileScanf(inputFile, 1, 10000);
  308.         ret.mileage = correctFileScanf(inputFile, 0, 10000000);
  309.  
  310.     }
  311.     else
  312.     {
  313.         printf("\nВведите название марки: ");
  314.         EnterString(ret.sizeBrand, ret.brand);
  315.         ret.date = correctScanf(1800, 2019, "Введите дату выпуска машины: ");
  316.         ret.volume = correctScanf(1, 10000, "Введите объем двигателя машины: ");
  317.         ret.mileage = correctScanf(0, 10000000, "Введите пробег машины: ");
  318.     }
  319.     return ret;
  320. }
  321.  
  322. void BubbleSort(Data& data, int choice)
  323. {
  324.     Auto buf;
  325.     int i = 0;
  326.     int j = 0;
  327.     //Сортировка пузырьком
  328.     for (i = 0; i < data.size; ++i)
  329.     {
  330.         for (j = 0; j < data.size - 1 - i; ++j) //До конца нет смысла доходить, так как 'пузырьки' всплывают
  331.         {
  332.             if (comparisonAuto(data.cars[j], data.cars[j + 1], choice))
  333.             {
  334.                 buf = data.cars[j];
  335.                 data.cars[j] = data.cars[j + 1];
  336.                 data.cars[j + 1] = buf;
  337.             }
  338.         }
  339.     }
  340. }
  341.  
  342. void outData(Data data)
  343. {
  344.     for (int i = 0; i < data.size; ++i)
  345.     {
  346.         printf("%d-я машина\n", i + 1);
  347.         printf("Марка машины: %s\n", data.cars[i].brand);
  348.         printf("Дата выпуска: %d\n", data.cars[i].date);
  349.         printf("Объём двигателя: %d\n", data.cars[i].volume);
  350.         printf("Пробег: %d\n", data.cars[i].mileage);
  351.         printf("Налог: %d\n\n", getTax(data.cars[i].volume));
  352.     }
  353. }
  354.  
  355. void outFileData(FILE* outputFile, Data data)
  356. {
  357.     fprintf(outputFile, "%d\n", data.size);
  358.     for (int i = 0; i < data.size; ++i)
  359.     {
  360.         fprintf(outputFile, "%s\n", data.cars[i].brand);
  361.         fprintf(outputFile, "%d\n", data.cars[i].date);
  362.         fprintf(outputFile, "%d\n", data.cars[i].volume);
  363.         fprintf(outputFile, "%d\n", data.cars[i].mileage);
  364.     }
  365. }
  366.  
  367. void output(Data& data, int choiceSort, bool withFile)
  368. {
  369.     FILE* outputFile = nullptr;
  370.  
  371.    
  372.  
  373.     if (choiceSort >= 0)//Есть сортировка
  374.     {
  375.         BubbleSort(data, choiceSort);
  376.     }
  377.     if (withFile)
  378.     {
  379.         fopen_s(&outputFile, "in.txt", "w");
  380.         if (outputFile == NULL)
  381.         {
  382.             fprintf(stderr, "Не удалось открыть файл");
  383.         }
  384.         outFileData(outputFile, data);
  385.         fclose(outputFile);
  386.  
  387.     }
  388.     else
  389.     {
  390.         outData(data);
  391.     }
  392. }
  393.  
  394. void input(Data& data, bool withFile)
  395. {
  396.     int i = 0;
  397.     int j = 0; // Чтобы записывать, начиная с середины (то есть дополнять массив)
  398.     int num = 0;
  399.     FILE* inputFile = nullptr;
  400.     if (withFile)
  401.     {
  402.         fopen_s(&inputFile, "in.txt", "r");
  403.         if (inputFile == NULL)
  404.         {
  405.             printf("Файл не найден!\n");
  406.             exit(0);
  407.         }
  408.         if (getc(inputFile) == EOF)
  409.         {
  410.             printf("Файл пуст!");
  411.             exit(0);
  412.         }
  413.         fclose(inputFile);
  414.         FILE* inputFile = nullptr;
  415.         fopen_s(&inputFile, "in.txt", "r");
  416.         num = correctFileScanf(inputFile, 0, 100000);
  417.     }
  418.     else
  419.     {
  420.         num = correctScanf(0, 100000, "Введите количество машин");
  421.     }
  422.     j = data.size;
  423.     Data buf;
  424.     CopyData(buf, data, true);
  425.     deleteData(data);
  426.     data.size = buf.size + num;
  427.     if (data.size > 0)
  428.     {
  429.         data.cars = new Auto[data.size];
  430.     }
  431.     CopyData(data, buf, false);
  432.     deleteData(buf);
  433.     for (i = 0; i < num; i++, j++)
  434.     {
  435.         data.cars[j] = inputOne(inputFile);
  436.     }
  437.     fclose(inputFile);
  438. }
  439.  
  440. void deleteData(Data& data, int choice)
  441. {
  442.     if (data.size == 0)
  443.     {
  444.         printf("\n-------   Массив пуст, удалять нечего -----\n");
  445.         return;
  446.     }
  447.  
  448.     int* whoIsDelete = nullptr;
  449.     int num = 0;
  450.     int i = 0;
  451.     int amount = 0;
  452.     Auto buf; //Для считывания, а потом поиска на соответствие
  453.     switch (choice)
  454.     {
  455.     case 0:
  456.     {
  457.         //Приводим к общему типу (якобы могло быть несколько удаляемых объектов
  458.         whoIsDelete = new int[1];
  459.         num = correctScanf(1, data.size, "Введите порядковый номер");
  460.         whoIsDelete[0] = num - 1;
  461.         amount = 1;
  462.         break;
  463.     }
  464.     case 1:
  465.     {
  466.         printf("\n Введите название марки :");
  467.         char* brand = nullptr;
  468.         int sizeBrand = 0;
  469.         EnterString(sizeBrand, brand);
  470.         for (i = 0; i < data.size; ++i)
  471.         {
  472.             if (strcmp(brand, data.cars[i].brand) == 0)
  473.             {
  474.                 PushVector(amount, whoIsDelete, i);
  475.             }
  476.         }
  477.         delete[] brand;
  478.         break;
  479.     }
  480.     case 2:
  481.     {
  482.         buf = inputOne(nullptr); // Всегда считываем с консоли
  483.         for (i = 0; i < data.size; ++i)
  484.         {
  485.             if (isEqual(buf, data.cars[i]))
  486.             {
  487.                 PushVector(amount, whoIsDelete, i);
  488.             }
  489.         }
  490.         deleteAuto(buf);
  491.         break;
  492.     }
  493.     }
  494.  
  495.     deleteAllPosition(data, amount, whoIsDelete);
  496.     delete[] whoIsDelete;
  497. }
  498.  
  499. void choiceDelete(Data& data)
  500. {
  501.     printf("\n Если хотите отменить, введите \"no\"\n если хотите продолжить, можете ввести любую строку :");
  502.     char* cancel = nullptr;
  503.     int size = 0;
  504.     EnterString(size, cancel);
  505.     if (strcmp(cancel, "no") != 0)
  506.     {
  507.         deleteData(data);
  508.     }
  509.     delete[] cancel;
  510. }
  511.  
  512. void menuSortData(Data& data)
  513. {
  514.     int choice = 0;
  515.     while (true)
  516.     {
  517.         printf("\n-------   Подменю сортировки данных  -----\n");
  518.         printf("0 - Удалить всё\n");
  519.         printf("1 - Отсортировать по названию марки\n");
  520.         printf("2 - Отсортировать по году выпуску\n");
  521.         printf("3 - Отсортировать по объёму двигателя\n");
  522.         printf("4 - Отсортировать по пробегу\n");
  523.         printf("5 - Отсортировать по сумме налога на т.с.\n");
  524.  
  525.         printf("8 - выйти из меню ввода данных\n");
  526.         scanf_s("%d", &choice);
  527.         switch (choice)
  528.         {
  529.         case 0:
  530.         {
  531.             choiceDelete(data);
  532.             break;
  533.         }
  534.         case 1:
  535.         case 2:
  536.         case 3:
  537.         case 4:
  538.         case 5:
  539.         {
  540.             BubbleSort(data, choice - 1);
  541.             break;
  542.         }
  543.         case 8:
  544.         {
  545.             return;
  546.         }
  547.         default:
  548.         {
  549.             printf("\n данной функции в программе нет\n");
  550.             break;
  551.         }
  552.         }
  553.     }
  554. }
  555.  
  556. void menuDeleteData(Data& data)
  557. {
  558.     int choice = 0;
  559.     while (true)
  560.     {
  561.         printf("\n-------   Подменю удаления данных  -----\n");
  562.         printf("0 - Удалить всё\n");
  563.         printf("1 - удалить сведения о машине по порядковому номеру в массиве (от единицы)\n");
  564.         printf("2 - удалить сведения всех машин указанной марки\n");
  565.         printf("3 - удалить сведения о машине по совпадению всех данных\n");
  566.  
  567.         printf("8 - выйти из меню ввода данных\n");
  568.         scanf_s("%d", &choice);
  569.         switch (choice)
  570.         {
  571.         case 0:
  572.         {
  573.             choiceDelete(data);
  574.             break;
  575.         }
  576.         case 1:
  577.         case 2:
  578.         case 3:
  579.         {
  580.             deleteData(data, choice - 1);
  581.             break;
  582.         }
  583.         case 8:
  584.         {
  585.             return;
  586.         }
  587.         default:
  588.         {
  589.             printf("\n данной функции в программе нет\n");
  590.             break;
  591.         }
  592.         }
  593.     }
  594. }
  595.  
  596. void menuOutputData(Data& data)
  597. {
  598.     int choice = 0;
  599.     while (true)
  600.     {
  601.         printf("\n-------   Подменю вывода данных  -----\n");
  602.         printf("0 - Удалить всё\n");
  603.         printf("1 - вывести данные на консоль (без сортировки)\n");
  604.         printf("2 - Отсортировать по названию марки (консоль)\n");
  605.         printf("3 - Отсортировать по году выпуску (консоль)\n");
  606.         printf("4 - Отсортировать по объёму двигателя (консоль)\n");
  607.         printf("5 - Отсортировать по пробегу (консоль)\n");
  608.         printf("6 - Отсортировать по сумме налога на т.с. (консоль)\n");
  609.  
  610.         printf("\n------------------\n");
  611.         printf("7 - вывести данные в файл (без сортировки)\n");
  612.         printf("8 - Отсортировать по названию марки (в файл)\n");
  613.         printf("9 - Отсортировать по году выпуску (в файл)\n");
  614.         printf("10 - Отсортировать по объёму двигателя (в файл)\n");
  615.         printf("11 - Отсортировать по пробегу (в файл)\n");
  616.         printf("12 - Отсортировать по сумме налога на т.с. (в файл)\n");
  617.  
  618.         printf("13 - выйти из меню вывода данных\n");
  619.  
  620.         scanf_s("%d", &choice);
  621.  
  622.         if (choice == 0)
  623.         {
  624.             choiceDelete(data);
  625.         }
  626.         else
  627.         {
  628.             if (choice <= 6)
  629.             {
  630.                 output(data, choice - 2, false);
  631.             }
  632.             else
  633.             {
  634.                 if (choice <= 12)
  635.                 {
  636.                     output(data, choice - 8, true);
  637.                 }
  638.                 else
  639.                 {
  640.                     if (choice == 13)
  641.                     {
  642.                         return;
  643.                     }
  644.                     printf("\n данной функции в программе нет\n");
  645.                 }
  646.             }
  647.         }
  648.  
  649.  
  650.     }
  651. }
  652.  
  653. void menuInputData(Data& data)
  654. {
  655.     int choice = 0;
  656.     while (true)
  657.     {
  658.         printf("\n-------   Подменю ввода данных  -----\n");
  659.         printf("0 - Удалить всё\n");
  660.         printf("1 - добавить данные с консоли в конец\n");
  661.         printf("2 - добавить данные с указанного файла в конец\n");
  662.         printf("8 - выйти из меню ввода данных\n");
  663.         scanf_s("%d", &choice);
  664.         switch (choice)
  665.         {
  666.         case 0:
  667.         {
  668.             choiceDelete(data);
  669.             break;
  670.         }
  671.         case 1:
  672.         case 2:
  673.         {
  674.             input(data, choice == 2);
  675.             break;
  676.         }
  677.         case 8:
  678.         {
  679.             printf("\n");
  680.             return;
  681.         }
  682.         default:
  683.         {
  684.             printf("\n Данной функции в программе нет\n");
  685.             break;
  686.         }
  687.         }
  688.     }
  689. }
  690.  
  691. int main()
  692. {
  693.     setlocale(LC_ALL, "");
  694.  
  695.     int choice = 0;
  696.     Data data;
  697.     while (true)
  698.     {
  699.         printf("0 - Ввод данных\n");
  700.         printf("1 - Удаление данных\n");
  701.         printf("2 - Вывод данных\n");
  702.         printf("3 - Сортировка данных\n");
  703.  
  704.         printf("8 - выйти\n");
  705.         scanf_s("%d", &choice);
  706.         switch (choice)
  707.         {
  708.         case 0:
  709.         {
  710.             menuInputData(data);
  711.             break;
  712.         }
  713.         case 1:
  714.         {
  715.             menuDeleteData(data);
  716.             break;
  717.         }
  718.         case 2:
  719.         {
  720.             menuOutputData(data);
  721.             break;
  722.         }
  723.         case 3:
  724.         {
  725.             menuSortData(data);
  726.             break;
  727.         }
  728.         case 8:
  729.         {
  730.             printf("\nдля завершения программы нажмите Enter...\n");
  731.             getchar();
  732.             deleteData(data);
  733.             _CrtDumpMemoryLeaks();
  734.             return 0;
  735.         }
  736.         default:
  737.         {
  738.             printf("\n данной функции в программе нет\n");
  739.             break;
  740.         }
  741.         }
  742.     }
  743. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement