2

I am trying to implement Vigenere's Cipher in C but the problem is that when I try to repeat the key used in the array it is in, it breaks after the 4th letter. So if the key is ABC and the plaintext is HELLO, it returns HFNLO instead of HFNLP. When I look at my code it logically makes sense but it seems to just not work. Can anybody see the problem?

Here is the code:

int main(int argc, string argv[])
{
    if(argc != 2)
    {
        printf("usage: ./vigenere k\n");
        return 1;
    }
    //asks for plain text
    printf("plaintext: ");
    string text = get_string();
    string k = argv[1];
    printf("ciphertext: ");

    //checks to see if length of key is shorter than length of plaintext and duplicates it.
    int count = 0;
    while(strlen(k) <= strlen(text))
    {
        k[strlen(k + count)] = k[count];
        count++;
    }

    //changes key to be within 0 - 25 and encrypts plaintext
    for(int i = 0; i < strlen(text); i++)
    {
        if(k[i] >= 'A' && k[i] <= 'Z')
        {
             k[i] = k[i] - 65;
        }
        else if (k[i] >= 'a' && k[i] <= 'z')
        {
            k[i] = k[i] - 97;
        }

        //if statement for plaintext capital letters
        if(text[i] >= 'A' && text[i] <= 'Z')
        {
            text[i] = text[i] - 64;
            text[i] = ((text[i] + k[i]) % 26) + 64;   
        }
        //if statement for plaintext lowercase letters
        else if(text[i] >= 'a' && text[i] <= 'z')
        {
             text[i] = text[i] - 96;
             text[i] = ((text[i] + k[i]) % 26) + 96;   
        }
        //prints final cipher
        printf("%c", text[i]);
    } 
    printf("\n");
    return 0;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278

1 Answers1

2

You should use the modulo operator to compute the offset into the key.

Here is a modified version:

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

int main(int argc, string argv[]) {
    if (argc != 2) {
        printf("usage: ./vigenere k\n");
        return 1;
    }
    string k = argv[1];
    size_t klen = strlen(k);
    if (klen == 0) {
        fprintf(stderr, "vigenere: key must not be empty\n");
        return 1;
    }

    printf("plaintext: ");
    string text = get_string();

    printf("ciphertext: ");

    for (size_t i = 0; text[i] != '\0'; i++) {
        int d = (unsigned char)k[i % klen];
        if (d >= 'A' && d <= 'Z') {
            d -= 'A';
        } else
        if (d >= 'a' && d <= 'z') {
            d -= 'a';
        } else {
            d = 0;
        }

        int c = (unsigned char)text[i];
        if (c >= 'A' && c <= 'Z') {
            c = 'A' + (c - 'A' + d) % 26;   
        } else
        if (c >= 'a' && c <= 'z') {
            c = 'a' + (c - 'a' + d) % 26;   
        }
        putchar(c);
    }
    putchar('\n');
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189