0

I have a solution for Vigenère’s cipher that passes all of the check50 tests, however I don't think my solution for how to wrap around the keyword is what the problem is looking for. Below is my code. The TLDR of my code is that I maintain two iterators. One for iterating through the plaintext string and one for keeping the position of the letter in the keyword and inside my loop whenever the iterator for keyword is equal to the length of keyword I reset it to 0 to "wrap around". It seems from the video that there is a modulo solution for wrapping around the keyword, but I am just not able to follow that and am confused by it. If you could help me understand how to apply the modulo operator to the keyword such that I don't need the if (k == key_length) reset logic that would be great!

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

int main(int argc, string argv[])
{
    //we must have 2 arguments, 1 for the program name and 1 for a keyword composed entirely of alphabetical characters
    if (argc != 2)
    {
        printf("You must specify one and only one command line argument.\n");
        return 1;
    }

    //get the key the user typed in at the command line
    string key = argv[1];
    int key_length = strlen(key);

    //only allow alpha letters in the key
    for (int i = 0, n = key_length; i < n; i++)
    {
        if (!isalpha(key[i]))
        {
            printf("Your keyword must be composed entirely of alphabetical characters..\n");
            return 1;
        }
    }

    //get the plaintext from the user
    string s = get_string("plaintext: ");

    printf("ciphertext: ");

    //iterate for the length of the users plain text
    for (int i = 0, k = 0, n = strlen(s); i < n; i++)
    {
        //we don't want to convert non letters like punctuation
        if (isalpha(s[i]))
        {
            //reset the key counter back to 0 once its equal to the key_length
            if (k == key_length)
            {
                k = 0;
            }

            /*
                Get the alpha index for the key (e.g. A=0, B=1... Z=25). Since lower and upper case letters in the key should have the same value we normalize with toUpper() and then increment the counter k by 1.
            */
            int key_index = toupper(key[k]) - 'A';
            k++;

            //we use isupper to ensure we maintain capitalization
            if (isupper(s[i]))
            {
                /*
                    First we convert the current letter of string s[i] to it's alpha index (e.g., A=0, B=1, C=2, D-3.... Z=25) by subtracting it's ASCII value
                    Second we shift the alpha index by the key index and we mod by 26 to ensure we never exceed the upper bound of 26 letters of the alphabet
                    Lastly we convert the alpha index back into ASCII by re-adding A
                */
                int alpha_index = s[i] - 'A';
                int shifted_alpha_index = (alpha_index + key_index) % 26;
                int ascii_value = shifted_alpha_index + 'A';
                printf("%c", ascii_value);
            }
            else
            {
                int alpha_index = s[i] - 'a';
                int shifted_alpha_index = (alpha_index + key_index) % 26;
                int ascii_value = shifted_alpha_index + 'a';
                printf("%c", ascii_value);
            }
        }
        else
        {
            printf("%c", s[i]);
        }
    }
    printf("\n");
    return 0;
}
1

Congratulations on your success, and kudos for "takin' it to the next level.

In plain language, if k equals key_len, then k divided by key_len has a remainder of 0, therefore, k modulo key_len is 0. Now you should be able to reset k with one line, instead of using an if block.

1
  • Thanks! Your answer was exactly what I needed to improve my solution and help me learn how modulo wrapped around the keyword. I was able to replace my if block with k = k % key_length; and then re-run the tests and everything passed. Dec 21 '18 at 6:09

You must log in to answer this question.

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