关于CS50 pset2 vigenere

时间:2018-12-26 02:09:05

标签: c cs50 vigenere

为什么我的代码不会跳过空格并导致错误的加密顺序?

当我查看示例“ Hello,World!”时,我的代码也计算了空间,并转换为“ Iekmo,Wnslc!”。而不是“ Iekmo,Vprke!”使用键“ baz”

有人可以解释背后的逻辑吗?非常感谢!

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

//getting user encryption key


int main(int argc, string argv[])
{

    if (argc != 2)
    {
        printf("Usage: ./vigenere keyword\n");
        return 1;
    }
    //check if all are alphabeticals
    else 
    {
           for (int i = 1; i < argc; i++)
        {
            for (int j = 0; j < strlen(argv[i]); j++)
            {
                if (isalpha(argv[i][j]) == false)
                {                
                    printf("Usage: ./vigenere keyword\n");
                    return 1;
                }
            }
        }
    }  


    //getting plaintext divide it into each character
    string pt = get_string("plaintext: ");

    printf("ciphertext: ");
    //convert to ciphertext
    //C = (P + k) % 26
    for (int r = 0; r < strlen(pt); r++)
    {                           
        if (isupper(pt[r]))
        {
            //making loop with j group corresponding to keyword
            int j = r % strlen(argv[1]);
            int key = tolower(argv[1][j]) - 97;
            printf("%c", (pt[r] - 65 + key) % 26 + 65);
        }
        else if (islower(pt[r]))
        {
            //making loop with j group corresponding to keyword
            int j = r % strlen(argv[1]);
            int key = tolower(argv[1][j]) - 97;
            printf("%c", (pt[r] - 97 + key) % 26 + 97);
        }
        else
        {
            printf("%c", pt[r]);
        }

     }            
       printf("\n");       

}

2 个答案:

答案 0 :(得分:1)

问题在于此处{ "presets": [ "es2015", "react" ] } 的j的计算。键的索引与int j = r % strlen(argv[1]);(消息的索引)无关。程序需要仅根据密钥(的长度)来遍历密钥。每次“使用”键索引时,都需要增加它,然后“包装”它,以使它不会超出结尾。您可以考虑在r循环之前声明j;每当您使用键索引时,递增j(提示:r);并用模运算符“包装” j(提示:j++)。我将实际代码留给您。

答案 1 :(得分:1)

显示起来比解释容易得多:

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

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        fprintf(stderr, "Usage: %s keyword\n", argv[0]);
        return 1;
    }

    for (int i = 1; i < argc; i++)
    {
        for (int j = 0; argv[i][j] != '\0'; j++)
        {
            if (isalpha(argv[i][j]) == false)
            {                
                fprintf(stderr, "%s: non-alphabetic character '%c' (%d) in key\n",
                        argv[0], argv[i][j], argv[i][j]);
                return 1;
            }
        }
    }

    string pt = get_string("plaintext:  ");

    printf("ciphertext: ");
    int k = 0;
    int keylen = strlen(argv[1]);
    for (int r = 0; pt[r] != '\0'; r++)
    {                           
        if (isupper(pt[r]))
        {
            int j = k++ % keylen;
            int key = tolower(argv[1][j]) - 'a';
            printf("%c", (pt[r] - 'A' + key) % 26 + 'A');
        }
        else if (islower(pt[r]))
        {
            int j = k++ % keylen;
            int key = tolower(argv[1][j]) - 'a';
            printf("%c", (pt[r] - 'a' + key) % 26 + 'a');
        }
        else
        {
            printf("%c", pt[r]);
        }

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

示例运行:

$ ./vig89 baz
plaintext:  Hello, World!
ciphertext: Iekmo, Vprke!
$

正如我在评论中指出的那样,您需要将“字符串位置r”与“加密字符号”分开。您需要一个额外的变量,该变量仅在字符为字母时才递增。

在上面的代码中,k是额外的变量(keylen是另一个变量,但它只是记录密钥的长度,而不是重复调用strlen())。如果知道该字符是字母,则k中的值将递增。

我注意到处理argv[1]可能是明智的,这样您就不必每次都进行tolower()转换;您可以在验证关键字的同时这样做。

我还报告了有关标准错误的错误,并且没有在循环的条件部分中使用strlen()。尽管使用3个字母的键的代价并不高昂,但如果您开始计算每次迭代的字符串长度为20 KiB,那么您可能会发现开销(除非编译器设法对其进行优化) -可能会,也可能不会)。我还将I / O中的纯文本和密文对齐。

还有很多其他可能/应该进行的更改。例如,不需要第一个for (int i = 1; …)循环;您只有一个参数,因此只需要内部for (int j = 0; …)循环。使用if (!isalpha(argv[i][j]))比将结果与false进行比较也更惯用了,尤其是因为不能保证isalpha宏返回0或1(它返回零或非零)。 –因此将if (isalpha(argv[i][j]) == false)更改为if (isalpha(argv[i][j] != true)是不可靠的。我可能会创建一个简单的变量char *key = argv[1];(或者在CS50的背景下创建string key = argv[1];,尽管我不认为CS50 typedef char *string;是个好主意),并在程序。