0

My code is not elegant, but even though it's ugly, conceptually, I thought it would work. Nope. I feel as though it's staring me in the face and I can't see it.

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

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

    // accepts one, non-negative command-line argument
if (argc != 2)
{
    printf("Usage: ./vigenere k\n");
    return 1;
}

// creates variable for keyword
string keyword = argv[1];

// iterates thru keyword and quits if non-alphabetic
for (int i = 0, n = strlen(keyword); i < n; i++)
{
    if(!isalpha(keyword[i]))
    {
        printf("Usage: ./vigenere k\n");
        return 1;
    }

}

// prompts user for text to encrypt
printf("plaintext:");
string plain = get_string();

// checks user entered valid string
if (plain != NULL)
{
    printf("ciphertext:");

    // iterates thru plain one char at a time
    for (int i = 0, j = 0, pl = strlen(plain), kl = strlen(keyword); i < pl; i++)
    {

        // checks if char in string is alphabetic letter
        if (isalpha(plain[i]))
        {

            // checks if plaintext char is uppercase
            if (isupper(plain[i]))
            {

                // changes plain from ascii to alphabetic, adds keyword[j], changes back
                char cipher_up = (((plain[i] - 'A') + ((toupper(keyword[j]) - 'A') % kl)) % 26) + 'A';
                printf("%c", cipher_up);

            }

            // checks if plaintext char is lowercase
            else if (islower(plain[i]))
            {

                // changes plain from ascii to alphabetic, adds keyword[j], changes back
                char cipher_low = (((plain[i] - 'a') + ((toupper(keyword[j]) - 'a') % kl)) % 26) + 'a';
                printf("%c", cipher_low);

            }

            j++;

        }

        else
        {
            printf("%c", plain[i]);
        }

    }

}

printf("\n");

return 0;

} 

Case and non-alphabetic characters appear to be handled correctly, so then it's a modulo issue? Thanks for any help. I'm going to try and simplify it by creating addt'l variables.

~/workspace/ $ cd ~/workspace/pset2/vigenere
~/workspace/pset2/vigenere/ $ make vigenere3
clang -fsanitize=integer -fsanitize=undefined -ggdb3 -O0 -std=c11 -Wall -Werror -Wextra -Wno-sign-compare -Wshadow    vigenere3.c  -lcrypt -lcs50 -lm -o vigenere3
~/workspace/pset2/vigenere/ $ ./vigenere3 ABC
plaintext:HELLO HELLO HELLO
ciphertext:HFNJO HENMP HENLO
~/workspace/pset2/vigenere/ $ ./vigenere3 bacon
plaintext:Meet me at the park at eleven am
ciphertext:Nceq ic _r rhe m_pg ]r chdsdn aj

~/workspace/pset2/vigenere/ $

1 Answer 1

0

Look at this line:

char cipher_up = (((plain[i] - 'A') + ((toupper(keyword[j]) - 'A') % kl)) % 26) + 'A';

Specifically, look at this part: ((toupper(keyword[j]) - 'A') % kl)) % 26) I understand that the idea of % kl was to wrap back around when j exceeded the length of the key, but it is being applied to the converted ascii value of the key letter, not to j, so it's corrupting the conversion of the key letter to a value between 0 and 25.

the % kl needs to be applied directly to j, not the array element or any calculated value derived from the array element, maybe where j is being incremented?

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

1
  • Brilliantly explained. And so succinct. Helps tremendously. I just have to figure out how to implement it. Thanks for the suggestion, too :-)
    – Lindsey
    Mar 28, 2017 at 17:11

You must log in to answer this question.

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