c - Vigenere Cipher 只能在处理 C 中的空格 ("") 之前有效 - 为什么?

标签 c cs50 vigenere

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

 int main(int argc, string argv[])
 {
      string k = argv[1];
      string s = GetString();
      int l = strlen(k);

      for(int i = 0, n = strlen(s); i < n; i++)
      {
          if(s[i] >= 65 && s[i] <= 90)
          {
              int i2 = ((s[i]-65) + (k[i%l]-97)) % 26;
              printf("%c", i2+65);
          } else if(s[i] >= 97 && s[i] <= 122)
          {
              int i2 = ((s[i]-97) + (k[i%l]-97)) % 26;
              printf("%c", i2+97);
          } else
          {
              printf("%c", s[i]);
          }
      }
      printf("\n");
      return 0;
 }

我已经删除了尽可能多的部分,以使代码与问题更相关。基本上为什么当“s”中没有任何空格(“”)时这段代码可以工作,而当“s”由空格(“”)组成时这段代码则不起作用?

正如你们大多数人可能知道的那样,在 argv[1] 处输入的参数是密码的“关键字”。然后用户输入“纯文本”进行加密。当我尝试使用各种单词或句子(如果不包含任何空格“”)时,它会起作用。我只是不明白这背后的逻辑。如果 s[i] 不是前两个条件之一,为什么循环会中断 - 我本以为“else”条件会起作用。

如果有人能对此有所了解,我将非常感激 - 非常感谢!

ps:我知道顶部有一些额外的库,并且 argv[1] 处的用户输入未通过 isalpha() 进行验证。我现在只是想更好地了解循环过程,我已在另一个文件中准备好这些检查。

最佳答案

这是实现我所做的“字符串和键的单独计数器”注释的代码。它还使用字母代码 'a''A' (并避免需要使用 'z''Z' )而不是使用数字。它确实假设您正在处理单字节代码集(不是 UTF-8,除非您在 ASCII 范围内工作),其中小写字母和大写字母各自位于连续范围内(因此它不会不能与 EBCDIC 一起可靠地工作,但可以与大多数其他代码集一起工作),并且它还会忽略重音字符。 (必须执行 setlocale("") 才能获取哪些字符是字母的特定于区域设置的解释。)

#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

int main(int argc, string argv[])
{
    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s key\n", argv[0]);
        return 1;
    }

    string k = argv[1];
    int l = strlen(k);

    for (int i = 0; i < l; i++)
    {
        int c = k[i];
        if (!isalpha(c))
        {
            fprintf(stderr, "%s: non-alpha character %c in key string\n", argv[0], c);
            return 1;
        }
        k[i] = tolower(c);
    }

    printf("Enter a string to be encrypted:\n");
    string s = GetString();
    int n = strlen(s);

    for (int i = 0, j = 0; i < n; i++)
    {
        int c = (unsigned char)s[i];
        if (isupper(c))
            c = ((c - 'A') + (k[j++ % l] - 'a')) % 26 + 'A';
        else if (islower(c))
            c = ((c - 'a') + (k[j++ % l] - 'a')) % 26 + 'a';
        putchar(c);
    }
    putchar('\n');

    return 0;
}

下面是一个示例运行,演示了使用“a”作为维吉尼亚密码 key 中的字母之一的弱点:

./vc caesArandAbrAcaDabRa
Enter a string to be encrypted: 
It is reported that Caesar said "Veni, vidi, vici" when he conquered Britain.
Kt mk rvpbutfu tjaw Cbvscr wsiu "Vrqi, wzdk, vlcj" nhgn lw cfndxesvd Drltbzn.

关于c - Vigenere Cipher 只能在处理 C 中的空格 ("") 之前有效 - 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34910414/

相关文章:

c - 多字符字符常数错误

c - Vigenere Cipher - 如何忽略纯文本中的空格(在 C 中)?

c - 陷入 Vigenere 加密程序的最后部分

从单个客户端套接字 C 连接到多个服务器

c - 使用 struct 和 realloc 验证文件

c - 在 Microchip C18 中,为什么插入 NOP 会导致更大的代码?

c - 除了 for 循环之外,还有其他方法可以检查凯撒密码中是否为整数吗? CS50 pset2 凯撒密码

连接到服务器并获取接收到的缓冲区

c - 如何将主题标签金字塔编程到左侧?

c - 在 cs50 pset3 二分搜索中陷入 while 循环