替换 cs50 在 check50 中输出一些错误,但代码在我的终端上运行良好

Substitution cs50 output some error in check50 but code works fine on my terminal

提问人:Kevinkun 提问时间:12/8/2022 更新时间:12/8/2022 访问量:136

问:

因此,任务是将用户提示文本中的每个字符更改为给定的键。我从另一个人那里读到过同样的问题,但没有解决方案。

以下是任务的链接:https://cs50.harvard.edu/x/2022/psets/2/substitution/

问题是,当我在自己的终端上运行代码时,它会根据需要输出正确的结果。但是当我运行 check50 时,它失败了。

这是他们向我展示的失败任务(当我自己尝试时,它也会输出正确的结果):

:( encrypts "A" as "Z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key
    expected "ciphertext: Z\...", not ""
:( encrypts "a" as "z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key
    expected "ciphertext: z\...", not ""
:( encrypts "ABC" as "NJQ" using NJQSUYBRXMOPFTHZVAWCGILKED as key
    expected "ciphertext: NJ...", not ""
:( encrypts "XyZ" as "KeD" using NJQSUYBRXMOPFTHZVAWCGILKED as key
    expected "ciphertext: Ke...", not ""
:( encrypts "This is CS50" as "Cbah ah KH50" using YUKFRNLBAVMWZTEOGXHCIPJSQD as key
    expected "ciphertext: Cb...", not ""
:( encrypts "This is CS50" as "Cbah ah KH50" using yukfrnlbavmwzteogxhcipjsqd as key
    expected "ciphertext: Cb...", not ""
:( encrypts "This is CS50" as "Cbah ah KH50" using YUKFRNLBAVMWZteogxhcipjsqd as key
    expected "ciphertext: Cb...", not ""
:( encrypts all alphabetic characters using DWUSXNPQKEGCZFJBTLYROHIAVM as key
    expected "ciphertext: Rq...", not ""
:( does not encrypt non-alphabetical characters using DWUSXNPQKEGCZFJBTLYROHIAVM as key
    expected "ciphertext: Yq...", not ""

这是我的代码:

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

bool validate_command_line(int argc, string key);
string encrypt(string key, string txt);

int main(int argc, string argv[]) 
{
    // Validate command-line arguments
    if (!validate_command_line(argc, argv[1]))
    {
        return 1;
    }
    
    // Prompt user for a plaintext
    string plaintext = get_string("plaintext: ");
    
    // Encrypt plaintext to ciphertext using a key
    string ciphertext = encrypt(argv[1], plaintext);

    // Display ciphertext
    printf("ciphertext: %s\n", ciphertext);

    return 0;
}

// To encrypt plaintext to ciphertext by key
string encrypt(string key, string txt)
{
    // Get length of a user plaintext
    int l = strlen(txt);

    // This will store at which index key should access
    int index_letter = 0;

    // To store encrypted text
    char encrypted_text[l + 1];
    
    // Iterate throught plaintext by it's length
    for (int i = 0; i < l; i++)
    {
        // Make sure to only encrypt alphabet characters
        if (isalpha(txt[i]))
        {
            /*
                Handling lowercase character
                We substract current character to ASCII Code of a, which 97
                to get at index position value of the character
                Ex: a is 97-97 = 0 | b is 98-97 = 1
                Then use it to access at which key to access
            */
            if (islower(txt[i]))
            {
                index_letter = txt[i] - 97;
                encrypted_text[i] = tolower(key[index_letter]);
            }
            /* Handling uppercase character */
            else
            {
                index_letter = txt[i] - 65;
                encrypted_text[i] = toupper(key[index_letter]);
            }
        }
        // If it's other symbol, just copying it
        else
        {
            encrypted_text[i] = txt[i];
        }
    }

    // Store NUL character at the end of char array
    encrypted_text[l] = '\0';

    // Store it to string, because we can't return char array
    string ciphertext = encrypted_text;

    return ciphertext;
}

// To validate command-line arguments 
bool validate_command_line(int argc, string key)
{
    // Validate total of command-line arguments
    if (argc != 2)
    {
        printf("Usage: ./substitution key\n");
        return false;
    }

    // Validate key contain 26 alphabet
    int key_length = strlen(key);
    if (key_length != 26)
    {
        printf("Key must contain 26 characters.\n");
        return false;
    }

    // Validate key should only alphabet AND not contain repeated characters
    int repeated_charaters[key_length];
    int index_character = 0;

    for (int i = 0; i < key_length; i++)
    {
        if (!isalpha(key[i]))
        {
            printf("Key must only contain alphabetic characters.\n");
            return false;
        }

        index_character = tolower(key[i]) - 97;
        if (repeated_charaters[index_character] == 1)
        {
            printf("Key must not contain repeated characters.\n");
            return false;
        }
        
        repeated_charaters[index_character]++;
    }

    return true;
}

正如你在string encrypt(string key, string txt)

我创建了一个将返回字符串的函数,因为我想在我的 .也许你会告诉我,我无法返回字符串或字符数组main()

但是我将函数更改为,以便它将在函数内打印结果而不会返回。而且它也未通过 check50。void()

喜欢这个:

void encrypt(string key, string txt)
{
    // Get length of a user plaintext
    int l = strlen(txt);

    // This will store at which index key should access
    int index_letter = 0;

    // To store encrypted text
    char encrypted_text[l + 1];
    
    // Iterate throught plaintext by it's length
    for (int i = 0; i < l; i++)
    {
        // Make sure to only encrypt alphabet characters
        if (isalpha(txt[i]))
        {
            /*
                Handling lowercase character
                We substract current character to ASCII Code of a, which 97
                to get at index position value of the character
                Ex: a is 97-97 = 0 | b is 98-97 = 1
                Then use it to access at which key to access
            */
            if (islower(txt[i]))
            {
                index_letter = txt[i] - 97;
                encrypted_text[i] = tolower(key[index_letter]);
            }
            /* Handling uppercase character */
            else
            {
                index_letter = txt[i] - 65;
                encrypted_text[i] = toupper(key[index_letter]);
            }
        }
        // If it's other symbol, just copying it
        else
        {
            encrypted_text[i] = txt[i];
        }
    }

    // Store NUL character at the end of char array
    encrypted_text[l] = '\0';

    printf("%s", encrypted_text);
}

我对编程很陌生。我希望你们能给我解决方案。谢谢。

C CS50

评论

0赞 Eugene Sh. 12/8/2022
您是这个愚蠢的 CS50 决定将别名与 . 是一个局部数组,您将在函数外部返回指向它的指针,在那里它不再存在。char*stringencrypted_text
0赞 Kevinkun 12/8/2022
@EugeneSh。但是,当我在自己的终端上运行它时,为什么它会给出正确的结果呢?
0赞 Kevinkun 12/8/2022
@EugeneSh。你也可以看看我上面写的内容。在函数中,我选择立即打印结果而不将其返回给 。但它仍然没有通过测试。所以我不明白问题出在哪里。void encrypt(string key, string txt)main()
0赞 Fe2O3 12/8/2022
在第 2 个版本(在函数内打印)中,您是否在调用函数之前打印了字符串“密文:”?
0赞 David C. Rankin 12/8/2022
可能相关的问题 CS50x - PSET2- 替换或 CS50 替换,它们可能对您来说很重要。另外,如果你的意思是 ,请使用 ,而不是 。如果你的意思是 ,使用 ,而不是 -- 不要在代码中使用 MagicNumbers'a''a'97'A''A'65

答:

1赞 pm100 12/8/2022 #1

我的理解是 IS 只是在 CS50 中。这使得这段代码stringchar *

string ciphertext = encrypted_text;

return ciphertext;

无效,因为 encrypted_text 是一个本地数组,将在函数结束时被销毁。不能返回指向本地数组的指针

评论

0赞 Kevinkun 12/8/2022
但是,如果选择在函数中打印结果,我也会失败。看看我上面写的:void()void encrypt(string key, string txt)
0赞 Kevinkun 12/8/2022
在那个函数中,我没有返回任何字符串
0赞 pm100 12/8/2022
那个 printf 是错误的格式 - 它应该说“密文:....”
0赞 DinoCoderSaurus 12/8/2022 #2

问题是数组未初始化。本地系统与 check50 系统的区别在于“统一化”内存中的内容。在声明后将所有array_elements设置为 0 以解决问题(在“这是我的代码”之后粘贴的代码中)repeated_charaters