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")