I am stuck in this Caesar cipher encryption question of C++

749 Views Asked by At

Single File Programming Question

Problem Statement

You are tasked with building a program that encrypts secret messages using a specified encryption technique. The encryption technique involves shifting each character in the message by a certain number of positions based on an encryption key. The encrypted message will be sent over an insecure channel and can only be decrypted by the intended recipient who knows the encryption key.

Function Name: string encryptString

Input format:

The first line of input consists of a string to be encrypted, str.

The second line of input consists of an integer, n representing the encryption key.

Output format:

The output displays the encrypted string as described in the problem statement.

Code constraints:

1 <= Length of the string, str <= 100

1 <= n <= 5

Sample test cases:

Input 1:

welcome

2

Output 1:

ygneqog

Input 2:

Hello@123

4

Output 2:

LippsD567

I tried to solve this question many times and also took help of chatbots like ChatGPT. I gave my code to ChatGPT as in my code some hidden cases are failing. ChatGPT improved my code, but now also one hidden test case is failing and I don't know the inputs of that particular case.

Here is the best possible code which I have:

#include <iostream>
#include <cstring>

using namespace std;

string encryptString(string str, int n)
{
    int length = str.length();
    for (int i = 0; i < length; ++i) {
        char ch = str[i];

        if (ch >= 'a' && ch <= 'z') {
            ch = ch + n;
            if (ch > 'z') {
                ch = ch - 'z' + 'a' - 1;
            }
            str[i] = ch;
        } else if (ch >= 'A' && ch <= 'Z') {
            ch = ch + n;
            if (ch > 'Z') {
                ch = ch - 'Z' + 'A' - 1;
            }
            str[i] = ch;
        } else if (ch >= 32 && ch <= 126) {
            ch = ch + n;
            if (ch > 126) {
                ch = ch - 95;
            }
            str[i] = ch;
        }
    }
    return str;
}

int main() {
    cout << "Enter the message: " << endl;
    string msg; getline(cin, msg);

    int key;
    cout << "Enter key: ";
    cin >> key;

    string encryptedMsg = encryptString(msg, key);
    cout << "Encrypted message: " << encryptedMsg << endl;

    return 0;
}

The code I provided is failing in one hidden case. Guide me to make it more robust, so that it would be able to handle that case also.

1

There are 1 best solutions below

2
tbxfreeware On
Implementing a Caesar cipher

The cipher named after Julius Caesar uses a simple shift method such as this. When you restrict the cipher to only letters, you can implement it as described here.

  1. Convert each character to a zero-based equivalent
  2. Add the encrytion key
  3. Take the result mod 26 (i.e., the size of the alphabet). Use ch % 26 for this.
  4. Convert back to a character.
Converting to and from a zero-based equivalent

This step depends on the letters being adjacent to each other in a character set. That is the case for ASCII characters, but not necessarily for other character sets.

Convert to zero-based by subtracting 'A' for upper-case letters, or 'a' for lower case letters.

Convert back to a regular character by adding 'A' for upper-case letters, or 'a' for lower case letters.

Detecting upper case and lower case letters

Read up on std::isupper and std::islower at CppReference.

The rest is obvious.

What about using the entire range of ASCII characters?

One of the examples in your question suggests that the same technique should be applied to a larger alphabet, i.e., one that contains the entire extended ASCII character set.

Several potential problems arise:

  1. What do we do about unprintable characters? This discussion assumes that they should be treated just like any other character.
  2. Do we use the ASCII character set (0-127) or the extended ASCII character set (0-255). This discussion assumes the latter.

Basically, what we have here is an "alphabet" with 256 characters. One of the advantages is that there is no need to worry about upper case versus lower. Everything is just a character.

The basic algorithm is simpler. All you need are steps 2 and 3 above.

For each character:

  • Add the encryption key.
  • Take the result mod 256.

Taking the modulus is easy. You can simply cast the result of the addition back to type char. There is no need to use ch % 256.

ch = static_cast<char>(ch + key);  // encrypt character ch

You could also use the more consise:

ch += static_cast<char>(key);  // encrypt character ch

I have a working program, but I am not posting it here. I want to you to have the reward of coding this yourself.

Hope this helps.