Search code examples
c++oopcaesar-cipher

Caesar cipher object oriented programming


I have been implementing the Caesar cipher using object oriented programming. The problem is that when I call the encrypted function I get the same message as the user input... The message is not being encrypted properly.

For example if I write "abc" instead of getting "bcd", I am getting "abc". I tried it in C++, the code was working (the logic was fine) but I tried using object-oriented programing in C++ and created three files to separate the code.

Can anyone help or identify any mistake that I may have made?

Executable test File (main function):

#include <iostream>
#include <string>
#include "CyclicShift.h"

using namespace std;


int main()
{

string text;//the string that holds the user input

int key;//key holds the number by which the user wants the alphabets to be     shifted

cout << "Enter your phrase: " << endl;
getline(cin, text);//gets the user input ( including spaces and saves it to the variable text)

cout << "Please choose a number(key) for which you wants the alphabets to be shifted:  " << endl;
/*Note: the key can either be positive (forward shifting), negative (backward shifting) or zero (no shifting)*/

cin >> key;//User input for number by which alphabets are going to be shifted

const CyclicShift aShift;

cout << "Encrypted Message : " << aShift.Encrypt(text, key) << endl;

//system("Pause");

return 0;
}

Header file .h:

#pragma once
#include <iostream>
#include<string>
//Note: No using "namespace std;" in header files 

class CyclicShift
{
private:

char fUpperCase[26];//A-Z
char fLowerCase[26];//a-z

public:
CyclicShift();

std::string& Encrypt(std::string& aOriginalMessage, int &aKey) const;//  Function Prototype.  This declares Encrypt to be a function that needs one string and one integer variables as arguments. Reference operator & in prototype

};

Source file .cpp:

#include "CyclicShift.h"
#include<iostream>
#include<string>

using namespace std;

CyclicShift::CyclicShift()
{
char fUpperCase[26] = {'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'};//Initialization of class member
char fLowerCase[26] = {'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'};//Initialization of class member

}

string& CyclicShift::Encrypt(string& aOriginalMessage, int & aKey) const
{

int z;//z holds the value (int) of the length of the user input ( including spaces)
z = (int)aOriginalMessage.length(); /*give the variable z the value of the user input length and length is normally an unsigned long integer hence
                            we have to typecast it*/

/*counter that makes it keep looping until it "encrypts" all of the user input (that's why it keeps looping while its less than z)*/
for (int i = 0; i < z; i++)
{
    for (int j = 0; j < 26; j++)
    {
        if (aOriginalMessage[i] == fLowerCase[j] || aOriginalMessage[i] == fUpperCase[j])
        {

            if (aKey > 0)
            {
                //another counter that loops forwards key times by incrementing method
                for (int counter = 0; counter < aKey; counter++)
                {
                    /*it checks if the letter text[x] is 'z' and if it is 'z' it will make it 'a'*/
                    if (aOriginalMessage[i] == 'z')
                    {
                        aOriginalMessage[i] = 'a';
                    }

                    else if (aOriginalMessage[i] == 'Z')
                    {
                        aOriginalMessage[i] = 'A';
                    }

                    else
                    {
                        aOriginalMessage[i]++;
                    }

                }
            }

            else    if (aKey < 0)
            {
                //another counter that loops backwards key times by decrementing method
                for (int counter = 0; counter < abs(aKey); counter++)
                {
                    /*it checks if the letter text[x] is 'a' and if it is 'a' it will make it 'z'*/
                    if (aOriginalMessage[i] == 'a')
                    {
                        aOriginalMessage[i] = 'z';
                    }

                    else if (aOriginalMessage[i] == 'A')
                    {
                        aOriginalMessage[i] = 'Z';
                    }

                    else
                    {
                        aOriginalMessage[i]--;
                    }
                }
            }

            else
            {
                aOriginalMessage[i];//No alphabet shifts
            }

        }

        else {

            continue;
            }

        break;
    }

}

return aOriginalMessage;
}

Above are the three code files of my object-oriented implementation: Testing (main), Header and source .cpp file.


Solution

  • You should declare fUpperCase and fLowerCase as static and initialize them in the header file. In your code the variables you initialized are local to the constructor, while the private members stay untouched.

    EDIT

    If you have to initialize them in the constructor, well, you can do something like this:

    class CyclicShift
    {
      private:
    
        char fUpperCase[26]; // A-Z
        char fLowerCase[26]; // a-z
    
      // ... etc. ...
    }     
    
    CyclicShift::CyclicShift()
    {
        for ( int i = 0; i < 26; ++i) {
            fUpperCase[i] = 'A' + i; 
            fLowerCase[i] = 'a' + i;
        }
    }