0

I can't see what my code for pset2 substitution is missing. When I use check50 to test the program it returns this result:

:) substitution.c exists

:) substitution.c compiles

:( encrypts "A" as "Z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key expected "ciphertext: Z...", not "ciphertext: Z..."

:( encrypts "a" as "z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key expected "ciphertext: z...", not "ciphertext: z..."

:( encrypts "ABC" as "NJQ" using NJQSUYBRXMOPFTHZVAWCGILKED as key expected "ciphertext: NJ...", not "ciphertext: NJ..."

:( encrypts "XyZ" as "KeD" using NJQSUYBRXMOPFTHZVAWCGILKED as key expected "ciphertext: Ke...", not "ciphertext: Ke..."

:( encrypts "This is CS50" as "Cbah ah KH50" using YUKFRNLBAVMWZTEOGXHCIPJSQD as key expected "ciphertext: Cb...", not "ciphertext: Cb..."

:( encrypts "This is CS50" as "Cbah ah KH50" using yukfrnlbavmwzteogxhcipjsqd as key expected "ciphertext: Cb...", not "ciphertext: Cb..."

:( encrypts "This is CS50" as "Cbah ah KH50" using YUKFRNLBAVMWZteogxhcipjsqd as key expected "ciphertext: Cb...", not "ciphertext: Cb..."

:( encrypts all alphabetic characters using DWUSXNPQKEGCZFJBTLYROHIAVM as key expected "ciphertext: Rq...", not "ciphertext: Rq..."

:) handles lack of key

:) handles invalid key length

:) handles invalid characters in key

:) handles duplicate characters in key

:) handles multiple duplicate characters in key

However, when I manually type in a key and plaintext it works exactly as it is supposed to. Furthermore, the 'expected' result of check50 seems to be exactly the same as the output so it is not obvious what is wrong.

my code is as follows:

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

int get_validkey(string A);

int main(int argc, string argv[])
{
    if (argc != 2)
    {
        printf("useage: ./substitution key\n");

        return 1;
    }


        int validation = get_validkey(argv[1]);
        if (validation == 1)
        {
            printf("key must contain 26 alphabetical characters\n");

            return 1;
        }

            // prompting user for plaintext
            string plaintext = get_string("plaintext: ");
            printf("ciphertext: ");

            int length = strlen(plaintext);

            for (int c = 0; c <= length ; c++)
            {
                // printing any non-alphabet characters unchanged
                if (plaintext[c] < 'A' || (plaintext[c] > 'Z' && plaintext[c] < 'a') || plaintext[c] > 'z')
                {
                    printf("%c", plaintext[c]);
                }
                else
                {
                    for (int b = 0; b <= 25; b++)
                    {
                        if (plaintext[c] == 65 + b)
                        {
                            char upper = argv[1][b];
                            int up = isupper(upper);
                            if (up == 0)
                            {
                                upper = toupper(upper);
                                printf("%c", upper);
                            }
                            if (up != 0)
                            {
                                printf("%c", upper);
                            }

                        }
                        else if (plaintext[c] == 97 + b)
                        {
                            char lower = argv[1][b];
                            int low = islower(lower);
                            if (low == 0)
                            {
                                lower = tolower(lower);
                                printf("%c", lower);
                            }
                            if (low != 0)
                            {
                                printf("%c", lower);
                            }

                        }

                    }

                }

            }
            printf("\n");
            return 0;

}

// function assesses if the key input is valid and returns 0 if it is and 1 if it is not
int get_validkey(string A)
{
    int inputlength = strlen(A);
    if (inputlength != 26)
    {
        return 1;
    }
    else
    {

        for (int g = 0; g < 26; g++)
        {
            // checks if the character is non alphabetical
            if (A[g] < 'A' || (A[g] > 'Z' && A[g] < 'a') || A[g] > 'z')
            {
                return 1;
            }
            // scans all characters before A[g] to see if it has already been used
            for (int k = (g - 1); k >= 0; k--)
            {
                if (A[k] == A[g])
                {
                    return 1;
                }
                // also checks if different case of the same character has been used
                if (A[k] == A[g] + 32)
                {
                    return 1;
                }
                if (A[k] == A[g] - 32)
                {
                    return 1;
                }
            }
            // scans all characters after A[g] to check if it has been used already. (Not sure if this is necessary)
            for (int l = (g + 1); l < 26; l++)
            {
                if (A[l] == A[g])
                {
                    return 1;
                }
                // also checks if a different case of the same letter is used
                if (A[l] == A[g]  + 32)
                {
                    return 1;
                }
                if (A[l] == A[g] - 32)
                {
                    return 1;
                }
            }

        }
        return 0;
    }

}

I am very new to programming and any help would be greatly appreciated.

lm201
  • 1
  • 1
  • 1
  • 3
    It's enciphering the terminating null byte of plaintext, which is an unprintable character, so you can't see it. but check50 does! Check this line `for (int c = 0; c <= length ; c++)` – DinoCoderSaurus Apr 25 '20 at 21:42
  • Thanks @DinoCoderSaurus , I used `c < length` and it all works now! – lm201 Apr 25 '20 at 22:09

1 Answers1

2

I've encountered the same problem, but then I realized that when I was iterating the for loop for my plain text which is, for (int c = 0; c <= length ; c++), that the programming language itself internally starts with 0 when counting. Even though we knew it should be equal to the length of the plain text, the language will iterate to that null element within the array of string. I suggest you do this, for (int c = 0; c <= length ; c++). Hope, it helps.