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

时间:2017-09-05 10:52:21

标签: c encryption caesar-cipher

我做了这个程序,似乎没有工作,你能告诉我为什么吗?我花了3个小时才弄清楚它为什么不起作用,但我不知道。我想知道它是不是有转移的东西,但我不确定。这是我的第一个项目,我对一些基本的错误表示遗憾。

#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] != '\0'; 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] != '\0'; 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);
}

这是一个输出屏幕:

screenshot

1 个答案:

答案 0 :(得分:3)

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

../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);

但代替用于%d的{​​{1}},对于C字符串(int),它应该是%s。最好使用char*来避免string format vulnerability。此外,它应该只是%99s没有&符号(message)因为the array name will decay&char*将是指向数组的指针:{{1 }}。这会导致警告,因为&message期望char (*)[100]

%s

此外char*返回成功读取元素的数量。我建议始终检查指示错误的返回值。

<强> 2。解密中的逻辑错误:

当您减去char message[100]; if (1 != scanf("%99s", message)) /* buffer size - 1 */ return EXIT_FAILURE; 值时,它必须是scanf(),而不是检查message[i] > 'z'。在这种情况下,再添加26而不是减去它。

message[i] < 'a'

编辑#1:

您输入的邮件还有另一个逻辑问题。您的代码仅适用于由较低字母组成的邮件。您可以将其扩展为使用大写字母。

此外,您的缓冲区可以保留shift s 1 ,因为它被声明为for (i = 0; message[i] != '\0'; i++) { message[i] = message[i] - shift; if (message[i] < 'a') message[i] = message[i] + 26; } ,这意味着如果计算:signed char overflows the bahaviour is undefined 。例如,如果您使用字符char message[100];ASCII code中的小数122)和message[i] = message[i] + shift;为6,这将导致128但z最多可以容纳127

1 我写“可以保留shift s”,因为C标准将其留给了define wether a char is signed or unsigned的实现,但对于GCC默认情况下,MSVC signed char将为signed char