C中简单的凯撒变换

时间:2013-08-31 20:24:52

标签: c

我正在尝试用C创建一个简单的Caesar shift程序,但我似乎无法弄明白。该程序不断崩溃。任何帮助将不胜感激。

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

int main(int arc, const char* argv[])
{
    int shift = atoi(argv[1]);
    char message[256];
    strcpy(message, argv[2]);
    int i;
    for(i = 0; i < strlen(message); i++) {
        printf("%c", message[i] + shift);
    }
    putchar('\n');
    return 0;
}

2 个答案:

答案 0 :(得分:5)

你没有正确实施凯撒密码。您的代码包含以下行,这是错误的:

printf("%c", message[i] + shift);

要正确执行此操作,您需要将其转换为函数:

printf("%c", encrypt(message[i], shift));

让我们实现这个功能:

char encrypt(char input, int shift) {
    if (input >= 'a' && input <= 'z')
        return ((input - 'a' + shift) % 26) + 'a';
    if (input >= 'A' && input <= 'Z')
        return ((input - 'A' + shift) % 26) + 'A';
    return input;
}

只是为了解释数学在该函数中的作用:

  1. input - 'a'告诉我们输入的字母表中的位置(假设输入是小写字母)。因此,如果输入为'c',那么我们将返回2。如果输入为'z',我们会获得25
  2. input - 'a' + shift为我们提供了我们用来制作密码的角色的新位置。请注意,这可能是一个比字母更大的数字(26个字符)。
  3. 因此,要解决该问题,我们使用模运算将该数字绑定在[0 - 25]
  4. 之间
  5. 然后在该角色上添加'a',即可获得我们想要打印的实际角色。
  6. 请注意,这仅适用,因为azAZ的字符代码是连续的。

答案 1 :(得分:4)

您的计划有三个问题。

  1. 程序从argv[1]argv[2]读取,但它假定程序至少接收2个参数。如果它没有收到这么多,那么它可能会崩溃或做任意事情。您应该明确检查程序是否至少(或确切地)收到两个命令行参数:

    if (argc != 3) {
        fprintf(stdout, "Not enough arguments\n");
        exit(1);
    }
    

    注意:将arc重命名为argc,并且程序名称有一个额外的隐式参数,这就是我们检查3的原因。)

  2. 程序将argv[2]复制到固定大小的缓冲区中。如果消息长度超过255个字符(加上空终止符),那么它可能会覆盖内存并导致任意事情发生。在当前情况下,您可以直接处理argv[2]的字符,而无需将其复制到临时变量:

    for (i = 0; argv[2][i] != '\0' ; i++) {
        printf("%c", encrypt(argv[2][i], shift));
    }
    
  3. 凯撒班次需要在z或Z之后环绕。见sharth's answer