我为caesar的密码编写了一个代码,该代码可以正常工作,除了我不能对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;
}
}
}
答案 0 :(得分:2)
caesar()
似乎只是以非常复杂的方式简单地将字符b的位置返回到数组中的z,并且完全省略了!而且,由于alphabets
不是以null结尾的字符串,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()
之间划分密码步长是一个糟糕的设计,缺乏内聚力和不必要的 coupling 。
如果字符x
出现在alphabet
中,则会被alphabet[(i + key) % sizeof( alphabet )] ;
修改。这会像往常一样添加key
,而且还会“环绕”(%
模运算),例如对于key = 1
,z
会绕到{ {1}}而不是像代码一样引用a
数组末尾的字节。至关重要的是,如果它未出现在alphabet
中,则它没有被修改-这就是alphabet
用cipher
初始化的原因。修改x
(cipher
)或到达cipher != x
的结尾时,循环退出。
然后在alphabet
的迭代中:
plain_text
这里的for (i = 0; i <= strlen(plain_text); i++ )
{
cipher_text[i] = caesar( plain_text[i], key ) ;
}
很特殊,但是这里可以确保将nul终止符复制到<= strlen()
-cipher_text
不会对其进行修改。
请注意,上述解决方案仅加密小写文本(原始代码也是如此)。您的代码中还有其他问题和不明智的做法,在注释中进行了讨论,但可能与您的问题没有直接关系,但是使用上述功能,以下完整的实现可以解决大多数问题:
caesar()
示例:
#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 ;
}
忽略大小写,然后在找到匹配项时,如果alphabet[i] == tolower( x )
为大写,则应用cipher = toupper( cipher )
,得出大写密码。
示例输出:
x
请注意,您可以在循环中分配Plain text: aBc, XyZ 123
The plain text is: aBc, XyZ 123
Key: 1
The cipher text is: bCd, YzA 123
之后cipher = x
,而不是在for循环中测试break
-减少测试次数-但是arguably breaks structured programming “规则”-我不会批评别人使用它,但这不是我的偏好。在这种情况下,您可能还使用cipher
来完全跳过循环,但是例如,该实现具有针对重音字符的实现定义的行为,因此,如果要扩展受支持的“字母”,它可能无法按预期工作。
如果仅使用字母中的a到z字符,则可以进一步简化,其中可以使用字符代码值以算术方式确定密码:
isalpha(x)
严格地,这假设字符a到z在目标字符集中是连续的,但是对于可能在其上运行该代码的任何系统(即不是IBM 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 ;
}
阵列解决方案仍然有效。我指出这一点仅仅是因为否则有人会对此发表评论,好像这确实是一个问题。
要解释该表达式:alphabet
:
cipher = ((cipher - 'a') + key) % ('z' - 'a' + 1) + 'a'
-减去'a'的代码,将字符(cipher - 'a')
到a
的值从0到25。z
-添加键“ shift” ... + key
-实际上,此常量表达式解析为... % ('z' - 'a' + 1)
,称为“环绕”。 % 26
a ... +
a - transform the range 0 to 25 back into character codes
z`。