Reputation: 147
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:
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
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
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:
size_t plainstr_len = strlen(s);
and using it anywhere in place of a plain strlen(s)
for performance's sakeUpvotes: 1