Encrypting a String in C++

Viewed 552

I am in desperate need of help with my C++ program that is supposed to encrypt a string that the user inputs (source) and saves the encrypted string to another string (destination).

Before the string is encrypted, it runs through the lowerCaseString() function where it converts source to all lowercase. This function works perfectly fine.

Can you help my make my program properly display the encrypted message? I am new to C++.

My error:

terminate called after throwing an instance of 'std::out_of_range'
  what():  basic_string::at: __n (which is 0) >= this->size() (which is 0)
#include <iostream>
#include <string>
#include <ostream>
#include <fstream>
#include <sstream>
#include <cctype>
#include <vector>

using namespace std;

string lowerCaseString(string &source);
bool substitution(string &source, string cipherKey, string &destination);

int main()
{
    string source;
    string cipherKey = "qwertyuiopasdfghjklzxcvbnm";
    string destination;
    ifstream inFile;

    cout << "Please enter a string: " << endl;
    cin >> source;

//eventually has to write to a file, but I want to get the cipher part working first
//cin >> cipherKey;
//    inFile.open("C:/Users/ellio/OneDrive/Desktop/Freshman Semester 2/ECE 1080C/ECE Labs/otherlabfiles/small-file.txt"); /*make necessary change for
//                                           file access path*/
//        if (!inFile){
//            cout << "Input file cannot be opened" << endl;
//               return 0;
//        }
//        stringstream buffer;
//        buffer << inFile.rdbuf();
//        //change to file_string
//        source = buffer.str();

    lowerCaseString(source);
    substitution(source, cipherKey, destination);

    cout << destination << endl;

    return 0;
}

//converts all letters that are upper case to lower case in source
string lowerCaseString(string &source)
{
    unsigned i;
    for(i = 0; i < source.size(); ++i)
    {
        if(isupper(source.at(i)))
        {
            source.at(i) = tolower(source.at(i));
        }
    }
    return source;
}

//encrypts the source string based on the cipher key, then writes the encrypted string to string destination
bool substitution(string & source, string cipherKey, string &destination)
{
    //the boolean function type is irrelevant to my error (I tried to run it with void type), I just have to return true or false if the
    //string source is empty

    //alphabet is used to compare to each value in source
    string alphabet = "abcdefghijklmnopqrstuvwxyz";

    unsigned i;
    unsigned j;

    //this for loop is probably unnecessary but I did it for the purpose of potential debugging
    for(i = 0; i < source.size(); ++i)
    {
        destination.at(i) = source.at(i);
    }

    //if the string is empty
    if(source.size() == 0)
    {
        return 0;
    }

    //if the string isn't empty
    else
    {
        for(i = 0; i < source.size(); ++i)
        {
            for(j = 0; alphabet.at(j) == 'z'; ++j)
            {
                //if the current character in source is equal to a certain letter in the
                //alphabet, write the corresponding value from the cipher key into destination
                if(source.at(i) == alphabet.at(j))
                {
                    destination.at(i) = cipherKey.at(j);
                }
            }
        }
        //changed this maybe change back
        return 1;
    }    
}
2 Answers

Here is your substitution method working. The destination string was empty, causing the error :

bool substitution(string & source, string cipherKey, string &destination)
{
    string alphabet = "abcdefghijklmnopqrstuvwxyz";

    destination = source; // To make sure the size of destination is the same as source

    if(source.size() == 0)
    {
        return false;
    }
    else
    {
        for(unsigned int i = 0; i < source.size(); ++i) // You can declare i and j in the loop if you want (in c++ not in c)
        {
            for(unsigned int j = 0; j < alphabet.size(); ++j) // way easier to use size instead of finding 'z'
            {
                if(source.at(i) == alphabet.at(j))
                {
                    destination.at(i) = cipherKey.at(j);
                }
            }
        }
        return true;
    }


}

Note that the character finding bit can be reduced to :

bool substitution(string & source, string cipherKey, string &destination)
{
    string alphabet = "abcdefghijklmnopqrstuvwxyz";

    destination = source; // To make sure the size of destination is the same as source

    if(source.size() == 0)
        return false;
    else
    {
        for(unsigned int i = 0; i < source.size(); ++i)
            destination.at(i) = cipherKey.at(alphabet.find(source.at(i)));
        return true;
    }
}

You were trying to access destination but it was empty. Try to avoid operating on particular indexes. It could be done like this:

void substituteCharacters(const std::string& source,
                          const std::string& cipherKey,
                          std::string& destination)
{
    destination.reserve(source.size());//allocate memory once, so no allocation during push_backs
    for(auto c : source)
        destination.push_back(cipherKey[c-'a']);
}
Related