2017-08-13 172 views
0

我正在为Vigenere密码制作一个程序。我让程序成功打印密文。但是,我无法循环钥匙。所以如果我的密钥是'abc'而我的纯文本是hello,它应该打印'hfnlp'而不是'hfn'。如何在vigenere cipherkey中重用(循环)密钥cs50 pset2

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

int main(int argc, string argv[]) 
{ 
    if(argc != 2) 
    { 
     printf("\aError\n"); 
     return 1; 
    } 
    else 
    { 
     string a = argv[1]; // converts argv[1] 

     printf("plaintext: "); 
     string b = get_string(); // takes the plaintext 

     printf("ciphertext: "); 

     for(int c = 0, d = strlen(a); c < d; c++) 
     { 
      for(int e = 0, f = strlen(b); e < f; e++) 
      { 
       if(islower(a[c])) 
        { 
         printf("%c\n", b[e] + ((a[c] - 97) % 26)); // works for lowercase letters 
         return 0; 
        } 
        else if(isupper(a[i])) 
        { 
         printf("%c\n", b[e] + ((a[c] - 65) % 26)); // works for uppercase letter 
        } 
        else 
        { 
         printf("%c", b[e]); // works for non alphabetical inputs 
        } 

        if(true) 
         break; 
      } 
    } 

    printf("\n"); 
} 
} 
+0

当你到达关键的最后,你必须回到起点。模运算符'%'通常用于管理这个,尽管一个简单的条件也适用。您需要一个计数器来逐句通过纯文本;您需要一个单独的计数器来多次循环访问密钥(通常,除非明文比密钥短)。你也只需要一个循环,而不是两个嵌套循环 - 并且它应该遍历纯文本(代码中的“b”)。请注意,初始化'string a = argv [1]中没有'转换';' - 您只是将指针复制到更方便的名称。 –

+0

此外,错误消息应打印到标准错误,并且当命令行出现问题时,指示如何使用该程序通常比仅说'错误'更好。 'fprintf(stderr,“Usage:%s key \ n”,argv [0]);'会更好;你甚至可以使用'fprintf(stderr,“用法:%s key <纯文本\ n”,argv [0]);'来表示如何将纯文本读入程序。 –

+0

@JonathanLeffler我删除了if(true)语句的代码。但是现在,它会打印错误的密码字母。该公式是写在代码中的。但不是让一些字母更正。它输出错误。 [SORRY如果我的英语有错误] –

回答

1

您选择的单字母变量名称是奇数;它使你更难处理你的代码。我不喜欢长名字,但中间长度的变量名称(2-8个字符 - 除了一些程式化的单字母名称(c,i,j,k,ps) - 通常是合适的)。

您遇到了麻烦,因为如果您的密钥是6个字符,而您的字符串是24个字母字符,则由于循环结构,您将尝试输出144个字母字符。你只需要一个循环遍历纯文本中的字符。你有一个单独的变量,循环遍历该键的长度,当它用完时重置回开始。在此代码中,密钥长度为keylen(您使用d),密钥的偏移量(索引)为keyoff(您使用的是c) - 但密钥仍在a中,因为这是您使用的密钥。留给我自己的设备,我可能会使用text(或plain)代替b,textlen代替f,我将使用i而不是e作为循环变量。如果我想使用短指数,我可能会使用k而不是keyoff。我也可能会在原地编辑字符串,并在最后打印整个字符串。

此代码还可确保密钥中的字母字符为小写。它并不能确保关键是全部是阿尔法;它可以说是应该的,因为无论如何都要扫描密钥,所以这样做会很简单。就现在而言,这是一个GIGO的案例 - 垃圾进入垃圾场。

的代码输入字母(a-zA-Z)转换为通过减去aA“偏移到字母”,转换密钥信为偏移到字母,增加了两个偏移模26(的字母数在字母表中),并将偏移量转换回适当大小写的字母。

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

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

    string a = argv[1]; 
    int keylen = strlen(a); 
    for (int i = 0; i < keylen; i++) 
     a[i] = tolower((unsigned char)a[i]); 
    printf("key: %s\n", a); 

    printf("plaintext: "); 
    string b = get_string(); 

    printf("ciphertext: "); 

    int keyoff = 0; 
    // Step through each character of the plain text. Encrypt each 
    // alpha character with the (lower-case) key letter at a[keyoff], 
    // incrementing keyoff. Don't increment key offset when processing 
    // non-alpha data. 
    for (int e = 0, f = strlen(b); e < f; e++) 
    { 
     if (islower(b[e])) 
      printf("%c", ((b[e] - 'a') + (a[keyoff++] - 'a')) % 26 + 'a'); 
     else if (isupper(b[e])) 
      printf("%c", ((b[e] - 'A') + (a[keyoff++] - 'a')) % 26 + 'A'); 
     else 
      printf("%c", b[e]); 
     if (keyoff >= keylen) 
      keyoff = 0; 
    } 
    printf("\n"); 
    return 0; 
} 

当编译为程序vc41和运行,它产生,例如:

$ vc41 abcdef 
key: abcdef 
plaintext: The quick brown Fox jumped over the lazy Dog. 
ciphertext: Tig tyncl dusbn Gqa nzmqgg saes vki qaaa Gsl. 
$ 

我生成的8信随机密钥(它是GZlfmTMk)和运行在一个数字的代码“完整的字母”字符串:

$ vc41 GZlfmTMk 
key: gzlfmtmk 
plaintext: Pack my box with five dozen liquor jugs. 
ciphertext: Vznp yr nyd vtyt yufk czeqg xswtzw vnsc. 
$ vc41 GZlfmTMk 
key: gzlfmtmk 
plaintext: The five boxing wizards jump quickly. 
ciphertext: Zgp kuoq luwtss pujgqox vnyz wtthwek. 
$ vc41 GZlfmTMk 
key: gzlfmtmk 
plaintext: How vexingly quick daft zebras jump. 
ciphertext: Nnh aqquxmkj vgbou jzqy lxnbgr uzyi. 
$ vc41 GZlfmTMk 
key: gzlfmtmk 
plaintext: Bright vixens jump; dozy fowl quack. 
ciphertext: Hqtltm hsddyx vnyz; jnkd rhiv wtlhw. 
$ vc41 GZlfmTMk 
key: gzlfmtmk 
plaintext: The quick brown fox jumps over the lazy dog. 
ciphertext: Zgp vgbou hqzbz yah ptxue hhox ssj xtli jnr. 
$ 

(我会顺便指出,在Mac上运行使用GCC 7.1.0,而不包括该代码链接的MacOS塞拉利昂10.12.6注意(新)CS50库 - 有一个系统功能get_string(),它具有与CS50版本不同的接口,它满足引用但会使程序崩溃。但是,它没有被man get_string记录,所以我不确定该名称的系统函数实际上做了什么;我没有更积极地追逐它,或者发现这个问题有多广泛。这让我很头疼,旧的CS50库没有。叽......)

0

修复此类

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

int main(int argc, string argv[]){ 
    if(argc != 2 || !*argv[1]){ 
     printf("\aError:The number of command arguments is incorrect.\n"); 
     printf("Usage: %s key_string\n", argv[0]); 
     return 1; 
    } 
    //Since it is `return 1;` in the if-statement, 
    //the else clause is unnecessary (unnecessarily deepening the nest) 
    string key = argv[1];//It does not convert. 
    size_t i, key_len; 
    unsigned char curr_char; 
    for(i = 0; (curr_char = key[i]) != '\0'; ++i){ 
     if(!isalpha(curr_char)){ 
      printf("\aError:Only the alphabet can be specified as the key.\n"); 
      return 1; 
     } 
     key[i] -= islower(curr_char) ? 'a' : 'A';//Convert to Deviation 
    } 
    key_len = i; 
    i = 0; 

    printf("plaintext : "); 
    string plain = get_string(); 

    printf("ciphertext: "); 

    for(size_t j = 0; (curr_char = plain[j]) != '\0'; ++j){//Scan of plain text should be the main loop. 
     if(isalpha(curr_char)){ 
      char base_char = islower(curr_char) ? 'a' : 'A';//Avoid using magic numbers 

      putchar(base_char + (curr_char - base_char + key[i]) % 26);//Make the same process one 
      if(++i == key_len) 
       i = 0;//reset key index 
     } else { 
      putchar(curr_char);//non alphabetical inputs 
     } 
    } 
    printf("\n"); 
    free(plain); 
} 
+0

这种方法取决于字符代码的顺序。 – BLUEPIXY