Криптография на C

Вы перехватили плохо развитую террористическую ячейку, которая использует метод Цезаря в качестве шифра. Сообщения всегда на английском языке. Они заменяют каждую букву другой буквой, перемещая K-позиции алфавита. Так, например, если мы переместим алфавит на две позиции вперед, мы получим следующее соответствие:

**АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЫЭЮЯ

CDEFGHIJKLMNOPQRSTUVWXYZAB **

Конечно, этот метод имеет очень простую атаку:

Попробуйте все возможные замены;

Рассчитайте для каждой возможной замены следующую меру между ожидаемой относительной частотой каждой буквы Ei и полученной **Oi ** по формуле: (Ei-Oi)^2 / Ei

Ваша программа должна прочитать строку текста длиной не более 10^4 символов.

Ваша программа должна вывести необходимое смещение и расшифрованный текст. Ваша программа должна обрабатывать только буквы (верхние или строчные).

Напишите программу, которая читает строку текста и расшифровывает ее. Используйте таблицу ниже для значения Ei (третий столбец) каждой буквы:

Э 11,1607% 56,88 М 3,0129% 15,36

А 8,4966% 43,31 Н 3,0034% 15,31

Р 7,5809% 38,64 Г 2,4705% 12,59

И 7,5448% 38,45 Б 2,0720% 10,56

О 7,1635% 36,51 Ж 1,8121% 9,24

Т 6,9509% 35,43 Д 1,7779% 9,06

Н 6,6544% 33,92 Вт 1,2899% ​​6,57

С 5,7351% 29,23 К 1,1016% 5,61

Л 5,4893% 27,98 В 1,0074% 5,13

С 4,5388% 23,13 Х 0,2902% 1,48

У 3,6308% 18,51 З 0,2722% 1,39

Д 3,3844% 17,25 Дж 0,1965% 1,00

Р 3,1671% 16,14 К 0,1962% 1,00

Примеры: ** Вход 1**

GXOXKFHKX

Выход 1

7 БОЛЬШЕ НИКОГДА

Вход 2

Oj wz, jm ijo oj wz, ocvo dn ocz lpznodji: Rczoczm 'odn ijwgzm di ocz hdiy oj npaazm.

Выход 2

5 Быть или не быть, вот в чем вопрос: благороднее ли в уме страдать.

#include <stdio.h>
#include <string.h>



double tab[26] = {43.31, 10.56, 23.13, 17.25, 56.88, 9.24,

                    12.59, 15.31, 38.45, 1.00, 5.61, 27.98,

                    15.36, 33.92, 36.51, 16.14, 1.00, 38.64,

                    29.23, 35.43, 18.51, 5.13, 6.57, 1.48,

                    9.06, 1.39};


void calcularfrequencias(const char texto[], double frequencias[]) 
{
    int letras = 0;

    for (int i = 0; texto[i] != '\0'; i++) 
    {
        char c = texto[i];
        if (c >= 'A' && c <= 'Z')
         {
            frequencias[c - 'A']++;
            letras++;
        }
         else if (c >= 'a' && c <= 'z') 
        {
            frequencias[c - 'a']++;
            letras++;
        }
    }


    for (int i = 0; i < 26; i++) 
    {
        frequencias[i] /= letras;
    }
}


int encontrardeslocamento(double frequencias[])
 {
    int deslocamento = 0;
    double menor = 1e9;

    for (int i = 0; i < 26; i++)
     {
        double diferenca = 0.0;
        for (int j = 0; j < 26; j++)
         {
            int x = (j + i) % 26;
            diferenca += (frequencias[j] - tab[x]) * (frequencias[j] - tab[x]);
        }
        if (diferenca < menor) 
        {
            menor = diferenca;
            deslocamento = i;
        }
    }

    return deslocamento;
}

void decifrar(char texto[], int deslocamento)
 {
    for (int i = 0; texto[i] != '\0'; i++) 
    {
        char c = texto[i];
        if (c >= 'A' && c <= 'Z') 
        {
            printf("%c", ((c - 'A' + deslocamento) % 26) + 'A');
        }
        else if (c >= 'a' && c <= 'z') 
        {
            printf("%c", ((c - 'a' + deslocamento) % 26) + 'a');
        } 
        else 
        {
            printf("%c", c);
        }
    }
}

int main() 
{
    char texto_cifrado[10000];
     if (fgets(texto_cifrado, sizeof(texto_cifrado), stdin) != NULL) 
     {

    double frequencias[26];
    calcularfrequencias(texto_cifrado, frequencias);

    int deslocamento = encontrardeslocamento(frequencias);

    printf("%d ", deslocamento);
    decifrar(texto_cifrado, deslocamento);
     }
    return 0;
}


Я пробовал это, но когда я пробую, это не работает при одном вводе: Gx ‘Fwnwj—fwnwjegjw’».

на выходе должно быть: 8 «Никогда-никогда».

но в этом коде на выходе будет 21 Bs «Arire—arirezber». и я не могу этого понять.

Спасибо за помощь.

Какие частоты ваша программа определяет для правильного 8 и неправильного 21? Имеет ли смысл, если ваша программа выбирает 21, судя по этим числам? Я спрашиваю, потому что это разделяет две основные возможные ошибки: а) ошибка в измерении частот, б) принятие решения на основе этих данных.

Yunnosch 10.03.2024 13:45

Есть две ошибки: (1) вы не обнуляете frequencias вначале и (2) вы забыли разделить разницу на Ei, которая есть tab[x] в вашем коде.

n. m. could be an AI 10.03.2024 14:02

@Yunnosch уже решил эту проблему, я забыл добавить две вещи, спасибо!

Birdy 10.03.2024 15:05

Собираетесь ли вы теперь поделиться своим решением, добавив сообщение с ответом? Или вы в противном случае удалите этот вопрос?

Yunnosch 10.03.2024 15:06

@Yunnosch Думаю, я не могу добавить сообщение с ответом, поэтому собираюсь отредактировать и добавить решение

Birdy 10.03.2024 15:09

Нет. Создайте ответный пост. Не добавляйте решение к вопросу, пожалуйста. Даже добавление «SOLVED» не соответствует концепции StackOverflow. Здесь должна быть возможность создать ответный пост, иначе опишите, что вам мешает. Я постараюсь помочь вам добраться до корня этой странности.

Yunnosch 10.03.2024 15:11
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
73
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Регулировка:

frequencias [i] = 0;

поэтому перед началом вычислений он начинается с чистого массива, без сохранения значений в frequencias [i], иначе он начинался бы с frequencias[последнее вычисленное значение];

и

diferenca += (frequencias[j] - tab[x]) * (frequencias[j] - tab[x]) / tab [x];

деление «диференсы» на ожидаемую частоту табуляции [x] (это должна быть соответствующая формула, которую они дают в задании).

#include <stdio.h>

#include <string.h>


double tab[26] = {43.31, 10.56, 23.13, 17.25, 56.88, 9.24,
                    12.59, 15.31, 38.45, 1.00, 5.61, 27.98,
                    15.36, 33.92, 36.51, 16.14, 1.00, 38.64,
                    29.23, 35.43, 18.51, 5.13, 6.57, 1.48,
                    9.06, 1.39};


void calcularfrequencias(const char texto[], double frequencias[]) 
{    for (int i = 0; i < 26; i++) 
{
frequencias [i] = 0;

}
    int letras = 0;
    for (int i = 0; texto[i] != '\0'; i++) 
    {
        char c = texto[i];
        if (c >= 'A' && c <= 'Z')
         {
            frequencias[c - 'A']++;
            letras++;
        }
         else if (c >= 'a' && c <= 'z') 
        {
            frequencias[c - 'a']++;
            letras++;
        }
    }
    for (int i = 0; i < 26; i++) 
    {
        frequencias[i] /= letras;
    }
}
int encontrardeslocamento(double frequencias[])
 {
    int deslocamento = 0;
    double menor = 1e9;
    for (int i = 0; i < 26; i++)
     {
        double diferenca = 0.0;
        for (int j = 0; j < 26; j++)
         {
            int x = (j + i) % 26;
            diferenca += (frequencias[j] - tab[x]) * (frequencias[j] - tab[x]) / tab [x];
        }
        if (diferenca < menor) 
        {
            menor = diferenca;
            deslocamento = i;
        }
    }
    return deslocamento;
}
void decifrar(char texto[], int deslocamento)
 {
    for (int i = 0; texto[i] != '\0'; i++) 
    {
        char c = texto[i];
        if (c >= 'A' && c <= 'Z') 
        {
            printf("%c", ((c - 'A' + deslocamento) % 26) + 'A');
        }
        else if (c >= 'a' && c <= 'z') 
        {
            printf("%c", ((c - 'a' + deslocamento) % 26) + 'a');
        } 
        else 
        {
            printf("%c", c);
        }
    }
}
int main() 
{
    char texto_cifrado[10000];
     if (fgets(texto_cifrado, sizeof(texto_cifrado), stdin) != NULL) 
     {

    double frequencias[26];
    calcularfrequencias(texto_cifrado, frequencias);

    int deslocamento = encontrardeslocamento(frequencias);

    printf("%d ", deslocamento);
    decifrar(texto_cifrado, deslocamento);
     }
    return 0;
}

Предполагая, что вы превращаете комментарий в ответ, скажите об этом. (Автор комментария решил не отвечать, так что это нормально. И, возможно, это только мое мнение, что вам все же следует упомянуть об этом. Просто рекомендация.)

Yunnosch 10.03.2024 15:23

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

Birdy 10.03.2024 15:24

Помощь по форматированию публикации можно найти здесь: stackoverflow.com/help/formatting .

Yunnosch 10.03.2024 15:24

Да, вы не можете принять собственный ответ в течение определенного времени. Это правда. У вас есть вопросы относительно этого правила?

Yunnosch 10.03.2024 15:25

Другие вопросы по теме