cs50x 2020-pset2-替换-密钥中重复的字符

时间:2020-08-20 13:44:53

标签: cs50

在检查我的代码中是否存在CS50课程2020的pset2中的替换问题时,在处理密钥中的重复字符时,我总是遇到错误。我的代码和更多详细信息在下面-有人可以帮忙吗?谢谢

它给我的错误消息是

:( handles duplicate characters in key
timed out while waiting for program to exit

当我检查代码中是否有重复的字符时,它似乎可以正常工作(打印用法:./ substitution键并结束程序)

下面的代码

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

int main(int argc, string argv[])
{
// Check that only one argument submitted



if (argc == 2)
{

    // Check that key contains 26 characters
    int keylen = strlen(argv[1]);
    if (keylen == 26)
    {
        // Check that all characters are letters
        for (int i = 0; i < keylen; i++)
        {
            bool lettercheck = isalpha(argv[1][i]);
            if (lettercheck == true)
            {
                // THIS IS CAUSING ERROR - Check that no letters have been repeated - put all in lowercase to do so
                for (int n = 0; n < i; n++)
                {
                    char currentletter = argv[1][i];
                    char previousletter = argv[1][i - 1];
                    if (tolower(currentletter) == tolower(previousletter))
                    {
                        printf("Usage: ./substitution key\n");
                        return 1;
                    }
                }
            }
            else
            {
                printf("Usage: ./substitution key\n");
                return 1;
            }
        }
    }
    else
    {
        printf("Key must contain 26 characters.\n");
        return 1;
    }
}
else
{
    printf("Usage: ./substitution key\n");
    return 1;
}

// Get user input

string input = get_string("plaintext: ");

//Transform input using key
for(int i = 0; i < strlen(input); i++)
{
    char currentletter = input[i];
    int testlower = islower(currentletter);
    int testupper = isupper(currentletter);
    if (testupper > 0)
    {
        int j = input[i] - 65;
        input[i] = toupper(argv[1][j]);
    }
    else if (testlower > 0)
    {
        int j = input[i] - 97;
        input[i] = tolower(argv[1][j]);
    }
}

printf("ciphertext: %s\n", input);
}

编辑: 找出解决方案-第二个for循环的问题是针对 i-1 次而不是n次进行迭代

代码应该是

    charpreviouslletter = argv[1][n] 

代替

     charpreviousletter = argv[1][i - 1]

    for (int n = 0; n < i; n++)
            {
                char currentletter = argv[1][i];
                char previousletter = argv[1]**[i - 1]**

1 个答案:

答案 0 :(得分:0)

在此循环中-

 // THIS IS CAUSING ERROR - Check that no letters have been repeated - put all in lowercase to do so
for (int n = 0; n < i; n++)
{
    char currentletter = argv[1][i];
    char previousletter = argv[1][i - 1];
    if (tolower(currentletter) == tolower(previousletter))
    {
        printf("Usage: ./substitution key\n");
        return 1;
    }
}

您仅将当前字符与前一个字符进行比较。这不适用于abcdefca

之类的字符串

请注意ca的重复方式-但是它们并不紧邻原件,因此您的逻辑将找不到这些重复品。您的逻辑仅适用于彼此相邻的重复项,例如aabcddef

相反,您需要记录遍历时遇到的字符。如果遇到已经已经遇到的角色,您就会知道有重复的角色。

非常感谢,密钥只能包含字母表中的所有26个字符,且不能重复。这意味着您可以简单地拥有一个由26个插槽组成的int数组-每个插槽都会计算该索引处字母的出现次数。索引0代表'a',索引1代表'b',依此类推。

这样,您可以非常容易地使用letter - 'a'获得字母字符的索引,其中letter是字母字符。因此,如果lettera,您将得到0,这实际上是'a'的索引

此外,遍历键时会有一个嵌套循环,该嵌套循环遍历键。除非它仅执行直到确定的索引,该索引是外循环的当前索引。这似乎是浪费而又怪异的。为什么不简单地循环浏览一次,请检查当前字符是否为字母,还请检查该字符是否以前曾遇到过。这就是您要做的一切!

int letter_presence[26];
char upperletter;
string key = argv[1];
if (strlen(key) == KEY_LEN)
{
    for (int index = 0; index < KEY_LEN; index++)
    {
        if (!isalpha(key[index]))
        {
            // Wrong key - invalid character
            printf("Usage: ./substitution key\n");
            return 1;
        }
        if (letter_presence[tolower(key[index]) - 'a'] == 0)
        {
            // This letter has not been encountered before
            letter_presence[upperletter - 'A'] = 1;
        }
        else
        {
            // Wrong key - Duplicate letters
            return 1;
        }
    }
    // All good
}