Главная страница
Навигация по странице:

  • ЛАБОРАТОРНАЯ РАБОТА № 2

  • Постановка задачи

  • Теоретические исследования

  • Описание решения

  • Тестирование и результаты работы программы

  • Приложение A

  • Отчёт 2 Основы частотного анализа. Лабораторная работа 2 Основы частотного анализа по дисциплине Основы информационной безопасности


    Скачать 0.54 Mb.
    НазваниеЛабораторная работа 2 Основы частотного анализа по дисциплине Основы информационной безопасности
    АнкорОтчёт 2 Основы частотного анализа.docx
    Дата03.10.2022
    Размер0.54 Mb.
    Формат файлаdocx
    Имя файлаОтчёт 2 Основы частотного анализа.docx
    ТипЛабораторная работа
    #710355

    1. Министерство образования и науки Российской Федерации

    2. Санкт-Петербургский Политехнический Университет Петра Великого



    3. Институт кибербезопасности и защиты информации


    ЛАБОРАТОРНАЯ РАБОТА № 2


    1. «Основы частотного анализа»



    2. по дисциплине «Основы информационной безопасности»




    1. Выполнил

    2. студент гр. 4831001/10003 Бабаев С.Ш.

    <подпись>



    1. Преподаватель

    2. асс. преподавателя Панков И.Д.

    <подпись>






    1. Санкт-Петербург

    2. 2022

    1. Цель работы

    В данной работе требуется ознакомиться с основами криптоанализа и написать программу, реализующую функции инструмента криптоаналитика.


    1. Постановка задачи

    Нужно разработать программу, которая поможет в расшифровке криптограммы. Требуется сделать частотный анализатор криптограммы, сортировку слов по количеству букв и по количеству расшифрованных букв. А также основной функционал, это возможность дешифровать криптограмму, и сохранение истории замены.


    1. Теоретические исследования

    Шифр моноалфавитной подстановки, это шифр, в котором каждый

    символ текста заменяется на некоторый символ того же алфавита.

    Моноалфавитные подстановки не нарушают частот появления символов, характерных для данного алфавита. Для получения исходного текста нужно сопоставить частоты появления символов шифра с частотой использования букв в алфавите. Самые наиболее вероятные, заменяются самыми наиболее вероятными и наоборот.

    1. Описание решения

    Весь функционал программы находится в одном бесконечном цикле, это позволяет без проблем перемещаться из разных пунктов меню сохраняя ранее введённые данные. Весь функционал находится в одном цикле, благодарю чему весь функционал в коде собран в одном месте.

    Считывание текста было решено сделать совмещённым, но преимущественно выбран построчный анализ, поскольку он будет работать намного быстрее. Посимвольное считывание используется лишь для того что бы определить сколько всего символов в файле, для того что бы в дальнейшем создать динамический массив для хранения всего текста. Данный способ имеет свои недостатки в виде нерационального использования памяти, но для современных систем затраты памяти в таком проекте не существенны.

    Для удобства использования программы, а также для того что бы минимизировать вероятность неверного ввода от пользователя решено использовать ввод при помощи кнопок на клавиатуре. Лишь в пункте с заменой букв, пользователю предоставляется возможность вводить символы в консоль. А также, для того что бы пользователь сразу понимал, как управлять главным меню, выводится инструкция по управлению, которую можно пропустить нажатием любой клавиши.
    В главном меню предоставляется выбор определённого пункта.



    Рисунок 1 – Меню программы
    Перед работой любого из пунктов, кроме Автозамены, Инструкции и Выхода, требуется отсканировать текст. Для этого есть нулевой пункт с соответствующим названием. После того как текст отсканирован, открывается доступ к остальным пунктам меню.

    Анализ частоты букв и предположительные замены, производит анализ частоты букв и выводит предположительные замены (рис. 2).


    Рисунок 2 – Частотный анализ входной криптограммы
    Пункты с группировкой букв соответственно группируют слова по введённым условиям. Т.е. по длине или количеству расшифрованных букв (рис. 3).



    Рисунок 3 – Сортировка по количеству букв
    Пункт меню «Отображение криптограммы» выводит пользователю на экран криптограмму из файла.


    Рисунок 4 – Отображение криптограммы
    Пункт меню «Замена букв» позволяет пользователю заменять буквы в криптограмме (рис. 5). А также можно отменять последнюю замену, либо просо вернуться в меню.


    Рисунок 5 – Замена букв
    Пункт «История замены», показывает пользователю какие замены были произведены в криптограмме. Если же замен нет, пользователь увидит надпись: «История замен пустая». Сразу стоит упомянуть связанный с историей замены пункт «Очистить историю», который соответственно очищает историю.

    Последний пункт, который стоит рассмотреть это «Автозамена», в данном пункте происходит автоматическая расшифровка текста с использованием частотного анализа букв



    Рисунок 6 – Автозамена


    1. Тестирование и результаты работы программы

    Исходная криптограмма имеет вид:


    Рисунок 7 – Отображение криптограммы

    На основе ранее полученного частного анализа, можно расшифровать данную криптограмму. Но полагаться только на частотный анализ, как делает автозамена не стоит, поскольку исходная криптограмма имеет слишком маленький объём, для того что бы автозамена работала корректно. По этой причине криптограмму приходится расшифровать вручную.



    Рисунок 8 – Расшифрованная криптограмма

    Исходя из истории замен, можно составить таблицу

    Таблица 1 – Результаты расшифровки.

    а

    б

    в

    г

    д

    е

    ж

    з

    и

    й

    к

    л

    м

    н

    о

    п

    р

    с

    т

    у

    ф

    х

    ц

    ч

    ш

    щ

    ы

    ь

    э

    ю

    я

    И

    Й

    Г

    К

    Б

    Л

    О

    П

    Т

    Ь

    У

    Х

    Ц

    З

    Ч

    Р

    А

    В

    С

    Щ

    Ы

    Д

    Э

    Ю

    Ъ

    Ш

    М

    Н

    Ж

    Я

    Й




    1. Выводы

    В процессе написания программы был получены опыт использования моноалфавитной подстановки. Также получен опыт частотного анализа текста. Были получены новые навыки использования структур, динамических массивов, и считываний текста из файла. В том числе применение алгоритмов сортировки на практике.

    Приложение A

    #pragma warning(disable : 4996) //для работы getch

    #define _CRT_SECURE_NO_WARNINGS

    #include

    #include

    #include

    #include

    #include

    #include

    #include


    #define WAY_TO_FILE "C:\\Users\\babae\\Desktop\\lab_var_1.txt"

    #define ALPHABET_SIZE 33

    #define BASE_LINE_WIDTH 5

    #define LONG_STR 120
    #define FIELD_WIDTH 70

    #define FIELD_HEIGHT_MENU 30
    #define POINT_HOME_X_AXIS 6

    #define POINT_HOME_Y_AXIS 6

    #define POINT_STEP 2

    #define CURSOR_POSITION_FOR_TITLE_X 24

    #define CURSOR_POSITION_FOR_TITLE_Y 3

    #define HIDDEN_POINT_POSITION 0
    #define ENTER_BUTTON 13

    #define BUTTON_DOWN 80

    #define BUTTON_UP 72

    #define BUTTON_SPACE 32
    #define MAXIMUM_POSITION_Y 26
    #define ADD_TWO_ZERO 100

    #define TWO_NUMBERS 10

    #define MAXIMUM_WORD_LENGTH 55

    #define INPUT_SIZE 4

    //char WAY_TO_FILE[256] = "C:\\Users\\babae\\Desktop\\lab_var_1.txt" ;

    struct computer

    {

    //replacement_counter

    double letter_frequency[ALPHABET_SIZE+1];// массив для информации о частоте использования букв

    int character_count;

    char replacement_base[BASE_LINE_WIDTH][ALPHABET_SIZE];

    int replacement_counter;

    char* all_text;

    char* all_symb_auto_change;

    int auto_change_ckeck;

    } perem;

    void cursor_movement_in_x_y(SHORT x, SHORT y)

    {

    COORD p = { x,y };

    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), p);

    }

    //перемещение курсора

    void drawing_main_menu() {
    for (int Y_axis_box = 0; Y_axis_box < FIELD_HEIGHT_MENU+1; Y_axis_box++)

    {
    cursor_movement_in_x_y(0, Y_axis_box);

    printf("|");

    cursor_movement_in_x_y(FIELD_WIDTH, Y_axis_box);

    printf("|");

    }

    for (int X_axis_box = 0; X_axis_box < FIELD_WIDTH+1; X_axis_box++)

    {
    cursor_movement_in_x_y(X_axis_box, 0);

    printf("|");

    cursor_movement_in_x_y(X_axis_box, FIELD_HEIGHT_MENU);

    printf("|");

    }
    cursor_movement_in_x_y(CURSOR_POSITION_FOR_TITLE_X, CURSOR_POSITION_FOR_TITLE_Y); printf("Криптоанализатор");

    cursor_movement_in_x_y(POINT_HOME_X_AXIS, POINT_HOME_Y_AXIS); printf("0. Отсканировать текст из файла");

    cursor_movement_in_x_y(POINT_HOME_X_AXIS, POINT_HOME_Y_AXIS+ (POINT_STEP * 1)); printf("1. Анализ частоты букв и предположительные замены");

    cursor_movement_in_x_y(POINT_HOME_X_AXIS, POINT_HOME_Y_AXIS + (POINT_STEP * 2)); printf("2. Все слова, сгруппированные по количеству букв");

    cursor_movement_in_x_y(POINT_HOME_X_AXIS, POINT_HOME_Y_AXIS + (POINT_STEP * 3)); printf("3. Все слова, сгруппированные по количеству расшифорванных");

    cursor_movement_in_x_y(POINT_HOME_X_AXIS+8, POINT_HOME_Y_AXIS + (POINT_STEP * 3)+1); printf("на данный момент букв");

    cursor_movement_in_x_y(POINT_HOME_X_AXIS, POINT_HOME_Y_AXIS + (POINT_STEP * 4)); printf("4. Отобразить криптограмму");

    cursor_movement_in_x_y(POINT_HOME_X_AXIS, POINT_HOME_Y_AXIS + (POINT_STEP * 5)); printf("5. Замена букв");

    cursor_movement_in_x_y(POINT_HOME_X_AXIS, POINT_HOME_Y_AXIS + (POINT_STEP * 6)); printf("6. История замены");

    cursor_movement_in_x_y(POINT_HOME_X_AXIS, POINT_HOME_Y_AXIS + (POINT_STEP * 7)); printf("7. Автозамена");

    cursor_movement_in_x_y(POINT_HOME_X_AXIS, POINT_HOME_Y_AXIS + (POINT_STEP * 8)); printf("8. Инструкция");

    cursor_movement_in_x_y(POINT_HOME_X_AXIS, POINT_HOME_Y_AXIS + (POINT_STEP * 9)); printf("9. Очистить историю");

    cursor_movement_in_x_y(POINT_HOME_X_AXIS, POINT_HOME_Y_AXIS + (POINT_STEP * 10)); printf("10. Выход");

    }

    //отрисовка меню

    int arrow_movement()

    {

    int pressed_button = 0; //нажатая кнопка

    int pointer_location = 6; //отслеживание местоположения курсора

    cursor_movement_in_x_y(POINT_HOME_X_AXIS, POINT_HOME_Y_AXIS);

    printf("\b");

    printf(">");

    cursor_movement_in_x_y(HIDDEN_POINT_POSITION, HIDDEN_POINT_POSITION);

    pressed_button = 0;
    while (pressed_button != ENTER_BUTTON) //если не Enter

    {
    pressed_button = getch();
    if (pressed_button == BUTTON_DOWN) //вниз

    {
    cursor_movement_in_x_y(POINT_HOME_X_AXIS-1, pointer_location);

    printf(" ");
    pointer_location = pointer_location + POINT_STEP;

    if (pointer_location == MAXIMUM_POSITION_Y+POINT_STEP)

    {

    pointer_location = POINT_HOME_Y_AXIS;

    }
    cursor_movement_in_x_y(POINT_HOME_X_AXIS, pointer_location);

    printf("\b");

    printf(">");

    cursor_movement_in_x_y(HIDDEN_POINT_POSITION, HIDDEN_POINT_POSITION);
    }

    if (pressed_button == BUTTON_UP) //вверх

    {
    cursor_movement_in_x_y(POINT_HOME_X_AXIS-1, pointer_location);

    printf(" ");

    pointer_location = pointer_location - POINT_STEP;

    if (pointer_location == POINT_HOME_Y_AXIS- POINT_STEP)

    {

    pointer_location = MAXIMUM_POSITION_Y;

    }

    cursor_movement_in_x_y(POINT_HOME_X_AXIS, pointer_location);

    printf("\b");

    printf(">");

    cursor_movement_in_x_y(HIDDEN_POINT_POSITION, HIDDEN_POINT_POSITION);
    }

    }

    return pointer_location;

    }

    int button_check(int button)

    {

    while (button != BUTTON_SPACE)

    {

    button = getch();

    }

    system("cls");

    return 0;

    }

    int all_cyrillic_check(char letter)

    {

    char all_cyrillic_symb[67] = "ОЕАИНТРСЛВКПМУДЯЫЬЗБГЙЧЮХЖШЦЩФЭЁЪоеаинтрслвкпмудяыьзбгйчюхжшцщфэёъ";

    for (int letter_number = 0; letter_number < 66; letter_number++)

    {

    if (letter == all_cyrillic_symb[letter_number] && letter != '\0')

    {

    return 1;

    }

    }

    return 0;

    }

    //функция для поиска криллицы в тесте

    int small_сyrillic_check(char letter)

    {

    char small_cyrillic_symb[ALPHABET_SIZE+1] = "оеаинтрслвкпмудяыьзбгйчюхжшцщфэёъ";

    for (int letter_number = 0; letter_number < ALPHABET_SIZE; letter_number++)

    {

    if (letter == small_cyrillic_symb[letter_number])

    {

    return 1;

    }
    }

    return 0;

    }

    //функция для поиска строчных букв

    int big_сyrillic_check_with01(char letter)

    {

    char big_cyrillic_symb[ALPHABET_SIZE+4] = "ОЕАИНТРСЛВКПМУДЯЫЬЗБГЙЧЮХЖШЦЩФЭЁЪ01";

    for (int letter_number = 0; letter_number < ALPHABET_SIZE+3; letter_number++)

    {

    if (letter == big_cyrillic_symb[letter_number] && letter != '\0')

    {

    return 1;

    }
    }

    return 0;

    }

    //функция для поиска заглавных букв, а так же используется в защите от некоректоного ввода

    double frequency_analysis()

    {

    perem.character_count = 0; //счётчик размера файла обнуляется при каждом использованни функции

    char alphabet[ALPHABET_SIZE+1] = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"; //алфавии, для сверки

    double all_letters_number = 0; // общее количество БУКВ

    char current_letter = 0; //символ полученный из документа

    FILE* file;

    file = fopen(WAY_TO_FILE, "r"); //путь к файлу

    for (int cell_counter = 0; cell_counter < ALPHABET_SIZE; cell_counter++) // массив для информации о частоте использования букв очищается как и колличество букв

    {

    all_letters_number = 0;

    perem.letter_frequency[cell_counter] = 0;

    }

    if (file != NULL) //проверка существования файла

    {

    while (!feof(file)) //цикл до конца файла

    {

    perem.character_count++; //считаем размер файла

    current_letter = fgetc(file); //приравниваем переменной символ

    for (int cell_counter = 0; cell_counter < ALPHABET_SIZE; cell_counter++)

    {

    if (current_letter == alphabet[cell_counter]) //проверяем, является ли символв кириллицей

    {

    all_letters_number++;

    perem.letter_frequency[cell_counter]++;

    }

    }

    }

    fclose(file);

    }

    return all_letters_number;

    }

    //анализ текста: частота использовани букв и общее кол-во символов

    void text_to_array()

    {

    // прирваниваем к нулю, на случай повторного использования

    perem.character_count = 0;

    frequency_analysis();// получаем размер файла

    perem.all_text = (char*)calloc(perem.character_count, sizeof(char)); //создаём динамический массив, с учётом кол-ва символов

    perem.all_text[perem.character_count - 1] = NULL;
    FILE* file; //все элементы файла

    file = fopen(WAY_TO_FILE, "r");

    int cell_counter = 0; //счётчик

    if (file != NULL)

    {

    while (!feof(file)) //цикл до конца файла

    {

    if (perem.all_text != NULL && cell_counter >= 0) //для избежания ошибки пустого указателя

    {

    perem.all_text[cell_counter] = fgetc(file); //заполняем массив элементов

    cell_counter++;

    }

    }

    }
    else

    {

    printf("Файл по пути: %s не найден, убедитьсь что он существует \n", WAY_TO_FILE);

    system("pause");

    exit(EXIT_SUCCESS);

    }
    }

    //запись текста в дин. массив

    void bubble_sort(double* arr, char* buk) { //сортировка пузырьком
    //сортировка по частоте использования буквы

    for (int i = 0; i < ALPHABET_SIZE; i++)

    {

    for (int j = ALPHABET_SIZE; j > i; j--)

    {

    if (arr[j - 1] < arr[j])

    {

    double temp = arr[j - 1];// меняем их местами

    arr[j - 1] = arr[j];

    arr[j] = temp;

    char tempb = buk[j - 1];

    buk[j - 1] = buk[j];

    buk[j] = tempb;

    }

    }

    }
    }

    //сортируем частоту использования букв и сортируем буквы под частоту

    char* frequency_analysis_output(int command)

    {

    int print = command; //для предовращения вывода частоты, когда этого не требуется

    char alphabet_const[ALPHABET_SIZE+1] = "ОЕАИНТРСЛВКПМУДЯЫЬЗБГЙЧЮХЖШЦЩФЭЁЪ"; //алфаит сортированный в порядке частоты использования букв

    char alphabet_change[ALPHABET_SIZE+1] = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"; //оигинальный алфавит

    double all_letters_number = frequency_analysis();//получаем колличество букв

    bubble_sort(perem.letter_frequency, alphabet_change);//сортируем частоту использования букв и сортируем буквы под частоту

    for (int letter_number = 0; letter_number < ALPHABET_SIZE; letter_number++)

    {

    perem.letter_frequency[letter_number] = perem.letter_frequency[letter_number] / all_letters_number * ADD_TWO_ZERO;

    }

    if (print == 2 )

    {

    printf(" ___________________________________\n| Буква в тексте | Частота | Замена |\n -----------------------------------");

    for (int letter_number = 0; letter_number < ALPHABET_SIZE; letter_number++)

    {
    if (perem.letter_frequency[letter_number] > TWO_NUMBERS)

    {

    printf("\n| %c | %.3f | %c |", alphabet_change[letter_number], perem.letter_frequency[letter_number], alphabet_const[letter_number]);

    }

    else

    {

    printf("\n| %c | %.3f | %c | ", alphabet_change[letter_number], perem.letter_frequency[letter_number], alphabet_const[letter_number]);

    }

    }

    printf("\n_____________________________________\n"

    "\n\n\n Нажмите Пробел что бы вернуться в главное меню");

    }

    if (print == 3)

    {

    printf(" ___________________________________\n| Буква в тексте | Замена |\n -----------------------------------");

    for (int letter_number = 0; letter_number < ALPHABET_SIZE; letter_number++)

    {
    if (perem.letter_frequency[letter_number] > TWO_NUMBERS)

    {

    printf("\n| %c | %c |", alphabet_change[letter_number], alphabet_const[letter_number]);

    }

    else

    {

    printf("\n| %c | %c | ", alphabet_change[letter_number], alphabet_const[letter_number]);

    }

    }

    }

    return alphabet_change; //возвращем массив с частотой

    }

    //вывод частоты использования букв

    int find_longest_word()

    {

    system("cls");

    int long_word = 0;

    int max_size = 0;

    int flag_end_word = 0;

    for (int character_in_text = 0; character_in_text < perem.character_count; character_in_text++)

    {

    flag_end_word = 0;
    if (all_cyrillic_check(perem.all_text[character_in_text]) == 1)

    {

    flag_end_word = 1; //если flag_end_word=1, вы начинаем считать буквы, пока слово не закончится, т.е узнаём длину слова

    long_word++;

    }

    if (flag_end_word == 0)

    {

    long_word = 0;

    }

    if (max_size < long_word)

    {

    max_size = long_word;

    }

    }

    return max_size;

    }

    //поиск самого длинного слова

    int sort_words_by_length()

    {

    system("cls");

    int word_count = 0; //счётчик слов

    char current_symbol = 0; //переменная в которую будет записываться данный символ

    int longg_word = find_longest_word(); //получаем длину самого большого слова

    int element_counter = 0; //счётчик элементов массива со словом

    char array_for_word[MAXIMUM_WORD_LENGTH] = { 0 };//массив для записи отдельного слова

    int length_counter = 0; //счётчик длинны слова в массиве

    //int long_world

    printf("___________________________________\n"

    "|Максимальная длина слова: %d"

    "|\n"

    "___________________________________\n", longg_word);

    while (longg_word >= 0)

    {

    for (int character_in_text = 0; character_in_text < perem.character_count - 1; character_in_text++)

    {

    if (all_cyrillic_check(perem.all_text[character_in_text]) == 1) //заносим слово в массив

    {

    current_symbol = perem.all_text[character_in_text];

    array_for_word[element_counter] = perem.all_text[character_in_text];

    element_counter++;
    if (all_cyrillic_check(perem.all_text[character_in_text + 1]) == 0 || perem.all_text[character_in_text + 1] == EOF) //если полсе рассматриваемого символа не кириллица, мы обнуляем переменную с символами

    {

    current_symbol = 0;

    element_counter = 0;

    length_counter = 0;

    for (int letters_in_array = 0; letters_in_array < MAXIMUM_WORD_LENGTH-1; letters_in_array++) //считаем длинну слова в массиве

    {

    if (all_cyrillic_check(array_for_word[letters_in_array]) == 1 && array_for_word[letters_in_array] != '\0')

    {

    length_counter++;

    }

    }

    if (length_counter == longg_word) //если длинна равна масимальной, выводим его

    {

    word_count++;

    printf("\n");

    printf("%s", array_for_word);
    }

    memset(array_for_word, NULL, MAXIMUM_WORD_LENGTH);//очищаем массив со словом


    }

    }
    }
    longg_word--;
    }
    printf("\n\n\n Нажмите Пробел что бы вернуться в главное меню");

    return word_count;

    }

    //сортировка слов по длине

    int find_maximum_change()

    {

    //принцип работы как сортировки слов по длинне//
    int longg_word = find_longest_word(); //получаем самое длинное слов

    char array_for_word[MAXIMUM_WORD_LENGTH] = { 0 }; //массив для записи отдельного слова

    int element_counter = 0; //счётчик элементов массива со словом

    char current_symbol = 0; //переменная в которую будет записываться данный символ

    int count_change = 0;//счётчик замен

    int max_change = 0; //максимум замен

    {

    for (int character_in_text = 0; character_in_text < perem.character_count; character_in_text++) //проходимся по тексту

    {

    if (all_cyrillic_check(perem.all_text[character_in_text]) == 1) //записываем все символы в масиив для слова

    {

    current_symbol = perem.all_text[character_in_text];

    array_for_word[element_counter] = perem.all_text[character_in_text];

    element_counter++;


    if (all_cyrillic_check(perem.all_text[character_in_text + 1]) == 0 || perem.all_text[character_in_text + 1] == EOF) //если далее идёт не буква очищаем переменные

    {

    current_symbol = 0;

    element_counter = 0;

    count_change = 0;

    for (int letters_in_array = 0; letters_in_array < MAXIMUM_WORD_LENGTH-1; letters_in_array++) //проходимся по массиву со словом

    {

    if (small_сyrillic_check(array_for_word[letters_in_array]) == 1 && array_for_word[letters_in_array] != '\0')

    {

    count_change++; //считаем кол-во замен

    if (count_change > max_change)

    {

    max_change = count_change;

    }

    }

    array_for_word[letters_in_array] = NULL;

    }

    }

    }
    }

    printf("%d", max_change);

    }

    return max_change;

    }

    //ищем слово с макисмальным кол-вом замен

    void chang()

    {

    //принцип работы как сортировки слов по длинне//

    system("cls");

    int max_change = find_maximum_change();

    system("cls");

    char array_for_word[50] = { 0 };

    int element_counter = 0;

    char current_symbol = 0;

    int count_change = 0;

    {

    while (max_change >= 0)

    {

    for (int character_in_text = 0; character_in_text < perem.character_count - 1; character_in_text++)

    {

    if (all_cyrillic_check(perem.all_text[character_in_text]) == 1)

    {

    current_symbol = perem.all_text[character_in_text];

    array_for_word[element_counter] = perem.all_text[character_in_text];

    element_counter++;


    if (all_cyrillic_check(perem.all_text[character_in_text + 1]) == 0 || perem.all_text[character_in_text + 1] == EOF)

    {

    current_symbol = 0;

    element_counter = 0;

    count_change = 0;

    for (int z = 0; z < 49; z++)

    {

    if (small_сyrillic_check(array_for_word[z]) == 1 && array_for_word[z] != '\0')

    {

    count_change++;

    }

    }

    if (count_change == max_change)

    {

    printf("\n");

    printf("%s", array_for_word);
    }
    memset(array_for_word, NULL, 50);
    }

    }
    }

    max_change--;

    }

    }

    printf("\n\n\n Нажмите Пробел что бы вернуться в главное меню");

    }

    //выводим слово с макс. заменами

    int zamena()

    {
    char Entered_character_1[INPUT_SIZE] = { 0 }; //введённый символ 1

    char Entered_character_2[INPUT_SIZE] = { 0 };//введённый символ 2
    while (1) //бесконечный массив, т.к. фун-я перестанет работать только при вводе "0"

    {

    system("cls");

    if (perem.all_text != NULL) //выводим криптограмму

    {

    perem.all_text[perem.character_count - 1] = NULL;

    printf("%s", perem.all_text);

    }

    char str[LONG_STR] = { 0 };

    memset(str, '_', LONG_STR-1);

    if (perem.auto_change_ckeck == 1)

    {

    printf("%s\nАвтозамена: \n", str);
    if (perem.all_symb_auto_change != NULL) //выводим криптограмму

    {

    perem.all_symb_auto_change[perem.character_count - 1] = NULL;

    printf("%s", perem.all_symb_auto_change);

    }

    frequency_analysis_output(3);

    printf("\n%s", str);

    }

    printf("\n\nЗамен было: %d"

    "\nДля выхода введите 0\nДля отмены последнего шага введите 1"

    "\n\nвведите букву которую нужно заменить (ЗАГЛАВНУЮ) \n", perem.replacement_counter);
    fseek(stdin, 0, SEEK_END);//очищаем поток

    fgets(Entered_character_1, 2, stdin); //получаем первый символ
    while (big_сyrillic_check_with01(Entered_character_1[0]) != 1 && Entered_character_1[1] != '0') //защита от некорретного ввода

    {

    printf("\nнекорректный ввод, повторите попытку\n");

    fseek(stdin, 0, SEEK_END);

    fgets(Entered_character_1, 2, stdin);

    }

    if (Entered_character_1[0] == '0') //заканчиваем работу функции

    {

    return 0;

    }

    if (Entered_character_1[0] != '1')

    {

    printf("заменить на \n");

    fseek(stdin, 0, SEEK_END);//очищаем поток

    fgets(Entered_character_2, 2, stdin);//получаем второй символ

    while (small_сyrillic_check(Entered_character_2[0]) != 1 && Entered_character_2[1] != '0') //защита от некорректоного ввода

    {

    printf("\nнекорректный ввод, повторите попытку\n");

    fseek(stdin, 0, SEEK_END);

    fgets(Entered_character_1, 2, stdin);

    }

    printf("\n");


    for (int letter_in_text = 0; letter_in_text < perem.character_count; letter_in_text++) //замена буквы

    {

    if (perem.all_text != NULL)

    {

    if (perem.all_text[letter_in_text] == Entered_character_1[0])

    {

    perem.all_text[letter_in_text] = Entered_character_2[0];
    }

    }

    }

    perem.replacement_counter++; //засчитываем замену
    if (perem.all_text != NULL) //выводим криптограмму

    {

    printf("%s", perem.all_text);

    }

    //заносим замены в массив

    //snprintf()

    perem.replacement_base[0][perem.replacement_counter] = '.';

    perem.replacement_base[1][perem.replacement_counter] = Entered_character_1[0];

    perem.replacement_base[2][perem.replacement_counter] = '-';

    perem.replacement_base[3][perem.replacement_counter] = Entered_character_2[0];
    }

    if (Entered_character_1[0] == '1') //отмена замены

    {
    if (perem.replacement_counter != 0) //если замены уже были

    {

    printf("\nПоследняя замена отменена\n");

    for (int letter_in_text = 0; letter_in_text < perem.character_count; letter_in_text++) //возвращем символ на место пользуясь базой замены

    {
    if (perem.all_text != NULL)

    {

    if (perem.all_text[letter_in_text] == perem.replacement_base[3][perem.replacement_counter])

    {

    perem.all_text[letter_in_text] = perem.replacement_base[1][perem.replacement_counter];
    }

    }

    }

    //очищаем элементы с отменённой заменой

    for (int cell_number = 0; cell_number < 5;cell_number++)

    {

    perem.replacement_base[cell_number][perem.replacement_counter] = NULL;

    }

    perem.replacement_counter--;

    system("pause");

    }

    else //если замен не было

    {

    printf("\nЗамен нет\n");

    system("pause");

    }

    }

    }

    }

    //замены букв

    void scan_text()

    {

    text_to_array();

    system("cls");

    cursor_movement_in_x_y(0, 35);

    printf("Текст отсканирован");

    cursor_movement_in_x_y(0, 0);

    }

    //занести текст в массив

    void autocorrect()

    {

    perem.auto_change_ckeck = 1;

    //char* all_symb_auto_change = NULL;

    perem.character_count = 0;

    frequency_analysis();// полуаем размер файла
    perem.all_symb_auto_change = (char*)calloc(perem.character_count, sizeof(char)); //создаём динамический массив, с учётом кол-ва символов

    //all_symb_auto_change[perem.character_count ] = NULL;


    FILE* file; //все элементы файла

    file = fopen(WAY_TO_FILE, "r");

    int cell_counter = 0; //счётчик

    if (file != NULL)

    {

    while (!feof(file)) //цикл до конца файла

    {

    if (perem.all_symb_auto_change != NULL && cell_counter >= 0) //для избежания ошибки пустого указателя

    {

    //if (fgetc(file) != -1)
    perem.all_symb_auto_change[cell_counter] = fgetc(file); //заполняем массив элементов

    cell_counter++;

    }

    }

    }

    perem.all_symb_auto_change[perem.character_count - 1] = '\0';

    system("cls");

    char* array_frequency_analysis = frequency_analysis_output(1);

    char alphabet_const[ALPHABET_SIZE+1] = "оеаинтрслвкпмудяыьзбгйчюхжшцщфэёъ";

    if (perem.all_symb_auto_change != NULL)

    {

    for (int character_counter = 0; character_counter < perem.character_count - 1; character_counter++)

    {

    for (int replacement_counter = 0; replacement_counter < ALPHABET_SIZE; replacement_counter++)

    {
    if (perem.all_symb_auto_change[character_counter] == array_frequency_analysis[replacement_counter])

    {

    //alf[j]

    perem.all_symb_auto_change[character_counter] = alphabet_const[replacement_counter];
    }

    }

    }

    }

    if (perem.all_symb_auto_change != NULL)

    {

    printf("%s", perem.all_symb_auto_change);

    }

    printf("\nЧто бы вернуться в главное меню , нажмите Пробел\n");

    cursor_movement_in_x_y(0, 0);

    }

    void instruction_control() {

    printf(" Управление\n\n"

    "\n /----\\ /-----\\"

    "\n | / \\ | | |"

    "\n | | | -- Вверх | |"

    "\n \\____/ | | - перейти в пункт"

    "\n __________| |"

    "\n /----\\ /----\\ /----\\ | |"

    "\n| | | | | | |"

    "\n| | | | | | Enter |"

    "\n| | \\ / | | | |"

    "\n \\____/ \\____/ \\____/ |________________|"

    "\n |\n |\n Вниз\n"

    "\n /--------------\\ "

    "\n| |\n| Space | - вернуться назад\n| |"

    "\n \\_____________/"

    "\n");

    }

    void instruction()

    {

    system("cls");

    printf("1. Перед использованием любого из пункта кроме Автозамена вам \nнужно отсканировать текст"

    "\n2. При использовании Автозамены ранее изменённый текст не будет изменён,"

    "\nа так же вы не можете сами редакировать текст автозамены"

    "\n3. Находясь в пункте с заменой букв"

    "\n a. Нельзя менять сторчные буквы на заглавыне"

    "\n б. Для выхода нужно ввести 0"

    "\n в. Для отмены последней замены введите 1"

    "\n\n\n Нажмите Пробел что бы вернуться в главное меню");

    }

    void replacement_history()

    {

    system("cls");

    printf("История замены:\n");

    if (perem.replacement_base[0][1] != '.')

    {

    printf("\nИстория замен пустая\n");

    printf("Что бы вернуться в главное меню , нажмите Пробел\n");

    cursor_movement_in_x_y(15, 0);

    }

    else {

    for (int replacement_string = 1; replacement_string < ALPHABET_SIZE+2; replacement_string++)

    {

    if (perem.replacement_base[0][replacement_string] == '.')

    {

    printf("%d", replacement_string);

    }

    for (int replacement_line = 0; replacement_line < 5; replacement_line++)

    {
    if (perem.replacement_base[0][replacement_string] == '.')

    {

    printf(" %c", perem.replacement_base[replacement_line][replacement_string]);

    }

    }

    printf("\n");

    }

    printf("Что бы вернуться в главное меню , нажмите Пробел\n");

    cursor_movement_in_x_y(15, 0);
    }

    }

    void clearing_history()

    {

    system("cls");

    printf("История очищена\n");

    printf("Что бы вернуться в главное меню , нажмите Пробел\n");

    for (int replacement_string = 1; replacement_string < ALPHABET_SIZE+2; replacement_string++)

    {

    for (int replacement_line = 0; replacement_line < 5; replacement_line++)

    {

    perem.replacement_base[replacement_line][replacement_string] = '\0';

    }

    printf("\n");

    }
    perem.replacement_counter = 0; //счётчик замен

    }

    void print_text()

    {

    system("cls");

    if (perem.all_text != NULL)

    {

    perem.all_text[perem.character_count - 1] = NULL;

    printf("%s", perem.all_text);

    }
    printf("\n\n\n Нажмите Пробел что бы вернуться в главное меню");

    }

    int main()

    {

    perem.all_text = NULL;

    perem.replacement_counter = 0;

    perem.character_count = 0;
    setlocale(LC_ALL, "Russian");

    SetConsoleCP(1251);

    SetConsoleOutputCP(1251);
    instruction_control();

    system("pause");

    system("cls");

    text_to_array();

    int control = 1; //переменная для возврата в меню

    int text_scan_check = 0; //отслеживание того что файл был занесён в массив
    while (1) {
    drawing_main_menu();

    control = 1;

    while (control == 1)

    {

    int pointer_location = arrow_movement();

    int button = 0;
    if (pointer_location == 6) //выбран пункт

    {

    scan_text();

    text_scan_check = 1;

    control--;

    }

    if (text_scan_check == 0) //проверяем был ли тест уже отскнирован

    {

    system("cls");

    cursor_movement_in_x_y(0, 35);

    printf("Текст ещё не отсканирован");

    cursor_movement_in_x_y(0, 0);

    control--;

    }

    else //если да то мы можем делать всё остальное

    {

    if (pointer_location == 8) //анализ частоты

    {

    system("cls");

    frequency_analysis_output(2);

    control = button_check(button);
    }
    if (pointer_location == 10) //вывод соритрованых слов по длине

    {

    sort_words_by_length();

    control = button_check(button);

    }
    if (pointer_location == 12) //вывод соритрованых слов по заменам

    {

    chang();

    control = button_check(button);

    }

    if (pointer_location == 14) //вывод текста

    {

    print_text();

    control = button_check(button);

    }

    if (pointer_location == 16) //замена букв

    {

    system("cls");

    if (zamena() == 0)

    {

    system("cls");control--;

    }
    }

    if (pointer_location == 18) //история замены

    {

    replacement_history();

    control = button_check(button);

    }

    if (pointer_location == 24) //очистка истории замены

    {

    clearing_history();

    control = button_check(button);

    }
    }
    if (pointer_location == 26) //выход

    {

    system("cls");

    exit(EXIT_SUCCESS);
    }

    if (pointer_location == 20) //автозамена

    {

    autocorrect();

    control = button_check(button);
    }

    if (pointer_location == 22) //инструкция

    {

    instruction();

    control = button_check(button);

    }

    }

    }

    }


    написать администратору сайта