Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
240 views
in Technique[技术] by (71.8m points)

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

 #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("
");
      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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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
", 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
", argv[0], c);
            return 1;
        }
        k[i] = tolower(c);
    }

    printf("Enter a string to be encrypted:
");
    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('
');

    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.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.9k users

...