Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <fstream>
- #include <windows.h>
- #include <conio.h>
- #include <string>
- using namespace std; //Пространство имён подключил для Функции FileRead, так как там используется fstream
- struct Date
- {
- int day;
- int month;
- int year;
- };
- struct Phone
- {
- char* mark;
- char* model;
- int price;
- Date date;
- };
- Phone* DefaultPhone(int &Size) //Данная функция просто возращает заранее подготовленный массив, как стандартный
- {
- Size = 1;
- Phone* phones = new Phone[Size];
- phones[0].mark = (char*)"mark";
- phones[0].model = (char*)"model";
- phones[0].price = 0;
- phones[0].date.day = 1;
- phones[0].date.month = 1;
- phones[0].date.year = 1111;
- return phones;
- }
- Phone DefaultPhone() //Возвращает один объект как стандартный, используется при редактировании объекта, когда мы отменяем изменения.
- {
- Phone phone;
- phone.mark = (char*)"mark";
- phone.model = (char*)"model";
- phone.price = 0;
- phone.date.day = 1;
- phone.date.month = 1;
- phone.date.year = 1111;
- return phone;
- }
- void FileWrite(Phone* phones, int Size) //Функция для записи в файл.
- {
- FILE* fout = fopen("Phones.txt", "w"); //Создаем указатель на потоковый файл и загружаем его в режиме чтения - "w"
- if(Size <= 0 || fout == NULL) //В случае неудачи, пишем пользователь об ошибке с файлам.
- {
- printf("Ошибка записи в файл.");
- }
- else //В случае удачи, просто заполняем файл в цикле необходимой информацией...
- {
- fprintf(fout, "%d\n", Size);
- for(int i = 0; i < Size; i++)
- {
- fprintf(fout, "%s ", phones[i].mark);
- fprintf(fout, "%s ", phones[i].model);
- fprintf(fout, "%d ", phones[i].price);
- fprintf(fout, "%d %d %d\n", phones[i].date.day, phones[i].date.month, phones[i].date.year);
- }
- }
- fclose(fout); //Файл необходимо закрыть, так как могут быть потери данных...
- }
- //Функция конвертирует C++ строки в C строки, ничего особенного
- char* cstc(string s){
- char *cstr = new char[s.length() + 1];
- strcpy(cstr, s.c_str());
- return cstr;
- }
- Phone* FileRead(int &Size){ //Чтение файла с использованием C++ fstream, так как за 2 часа опытов не удалось написать функцию, которая не использовала бы C++ fstream
- Phone* phones = NULL; //Создаем массив с объектами и не инициализируем - NULL
- ifstream f;//Создаем указатель на потоковый файл.
- f.open("Phones.txt"); //Читаем файл, в данном случае тип чтения/записи с файлом определяется в ifstream
- if(f.is_open()) //Надо проверить на успешное открытие файла.
- {
- string str; //Строки языка C++, так как обычные строки нельзя использовать в функции getline
- getline(f, str, '\n'); //Функция языка C++, так как взаимодействует со строками C++
- Size = atoi(cstc(str))? atoi(cstc(str)) : 0; //Линейное условие(ленивый if) - определяется как (Условие)? если правда : если ложь;
- if(Size > 0) //Вдруг мы пытаемся прочитать пустой файл, следует исключить...
- {
- phones = new Phone[Size]; //Мы теперь знаем, что размер больше 0, так что смело инициализируем массив объектов...
- for(int i = 0; i < Size; i++)
- {
- getline(f, str, ' '); //Схема чтения из файла в данном случае очень простая, мы просто читаем строку с помощью getline и вносим её в массив объектов.
- phones[i].mark = cstc(str);
- getline(f, str, ' ');
- phones[i].model = cstc(str);
- getline(f, str, ' ');
- phones[i].price = atoi(cstc(str));
- getline(f, str, ' ');
- phones[i].date.day = atoi(cstc(str));
- getline(f, str, ' ');
- phones[i].date.month = atoi(cstc(str));
- getline(f, str, '\n'); //Важно, здесь требуется указать не пробел(' '), а переход на следущую строку, так как мы храним данные именно в таком виде.
- phones[i].date.year = atoi(cstc(str));
- }
- }
- }
- f.close(); //куда же без закрытия файла.
- return phones;
- }
- int Write_int(bool zero = false) //Стандартная функция, без комментариев.
- {
- char str[10];
- int value;
- while(true)
- {
- scanf("%s", str);
- value = abs(atoi(str))? abs(atoi(str)) : 0;
- if (zero) break;
- if (!zero && value > 0)
- break;
- else
- printf("Введите значение |n| > 0: ");
- }
- return value;
- }
- Phone* Phone_Add(Phone* phones, int &Size, Phone newPhone) //Данная функция расширяет массив объектов и в конец добавляет новый...
- {
- Size++;
- Phone* copyPhones = new Phone[Size];
- for (int i = 0; i < Size - 1; i++)
- copyPhones[i] = phones[i];
- copyPhones[Size - 1].mark = newPhone.mark;
- copyPhones[Size - 1].model = newPhone.model;
- copyPhones[Size - 1].price = newPhone.price;
- copyPhones[Size - 1].date = newPhone.date;
- delete[] phones;
- return copyPhones;
- }
- Phone* Phone_Remove(Phone* phones, int &Size, int Index) //Функция удаляет объект путём обхода его стороной, например мы хотим удалить 6-ой элемент, сделаем это 0..5 7..10
- {
- Size--;
- Phone* copyPhones = new Phone[Size];
- for (int i = 0; i < Index; ++i)
- copyPhones[i] = phones[i];
- for (int i = Index; i < Size; ++i)
- copyPhones[i] = phones[i + 1];
- delete[] phones;
- return copyPhones;
- }
- int DateCmp(Date d1, Date d2) //Породия на strcmp, только работает не со строками, а со структурой даты.
- {
- if(d1.year > d2.year)
- return -1;
- else
- if(d1.year < d2.year)
- return 1;
- else
- {
- if(d1.month > d2.month)
- return -1;
- else
- if(d1.month < d2.month)
- return 1;
- else
- {
- if(d1.day > d2.day)
- return -1;
- else
- if(d1.day < d2.day)
- return 1;
- else
- return 0;
- }
- }
- }
- //Редактор строки
- char* strEdit(bool Number = false)
- {
- system("cls");
- HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); //Получаем объект консоли с которой будем работать.
- COORD pos; //Позиция курсора на экране.
- pos.Y = 1;
- pos.X = 0;
- char* cloneStr = NULL;
- char* str = NULL;
- printf("Строка:\n");
- while(true)
- {
- int symbol = _getch();
- //Расширение
- cloneStr = new char[pos.X + 1]; //В данном случае просто расширяем массив символов на 1
- for (int i = 0; i < pos.X; i++)
- if (str[i] != '\0')
- cloneStr[i] = str[i];
- str = new char[pos.X + 1];
- for (int i = 0; i < pos.X; i++)
- str[i] = cloneStr[i];
- delete[] cloneStr; //Кстати, данной команды в прошлых редакторах строк небыло, но она здесь очень важна, так как с каждым редактированием строки наша память засерается на пару байт.
- if (symbol >= 97 && symbol <= 122 && !Number && pos.X < 50) //Проверяем на нажатие англ клавиш.
- {
- str[pos.X] = symbol;
- printf("%c", str[pos.X]);
- pos.X++;
- }
- //Пробел
- if(symbol == 32 && !Number && pos.X < 50)
- {
- str[pos.X] = '_';
- printf("%c", ' ');
- pos.X++;
- }
- if(symbol >= 48 && symbol <= 58 && pos.X < 50 && Number) //Цифры
- {
- str[pos.X] = symbol;
- printf("%c", str[pos.X]);
- pos.X++;
- }
- if (symbol == 8 && pos.X > 0) //Backspace
- {
- str[pos.X] = ' ';
- pos.X--;
- SetConsoleCursorPosition(hConsole, pos); //Функция изменяет позицию курсора в консоли(HANDLE hConsole) на определённую позицию(COORD pos)
- printf("%s", " ");
- }
- SetConsoleCursorPosition(hConsole, pos);
- if (symbol == 13)
- {
- str[pos.X] = '\0';
- break;
- }
- }
- delete[] cloneStr; //Удаляем лишнее..
- return str;
- }
- //Редактор даты, очень похож на редактор строк...
- Date dateEdit()
- {
- system("cls");
- HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
- COORD cursor;
- cursor.X = 0;
- cursor.Y = 1;
- char* cloneStr = NULL;
- char* str = NULL;
- printf("[Дата]:\n / /"); //Данный printf очень важен, так как без его не будут показаны '/' - слешы в дате при редактировании.
- SetConsoleCursorPosition(hConsole, cursor); //Так как мы сместились с изначальной точки, то лучше было бы вернуться на неё обратно.
- while(true)
- {
- int symbol = _getch();
- //Расширение
- cloneStr = new char[cursor.X + 1];
- for (int i = 0; i < cursor.X; i++)
- if (str[i] != '\0')
- cloneStr[i] = str[i];
- str = new char[cursor.X + 1];
- for (int i = 0; i < cursor.X; i++)
- str[i] = cloneStr[i];
- delete[] cloneStr;
- if(symbol >= 48 && symbol <= 58 && cursor.X < 10)
- {
- str[cursor.X] = symbol;
- printf("%c", str[cursor.X]);
- cursor.X++;
- if(cursor.X == 2 || cursor.X == 5)
- cursor.X++;
- }
- if (symbol == 8 && cursor.X > 0)
- {
- str[cursor.X] = ' ';
- cursor.X--;
- if(cursor.X == 2 || cursor.X == 5)
- cursor.X--;
- SetConsoleCursorPosition(hConsole, cursor);
- printf("%s", " ");
- }
- SetConsoleCursorPosition(hConsole, cursor);
- if (symbol == 13 && cursor.X == 10)
- {
- str[cursor.X] = '\0';
- break;
- }
- }
- //Извлечение символ из строки "01/02/2013" и дальнейшее преобразование в число из записть в Date.
- Date date;
- char* temp = new char[3];
- temp[0] = str[0]; temp[1] = str[1]; temp[2] = '\0';
- date.day = atoi(temp);
- temp[0] = str[3]; temp[1] = str[4]; temp[2] = '\0';
- date.month = atoi(temp);
- delete[] temp; temp = new char[5];
- temp[0] = str[6]; temp[1] = str[7]; temp[2] = str[8]; temp[3] = str[9]; temp[4] = '\0';
- date.year = atoi(temp);
- delete[] temp; //Удаляем temp и str, так как мы не используем их в дальнейшем.
- delete[] str;
- return date;
- }
- //Редактор
- Phone Phone_Edit(Phone phone, bool isCreated = false)
- {
- Phone copyPhone; //Создаем объект, который будем редактировать в дальнейшем
- if(isCreated) //Тут мы копируем данные из Music music, если они были переданы.
- copyPhone = phone;
- else
- copyPhone = DefaultPhone(); //загружаем стандартный объект
- bool RUN = true;
- while(RUN)
- {
- system("cls"); //бла.. бла.. бла.. стандартное меню.
- printf("[Редактор книг]\n1.Марка\n2.Модель\n3.Цена\n4.Дата\n5.Сохранить\n6.Не сохранять.\nВыбор: ");
- switch(Write_int())
- {
- case 1:
- copyPhone.mark = strEdit(); //В случае выбора именно этой строки, мы перейдём в редактор строки, который был описан выше.
- break;
- case 2:
- copyPhone.model = strEdit();
- break;
- case 3:
- copyPhone.price = atoi(strEdit(true)); //atoi используем, потому что rating - является не строкой, а int
- break;
- case 4:
- copyPhone.date = dateEdit(); //Используем редактор Даты
- break;
- case 5:
- phone = copyPhone; //Сохраняем изменённые данные
- RUN = false;
- break;
- case 6:
- if(!isCreated)
- phone = DefaultPhone(); //или загружаем стандартные и выходим из редактора объекта.
- RUN = false;
- break;
- default:
- break;
- }
- }
- return phone;
- }
- Phone* InputPhone(Phone* phones, int &Size) //Функция для работы с объектами...
- {
- bool RUN = true;
- while(RUN){
- system("cls");
- printf("[Редактирование списка]\n1.Добавить\n2.Изменить\n3.Удалить\n4.Назад\nВыбор: ");
- switch(Write_int())
- {
- case 1:
- {
- system("cls");
- Phone newPhone = DefaultPhone();
- newPhone = Phone_Edit(newPhone);
- phones = Phone_Add(phones, Size, newPhone);
- printf("Музыка успешно была добавлена в список телефонов.\n");
- printf("Для продолжения нажмите любую клавишу...\n");
- _getch();
- break;
- }
- case 2:
- {
- system("cls");
- printf("[Изменить]\nИндекс: ");
- int index = Write_int(true);
- if(index >= Size)
- {
- printf("Вы ввели индекс, который привышает размер списка телефонов.\n");
- printf("Для продолжения нажмите любую клавишу...\n");
- _getch();
- break;
- }
- phones[index] = Phone_Edit(phones[index], true);
- printf("Телефон успешно был изменен в списке телефонов.\n");
- printf("Для продолжения нажмите любую клавишу...\n");
- _getch();
- break;
- }
- case 3:
- {
- printf("[Удаление]\nВведите индекс:\n");
- int index = Write_int(true);
- if(index >= Size)
- {
- printf("Вы ввели индекс, который привышает размер списка телефонов.\n");
- printf("Для продолжения нажмите любую клавишу...\n");
- _getch();
- break;
- }
- phones = Phone_Remove(phones, Size, index);
- printf("Телефон удален.\n");
- printf("Для продолжения нажмите любую клавишу...\n");
- _getch();
- break;
- }
- case 4:
- RUN = false;
- break;
- default:
- break;
- }
- }
- return phones;
- }
- void OutputPhone(Phone* phones, int Size){ //Функция сортировки и вывода одновременно...
- int* index = new int[Size]; //Мы сортеруем индексы, дабы не создавать разные типы данных для сортировки...
- for(int i = 0; i < Size; i++)
- index[i] = i; //Индексы не могут повторяться, так что заполняем их индивидуальными значениями.
- int temp = 0;
- bool output = false;
- system("cls");
- printf("[Вывод списка]\n1.По индексу\n2.По Марке\n3.По Модели\n4.По Цене\n5.По Дате\nВыбор: ");
- switch(Write_int())
- {
- case 1:
- output = true;
- break;
- case 2: //Сортировка по Марке
- for (int i = 0; i < Size - 1; i++) //Сортировка по пузырьковому алгоритму, расказать нечего...
- for (int j = 0; j < Size - i - 1; j++)
- if (strcmp(phones[index[j]].mark, phones[index[j + 1]].mark)> 0)
- {
- temp = index[j]; //замена индексов местами...
- index[j] = index[j + 1];
- index[j + 1] = temp;
- }
- output = true;
- break;
- case 3: //Сортировка по Модели
- for (int i = 0; i < Size - 1; i++)
- for (int j = 0; j < Size - i - 1; j++)
- if (strcmp(phones[index[j]].model, phones[index[j + 1]].model)> 0)
- {
- temp = index[j];
- index[j] = index[j + 1];
- index[j + 1] = temp;
- }
- output = true;
- break;
- case 4: //Сортировка по Цене
- for (int i = 0; i < Size - 1; i++)
- for (int j = 0; j < Size - i - 1; j++)
- if (phones[index[j]].price > phones[index[j + 1]].price)
- {
- temp = index[j];
- index[j] = index[j + 1];
- index[j + 1] = temp;
- }
- output = true;
- break;
- case 5: //Сортировка по Рейтингу
- for (int i = 0; i < Size - 1; i++)
- for (int j = 0; j < Size - i - 1; j++)
- if (DateCmp(phones[index[j]].date, phones[index[j + 1]].date) > 0) //Используем вместо strcmp DateCmp, так как нам надо сравнить даты. >(-1) <(1) ==(0)
- {
- temp = index[j];
- index[j] = index[j + 1];
- index[j + 1] = temp;
- }
- output = true;
- break;
- default:
- break;
- }
- if(output) //если мы выбрали один из типов сортировки, то сортировка уже прошла, остаётся только вывести их по сортированным индексам...
- {
- system("cls");
- printf("[Вывод списка/По индексу]\n");
- for (int i = 0; i < Size; i++)
- printf("%d) %s %s %d %d/%d/%d\n", index[i], phones[index[i]].mark,
- phones[index[i]].model, phones[index[i]].price, phones[index[i]].date.day,
- phones[index[i]].date.month, phones[index[i]].date.year);
- }
- delete[] index; //Чистим память!
- printf("Для продолжения нажмите любую клавишу...\n");
- _getch();
- }
- int main()
- {
- SetConsoleCP(1251); //Русский язык в консоли. Использовать SetLocale нет смысла, так как он изменяет видимый шрифт, но не вводимые данные...
- SetConsoleOutputCP(1251);
- int Size = 0;
- Phone* phones = NULL; //Главный массив объектов, который передается куда либо по цепочке...
- bool firstRun = true; //Для вывода надписи приветствия...
- bool RUN = true;
- while(RUN){
- system("cls");
- if(firstRun)
- {
- printf("Добро пожаловать в меню, Денис Владимирович!\nВыбирайте!\n\n");
- firstRun = false;
- }
- printf("[Меню]\n1.Загрузить список\n2.Сохранить список\n3.Вывод списка\n4.Редактирование списка\n5.Выход\nВыбор: ");
- switch(Write_int()){
- case 1:
- {
- system("cls");
- phones = FileRead(Size); //Загружаем данные из файла.
- }
- case 2:
- {
- system("cls");
- FileWrite(phones, Size); //Записываем данные в файл.
- break;
- }
- case 3:
- {
- OutputPhone(phones, Size); //Выводим данные на экран по определённым полям.
- break;
- }
- case 4:
- {
- phones = InputPhone(phones, Size); //Редактируем объекты.
- break;
- }
- case 5:
- RUN = false; //Выход)))
- break;
- }
- }
- delete[] phones; //Чистим память после работы программы.
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement