Home > front end >  CS50 Caesar Cipher Bug
CS50 Caesar Cipher Bug

Time:02-26

Okay, so I am completely stumped. I cannot understand why this programs output acts as if there is a random key everytime.

This program:

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

int main(int argc, string argv[])
{
    string sKey = argv[1];
// Make sure program was run with just one command-line argument
    if (argc != 2 || atoi(argv[1]) < 0)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

//Counts length of string and checks if all chars are digits
    int counter = 0;
    for (int i = 0; i < strlen(sKey); i  )
    {
        if isdigit(sKey[i])
        {
            counter  ;
        }
    }

//Checks if the key is a number
    if (counter != strlen(sKey))
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

// Convert argv[1] from a `string` to an `int`
    int key = (int)sKey;

// Prompt user for plaintext
    string plaintext = get_string("Plaintext:  ");
    printf("Ciphertext: ");
    for (int i = 0; i < strlen(plaintext); i  )
    {
        if (isalpha(plaintext[i]) && isupper(plaintext[i]))
        {
            printf("%c", (((plaintext[i] - 'A')   key) % 26)   'A');
        }
        else if (isalpha(plaintext[i]) && islower(plaintext[i]))
        {
            printf("%c", (((plaintext[i] - 'a')   key) % 26)   'a');
        }
        else
        {
            printf("%c", plaintext[i]);
        }
    }
    printf("\n");
}

Will output this:

caesar/ $ ./caesar 1
Plaintext:  Hello, I'm Justin.
Ciphertext: Fcjjm, G'k Hsqrgl.
caesar/ $ ./caesar 1
Plaintext:  Hello, I'm Justin.
Ciphertext: Pmttw, Q'u Rcabqv.

It seems to be due to the modulo operator, because when I isolated it I could recreate the issue. Is it one of my included libraries? I solved the problem on my own and ended up looking up a solution on youtube only to find my solution performed the same operations as the correct solution. I must be missing something.

Thank you

CodePudding user response:

This is because int key = (int)sKey; does NOT convert the string to an integer... at least not in the way you think it does. It takes the string pointer sKey (a memory address) to an integer. Since every time you run the progra this can be a different address, this is why it looks random. The correct way to convert a numerical string to a value is using atoi or strtol. The first part of your program should be something like this:

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

int main(int argc, string argv[])
{
    string sKey = argv[1];
    int i;

    // Make sure program was run with just one command-line argument
    if (argc != 2)
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

    // Checks if all chars are digits
    for (int i = 0; sKey[i]; i  )
        if (!isdigit(sKey[i]) break;

    // If the key contains any non-digits, error
    if (sKey[i])
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }

    // Convert argv[1] from a `string` to an `int`
    int key = atoi(sKey);

// The rest should be fine
  • Related