What isn't working properly with my Vigenere cipher code? - c

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.

Related

substitution of one letter for another cipher key

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...

CS50 caesar.c - ciphertext printing out of ASCII code range

I'm going through CS50 (2021x version) of Caesar problem, and ran into problem. My program is printing outside of ASCII range (thanks to curiouskiwi over at discord for this hint). The error message says ":( encrypts "barfoo" as "yxocll" using 23 as key, output not valid ASCII text". Another one I'm having trouble is "world, say hello!", for same reason (Not valid ASCII text). Other ones are encrypting fine.
I've stepped through the debugger and found that 'letter' variable is sometimes becoming a negative integer like -119'/211', but can't figure out why that may be so. I expected to see positive value associated with an alphabet in ASCII. When this happens the letters will stop printing on the console.
If I type ./caesar 23 | cat -A and then give barfoo as plaintext, the cyphertext will come out as yxM-^IcM-^FM-^F$.
int main(int argc, string argv[])
{
// only 1 arugment, and positive argument only
if (argc == 2 && argv[1] > 0)
{
// check if each char of argument is digit
for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
if (isdigit(argv[1][i]))
{
// do nothing
}
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}
// change the key to how much letters should move over
int input = atoi(argv[1]);
int key = input % 26;
char letter;
// get the input
string text = get_string("plaintext: ");
printf("ciphertext: ");
for (int i = 0, n = strlen(text); i < n; i++)
{
if (isalpha(text[i])) // if it is an alphabet
{
if (islower(text[i])) // if it is lowercase
{
letter = text[i] + key; // add key to text[i]
if (letter > 122)
{
// loop around the alphabet
letter -= 26;
}
printf("%c", letter);
}
else // if it is uppercase
{
letter = text[i] + key; // add key to text[i]
if (letter > 90)
{
// loop around the alphabet
letter -= 26;
}
printf("%c", letter);
}
}
else // if it is not an alphabet
{
printf("%c", text[i]);
}
}
printf("\n");
}
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}
You should use int letter instead of char letter.
This is because
letter = text[i] + key;
will overflow signed char for, say, 'z' + 23.

How to put a group of changes to an array and then print all of them as one in C

I'm solving a coding problem currently. I must encipher a code and change words into other encoded words. I know I can check and print each character. However, I want to try to save the result of the checking of each character to an array, and then later I want to just print it.
Below is the full code... I deeply appreciate it if anyone can help me answer my question, or if it is even possible.
//one command line argument with the type int
int main(int argc, string argv[])
{
//setting condition that: K = +; if more or less than one, immediate error message, return 1
//if not decimal return = usage ./caesar. key, return value 1 to main
if (argc != 2)
{
printf("Error 404 : \n");
return 1;
}
//main program
else if ( argc == 2 && isdigit(*argv[1]))
{
int k = atoi(argv[1]);
string pltext = get_string("plaintext: "); //getting input for the plain text
char cptext[]
for (int i = 0, n = strlen(pltext) ; i < n; i++) //turning pltext to integer
{
if (pltext[i] >= 'a' && pltext[i] <= 'z')
{
cptext[i] = ((pltext[i] - 'a' + k)%26)+'a'; //shifting the integer with k (lowercase)
}
else if (pltext[i] >= 'A' && pltext[i] <= 'Z')
{
cptext[i] = ((pltext[i] - 'A' + k)%26)+'A'; //shifting the integer with k (uppercase)
}
else
{
cptext[i] = pltext[i]; //other symbol stays
}
}
//print out result
string cptext = ("test");
printf("ciphertext: %s\n", cptext[]);
}
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}
You should allocate an array according to the number of elements to be stored.
char cptext[]
should be
char cptext[strlen(pltext) + 1]; // +1 for terminating null-character
(variable-length array introduced in C99)
and
string cptext = ("test");
printf("ciphertext: %s\n", cptext[]);
should be
cptext[strlen(pltext)] = '\0'; // terminate the string
printf("ciphertext: %s\n", cptext); // remove extra []

CS50 Vigenere, code is almost done but I don't know what's missing?

#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc, string argv[])
{
// two arguments
if (argc != 2)
{
printf("Give two arguments\n");
return 1;
}
printf("plaintext: ");
string plaintext = get_string();
printf("ciphertext: ");
string key = argv[1];
for (int i = 0, t = 0, n = strlen(plaintext); i < n; i++, t++)
{
// if it's no letter, then:
if (!isalpha(plaintext[i]) && plaintext[i] != ' ')
{
printf("False");
return 1;
}
int number = 0;
if (isalpha(plaintext[i]))
{
number += 1;
}
if (strlen(key) > number)
{
number = 0;
}
if (isupper(plaintext[i]))
{
printf("%c", (((plaintext[i] - 65) + key[number]) % 26) + 65);
}
//if it is lowercase
else if (islower(plaintext[i]))
{
printf("%c", (((plaintext[i] - 97) + key[number]) % 26) + 97);
}
else
{
printf("%c", plaintext[i]);
}
}
printf("\n");
}
So there's something missing with my code. When I do ./vigenere baz and then type as plaintext: Hello, world!, I get ciphertext: ByffiFalse. I should be getting iekmo, vprke! Also, when I type ./vigenere hello, and then type bye as the plaintext, I get ciphertext bye too while it should be icp. Can someone figure out what's missing or wrong with my code?
The biggest two problems with your code are the calculating the correct key differential value (you're not), and key advancement. I'll talk about them in reverse order.
Key advancement should start with the first key character, then advance one by one with each plain text being processed. When the key position reaches end-of-string, it is restarted. The most basic pseudo code for that would be
char *keyp = argv[1];
for (loop through plainttext)
{
if (*keyp == 0) // reached the terminator ?
keyp = argv[1]; // then reset to beginning.
//... process the current plain text character, using *keyp
//... as the next key character to use.
// advance key to next position (possibly conditionally)
++keyp;
}
But your code doesn't do that. Rather, it advances the key immediately, meaning you're starting with the second character onward.
int number = 0;
if (isalpha(plaintext[i]))
{
number += 1; // HERE. first pass will use key[1]. it should be key[0]
}
if (strlen(key) > number) // this is backward
{
number = 0;
}
Secondly, and probably more important, the whole point if a Vigenere cipher is effectively using a square shading table. See this link for a picture of that. The point of the algorithm you're coding is to act like that table exists using math. The offsets are the important part.When you do this calculation:
(((plaintext[i] - 65) + key[number]) % 26) + 65
which in reality should look like this:
(((plaintext[i] - 'A') + key[number]) % 26) + 'A'
consider what that key character addition is doing. Take your example:
key: baz
plaintext: Hello, World!
The first ciphertext character by your calculation will be:
((('H' - 'A') + 'a') % 26) + 'A'
Note: the 'a' is there because your first-pass is broken by one, remember?
That crunches down as follows
(((7) + 97) % 26) + 'A'
((105) % 26) + 'A'
(1 % 26) + 'A'
1 + 'A'
'B'
And that's exactly what you're getting. But its wrong. Its wrong because this is wrong:
(((plaintext[i] - 'A') + key[number]) % 26) + 'A'
^^^^^^^^^^^
That's the raw ascii value of the input character. What it should be is a calculated value between 1..26. In short, you're not adjusting your key input correctly.
Assumptive Solution
The following assumes the key will always be lower-case. It also fixes your first-skip logic, and decouples using cs50.h (which, frankly, I think does more harm than good). Finally it uses a `char* to track which key character is being used next. I leave the task of supporting mixed case input keys to you:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(int argc, char *argv[])
{
// two arguments
if (argc != 2)
{
printf("Give two arguments\n");
return 1;
}
printf("plaintext: ");
char pt[256] = { 0 };
if (fgets(pt, sizeof pt, stdin))
{
// get the plaintext length
size_t ptlen = strlen(pt);
// remove trailing newline if present, and adjust ptlen
if (ptlen > 0 && pt[ptlen - 1] == '\n')
pt[--ptlen] = 0;
// the key we're using. intially at the start
char *key = argv[1];
for (size_t i = 0; i < ptlen; ++i)
{
// reset key if prior iteration landed on terminator
if (!*key)
key = argv[1];
if (isalpha((unsigned char)pt[i]))
{
if (isupper((unsigned char)pt[i]))
{
printf("%c", (((pt[i] - 'A') + (*key-'a')) % 26) + 'A');
++key;
}
//if it is lowercase
else if (islower((unsigned char)pt[i]))
{
printf("%c", (((pt[i] - 'a') + (*key-'a')) % 26) + 'a');
++key;
}
else
{
fputc(pt[i], stdout);
}
}
else
{
fputc(pt[i], stdout);
}
}
fputc('\n', stdout);
}
else
{
perror("Failed to read string");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Output from ./progname baz
plaintext: Hello, World!
Iekmo, Vprke!
All non-alpha characters (not spaces only) should be skipped without encoding. Do not print "False" and return on, for example ',' symbol in "Hello, world!" string. Also, you can encode string in-place. Thus, main loop may looks like
printf("plaintext: ");
string s = GetString();
if (s == NULL)
return 1;
for (int i = 0, len = strlen(s); i < len; ++i) {
if (isalpha(s[i])) {
/* encode s[i] in-place,
* all non-alpha characters left as is
*/
}
}
printf("ciphertext: %s\n", s);
Key characters should also be "shifted". For example, for uppercase letters
s[i] = ((s[i] - 'A') + (key[n] - 'A') % 26) + 'A';
if (++n >= keylen)
n = 0;
I suggest to normalize key before main loop, so that you will be able to use (key[n] - 'A') both for lower and upper characters from input string:
string key = argv[1];
strupper(k);
int keylen = strlen(key);
int n = 0;
Although I don't want provide full code because this is your courses, I think it would be better if you do it by yourself. But… some pieces:
strupper function:
void strupper(string s)
{
for (int i = 0, n = strlen(s); i < n; ++i)
s[i] = toupper(s[i]);
}
Compact main loop:
for (int i = 0, n = strlen(s); i < n; ++i) {
if (isalpha(s[i])) {
char ref = isupper(s[i]) ? 'A' : 'a';
int shift = k[j] - 'A';
s[i] = ref + (s[i] - ref + shift) % 26;
if (++j >= klen) j = 0;
}
}
p.s. You use the same key character for all input characters because of int number = 0; defined and zeroed inside for loop.

C - Encryption Algorithm

I'm trying to make a simple encryption program with C. My aim is to translate abc (it can be any word) to 123. Then multiply 2 and get 246 then again translate to text, then write on screen bdf. Here is my algorithm which is not working correctly. I entered abc and I got cbc. Can you help me?
int main()
{
int z,o,c,l,i,j,k,*D;
char word[10];
char alfabe[24]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','r','s','t','u','v','y','z','\0'};
printf("enter word");
scanf("%s",word);
c=strlen(word);
printf("has %d letters ", c);
D = (int *) malloc( sizeof(int)*c );
for(i=0;i<c;i++) {
for(j=0;j<26;j++) {
if(word[i]==alfabe[j]) {
D[i]=2*(j+1);
break;
}
}
}
printf("\nlast form before translation ");
for(l=0;l<c;l++) {
printf("%d",D[l]); /*it s just for control */
}
for(z=0;z<c;z++){
printf("%c",alfabe[o]);
o=D[z];
word[z]=alfabe[o] ; break; }
printf("\nnew form of word: ");
for(k=0;k<c;k++) {
printf("%c",word[k]);
}
scanf("%d");
}
The problem is in the following loop.
for(z=0;z<c;z++){
printf("%c",alfabe[o]);
o=D[z];
word[z]=alfabe[o] ;
break;
}
Why did you break? It just translates first character. Second, you need to subtract 1 to get the right index of alphabet array(to redo the addition you did).
word[z]=alfabe[o-1];
Third, you are using o before initializing it? Your compiler should warn you for this.
Fourth, why are you storing 27 characters in char array of size 24?
char alfabe[24]={'a','b',...........,'\0'}
And last but not least you need to use modular arithmetic, this wont work if user enters something like xyz.
OK, first of all '\0' marks the end of an inputed string, you don't need to encrypth this particular character, my suggestion is to place it first in the alfabet so you would get:
alfabet[24] = {'\0', 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','r','s','t','u','v','y','z'};
This will save you the trouble of substracting 1, so you will have:
for (i = 0; i < c; i++)
{
for (j = 0; j < 24; j++)
{
if (word[i] == alfabet[j])
{
D[i] = 2 * j;
}
}
}
In the part where you encode the input. And when you generate the output word:
for (z = 0; z < c; z++)
{
printf("%c", alfabet[D[z]]);
word[z] = alfabet[D[z]];
}
No need for o and especially no break; in the loop.
A more efficient way would be to create a function that handles the encryption of the string passed:
char* getEncryptedWord(char* word)
{
char alfabet[25]={'\0', 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','r','s','t','u','v', 'x', 'y','z'};
int i, j;
int size = strlen(word);
char* encryptedWord = (char*) malloc(size + 1);
for (i = 0; i < size; i++)
{
for (j = 0; j <= 25; j++)
{
if (word[i] == alfabet[j])
{
if (2 * j > 25)
encryptedWord[i] = alfabet[2 * j % 25];
else
encryptedWord[i] = alfabet[2 * j];
break;
}
}
}
encryptedWord[size] = '\0';
return encryptedWord;
}
I've added 'x' in the alfabet - that is the reason why now there are 25 elements. I'm sure there is one character of the English alphabet missing, but it's 3 AM here and English isn't my primary language. Also, this solution is working on the assumption that the alfabet you provided are the only characters that are supposed to exist in the input and output.
(tip: If you only expect letters A-Z, you don't need to loop through the array to find the corresponding number, you may simply get the number by subtracting the numerical value of 'a', and add 1, if you want the letter 'a' to map to 1.)
Modulo arithmetic is mentioned, but that will give you problems because you will loose the 1:1-mapping, i.e. two letters can end up being translated to the same number.

Resources