What does ++letter[c - 'A']; mean in this C program? - c

I have the following program which counts the number of occurrences of every uppercase letter from a text file.
I am commenting every line to understand what is happening with the program when it's executed, however I got lost in the following line ++letter[c - 'A'];. I cannot get it, I think it's suppose to collect the letter and store the cum sum of the occurrence of this letter. But the notation c - 'A', it's a bit alien for me.
void main(argc,argv)
int argc;
char *argv[];
{
int c, i, letter[26];
FILE *ifp, *ofp, *fopen(); // pointers to in file and output file pointer
if (argc != 3) /* if the number of arguments is not equal to 3 */
printf("\nusage: %s infile outfile\n\n", argv[0]); // prints the following
// message "usage letter infile outfile */
else { // if the number of arguments is three
ifp = fopen(argv[1], "r"); // opens the first file (pointer to file
// in reading mode //
ofp = fopen(argv[2], "w"); // then opens the the second argument "second
// file in writting mode. //
for (i = 0; i < 26; ++i) /* initialize array to zero */
letter[i] = 0; // makes every element in the array of 26 to 0, in other
// words the counter for every letter to 0
while (( c=getc(ifp)) != EOF) // gets the characters (next of a file)
if ('A' <= c && c <= 'Z') // if the character found is an uppercase
// character between A and Z
++letter[c - 'A']; //
for (i = 0; i < 26; ++i) {
if (i % 6 == 0)
fprintf(ofp, "\n");
fprintf(ofp, "%5c: %5d", 'A' + i, letter[i]);
}
fprintf(ofp, "\n\n");
}
}

It counts the number of occurrences of each letter.
'A' is just a number. On an ASCII-based machine, 'A' is just another way of writing 65.
In ASCII, the 26 latin uppercase letters are found consecutively, so,
'A'-'A' = 0
'B'-'A' = 1
'C'-'A' = 2
...
'Z'-'A' = 25
(Note that this code doesn't work on EBCDIC machines because the letters aren't contiguous in that encoding.)
So letter[c - 'A'] produces a unique element of letter for each letter.
Finally, ++x increments the value of x, so ++letter[c - 'A'] increments the element of letter that corresponds to the letter in c.
For example, if we read in ABRACADABRA, we'll end up with
int letter[26] = {
/* A B C D E F G H I J K L M */
5, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* N O P Q R S T U V W X Y Z */
0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0
};

regarding:
if ('A' <= c && c <= 'Z')
++letter[c - 'A'];
would be much better written as:
if( isupper( c ) )
{
letter[ c-'A' ]++;
}
where isupper() is exposed via the header file ctype.h
regarding:
for (i = 0; i < 26; ++i)
letter[i] = 0;
can be eliminated IF this:
int c, i, letter[26];
had been written as:
int c, i, letter[26] = {0};
Now for your question:
letter[] is an array for all the capital (ASCII) alphabet where letter[0] is a counter for the letter A.... letter[25] is a counter for the letter Z.
This calculation:
[ c-'A' ]
is taking the ordinal value in the variable c and subtracting the ordinal value of the capital letter A. I.E. if c contains A then the result is 0 (which matches the index for the letter A in the array letter[]
The ++ says to increment the value in the array letter[]
The overall result is the entry in the array letter[] for the current letter in c will be incremented, thereby keeping a count of the number of occurrences of each capital letter encountered in the input

In the program there is declared an array
int c, i, letter[26];
that is evidently used to count letters in an input file.
In this loop
while (( c=getc(ifp)) != EOF) // gets the characters (next of a file)
if ('A' <= c && c <= 'Z') // if the character found is an uppercase
// character between A and Z
++letter[c - 'A']; //
if the character c contain a symbol between letters ['A', 'Z'] then to get the index in the array there is used the expression c - 'A'. For example if c is equal to 'A' then the expression will yield 0. If c is equal to 'B' then the expression will yield 1/ And so on. SO the element of the array with the index 0 corresponds to the letter 'A'. The element of the index 1 corresponds to the letter 'B'. The value of the element is increased in this statement
++letter[c - 'A'];
So each element of the array accumulate the frequency of the corresponding letter encountered in the input file.

Your array
int letter[26];
is supposed to contain a counter for each capital letter.
In ASCII representation every character is represented by a 8 bit integer (base type char). And capital letters are represented by the compact range [65-90]:
A is represented by value 65
B is represented by value 66
... and so on
So, how to translate the input char to the index of your array of counters? Just by calculating c - 'A': its value will be 0 for A, 1 for B and so on.
In conclusion, ++letter[c - 'A'] just increments the counter corresponding to character c.

c is the character code that was read from the file. 'A' is the character code of the letter A. So c - 'A' subtracts those two codes.
This takes advantage of the design that character codes for letters are sequential. So when c is 'D', c - 'A' will be 3.

ASCII Value of 'A' is 65.
c is the character code that was read from the file.
So when we write ++letter[c-'A']
here c gives us current character which also have some ASCII value.
Suppose c is 'B' ASCII code is 66
Then we will increase count of index (66-65)that is 1.

Related

Don't understand this unfamiliar syntax: arr1[ arr2[i] - 'a' ]++

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.

How to calculate the frequency of a character in a string in C

I have found code that calculate the frequency of a character in a string, however, all of them are using the same line of code and don't explain what it means. Can someone please enlighten me?
Here is an example:
int c = 0, count[26] = {0}, x;
while (string[c] != '\0') {
/** Considering characters from 'a' to 'z' only and ignoring others. */
if (string[c] >= 'a' && string[c] <= 'z') {
x = string[c] - 'a';
count[x]++;
}
I understand that the loop will iterate through the string until it reaches the end.
I also get the if statement, as that only limits it between a and z.
However, I have no idea what x = string[c] -'a' is doing, why is it subtracting 'a'?
I also don't understand what the purpose of count[26] is.
Here is where I got this program from:
https://www.programmingsimplified.com/c-program-find-characters-frequency
Any help would be great thanks.
TL;DR Is taken advantage of the ASCII table.
The code only accepts characters from a to z:
if (string[c] >= 'a' && string[c] <= 'z')
therefore it creates an array with 26 positions (i.e., count[26]) to store the frequency of those same characters. The following
x = string[c] - 'a';
converts string[c] into an int; fact which can be used to take advantage of the ASCII table.
According to the ASCII table the letters 'a' to 'z' are represented by the int values from 97 to 112, respectively. Therefore, because arrays in C start with 0 we need to shift 97 elements to the left from the value that will be return by string[c], namely:
x = string[c] - 97;
which can be represented by
x = string[c] - 'a';
With this trick if string[c] is 'a' then :
x = 'a' - 'a';
which is converted to x = 97 - 97, then x = 0; Therefore,
count[x]++; is count[0]++;
which increments by 1 the position 0 of the array count, which is "reserved" to the letter 'a'. This same logic applies to all the other letters from 'a' to 'z'.
Bear in mind, however, and quoting Eric Postpischil:
The character codes used in C implementations do not necessarily have
all the letters consecutively. ASCII does and is very common, but not
required by the standard.
Hence, this solution will work if your encoding is ASCII.
count[26] is the frequency table. count[0] is the number of occurrences of a. count[1] is the number of occurrences of b, etc...
Initialize the count array to all zero values
count[26] = {0}
While not at the end of the string. Remember, C strings always end with a null char (\0).
while (string[c] != '\0') {
Evaluate if the character at string[c] is between a and z
if (string[c] >= 'a' && string[c] <= 'z') {
Normalize the ascii value of this character (which will be between 97 and 122) to a value from 0 to 25. a is 97 when evaluated in a math expression.
x = string[c] - 'a';
Using the x value computed above, use that as an index into the count table
Increment whatever value that is in count[x] by 1.
count[x]++;
What's missing from this code sample is the place where c gets incremented by 1 such that string[c] is referencing the next character in the string.
In the ASCII data base, 'a' to 'z' have consecutive numerical code from 0x61 to 0x7A. cf. man ascii.
Hence, if you substract the value of 'a', you get numbers from 0 to 25. This number is an index in count[] table.
count[26] is an array of 26 integers, each one represent the count of a lowercase letter from 'a' to 'z' from within string
count[0] is the counter for 'a', count[1] is the counter for 'b' etc...
x = string[c] - 'a' calculates and assign to x the index 0-25 for the char found at string[c].
Simplifyng: remember that 'a' is the integer ascii value 97 decimal. The subtraction of 'a' is to reduce all indexes from 'a' to 'z' to a value from 0 to 25 needed for the count[] array.
First, that code depends on the characters 'a' through 'z' being represented consecutively, something that's common but not guaranteed.
Second,
int c = 0, count[26] = {0}, x;
while (string[c] != '\0') {
/** Considering characters from 'a' to 'z' only and ignoring others. */
if (string[c] >= 'a' && string[c] <= 'z') {
x = string[c] - 'a';
count[x]++;
}
has several issues and I'd say is more clear as
#include <ctype.h>
// multiple variables on one line is ***very*** bug prone
// so don't do it
int c = 0;
int count[26] = {0};
// set the input - unsigned is important
unsigned char *string = ...;
// loop until the character pointed at by string is '\0'
while ( *string )
{
// islower() returns non-zero only if the unsigned char value
// passed is a lower-case letter.
//
// If the input int value can't be represented as an unsigned
// char the results are undefined behavior (because tolower()
// actually takes an int argument.)
//
// signed char will be sign-extended when passed as an int argument
if ( islower( *string ) )
{
// get the "index" of the lower-case letter
// a -> 0, b -> 1, z -> 25
// depends on a-z being consecutive - not necessarily true
int x = *string - 'a';
// increment the number of times this lower-case character
// is in this string
count[x]++;
}
// go to the next character in the string
string++;
}
Note that there is zero effort on my part to reduce the number of lines used. You gain nothing by cramming code into fewer lines, but you will make the code harder to read and therefore more bug prone.
A better way to count characters in a string:
#include <limits.h>
void countChars( unsigned char *string )
{
int counts[ UCHAR_MAX ] = { 0 };
while ( *string )
{
counts[ *string ]++;
string++;
}
}
If you want to count lower-case characters:
#include <limits.h>
void countLowerCaseChars( unsigned char *string )
{
int counts[ UCHAR_MAX ] = { 0 };
while ( *string )
{
counts[ tolower( *string ) ]++;
string++;
}
}

Problems with sums of chars in C

I'm very new to C so I'll make it quick: I'm making a Caesar's Cipher but at some point it starts giving me ? symbols.
#include <stdio.h>
#include <ctype.h>
int main(void){
char c;
int k;
printf("Inserisci la chiave di cifratura: ");
scanf("%d", &k);
if (k > 26)
k = (k%26);
printf("%d", k);
while ((c=getchar()) != '.') {
if (isalpha(c)) {
if (c >= 'a' && c <= 'z') {
c = c + k;
if (c > 'z') {
c = c - 'z' + 'a' - 1;
}
}
else if (c >= 'A' && c <= 'Z') {
c = c + k;
if (c > 'Z') {
c = c - 'Z' + 'A' - 1;
}
}
putchar(c);
}
else
putchar(c);
}
printf("\n");
return 0;
}
If k is 6, it starts giving me the symbol with z.
If it is 7, it start with y.
Etc...
I can't find anything around, thank you to whoever helps me.
When you use char, it's implementation-defined whether it's treated as signed char or unsigned char. Your implementation apparently defaults to signed char. The value of 'z' is 122, and when you add 6 to this you get 128, which overflows and causes undefined behavior. The maximum value of signed char is 127.
You should declare c to be int or unsigned char.
Your solution ensures the offset k is in the range of 0 through 26. You can get the correct solution if your offset is in the range of 0 through 25. An offset of 26 should produce the same results as an offset of 0.
When calculating the offset character you simply add K and then try to use addition to adjust for values greater than 'z' or 'Z'. You can adjust the value without the use of another set of conditional statements using the modulus operator.
Since this appears to be a homework problem I have created a solution in Ada rather than C. You can translate the logic into C.
with Ada.Text_Io; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Main is
subtype Offset is Natural range 0..25;
K : Offset;
C : Character := ' ';
Code : Natural;
adjusted : Character;
begin
Put("Enter the letter shift amount: ");
Get(K);
Put_Line("Specified offset is" & K'Image);
while C /= '.' loop
Get(C);
if C in 'a'..'z' then
Code := (Character'Pos(C) - Character'Pos('a') + k) mod 26;
adjusted := Character'Val(Code + Character'Pos('a'));
Put(adjusted);
elsif C in 'A'..'Z' then
Code := (Character'Pos(C) - Character'Pos('A') + k) mod 26;
adjusted := Character'Val(Code + Character'Pos('A'));
Put(adjusted);
else
Put(C);
end if;
end loop;
end Main;
Ada does not allow arithmetic directly on characters. Instead it allows arithmetic on the "position" of the character, which is a numeric value. The function Character'Pos(C) returns the numeric position of the character stored in variable C. The function Character'Val() returns the character corresponding to a specified numeric value.

C beginner: Need explanation of error messages from "ideone"

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 - ' ');
}

Cipher text in C,How to repeat key characters

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.

Resources