2

我正在尝试在 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;
}
4

2 回答 2

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. 然后在该字符上添加 'a' 得到我们想要打印的实际字符。

请注意,这仅适用于atozAto的字符代码Z是连续的。

于 2013-08-31T20:46:50.497 回答
4

您的程序存在三个问题。

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

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

    注意:重命名arcargc,程序名称有一个额外的隐含参数,这就是我们检查 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 的答案

于 2013-08-31T20:51:25.517 回答