2

My Caesar code seems to be working correctly in this form:

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

// validates that the key is only numbers
int validate_key(string);

int main(int argc, string argv[])
{
    // checking if the command line provides exactly one argument
    if(argc != 2 || validate_key(argv[1]) == 1)
    {
        printf("Usage: ./caesar key\n");
        return 1; 
    }

    // reading the key, casting it to an integer
    int key = atoi(argv[1]);

    const string ptxt = get_string("plaintext: ");

    // I use the length of plaintext twice, so I decrare it
    int len = strlen(ptxt);

    // IF I REMOVE THIS PRINTF STATEMENT THE CODE DOESN'T RUN PROPERLY
    printf("length is: %i\n", len); 

    // array for the cipher text, same length as the input text
    char ctxt[len];

    for(int i = 0; i < len; i++)
    {
        char c = ptxt[i]; 

        if (c >= 65 && c <= 90)
        {
            ctxt[i] = 65 + (c - 65 + key) % 26; 
        }
        else if (c >= 97 && c <= 122)
        {
            ctxt[i] = 97 + (c - 97 + key) % 26; 
        }
        else
        {
            ctxt[i] = c;
        }
    }

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

int validate_key(string key)
{
    int len_key = strlen(key);

    for(int i = 0; i < len_key; i++)
    {
        char c = key[i];
        if(c < 48 || c > 57)
        {
            return 1;
        }
    }
    return 0;
}

Notice the seemingly unnecessary printf("length is: %i\n", len); statement. It just prints the length of the plaintext string. It should be redundant. However, the program changes it behaviour if I remove it. For example, for key = 13, the sting 'hello' maps to 'uryy ', which is incorrect. With this printf statement on, the code seems to be working perfectly.

Any ideas why this is happening? Thanks!

3
  • Are you sure? Works fine for me. Did you recompile without the printf statement? – Cliff B Mar 1 '19 at 20:28
  • Yes Cliff, several times! Just try to recompile with the printf statement commented out and give key=13 and plaintext="hello" – Vasilis D Mar 1 '19 at 20:42
  • 1
    This is a lesson for everyone. If you can't duplicate the problem, how can you find the solution? See the answer below and the comments that follow. I'm upvoting this questions because it's an excellent lesson in how a bug can SOMETIMES produce an error and other times not. These are the most irritating bugs there are because they produce bad results intermittently and can be difficult to replicate. – Cliff B Mar 1 '19 at 22:05
4

It's a memory thing, as in you will get different results based on what is in memory.ctxt is declared as an array of chars. Here printf("ciphertext: %s\n", ctxt); is treating it like a string (viz the print format of %s). But what is the thing that makes a string a string? It is the terminating null byte. Don't forget the add one to ctxt before you try to print it as a string. And make sure it is allocated to accommodate said byte.

5
  • missed that. I must be slipping. :-/ – Cliff B Mar 1 '19 at 21:02
  • I started to doubt myself; I was surprised you missed that. – DinoCoderSaurus Mar 1 '19 at 21:07
  • Thanks a lot, that was very instructive :) I fixed it by declaring char ctxt[len+1] and then adding a zero at the end: ctxt[len]=0 – Vasilis D Mar 1 '19 at 21:22
  • @DinoCoderSaurus Guess I'm just a bit lazy today. A little voice in my ear was screaming something about a memory storage issue related to a string, but I didn't want to listen this time. :-( So, I got lazy and just ran a few tests without really looking into the code and without duplicating the result. Let that be a lesson to everyone!!!! ;-) – Cliff B Mar 1 '19 at 22:01
  • 1
    staggers our myth! ( just kidding) – MARS Mar 1 '19 at 22:17

You must log in to answer this question.

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