您拦截了一个进化不良的恐怖分子组织,该组织使用凯撒方法作为密码。消息始终是英文的。他们所做的就是通过移动字母表的 K 个位置来将每个字母替换为另一个字母。因此,例如,如果我们将字母表向前移动两个位置,我们将得到以下对应关系:
**A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
CDEFGHIJKLMNOPQRSTUVWXYZAB **
当然这个方法有一个非常简单的攻击方式:
尝试所有可能的替代方案;
使用公式:(Ei-Oi)^2 / Ei 计算每个可能的替换每个字母 Ei
的预期相对频率与获得的 **Oi ** 之间的下一个度量您的程序应读取一行最多 10^4 个字符的文本。
您的程序应该打印所需的偏移量和解密的文本。您的程序应该只处理字母(大写或小写)。
编写一个程序来读取一行文本并解密它。使用下表计算每个字母的值 Ei(第三列):
E 11.1607% 56.88 M 3.0129% 15.36
A 8.4966% 43.31 H 3.0034% 15.31
R 7.5809% 38.64 G 2.4705% 12.59
I 7.5448% 38.45 B 2.0720% 10.56
O 7.1635% 36.51 F 1.8121% 9.24
T 6.9509% 35.43 Y 1.7779% 9.06
N 6.6544% 33.92 W 1.2899% 6.57
S 5.7351% 29.23 K 1.1016% 5.61
L 5.4893% 27.98 V 1.0074% 5.13
C 4.5388% 23.13 X 0.2902% 1.48
U 3.6308% 18.51 Z 0.2722% 1.39
D 3.3844% 17.25 J 0.1965% 1.00
P 3.1671% 16.14 Q 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 of ‘Never—nevermore’。”
但在这段代码中,输出是 21 Bs ‘Arire—arirezber’。” 我无法弄清楚。
谢谢您的帮助。
#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;
}