2017-03-15 98 views
-1

这是我的Vigenere密码代码。我正在尝试使用do while循环来重复遍历用户输入的键。密钥应用于用户输入的明文单词,一次一个字母。我需要能够遍历密钥直到明文单词结束,以防密钥短于单词。我试图使用do-while循环添加重复循环,第一个for循环是关键迭代。如何使用'do while'循环重复'for'循环

'do while'循环的最后一行是抛出未声明标识符i的错误。这是我得到的唯一的错误。 'for'循环内部来自凯撒密码,并通过了所有检查。我认为我的while while循环是错误的。如果我添加char * word [i]或word [i]的定义,无论我在哪里放置它,都会产生遮蔽错误。我想使用这段代码,而不是彻底改变它,所以我明白如果可以这样做。但是,任何建议都会受到欢迎。

int main(int argc, char* argv[]) 
{ 
    if (argc<2) //key 
    { 
     printf("Please enter your word key"); //prompts if no key is entered 
     return 1; 
    } 

    char* key = (argv[1]); 

    if(argc>=2) 
    { 
     printf("plaintext:"); 
     char* word = GetString(); 

     printf("ciphertext:"); 

     do 
     { //starts loop to repeat following for loop 

      for(int l=0; l<strlen(key); l++) //iterate over letters in key 
      { 
       int num=l; 
       for(int i=0; i<strlen(word); i++) //iterates through word entered by user as plaintext 
       { 
        if(isupper(word[i])) //if original characters are uppercase 
        { 
         int cipher = (word[i] + num -65) % 26 + 65; 
         printf("%c", cipher); 
        } 
        else if(islower(word[i])) //if original characters are lowercase 
        { 
         int cipher = (word[i] + num - 97) % 26 + 97; 
         printf("%c", (cipher)); 
        } 
        else //all other types of characters 
        { 
         printf("%c", word[i]); 
        } 
       } 
      } 
      printf("\n"); 
     }while((word[i])<strlen(word)); // loop to recommence iterating over letters in the key (i throwing undeclared identifier error) 
    } 
} 
+1

那'i'在'for'循环的初始化表达式声明,所以它只有'for'循环内有效......这就是为什么你不能在'do ... while()'条件下测试它。只需在'do ... while()'之前声明它,而不是在'for'的初始化之前。还要记住'for'后的'i'会比通过'for'循环的最后一次更大。 – Dmitri

+0

变量'i'在作用域'for'循环的范围上受到限制。在该循环之外不可访问。如果你想在'do ... while'循环的'while'条件中访问'i',你需要在'do ... while'循环的范围之外定义它(如果你在里面定义它,它会不能在条件下访问;在条件之前,它会在'}处不存在 –

+0

我明白这就是为什么发生这种情况,但我找不到解决方法。每当我重新声明我在任何地方否则在脚本中我会看到一个过度阴影的错误,你能不能再告诉我如何再次表达word [i],以及在哪里这样做,以避免在脚本中出现阴影错误,因为我尝试了所有我能想到的?还有什么是你在底部脚本的我而行的意见。它是另外合适?有另一种方式,我可以表达这种循环到了关键,只要有剩余的字中的字母反复迭代? – Android

回答

1

我觉得你有太多的循环[levels]。

如果密钥长度在单词结束之前用完,则重新开始加密单词开头的中的单词(即错误)。

主要的重点是循环所有字词。 A 单个循环递增i工作,提供它也递增l [模数键长度]。

这里有一个清理版本[请原谅无偿风格清理]:

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

// NOTE: I don't have GetString on my system 
char *FakeGetString(void); 

int 
main(int argc, char *argv[]) 
{ 

    // key 
    // prompts if no key is entered 
    if (argc < 2) { 
     printf("Please enter your word key"); 
     return 1; 
    } 

    char *key = (argv[1]); 
    int klen = strlen(key); 

    if (argc >= 2) { 
     printf("plaintext:"); 

#if 0 
     char *word = GetString(); 
#else 
     char *word = FakeGetString(); 
#endif 

     int wlen = strlen(word); 

     printf("ciphertext:"); 

     // current key index 
     int l = 0; 

     // starts loop to repeat following for loop 
     // iterates through word entered by user as plaintext 
     // advance to next key char [with wrap to beginning if we're short] 
     for (int i = 0; i < wlen; ++i, l = (l + 1) % klen) { 
      int num = key[l]; 
      int cipher; 

      // if original characters are uppercase 
      if (isupper(word[i])) { 
       cipher = (word[i] + num - 65) % 26 + 65; 
      } 

      // if original characters are lowercase 
      else if (islower(word[i])) { 
       cipher = (word[i] + num - 97) % 26 + 97; 
      } 

      // all other types of characters 
      else { 
       cipher = word[i]; 
      } 

      printf("%c", cipher); 
     } 

     printf("\n"); 
    } 

    return 0; 
} 

// NOTE: I don't have GetString on my system 
char * 
FakeGetString(void) 
{ 
    static char buf[1000]; 
    char *cp; 

    fgets(buf,sizeof(buf),stdin); 
    cp = strchr(buf,'\n'); 
    if (cp != NULL) 
     *cp = 0; 

    return buf; 
} 

UPDATE:

上面的代码我写的是很接近,但没有的V @ genere因为你的原始方程已关闭。键值必须是偏移/行号,因此需要从中减去'A'(即关键字只能是大写)。

所以,这里是修正版本[有一些额外的清理]:

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

// NOTE: I don't have GetString on my system 
char *FakeGetString(void); 

int 
baseof(int chr) 
{ 
    int base; 

    // if original character is uppercase 
    if (isupper(chr)) { 
     base = 'A'; 
    } 

    // if original character is lowercase 
    else if (islower(chr)) { 
     base = 'a'; 
    } 

    // anything else 
    else 
     base = 0; 

    return base; 
} 

int 
main(int argc, char *argv[]) 
{ 
    int kval; 
    int base; 
    int i; 

    // key 
    // prompts if no key is entered 
    if (argc < 2) { 
     printf("Please enter your word key\n"); 
     return 1; 
    } 

    char *key = argv[1]; 
    int klen = strlen(key); 

    // key must be uppercase and we only want row numbers 
    for (i = 0; i < klen; ++i) { 
     kval = key[i]; 
     base = baseof(kval); 

     if (base) { 
      key[i] = kval - base; 
      continue; 
     } 

     printf("Key value must be only A-Z\n"); 
     return 1; 
    } 

    if (argc >= 2) { 
     printf("plaintext:"); 

#if 0 
     char *word = GetString(); 
#else 
     char *word = FakeGetString(); 
#endif 
     int wlen = strlen(word); 

     printf("ciphertext:"); 

     // starts loop to repeat following for loop 
     // iterates through word entered by user as plaintext 
     // advance to next key char [with wrap to beginning if we're short] 
     for (i = 0; i < wlen; ++i) { 
      int wval = word[i]; 
      int cipher; 

      base = baseof(wval); 

      // uppercase or lowercase 
      if (base) { 
       kval = key[i % klen]; 
       cipher = ((wval - base) + kval) % 26 + base; 
      } 

      // all other types of characters 
      else { 
       cipher = wval; 
      } 

      printf("%c",cipher); 
     } 

     printf("\n"); 
    } 

    return 0; 
} 

// NOTE: I don't have GetString on my system 
char * 
FakeGetString(void) 
{ 
    static char buf[1000]; 
    char *cp; 

    fgets(buf,sizeof(buf),stdin); 
    cp = strchr(buf,'\n'); 
    if (cp != NULL) 
     *cp = 0; 

    return buf; 
} 

更新#2:

您的代码通过了所有check50检查,除了这一个: :(使用“baz”作为关键字\期望的输出,而不是“密文:xoqmd,szz gflkp!\”来加密“世界,打个招呼!”为“xoqmd,rby gflkp!”,它不会加密单词'正确地说',这就是伟RD。

我测试使用来自上的V @ genere维基百科页测试数据/例子,但它只有一个准备试验例[而不空格或标点。

这是包含一个空格(在“say”之前)的唯一检查。空间必须直接复制。也许这就是原因。

的空间直接复制,所以这是好的。但是...

正确的方法是,当复制非字母字符时,密钥索引必须增加而不是

我的版本中使用i索引的语句和i % klen索引的关键,所以关键指标将总是递增[有效。这是错误。

讽刺的是,我已经不知道这一点,但没有在当时展开的测试数据。

因此,解决方案是[再:-)]分离索引的变量。

这里的修正版本。当我将其固定我改名i变量为更具说明性的(例如widx)和(重新)创建的索引变量的密钥(例如kidx)。

请注意,现在kidx只有在实际加密字符时递增。在“通过”的情况下不

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

// NOTE: I don't have GetString on my system 
char *FakeGetString(void); 

int 
baseof(int chr) 
{ 
    int base; 

    // if original character is uppercase 
    if (isupper(chr)) { 
     base = 'A'; 
    } 

    // if original character is lowercase 
    else if (islower(chr)) { 
     base = 'a'; 
    } 

    // anything else 
    else 
     base = 0; 

    return base; 
} 

int 
main(int argc, char *argv[]) 
{ 
    int kval; 
    int base; 
    int widx; 
    int kidx; 

    // key 
    // prompts if no key is entered 
    if (argc < 2) { 
     printf("Please enter your word key\n"); 
     return 1; 
    } 

    char *key = argv[1]; 
    int klen = strlen(key); 

    // key must be uppercase and we only want row numbers 
    for (kidx = 0; kidx < klen; ++kidx) { 
     kval = key[kidx]; 
     base = baseof(kval); 

     if (base) { 
      key[kidx] = kval - base; 
      continue; 
     } 

     printf("Key value must be only A-Z\n"); 
     return 1; 
    } 

    if (argc < 2) 
     return 1; 

    printf("plaintext:"); 

#if 0 
    char *word = GetString(); 
#else 
    char *word = FakeGetString(); 
#endif 
    int wlen = strlen(word); 

    printf("ciphertext:"); 

    kidx = 0; 

    // starts loop to repeat following for loop 
    // iterates through word entered by user as plaintext 
    // advance to next key char [with wrap to beginning if we're short] 
    for (widx = 0; widx < wlen; ++widx) { 
     int wval = word[widx]; 
     int cipher; 

     base = baseof(wval); 

     // uppercase or lowercase 
     if (base) { 
      kval = key[kidx]; 
      cipher = ((wval - base) + kval) % 26 + base; 
      kidx = (kidx + 1) % klen; 
     } 

     // all other types of characters 
     else { 
      cipher = wval; 
     } 

     printf("%c",cipher); 
    } 

    printf("\n"); 

    return 0; 
} 

// NOTE: I don't have GetString on my system 
char * 
FakeGetString(void) 
{ 
    static char buf[1000]; 
    char *cp; 

    fgets(buf,sizeof(buf),stdin); 
    cp = strchr(buf,'\n'); 
    if (cp != NULL) 
     *cp = 0; 

    return buf; 
} 
+0

您的代码通过了所有检查check50除了这一个::(加密“的世界里,打个招呼!”为使用“巴兹”作为关键字 \预期的输出,而不是“密文“xoqmd,RBY gflkp!” xoqmd,SZZ gflkp! \ N”。它没有恰当地加密'say'这个词,这很奇怪。这是包含空格的唯一检查(在“说”之前)。空间必须直接复制。也许这就是原因。 – Android

+0

那个人按预期通过了所有的check50检查。我会研究它,但我不明白它,然后再次启动我的代码。你的看法与我正在尝试做的很不一样。感谢你的协助。我认为这有点适得其反,因为我们没有被教导只使用我们在现实世界中找到的库。 – Android

+0

我给你3个版本。从第一个[最接近你原来的]开始。看看你自己的差异。然后,第二和第三。每一个改进算法和模块化/简单性[这是故意作为教学工具]。问问自己:有什么不同,他为什么这样做?你的原始有3个循环,我有一个。想想:为什么?那么,为什么'baseof'创建(提示:因为,否则会有复制的代码)。对于这样简单的东西,不会有太多的替代方法可以做到这一点,不增加不必要的复杂性或代码复制 –