Skip to main content
Bumped by Community user
edited tags
Link
UpAndAdam
  • 1.7k
  • 1
  • 3
  • 20
added 3660 characters in body
Source Link

My code:

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

// prototypes
int verifyKey(int argc, string key);
int encrypt(string key, string plaintext);
string toupperText(string text);

int main(int argc, string argv[])
{
    string key = argv[1];
    // verify used key
    int keyOK = verifyKey(argc, key);
    if (keyOK == 1)
    {
        return 1;
    }

    // prompt user for text to be encrypted
    string plaintext = get_string("plaintext: ");
    // print
    printf("ciphertext: ");
    // encrypt text
    int ciphertext = encrypt(key, plaintext);

    return 0;
}

int verifyKey(int argc, string key)
{
    const string WARNING_USAGE = "Usage: ./substitution key";

    // prompt user for exactly one cmd argument
    if (argc != 2)
    {
        printf("%s\n", WARNING_USAGE);
        return 1;
    }

    // cmd argument must be 26 characters long
    if (strlen(key) != 26)
    {
        printf("Key must contain 26 characters.\n");
        return 1;
    }

    // handle invalid characters in key
    for (int i = 0; i < strlen(key); i++)
    {
        if (!isalpha(key[i]))
        {
            printf("%s\n", "Key must contain only alphabetical characters.\n");
            return 1;
        }
    }

    // handle duplicate characters in key
    char testKey[strlen(key)];
    for (int i = 0; i < strlen(key); i++)
    {
        //
        for (int j = 0; j < strlen(testKey); j++)
        {
            if (key[i] == testKey[j])
            {
                printf("%s\n", WARNING_USAGE);
                return 1;
            }
        }
        testKey[i] = key[i];
    }

    return 0;
}

int encrypt(string key, string plaintext)
{
    // key to upper case for easier computing
    key = toupperText(key);
    // ASCII values from key
    int keyIndexes[strlen(key)];
    for (int i = 0; i < strlen(key); i++)
    {
        // get ASCII value for i-th key character
        int ascii = (int) key[i];
        keyIndexes[i] = ascii;
    }

    // array of ASCII values of encrypted text
    int encryptedtext[strlen(plaintext)];

    // loop through plaintext
    for (int i = 0; i < strlen(plaintext); i++)
    {
        char c = plaintext[i];
        // if character is alphabetical -> encrypt
        if (isalpha(c))
        {
            // get ASCII value of character
            int index = (int) c;
            // get position in alphabet
            index -= 65;
            int moveToUpper = 0;
            if (islower(c))
            {
                // get position in alphabet for lowercase characters
                moveToUpper = 32;
            }
            encryptedtext[i] = keyIndexes[index - moveToUpper] + moveToUpper;
        }
        else
        {
            encryptedtext[i] = c;
        }
        printf("%c", (char) encryptedtext[i]);
    }
    printf("\n");
    return 0;
}

string toupperText(string text)
{
    for (int i = 0; i < strlen(text); i++)
    {
        text[i] = toupper(text[i]);
    }
    return text;
}

My code:

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

// prototypes
int verifyKey(int argc, string key);
int encrypt(string key, string plaintext);
string toupperText(string text);

int main(int argc, string argv[])
{
    string key = argv[1];
    // verify used key
    int keyOK = verifyKey(argc, key);
    if (keyOK == 1)
    {
        return 1;
    }

    // prompt user for text to be encrypted
    string plaintext = get_string("plaintext: ");
    // print
    printf("ciphertext: ");
    // encrypt text
    int ciphertext = encrypt(key, plaintext);

    return 0;
}

int verifyKey(int argc, string key)
{
    const string WARNING_USAGE = "Usage: ./substitution key";

    // prompt user for exactly one cmd argument
    if (argc != 2)
    {
        printf("%s\n", WARNING_USAGE);
        return 1;
    }

    // cmd argument must be 26 characters long
    if (strlen(key) != 26)
    {
        printf("Key must contain 26 characters.\n");
        return 1;
    }

    // handle invalid characters in key
    for (int i = 0; i < strlen(key); i++)
    {
        if (!isalpha(key[i]))
        {
            printf("%s\n", "Key must contain only alphabetical characters.\n");
            return 1;
        }
    }

    // handle duplicate characters in key
    char testKey[strlen(key)];
    for (int i = 0; i < strlen(key); i++)
    {
        //
        for (int j = 0; j < strlen(testKey); j++)
        {
            if (key[i] == testKey[j])
            {
                printf("%s\n", WARNING_USAGE);
                return 1;
            }
        }
        testKey[i] = key[i];
    }

    return 0;
}

int encrypt(string key, string plaintext)
{
    // key to upper case for easier computing
    key = toupperText(key);
    // ASCII values from key
    int keyIndexes[strlen(key)];
    for (int i = 0; i < strlen(key); i++)
    {
        // get ASCII value for i-th key character
        int ascii = (int) key[i];
        keyIndexes[i] = ascii;
    }

    // array of ASCII values of encrypted text
    int encryptedtext[strlen(plaintext)];

    // loop through plaintext
    for (int i = 0; i < strlen(plaintext); i++)
    {
        char c = plaintext[i];
        // if character is alphabetical -> encrypt
        if (isalpha(c))
        {
            // get ASCII value of character
            int index = (int) c;
            // get position in alphabet
            index -= 65;
            int moveToUpper = 0;
            if (islower(c))
            {
                // get position in alphabet for lowercase characters
                moveToUpper = 32;
            }
            encryptedtext[i] = keyIndexes[index - moveToUpper] + moveToUpper;
        }
        else
        {
            encryptedtext[i] = c;
        }
        printf("%c", (char) encryptedtext[i]);
    }
    printf("\n");
    return 0;
}

string toupperText(string text)
{
    for (int i = 0; i < strlen(text); i++)
    {
        text[i] = toupper(text[i]);
    }
    return text;
}
Source Link

I am getting different test results for the same code

I am testing my substitution.c program, but I get every time different results for the same code.

On the very 1.st time I got all good but :( does not encrypt non-alphabetical characters using DWUSXNPQKEGCZFJBTLYROHIAVM as key expected "ciphertext: Yq...", not "". According assignment, non-alphabetical characters should stay unchanged.

So I tried another test with the same code and I got:

:) substitution.c exists
:) substitution.c compiles
:( encrypts "A" as "Z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key
    expected "ciphertext: Z\...", not ""
:) encrypts "a" as "z" using ZYXWVUTSRQPONMLKJIHGFEDCBA as key
:) encrypts "ABC" as "NJQ" using NJQSUYBRXMOPFTHZVAWCGILKED as key
:) encrypts "XyZ" as "KeD" using NJQSUYBRXMOPFTHZVAWCGILKED as key
:( 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
:) encrypts "This is CS50" as "Cbah ah KH50" using YUKFRNLBAVMWZteogxhcipjsqd as key
:) encrypts all alphabetic characters using DWUSXNPQKEGCZFJBTLYROHIAVM as key
:( does not encrypt non-alphabetical characters using DWUSXNPQKEGCZFJBTLYROHIAVM as key
    expected "ciphertext: Yq...", not ""
:) handles lack of key
:) handles too many arguments
:) handles invalid key length
:) handles invalid characters in key
:) handles duplicate characters in uppercase key
:) handles duplicate characters in lowercase key
:) handles multiple duplicate characters in key

Once I've got all checks good, another time completely different. And apart this problem, the A character should be encrypted as Z with ZYXWVUTSRQPONMLKJIHGFEDCBA key. So why is the result negative? Any idea what could get wrong? Thanks!