cs50 caesar - cypher not printing what is going wrong? - c

Stuck on this problem. Codes compiles, and takes input. however when attempting to use key '1' with plaintext 'a', i'm expecting 'b' but returning "\001" (which is not printing) when i check the debugger. Can someone help me explain why this is happening? I suspect error is when im allocating memory for the cypher test.. or when actually doing the cypher in my for / if statements.
int main(int argc,string argv[])
{
check_commands(argc);
//checks if key is alpha
string key = argv[1];
for (int i = 0; i < strlen(key); i++)
{
if (isalpha(key[i]))
{
printf("Usage: ./caesar key\n");
return 1;
}
}
//convert string argv[1] into an int
int k = atoi(key);
//ask user for pplaintect
string plaintext = get_string("Plaintext: ");
//create cyphertext variable
int s = strlen(plaintext);
char *cyphertext = malloc(s + 1);
printf("Cyphertext: ");
for (int i = 0; i < s; i++)
{
if (isalpha(plaintext[i]))
{
if (isupper(plaintext[i]))
{
// cypher based of k but keep upper
cyphertext[i] = ((plaintext[i] - 65) + k) % 26;
//print uppercase cypher
printf("%s", cyphertext);
}
if (islower(plaintext[i]))
{
//cypher based of k but keep lower
cyphertext[i] = ((plaintext[i] - 97) + k) % 26;
//print lowercase cypher
printf("%s", cyphertext);
}
}
else
{
printf("%c", plaintext[i]);
}
}
free(cyphertext);
printf("\n");
}
int check_commands(int argc)
{ //checks wether we have two command line arguments
if (argc != 2)
{
printf("Usage: ./caesar key\n");
return 1; //error
}
return 0;
}

You're just putting the modulus into cyphertext. You need to add that to the first character of the alphabet to get the corresponding letter, just as you subtract the character before adding k.
cyphertext[i] = 'A' + ((plaintext[i] - 'A') + k) % 26;
Also, don't hard-code ASCII codes like 65 and 97. Use character literals.

You allocated an uninitialized memory
char *cyphertext = malloc(s + 1);
It does not contain a string. So you may not use the conversion specifier s in calls of printf like this
printf("%s", cyphertext);
Also in these statements
cyphertext[i] = ((plaintext[i] - 65) + k) % 26;
and
cyphertext[i] = ((plaintext[i] - 97) + k) % 26;
you are storing not printable alpha characters.
Also this record
int s = strlen(plaintext);
is redundant.
Use do-while loop instead of the for loop. For example
size_t i = 0;
do
{
if ( isupper( ( unsigned char )plaintext[i] ) )
{
// cypher based of k but keep upper
cyphertext[i] = 'A' + ( plaintext[i] - 'A' + k ) % 26;
}
else if ( islower( ( unsigned char )plaintext[i] ) )
{
//cypher based of k but keep lower
cyphertext[i] = 'a' + ( plaintext[i] - 'a' + k ) % 26;
}
else
{
cyphertext[i] = plaintext[i];
}
} while ( plaintext[i++] != '\0' );
puts( cyphertext );
free( cyphertext );

Related

CS50 Caesar Prints Random Characters

I'm a little confused with this problem, because I got it to work and submitted and got full credit, but the code only words when I print the initial variables before the loop. This code works:
int main(int argc, string argv[]) {
// c = (p + k) % 26, where c is result text, p is input and k
// is key
//considers if arg count is two
if (argc == 2) {
int n = strlen(argv[1]);
int check = 0;
if (isdigit(argv[1][0])) {
for (int i = 1; i < n; i++) {
if (isdigit(argv[1][i]) || argv[1][i] == '0') {
check++;
} else {
check--;
}
}
}
// verifies all characters are numeric
if (check != n - 1) {
printf("Usage: ./caesar key\n");
return 1;
}
} else {
printf("Usage: ./caesar key\n");
// returning 1 identifies an error and exits the program
return 1;
}
int key = atoi(argv[1]);
string plaintext = get_string("plaintext: ");
printf("%i\n", key);
printf("%s\n", plaintext);
int m = strlen(plaintext);
printf("%i\n", m);
char ciphertext[m];
int usekey = (key % 26);
printf("%i\n", key);
// NEED to figure out how to handle wrap around
// need to understand ASCII
for (int i = 0; i < m; i++) {
int c = plaintext[i];
//encrypts upper case letters
if (c >= 65 && c <= 90) {
//incorporates wrap around for uppercase
if (c + usekey >= 90) {
int val = 90 - c;
int key2 = usekey - val;
char cipher = 64 + key2;
ciphertext[i] = cipher;
}
//considers if key works fine
else {
char cipher = c + usekey;
ciphertext[i] = cipher;
}
}
//encrypts lower case letters
else if (c >= 97 && c <= 122) {
//incorporates wrap around for lowercase
if (c + usekey >= 122) {
int val = 122 - c;
int key2 = usekey - val;
char cipher = 96 + key2;
ciphertext[i] = cipher;
} else {
char cipher = c + usekey;
ciphertext[i] = cipher;
}
} else {
//encrypts punctuation
ciphertext[i] = c;
}
printf("*\n");
}
printf("ciphertext: %s\n", ciphertext);
}
However, this code, does not work (for encrypts a as b using 1 as key, and for world, say hello! as iadxp, emk tqxxa! using 12 as key). It randomly prints different characters after the correct answer, and I cannot figure out why.
int main(int argc, string argv[]) {
// c = (p + k) % 26, where c is result text, p is input and k
// is key
//considers if arg count is two
if (argc == 2) {
int n = strlen(argv[1]);
int check = 0;
if (isdigit(argv[1][0])) {
for (int i = 1; i < n; i++) {
if (isdigit(argv[1][i]) || argv[1][i] == '0') {
check++;
} else {
check--;
}
}
}
// verifies all characters are numeric
if (check != n - 1) {
printf("Usage: ./caesar key\n");
return 1;
}
} else {
printf("Usage: ./caesar key\n");
// returning 1 identifies an error and exits the program
return 1;
}
int key = atoi(argv[1]);
string plaintext = get_string("plaintext: ");
int m = strlen(plaintext);
char ciphertext[m];
int usekey = (key % 26);
// NEED to figure out how to handle wrap around
// need to understand ASCII
for (int i = 0; i < m; i++) {
int c = plaintext[i];
//encrypts upper case letters
if (c >= 65 && c <= 90) {
//incorporates wrap around for uppercase
if (c + usekey >= 90) {
int val = 90 - c;
int key2 = usekey - val;
char cipher = 64 + key2;
ciphertext[i] = cipher;
}
//considers if key works fine
else {
char cipher = c + usekey;
ciphertext[i] = cipher;
}
}
//encrypts lower case letters
else if (c >= 97 && c <= 122) {
//incorporates wrap around for lowercase
if (c + usekey >= 122) {
int val = 122 - c;
int key2 = usekey - val;
char cipher = 96 + key2;
ciphertext[i] = cipher;
} else {
char cipher = c + usekey;
ciphertext[i] = cipher;
}
}
//encrypts punctuation
else {
ciphertext[i] = c;
}
}
printf("ciphertext: %s\n", ciphertext);
}
I think your if conditions is not works as it should be. you can print 'argv[1][i]' and see the problem. here is my code may help you.
bool isNumber(char number[])
{
int i = 0;
for (; number[i] != 0; i++)
{
if (!isdigit(number[i])) //check if there is something that is not digit
{
return false;
}
}
return true;
}
int main(int argc, string argv[])
{
if (argc == 2 && isNumber(argv[1]) == 1)
{
int k = atoi(argv[1]);
string plainText, chipherText;
plainText = get_string("plaintext: ");
printf("ciphertext: ");
for (int i = 0, n = strlen(plainText) ; i < n; i++)
{
// checking if it is lowercase 97 = a to 112 = z and if it + 13 characters along.
if (plainText[i] >= 'a' && plainText[i] <= 'z')
{
printf("%c", (((plainText[i] - 'a') + k) % 26) + 'a'); // print out lowercase with key
} // if it it between uppercase A and Z
else if (plainText[i] >= 'A' && plainText[i] <= 'Z')
{
printf("%c", (((plainText[i] - 'A') + k) % 26) + 'A'); // print out uppercase with key
}
else
{
printf("%c", plainText[i]);
}
}
printf("\n");
return 0;
}
else if (argc != 2 || isNumber(argv[1]) == 0)
{
printf("Error\n");
return 1;
}
}
You allocate m bytes for cyphertext, which is not enough for the null terminator, which you do not set either, causing random characters to appear after the encrypted output. This is actually undefined behavior, so anything can happen including a program crash.
You do not need to store the encrypted text, just output it one byte at a time.
Also do not use ASCII values such as 65 and 90, use character constants 'A' and 'Z' that are much more readable.
Here is a simplified version:
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
int main(int argc, string argv[]) {
if (argc != 2) {
printf("Usage: ./caesar key\n");
// returning 1 identifies an error and exits the program
return 1;
}
char *p;
int key = strtol(argv[1], &p, 10);
if (*p || p == argv[1]) {
printf("caesar: invalid argument: %s\n", argv[1]);
return 1;
}
string plaintext = get_string("plaintext: ");
// assuming ASCII
for (size_t i = 0; plaintext[i]; i++) {
int c = plaintext[i];
if (c >= 'A' && c <= 'Z') {
c = 'A' + (c - 'A' + key) % 26;
} else
if (c >= 'a' && c <= 'z') {
c = 'a' + (c - 'a' + key) % 26;
}
putchar(c);
}
putchar('\n');
free(plaintext);
return 0;
}

Cs50 Caesar Check50 fail

I am doing Caesar exercise from CS50 course, but it fail.
Here is the code:
# include <stdio.h>
# include <cs50.h>
# include <string.h>
# include <stdlib.h>
# include <ctype.h>
int main(int argc, string argv[])
{
if (argc == 2)
{
string key = argv[1];
int l = strlen(key);
for (int i = 0; i < l; i++)
{
// if key[i] is an alphabet character
if (isalpha(key[i]) != 0)
{
printf("Usage: ./caesar key\n");
return 1;
}
}
//change charater to number
int k = atoi(argv[1]);
//print Plaintext
string plaintext = get_string("Plaintext: ");
int n = strlen(plaintext);
char ciphertext[n];
//declare plaintext in ASCII
int nplaintext[n];
//Change plaintext to ASCII
for (int i = 0; i < n; i++)
{
nplaintext[i] = (int)plaintext[i];
}
//Declare ASCII for ciphertext which we name "plusplaintext"
int plusnplaintext[n];
for (int i = 0; i < n; i++)
{
//if Capital
if ((nplaintext[i] < 91) && (nplaintext[i] > 64))
{
plusnplaintext[i] = 65 + ((nplaintext[i] + k) - 65) % 26 ;
}
//if Lowercase
else if ((nplaintext[i] < 123) && (nplaintext[i] > 96))
{
plusnplaintext[i] = 97 + ((nplaintext[i] + k) - 97) % 26 ;
}
//if not character a -> z and A -> Z
else
{
plusnplaintext[i] = nplaintext[i];
}
}
for (int i = 0; i < n; i++)
{
ciphertext[i] = (char)plusnplaintext[i];
}
printf("ciphertext: %s\n", ciphertext);
}
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}
Here is the output from Check50:
:) caesar.c exists.
:) caesar.c compiles.
**:( encrypts "a" as "b" using 1 as key, output not valid ASCII text**
:) encrypts "barfoo" as "yxocll" using 23 as key
:) encrypts "BARFOO" as "EDUIRR" using 3 as key
:) encrypts "BaRFoo" as "FeVJss" using 4 as key
:) encrypts "barfoo" as "onesbb" using 65 as key
**:( encrypts "world, say hello!" as "iadxp, emk tqxxa!" using 12 as key, output not valid ASCII text**
:) handles lack of argv[1]
When I test the code, sometimes it gives right result, sometimes it give the wrong result with some more characters at the end...
How can I correct my code?
The problem is with the logic here
//if Capital
plusnplaintext[i] = 65 + ((nplaintext[i] + k) - 65) % 26 ;
and
//if Lowercase
plusnplaintext[i] = 97 + ((nplaintext[i] + k) - 97) % 26 ;
use this logic instead
//if Capital
((((nplaintext[i] - 90) + 25) + key) % 26) + 65
//if Lowercase
((((nplaintext[i] - 122) + 25) + key) % 26) + 97
and it is also not necessary to assign the letters to a string, instead you can directly print it
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
// Error Checking on the command line argument
if (argc != 2)
{
printf("Usage: ./caesar key\n");
return 1;
}
else if (argc == 2)
{
for (int i = 0; i < strlen(argv[1]); i++)
{
if (isdigit(argv[1][i]) == 0)
{
printf("Usage: ./caesar key\n");
return 1;
}
}
}
int key = atoi(argv[1]);
string plain_text = get_string("plaintext: ");
printf("ciphertext: ");
for (int i = 0; i < strlen(plain_text); i++)
{
if (isalpha(plain_text[i]) != 0)
{
// printf("%c", plain_text[i] + key);
if (isupper(plain_text[i]))
{
printf("%c", ((((plain_text[i] - 90) + 25) + key) % 26) + 65);
}
else
{
printf("%c", ((((plain_text[i] - 122) + 25) + key) % 26) + 97);
}
}
else
{
printf("%c", plain_text[i]);
}
}
printf("\n");
}
Instead of using the ascii value of a letter in your code, it could be helpful to keep them as characters for the sake of clarity. I took a snippet of your code and changed the values to demonstrate.
//if Capital
if ((nplaintext[i] <= 'Z') && (nplaintext[i] >= 'A'))
{
plusnplaintext[i] = 'A' + ((nplaintext[i] + k) - 'A') % 26 ;
}
This makes it clear what those values represent, and you don't have to reference an ascii chart. More comments would also help a user, or yourself later on, understand what the purpose is for each part of your code.
You could also create some functions outside of your main function. For example, to check for all digits in command line input, or change the letters by the amount given in the key. If you start working on long programs of code, it could be helpful to have functions defined that you can use as many times as you need. It also cleans up your main for clarity.
This function below takes the character of each letter in the original text (char p), then "moves" the character by k spaces (int k, given by the user as the key in the command line). It works when called in a for loop in main that iterates over each letter in the original given string (text[i]), with i being increased for each time the loop executes.
char rotate(char p, int k)
{
// declare variable for the rotated letter to be stored
char c;
// check if it is a letter
if (isalpha(p))
{
// check for lowercase letter
if (islower(p))
{
// subtract ascii value from p to initialize to 0 - 25 for computations
p -= 'a'; // if p is a, it is now initialized to 0, if b to 1, if c to 3, etc
c = (p + k) % 26; // use Caesar's algorithm to rotate letters, 'wrapping' by using % 26
c += 'a'; // add ascii value back to result to get the rotated letter
}
// the only other option is uppercase since we checked for only letters, do the same for uppercase letters as for lowercase
else
{
p -= 'A';
c = (p + k) % 26;
c += 'A';
}
}
// if it is the nul character '\0' return 0, do not print
else if (p == '\0')
{
return 0;
}
// if not a letter or nul character, return the character as is
else
{
c = p;
}
// print the rotated letter which is now stored in c
printf("%c", c);
// return the value of c
return c;
}

Caesar cipher outputs blank line

I am doing a problem set from the CS50 course and we have to implement Caesar's cipher. The following code works only with numbers (they remain the same as intended), when you put in a character, however, nothing is output. What's wrong?
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
//problem set requires arguments
int main (int argc, string argv [])
{
int i = 0;
if (argc != 2){
printf ("Retry\n");
return 1;
} else {
int x = atoi(argv [1]);
//gets plaintext
string a = get_string ("plaintext:");
printf("ciphertext:");
for (i = 0; i <= strlen(a); i++){
//if character is a number it remains unchanged
if (isdigit(a[i])){
printf ("%c", a[i]);
} else {
if (isupper(a[i])){
//converts from ASCII index to alphabetical index
char y = a[i] - 65;
//Caesar cipher formula. If upper case remains upper case.
y = toupper(a[i] + x % 26);
//goes back ASCII
printf("%c", y + 65);
} else if (islower(a[i])){
//converts from ASCII index to alphabetical index
char t = a[i] - 65;
//Caesar cipher formula. If lower case remains lower case.
t = tolower(a[i] + x % 26);
//goes back to ASCII
printf("%c", t + 65);
}
}
}
}
}
65 is the ASCII value for letter 'A'. If you are working on lower case word, you would need 97, which is ASCII value for 'a'
You have calculated t, but you didn't carry the result to the next line. Moreover, you have to take the modulus on the whole line. You are expecting that t is between 0 and 26, then you add it to 97
char t = a[i] - 97;
t = (t + x) % 26;
printf("%c", t + 97);
Also the for loop should go up to strlen(a). The last index in the string a is null-character, it should not be modified. You can also use 'a' instead of 97 here.
for(i = 0; i < strlen(a); i++)
{
if(isupper(a[i]))
{
char y = a[i] - 'A';
y = (y + x ) % 26;
printf("%c", y + 'A');
}
else if(islower(a[i]))
{
char t = a[i] - 'a';
t = (t + x )% 26;
printf("%c", t + 'a');
}
else
{
printf("%c", a[i]);
}
}

Why is my vigenere.c not working?

I keep making changes to the looping part of this code and my check50 always fails. I don't know what's going on. Below is my code:
#include <stdio.h>
#include <ctype.h>
#include <cs50.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, string argv[])
{
// declare variables
int cipherText;
if (argc != 2)
{
printf("Usage: ./vigenere keyword");
printf("\n");
return 1;
}
// keyword is the second command line argument
string key = argv[1];
int keylen = strlen(argv[1]);
// iterate through keyword to check if alphabetical
for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
if ((key[i] >= '0') && (key[i] <= '9'))
{
printf("Keyword must consist only of letters.");
return 1;
}
}
// get the plaintext
string plainText = GetString();
// encypher - iterate over the characters in string, print each one encrypted
for (int i = 0, j = 0, n = strlen(plainText); i < n; i++, j++)
{
// start the key again if key shorter than plainText
if (j >= strlen(key))
{
j = 0;
}
// skip key[j] if plainText[i] is not an alpha character
if (!isalpha(plainText[i]))
{
j = (j-1);
}
// makes Aa = 0, Zz = 25 for the uppercase letters
if (isupper(key[j]))
{
key[j] = (key[j] - 'A');
}
// makes Aa = 0, Zz = 25 for lowercase letters
else if (islower(key[j]))
{
key[j] = (key[j] - 'a');
}
if (isupper(plainText[i]))
{
cipherText = (plainText[i] - 'A');
cipherText = ((cipherText + key[j%keylen])%26) + 'A';
printf("%c", cipherText);
}
else if (islower(plainText[i]))
{
cipherText = (plainText[i] - 'a');
cipherText = ((cipherText + key[j%keylen])%26 + 'a');
printf("%c", cipherText);
}
else
{
printf("%c", plainText[i]);
}
}
printf("\n");
return 0;
}
Some answered this: "The first for loop has a problem. The condition is checking for i > keylen when it should be checking for i < keylen".
Also when computing the next output value, the steps should be
(p[i]-65) results in a number between 0 and 25
adding (key[i % keylen]) results in a number between 0 and 50
apply modulo 26 so the number is between 0 and 25 (this is the missing step)
then add 65 to get the output"
and it's what I tried to do.
Given this code:
int keylen = strlen(argv[1]);
// iterate through keyword to check if alphabetical
for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
if ((key[i] >= '0') && (key[i] <= '9'))
{
printf("Keyword must consist only of letters.");
return 1;
}
}
Your test inside the loop identifies digits as 'not a letter' (which is valid), but ignores punctuation, spaces and so on. You should probably be using if (!isalpha(key[i])) for the test (and it is courteous to print the erroneous character in the error message, which should be printed on standard error, not standard output, and should end with a newline:
fprintf(stderr, "Keyword must consist only of letters (%c found at %d)\n",
key[i], i+1);
You could refine that so it doesn't try printing non-printable characters with %c, but this is a huge step in the right direction.
You really don't need to set n in the loop; you just set keylen before the loop, so you could have written:
for (int i = 0; i < keylen; i++)
However, that is mostly cosmetic. Your real problem lies here:
// start the key again if key shorter than plainText
if (j >= strlen(key))
{
j = 0;
}
// makes Aa = 0, Zz = 25 for the uppercase letters
if (isupper(key[j]))
{
key[j] = (key[j] - 'A');
}
// makes Aa = 0, Zz = 25 for lowercase letters
else if (islower(key[j]))
{
key[j] = (key[j] - 'a');
}
You modify the key string on each iteration through the key. Unfortunately, though, if any of the letters in the key is a or A, you've converted that to '\0', which means that strlen(key) returns a different answer from before. So, you should use keylen in place of strlen(). AFAICS, if there isn't an a or A, that part of the code is OK.
Later, you have:
if (isupper(plainText[i]))
{
cipherText = (plainText[i] - 'A');
cipherText = ((cipherText + key[j%keylen])%26) + 'A';
printf("%c", cipherText);
}
The j % keylen is superfluous; j is already limited to 0 .. keylen-1. Similarly with the code for lower-case text.
Putting these changes together, and dummying up a GetString() function using fgets(), I get:
#include <stdio.h>
#include <ctype.h>
// #include <cs50.h>
#include <stdlib.h>
#include <string.h>
typedef char *string;
static char *GetString(void)
{
static char buffer[4096];
if (fgets(buffer, sizeof(buffer), stdin) == 0)
{
fprintf(stderr, "EOF detected in GetString()\n");
exit(EXIT_SUCCESS);
}
buffer[strlen(buffer) - 1] = '\0';
return buffer;
}
int main(int argc, string argv[])
{
// declare variables
int cipherText;
if (argc != 2)
{
printf("Usage: ./vigenere keyword");
printf("\n");
return 1;
}
// keyword is the second command line argument
string key = argv[1];
int keylen = strlen(argv[1]);
// iterate through keyword to check if alphabetical
for (int i = 0; i < keylen; i++)
{
if (!isalpha(key[i]))
{
printf("Keyword must consist only of letters (%c at %d)\n",
key[i], i+1);
return 1;
}
}
// get the plaintext
string plainText = GetString();
// encypher - iterate over the characters in string, print each one encrypted
for (int i = 0, j = 0, n = strlen(plainText); i < n; i++, j++)
{
// start the key again if key shorter than plainText
if (j >= keylen)
{
j = 0;
}
// skip key[j] if plainText[i] is not an alpha character
if (!isalpha(plainText[i]))
{
j = (j - 1);
}
// makes Aa = 0, Zz = 25 for the uppercase letters
if (isupper(key[j]))
{
key[j] = (key[j] - 'A');
}
// makes Aa = 0, Zz = 25 for lowercase letters
else if (islower(key[j]))
{
key[j] = (key[j] - 'a');
}
if (isupper(plainText[i]))
{
cipherText = (plainText[i] - 'A');
cipherText = ((cipherText + key[j]) % 26) + 'A';
printf("%c", cipherText);
}
else if (islower(plainText[i]))
{
cipherText = (plainText[i] - 'a');
cipherText = ((cipherText + key[j]) % 26 + 'a');
printf("%c", cipherText);
}
else
{
printf("%c", plainText[i]);
}
}
printf("\n");
return 0;
}
Sample run:
$ ./vigenere bakedalaska
What a wonderful world! The news is good, and the Vigenere cipher is solved.
Xhkx d wznvorguv arrwd! Lre oegw ls rogn, aod dlh Vtgwxese mmshpr ac splfig.
$

stuck with the vigenere.c

I am stuck in this example. Whenever I put the keyword 'bacon' I get the wrong answer.
Any idea why this is happening? I can't find the bug and I have tried a lot.
Can you please help me?
When I run this: ./vigenere bacon and input the text Meet me at the park at eleven am the answer should be Negh zf av huf pcfx bt gzrwep oz, but instead I get Negh ne og tjs qaty bt syfvgb bm
Update: I made some changes as suggested by the comments but still having the same problem.
#include<cs50.h>
#include<ctype.h>
#include<stdio.h>
#include<string.h>
int main(int argc, char *argv[])
{
//check if it has only two values
if (argc != 2)
{
printf("Usage: ./vigenere keyword\n");
return 1;
}
// check that every letter of keyword is alphabetic
char *keyword = argv[1];
int keylen = strlen(keyword);
for (int i = 0, n = keylen; i < n; i++)
{
if(!isalpha(keyword[i]))
{
printf("alphabetic keyword only!!!\n");
return 1;
}
if(isalpha(keyword[i]))
{
// if a letter of keyword is uppercase
if (isupper(keyword[i]))
{
keyword[i] = keyword[i] - 'A';
}
// if a letter of keyword is lowercase
if (islower(keyword[i]))
{
keyword[i] = keyword[i] - 'a';
}
}
}
char *text = GetString();
for (int i = 0, n = strlen(text); i < n; i++)
{
if (isalpha(text[i]))
{
// if plaintext letter uppercase then...
if (isupper(text[i]))
{
text[i] = ((text[i] - 'A') + (keyword[i % keylen])) % 26 + 'A';
printf("%c",text[i]);
// ^^^^^^ ----> repeat the pattern
}
// if plaintext letter lowercase then ...
if (islower(text[i]))
{
text[i] = ((text[i] - 'a') + (keyword[i % keylen])) % 26 + 'a';
printf("%c",text[i]);
}
}
// if no letters in plaintext then ...
if (!isalpha(text[i]))
{
text[i] = text[i];
printf("%c",text[i]);
}
}
printf("\n");
}
So as #BLUEPIXY suggested I had to use a different variable in order to get the right answer:
`char *text = GetString();
int k = 0;
for (int i = 0, n = strlen(text); i < n; i++)
{
if (isalpha(text[i]))
{
// if plaintext letter uppercase
if (isupper(text[i]))
{
text[i]= ((text[i] - 'A') + (keyword[k % keylen])) % 26 + 'A';
printf("%c",text[i]);
//^^^^^ ----> repeat the keyword pattern
}
// if plaintext letter lowercase
if (islower(text[i]))
{
text[i] = ((text[i] - 'a') + (keyword[k % keylen])) % 26 + 'a';
printf("%c",text[i]);
}
k++;
}`

Resources