C中的凯撒密码 - 加密和解密

Caesar cipher in C - encryption and decryption

我制作了这个程序,但似乎不起作用,你能告诉我为什么吗?我花了大约 3 个小时才弄清楚为什么它不起作用,但我不知道。我想知道这是否与 shift 无关,但我不确定。这是我制作的第一个程序,对于一些基本错误我深表歉意。

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

int main(int argc, char** argv) {

   char message[100];
   int shift;
   int i;
   int choice;

   printf("Enter operation with message\n");
   printf("encrypt - 1\n");
   printf("decrypt - 2\n");
   scanf("%d", &choice);

   switch(choice)
   {
      case 1:
      {
         printf("Enter message to encrypt\n");
         scanf("%d", &message);

         printf("Enter shift\n");
         scanf("%d", &shift);

         for (i = 0; message[i] != '[=10=]'; i++)
         {
            message[i] = message[i] + shift;
            if (message[i] > 'z')
               message[i] = message[i] - 26;
         }
         printf("Encrypted message: %s\n", message);
         break;
      }
      case 2: 
      {
         printf("Enter message to decrypt\n");
         scanf("%d", &message);

         printf("Enter shift\n");
         scanf("%d", &shift);

         for (i = 0; message[i] != '[=10=]'; i++)
         {
            message[i] = message[i] - shift;
            if (message[i] > 'z')
               message[i] = message[i] - 26;
         }
         printf("Decrypted message: %s\n", message);
         break;
      }
   }

   return (EXIT_SUCCESS);
}

这是一个输出屏幕:

始终注意编译器警告。如果我编译您的代码,我会收到以下警告(以及更多警告):

../main.c:21:10: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘char (*)[100]’ [-Wformat=]
          scanf("%d", &message);
          ^
../main.c:38:10: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘char (*)[100]’ [-Wformat=]
          scanf("%d", &message);
          ^

主要有两个问题:

1. scanf():

格式说明符错误

了解不同的格式说明符 here on cppreference
在您使用的代码中:

char message[100];
scanf("%d", &message);

但不是用于 int%d,对于 C 字符串 (char*) 应该是 %s。最好使用 %99s 来避免 string format vulnerability. Further it should be just message without the ampersand (&) because the array name will decaychar*,但 &message 将是指向数组的指针:char (*)[100]。这将导致警告,因为 %s 期望 char*.

char message[100];
if (1 != scanf("%99s", message)) /* buffer size - 1 */
   return EXIT_FAILURE;

此外scanf() returns 成功读取元素的数量。我建议始终检查指示错误的 return 值。

2。解密逻辑错误:

而不是检查 message[i] > 'z',它必须是 message[i] < 'a',因为您要减去 shift 值。在这种情况下,进一步加 26 而不是减去它。

for (i = 0; message[i] != '[=13=]'; i++)
{
   message[i] = message[i] - shift;
   if (message[i] < 'a')
      message[i] = message[i] + 26;
}

编辑#1:

您输入的消息还有另一个逻辑问题。您的代码仅适用于由小写字母组成的消息。您可以将其扩展为使用大写字母 to.

此外,您的缓冲区可能包含 signed chars1,因为它被声明为 char message[100];,这意味着如果计算:message[i] = message[i] + shift; overflows the bahaviour is undefined. That would happen for example if you use character z (decimal 122 in ASCII code) 和 6 的 shift 将导致 128 但 signed char 最多可以容纳 127.


1 我写 "may hold signed chars" 因为 C 标准将它留给 define wether a char is signed or unsigned 的实现,但对于 GCC 和 MSVC,默认情况下 char 将是 signed char