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

int main(int argc, string argv[])
{
    string key = (argv[1]);
    string plaintext;
    int a;
    int j;
    int i;
    if(argc == 2)
    {
        for(i = 0; i < strlen(key); i++)
        {
            bool alpha = isalpha(key[i]);
            if(alpha != true)
            {
                printf("Usage: ./vigenere k\n");
                return 1;
            }
        }
        plaintext = get_string("plaintext: ");
        for (i = 0; i < strlen(key); i++)
        {
            if(islower(key[i]))
            {
                key[i] = (int)key[i] - 97;
            }
            else if(isupper(key[i]))
            {
                key[i] = (int)key[i] - 65;
            }
        }
        for (j = 0; j < strlen(plaintext); j++)
        {
            if(strlen(key) == 0)
            {
                break;
            }
            else if(isspace(plaintext[j]))
            {
                a = plaintext[j];
            }
            else if(islower(plaintext[j]) && isalpha(plaintext[j]))
            {
                a = ((plaintext[j] + key[(j % strlen(key))] - 97) % 26) + 97;
            }
            else if(isupper(plaintext[j]) && isalpha(plaintext[j]))
            {
                a = ((plaintext[j] + key[(j % strlen(key))] - 65) % 26) + 65;
            }
            else
            {
                a = plaintext[i];
            }
        plaintext[j] = a;
        }
    }
    else
    {
        printf("Usage: ./vigenere k\n");
        return 1;
    }
    printf("ciphertext: %s\n", plaintext);
    return 0;
}

This is what I get:

~/workspace/pset2/ $ check50 cs50/2018/x/vigenere
Connecting.....
Authenticating.........
Preparing....................
Uploading..............
Checking........
:) vigenere.c exists.
:) vigenere.c compiles.
:) encrypts "a" as "a" using "a" as keyword
:( encrypts "barfoo" as "caqgon" using "baz" as keyword
    expected "ciphertext: caq...", not "ciphertext: cbs..."
:( encrypts "BaRFoo" as "CaQGon" using "BaZ" as keyword
    expected "ciphertext: CaQ...", not "ciphertext: CbS..."
:( encrypts "BARFOO" as "CAQGON" using "BAZ" as keyword
    expected "ciphertext: CAQ...", not "ciphertext: CBS..."
:( encrypts "world!$?" as "xoqmd!$?" using "baz" as keyword
    expected "ciphertext: xoq...", not "ciphertext: xps..."
:( encrypts "hello, world!" as "iekmo, vprke!" using "baz" as keyword
    expected "ciphertext: iek...", not "ciphertext: ifm..."
:) handles lack of argv[1]
:) handles argc > 2
:) rejects "Hax0r2" as keyword
See https://cs50.me/checks/3dd9f73e9815723ddaf7bfb41b78e9118f3c53e3 for more detail.
1
  • Pattern I've noticed, the letters you have encrypted are off by 0 first, then 1, then 2, then 0, then 1 from the correct answers... May 14, 2018 at 21:26

1 Answer 1

2

If you printf the value of strlen(key) BEFORE your loop that starts with for (i = 0; i < strlen(key); i++) you will find that the value is what you would expect. However, your loop seems to change your value: if you look at the value of strlen(key) AFTER this loop runs, it is only 1!

Therefore, while your line of code key[(j % strlen(key))] is correct, it will never make the right answer because it is always essentially executing as j % 1.

Here's Why:

This is probably because you are modifying keys. Think about it: strlen looks for letters until it finds \0. However, it's hard to say for sure that you know what strlen will do if it finds things that are NOT letters! Also, how do you know that one of your new key values is not the same thing as \0?

The solution is this: replace for (i = 0; i < strlen(key); i++) with something like

int ln= strlen(key)
for (i = 0; i < ln; i++)

Then be sure to replace all OTHER instances of strlen(key) with ln.

(PS: This make you pass most of the tests; I think you can solve the rest.)

1
  • 1
    Very good! The concise description of the strlen issue is this. The strlen function looks for \0 as the end of string marker. That happens to be binary/hex 0. It also happens to be what you get as a result of 'a' - 'a' or 'A' - 'A'. So, when a or A is converted to 0, it looks to strlen like the end of string marker. ;-)
    – Cliff B
    May 14, 2018 at 23:34

You must log in to answer this question.

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