0

My substitution cipher is producing the correct output on my terminal when I run the same checks. I have reviewed other responses to similar issues but wasn't able to figure out how to find my error. Any help you can provide is much appreciated.

When I run Check50 it produces the following output:

Results for cs50/problems/2020/x/substitution generated by check50 v3.1.2 :) substitution.c exists :) substitution.c compiles :( encrypts "A" as "Z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key output not valid ASCII text :( encrypts "a" as "z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key output not valid ASCII text :( encrypts "ABC" as "NJQ" using NJQSUYBRXMOPFTHZVAWCGILKED as key output not valid ASCII text :( encrypts "XyZ" as "KeD" using NJQSUYBRXMOPFTHZVAWCGILKED as key output not valid ASCII text :) encrypts "This is CS50" as "Cbah ah KH50" using YUKFRNLBAVMWZTEOGXHCIPJSQD as key :) encrypts "This is CS50" as "Cbah ah KH50" using yukfrnlbavmwzteogxhcipjsqd as key :) encrypts "This is CS50" as "Cbah ah KH50" using YUKFRNLBAVMWZteogxhcipjsqd as key :) encrypts all alphabetic characters using DWUSXNPQKEGCZFJBTLYROHIAVM as key :) handles lack of key :) handles invalid key length :) handles invalid characters in key :) handles duplicate characters in key :) handles multiple duplicate characters in key

My code:

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

//Class Variables
// string of 26 alpha characters will be passed in the command to run the program as an argument sent to the main method parameter argv[]. Used to construct the cipher alphabet
string key;
// plaintext alphabet is a constant in all caps only. Only alpha characters are considered.
char ALPHABET[26] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
// ciphertext alphabet is initialized to the same values as ALPHABET to allocate memory. It is shifted the amount of positions indicated in the command line argument (key).
char cipher_alphabet[26] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};
// used to store the user input of the original message
string plaintext;
//used to store the changes to plaintext when it is shifted by the amount of characters indicated in the key.
string ciphertext;


//Class Methods
// sets the cipher alphabet using key
void setCipherAlphabet(void);
// encrypts plaintext by shifting it key positions
void encrypt(void);
// TODO not implemented yet
void decrypt(string ciphertext);
// prints all class variables to aid in debugging.
void print_vars(void);
// used by the encrypt method to find the corespoonding character in the cipher alphabet
char getCipherChar(char c);
// is used to determine if the command line argument passed running the program contains only alpha characters. returns true if str has all alpha characters; false otherwise.
bool is_all_alpha(string str);
// returns true if str contains a duplicate character; false otherwise.
bool hasDuplicate(string str);


int main(int argc, string argv[])
{
// validating command prompt argument and getting plaintext input.
//if a valid argument was passed in the command line prompt
    if (argc == 2 && is_all_alpha(argv[1]) && strlen(argv[1]) == 26 && !hasDuplicate(argv[1]))
    {
        key = argv[1];
// get user input for the plaintext message
        plaintext = get_string("plaintext: ");
        while (strlen(plaintext) < 1)
        {
            plaintext = get_string("plaintext: ");
        }
    }
//if no arguments or too many arguments were passed on command line
    else if (argc == 1 || argc > 2)
    {
        printf("Usage: ./substitution key\n");
        return 1;
    }
//handles duplicate characters in key
    else if (hasDuplicate(argv[1]))
    {
        printf("Key must contain 26 unique alpha characters. \n");
        return 1;
    }
// if another type of invalid key was passed through the command line exit program
    else
    {
        printf("Key must contain 26 characters.\n");
        return 1;
    }

// initialize the cipher alphabet
    setCipherAlphabet();

// initialize ciphertext to allocate memmory
    int size = strlen(plaintext);
// create a string of spaces to allocate memory for ciphertext
    char str[size];
    for (int i = 0; i < size; i++)
    {
        str[i] = plaintext[i];
    }
    ciphertext = str;

//encrypt the plaintext message.
    encrypt();

//print the encrypted message to the command prompt.
    printf("ciphertext: ");
    printf("%s", ciphertext);
    printf("\n");

//exit program
    return 0;
}// end main

bool is_all_alpha(string str)
{
    for (int i = 0; i < strlen(str); i++)
    {
        if (!isalpha(str[i]))
        {
            return false;
        }
    }
    return true;
}


//initializes the cipher alphabet given the key as an input.
void setCipherAlphabet(void)
{
    for (int i = 0; i < 26; i++)
    {
        cipher_alphabet[i] = toupper(key[i]);
    }
}

void print_vars(void)
{

    printf("Key: ");
    printf("%s", key);
    printf("\n");

    printf("Cipher Alphabet: ");
    printf("%s", cipher_alphabet);
    printf("\n");

    printf("plaintext: ");
    printf("%s", plaintext);
    printf("\n");

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

void encrypt(void)
{
    for (int i = 0; i < strlen(plaintext); i++)
    {
        for (int j = 0; j < 26; j++)
        {
            if (toupper(plaintext[i]) == toupper(ALPHABET[j]))
            {
                ciphertext[i] = cipher_alphabet[j];
            }
        }
        if (islower(plaintext[i]))
        {
            ciphertext[i] = tolower(ciphertext[i]);
        }
    }
}

// returns true if str contains a duplicate character; false otherwise.
bool hasDuplicate(string str)
{
    for (int i = 0; i < strlen(str); i++)
    {
        for (int j = i + 1; j < strlen(str); j++)
        {
            if (str[i] == str[j])
            {
                return true;
            }
        }
    }
    return false;
}

2 Answers 2

1

I was able to fix my problem by appending an '\0' char at the end of my ciphertext.

ciphertext[size] = '\0';
0

There is a null character at the end and you have to take it out, if u get output nt even valid it is saying that your loops where you are going back to A or a to Z or z isnt working and its printing something wrong If this helps pls hit the checkmark :)

You must log in to answer this question.

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