#include #include // Для функций работы с файлами и C-строками #include // Для функций работы со строками #include // Для функций проверки символов #include // Для функций выделения памяти 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() { // 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; }