gpt4 book ai didi

c - 想做凯撒的密码,但不能更改最后两个字符

转载 作者:太空宇宙 更新时间:2023-11-04 01:43:49 25 4
gpt4 key购买 nike

我为凯撒的密码写了一个密码,这个密码有效,除了我不能密码超过8个字母,我也不能处理空格。它显示“>>”这个符号而不是空格。另外,我想在代码的第二个函数中进行二进制搜索,但我不知道我是否做过。

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

char caesar (char x, char alphabets[]);

int j;

int main()

{

char* plain_text = malloc (10 * sizeof(char) + 1);
int key, num;
char* cipher_text = malloc (10 * sizeof(char) + 1);

printf("Plain text: ");
gets(plain_text);
printf("\nThe plain text is: ");
puts(plain_text);
printf("\nKey: ");
scanf("%d", &key);
num = (int)key;

if (key != num)
{
return 1;
}
int i;
char alphabets[] = {'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'};
for (i=0;i<=strlen(plain_text);i++)
{
char x = plain_text[i];
caesar(x, alphabets);
cipher_text[i] = alphabets[j+key];
printf("%c", cipher_text[i]);
}
free(plain_text);
}

char caesar (char x, char alphabets[])

{

if(x == alphabets[13])
{
return 13;
}
for(j = 1; j <= 13; j++)
{
if(x == alphabets[j])
{
return j;
}
}
for(j = 13; j <= strlen (alphabets); j++)
{
if(x == alphabets[j])
{
return j;
}
}
}

最佳答案

caesar()似乎只是以一种非常复杂的方式返回数组中字符b到z的位置,而完全忽略了a!此外,因为alphabets不是以空结尾的字符串strlen()在任何情况下都不是有效的操作。“加密”是由alphabets[j+key]中的main()完成的(不正确),使得caesar()的命名特别糟糕,因为这根本不是它所做的。
以下函数将返回alphabet中任何字符的密码,并保留任何其他字符不变:

char caesar( char x, int key )
{
const char alphabet[] = {'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'};

char cipher = x ;

for( int i = 0;
cipher == x && i < sizeof( alphabet );
i++ )
{
if( alphabet[i] == x )
{
cipher = alphabet[(i + key) % sizeof( alphabet )] ;
}
}

return cipher ;
}

key传递到 ceasar()比传递常量 alphabet更有意义,并且在 alphabet是“已知”的地方执行加密。正如您所做的那样,在 caesar()main()之间分割密码步骤是一个糟糕的设计,缺乏内聚性,并且具有不必要的耦合。
如果字符 x出现在 alphabet中,它将被 alphabet[(i + key) % sizeof( alphabet )] ;修改。这就添加了原来的 key,但也添加了“环绕”(模运算),因此例如,对于 %key = 1环绕到 z,而不是像代码一样引用 a数组末尾以外的一个字节。关键的是,如果它没有出现在 alphabet中,它是未修改的-这就是为什么 alphabet是用 cipher初始化的。当 x被修改时( cipher),或者当 cipher != x结束时,循环退出。
然后在 alphabet的迭代中:
for (i = 0; i <= strlen(plain_text); i++ )
{
cipher_text[i] = caesar( plain_text[i], key ) ;
}

这里的 plain_text是不寻常的,但是这里它确保了nul终结符被复制到 <= strlen()-它不会被 cipher_text修改。
请注意,上面的解决方案只加密小写文本(与原始代码一样)。在您的代码中还有其他问题和不明智的实践,在注释中讨论过,但可能与您的问题没有直接关系,但是使用上述函数,以下完整的实现解决了大多数问题:
#include <stdio.h>
#include <string.h>

char caesar( char x, int key ) ;

#define MAX_TEXT 128

int main()
{
char plain_text[MAX_TEXT] = "" ;
char cipher_text[MAX_TEXT] = "" ;

printf( "Plain text: " );
fgets( plain_text, MAX_TEXT, stdin ) ;

printf( "\nThe plain text is: %s\n", plain_text ) ;

printf( "Key: " ) ;
int key = 0 ;
scanf( "%d", &key );

for( size_t i = 0; i <= strlen( plain_text ); i++ )
{
cipher_text[i] = caesar( plain_text[i], key ) ;
}

printf( "\nThe cipher text is: %s\n", cipher_text ) ;
return 0 ;
}

例子:
Plain text: abc, xyz

The plain text is: abc, xyz

Key: 1

The cipher text is: bcd, yza

允许大写字母的修改:
#include <ctype.h>

char caesar( char x, int key )
{
const char alphabet[] = {'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'};

char cipher = x ;

for( int i = 0;
cipher == x && i < sizeof( alphabet );
i++ )
{
if( alphabet[i] == tolower( x ) )
{
cipher = alphabet[(i + key) % sizeof( alphabet )] ;
if( isupper( x ) )
{
cipher = toupper( cipher ) ;
}
}
}

return cipher ;
}

在这里,测试忽略了大小写,然后当匹配失败时,如果 caesar()是大写,则应用 alphabet[i] == tolower( x )生成大写密码。
示例输出:
Plain text: aBc, XyZ 123

The plain text is: aBc, XyZ 123

Key: 1

The cipher text is: bCd, YzA 123

注意,不是在for循环中测试 cipher = toupper( cipher ),而是在循环中分配 x之后可以 cipher = x-减少测试的数量-但是 arguably breaks structured programming“规则”-我不会批评其他人使用它,但这不是我的偏好。在这种情况下,您还可以使用 break来完全跳过循环,但它具有针对重音字符的实现定义的行为,例如,如果您要扩展支持的“字母表”,它可能无法按预期工作。
如果您只使用字母表中的字符a到z,则可以进一步简化,其中可以使用字符代码值算术确定密码:
char caesar( char x, int key )
{
char cipher = tolower( x ) ;

if( isalpha( x ) )
{
cipher = ((cipher - 'a') + key) % ('z' - 'a' + 1) + 'a' ;
if( isupper( x ) )
{
cipher = toupper( cipher ) ;
}
}

return cipher ;
}

严格地说,这假设字符a到z在目标字符集中是连续的,但对于任何可能在其上运行此代码的系统(即,不是IBM z系列大型机或各种仿古大型机/小型计算机),这是普遍的,如果不是,则 cipher阵列解决方案仍然有效。我指出这一点仅仅是因为,否则有人会对它发表评论,好像它真的是一个问题。
要解释表达式: isalpha(x)
alphabet-减去“a”的代码,得到字符 cipher = ((cipher - 'a') + key) % ('z' - 'a' + 1) + 'a'(cipher - 'a')的值0到25。
a-添加“shift”键
z-这个常量表达式在实际中解析为“环绕”。
... + keya ... % ('z' - 'a' + 1)a % 26z`。

关于c - 想做凯撒的密码,但不能更改最后两个字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57655966/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com