Explanation
The ciphertext is generated from the plaintext by “adding” corresponding characters of the plaintext and the key together. If the plaintext is shorter than the key, only some of the key will be used. Similarly, if the plaintext is shorter than the key, the key will be used multiple times.
For example, to encode the plaintext “HELLO” with the key “CAT”:
Plaintext: HELLO
Key: CATCA
Ciphertext: KFFOP
And to encode the plaintext “DOG” with the key “FIDO”:
Plaintext: DOG
Key: FID
Ciphertext: JXK
To add two letters together, use the following convention: A=1, B=2, …, Z=26. If the sum of two letters is greater than 26, subtract 26 from the sum. For example: A + E = 1 + 5 = 6 = F, and D + X = 4 + 24 = 28 = 2 = B.
Now the problem with my code is that i am unable to repeat the key characters for further coding of plain text if key characters are less,how to repeat the key characters,so further coding can possible?
Help me guys.
Here is my code:
#include<stdio.h>
#include<string.h>
int main()
{
char str[100],k[50],str1[100];
int i,n;
gets(str);// Input plain text.
gets(str1);//Input key.
for(i=0;str[i]!='\0';i++)
{
n=(str[i]-65+1)+(str1[i]-65+1);//Extracting the numerical position and adding them.
if(n>26) //if numerical value exceeds 26 then subtracting 26 from it and getting the numerical value.
{
n=n-26;
}
str[i]=n+64;//storing the ciphered character.
}
for(i=0;str[i]!='\0';i++)//printing the ciphered characters.
printf("%c",str[i]);
return 0;
}
You can use another loop variable an make the index of the key 0 every time it reaches its length. I have used variable j in this case. Try this code:
#include<stdio.h>
#include<string.h>
int main()
{
char str[100],k[50],str1[100];
int i,n;
gets(str);// Input plain text.
gets(str1);//Input key.
int lenk=strlen(str1),j; //calculate length of key
for(i=0,j=0;str[i]!='\0';i++,j++)
{
if(j==lenk) j=j-lenk; //make j=0
n=(str[i]-65+1)+(str1[j]-65+1); // add str1[j] instead
if(n>26)
{
n=n-26;
}
str[i]=n+64;//storing the ciphered character.
}
for(i=0;str[i]!='\0';i++)
printf("%c",str[i]);
return 0;
}
NOTE THAT THIS WORKS ONLY FOR CAPITAL LETTER, YOU HAVE TO CHANGE YOUR CODE FOR SMALL LETTERS
While writing the loop, the variable used to index the key should be reset to 0 in order to repeat the key (if original text length is larger).
for(int i = 0, j = 0; input[i] != '\0'; ++i, ++j) {
new_char = (input[i] - 64) + (key[j] - 64);
new_char = adjust(new_char);
cipher[i] = new_char + 64 ;
if(j == (key_length - 2)) // if j is at the end, excluding null character, then make j = -1, which gets incremented to j = 0 in the next loop iteration
j = -1;
}
Also use fgets for string input and dont use gets. Strings in C can be printed using the %s format specifier without writing an explicit loop to output the characters. For that make the last element of the cipher char array as the \0 character.
You could also use modular arithmetic to repeat the characters.
for(i=0;str[i]='\0';i++)
{
n = (str[i]-65+1 + (str1[i % lenk]-65 +1);
n = (n % 26) + 1;
str[i] = n+64;
//storing the ciphered character.
}
The expression i % 26 automatically rotates the value 0 through 25.
The same can be applied to rotate n from 1 to 26.
Related
My code seems to be working properly except at the point when it should print the final output. The problem is to input a string and output an encrypted version. The encryption works by adding an int defined as the key and then adding that value to each character of the ascii values of the inputed string. My issue is that when the cypher text is outputted there are only spaces and no letters or even numbers.
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, string argv[]) {
int key = atoi(argv[1]);
printf("%i\n", key);
if (argc != 2) {
printf("Usage: ./ceasar key\n");
} else {
string text = get_string("Plaintext: ");
for (int i = 0, len = strlen(text); i < len; i++) {
int cipher = text[i];
int ciphertext = cipher + key;
int ciphermod = ciphertext % 26;
printf("%c", ciphermod);
}
printf("\n");
}
}
You've got a few issues going on here. Please make sure to thoroughly read the assignment before turning to others for assistance.
The assignment requires you to:
Only encode alphabetic characters. Look to the function isalpha() for this.
Encode both uppercase and lowercase characters accurately. Note that, in ASCII, uppercase letters and lowercase letters are separate entities.
Meaning, you must have your code be able to handle both, as they are each handled differently.
Perhaps taking some time to sit and take in the ASCII table may be helpful to you, as it will help you understand what is really happening when you add the key.
Use the correct formula for encoding letters. The i'th ciphered letter ci corresponding to the i'th plaintext letter pi is defined as ci = (pi + k) % 26.
Your code is equivalent to this formula, but it does not account for wrapping, uppercase/lowercase letters, etc. The project specification doesn't just ask you to repeat the formula, it asks you to solve a problem using it. To do so, you must understand it. I explain more, subsequently.
I recommend:
Modifying the text in-place. Currently, you calculate the ciphered text and print it. If you add code for modifying the text where it sits, it'll make ignoring non-alphabetic characters easier.
Modify the formula.
Where 𝚨 is the ASCII character code for the beginning of either the uppercase or lowercase characters, the formula might shake out as follows:
ci = (pi - 𝚨 + k) % 26 + 𝚨
What this modified formula does is first take the ASCII code for Pi and turn it into a number that represents which letter in the alphabet it is, ignoring case. Then, you can add the key(shift the cipher). Using % 26 on this result then makes sure that the result is between 1 and 26—always a letter. Finally, we add back 𝚨 so that the character has a case again.
Here's the modified code with the solution broken down, step by step:
// ...
for (int i = 0, n = strlen(text); i < n; i++) {
if (!isalpha(text[i])) continue;
if (isupper(text[i])) {
// the letter's ASCII code on its own.
int charcode = text[i];
// the letter's index in the alphabet. A = 0, B = 1, etc.
// this is no longer a valid ASCII code.
int alphabet_index = charcode - 'A';
// the letter's index in the alphabet, shifted by the key.
// note, this may shift the letter past the end/beginning of the alphabet.
int shifted_alphabet_index = alphabet_index + key;
// the letter's index in the alphabet, shifted by the key, wrapped around.
// the modulo operator (%) returns the remainder of a division.
// in this instance, the result will always be between 0 and 25,
// meaning it will always be a valid index in the alphabet.
int shifted_index_within_alphabet = shifted_alphabet_index % 26;
// this is the final ASCII code of the letter, after it has been shifted.
// we achieve this by adding back the 'A' offset so that the letter is
// within the range of the correct case of letters.
int final_shifted_charcode = shifted_index_within_alphabet + 'A';
text[i] = final_shifted_charcode;
}
else { // islower
int charcode = text[i];
int alphabet_index = charcode - 'a';
int shifted_alphabet_index = alphabet_index + key;
int shifted_index_within_alphabet = shifted_alphabet_index % 26;
int final_shifted_charcode = shifted_index_within_alphabet + 'a';
text[i] = final_shifted_charcode;
}
}
printf("ciphertext: %s\n", text);
// ...
And here is the solution, simplified down:
// ...
for (int i = 0, n = strlen(text); i < n; i++) {
if (!isalpha(text[i])) // if not alphabetic, skip
continue; //
if (isupper(text[i])) // if uppercase
text[i] = (text[i] - 'A' + key) % 26 + 'A'; //
else // if lowercase
text[i] = (text[i] - 'a' + key) % 26 + 'a'; //
}
printf("ciphertext: %s\n", text);
// ...
Just as a side note, the statement if (!isalpha(text[i])) is acting like something called a guard clause. This is a useful concept to know. Using guard clauses allows you to have simpler, more readable code. Imagine if I had nested all of the code inside the for loop under the if (isalpha(text[i])) condition. It would be harder to read and understand, and difficult to match up the different bracket pairs.
Edit: I would also echo what chqrlie said. Do not use argv[n] until you have verified that argc >= (n + 1)
The formula to compute the ciphered characters is incorrect:
you should only encode letters
you should subtract the code for the first letter 'a' or 'A'
you should add the code for the first letter 'a' or 'A' to the encoded index.
Note also that you should not use argv[1] until you have checked that enough arguments have been passed.
Here is a modified version:
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, string argv[]) {
if (argc != 2) {
printf("Usage: ./ceasar key\n");
} else {
int key = atoi(argv[1]);
printf("%i\n", key);
string text = get_string("Plaintext: ");
for (int i = 0, len = strlen(text); i < len; i++) {
int c = text[i];
if (c >= 'a' && c <= 'z') {
int cipher = c - 'a';
int ciphertext = cipher + key;
int ciphermod = ciphertext % 26;
c = 'a' + ciphermod;
} else
if (c >= 'A' && c <= 'Z') {
int cipher = c - 'A';
int ciphertext = cipher + key;
int ciphermod = ciphertext % 26;
c = 'A' + ciphermod;
}
printf("%c", c);
}
printf("\n");
}
return 0;
}
I am looking at a program that finds the frequency of strings entered. Comparison is made based on a string's ASCII value against the ASCII value of lowercase 'a'. I have implemented it; it works, albeit, with a bug, but essentially, I am ignorant of a particular line of code;
for (int i = 0; i < strlen(arr2); i++)
{
// this line...
arr1[ arr2[i] - 'a' ]++;
}
arr1 is arr1[26] = {0},
that is, all the letters of the alphabet are assigned an index and the array is initialised to zero, while arr2[] as a function argument, receives the stdin.
How does the mysterious line of code work and what is it saying?
The full code:
#include <stdio.h>
#include <string.h>
#define ALEPH 26
void freq(char arr2[]);
int main ()
{
char * str;
printf("\nCharacter Frequency\n"
"--------------------\n");
// user input
printf("\nEnter a string of characters:\n");
fgets(str, ALEPH, stdin);
freq(str);
return 0;
}
// Function Definiton
void freq (char arr2[])
{
// array for ascii characters initialised to 0
int arr1[ALEPH] = {0};
// scan and cycle through the input array
for (int i = 0; i < strlen(arr2); i++)
{
arr1[ arr2[i] - 'a' ]++;
}
for (int j = 0; j < 26; j++)
{
if ( arr1[j] != 0 )
{
printf("\nCharacter: %c - Frequency: %d", 'a'+j, arr1[j]);
}
}
printf("\n");
}
arr1 is an array of 26 ints initialized to 0s. The indexes of its elements are 0..25.
arr2 is assumed to be a string of lowercase letters 'a'..'z' only. The characters are assumed to be using an encoding where lowercase letters are single-byte and sequential in value, such as ASCII (where a=97, ..., z=122). Anything else that does not match these assumptions will cause undefined behavior in this code.
The code loops through arr2, and for each character, calculates an index by subtracting the numeric value of 'a' (ie, ASCII 97) from the character's numeric value:
'a' - 'a' = 97 - 97 = 0
'b' - 'a' = 98 - 97 = 1
...
'z' - 'a' = 122 - 97 = 25
Then the code accesses the arr1 element at that index, and increments that element's value by 1.
You ask about the line:
arr1[ arr2[i] - 'a' ]++;
In this line:
arr1 is the array that will accumulate the histogram
arr2 is the input string which will contribute to the histogram
i is the index into input string.
This can be rewritten as:
ch = arr2[i];
histogram_slot = ch - 'a';
arr1[histogram_slot ] = arr1[histogram_slot ] + 1;
For each character in the input string, the character is fetched from the string and assigned to "ch". "ch" is converted to the index in the histogram array by subtracting 'a'. In the third line, the histogram_slot is increased by one. histogram_slot 0 is incremented for 'a', 1 for 'b', 2 for 'c', ... , and 25 for 'z'.
A serious bug in this code is that it only works for the lower case letters. An upper case letter, digit, punctuation, Unicode, extended ASCII, or any character not between 'a' and 'z' inclusive will write in an unintended region of memory. At the best, this will cause an unexpected crash. In the medium disaster, it will cause sporatic malfunction that gets through your testing. In the worst case, it creates a security hole allowing someone uncontrolled access to your stack, and thus the ability to take over execution of the thread.
I am attempting to write a program that accepts grammatically incorrect text (under 990 characters in length) as input, corrects it, and then returns the corrected text as output. I attempted to run the program using the online compiler, "ideone", but it returned quite a few errors that I don't quite understand. I have posted my code, as well as a picture of the errors below. Can anybody explain to me what exactly the errors mean?
#include "stdio.h"
char capitalize(int i); //prototype for capitalize method
int main(void)
{
char userInput[1200]; //Array of chars to store user input. Initialized to 1200 to negate the possibility of added characters filling up the array.
int i; //Used as a counter for the for loop below.
int j; //Used as a counter for the second for loop within the first for loop below.
int numArrayElements;
printf("Enter your paragraphs: ");
scanf("%c", &userInput); //%c used since chars are expected as input(?)
numArrayElements = sizeof(userInput) / sizeof(userInput[0]); //stores the number of elements in the array into numArrayElements.
if (userInput[0] >= 97 && userInput[0] <= 122) //Checks the char in index 0 to see if its ascii value is equal to that of a lowercase letter. If it is, it is capitalized.
userInput[0] = capitalize(userInput[0]);
//code used to correct input should go here.
for (i = 1; i < numArrayElements; i++) //i is set to 1 here because index 0 is taken care of by the if statement above this loop
{
if (userInput[i] == 32) //checks to see if the char at index i has the ascii value of a space.
if (userInput[i + 1] == 32 && userInput[i - 1] != 46) //checks the char at index i + 1 to see if it has the ascii value of a space, as well as the char at index i - 1 to see if it is any char other than a period. The latter condition is there to prevent a period from being added if one is already present.
{
for (j = numArrayElements - 1; j > (i - 1); j--) //If the three conditions above are satisfied, all characters in the array at location i and onwards are shifted one index to the right. A period is then placed within index i.
userInput[j + 1] = userInput[j];
userInput[i] = 46; //places a period into index i.
numArrayElements++; //increments numArrayElements to reflect the addition of a period to the array.
if (userInput[i + 3] >= 97 && userInput[i + 3] <= 122) //additionally, the char at index i + 3 is examined to see if it is capitalized or not.
userInput[i + 3] = capitalize(userInput[i + 3]);
}
}
printf("%c\n", userInput); //%c used since chars are being displayed as output.
return 0;
}
char capitalize(char c)
{
return (c - 32); //subtracting 32 from a lowercase char should result in it gaining the ascii value of its capitalized form.
}
Your code hase several problems, quite typical for a beginner. Teh answer to teh question in your last commenst lies in the way scanf() works: it takes everything between whitepsaces as a token, so it just ends after hey. I commented the code for the rest of the problems I found without being too nitpicky. The comments below this post might do it if they fell so.
#include "stdlib.h"
#include "stdio.h"
#include <string.h>
// Check for ASCII (spot-checks only).
// It will not work for encodings that are very close to ASCII but do not earn the
// idiomatic cigar for it but will fail for e.g.: EBCDIC
// (No check for '9' because non-consecutive digits are forbidden by the C-standard)
#if ('0' != 0x30) || ('a' != 0x61) || ('z' != 0x7a) || ('A' != 0x41) || ('Z' != 0x5a)
#error "Non-ASCII input encoding found, please change code below accordingly."
#endif
#define ARRAY_LENGTH 1200
// please put comments on top, not everyone has a 4k monitor
//prototype for capitalize method
char capitalize(char i);
int main(void)
{
//Array of chars to store user input.
// Initialized to 1200 to negate the possibility of
// added characters filling up the array.
// added one for the trailing NUL
char userInput[ARRAY_LENGTH + 1];
// No need to comment counters, some things can be considered obvious
// as are ints called "i", "j", "k" and so on.
int i, j;
int numArrayElements;
// for returns
int res;
printf("Enter your paragraphs: ");
// check returns. Always check returns!
// (there are exceptions if you know what you are doing
// or if failure is unlikely under normal circumstances (e.g.: printf()))
// scanf() will read everything that is not a newline up to 1200 characters
res = scanf("%1200[^\n]", userInput);
if (res != 1) {
fprintf(stderr, "Something went wrong with scanf() \n");
exit(EXIT_FAILURE);
}
// you have a string, so use strlen()
// numArrayElements = sizeof(userInput) / sizeof(userInput[0]);
// the return type of strlen() is size_t, hence the cast
numArrayElements = (int) strlen(userInput);
// Checks the char in index 0 to see if its ascii value is equal
// to that of a lowercase letter. If it is, it is capitalized.
// Do yourself a favor and use curly brackets even if you
// theoretically do not need them. The single exception being "else if"
// constructs where it looks more odd if you *do* place the curly bracket
// between "else" and "if"
// don't use the numerical value here, use the character itself
// Has the advantage that no comment is needed.
// But you still assume ASCII or at least an encoding where the characters
// are encoded in a consecutive, gap-less way
if (userInput[0] >= 'a' && userInput[0] <= 'z') {
userInput[0] = capitalize(userInput[0]);
}
// i is set to 1 here because index 0 is taken care of by the
// if statement above this loop
for (i = 1; i < numArrayElements; i++) {
// checks to see if the char at index i has the ascii value of a space.
if (userInput[i] == ' ') {
// checks the char at index i + 1 to see if it has the ascii
// value of a space, as well as the char at index i - 1 to see
// if it is any char other than a period. The latter condition
// is there to prevent a period from being added if one is already present.
if (userInput[i + 1] == ' ' && userInput[i - 1] != '.') {
// If the three conditions above are satisfied, all characters
// in the array at location i and onwards are shifted one index
// to the right. A period is then placed within index i.
// you need to include the NUL at the end, too
for (j = numArrayElements; j > (i - 1); j--) {
userInput[j + 1] = userInput[j];
}
//places a period into index i.
userInput[i] = '.';
// increments numArrayElements to reflect the addition
// of a period to the array.
// numArrayElements might be out of bounds afterwards, needs to be checked
numArrayElements++;
if (numArrayElements > ARRAY_LENGTH) {
fprintf(stderr, "numArrayElements %d out of bounds\n", numArrayElements);
exit(EXIT_FAILURE);
}
// additionally, the char at index i + 3 is examined to see
// if it is capitalized or not.
// The loop has the upper limit at numArrayElements
// i + 3 might be out of bounds, so check
if (i + 3 > ARRAY_LENGTH) {
fprintf(stderr, "(%d + 3) is out of bounds\n",i);
exit(EXIT_FAILURE);
}
if (userInput[i + 3] >= 97 && userInput[i + 3] <= 122) {
userInput[i + 3] = capitalize(userInput[i + 3]);
}
}
}
}
printf("%s\n", userInput);
return 0;
}
char capitalize(char c)
{
// subtracting 32 from a lowercase char should result
// in it gaining the ascii value of its capitalized form.
return (c - ' ');
}
For class, I am required to create a function that converts an Integer into it's corresponding Binary number. However, I am forced to use the given main and parameters for the to_binary function. The whole problem requires me to print out the 32 bit binary number, but to break it up, I am just trying to print out the Char Array, that I thought I filled with Integers (perhaps the issue). When I do compile, I receive just a blank line (from the \n) and I am wondering how I can fix this. All I want to do is to be able to print the binary number for 5 ("101") yet I can't seem to do it with my professor's restrictions. Remember: I cannot change the arguments in to_binary or the main, only the body of to_binary. Any help would be greatly appreciated.
#include<stdio.h>
void to_binary(int x, char c[]) {
int j = 0;
while (x != 0) {
c[j] x = x % 2;
j++;
}
c[33] = '\0';
}
int main() {
int i = 5;
char b[33];
to_binary(i,b);
printf("%s\n", b);
}
This is the answer to your question.
void to_binary(int x, char c[]) {
int i =0;
int j;
while(x) {
/* The operation results binary in reverse order.
* so right-shift the entire array and add new value in left side*/
for(j = i; j > 0; j--) {
c[j] = c[j-1];
}
c[0] = (x%2) + '0';
x = x/2;
i++;
}
c[i]=0;
}
the problem is in the code below:
while (x != 0) {
c[j] = x % 2; // origin: c[j] x = x % 2; a typo?
j++;
}
the result of x % 2 is a integer, but you assigned it to a character c[j] —— integer 1 is not equal to character '1'.
If you want to convert a integer(0-9) to a character form, for example: integer 7 to character '7', you can do this:
int integer = 7;
char ch = '0' + integer;
One of the previous answers has already discussed the issue with c[j] x = x % 2; and the lack of proper character conversion. That being said, I'll instead be pointing out a different issue. Note that this isn't a specific solution to your problem, rather, consider it to be a recommendation.
Hard-coding the placement of the null-terminator is not a good idea. In fact, it can result in some undesired behavior. Imagine I create an automatic char array of length 5. In memory, it might look something like this:
Values = _ _ _ _ _
Index = 0 1 2 3 4
If I were to populate the first three indexes with '1', '0', and '1', the array might look like so:
Values = 1 0 1 _ _
Index = 0 1 2 3 4
Let's say I set index 4 to contain the null-terminator. The array now looks like so:
Values = 1 0 1 _ \0
Index = 0 1 2 3 4
Notice how index three is an open slot? This is bad. In C/C++ automatic arrays contain garbage values by default. Furthermore, strings are usually printed by iterating from character to character until a null-terminator is encountered.
If the array were to look like it does in the previous example, printing it would yield a weird result. It would print 1, 0, 1, followed by an odd garbage value.
The solution is to set the null-terminator directly after the string ends. In this case, you want your array to look like this:
Values = 1 0 1 \0 _
Index = 0 1 2 3 4
The value of index 4 is irrelevant, as the print function will terminate upon reading index 3.
Here's a code example for reference:
#include <stdio.h>
int main() {
const size_t length = 4;
char binary[length];
size_t i = 0;
while (i < length - 1) {
char c = getchar();
if (c == '0' || c == '1')
binary[i++] = c;
}
binary[i] = '\0';
puts(binary);
return 0;
}
#include<stdio.h>
int binary(int x)
{
int y,i,b,a[100];
if(x<16)
{
if(x%2==1)
a[3]=1;
if(x/2==1||x/2==3 || x/2==5 || x/2==7)
a[2]=1;
if(x>4 && x<8)
a[1]=1;
else if(x>12 && x<16)
a[1]=1;
if(x>=8)
a[0]=1;
}
for(i=0;i<4;i++)
printf("\t%d",a[i]);
printf("\n");
}
int main()
{
int c;
printf("Enter the decimal number (less than 16 ):\n");
scanf("%d",&c);
binary(c);
}
this code might help it will simply convert the decimal number less than 16 into the 4 digit binary number.if it contains any error than let me know
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am attempting to make the vigenere cipher.
Information about it is here: https://www.youtube.com/watch?v=9zASwVoshiM
My code doesnt seem to work for a few cases.
My code is listed below please dont send me a link how to make the vigenere cipher but instead a way to fix mine. If I put the key as z for example it is value 25 acc to alphabet. Now if I put the to be encrypted text as c which is 2 the new text is of value 27 and should show b but for me it doesn't. So if the value exceeds 25 it doesn't show what I want else it works. And for the actual output example:
ab as key should change ca to cb
#include<stdio.h>
#include<cs50.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
int main( int argc , string argv[]){
//string plaintext;
string key;
if(argc != 2){
printf("Please run the programme again this time using a command line argument!\n");
return 1;
}
key = argv[1];
int keys[strlen(key)];
for(int m = 0; m< strlen(key);m++){
if(isalpha(key[m])==false){
printf("Re-Run The programme without any symbols.\n");
return 1;
}
}
for(int b = 0; b < strlen(key);b++){
if(isupper(key[b]) == false){
keys[b] = key[b] - 'a';
}
else{
keys[b] = key[b] - 'A';
}
}
//printf("Enter a string which should be encrypted: \n");
string plaintext = GetString();
int plength = strlen(plaintext);
int klength = strlen(key);
string ciphertext = key;
for(int u = 0; u<plength;u++){
if(isalpha(plaintext[u])==false){
printf("%c",plaintext[u]);
continue;
}
int value = u % klength;
ciphertext[u] = (keys[value] + plaintext[u]);
//By the more than 90 I am referring to 'z'
if(ciphertext[u]>90){
ciphertext[u] = ciphertext[u] ;
}
printf("%c",ciphertext[u]);
}
printf("\n");
return 0;
}
Thanks
Kalyan
You are correctly processing the value in the key by consistently substracting from its code the code of 'A' for an uppercase letter and 'a' for a lower case one. It gives you: A|a => 0, B|b => 1, ... , Z|z => 25. Fine till here...
But when encrypting, you are just adding this value to the code of a character without wrapping at any time.
Let us use your example: key is 'z' => value 25 in keys, fine. Take character 'c'. Its ASCII(*) code is 0x63 or 99. 99+25=124 giving in ascii table '|' ! To correctly wrap it, you must ensure that in any way 'z' + 1 => 'a'. You code could be
/* test wrapping for lowercase letters */
if ((islower(plaintext[u]) && (ciphertext[u]>'z')) {
ciphertext[u] = ciphertext[u] - 'z' + 'a' - 1;
}
/* same for uppercase */
if ((isupper(plaintext[u]) && (ciphertext[u]>'Z')) {
ciphertext[u] = ciphertext[u] - 'Z' + 'A' - 1;
}
(*) the example assumed ASCII code because it is the most common nowadays, but the code only assumes that all uppercase letters are in sequence and all lowercase letters are also in sequence without any requirement for their exact values nor the order of upper and lower case sequences.