/
Vanshi77
/
Prom
Обзор
Документация
Войти
/
Vanshi77
/
Prom
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
lab6.cpp
528 строк
21 KB
Vanshi77
upload files
25 фев 2025, 19:15
25 фев 2025, 19:15
02ce433
Код
Авторство
О чём код?
#include "library.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> /* * TODO: * 1. При поиске по жанру дать возможность выбрать из списка * 2. Что происходит с памятью - разобраться (скорее всего при загрузке) * 3. При поиске по автору не дает вводить, сразу что-то находит * 4. При поиске книг с минимальным годом - вывести все подходящие * 5. Сортировка по убыванию и возрастанию. * --- * 6. Починить отмену операций * 7. Что-то странное с поиском по автору * * Я реализовала функцию глубокого копирования состояния библиотеки(copyLibrary), * которая выделяет новую память для динамических массивов книг и жанров и копирует каждый элемент отдельно, * затем в функции отмены операций перед восстановлением предыдущего состояния сначала происходит освобождение текущей памяти, * а затем с помощью новой функции глубокого копирования производится восстановление сохранённого состояния из истории. * --- * Посмотреть сохранение и загрузку в файлы */ void clearInputBuffer() { int c; while ((c = getchar()) != '\n' && c != EOF) {} } // Проверяем, что строка состоит только из цифр int isValidNumber(const char* str) { for (int i = 0; str[i] != '\0'; i++) { if (!isdigit((unsigned char)str[i])) { return 0; } } return 1; } int isValidYear(int y) { return (y >= 1400 && y <= 2050); } // Примеры функций сравнения int compareByTitle(const void* a, const void* b) { return strcmp(((const Book*)a)->title, ((const Book*)b)->title); } int compareByTitleDesc(const void* a, const void* b) { return -compareByTitle(a, b); } int compareByYear(const void* a, const void* b) { return ((const Book*)a)->year - ((const Book*)b)->year; } int compareByYearDesc(const void* a, const void* b) { return -compareByYear(a, b); } // Сравнение по автору, а затем по году издания (возрастание) int compareByAuthorThenYear(const void *a, const void *b) { const Book *bookA = (const Book *)a; const Book *bookB = (const Book *)b; int authorComparison = strcmp(bookA->author, bookB->author); if (authorComparison == 0) { return bookA->year - bookB->year; // Сортировка по возрастанию года } return authorComparison; } // Сравнение по автору, а затем по году издания (по убыванию) int compareByAuthorThenYearDesc(const void *a, const void *b) { const Book *bookA = (const Book *)a; const Book *bookB = (const Book *)b; int authorComparison = strcmp(bookB->author, bookA->author); if (authorComparison == 0) { return bookB->year - bookA->year; // Сортировка по убыванию года } return authorComparison; } // Сравнение по году издания, а затем по названию (по возрастанию) int compareByYearThenTitle(const void *a, const void *b) { const Book *bookA = (const Book *)a; const Book *bookB = (const Book *)b; int yearComparison = bookA->year - bookB->year; if (yearComparison == 0) { return strcmp(bookA->title, bookB->title); // Сортировка по возрастанию названия } return yearComparison; } // Сравнение по году издания, а затем по названию (по убыванию) int compareByYearThenTitleDesc(const void *a, const void *b) { const Book *bookA = (const Book *)a; const Book *bookB = (const Book *)b; int yearComparison = bookB->year - bookA->year; if (yearComparison == 0) { return strcmp(bookB->title, bookA->title); // Сортировка по убыванию названия } return yearComparison; } int main() { Library lib; initLibrary(&lib); LibraryHistory history; initLibraryHistory(&history, 20); loadLibrary(&lib, "library2.txt"); // Сразу сохраняем начальное состояние saveLibraryState(&history, &lib); while (1) { printf("\nДобро пожаловать в библиотеку! Выберите действие:\n"); printf("1. Распечатать библиотеку.\n"); printf("2. Добавить книгу.\n"); printf("3. Удалить книгу.\n"); printf("4. Сортировать книги.\n"); printf("5. Сохранить в файл.\n"); printf("6. Загрузить из файла.\n"); printf("7. Поиск книг.\n"); printf("8. Изменение книги.\n"); printf("9. Найти книгу с самым маленьким годом издания после заданного.\n"); printf("10. Отмена последних операций.\n"); printf("0. Выход.\n"); printf("Ваш выбор: "); int choice; if (scanf("%d", &choice) != 1) { printf("Неверный ввод.\n"); clearInputBuffer(); continue; } clearInputBuffer(); switch (choice) { case 0: { saveLibrary(&lib, "library2.txt"); freeLibrary(&lib); freeLibraryHistory(&history); printf("Программа завершена.\n"); return 0; } case 1: { // Печать printLibrary(&lib); break; } case 2: { // Добавить книгу Book newBook; memset(&newBook, 0, sizeof(newBook)); char buffer[300]; printf("Введите название книги: "); fgets(buffer, sizeof(buffer), stdin); buffer[strcspn(buffer, "\n")] = '\0'; strncpy(newBook.title, buffer, sizeof(newBook.title) - 1); printf("Введите автора книги: "); fgets(buffer, sizeof(buffer), stdin); buffer[strcspn(buffer, "\n")] = '\0'; strncpy(newBook.author, buffer, sizeof(newBook.author) - 1); while (1) { printf("Введите год издания: "); fgets(buffer, sizeof(buffer), stdin); buffer[strcspn(buffer, "\n")] = '\0'; if (!isValidNumber(buffer)) { printf("Год должен быть числом.\n"); continue; } int y = atoi(buffer); if (!isValidYear(y)) { printf("Некорректный год.\n"); continue; } newBook.year = y; break; } // При добавлении книги выводим список имеющихся жанров printf("\nИмеющиеся жанры в библиотеке:\n"); if (lib.genreCount == 0) { printf("Пока нет ни одного жанра.\n"); } else { printGenres(&lib); } printf("Введите номер жанра из списка ИЛИ введите новый жанр: "); fgets(buffer, sizeof(buffer), stdin); buffer[strcspn(buffer, "\n")] = '\0'; // Если ввели число — пытаемся выбрать существующий жанр if (isValidNumber(buffer)) { int idx = atoi(buffer); if (idx > 0 && idx <= (int)lib.genreCount) { // Выбираем жанр по индексу strncpy(newBook.genre, lib.genres[idx - 1], sizeof(newBook.genre) - 1); } else { // Неправильный номер — пусть это будет новый жанр strncpy(newBook.genre, buffer, sizeof(newBook.genre) - 1); addGenre(&lib, newBook.genre); } } else { // Ввели текст — считаем это новым жанром strncpy(newBook.genre, buffer, sizeof(newBook.genre) - 1); if (strlen(newBook.genre) > 0) { addGenre(&lib, newBook.genre); } } printf("Введите описание: "); fgets(buffer, sizeof(buffer), stdin); buffer[strcspn(buffer, "\n")] = '\0'; strncpy(newBook.description, buffer, sizeof(newBook.description) - 1); addBook(&lib, &newBook); // Сохраняем состояние ПОСЛЕ добавления saveLibraryState(&history, &lib); printf("Книга добавлена.\n"); break; } case 3: { // Удалить книгу if (lib.size == 0) { printf("Библиотека пуста.\n"); break; } char title[100]; printf("Введите название книги для удаления: "); fgets(title, sizeof(title), stdin); title[strcspn(title, "\n")] = '\0'; removeBook(&lib, title); // Сохраняем состояние ПОСЛЕ удаления saveLibraryState(&history, &lib); printf("Книга (если была) удалена.\n"); break; } case 4:{ saveLibraryState(&history, &lib); if (lib.size == 0) { printf("Библиотека пуста.\n"); } else { printf("Выберите критерий сортировки:\n"); printf("1. По названию.\n"); printf("2. По году издания.\n"); printf("3. По автору, затем по году\n"); printf("4. По году, затем по названию\n"); int sortChoice; if (scanf("%d", &sortChoice) != 1) { printf("Неверный ввод. Попробуйте снова.\n"); clearInputBuffer(); continue; } printf("Выберите порядок сортировки:\n"); printf("1. По возрастанию.\n"); printf("2. По убыванию.\n"); int sortDirection; if (scanf("%d", &sortDirection) != 1) { printf("Неверный ввод. Попробуйте снова.\n"); clearInputBuffer(); continue; } if (sortChoice == 1) { if(sortDirection == 1){ bubbleSort(&lib, compareByTitle); } else if(sortDirection == 2) { bubbleSort(&lib, compareByTitleDesc); } else{ printf("Неверный выбор направления сортировки.\n"); continue; } printLibrary(&lib); } else if (sortChoice == 2) { if (sortDirection == 1) { bubbleSort(&lib, compareByYear); } else if (sortDirection == 2) { bubbleSort(&lib, compareByYearDesc); } else { printf("Неверный выбор критерия сортировки.\n"); continue; } printLibrary(&lib); } else if (sortChoice == 3) { if (sortDirection == 1) { bubbleSort(&lib, compareByAuthorThenYear); } else if (sortDirection == 2){ bubbleSort(&lib, compareByAuthorThenYearDesc); } else { printf("Неверный выбор критерия сортировки.\n"); continue; } printLibrary(&lib); } else if (sortChoice == 4) { if (sortDirection == 1) { bubbleSort(&lib, compareByYearThenTitle); } else if (sortDirection == 2){ bubbleSort(&lib, compareByYearThenTitleDesc); } else { printf("Неверный выбор критерия сортировки.\n"); continue; } printLibrary(&lib); } break; } } case 5: { // Сохранить char filename[100]; printf("Введите имя файла для сохранения: "); fgets(filename, sizeof(filename), stdin); filename[strcspn(filename, "\n")] = '\0'; saveLibrary(&lib, filename); printf("Сохранено в '%s'.\n", filename); break; } case 6: { // Загрузить freeLibrary(&lib); initLibrary(&lib); char filename[100]; printf("Введите имя файла для загрузки: "); fgets(filename, sizeof(filename), stdin); filename[strcspn(filename, "\n")] = '\0'; loadLibrary(&lib, filename); // Сохраняем состояние ПОСЛЕ загрузки saveLibraryState(&history, &lib); printf("Загружено из '%s'.\n", filename); break; } case 7: { // Поиск if (lib.size == 0) { printf("Библиотека пуста.\n"); break; } printf("Искать по:\n1) Названию\n2) Автору\n3) Жанру\n"); int st; if (scanf("%d", &st) != 1) { clearInputBuffer(); printf("Неверный ввод.\n"); break; } clearInputBuffer(); if (st == 3) { // Поиск по жанру: выводим имеющиеся жанры printf("\nИмеющиеся жанры:\n"); if (lib.genreCount == 0) { printf("Пока нет ни одного жанра.\n"); } else { printGenres(&lib); } printf("Введите номер жанра или введите новый жанр: "); char buf[100]; fgets(buf, sizeof(buf), stdin); buf[strcspn(buf, "\n")] = '\0'; char realGenre[50] = {0}; if (isValidNumber(buf)) { int idx = atoi(buf); if (idx > 0 && idx <= (int)lib.genreCount) { strncpy(realGenre, lib.genres[idx - 1], sizeof(realGenre) - 1); } else { strncpy(realGenre, buf, sizeof(realGenre) - 1); if (strlen(realGenre) > 0) { addGenre(&lib, realGenre); } } } else { strncpy(realGenre, buf, sizeof(realGenre) - 1); if (strlen(realGenre) > 0) { addGenre(&lib, realGenre); } } searchBooks(&lib, realGenre, 3); } else { // Поиск по названию / автору char criteria[100]; printf("Введите: "); fgets(criteria, sizeof(criteria), stdin); criteria[strcspn(criteria, "\n")] = '\0'; searchBooks(&lib, criteria, st); } break; } case 8: { // Изменение книги if (lib.size == 0) { printf("Библиотека пуста.\n"); break; } char oldTitle[100]; printf("Введите название книги для изменения: "); fgets(oldTitle, sizeof(oldTitle), stdin); oldTitle[strcspn(oldTitle, "\n")] = '\0'; Book newData; memset(&newData, 0, sizeof(newData)); printf("Новое название (Enter, чтобы пропустить): "); fgets(newData.title, sizeof(newData.title), stdin); newData.title[strcspn(newData.title, "\n")] = '\0'; printf("Новый автор (Enter, чтобы пропустить): "); fgets(newData.author, sizeof(newData.author), stdin); newData.author[strcspn(newData.author, "\n")] = '\0'; char buf[100]; printf("Новый год (Enter, чтобы пропустить): "); fgets(buf, sizeof(buf), stdin); buf[strcspn(buf, "\n")] = '\0'; if (strlen(buf) > 0 && isValidNumber(buf)) { int maybeYear = atoi(buf); if (isValidYear(maybeYear)) { newData.year = maybeYear; } } // При изменении жанра — список имеющихся printf("\nИмеющиеся жанры:\n"); printGenres(&lib); printf("Введите номер жанра (или новый жанр) (Enter, чтобы пропустить): "); fgets(newData.genre, sizeof(newData.genre), stdin); newData.genre[strcspn(newData.genre, "\n")] = '\0'; if (isValidNumber(newData.genre)) { int idx = atoi(newData.genre); if (idx > 0 && idx <= (int)lib.genreCount) { strncpy(newData.genre, lib.genres[idx - 1], sizeof(newData.genre) - 1); } } else { if (strlen(newData.genre) > 0) { addGenre(&lib, newData.genre); } } printf("Новое описание (Enter, чтобы пропустить): "); fgets(newData.description, sizeof(newData.description), stdin); newData.description[strcspn(newData.description, "\n")] = '\0'; updateBook(&lib, oldTitle, &newData); // Сохраняем состояние ПОСЛЕ изменения saveLibraryState(&history, &lib); break; } case 9: { // Книга с самым маленьким годом после заданного if (lib.size == 0) { printf("Библиотека пуста.\n"); break; } int minY; printf("Введите год, после которого искать: "); if (scanf("%d", &minY) != 1) { clearInputBuffer(); printf("Неверный ввод.\n"); break; } clearInputBuffer(); ResultBook rb = findEarliestBookAfterYear(&lib, minY); if (rb.count == 0) { printf("Книги не найдены.\n"); } else { printf("Найдены книги:\n"); for (int i = 0; i < rb.count; i++) { printBook(&rb.books[i]); } } free(rb.books); rb.books = NULL; break; } case 10: { // Отмена int k; printf("Сколько операций отменить? "); if (scanf("%d", &k) != 1) { clearInputBuffer(); printf("Неверный ввод.\n"); break; } clearInputBuffer(); undoLastOperations(&history, &lib, k); break; } default: printf("Неверный пункт меню.\n"); break; } } return 0; }