Vigenere Cipher only works up until dealing with a space(“ ”) in C - why?

╄→гoц情女王★ 提交于 2019-12-12 06:50:08

问题


 #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;
 }

I have removed as many parts as I can in order to make the code more relevant to the question. Basically why does this code work when "s" does not have any space(" ") in it and doesn't when "s" consists of space(" ")?

As most of you may know the idea is the argument entered at argv[1] is the "keyword" for the cipher. User then inputs a "plain-text" to cipher (s). It works when I try with various words or sentences if it doesn't include any space, " ". I just don't understand the logic behind this. Why does the cycle break if s[i] is not one of the first two conditions - I would have thought that "else" condition would work.

I would really appreciate it if someone can shed some light on this - many thanks in advance!

ps: I know there are some extra libraries at the top and the user input at argv[1] is not verified via isalpha(). I just want to understand the cycle process better for now, I have those checks in another file ready.


回答1:


Here is code that implements the 'separate counters for string and key' comment that I made. It also uses the letter codes 'a' and 'A' (and avoids needing to use 'z' or 'Z') instead of using numbers. It does assume that you are dealing with a single-byte code set (not UTF-8 unless you're working in the ASCII range) where the lower-case and upper-case letters are each in a contiguous range (so it won't work reliably with EBCDIC, but will with most other code sets), and it also ignores accented characters. (It would have to do setlocale("") to get locale-specific interpretations of which characters are letters.)

#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;
}

Here is a sample run that demonstrates the weakness of using 'a' as one of the letters in the key for this Vigenere cipher:

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


来源:https://stackoverflow.com/questions/34910414/vigenere-cipher-only-works-up-until-dealing-with-a-space-in-c-why

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!