我如何重复' for'使用' do while'环

时间:2017-03-15 17:57:32

标签: c encryption vigenere

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

''的最后一行。循环是抛出未声明的标识符i的错误。这是我唯一的错误。内部' for'循环来自Caesar Cipher并通过所有检查。我认为我的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 个答案:

答案 0 :(得分:1)

我认为你有太多的循环[等级]。

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

主要推动力是遍历所有单词字符。一个循环使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;
}

<强>更新

我写的上面的代码非常接近,但不是Vigenere,因为你的原始方程式已关闭。键值必须是偏移量/行号,因此需要从中减去'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检查,除了这一个:(加密“世界,打个招呼!”作为“xoqmd,rby gflkp!”使用“baz”作为关键字\期望输出,但不是“ciphertext:xoqmd,szz gflkp !\ n“。它没有正确地加上'说'这个词,这很奇怪。

我使用Vigenere上维基百科页面中的测试数据/示例对其进行了测试,但它只有一个现成的测试示例[没有空格或标点符号]。

  

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

空格直接复制的,所以没关系。但是......

正确的方法是,当复制非alpha字符时,密钥索引必须递增。

我的版本使用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;
}