From 4b8e15e5296ed6a920a323c57970ebbc7c49706c Mon Sep 17 00:00:00 2001 From: NikolaichukAlV Date: Wed, 15 Jan 2025 18:57:01 +0000 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=204.?= =?UTF-8?q?=20=D0=9D=D0=B0=D0=BF=D0=B8=D1=81=D0=B0=D1=82=D1=8C=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D0=B3=D1=80=D0=B0=D0=BC=D0=BC=D1=83=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B8?= =?UTF-8?q?=20=D1=82=D0=B5=D0=BA=D1=81=D1=82=D0=BE=D0=B2=D0=BE=D0=B3=D0=BE?= =?UTF-8?q?=20=D1=84=D0=B0=D0=B9=D0=BB=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lab04_task4.cpp | 178 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 lab04_task4.cpp diff --git a/lab04_task4.cpp b/lab04_task4.cpp new file mode 100644 index 0000000..dac5797 --- /dev/null +++ b/lab04_task4.cpp @@ -0,0 +1,178 @@ +#include +#include // Для функций работы с файлами и C-строками +#include // Для функций работы со строками +#include // Для функций проверки символов +#include // Для функций выделения памяти +#include // Для функции setlocale + +using namespace std; + +// Максимальная длина имени файла (предположим 260 символов, типичная максимальная длина пути в Windows) +const size_t MAX_FILENAME_LENGTH = 260; + +// Максимальная длина строки для поиска (предположим 256 символов) +const size_t MAX_SEARCH_STRING_LENGTH = 256; + +// Запрещенные символы в имени файла +const char* forbidden_chars = "*\"<>?|"; + +// Функция для проверки корректности имени файла +bool isValidFilename(const char* filename) { + // Проверка на наличие запрещенных символов + for (size_t i = 0; i < strlen(forbidden_chars); ++i) { + if (strchr(filename, forbidden_chars[i]) != nullptr) { + return false; + } + } + + // Проверка на двоеточие + const char* colon = strchr(filename, ':'); + if (colon != nullptr) { + // Двоеточие должно быть вторым символом + if (colon - filename != 1) { + return false; + } + // Первый символ должен быть буквой + if (!isalpha(filename[0])) { + return false; + } + // После двоеточия должна идти обратная косая черта + if (*(colon + 1) != '\\') { + return false; + } + } + + // Проверка расширения файла + const char* dot = strrchr(filename, '.'); + if (dot != nullptr) { + // Проверяем, что расширение .txt (без учета регистра) + if (strlen(dot) != 4) { // Длина должна быть 4 символа: '.' + 'txt' + return false; + } + // Преобразуем расширение к нижнему регистру для сравнения + char ext[5]; + strncpy(ext, dot, 4); + ext[4] = '\0'; + for (int i = 0; i < 4; ++i) { + ext[i] = tolower(ext[i]); + } + if (strcmp(ext, ".txt") != 0) { + return false; + } + } + + return true; +} + +// Функция для добавления расширения .txt, если его нет +void addTxtExtension(char* filename) { + if (strrchr(filename, '.') == nullptr) { + // Добавляем .txt + strcat(filename, ".txt"); + } +} + +int main() { + // Устанавливаем локализацию на русский язык + setlocale(LC_ALL, "Russian"); // Для Linux/macOS + // В случае Windows можно использовать setlocale(LC_ALL, "Russian"); + + // 4.1. Запросить у пользователя имя файла, сохранив его в массиве символов на стеке + char filename[MAX_FILENAME_LENGTH]; + cout << "Введите имя файла: "; + cin.getline(filename, MAX_FILENAME_LENGTH); + + // 4.2. Проверка корректности имени файла + if (!isValidFilename(filename)) { + cout << "Некорректное имя файла." << endl; + return 1; // Завершаем программу с ошибкой + } + + // 4.3. Добавить расширение .txt, если его нет + addTxtExtension(filename); + + // Повторная проверка после добавления расширения + if (!isValidFilename(filename)) { + cout << "Некорректное имя файла после добавления расширения." << endl; + return 1; + } + + // 4.4. Загрузка содержимого файла в память + // Открываем файл в бинарном режиме для точного определения размера + FILE* file = fopen(filename, "rb"); + if (file == nullptr) { + cout << "Не удалось открыть файл: " << filename << endl; + return 1; + } + + // Перемещаемся в конец файла + if (fseek(file, 0, SEEK_END) != 0) { + cout << "Ошибка при перемещении в конец файла." << endl; + fclose(file); + return 1; + } + + // Определяем размер файла + long file_size = ftell(file); + if (file_size == -1L) { + cout << "Не удалось определить размер файла." << endl; + fclose(file); + return 1; + } + + // Возвращаемся в начало файла + rewind(file); + + // Выделяем динамическую память для содержимого файла (+1 для завершающего нуля) + char* file_content = (char*)malloc(file_size + 1); + if (file_content == nullptr) { + cout << "Не удалось выделить память для содержимого файла." << endl; + fclose(file); + return 1; + } + + // Читаем содержимое файла + size_t read_size = fread(file_content, sizeof(char), file_size, file); + if (read_size != (size_t)file_size) { + cout << "Ошибка при чтении файла." << endl; + free(file_content); + fclose(file); + return 1; + } + + // Добавляем завершающий ноль для безопасной работы со строками + file_content[file_size] = '\0'; + + // Закрываем файл + fclose(file); + + // 4.5. Запросить у пользователя строку для поиска, сохранив её в массиве на стеке + char search_string[MAX_SEARCH_STRING_LENGTH]; + cout << "Введите строку для поиска: "; + cin.getline(search_string, MAX_SEARCH_STRING_LENGTH); + + // 4.6. Подсчитать и вывести число вхождений введенной строки в текст файла + int count = 0; + char* pos = file_content; + + // Длина строки для поиска + size_t search_len = strlen(search_string); + if (search_len == 0) { + cout << "Пустая строка для поиска." << endl; + free(file_content); + return 1; + } + + // Поиск всех вхождений + while ((pos = strstr(pos, search_string)) != nullptr) { + count++; + pos += search_len; // Продвигаемся вперед, чтобы избежать бесконечного цикла + } + + cout << "Число вхождений строки \"" << search_string << "\": " << count << endl; + + // 4.7. Освободить выделенную память + free(file_content); + + return 0; +}