-2

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.

Blitzkoder
  • 1,768
  • 3
  • 15
  • 30
Ketnav
  • 1
  • 3

4 Answers4

2

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;
    }
}
Bob__
  • 12,361
  • 3
  • 28
  • 42
  • Thx anyways but according to my project the fUpperCase and fLowerCase should be initialized in the Constructor and the template was to declare them as: char fUpperCase[26]; Hence I cannot make it static.... – Ketnav Apr 05 '16 at 09:02
  • @Ketnav ok, only be sure not to redeclare them in the constructor, just initialize them (not with an initializer list). – Bob__ Apr 05 '16 at 09:05
  • I redeclared them in the constructor :) but the result is still ok! – Ketnav Apr 05 '16 at 09:10
  • do you know any other way where we can access a private member in any public function like similar to my initial code that is initializing in my constructor? Secondly why there was no error when I compiled if I can't get access to fUpperCase[j] and fLowerCase[j] alphabets?? – Ketnav Apr 05 '16 at 09:15
  • @Ketnav You can access private members from any function of the class, but the variables you initialize in the constructor (posted code) are not the member variables with the same name, as you are redeclaring them. Use a loop to initialize them in the constructor, without redeclaring them (no `char` before the names). – Bob__ Apr 05 '16 at 09:24
  • Really need your help man...How to initialize them with a loop in the constructor??@Bob__ – Ketnav Apr 05 '16 at 10:15
0

One problem that stands out to me is that you check the current character of the message

if (aOriginalMessage[i] == fLowerCase[j] || aOriginalMessage[i] == fUpperCase[j])

potentially after having changed it with your shift.

aOriginalMessage[i]++;

since you are iterating over all possible characters. You may want to save the encrypted message in a different variable.

Also, it might be more efficient to shift the whole alphabet first and then directly assign the shifted characters for the encrypted message.

Hope that helps.

Alexander Büse
  • 564
  • 7
  • 15
  • I don't think that's the problem...as i told you I tested the logic on C++ under one file and it works if type "abc" it vecomes "bcd" but its only when i tried it in oop its not working... – Ketnav Apr 05 '16 at 08:03
0

Below is the C++ code i tested and I repeat again its working both for encrypting and decrypting....meaning the logic is ok...

#include<iostream>
#include<string>

using namespace std;

string Encrypt(string&, int &);// Function Prototype.  This declares Encrypt to be a function that needs one variable as string and another as interger as arguments. Reference operator & in prototype
string Decrypt(string&, int &);//Function Prototype.  This declares Decrypt to be a function that needs one variable as string and another as interger as arguments. Reference operator & in prototype

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

string kolo = Encrypt(text, key);

cout << "Encrypted Message: " << kolo << endl;//Function call to display encrypted message

//Decrypt(Encrypt(text, key), key);

cout << "Decrypted Message: " << Decrypt(kolo, key)<< endl;//Function call to display decrypted message

//system("Pause");

return 0;
}



string Encrypt(string& Source, int& c)
{
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

int z;//z holds the value (int) of the length of the user input ( including spaces)
z = (int)Source.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 (Source[i] == fLowerCase[j] || Source[i] == fUpperCase[j])
        {
            //text[i] = fLowerCase[j];

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

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

                    else
                    {
                    Source[i]++;
                    }

                }
            }

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

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

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

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

        }

        else {
                continue;
             }

        break;
    }

}

return Source;
}

string Decrypt(string& EncryptedMessage, int& c)
{
int y;//z holds the value (int) of the length of the user input ( including spaces)
y = (int)EncryptedMessage.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*/


for (int i = 0; i < y; i++)
{

    if (isalpha(EncryptedMessage[i]))//verify if the all members of the encrypted message is alphabet if not the same special character is return whereas if it is alphabet it is eitther incremented or decremented
    {

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

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

                else
                {
                    EncryptedMessage[i]--;
                }

            }
        }

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

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

                else
                {
                    EncryptedMessage[i]++;
                }
            }
        }

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

    }

    //cout << "Decrypted Message: " << EncryptedMessage << endl;//Function call to display decrypted message


}
return EncryptedMessage;
}
Ketnav
  • 1
  • 3
0

Change the constructor code to:

CyclicShift::CyclicShift()
{
    static char const fUpper[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
    static char const fLower[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

    strcpy_s(fUpperCase, fUpper);
    strcpy_s(fLowerCase, fLower);
}

I changed the length of char arrays to 27 to avoid buffer overflow.

char fUpperCase[27];//A-Z
char fLowerCase[27];//a-z
abdul
  • 1,562
  • 1
  • 17
  • 22
  • Hey is there any other we can do this...In fact it's a project and its written that the constructor should initialize the Fuppercase and flowercase...Is there any other way to call the fUpperCase and fLowercase in the encrypt method? – Ketnav Apr 05 '16 at 08:57
  • You can use `strcpy` in constructor like `strcpy(fUpperCase, fUpper);`, `fUpperCase` is the private variable defined in your header. Do the same to `fLowerCase`. – abdul Apr 05 '16 at 09:22
  • Hey man I cannot use strcpy....my compiler is saying to use "strcpy_s"!!! I tried strcpy_s(fUpperCase,26, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); ...it is compiling but I get a message saying...debug assertion failed!!! @lucifer – Ketnav Apr 05 '16 at 10:36
  • @Ketnav Updated, given code is working for me. Are you using linux or windows? – abdul Apr 05 '16 at 12:19
  • Windows...am using visual studio 2013...and one more thing I rewrote the strcpy again : 'strcpy_s(fUpperCase, sizeof (fUpperCase), "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); strcpy_s(fLowerCase, sizeof (fLowerCase), "abcdefghijklmnopqrstuvwxyz"); ' but am still getting the same error – Ketnav Apr 05 '16 at 12:35
  • I think i need to use 'for' loop as @Bob stated since char fUpperCase[26] and char fLowerCase[26] are already provided as constructor members so I can't modify it to 27...Though if i modify it to 27 as you stated in your comments above it works....Thxs anyways..atleast I learnt how to use strcpy_s can be helpful to me while coding one day...Ths again bro :) – Ketnav Apr 05 '16 at 12:52