nerdcortex
nerdcortex

Reputation: 147

Vigenere Cipher Extra Characters

I was coding the Vigenere Cipher as part of CS50. This is my code.

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

int main(int argc, string argv[])
{
    if(argc != 2)
    {
        printf("Bad Argument!\n");
        return 1;
    }

    for(int k = 0; k <= strlen(argv[1]) - 1; k++)
    {
        if (isalpha(argv[1][k]) == 0)
        {
            printf("Bad Argument!\n");
            return 1;
        }
    }

    string s = GetString();
    char a[strlen(s)];

    int i, j = 0;
    int l = strlen(argv[1]);

    for (i = 0; i < strlen(s); i++)
    {
        int k = (int)(tolower(argv[1][j%l]) - 'a');

        if (s[i] >= 'A' && s[i] <= 'Z')
        {
            a[i] = (s[i] - 'A' + k) % 26 + 'A';
            j++;
        }
        else if (s[i] >= 'a' && s[i] <= 'z')
        {
            a[i] = s[i] - 'a' + k) % 26 + 'a';
            j++;
        }
        else
            a[i] = s[i];
    }

    printf("%s\n", a);

}

This is my code for pset2 vigenere.c. However, once I compile it and run it, I get misc characters at the end of the ciphertext like:TERMINAL SCREENSHOT

So, Check50 in some cases accepts the answer and in others it doesn't.

:( encrypts "a" as "a" using "a" as keyword
   \ expected output, but not "a\u001c������\n"
:( encrypts "world, say hello!" as "xoqmd, rby gflkp!" using "baz" as keyword
   \ expected output, but not "xoqmd, rby gflkp!v��\t��\n"
:) encrypts "BaRFoo" as "CaQGon" using "BaZ" as keyword
:) encrypts "BARFOO" as "CAQGON" using "BAZ" as keyword

What am I doing wrong?

Upvotes: 1

Views: 346

Answers (2)

user3386109
user3386109

Reputation: 34829

You forgot the NUL terminator.

C has no builtin type that's a "string", and your CS50 instructor is doing you a disservice by creating a typedef for "string" in "cs50.h". In C, a "string" is an array of characters with a NUL terminator at the end. The size of the array must be the string length plus one.

So the first error in your code is

char a[strlen(s)];

which should be

size_t length = strlen(s);
char a[length+1];

A slight optimization of your code would be to replace

for (i = 0; i < strlen(s); i++)

with

for (i = 0; i < length; i++)

But the biggest problem in your code is the lack of a NUL terminator, which you can fix by putting the following line after the end of the loop

a[length] = '\0';

If you're serious about learning C, I suggest transferring to a different university. Understanding strings in C is the key to writing stable, reliable, secure code. And because your professor is hiding the details from you, you are learning nothing.

Upvotes: 2

cadaniluk
cadaniluk

Reputation: 15229

You forgot to add a trailing null byte to the encrypted string. Therefore, everything following1 the string in memory (here, some data on the stack) is printed out until a random null byte is encountered.

So, allocate strlen(s) + 1 for the additional null byte:

char a[strlen(s) + 1];

And set the last element of a to '\0':

a[strlen(s)] = '\0';

1 means here: if x is at memory location 0x00, the following memory location is 0x01.


Notes:

  • I suggest introducing a variable like size_t plainstr_len = strlen(s); and using it anywhere in place of a plain strlen(s) for performance's sake

Upvotes: 1

Related Questions