Advertisement
Usow_Maxim

Lab_6.6

Dec 20th, 2017
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 22.90 KB | None | 0 0
  1. #include <fstream>
  2. #include <windows.h>
  3. #include <conio.h>
  4. #include <string>
  5.  
  6. using namespace std; //Пространство имён подключил для Функции FileRead, так как там используется fstream
  7.  
  8. struct Date
  9. {
  10.     int day;
  11.     int month;
  12.     int year;
  13. };
  14.  
  15. struct Phone
  16. {
  17.     char* mark;
  18.     char* model;
  19.     int price;
  20.     Date date;
  21. };
  22.  
  23. Phone* DefaultPhone(int &Size) //Данная функция просто возращает заранее подготовленный массив, как стандартный
  24. {
  25.     Size = 1;
  26.     Phone* phones = new Phone[Size];
  27.     phones[0].mark = (char*)"mark";
  28.     phones[0].model = (char*)"model";
  29.     phones[0].price = 0;
  30.     phones[0].date.day = 1;
  31.     phones[0].date.month = 1;
  32.     phones[0].date.year = 1111;
  33.     return phones;
  34. }
  35.  
  36. Phone DefaultPhone() //Возвращает один объект как стандартный, используется при редактировании объекта, когда мы отменяем изменения.
  37. {
  38.     Phone phone;
  39.     phone.mark = (char*)"mark";
  40.     phone.model = (char*)"model";
  41.     phone.price = 0;
  42.     phone.date.day = 1;
  43.     phone.date.month = 1;
  44.     phone.date.year = 1111;
  45.     return phone;
  46. }
  47.  
  48. void FileWrite(Phone* phones, int Size) //Функция для записи в файл.
  49. {
  50.     FILE* fout = fopen("Phones.txt", "w"); //Создаем указатель на потоковый файл и загружаем его в режиме чтения - "w"
  51.     if(Size <= 0 || fout == NULL) //В случае неудачи, пишем пользователь об ошибке с файлам.
  52.     {
  53.         printf("Ошибка записи в файл.");
  54.     }
  55.     else //В случае удачи, просто заполняем файл в цикле необходимой информацией...
  56.     {
  57.         fprintf(fout, "%d\n", Size);
  58.         for(int i = 0; i < Size; i++)
  59.         {
  60.             fprintf(fout, "%s ", phones[i].mark);
  61.             fprintf(fout, "%s ", phones[i].model);
  62.             fprintf(fout, "%d ", phones[i].price);
  63.             fprintf(fout, "%d %d %d\n", phones[i].date.day, phones[i].date.month, phones[i].date.year);
  64.         }
  65.     }
  66.     fclose(fout); //Файл необходимо закрыть, так как могут быть потери данных...
  67. }
  68.  
  69. //Функция конвертирует C++ строки в C строки, ничего особенного
  70. char* cstc(string s){
  71.     char *cstr = new char[s.length() + 1];
  72.     strcpy(cstr, s.c_str());
  73.     return cstr;
  74. }
  75.  
  76. Phone* FileRead(int &Size){ //Чтение файла с использованием C++ fstream, так как за 2 часа опытов не удалось написать функцию, которая не использовала бы C++ fstream
  77.     Phone* phones = NULL; //Создаем массив с объектами и не инициализируем - NULL
  78.     ifstream f;//Создаем указатель на потоковый файл.
  79.     f.open("Phones.txt"); //Читаем файл, в данном случае тип чтения/записи с файлом определяется в ifstream
  80.     if(f.is_open()) //Надо проверить на успешное открытие файла.
  81.     {
  82.         string str; //Строки языка C++, так как обычные строки нельзя использовать в функции getline
  83.         getline(f, str, '\n'); //Функция языка C++, так как взаимодействует со строками C++
  84.         Size = atoi(cstc(str))? atoi(cstc(str)) : 0; //Линейное условие(ленивый if) - определяется как (Условие)? если правда : если ложь;
  85.         if(Size > 0) //Вдруг мы пытаемся прочитать пустой файл, следует исключить...
  86.         {
  87.             phones = new Phone[Size]; //Мы теперь знаем, что размер больше 0, так что смело инициализируем массив объектов...
  88.             for(int i = 0; i < Size; i++)
  89.             {
  90.                 getline(f, str, ' '); //Схема чтения из файла в данном случае очень простая, мы просто читаем строку с помощью getline и вносим её в массив объектов.
  91.                 phones[i].mark = cstc(str);
  92.                 getline(f, str, ' ');
  93.                 phones[i].model = cstc(str);
  94.                 getline(f, str, ' ');
  95.                 phones[i].price = atoi(cstc(str));
  96.                 getline(f, str, ' ');
  97.                 phones[i].date.day = atoi(cstc(str));
  98.                 getline(f, str, ' ');
  99.                 phones[i].date.month = atoi(cstc(str));
  100.                 getline(f, str, '\n');  //Важно, здесь требуется указать не пробел(' '), а переход на следущую строку, так как мы храним данные именно в таком виде.
  101.                 phones[i].date.year = atoi(cstc(str));
  102.             }
  103.         }
  104.     }
  105.     f.close(); //куда же без закрытия файла.
  106.     return phones;
  107. }
  108.  
  109. int Write_int(bool zero = false) //Стандартная функция, без комментариев.
  110. {
  111.     char str[10];
  112.     int value;
  113.     while(true)
  114.     {
  115.         scanf("%s", str);
  116.         value = abs(atoi(str))? abs(atoi(str)) : 0;
  117.         if (zero) break;
  118.         if (!zero && value > 0)
  119.             break;
  120.         else
  121.             printf("Введите значение |n| > 0: ");
  122.     }
  123.     return value;
  124. }
  125.  
  126. Phone* Phone_Add(Phone* phones, int &Size, Phone newPhone) //Данная функция расширяет массив объектов и в конец добавляет новый...
  127. {
  128.     Size++;
  129.     Phone* copyPhones = new Phone[Size];
  130.     for (int i = 0; i < Size - 1; i++)
  131.         copyPhones[i] = phones[i];
  132.     copyPhones[Size - 1].mark = newPhone.mark;
  133.     copyPhones[Size - 1].model = newPhone.model;
  134.     copyPhones[Size - 1].price = newPhone.price;
  135.     copyPhones[Size - 1].date = newPhone.date;
  136.     delete[] phones;
  137.     return copyPhones;
  138. }
  139.  
  140. Phone* Phone_Remove(Phone* phones, int &Size, int Index) //Функция удаляет объект путём обхода его стороной, например мы хотим удалить 6-ой элемент, сделаем это 0..5 7..10
  141. {
  142.     Size--;
  143.     Phone* copyPhones = new Phone[Size];
  144.     for (int i = 0; i < Index; ++i)
  145.         copyPhones[i] = phones[i];
  146.     for (int i = Index; i < Size; ++i)
  147.         copyPhones[i] = phones[i + 1];
  148.     delete[] phones;
  149.     return copyPhones;
  150. }
  151.  
  152. int DateCmp(Date d1, Date d2) //Породия на strcmp, только работает не со строками, а со структурой даты.
  153. {
  154.     if(d1.year > d2.year)
  155.         return -1;
  156.     else
  157.         if(d1.year < d2.year)
  158.             return 1;
  159.         else
  160.         {
  161.             if(d1.month > d2.month)
  162.                 return -1;
  163.             else
  164.                 if(d1.month < d2.month)
  165.                     return 1;
  166.                 else
  167.                 {
  168.                     if(d1.day > d2.day)
  169.                         return -1;
  170.                     else
  171.                         if(d1.day < d2.day)
  172.                             return 1;
  173.                         else
  174.                             return 0;
  175.                 }
  176.         }
  177. }
  178.  
  179. //Редактор строки
  180. char* strEdit(bool Number = false)
  181. {
  182.     system("cls");
  183.  
  184.     HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); //Получаем объект консоли с которой будем работать.
  185.     COORD pos; //Позиция курсора на экране.
  186.     pos.Y = 1;
  187.     pos.X = 0;
  188.     char* cloneStr = NULL;
  189.     char* str = NULL;
  190.  
  191.     printf("Строка:\n");
  192.  
  193.     while(true)
  194.     {
  195.         int symbol = _getch();
  196.  
  197.         //Расширение
  198.         cloneStr = new char[pos.X + 1]; //В данном случае просто расширяем массив символов на 1
  199.         for (int i = 0; i < pos.X; i++)
  200.             if (str[i] != '\0')
  201.                 cloneStr[i] = str[i];
  202.         str = new char[pos.X + 1];
  203.         for (int i = 0; i < pos.X; i++)
  204.             str[i] = cloneStr[i];
  205.         delete[] cloneStr; //Кстати, данной команды в прошлых редакторах строк небыло, но она здесь очень важна, так как с каждым редактированием строки наша память засерается на пару байт.
  206.  
  207.         if (symbol >= 97 && symbol <= 122 && !Number && pos.X < 50) //Проверяем на нажатие англ клавиш.
  208.         {
  209.             str[pos.X] = symbol;
  210.             printf("%c", str[pos.X]);
  211.             pos.X++;
  212.         }
  213.  
  214.         //Пробел
  215.         if(symbol == 32 && !Number && pos.X < 50)
  216.         {
  217.             str[pos.X] = '_';
  218.             printf("%c", ' ');
  219.             pos.X++;
  220.         }
  221.  
  222.         if(symbol >= 48 && symbol <= 58 && pos.X < 50 && Number) //Цифры
  223.         {
  224.             str[pos.X] = symbol;
  225.             printf("%c", str[pos.X]);
  226.             pos.X++;
  227.         }
  228.  
  229.         if (symbol == 8 && pos.X > 0) //Backspace
  230.         {
  231.             str[pos.X] = ' ';
  232.             pos.X--;
  233.             SetConsoleCursorPosition(hConsole, pos); //Функция изменяет позицию курсора в консоли(HANDLE hConsole) на определённую позицию(COORD pos)
  234.             printf("%s", " ");
  235.         }
  236.  
  237.         SetConsoleCursorPosition(hConsole, pos);
  238.         if (symbol == 13)
  239.         {
  240.             str[pos.X] = '\0';
  241.             break;
  242.         }
  243.     }
  244.     delete[] cloneStr; //Удаляем лишнее..
  245.     return str;
  246. }
  247.  
  248. //Редактор даты, очень похож на редактор строк...
  249. Date dateEdit()
  250. {
  251.     system("cls");
  252.  
  253.     HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
  254.     COORD cursor;
  255.     cursor.X = 0;
  256.     cursor.Y = 1;
  257.  
  258.     char* cloneStr = NULL;
  259.     char* str = NULL;
  260.  
  261.     printf("[Дата]:\n  /  /"); //Данный printf очень важен, так как без его не будут показаны '/' - слешы в дате при редактировании.
  262.     SetConsoleCursorPosition(hConsole, cursor); //Так как мы сместились с изначальной точки, то лучше было бы вернуться на неё обратно.
  263.     while(true)
  264.     {
  265.         int symbol = _getch();
  266.  
  267.         //Расширение
  268.         cloneStr = new char[cursor.X + 1];
  269.         for (int i = 0; i < cursor.X; i++)
  270.             if (str[i] != '\0')
  271.                 cloneStr[i] = str[i];
  272.         str = new char[cursor.X + 1];
  273.         for (int i = 0; i < cursor.X; i++)
  274.             str[i] = cloneStr[i];
  275.         delete[] cloneStr;
  276.  
  277.         if(symbol >= 48 && symbol <= 58 && cursor.X < 10)
  278.         {
  279.             str[cursor.X] = symbol;
  280.             printf("%c", str[cursor.X]);
  281.             cursor.X++;
  282.             if(cursor.X == 2 || cursor.X == 5)
  283.                 cursor.X++;
  284.         }
  285.  
  286.         if (symbol == 8 && cursor.X > 0)
  287.         {
  288.             str[cursor.X] = ' ';
  289.             cursor.X--;
  290.             if(cursor.X == 2 || cursor.X == 5)
  291.                 cursor.X--;
  292.             SetConsoleCursorPosition(hConsole, cursor);
  293.             printf("%s", " ");
  294.         }
  295.  
  296.         SetConsoleCursorPosition(hConsole, cursor);
  297.         if (symbol == 13 && cursor.X == 10)
  298.         {
  299.             str[cursor.X] = '\0';
  300.             break;
  301.         }
  302.     }
  303.     //Извлечение символ из строки "01/02/2013" и дальнейшее преобразование в число из записть в Date.
  304.     Date date;
  305.     char* temp = new char[3];
  306.     temp[0] = str[0]; temp[1] = str[1]; temp[2] = '\0';
  307.     date.day = atoi(temp);
  308.  
  309.     temp[0] = str[3]; temp[1] = str[4]; temp[2] = '\0';
  310.     date.month = atoi(temp);
  311.  
  312.     delete[] temp; temp = new char[5];
  313.     temp[0] = str[6]; temp[1] = str[7]; temp[2] = str[8]; temp[3] = str[9]; temp[4] = '\0';
  314.     date.year = atoi(temp);
  315.  
  316.     delete[] temp; //Удаляем temp и str, так как мы не используем их в дальнейшем.
  317.     delete[] str;
  318.     return date;
  319. }
  320.  
  321. //Редактор
  322. Phone Phone_Edit(Phone phone, bool isCreated = false)
  323. {
  324.     Phone copyPhone; //Создаем объект, который будем редактировать в дальнейшем
  325.     if(isCreated) //Тут мы копируем данные из Music music, если они были переданы.
  326.         copyPhone = phone;
  327.     else
  328.         copyPhone = DefaultPhone(); //загружаем стандартный объект
  329.     bool RUN = true;
  330.     while(RUN)
  331.     {
  332.         system("cls"); //бла.. бла.. бла.. стандартное меню.
  333.         printf("[Редактор книг]\n1.Марка\n2.Модель\n3.Цена\n4.Дата\n5.Сохранить\n6.Не сохранять.\nВыбор: ");
  334.         switch(Write_int())
  335.         {
  336.             case 1:
  337.                 copyPhone.mark = strEdit(); //В случае выбора именно этой строки, мы перейдём в редактор строки, который был описан выше.
  338.                 break;
  339.             case 2:
  340.                 copyPhone.model = strEdit();
  341.                 break;
  342.             case 3:
  343.                 copyPhone.price = atoi(strEdit(true)); //atoi используем, потому что rating - является не строкой, а int
  344.                 break;
  345.             case 4:
  346.                 copyPhone.date = dateEdit(); //Используем редактор Даты
  347.                 break;
  348.             case 5:
  349.                 phone = copyPhone; //Сохраняем изменённые данные
  350.                 RUN = false;
  351.                 break;
  352.             case 6:
  353.                 if(!isCreated)
  354.                     phone = DefaultPhone(); //или загружаем стандартные и выходим из редактора объекта.
  355.                 RUN = false;
  356.                 break;
  357.             default:
  358.                 break;
  359.         }
  360.     }
  361.     return phone;
  362. }
  363.  
  364. Phone* InputPhone(Phone* phones, int &Size) //Функция для работы с объектами...
  365. {
  366.     bool RUN = true;
  367.     while(RUN){
  368.         system("cls");
  369.         printf("[Редактирование списка]\n1.Добавить\n2.Изменить\n3.Удалить\n4.Назад\nВыбор: ");
  370.         switch(Write_int())
  371.         {
  372.             case 1:
  373.             {
  374.                 system("cls");
  375.                 Phone newPhone = DefaultPhone();
  376.                 newPhone = Phone_Edit(newPhone);
  377.                 phones = Phone_Add(phones, Size, newPhone);
  378.                 printf("Музыка успешно была добавлена в список телефонов.\n");
  379.                 printf("Для продолжения нажмите любую клавишу...\n");
  380.                 _getch();
  381.                 break;
  382.             }
  383.             case 2:
  384.             {
  385.                 system("cls");
  386.                 printf("[Изменить]\nИндекс: ");
  387.                 int index = Write_int(true);
  388.                 if(index >= Size)
  389.                 {
  390.                     printf("Вы ввели индекс, который привышает размер списка телефонов.\n");
  391.                     printf("Для продолжения нажмите любую клавишу...\n");
  392.                     _getch();
  393.                     break;
  394.                 }
  395.                 phones[index] = Phone_Edit(phones[index], true);
  396.                 printf("Телефон успешно был изменен в списке телефонов.\n");
  397.                 printf("Для продолжения нажмите любую клавишу...\n");
  398.                 _getch();
  399.                 break;
  400.             }
  401.             case 3:
  402.             {
  403.                 printf("[Удаление]\nВведите индекс:\n");
  404.                 int index = Write_int(true);
  405.                 if(index >= Size)
  406.                 {
  407.                     printf("Вы ввели индекс, который привышает размер списка телефонов.\n");
  408.                     printf("Для продолжения нажмите любую клавишу...\n");
  409.                     _getch();
  410.                     break;
  411.                 }
  412.                 phones = Phone_Remove(phones, Size, index);
  413.                 printf("Телефон удален.\n");
  414.                 printf("Для продолжения нажмите любую клавишу...\n");
  415.                 _getch();
  416.                 break;
  417.             }
  418.             case 4:
  419.                 RUN = false;
  420.                 break;
  421.             default:
  422.                 break;
  423.         }
  424.     }
  425.     return phones;
  426. }
  427.  
  428. void OutputPhone(Phone* phones, int Size){ //Функция сортировки и вывода одновременно...
  429.     int* index = new int[Size]; //Мы сортеруем индексы, дабы не создавать разные типы данных для сортировки...
  430.     for(int i = 0; i < Size; i++)
  431.         index[i] = i; //Индексы не могут повторяться, так что заполняем их индивидуальными значениями.
  432.     int temp = 0;
  433.     bool output = false;
  434.     system("cls");
  435.     printf("[Вывод списка]\n1.По индексу\n2.По Марке\n3.По Модели\n4.По Цене\n5.По Дате\nВыбор: ");
  436.     switch(Write_int())
  437.     {
  438.         case 1:
  439.             output = true;
  440.             break;
  441.         case 2: //Сортировка по Марке
  442.             for (int i = 0; i < Size - 1; i++) //Сортировка по пузырьковому алгоритму, расказать нечего...
  443.                 for (int j = 0; j < Size - i - 1; j++)
  444.                     if (strcmp(phones[index[j]].mark, phones[index[j + 1]].mark)> 0)
  445.                     {
  446.                         temp = index[j]; //замена индексов местами...
  447.                         index[j] = index[j + 1];
  448.                         index[j + 1] = temp;
  449.                     }
  450.             output = true;
  451.             break;
  452.         case 3: //Сортировка по Модели
  453.             for (int i = 0; i < Size - 1; i++)
  454.                 for (int j = 0; j < Size - i - 1; j++)
  455.                     if (strcmp(phones[index[j]].model, phones[index[j + 1]].model)> 0)
  456.                     {
  457.                         temp = index[j];
  458.                         index[j] = index[j + 1];
  459.                         index[j + 1] = temp;
  460.                     }
  461.             output = true;
  462.             break;
  463.         case 4: //Сортировка по Цене
  464.             for (int i = 0; i < Size - 1; i++)
  465.                 for (int j = 0; j < Size - i - 1; j++)
  466.                     if (phones[index[j]].price > phones[index[j + 1]].price)
  467.                     {
  468.                         temp = index[j];
  469.                         index[j] = index[j + 1];
  470.                         index[j + 1] = temp;
  471.                     }
  472.             output = true;
  473.             break;
  474.         case 5: //Сортировка по Рейтингу
  475.             for (int i = 0; i < Size - 1; i++)
  476.                 for (int j = 0; j < Size - i - 1; j++)
  477.                     if (DateCmp(phones[index[j]].date, phones[index[j + 1]].date) > 0)  //Используем вместо strcmp DateCmp, так как нам надо сравнить даты. >(-1) <(1) ==(0)
  478.                     {
  479.                         temp = index[j];
  480.                         index[j] = index[j + 1];
  481.                         index[j + 1] = temp;
  482.                     }
  483.             output = true;
  484.             break;
  485.         default:
  486.             break;
  487.     }
  488.     if(output) //если мы выбрали один из типов сортировки, то сортировка уже прошла, остаётся только вывести их по сортированным индексам...
  489.     {
  490.         system("cls");
  491.         printf("[Вывод списка/По индексу]\n");
  492.         for (int i = 0; i < Size; i++)
  493.             printf("%d) %s %s %d %d/%d/%d\n", index[i], phones[index[i]].mark,
  494.                    phones[index[i]].model, phones[index[i]].price, phones[index[i]].date.day,
  495.                    phones[index[i]].date.month, phones[index[i]].date.year);
  496.     }
  497.     delete[] index; //Чистим память!
  498.  
  499.     printf("Для продолжения нажмите любую клавишу...\n");
  500.     _getch();
  501. }
  502.  
  503. int main()
  504. {
  505.     SetConsoleCP(1251); //Русский язык в консоли. Использовать SetLocale нет смысла, так как он изменяет видимый шрифт, но не вводимые данные...
  506.     SetConsoleOutputCP(1251);
  507.  
  508.     int Size = 0;
  509.     Phone* phones = NULL; //Главный массив объектов, который передается куда либо по цепочке...
  510.  
  511.     bool firstRun = true; //Для вывода надписи приветствия...
  512.     bool RUN = true;
  513.     while(RUN){
  514.         system("cls");
  515.         if(firstRun)
  516.         {
  517.             printf("Добро пожаловать в меню, Денис Владимирович!\nВыбирайте!\n\n");
  518.             firstRun = false;
  519.         }
  520.         printf("[Меню]\n1.Загрузить список\n2.Сохранить список\n3.Вывод списка\n4.Редактирование списка\n5.Выход\nВыбор: ");
  521.         switch(Write_int()){
  522.             case 1:
  523.             {
  524.                 system("cls");
  525.                 phones = FileRead(Size); //Загружаем данные из файла.
  526.             }
  527.             case 2:
  528.             {
  529.                 system("cls");
  530.                 FileWrite(phones, Size); //Записываем данные в файл.
  531.                 break;
  532.             }
  533.             case 3:
  534.             {
  535.                 OutputPhone(phones, Size); //Выводим данные на экран по определённым полям.
  536.                 break;
  537.             }
  538.             case 4:
  539.             {
  540.                 phones = InputPhone(phones, Size); //Редактируем объекты.
  541.                 break;
  542.             }
  543.             case 5:
  544.                 RUN = false; //Выход)))
  545.                 break;
  546.         }
  547.     }
  548.  
  549.     delete[] phones; //Чистим память после работы программы.
  550.     return 0;
  551. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement