【问题标题】:Troubles with CS50's pset2 "substitution" outputCS50 的 pset2 “替代”输出的问题
【发布时间】:2020-12-17 15:02:57
【问题描述】:

我似乎无法理解我的程序有什么问题。该作业是 CS50 第 2 周问题集的“替代”。目标是创建一个程序,在用户键入 26 个字符的密钥作为 argv[2] 后,将用户键入的文本转换为加密文本用键切换常规字母表。我的代码几乎完全可以正常工作,但是对于我要加密的每个文本都有一两个字母(每次都会更改),输出是错误的。

例如 ./substitution YUKFRNLBAVMWZteogxhcipjsqd

明文:这是 CS50

密文:Cbah ah DH50

(其中字母C应该是K,而不是D)

甚至:

./substitution NQXPOMAFTRHLZGECYJIUWSKDVB

明文:这是 CS50

密文:Kfki ki DI50

(其中,由于我不知道的原因,字母 T 和字母 i 都是 'k' 并且都是错误的)

我已经拼命寻找这个错误的原因几个小时,但我似乎找不到它。如果你们中的一个人能帮我找到它,我将不胜感激。 提前致谢。

(如果您需要进一步澄清输出,这里是“Check50”工具的消息:

:) 替换.c 存在

:) 替换.c 编译

:( 使用 ZYXWVUTSRQPONMLKJIHGFEDCBA 作为密钥将“A”加密为“Z” 预期“密文:Z...”,而不是“密文:A...”

:( 使用 ZYXWVUTSRQPONMLKJIHGFEDCBA 作为密钥将“a”加密为“z” 预期“密文:z...”,而不是“密文:a...”

:( 使用 NJQSUYBRXMOPFTHZVAWCGILKED 作为密钥将“ABC”加密为“NJQ” 预期“密文:NJ ...”,而不是“密文:CF ...”

:( 使用 NJQSUYBRXMOPFTHZVAWCGILKED 作为密钥将“XyZ”加密为“KeD” 预期“密文:Ke...”,而不是“密文:Ke...”

:( 使用 YUKFRNLBAVMWZTEOGXHCIPJSQD 作为密钥将“This is CS50”加密为“Cbah ah KH50” 预期“密文:Cb ...”,而不是“密文:Cb ...”

:( 使用 yukfrnlbavmwzteogxhcipjsqd 作为密钥将“This is CS50”加密为“Cbah ah KH50” 预期“密文:Cb ...”,而不是“密文:Cb ...”

:( 使用 YUKFRNLBAVMWZteogxhcipjsqd 作为密钥将“This is CS50”加密为“Cbah ah KH50” 预期“密文:Cb ...”,而不是“密文:Cb ...”

:( 使用 DWUSXNPQKEGCZFJBTLYROHIAVM 作为密钥加密所有字母字符 预期“密文:Rq...”,而不是“密文:Rr...”

:) 处理缺少密钥

:) 处理无效的密钥长度

:) 处理 key 中的无效字符

:) 处理 key 中的重复字符

:) 处理 key 中的多个重复字符)

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

// create the stirng variable alphabet for the key substitution
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

int main(int argc, string argv[])
{
    // get the key for the alphabet substitution as the second argument
    string key = argv[1];
    // if the user enters no key, instructions are given
    if (argc == 1)
    {
        printf("Usage: ./substitution key\n");
        return 1;
    }
    // loop to go through all the key chars and check them
    for (int i = 0; i < 26; i++)
    {
        // if at least one of the chars is not a letter, print an error and return 1
        if (!isalpha(key[i]))
        {
            printf("Key can contain only alphabetic characters.\n");
            return 1;
            break;
        }
        // adds another loop to confront a char with all the other 25 to see if there aare duplicates
        for (int j = i + 1; j < 26; j++)
        {
            // if there is a repeated char, print an error and return 1
            if (key[i] == key[j] || key[i] == ' ')
            {
                printf("Key doesn't allow repeating characters.\n");
                return 1;
                break;
            }
        }
    }
    // print an error and return 1 from main if the key is not 26 chats
    if (strlen(key) != 26)
    {
        printf("Key must contain 26 characters.\n");
        return 1;
    }
    else
    {
        // print 'plaintext: ', prompting the user for the string he wants to encrypt, using get_string
        string pltxt = get_string("plaintext: ");
        string cytxt = pltxt;
        // get the lenght of the plaintext variable
        int lentxt = strlen(pltxt);
        // loop that goes through all the chars of the plaintext
        for (int n = 0; n < lentxt; n++ )
        {
            // check if the char is a letter
            if (isalpha(pltxt[n]))
            {
                // loop that goes through all the alphabet letters to see which one the current letter is and to change it with the keys one
                for (int m = 0; m < 26; m++)
                {
                    if (toupper(pltxt[n]) == alphabet[m])
                    {
                        // conditions that keep the cases of the substituted chars
                        if (islower(pltxt[n]))
                        {
                            pltxt[n] = tolower(key[m]);
                        }
                        else if (isupper(pltxt[n]))
                        {
                            pltxt[n] = toupper(key[m]);
                        }
                    }
                }
            }
            // if char is not letter, let it as it is
            else
            {
                cytxt[n] = pltxt[n];
            }
        }
        // output 'cyphertext: ', followed by the encrypted string and a newline
        printf("cyphertext: %s\n", cytxt);
        // exit the program by returning 0 from main
        return 0;
    }
}

【问题讨论】:

    标签: c encryption cs50


    【解决方案1】:

    在循环中

                    for (int m = 0; m < 26; m++)
                    {
                        if (toupper(pltxt[n]) == alphabet[m])
                        {
                            // conditions that keep the cases of the substituted chars
                            if (islower(pltxt[n]))
                            {
                                pltxt[n] = tolower(key[m]);
                            }
                            else if (isupper(pltxt[n]))
                            {
                                pltxt[n] = toupper(key[m]);
                            }
                        }
                    }
    

    可能会发生多次替换。

    例如,在第一个例子中

    ./substitution YUKFRNLBAVMWZteogxhcipjsqd
    
    plaintext: This is CS50
    
    1. C 被替换为 K
    2. K 被替换为 M
    3. M 被替换为 Z
    4. Z 被替换为 D

    因此C 被替换为D

    为防止这种情况,您应该在第一次命中后中断循环,并让每个字符最多只发生一次替换。

                    for (int m = 0; m < 26; m++)
                    {
                        if (toupper(pltxt[n]) == alphabet[m])
                        {
                            // conditions that keep the cases of the substituted chars
                            if (islower(pltxt[n]))
                            {
                                pltxt[n] = tolower(key[m]);
                            }
                            else if (isupper(pltxt[n]))
                            {
                                pltxt[n] = toupper(key[m]);
                            }
                            break; // add this
                        }
                    }
    

    【讨论】:

    • 非常感谢,现在输出正确。我认为循环可能存在重复替换的问题,但无法弄清楚如何纠正它,尽管我需要的只是一个简单的“中断”啊哈。然而,现在的问题在于 check50 工具,所有测试看起来都很好(乍一看,输出是正确的),但它会将它们标记为好像它们失败了。我认为这可能是因为程序正在打印空字符,但我的循环条件似乎很好,因为变量都小于数字(即 n 小于长度,而不是
    • @dariocarretta 啊,您打印的是“cyphertext”而不是预期的“ciphertext”。
    猜你喜欢
    • 2020-08-09
    • 1970-01-01
    • 2022-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多