0

everyone,

I have been having trouble making vigenere encipher BaRFoo correctly when the key is BaZ. I kept getting the following error: "\ expected output, but not "CaQGoh\n"," which suggests to me that the wrapping of the key is working, as is the enciphering when the text and key cases match. What seems to not be working, then, is enciphering when the text and key cases do not match. (all other tests were green smiley faces)

My first attempt was converting the key's jth character (accounting for wrapping) to the case of the corresponding text's ith character separating the text characters in two "if" groups:

// begins original code

if (isupper(text[i]) { toupper(argv[1][j]); printf("%c", ((((int) text[i] - 'A') + ((int) argv[1][j] - 'A')) % 26) + 'A'); }

if (islower(text[i]) { tolower(argv[1][j]); printf("%c", ((((int) text[i] - 'a') + ((int) argv[1][j] - 'a')) % 26) + 'a'); }

// ends original code

It seems to me that if (isupper...) {toupper...} and if (islower...) {tolower...} are not doing the trick as I expected.

Eventually I made vigenere work by removing the case convertion for the key's jth characters described above and creating four different "if" cases, two when the text and key cases match as upper- and lowercase, and two for the two possible mismatches (key is upper but text is lower, vice versa). (See code below; key validation code omitted)

This results in: 1) an overly long code, in my opinion; 2) no use of toupper and tolower, as suggested in another post; and 3) a lot of confusion on my part. It seems to me like the assumptions I was making initially (that the case of the key's jth character will be transformed if needed) do not hold, and I have no idea why.

Any pointers or suggestions will be greatly appreciated!!

//begins working code

include

include

include

include

include

int main(int argc, string argv[]) {

// //////\ // code for returning 1 if key is invalid goes here // //////\

    // begins code to encipher text provided by user
    // declare counter variables to move through key, return 1 if not alpha
    int j = 0, n = strlen(argv[1]);

    // get text to encrypt from user
    string text = GetString();

    //declare counter variables to move through text array
    int i, x;

    // encipher each text character using a corresponding key letter, until end of text is reached 
    for (i = 0, j = 0, x = strlen(text); i < x; i++, j = (j + 1) % n)
    {

        // encipher character only if it is alphabetic
        if (isalpha(text[i]))
        {    

            // if both character and key are uppercase 
            if (isupper(text[i]) && isupper(argv[1][j]))
            {

                // calculate ASCII value of uppercase letter: ((p+k-130)%26)+65
                printf("%c", ((((int) text[i] - 'A') + ((int) argv[1][j] - 'A')) % 26) + 'A');
            }

            ///if character is upper but key is lowercase
            else if (isupper(text[i]) && islower(argv[1][j]))
            {

                //change case of corresponding key letter
                //toupper(argv[1][j]);

                // calculate ASCII value of uppercase letter: ((p+k-130)%26)+65
                printf("%c", ((((int) text[i] - 'A') + ((int) argv[1][j] - 'a')) % 26) + 'A');
            }

            // if both character and key are lowercase
            else if (islower(text[i]) && islower(argv[1][j]))
            {

                // calculate ASCII value of lowercase letter: ((p+k-194)%26)+97
                printf("%c", ((((int) text[i] - 'a') + ((int) argv[1][j] - 'a')) % 26) + 'a');
            }

            // if character is lowercase but key is uppercase
            else if (islower(text[i]) && isupper(argv[1][j]))
            {

                //change case of corresponding key letter
                //tolower(argv[1][j]);

            // calculate ASCII value of lowercase letter: ((p+k-194)%26)+97
                printf("%c", ((((int) text[i] - 'a') + ((int) argv[1][j] - 'A')) % 26) + 'a');
            }
        }

        // and print as is if character is not alphabetic
        else
        {
            printf("%c", text[i]);
            j--;
        }
    }

}

// carriage return at end of program
printf("\n");
return 0;

}

1

Once I fixed a few compile errors, the code works fine except for not handling validating various input errors. As for being excessively long, not really. There are 4 possible cases, which you handle.

Can it be shortened? yes. There are two improvements that I see. First, the isupper() and islower() tests imply isalpha(), so you could reduce the number of tests. Second, two of the cases can be eliminated. You know that the key is alpha (or at least you would if you had done the required validation of the key - a check50 test that your code fails). So, instead of testing for isupper() or islower() on the key, just do tolower(key[...])-'a' in both the upper and lower plaintext cases.

Also you could benefit from running your code through style50 and refining your code style using its suggestions. The biggest thing I see in your code is too many blank lines, especially following a left curly brace. Next in line is making sure your tab indents are right. As for the code that was pasted in above, there was an unpaired curly brace. It might have been a cut and paste error, but you get the idea.

If this answers your question, please click on the check mark to accept. Let's keep up on forum maintenance. ;-)

| improve this answer | |
  • Thanks, Cliff; this is very helpful. I modified the code with your suggestions, thus reducing the lines of code. I thought tolower()/toupper() changed the case permanently, but it looks like it only does so in that specific line of code, right? Also, thanks for pointing out the compiling/check50 errors. They were part errors in how the code was pasted, part me leaving out a section to ease you guys's reading. Apologies; I realize now that it complicates using check50 for you! Thanks again for your help! – dmorali Apr 11 '16 at 16:05
  • toupper()/tolower() don't make permanent changes directly. The change only becomes permanent if it is assigned back to the parameter. For example, in your_letter = toupper(my_letter);, if myletter contains a lowercase letter, it would convert it to uppercase and put the uppercase letter in your_letter. If it were anything else, it would just copy it, but either way, my_letter would remain unchanged. However, if it were my_letter = toupper(my_letter);, it would assign the result back to my_letter, making it permanent. – Cliff B Apr 11 '16 at 17:26

You must log in to answer this question.

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