So I am working on a SC50 problem where I need to make a simple cipher and be able to encrypt words or sentences... After 2 full days I actually kindof figured it all out, but my code was really long and after some googling I found a version out there that was much better. And it was real easy and all, except for the part where there is stuff that I don't really understand how it works, and I would really like to find out how... so here is the full code below (unfortunately I can't seem to find the original source of the code right now, but I actually did at least half of it myself, and only the part after "//SUBSTITUTION is copied) :
and also, what I wonder about, are these two rows:
printf("%c", toupper(arg[plaintext[i] - 65])); //calculation to print the encipher text amd make sure it is Uppercase (case doesn't change)
and
printf("%c", tolower(argv[1][plaintext[i] - 97])); ///calculation to print the encipher text amd make sure it is lowercase(case doesn't change)
...I can't wrap my head around, how the calculation "-65" and "-66" are solving the issue...
Lets say that in my key, the first letter is a Q, and when I write and A, it should be substituted for a Q...
A = 65 and Q = 81 on the Ascii table, so when I take 65 - 65... mm why would I do that? obviously it needs to be done for this program to work correctly, but I don't understand how it works and what actually happens...
what is the logic behind these calculations? please help!
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(int argc, string argv[]) {
if (argc != 2) {
printf("Usage: ./substitution key\n");
return 1;
}
string arg = argv[1];
int chars = 0;
for (int i = 0; i < strlen(arg); i++) {
if (isalpha(arg[i])) {
for (int j = i+1; j < strlen(arg); j++) {
if (toupper(arg[j]) == toupper(arg[i])) {
printf("Key must not contain repeated alphabets.\n");
return 1;
}
}
chars += 1;
}
}
if (chars != 26) {
printf("Key must contain 26 characters.\n");
return 1;
}
// SUBSTITUTION
printf("%s\n", arg);
string plaintext = get_string("plaintext: "); //Getting user's input as plaintext
printf("ciphertext: "); //to print the ciphertext
int plaintext_length = strlen(plaintext); //get the strlen of plaintext (user's input)
for (int i = 0; i < plaintext_length; i++) { //iterate over the plaintext_Length
if (isupper(plaintext[i])) { //check if plaintext character is uppercase
printf("%c", toupper(arg[plaintext[i] - 65])); //calculation to print the encipher text amd make sure it is Uppercase (case doesn't change)
}
else if (islower(plaintext[i])) { //check if plaintext character is lowercase
printf("%c", tolower(arg[plaintext[i] - 97])); ///calculation to print the encipher text amd make sure it is lowercase(case doesn't change)
}
else { //if plaintext is anything else, print it like that without changing
printf("%c", plaintext[i]);
}
}
printf("\n"); //print new line
}
In general it is a bad code.
For example instead of using magic numbers 65 or 97
printf("%c", toupper(arg[plaintext[i] - 65]));
printf("%c", tolower(argv[1][plaintext[i] - 97]));
it is better to write
printf("%c", toupper(arg[plaintext[i] - 'A']));
printf("%c", tolower(argv[1][plaintext[i] - 'a']));
argv[1] or arg contains a string of 26 letters as for example
"xyzabcgtidefuvwjklmn0rspqh"
If you have a string as for example "Hello" then 'H' - 'A' gives the value 7. Using the number you can find at position 7 in the array pointed by the string argv[1] or arg the letter t
"xyzabcgtidefuvwjklmn0rspqh"
^
|
'H'
So the letter 'H' in the source string is coded like the letter 'T'. For the second letter 'e' you have 'e' - 'a' is equal to 4. So you have
"xyzabcgtidefuvwjklmn0rspqh"
^
|
'e'
So the first two letter of the string "Hello" becomes "Tbllo". This approach is used for the remaining letters of the source string to encrypt it.
"... I can't wrap my head around,..."
Yes, it is difficult to see what is going on in code that avoids (appropriately) using a temporary copy of the data of interest.
Without the comments, this is the "confusing" portion of your code, rewritten to temporarily use a single character variable:
// SUBSTITUTION
printf("%s\n", arg);
string plaintext = get_string("plaintext: "); //Getting user's input as plaintext
printf("ciphertext: "); //to print the ciphertext
int plaintext_length = strlen(plaintext); //get the strlen of plaintext (user's input)
for (int i = 0; i < plaintext_length; i++) //iterate over the plaintext_Length
{
char c = plaintext[i];
if( isupper( c ) )
{
printf("%c", toupper(arg[c - 65]));
}
else if ( islower( c ) )
{
printf("%c", tolower(arg[c - 97]));
}
else
{
printf("%c", plaintext[i]);
}
}
It is now obvious that there will be an output character, so 3 calls to printf() are distracting. Simplifying that leads to 're-using' the temporary char variable. (Here just showing the for() loop):
for (int i = 0; i < plaintext_length; i++) //iterate over the plaintext_Length
{
char c = plaintext[i];
if( isupper( c ) )
{
c = toupper(arg[c - 65]);
}
else if ( islower( c ) )
{
c = tolower(arg[c - 97]);
}
else
{
c = plaintext[i];
}
printf( "%c", c );
}
It is now apparent that the final 'else' is redundant:
for (int i = 0; i < plaintext_length; i++) //iterate over the plaintext_Length
{
char c = plaintext[i];
if( isupper( c ) )
{
c = toupper(arg[c - 65]);
}
else if ( islower( c ) )
{
c = tolower(arg[c - 97]);
}
printf( "%c", c );
}
The values '65' and '97' are called "magic numbers" (that you already understand correspond to ASCII 'A' and 'a' respectively.) Cleaning up that bad practice.
if( isupper( c ) )
{
c = toupper( arg[ c - 'A' ] );
}
else if ( islower( c ) )
{
c = tolower( arg[ c - 'a' ] );
}
printf( "%c", c );
It now is readily apparent that the 'case' of each input character determines the 'case' of the corresponding output character.
It should now also be readily apparent that the difference 'offset' from 'A' or 'a' of the plaintext character ( 'A/a' = 0, 'B/b' = 1, 'C/c' = 2) is being calculated. The result of that calculation becomes the INDEX of the 26 character enciphering key. Your 'Q' becomes '16' so the 16th character of the key is "looked up", turned into the appropriate case, and then used.
This operation can be further reduced as per the following:
for (int i = 0; i < plaintext_length; i++) //iterate over the plaintext_Length
{
char c = plaintext[i]; // copy of plaintext character
if( isalpha( c ) ) { // translate only alphabetic chars
c = tolower( c ) - 'a'; // 'a-z' ==> '0-25'
c = arg[ c ]; // use as index into key.
if( isupper( plaintext[i] ) // make case of enciphered char match input
c = toupper( c );;
}
printf( "%c", c );
}
Or, even more:
for (int i = 0; i < plaintext_length; i++) //iterate over the plaintext_Length
{
char c = plaintext[i]; // copy of plaintext character
if( isalpha( c ) ) { // translate only alphabetic chars
c = arg[ tolower( c ) - 'a' ]; // select corresponding 'key' character
if( isupper( plaintext[i] ) // make case of enciphered char match input
c = toupper( c );;
}
printf( "%c", c );
}
Although that seems intricate, its brevity is its strength.
EDIT: isalpha() toupper() and tolower() are standard C functions. The code will need to: #include <ctype.h> to use those functions.
EDIT2: toupper() and tolower() will return an unsigned char. To compile without warnings, change the declaration of 'c':
unsigned char c = plaintext[i]; // copy of plaintext character
EDIT3:
Your OP did not ask about the "validation code" that you say you wrote. I'm sorry, but it is insufficient. While it confirms there are 26 distinct characters in the key, a user could type a key containing additional punctuation sprinkled in. "abc" contains 3 distinct letters, but so does "a.b:!c"... You test for isalpha(). Why not halt immediately if a non-alpha char is found in the key? As written, illegitimate keys may be used and the 'enciphering' very, very incorrect...
Related
The task is for the user to insert a string and the program will output a secret message, that changes each occurrence of a character of that string with another character. The list of new characters that will be inserted are given by the permutation "qjczieaungsdfxmphybklortvw", which correspond to every letter of the alphabet. So for example, the string "abcxyz" will return "qjctvw". The program will ignore symbols and capital letters, so "Abc" will become "Ajc".
I tried to achieve this by comparing each position of the string with each letter of the alphabet. If it matches, then that position of the string will be replaced by the position of the secret permutation that is the same as the position of the traditional alphabet (since they correspond). The code technically works, but I'm not getting the right values. For instance, for every "a" I should get a "q", but I'm returned a "h". If anyone can fix my code, it will be greatly appreciated.
CODE BELOW: PLEASE COPY AND PASTE INTO YOUR PREFERRED CODE EDITOR TO SEE WHAT I MEAN BY RETURNING THE WRONG VALUES.
#include <string.h>
#define MAX_STR_LEN 256
int main(void)
{
char perm[] = "qjczieaungsdfxmphybklortvw";
char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
int i, j;
char msg[MAX_STR_LEN+1];
/* read the message from the terminal using fgets. The variable msg will contain the message. */
fgets(msg, MAX_STR_LEN, stdin);
/*compares each value of the string to the alphabet*/
for (i = 0; i < (strlen(msg) - 1); i++) {
for (j = 0; j < (strlen(alphabet) - 1); j++) {
if (msg[i] == alphabet[j]) {msg[i] = perm[j];}
}
}
printf("%s", msg);
}
For starters after the call of fgets
fgets(msg, MAX_STR_LEN, stdin);
you need to remove the new line character '\n' that can be appended to the entered string by the function.
msg[ strcspn( msg, "\n" ) ] = '\0';
Also the for loops are incorrect.
At least instead of using the condition
j < (strlen(alphabet) - 1)
in the inner for loop
for (j = 0; j < (strlen(alphabet) - 1); j++) {
if (msg[i] == alphabet[j]) {msg[i] = perm[j];}
}
you need to use the condition
j < strlen(alphabet)
and when a character is found in the string alphabet you have to exit the loop. Otherwise the already changed character can be changed the second time.
You can use the function strchr instead of the manually written inner for loop. For example
/*compares each value of the string to the alphabet*/
for ( size_t i = 0; msg[i] != '\0'; i++ )
{
const char *p = strchr( alphabet, msg[i] );
if ( p != NULL )
{
msg[i] = perm[p - alphabet];
}
}
Here is your updated program.
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 256
int main( void )
{
const char *perm= "qjczieaungsdfxmphybklortvw";
const char *alphabet= "abcdefghijklmnopqrstuvwxyz";
char msg[MAX_STR_LEN+1];
/* read the message from the terminal using fgets. The variable msg will contain the message. */
fgets( msg, MAX_STR_LEN, stdin );
msg[ strcspn( msg, "\n" ) ] = '\0';
/*compares each value of the string to the alphabet*/
for ( size_t i = 0; msg[i] != '\0'; i++ )
{
const char *p = strchr( alphabet, msg[i] );
if ( p != NULL )
{
msg[i] = perm[p - alphabet];
}
}
puts( msg );
}
If to enter the string
abcxyz
then the program output is
qjctvw
This task can be very easy once you get to the root of the problem and observe that:
Your alphabet replacements string is just a simple array having letter values mapped to indexes from 0 to 25.
Characters themselves have some integer values specified by the ASCII standard, and they happen to be conscutive ('b'=='a'+1).
Having this knowledge, we can invent a function that takes a character and converts it to the correct position in the perm string. We can do that in a extremely simple manner, by just subtracting 'a' from whatever character we have. 'a'-'a' will be equal to 0, and so on.
This can be implemented as a function like this: (or you can just inline it, since it's pretty trivial)
int get_char_index(char c){
return c - 'a';
}
And now, having access to this function, all we need to do is to iterate over a string character by character (for loop, while loop, doesn't matter), read the char from the string, feed it to the function, and then once you get the corresponding index of the perm, you just need to assign the value of char under that index back to the string.
int main() {
const char perm[] = "qjczieaungsdfxmphybklortvw";
char some_string_to_convert[] = "aabbccddeeffgghhiijjkkllmmnnoopprrssttqqvvwhatever";
for(int i=0; i<strlen(some_string_to_convert); i++){
char c = some_string_to_convert[i];
int perm_index = get_char_index(c);
some_string_to_convert[i] = perm[perm_index];
}
printf("%s", some_string_to_convert);
}
The following code outputs:
qqjjcczziieeaauunnggssddffxxmmppyybbkkhhooruqkioiy
I hope my answer helps you solve the problem.
I'm trying to write code that will take each digit from a plaintext string input and, if it is a letter, output a different letter, as defined by a substitution key (26-letter key).
In other words, if the alphabet was "abcd" and provided key was "hjkl", an input of "bad" would output "jhl".
// Regular alphabet is to be used as comparison base for key indexes //
string alphabet = "abcdefghijklmnopqrstuvwxyz";
// Prompt user for input and assign it to plaintext variable //
string plaintext = get_string("plaintext: ");
Non-letters should be printed as-is.
My idea was to loop the input digit through every index in the alphabet looking for the corresponding letter and, if found, print the same index character from the string. (confusing, I think)
This loop, however, returns a segfault when I run it, but not when debugging:
// Loop will iterate through every ith digit in plaintext and operate the cipher //
for (int i = 0; plaintext[i] != '\0'; i++) {
// Storing plaintext digit in n and converting char to string //
char n[2] = "";
n[0] = plaintext[i];
n[1] = '\0';
// If digit is alphabetic, operate cipher case-sensitive; if not, print as-is //
if (isalpha(n) != 0) {
for (int k = 0; alphabet[k] != '\0'; k++) {
char j[2] = "";
j[0] = alphabet[k];
j[1] = '\0';
if (n[0] == j[0] || n[0] == toupper(j[0])) {
if (islower(n) != 0) {
printf("%c", key[k]);
break;
} else {
printf("%c", key[k] + 32);
break;
}
}
}
} else {
printf("%c", (char) n);
}
}
What's going wrong? I've looked for help online but most sources are not very beginner-friendly.
Your code seems to be working except one error: The program crashes at
isalpha(n)
Cause you declared
char n[2]
the parameter there is a pointer of type char*. But islower only accepts an int parameter, so just write it as
isalpha(n[0])
Same for islower.
I have an assignment to create a program that converts each character in a string by a set number entered at the command line. Example: if the user enters 1 at the command line then enters abc, def then the program should convert the string to bcd, efg.
I've written the program but I can't figure out how to get the program to not convert the punctuation characters.
The program currently converts abc, def and prints bcdefg. It needs to print bcd, efg and include the punctuation characters without converting them.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(int argc, string argv[]) //user enter number at cmd prompt
{
string key = argv[1]; //store user entered number
int k = atoi(argv[1]); //only accept consecutive digits
if (argc != 2 || k == 0)
{
printf("Usage: ./caesar key\n"); /*show error if user enters non-consecutive digits*/
return 1;
}
string original = get_string("Plaintext: "); /* prompt user for message to spin*/
for (int i = 0, n = strlen(original); i < n; i++) /* get string length and loop char change*/
if (isalnum(original[i])) /* only convert alphanumeric character*/
printf("%c", original[i] + k); /* print and convert character by number entered at prompt*/
printf("\n");
return 0;
}
You are only outputting the characters that your are transforming (those that are in the isalnum set). You need to also output the characters not transformed. For example:
char cipher = original[i] ;
if( isalnum( original[i] )
{
cipher += k ;
}
printf( "%c", cipher ) ;
However the algorithm as described remains deeply flawed in several ways, but it is not clear whether it is the assignment that is flawed (in which case that is not your problem) or if your description of the assignment is inaccurate.
A more practical solution might look like:
#include <ctype.h>
char caesar( char x, int key )
{
const char alphabet[] = {'a','b','c','d','e','f','g','h',
'i','j','k','l','m','n','o','p',
'q','r','s','t','u','v','w','x',
'y','z',
'0','1','2','3','4','5','6','7','8','9'};
char cipher = x ;
for( int i = 0;
cipher == x && i < sizeof( alphabet );
i++ )
{
if( alphabet[i] == tolower( x ) )
{
cipher = alphabet[(i + key) % sizeof( alphabet )] ;
if( isupper( x ) )
{
cipher = toupper( cipher ) ;
}
}
}
return cipher ;
}
Then your output loop would be:
for( int i = 0; original[i] != '\0' ); i++)
{
printf("%c", ceasar( original[i], k ) ) ;
}
What you're currently doing only prints the character + k if it's alpha-numeric, but not printing it otherwise. You you really want to do is only add k if it is alpha-numeric. With a little boolean logic and math, we can avoid the if-statement altogether.
printf("%c", original[i] + (k * !!isalnum(original[i])));
If isalnum returns true, !! will make the resulting value 1 (it can return non-zero value if true; double-negating logically will make it either 1 if true or 0 if false). So now we add k if it's alpha-numeric, or add nothing otherwise, and print the character either way.
I am trying to find the no of lower and uppercase characters from a input.
here's my code:
#include <stdio.h>
#include <string.h>
int main()
{
char cAFirst[25];
int k = 0,uc =0 ,lc =0 ;
fgets(cAFirst,25,stdin);
// printf("out: %d \n",k);
for (size_t i = 0; i < 25; i++) {
k = (int)cAFirst[i];
if ((k <= 90) && (k >= 65)) {
uc++;
}
if ((k >= 97) && (k <= 122)) {
lc++;
}
}
printf("Uppercase Letters=%i \nLowercase Letters=%i \n",uc,lc );
return 0;
}
lowercase (lc) is ok, but value of uc is randomly incremented.
I have already tried changing formatting of printf and it sometimes work, but problem is i have to submit this code with same formatting given above.
Rather then always iterate 25 times, iterate until the end of input is detected.
// for (size_t i = 0; i < 25; i++) {
for (size_t i = 0; cAFirst[i]; i++) { // detect null character.
Considering this snippet from OP's posted code:
char cAFirst[25]; // <- Uninitialized, the contents are indeterminated
// ...
fgets(cAFirst,25,stdin); // <- We don't know if it succeeded or not
// ...
for (size_t i = 0; i < 25; i++) {
// ... ^^^^^^
}
It copies up to 24 chars from stdin to the array (including the newline, if present), also adding the null-terminator (if no stream error occurred), but when the loop is executed, it goes over all the 25 char of the array, even if the inputted string is shorter, taking into account chars with indeterminate value.
To avoid this, we just have to test only the characters which were actually read from the input stream, by counting them or using the null-terminator as a sentinel.
We could intialize the array (to zero) and also avoid the use of repeated magic numbers, which is error prone.
#include <stdio.h>
// I'd use a bigger value, like 256, but OP's use case is not specified.
enum {
BUF_SIZE = 25
};
int main(void)
{
// All the elements of the array are set to zero, not only the first.
char buf[BUF_SIZE] = {'\0'};
// ...
Now, even if all the chars in the array are tested in the previous loop, there won't be spurious values and the statistics will be consistent. This is not a real solution, though, and while it is commonly suggested to initialize all the variables before their use, in this case it is not necessary.
As noted by chux, the return value of functions like fgets should be checked, to verify that the operation has succeeded and that our variables are in a valid state.
if ( fgets(buf, BUF_SIZE, stdin) == NULL ) {
if (feof(stdin)) {
fprintf(stderr, "Abnormal end of input.\n");
// The contents of the array are not altered
}
if (ferror(stdin)) {
fprintf(stderr, "A stream error occurred.\n");
// The contents of the array are indeterminated, maybe not even null-terminated
}
exit(EXIT_FAILURE);
}
The key point is to be sure that, after this call, the array is null-terminated. Even a check like the following could be enough:
if ( fgets(buf, BUF_SIZE, stdin) == NULL ) {
fprintf(stderr, "An error occurred while reading from stdin.\n");
buf[0] = '\0';
// Continues the program despite the error, but with a valid (empty) string
}
It's worth remembering that any further characters besides the ones read, remain in the input stream.
Now that we have a valid (null-terminated) array, we can loop through it:
int uc = 0, lc = 0;
for (size_t i = 0; buf[i] != '\0'; i++) {
// which can also be written as 'for (size_t i = 0; buf[i]; i++) {'
// It's also more readable without magic numbers:
if ( 'A' <= buf[i] && buf[i] <= 'Z' ) {
uc++;
}
else if ( 'a' <= buf[i] && buf[i] <= 'z' ) {
lc++;
}
}
printf("Uppercase Letters = %i\nLowercase Letters = %i\n", uc, lc);
return EXIT_SUCCESS;
}
The previous snippet may be generalized from ASCII codes using functions like isupper and islower defined in header <ctype.h>. Also, the actual length of the string can be used to limit the for-loop:
// Length of the maximum initial segment of the array, that consists of
// only the characters not equal to a newline or null character
size_t length = strcspn(buf, "\n");
int uc = 0, lc = 0;
for (size_t i = 0; i < length; i++) {
unsigned char k = buf[i];
if ( isupper(k) ) {
uc++;
}
else if ( islower(k) ) {
lc++;
}
}
// ...
You should first use a way to iterate your string only once maybe a while loop and try to read not just what you need but also what there could be which should not be counted. What happens if there is \t or \n Do you need them to count too?
Here is an approach which can help you to understand that:
#include <stdio.h>
int main( void )
{
char string[] = "AbcDEfgHiJKlmnOPqrstUVWxyZ\n§$%$§";
int uc, lc, i, others;
uc = lc = i = others = 0;
while ( string[i] )
{
if ( string[i] >= 'A' && string[i] <= 'Z' )
{
uc++;
}else if ( string[i] >= 'a' && string[i] <= 'z' ){
lc++;
}else{
others++;
}
i++;
}
if ( i == ( lc + uc + others ) )
{
printf( "OK\n\n" );
printf("Uppercase Letters = %i \nLowercase Letters = %i \nOthers = %d \n", uc, lc, others );
printf("Total = %d\n", i );
}else
{
printf("Something went Wrong.\n\n");
}
}
Your if/else statements could be easy replaced by the functions isupper( string[i] ) and islower( string[i] ) which are found in ctype.h
if ( isupper( string[i] ) )
{
uc++;
}else if ( islower( string[i] ) )
{
lc++;
}else{
others++;
}
I'm trying to make a Vigenere cipher code in C and I have done something that is wrong and I can't fix it... How do understand that something goes wrong? Well I have some examples with keyword and result cipher with Vigenere cipher like
keyword: bacon
text: Meet me at the park at eleven am
correct result: Negh zf av huf pcfx bt gzrwep oz
my code result with same text and keyword: Tegh ne og tjs qaty bt syfvgb bm
Code:
int main(int argc, string argv[])
{
string keyWord;
if( argc != 2 )
{
printf("Wrong Argument");
return 1;
}
else
{
keyWord = argv[1];
//check if argument is
//only alphabetical characters
for(int i = 0; i < strlen(keyWord); i++)
{
char c = keyWord[i];
if( !isalpha(c) )
{
printf("Your Keyword Must Contain Only alphabetical characters\n");
return 1;
}
}
}
//todo
printf("Enter Plain Text\n");
string plainText = GetString();
for(int i = 0; i < strlen(plainText); i++)
{
char c = plainText[i];
int keyWordWrapper;
char keyC;
if(isalpha(c))
{
keyWordWrapper = i % strlen(keyWord);
keyC = keyWord[keyWordWrapper];
if(islower(c))
{
int key = keyC - 'a';
c = (c - 'a' + key) % 26 + 'a';
}
if(isupper(c))
{
int key = keyC - 'A';
c = (c - 'A' + key) % 26 + 'A';
}
}
printf("%c",c);
}
printf("\n");
return 0;
}
GetString() is declared in a header and defined in a library that I'm using (it's like scanf).
this is the updated code
int main(int argc, string argv[])
{
string keyWord;
if( argc != 2 )
{
printf("Wrong Argument");
return 1;
}
else
{
keyWord = argv[1];
//check if argument is
//only alphabetical characters
for(int i = 0; i < strlen(keyWord); i++)
{
char c = keyWord[i];
if( !isalpha(c) )
{
printf("Your Keyword Must Contain Only alphabetical characters\n");
return 1;
}
}
}
string plainText = GetString();
int j;
for(int i = 0; i < strlen(plainText); i++)
{
j++;
char c = plainText[i];
int keyWordWrapper;
char keyC;
if(j > strlen(keyWord))
j = 0;
if(isalpha(c))
{
keyWordWrapper = i % strlen(keyWord);
keyC = keyWord[keyWordWrapper];
int key;
tolower(c);
if(islower(keyC))
key = keyC - 'a';
if(isupper(keyC))
key = keyC - 'A';
c = (c - 'a' + key) % 26 + 'a';
}
printf("%c",c);
}
printf("\n");
return 0;
}
There are two problems in the code.
First is the treatment of upper case letters in the keyword. Note that in one case, the code subtracts a from keyC, and in the other A is subtracted. But that's based on the case of the plain text character. That subtraction needs to be based on the case of the letter in the keyword.
Second, the code advances to the next character in the keyword for every character in the plain text. The "correct result" doesn't advance to the next character of the keyword if the plain text character is a space character.
Here's an example of what I'm talking about for the second problem
text Meet me at
keyC baco nb ac
i 0123456789 i must always increment to the next char in plain text
k 0123 40 12 index into the keyword does not increment on non-alpha
Therefore k cannot be computed directly from i with the line
keyWordWrapper = i % strlen(keyWord);
Instead k needs to be initialized to 0 and then incremented only when the plain text contains an alpha character. The following line will compute the correct index into the keyword.
keyWordWrapper = k % strlen(keyWord);
The only difference is that i is replaced by k and k only increments when the plain text has an alpha character.
You should convert the key to all lower case (or all upper case) and then use the same expression in both shift blocks:
int key = keyC - 'a'; // Or 'A' if you convert to upper
You should remove the strlen(plainText) from the condition of the for loop; it converts a linear algorithm into a quadratic one.