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;
}