Vigenere Cipher 只能在处理 C 中的空格(“”)之前有效 - 为啥?

Posted

技术标签:

【中文标题】Vigenere Cipher 只能在处理 C 中的空格(“”)之前有效 - 为啥?【英文标题】:Vigenere Cipher only works up until dealing with a space(" ") in C - why?Vigenere Cipher 只能在处理 C 中的空格(“”)之前有效 - 为什么? 【发布时间】:2016-01-20 21:00:23 【问题描述】:
 #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] 不是前两个条件之一,为什么循环会中断 - 我原以为“其他”条件会起作用。

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

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

【问题讨论】:

建议使用'a''z'(以及'A''Z')代替数字。 您的GetString 函数是如何工作的? '当“s”包含空格(“”)'是什么意思? 当您处理非字母字符时,您会跳过密钥中的一个字母,因为您使用i 来逐步检查密钥和要加密的数据。您需要使用单独的索引。 @nsilent22: GetString() 是包含&lt;cs50.h&gt; 标头时的半标准函数。你可以很容易地在网上找到源代码;它经常出现在 SO 上。 编程中的一般规则:不要使用幻数。 【参考方案1】:

这是实现我所做的“字符串和键的单独计数器”注释的代码。它还使用字母代码'a''A'(并避免使用'z''Z')而不是使用数字。它确实假设您正在处理一个单字节代码集(不是 UTF-8,除非您在 ASCII 范围内工作),其中小写和大写字母都在一个连续的范围内(所以它不会t 与 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”作为此 Vigenere 密码的密钥中的一个字母的弱点:

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

【讨论】:

以上是关于Vigenere Cipher 只能在处理 C 中的空格(“”)之前有效 - 为啥?的主要内容,如果未能解决你的问题,请参考以下文章

C中的Vigenere Cipher:空间未被忽略

Vigenere Cipher Key 未按预期工作

cipher命令有啥用?

Vigenere Cipher - 莫名其妙的细微差别

C++ 链表凯撒密码 Vigenere Cipher

Vigenere Cipher - 不给信[关闭]