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

Time:12-08

So, the task is to change each character in user prompt text to given key. I've reading the same problem from another people, but there's no solution.

Here's the link to the task: https://cs50.harvard.edu/x/2022/psets/2/substitution/

The problem is, when I run my code on my own terminal, it's output the right results as they want. But when I run check50 it's failed.

This is the failed task they show me (which also output the right result when I try it myself):

:( 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 ""

And this is my code:

#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;
}

As you can see in string encrypt(string key, string txt)

I create a function that will return string, since I want to print the text in my main(). Maybe you would tell me that I can't return string or array of characters.

But I change the function to void() so it will print the result within function without being return. And it failed the check50 also.

Like this:

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);
}

I'm very new on programming. I hope you guys can give me solution for this. Thank You.

CodePudding user response:

my understanding is the string is simply char * in cs50. That makes this code

string ciphertext = encrypted_text;

return ciphertext;

invalid as encrypted_text is a local array that will be destroyed at the end of the function. You cannot return a pointer to a local array

CodePudding user response:

The problem is the array repeated_charaters is not initialized. The difference in the local system vs. the check50 system is what is in that "unitialized" memory. Set all array_elements to 0 after the declaration to solve the problem (in the code pasted after "This is my code")

  • Related