0

I've been working on the CS50 Substitution problem and I have submitted it. When I submit it, it checks off the standards about compiling and about errors in the key. However, all the other values it marks as wrong even when I check the values and they are correct. Here are the return values: https://submit.cs50.io/check50/01a5244164d636f9203ea76ef8d22275dda66c48

I can't seem to find what is wrong with my code or with the return values that my program outputs. Thank you in advance.

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

string alphabet = "abcdefghijklmnopqrstuvwxyz"; // creates list of alphabet to act like a dictionary and be able to find the index of the corresponding cipher value

void cipher(string text, string key, int text_length);
int valid(string key);

int main(int argc, string argv[])
{
    // IF argc is not equal to 26 it is invalid
    // printf("%lu\n",strlen(argv[1]));


    if (argc != 2) // if not 2 values in commandline argument
    {
        printf("Usage: ./substitution key\n");
        return 1;
    }

    else if (valid(argv[1]) == false) // if the key isn't valid, exit
    {
        return 1;
    }

    else // else ask user for text and cipher text
    {
        string text = get_string("plaintext: ");
        cipher(text, argv[1], strlen(text));
        return 0;
    }
    return 1;


}

int valid(string key)
{
    int len = strlen(key);
    char prev[len]; // list of values to see if there is a double in the key

    if (strlen(key) != 26) // check key length
    {
        printf("Key must contain 26 characters.\n");
        return false;
    }

    for (int i = 0; i < len; i++) // loops through the key
    {
        for (int j = 0; j < i; j++) // loops through the list of previous characters in key
        {
        if (isdigit(key[i])) // if the character in the key is a digit, it is already not valid
            {
                printf("Key must only consist of letters.\n");
                return false;
            }
            // printf("Empty: %c\n", empty[j]);
            // printf("Key: %c\n\n", key[i]);
            if (key[i] == prev[j]) // if the current value of the key and the current value of the list of previous values match, the key has a duplicate
            {
                printf("Key must have no repeated letters\n");
                return false;
            }
        }



        prev[i] = key[i]; // if there is no duplicate, add the current key char into the list of characters already in the key.
    }
    return true; // eles return true, because the key had no duplicates

}

// create a funcion that ciphers the text
void cipher(string text, string key, int text_length)
{
    for (int i = 0, n = strlen(key); i <= n; i++) // turns the key into all lowercase
    {
        key[i] = tolower(key[i]);
    }
    char ciphertext = ' ';

    printf("ciphertext: "); // required text
    // loops through the key
    for (int i =  0; i <= text_length; i++) // loops through the text
    {
        bool islower = false; // initiating a value to see if character in text is capital or not
        if islower(text[i]) // if the text is lower, then the bool should be set to true
            {
                islower = true;
            }
        if (isalpha(text[i]) == false) // if the key is not a value
        {
            printf("%c", text[i]); // keep the character the same, as it doesn't need to be encoded
        }
        for (int j = 0; j < strlen(key); j++) // loop through the alphabet list above
        {
            if (text[i] == ' ') // if text is a space, output should also be space
            {
                ciphertext = ' ';
            }
            if (tolower(text[i]) == alphabet[j]) // if the current character in the text is in the alphabet
            {

                if (islower) // if character is lower
                {
                    ciphertext = tolower(key[j]); // turn key into lower
                }
                else
                {
                    ciphertext = toupper(key[j]); // else turn it into uppercase because character in text is also uppercase
                }
            printf("%c", ciphertext); // print the uppercase or lowercase ciphered character
            }
        }
    }
    printf("\n"); // print new line

}

//loop through text
//within loop, loop through alphabet
//if alphabet = i letter in the text
//find index of the letter in text
//find the corresponding value of the alphabet for the key
//return/ printout key

1 Answer 1

1

Non-printing characters. If you want to "see" what check50 "sees" try running the first example this way:

./substitution ZYXWVUTSRQPONMLKJIHGFEDCBA | cat -v

This pipes (|) the result to cat -v. The -v switch directs cat to display non-printing characters.

There is a problem in this line for (int i = 0; i <= text_length; i++). Remember the thing that makes a string a string? The terminating null byte.

3
  • When I use the | cat -v I do see that there is a ^@ at the end of my outputted text. Regarding , the terminating null byte, I need a bit more clarification about what you mean. Thanks!
    – Preston So
    Feb 26, 2022 at 17:07
  • The loop goes until i is equal to text_length, therefore, the loop is processing (ciphering) the null byte. Notice the difference to the loop that processes the key in the valid function. Feb 26, 2022 at 17:37
  • I see. I accidentally put in a <= sign, which makes my program cipher the null byte as well. It works fine now. Thanks.
    – Preston So
    Feb 26, 2022 at 17:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .