Using modulo for a caesar cipher

I'm only a couple of weeks into semester and I have no prior experience so I'm the beginner of the beginners. In fact, the code below represents most of the knowledge I have of C++. Please keep that in mind. I have two problems. First, whenever I input either character 'y' or 'z', the program adds 2 to the ascii assignment instead of the intended 1. I don't know why it occurs only with these characters but works fine for all the others. Second problem is with the non-letter characters between 'Z' and 'a'. The instructor is requiring we use only letters and I don't know how to exclude the ones in between the capitals and non-capitals. Also, I should point out that we are being required to use the modulo operator for this task. I know there's probably other ways to do this. Thanks in advance

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

#include <iostream>
#include <cmath>
using namespace std;

int main() {
   
   const int CRYPT_KEY = 1;
   char char1;
   cout << "Enter letter: ";
   cin >> char1;
   cout << char1 << endl;
   int ascii = static_cast<int>(char1) + CRYPT_KEY;;
   ascii = ((ascii - 65) % 57) + 65;
   char1 = static_cast<char>(ascii);
   cout << "Encrypted letter: " << char1;
   
   return 0;
}
What's up with the mod 57? What does that number come from? I assume it's an attempt to deal with capital lettering?

whenever I input either character 'y' or 'z', the program adds 2 to the ascii assignment instead of the intended 1. I don't know why it occurs only with these characters but works fine for all the others.

Let's try out the math.

65 == 'a'
120 == 'x' --> 120 - 65 + 1 = 56, 56 % 57 = 56, 56 + 65 = 121 == 'y'
but then...
121 == 'y' --> 121 - 65 + 1 = 57, 57 % 57 = 0, 0 + 65 = 0 == 'A'

The problem is that you incorrectly implementing the modular "wrap-around" logic.
Inputting 'Z' would not work correctly either. 57 isn't going to solve that.

Are you sure you have to make A -> B and a -> b? Usually these types of ciphers just stick with either all caps (or they represent lowercase as the cleartext, and ALL CAPS as the ciphertext). But it's not too big of a deal, you just have to change the offset if it's a capital letter.

Let's just focus on lowercase. That's working in modulo 26.
We want a -> b, but z -> a (wrap back around)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <cctype> // islower
using namespace std;

int main() {
   
   const int CRYPT_KEY = 1;
   char char1;
   cout << "Enter letter: ";
   cin >> char1;
   cout << char1 << endl;

   int ascii = static_cast<int>(char1) + CRYPT_KEY;
   ascii = ((ascii - 'a') % 26) + 'a';
   char1 = static_cast<char>(ascii);
   cout << "Encrypted letter: " << char1;
   
   return 0;
}


but now we want to incorporate capital letters as well. Simply change the offset from 'a' to 'A'.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <cctype>
using namespace std;

int main() {
   
   const int CRYPT_KEY = 1;
   char char1;
   cout << "Enter letter: ";
   cin >> char1;
   cout << char1 << endl;

   int ascii = static_cast<int>(char1) + CRYPT_KEY;
   if (islower(char1))
      ascii = ((ascii - 'a') % 26) + 'a';
   else
      ascii = ((ascii - 'A') % 26) + 'A';
   char1 = static_cast<char>(ascii);
   cout << "Encrypted letter: " << char1;
   
   return 0;
}

I'm sure you could do something fancy to eliminate the if statement, but that should do just fine.
Last edited on
The 57 was a typo, not just here on the forum, but that's how it copied over to here. As it turns out that was my problem. Since the first number for character A is 65 and the last number for character z is 122, I subtracted to find the range. It was supposed to be 58. Once I updated it, it worked fine. I wasn't able to spot this because I was doing the math wrong due to my lack of understanding of modulo.

After seeing your math example, it seems like I had the numbers reversed in my head when using modulo. I thought 56 % 57 meant the remainder after dividing 56/57, which yields no remainder. But your example seems to make it 57/56, which makes more sense. Is my thinking correct now?

As for the using only letters part, I got clarification from the instructors. They are fine with using the in between characters. I also would have used if-else statements, but they were adamant about using only knowledge we had at the time of being assigned this work, which was a week ago. I'm pretty sure I could have used if-else in such a way as to avoid modulo altogether.

I would consider this issue resolved. Thanks for you're help.
Topic archived. No new replies allowed.