0

I've been stuck for so many hours on this, and need some advice :(

When I loop through the plaintext input, if the character contains a 'z' character then it outputs a '{' character. I've tried printing out the integer values, and it shows that 25 is being shifted but it seems that the loop is actually shifting by 27 characters. These are my error messages:

:( encrypts "barfoo" as "caqgon" using "baz" as keyword expected "ciphertext: ca...", not "ciphertext: ca..."

$ ./vigenere baz

plaintext: barfoo

ciphertext: casgop

It seems to go wrong only on the 3rd character each time.

Thanks in advance for any insight :)

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

int shift(char c);

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

    // end the program if more than 1 argument is provided
    if (argc != 2)
    {
        printf("Usage: You must enter a single keyword\n");
        return 1;
    }

    // iterate over each character in the keyword
    for (int i = 0;  i < strlen(argv[1]); i++)
    {
        //return and exit the program if it contains any digits
        if (isdigit(argv[1][i]))
        {
            printf("Usage: The keyword must consist of only alphabetical characters\n");
            return 1;
        }
    }

    // prompt user for a string to be ciphered
    string plain = get_string("plaintext: ");

    printf("ciphertext: ");

    // define the length of the keyword so we know when to reset it to 0
    int keyword_length = strlen(argv[1]);

    // store length of the plaintext string in a variable for iteration
    int plen = strlen(plain);

    // iterate over the plaintext, and the keyword
    for (int j = 0, k = 0; j < plen; j++)
    {
        if (isalpha(plain[j]) && (plain[j] != '\0' && plain[j] != '\n'))
        {
            // once iterated through to the end of the keyword, wrap the loop back to the beginning of the keyword
            if ((k == keyword_length) && (keyword_length != '\0'))
            {
                k = 0;
            }

            // convert the kth character of keyword into an integer one character per loop iteration
            int keyword = shift(argv[1][k]);

            // apply modulo of keyword length to the index of the key, increment the keyword counter only if an alphabetic 
            // character is found
            if (isupper(plain[j]))
            {
                printf("%c", (plain[j] + (keyword % keyword_length)));
                k++;
            }
            else if (islower(plain[j]))
            {
                printf("%c", (plain[j] + (keyword % keyword_length)));
                k++;
            }
        }
        else
        {
            // print out any non alphabetic characters as they are
            printf("%c", plain[j]);
        }  
    }
    printf("\n");

    return 0;
}

int shift(char c)
{
    // define an int variable
    int i;

    // convert char c to ascii if uppercase
    if (isupper(c))
    {
        i = ((c - 65) % 26);
    }

    // convert char c to ascii if lowercase
    if (islower(c))
    {
        i = ((c - 97) % 26);
    }
    return i;
}

1 Answer 1

0

It will go wrong any time the alphabetic index (keyword) is greater than keyword_length.

Using baz: keyword_length is 3,the b index is 1 and the a index is 0, so this (keyword % keyword_length) evaluates to 1 and 0 respectively. What happens with the z? z is index 25, so (keyword % keyword_length) evaluates to 1 (the remainder of 25 divided by 3).

As you see in the sample output, that's what it has done on the 3rd and 6th char: shifted by 1.

Now let's look at this printf("%c", (plain[j] + (keyword % keyword_length)));.

First question, if program is using the same equation for upper case letters and lower case letters, then why are there if clauses?

Maybe writing out some pseudo code would help; hover to see mine

- convert plaintext letter from ascii to alpha index (0-25). Case matters. Subtraction is the commonly used operation
- shift it by keyword (which is already in alpha index)
- make sure the result is in the range 0-25 (that's where % 26 will come in handy)
- convert that result back to ascii. Addition is the commonly used operation.

The % 26 is redundant in the shift function. Since all letters will evaluate to numbers between 0 and 25, number % 26 will always evaluate to number.

You must log in to answer this question.

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