0

I am new to programming and I am trying to write a program in C for a Caesar Cipher.

Input consists of an integer ilength equal to the length of the string, followed by the string str and an integer encrypt.

My input is:

11
middle-Outz
2

Output:

okffng-Qwv@

Required output is:

okffng-Qwvb

Below is the code I have written. Could someone help me why I am getting the last character wrong in the output!

I'm totally clueless.

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main()
{
 int ilength = 0, encrypt = 0, i = 0, j = 0;
 char alph_base[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'X', 'Y', 'Z', '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'};
 scanf("%d", &ilength);
 char str[ilength + 1];
 scanf("%s", str);
 scanf("%d", &encrypt);
 //printf("%c\n", str[5]);
 char outputString[ilength + 1];
 char temp[ilength + 1];
 for (j = 0; j <= ilength; j++)
 {
 temp[j] = str[j];
 i = 0;
 if (str[j] == '0円')
 {
 outputString[j] = '0円';
 }
 while ((i >= 0) && (i < 26))
 {
 if (temp[j] == alph_base[i])
 {
 if (i == 25 && encrypt == 0)
 {
 outputString[j] = alph_base[25];
 }
 if ((i + encrypt) == 26)
 {
 outputString[j] = alph_base[(i + encrypt) % 26];
 }
 else
 outputString[j] = alph_base[(i + encrypt) % 26];
 }
 if ((temp[j] < 65 || temp[j] > 90) && temp[j] < 97)
 outputString[j] = temp[j];
 if ((temp[j] < 97 || temp[j] > 122) && temp[j] > 90)
 outputString[j] = temp[j];
 i++;
 }
 while ((i > 25) && (i < 52))
 {
 if (temp[j] == alph_base[i])
 {
 if (i == 51 && encrypt == 0)
 {
 outputString[j] = alph_base[51];
 }
 if ((i + encrypt) == 51)
 {
 outputString[j] = alph_base[51];
 }
 if ((i + encrypt) > 51)
 {
 outputString[j] = alph_base[((i + encrypt) % 51) + 25];
 }
 else
 outputString[j] = alph_base[(i + encrypt) % 51];
 }
 if ((temp[j] < 65 || temp[j] > 90) && temp[j] < 97)
 outputString[j] = temp[j];
 if ((temp[j] < 97 || temp[j] > 122) && temp[j] > 90)
 outputString[j] = temp[j];
 i++;
 }
 }
 printf("%s\n", outputString);
 return 0;
}
Richard Dally
1,4592 gold badges22 silver badges40 bronze badges
asked Aug 3, 2015 at 8:50
7
  • 1
    After the conditional block if (str[j] == '0円') { ... }, you probably need to wrap the remainder of the loop body with else { ... }. Commented Aug 3, 2015 at 8:59
  • @Giorgi : I am very new to coding. Will do my best to improve. Thanks Commented Aug 3, 2015 at 9:16
  • @squeamishossifrage : Ok will check with that. Thank you Commented Aug 3, 2015 at 9:16
  • The suggested answer is pretty good. It covers all cases and helps with reducing your code. You should use that Commented Aug 3, 2015 at 9:18
  • 1
    @JohnDemetriou : Sure. Thanks Commented Aug 3, 2015 at 9:28

2 Answers 2

3

Your code is too complex for what you want to do.

Your issue seems related to looping back from 'z' to 'a'.

A simple function like this can do the work for a character:

#include <ctype.h>
char caesar_encrypt(char input, int key)
{
 char output = input;
 char base, offset;
 // If not a letter, return the char unmodified
 if (! isalpha(input))
 {
 return output;
 }
 base = isupper(input) ? 'A' : 'a'; // Check if upper/lower case
 offset = input - base; // Take offset from 'a'
 offset += key; // Add key to offset
 offset %= 26; // Wrap offset to the 26 letters
 output = base + offset;
 return output;
}

Many ideas here:

  1. Use functions from <ctype.h> (isalpha, isupper), which avoids many comparaisons in your code.

  2. Consider your characters as an 'offset' from the letter A (uppercase or lowercase A). Thus you're working with numbers in range [0;25], and you can wrap using a simple modulus

  3. Charaters are 'integers', so you can add or subtract them. To get the third letter of the uppercase alphabet, you can do char c = 'A' + 2;, which is simpler than your huge array.

Disclaimer: Code written here, not tested, may contain typos ;)

answered Aug 3, 2015 at 9:15
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a ton. I was not aware of those useful functions in <ctype.h>
worked like a charm! thanks. The key learning is that I can use the <ctype.h> functions and that characters can be added/ subtracted.
0

Perfect answer by NiBZ. To add to it, if you still want to write your own checks rather than using library functions you can do something like:

int my_isalpha(char c){
 return ((c >= 'a' && c <= 'z')|| (c >= 'A' && c <= 'Z'));
}
int my_isupper(char c){
 return (c >= 'A' && c <= 'Z');
}

Warning: Above implementation is fine for ASCII but not so good for ISO 8859-1 or its relatives. Ref: https://stackoverflow.com/a/2169293/5183246

answered Aug 3, 2015 at 13:45

1 Comment

Thanks @d_geeks. I shall try this one too

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.