0

I am finishing the Caesar program in Problem Set 2 and, most of the time, my code works as intended - enciphering the user's input by incrementing each character by the integer entered at the command line (argv[1]). What I cant seem to explain or figure out is the fact that, though entering "z" or "zaz" will return "a" or "aba", respectively, entering "Z" or "ZAZ" will return "A[" or "A[BA[", respectively, when the command line integer is "1".

This output occurs despite the fact that the code for converting "z" to "a" is exactly the same as the code for converting "Z" to "A". Any help would be greatly appreciated. The code for the program is as follows:

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

int main(int argc, string argv[])
{
    //check to ensure argv[1] is an integer
    int m = strlen(argv[1]);
    char input[m];
    strcpy(input, argv[1]);
    int check = 0;

    for(int j = 0; j < m; j++)
    {
        if(isdigit(input[j]) == 0)
        {
            check++;
        }
    }
    // if only two command line arguments entered, and arg[v] is a non-    
    //   negative integer, proceed
    if((argc == 2) && (atoi(argv[1]) >= 0) && (check == 0))
    {
        // initialize key used to increment/encipher user's input
        int key = (atoi(argv[1]) % 26);

        // prompt user for plaintext to be enciphered
        printf("Plaintext: ");
        string ptext = get_string();

        int n = strlen(ptext);
        printf("Ciphertext: ");

        // iterate over plaintext input
        for(int i = 0; i < n; i++)
        {
            if(isalpha(ptext[i]))
        {
                // circle back to beginning of capital alphabet if increment 
                // passes "Z"
                if(117 > (ptext[i] + key) && (ptext[i] + key) > 90)
                {
                    printf("%c", (ptext[i] + key - 26));
                }

                // circle back to beginning of lowercase alphabet if increment 
                // passes "z"
                if(149 > (ptext[i] + key) && (ptext[i] + key) > 122)
                {
                    printf("%c", (ptext[i] + key - 26));
                }

                else 
                {
                    printf("%c", (ptext[i] + key));
                }
            }

            // print non-letters as entered by user
            else
            {
                printf("%c", ptext[i]);
            }
        }
        printf("\n");
        return 0;
    }
    else 
    {
        printf("Error, input must be single command line argument (non-negative integer).\n");
        return 1;
    }
}

As said earlier, entering "1" at the command line (or 53, 79, etc.) will change "z" to "a", as intended. I'm wondering why, in the same situation and moreover, using the same code, entering "1" at the command line changes "Z" to "A[".

I'd be grateful if anyone could explain. Thank you!

Edit: For what it's worth, the issue seems to be about passing "Z" in the capital alphabet. When the command line integer is "3", "X" changes to "A[", when the integer is "2", "Y" changes to "A[", and so on. Interestingly (?), when the integer is "2", "Z" changes to "B\", and when the integer is "3", "Z" changes to "C]". So, for some reason, it appears to be printing the ASCHII value (e.g. Z + 1 = [) after circling back to the beginning of the alphabet and printing the intended letter. Despite the code being the same, none of these issues occur with the lowercase letters - i.e. integer of "1" changes "z" to "a", and not "a{".

Edit 2: I got the job accomplished by changing the code dealing with "passing Z/z" entirely. If anyone has any theories on why this occurred to begin with, though, I'd love to hear them and better understand what the issue was.

1

The double characters come from two printfs being executed for one character (you have an if and an if-else, the first might print sometimes, the other would always print).

The way you're dealing with the wrap-around is less-than-ideal. For example, if plain[i] were 'Z' and key were 7, 'Z'+7 would be 'a', but so would be 'a'+0. Instead, you should differentiate between different cases of input characters. Usage of the % operator can help:

if (isupper(plain[i])) {
    printf("%c", (plain[i] - 'A' + key) % 26 + 'A');
} else if (islower(plain[i])) {
    ...
} else {
    printf("%c", plain[i]);
}
| improve this answer | |

You must log in to answer this question.

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