Search code examples
ccs50vigenere

Extra Characters at the end of Vigenere cs50 Pset2


I am new to coding and have been doing it for a couple of weeks. I am now taking the cs50 course and Ive written the code for pset2 vigenere. When I used check50, I realized it wanted me to account for spaces and non-letters without skipping ahead in the key.

I added the "j--;" and, although the code is correct, it now creates extra random characters at the end of the ciphertext.

Also, when checking argv[1] for just letters in my code I have an if statement that has "int key = argv[1][i];" in the body. It doesn't do anything but I don't know how to have it just continue checking the next char without having an empty body, which is not allowed.

Any help would be appreciated! Thank you very much!

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


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

{
    //making sure it is not more than one command line
    if (argc != 2)
    {
        printf("Usage: ./vigenere key \n");
        return 1;
    }

    //if it is one command line, making sure the input is just letters      
    if (argc == 2)
    {
        for (int i = 0, n = strlen(argv[1]); i < n; i++)
        {
            if (isalpha(argv[1][i]))
            {    
                int key = argv[1][i];
            }
            else
            {
                printf("Usage: ./vigenere key \n");
                return 1;
            }
        }   

    }
    //asking user for input text
    string plaintext = get_string("plaintext: ");
    printf("ciphertext:");

    //going through a loop to turn plain text into ciphertext 
    int i = 0; 
    int n = strlen(plaintext); 
    string key = argv[1];


    //looping through the key    
    while (i < n)

    {

        for (int j = 0, m= strlen(key); j < m; j++, i++)

        {   
            //using the asci of each char as an int
            int asc = (plaintext[i]);
            int k = key[j];
            //if lowercase
            if (k >= 97 && k <= 122)
            {
                k -= 97;
            }
            else
            {
                k -= 65;
            }

            //if lowercase
            if (asc >= 97 && asc <= 122)
            {
                printf("%c", ((((asc - 97) + k) % 26) + 97));
            }
            //if uppercase
            else
            {
                if (asc >= 65 && asc <= 90)
                {
                    printf("%c", ((((asc - 65) + k) % 26) + 65));
                }
                //if non-letter
                else
                {  
                    printf("%c", asc);
                    j--;

                }
            }

        }  


    }


    printf("\n");

}      

These are the expected vs actual results:

key: baz
plaintext: hello, world!
expected ciphertext: iekmo, vprke!

actual ciphertext:   iekmo, vprke!!pu

Solution

  • Because program increments i here for (int j = 0, m= strlen(key); j < m; j++, i++), it allows reading past the end of plaintext. The while loop is not going to evaluate i until after the for loop is done. And this has potential for an infinite loop, depending on what the contents of memory are after the end of plaintext. If it never encounters something in the a-z or A-Z range, it will j-- forever.

    You need to break out of the for loop if and when i == strlen(plaintext).