Родитель
58af48b285
Сommit
e959051d3f
@ -1,173 +1,127 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdio> // Для функций работы с файлами и C-строками
|
#include <cstdio> // Для работы с файлами и C-строками
|
||||||
#include <cstring> // Для функций работы со строками
|
#include <cstring> // Для обработки строк
|
||||||
#include <cctype> // Для функций проверки символов
|
#include <cctype> // Для проверки символов
|
||||||
#include <cstdlib> // Для функций выделения памяти
|
#include <cstdlib> // Для управления памятью
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
// Максимальная длина имени файла (предположим 260 символов, типичная максимальная длина пути в Windows)
|
const size_t MAX_FILENAME_LENGTH = 260; // Максимальная длина имени файла
|
||||||
const size_t MAX_FILENAME_LENGTH = 260;
|
const size_t MAX_SEARCH_STRING_LENGTH = 256; // Максимальная длина строки поиска
|
||||||
|
|
||||||
// Максимальная длина строки для поиска (предположим 256 символов)
|
const char* invalid_chars = "*\"<>?|";
|
||||||
const size_t MAX_SEARCH_STRING_LENGTH = 256;
|
|
||||||
|
|
||||||
// Запрещенные символы в имени файла
|
|
||||||
const char* forbidden_chars = "*\"<>?|";
|
|
||||||
|
|
||||||
// Функция для проверки корректности имени файла
|
|
||||||
bool isValidFilename(const char* filename) {
|
bool isValidFilename(const char* filename) {
|
||||||
// Проверка на наличие запрещенных символов
|
for (size_t i = 0; i < strlen(invalid_chars); ++i) {
|
||||||
for (size_t i = 0; i < strlen(forbidden_chars); ++i) {
|
if (strchr(filename, invalid_chars[i]) != nullptr) {
|
||||||
if (strchr(filename, forbidden_chars[i]) != nullptr) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверка на двоеточие
|
|
||||||
const char* colon = strchr(filename, ':');
|
const char* colon = strchr(filename, ':');
|
||||||
if (colon != nullptr) {
|
if (colon != nullptr) {
|
||||||
// Двоеточие должно быть вторым символом
|
if (colon - filename != 1 || !isalpha(filename[0]) || *(colon + 1) != '\\') {
|
||||||
if (colon - filename != 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Первый символ должен быть буквой
|
|
||||||
if (!isalpha(filename[0])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// После двоеточия должна идти обратная косая черта
|
|
||||||
if (*(colon + 1) != '\\') {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Проверка расширения файла
|
const char* extension = strrchr(filename, '.');
|
||||||
const char* dot = strrchr(filename, '.');
|
if (extension != nullptr) {
|
||||||
if (dot != nullptr) {
|
if (strlen(extension) != 4) return false;
|
||||||
// Проверяем, что расширение .txt (без учета регистра)
|
|
||||||
if (strlen(dot) != 4) { // Длина должна быть 4 символа: '.' + 'txt'
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Преобразуем расширение к нижнему регистру для сравнения
|
|
||||||
char ext[5];
|
char ext[5];
|
||||||
strncpy(ext, dot, 4);
|
strncpy(ext, extension, 4);
|
||||||
ext[4] = '\0';
|
ext[4] = '\0';
|
||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) ext[i] = tolower(ext[i]);
|
||||||
ext[i] = tolower(ext[i]);
|
return strcmp(ext, ".txt") == 0;
|
||||||
}
|
|
||||||
if (strcmp(ext, ".txt") != 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Функция для добавления расширения .txt, если его нет
|
void ensureTxtExtension(char* filename) {
|
||||||
void addTxtExtension(char* filename) {
|
|
||||||
if (strrchr(filename, '.') == nullptr) {
|
if (strrchr(filename, '.') == nullptr) {
|
||||||
// Добавляем .txt
|
|
||||||
strcat(filename, ".txt");
|
strcat(filename, ".txt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
// 4.1. Запросить у пользователя имя файла, сохранив его в массиве символов на стеке
|
|
||||||
char filename[MAX_FILENAME_LENGTH];
|
char filename[MAX_FILENAME_LENGTH];
|
||||||
cout << "Введите имя файла: ";
|
cout << "Введите имя файла: ";
|
||||||
cin.getline(filename, MAX_FILENAME_LENGTH);
|
cin.getline(filename, MAX_FILENAME_LENGTH);
|
||||||
|
|
||||||
// 4.2. Проверка корректности имени файла
|
|
||||||
if (!isValidFilename(filename)) {
|
if (!isValidFilename(filename)) {
|
||||||
cout << "Некорректное имя файла." << endl;
|
cout << "Неверное имя файла." << endl;
|
||||||
return 1; // Завершаем программу с ошибкой
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4.3. Добавить расширение .txt, если его нет
|
ensureTxtExtension(filename);
|
||||||
addTxtExtension(filename);
|
|
||||||
|
|
||||||
// Повторная проверка после добавления расширения
|
|
||||||
if (!isValidFilename(filename)) {
|
if (!isValidFilename(filename)) {
|
||||||
cout << "Некорректное имя файла после добавления расширения." << endl;
|
cout << "Ошибка в имени после добавления расширения." << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4.4. Загрузка содержимого файла в память
|
|
||||||
// Открываем файл в бинарном режиме для точного определения размера
|
|
||||||
FILE* file = fopen(filename, "rb");
|
FILE* file = fopen(filename, "rb");
|
||||||
if (file == nullptr) {
|
if (file == nullptr) {
|
||||||
cout << "Не удалось открыть файл: " << filename << endl;
|
cout << "Ошибка открытия файла: " << filename << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Перемещаемся в конец файла
|
|
||||||
if (fseek(file, 0, SEEK_END) != 0) {
|
if (fseek(file, 0, SEEK_END) != 0) {
|
||||||
cout << "Ошибка при перемещении в конец файла." << endl;
|
cout << "Ошибка перехода в конец файла." << endl;
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Определяем размер файла
|
|
||||||
long file_size = ftell(file);
|
long file_size = ftell(file);
|
||||||
if (file_size == -1L) {
|
if (file_size == -1L) {
|
||||||
cout << "Не удалось определить размер файла." << endl;
|
cout << "Не удалось узнать размер файла." << endl;
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Возвращаемся в начало файла
|
|
||||||
rewind(file);
|
rewind(file);
|
||||||
|
|
||||||
// Выделяем динамическую память для содержимого файла (+1 для завершающего нуля)
|
char* content = (char*)malloc(file_size + 1);
|
||||||
char* file_content = (char*)malloc(file_size + 1);
|
if (content == nullptr) {
|
||||||
if (file_content == nullptr) {
|
cout << "Ошибка выделения памяти." << endl;
|
||||||
cout << "Не удалось выделить память для содержимого файла." << endl;
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Читаем содержимое файла
|
size_t read_size = fread(content, sizeof(char), file_size, file);
|
||||||
size_t read_size = fread(file_content, sizeof(char), file_size, file);
|
|
||||||
if (read_size != (size_t)file_size) {
|
if (read_size != (size_t)file_size) {
|
||||||
cout << "Ошибка при чтении файла." << endl;
|
cout << "Ошибка чтения файла." << endl;
|
||||||
free(file_content);
|
free(content);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Добавляем завершающий ноль для безопасной работы со строками
|
content[file_size] = '\0';
|
||||||
file_content[file_size] = '\0';
|
|
||||||
|
|
||||||
// Закрываем файл
|
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
// 4.5. Запросить у пользователя строку для поиска, сохранив её в массиве на стеке
|
char search_str[MAX_SEARCH_STRING_LENGTH];
|
||||||
char search_string[MAX_SEARCH_STRING_LENGTH];
|
|
||||||
cout << "Введите строку для поиска: ";
|
cout << "Введите строку для поиска: ";
|
||||||
cin.getline(search_string, MAX_SEARCH_STRING_LENGTH);
|
cin.getline(search_str, MAX_SEARCH_STRING_LENGTH);
|
||||||
|
|
||||||
// 4.6. Подсчитать и вывести число вхождений введенной строки в текст файла
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
char* pos = file_content;
|
char* pos = content;
|
||||||
|
|
||||||
// Длина строки для поиска
|
size_t search_len = strlen(search_str);
|
||||||
size_t search_len = strlen(search_string);
|
|
||||||
if (search_len == 0) {
|
if (search_len == 0) {
|
||||||
cout << "Пустая строка для поиска." << endl;
|
cout << "Пустая строка для поиска." << endl;
|
||||||
free(file_content);
|
free(content);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Поиск всех вхождений
|
while ((pos = strstr(pos, search_str)) != nullptr) {
|
||||||
while ((pos = strstr(pos, search_string)) != nullptr) {
|
|
||||||
count++;
|
count++;
|
||||||
pos += search_len; // Продвигаемся вперед, чтобы избежать бесконечного цикла
|
pos += search_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << "Число вхождений строки \"" << search_string << "\": " << count << endl;
|
cout << "Частота появления строки \"" << search_str << "\": " << count << endl;
|
||||||
|
|
||||||
// 4.7. Освободить выделенную память
|
|
||||||
free(file_content);
|
|
||||||
|
|
||||||
|
free(content);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Загрузка…
Ссылка в новой задаче