/
Vanshi77
/
Prom
Обзор
Документация
Войти
/
Vanshi77
/
Prom
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
library.cpp
428 строк
15 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 <limits.h> #include <iostream> const char* bookGenres[] = { "Novel", "Fiction", "Mystery", "Thriller", "Autobiography", "Science Fiction", "Fantasy", "Romance", "Historical Fiction", "Horror", "Adventure", "Non-Fiction", "Biography", "Memoir", "Self-Help", "Science", "Humor", "Poetry", "Graphic Novel" }; const size_t numGenres = sizeof(bookGenres) / sizeof(bookGenres[0]); //глубокое копирование библиотеки static void copyLibrary(Library* dest, const Library* src) { //static-эта функция видна только в пределах текущего файла (единицы компиляции) dest->size = src->size;//Копирует значение size (размер) из исходной библиотеки (src) в целевую библиотеку (dest) dest->capacity = src->capacity;//Копирует значение capacity (вместимость) из исходной библиотеки (src) в целевую библиотеку (dest) dest->books = (Book*)malloc(dest->capacity * sizeof(Book));//память для массива книг в целевой библиотеке if (!dest->books) { fprintf(stderr, "Ошибка выделения памяти для книг\n"); exit(1); } for (size_t i = 0; i < dest->size; i++) { dest->books[i] = src->books[i];//копирует каждую книгу из исходной библиотеки (src) в целевую библиотеку (dest) } dest->genreCount = src->genreCount;//Копирует количество жанров dest->genreCapacity = src->genreCapacity;//Копирует вместимость массива жанров dest->genres = (char**)malloc(dest->genreCapacity * sizeof(char*));//память для массива указателей на строки (жанры) в целевой библиотеке if (!dest->genres) { fprintf(stderr, "Ошибка выделения памяти для жанров\n"); exit(1); } for (size_t i = 0; i < dest->genreCount; i++) { dest->genres[i] = strdup(src->genres[i]);//выделяет новую память и копирует строку из src->genres[i] в эту новую память. Это необходимо, чтобы целевая библиотека имела собственные копии строк жанров, а не просто указывала на те же строки, что и исходная библиотека if (!dest->genres[i]) { fprintf(stderr, "Ошибка выделения памяти для жанра\n"); exit(1); } } } void initLibraryHistory(LibraryHistory* history, int capacity) { history->states = (Library*)malloc(capacity * sizeof(Library)); if (!history->states) { fprintf(stderr, "Ошибка выделения памяти для истории\n"); exit(1); } history->capacity = capacity; history->size = 0; history->current = -1; } void freeLibraryHistory(LibraryHistory* history) { for (int i = 0; i < history->size; i++) { freeLibrary(&history->states[i]); } free(history->states); history->states = NULL; history->capacity = 0; history->size = 0; history->current = -1; } //Сохраняем текущее (уже обновлённое) состояние библиотеки. при переполнении мы корректно копируем вс с помощью deep copy, чтобы не было проблем с дублированием. void saveLibraryState(LibraryHistory* history, const Library* lib) { if (history->size == history->capacity) { // Удаляем самое старое состояние и сдвигаем оставшиеся freeLibrary(&history->states[0]); for (int i = 1; i < history->size; i++) { // После освобождения 0-го элемента делаем полноценную копию // из states[i] в states[i-1], чтобы не было "шальных" указателей initLibrary(&history->states[i - 1]); // TODO: сделать shallow-copy, без глубокого копирования данных copyLibrary(&history->states[i - 1], &history->states[i]); freeLibrary(&history->states[i]); } history->size--; history->current = history->size - 1; } // Создаём новую копию библиотеки в history->states[history->size] initLibrary(&history->states[history->size]); copyLibrary(&history->states[history->size], lib); history->size++; history->current = history->size - 1; } //Отмена последних k операций. Переходим на history->current - k. void undoLastOperations(LibraryHistory* history, Library* lib, int k) { if (k <= 0) { printf("Количество операций для отмены должно быть > 0.\n"); return; } int newIndex = history->current - k; if (newIndex < 0) { printf("Невозможно отменить %d операций: всего %d состояний.\n", k, history->current); return; } // Освобождаем текущую библиотеку freeLibrary(lib); // Восстанавливаем copyLibrary(lib, &history->states[newIndex]); // TODO: утекает пямять, если k > 1 // изменить size? history->current = newIndex; printf("Отмена %d операций выполнена.\n", k); } void initLibrary(Library* lib) { lib->books = (Book*)malloc(10 * sizeof(Book)); lib->size = 0; lib->capacity = 10; lib->genres = (char**)malloc(10 * sizeof(char*)); lib->genreCount = 0; lib->genreCapacity = 10; } void freeLibrary(Library* lib) { if (lib->books) { free(lib->books); lib->books = NULL; } if (lib->genres) { for (size_t i = 0; i < lib->genreCount; i++) { free(lib->genres[i]); } free(lib->genres); lib->genres = NULL; } lib->size = 0; lib->capacity = 0; lib->genreCount = 0; lib->genreCapacity = 0; } void addBook(Library* lib, const Book* book) { if (lib->size == lib->capacity) { enlargeLibrary(lib); } lib->books[lib->size++] = *book; } void removeBook(Library* lib, const char* title) { for (size_t i = 0; i < lib->size; i++) { if (strcmp(lib->books[i].title, title) == 0) { for (size_t j = i; j < lib->size - 1; j++) { lib->books[j] = lib->books[j + 1]; } lib->size--; break; } } } Book* findBookByTitle(Library* lib, const char* title) { for (size_t i = 0; i < lib->size; i++) { if (strcmp(lib->books[i].title, title) == 0) { return &lib->books[i]; } } return NULL; } void updateBook(Library* lib, const char* title, const Book* newBook) { Book* old = findBookByTitle(lib, title); if (!old) { printf("Книга '%s' не найдена.\n", title); return; } if (strlen(newBook->title) > 0) { strncpy(old->title, newBook->title, sizeof(old->title) - 1); old->title[sizeof(old->title) - 1] = '\0'; } if (strlen(newBook->author) > 0) { strncpy(old->author, newBook->author, sizeof(old->author) - 1); old->author[sizeof(old->author) - 1] = '\0'; } if (newBook->year > 0) { old->year = newBook->year; } if (strlen(newBook->genre) > 0) { strncpy(old->genre, newBook->genre, sizeof(old->genre) - 1); old->genre[sizeof(old->genre) - 1] = '\0'; } if (strlen(newBook->description) > 0) { strncpy(old->description, newBook->description, sizeof(old->description) - 1); old->description[sizeof(old->description) - 1] = '\0'; } printf("Книга успешно обновлена.\n"); } void printBook(const Book* book) { printf("Title: %s\nAuthor: %s\nYear: %d\nGenre: %s\nDescription: %s\n\n", book->title, book->author, book->year, book->genre, book->description); } void printLibrary(const Library* lib) { if (lib->size == 0) { printf("Библиотека пуста.\n"); return; } for (size_t i = 0; i < lib->size; i++) { printBook(&lib->books[i]); } } void bubbleSort(Library *lib, int (*compare)(const void *, const void *)) { if (!lib || lib->size <= 1) return; for (size_t i = 0; i < lib->size - 1; i++) { for (size_t j = 0; j < lib->size - i - 1; j++) { if (compare(&lib->books[j], &lib->books[j + 1]) > 0) { Book tmp = lib->books[j]; lib->books[j] = lib->books[j + 1]; lib->books[j + 1] = tmp; } } } } void insertionSort(Library* lib, int (*comparator)(const void*, const void*)) { if (!lib || lib->size <= 1) return; for (size_t i = 1; i < lib->size; i++) { Book key = lib->books[i]; size_t j = i; while (j > 0 && comparator(&lib->books[j - 1], &key) > 0) { lib->books[j] = lib->books[j - 1]; j--; } lib->books[j] = key; } } void searchBooks(const Library* lib, const char* criteria, int searchType) { if (!lib || lib->size == 0) { printf("Библиотека пуста.\n"); return; } int found = 0; for (size_t i = 0; i < lib->size; i++) { const Book* b = &lib->books[i]; if (searchType == 1) { // По названию if (strcmp(b->title, criteria) == 0) { printBook(b); found = 1; } } else if (searchType == 2) { // По автору if (strcmp(b->author, criteria) == 0) { printBook(b); found = 1; } } else if (searchType == 3) { // По жанру if (strcmp(b->genre, criteria) == 0) { printBook(b); found = 1; } } else { printf("Неверный тип поиска.\n"); return; } } if (!found) { printf("Книги не найдены.\n"); } } void enlargeLibrary(Library* lib) { lib->capacity = (size_t)(lib->capacity * 1.5); Book* newB = (Book*)realloc(lib->books, lib->capacity * sizeof(Book)); if (!newB) { fprintf(stderr, "Ошибка realloc (books)\n"); exit(1); } lib->books = newB; } void enlargeGenres(Library* lib) { lib->genreCapacity = (size_t)(lib->genreCapacity * 1.5); char** newG = (char**)realloc(lib->genres, lib->genreCapacity * sizeof(char*)); if (!newG) { fprintf(stderr, "Ошибка realloc (genres)\n"); exit(1); } lib->genres = newG; } void addGenre(Library* lib, const char* genre) { if (lib->genreCount == lib->genreCapacity) { enlargeGenres(lib); } lib->genres[lib->genreCount] = strdup(genre); lib->genreCount++; } void printGenres(const Library* lib) { if (!lib || !lib->genres || lib->genreCount == 0) { printf("Пока нет жанров.\n"); return; } for (size_t i = 0; i < lib->genreCount; i++) { printf("%zu) %s\n", i + 1, lib->genres[i]); } } int findGenreIndex(const Library* lib, const char* genre) { for (size_t i = 0; i < lib->genreCount; i++) { if (strcmp(lib->genres[i], genre) == 0) { return (int)i; } } return -1; } void saveLibraryToFile(const Library* lib, const char* filename) { FILE* f = fopen(filename, "w"); if (!f) { perror("Не удалось открыть файл для записи"); return; } for (size_t i = 0; i < lib->size; i++) { fprintf(f, "%s\n%s\n%d\n%s\n%s\n", lib->books[i].title, lib->books[i].author, lib->books[i].year, lib->books[i].genre, lib->books[i].description); } fclose(f); } void loadLibraryFromFile(Library* lib, const char* filename) { FILE* f = fopen(filename, "r"); if (!f) { return; } Book tmp; while (fscanf(f, "%99[^\n]\n%99[^\n]\n%d\n%49[^\n]\n%255[^\n]\n", tmp.title, tmp.author, &tmp.year, tmp.genre, tmp.description) == 5) { addBook(lib, &tmp); } fclose(f); } // Жанры (в отдельном файле genres.txt) void loadGenresFromFile(Library* lib, const char* filename) { FILE* f = fopen(filename, "r"); if (!f) return; char line[50]; while (fgets(line, sizeof(line), f)) { line[strcspn(line, "\n")] = '\0'; addGenre(lib, line); } fclose(f); } void saveGenresToFile(const Library* lib, const char* filename) { FILE* f = fopen(filename, "w"); if (!f) { perror("Не удалось открыть файл для записи жанров"); return; } for (size_t i = 0; i < lib->genreCount; i++) { fprintf(f, "%s\n", lib->genres[i]); } fclose(f); } void loadLibrary(Library* lib, const char* filename) { loadLibraryFromFile(lib, filename); loadGenresFromFile(lib, "genres.txt"); } void saveLibrary(const Library* lib, const char* filename) { saveLibraryToFile(lib, filename); saveGenresToFile(lib, "genres.txt"); } ResultBook findEarliestBookAfterYear(Library *lib, int minYear) { ResultBook result = {NULL, 0, 0}; if (!lib || lib->size == 0) { return result; } int earliestYear = INT_MAX; for (int i = 0; i < (int)lib->size; i++) { if (lib->books[i].year > minYear && lib->books[i].year < earliestYear) { earliestYear = lib->books[i].year; } } if (earliestYear == INT_MAX) { return result; } for (int i = 0; i < (int)lib->size; i++) { if (lib->books[i].year == earliestYear) { if (result.count >= result.capacity) { result.capacity = (result.capacity == 0) ? 1 : result.capacity * 2; Book* newMem = (Book*)realloc(result.books, result.capacity * sizeof(Book)); if (!newMem) { fprintf(stderr, "Ошибка realloc\n"); free(result.books); result.books = NULL; result.count = 0; result.capacity = 0; return result; } result.books = newMem; } result.books[result.count] = lib->books[i]; result.count++; } } return result; } void displayGenres() { std::cout << "Стандартные жанры (пример):\n"; for (size_t i = 0; i < numGenres; i++) { std::cout << i + 1 << ") " << bookGenres[i] << std::endl; } }