I am writing a program that uses a substitution cipher. I am trying to replace each char in a string (that the user entered) with a char from another string (the encryption key string). But I am having a bunch of issues doing this with the string.replace() function. It does not replace the the char in the userMessage with the correct char. Although this is not an issue when using a string literal as initialization value for letterReplacement. In addition to this, it somehow temporarily increases the size of the userMessage resulting in the loop running for e.g 5 times in a message 3 char long (no matter how letterReplacement was initialized). I would appreciate any information on why this happens.
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::string userMessage;
std::cout << "\nWelcome to my Military Grade* Encryption Software!" << std::endl;
std::cout << "--------------------------------------------------" << std::endl << std::endl;
std::cout << "Please enter a secret message you would like to encrypt:\n-" << std::endl;
getline(std::cin, userMessage);
std::cout << "-" << std::endl << std::endl;
const std::vector <std::string> encryptionKey {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZT.,<>!? - '",
"ß?pl ,;0=}okm9)]ijN8([uhb7/{zgv6&ctf%xdrys4$e3w|<2Q>1! #ä-:*GnB"};
for(size_t i {0}; i < userMessage.size(); i) // Here we encrypt the Message
{
char currentCharInUM {userMessage.at(i)};
size_t currentKeyPosition {encryptionKey.at(0).find(currentCharInUM)}; //finds the position that currentChar is at in first encryptionKey String
std::cout << "currentKeyPosition: " << currentKeyPosition << " - " << i << std::endl;
if(currentKeyPosition == std::string::npos) // is letter in userMessage is not in encryptionKey just keep it (skip iteration)
continue;
std::string letterReplacement {encryptionKey.at(1).at(currentKeyPosition)};
userMessage.replace(i,1,letterReplacement);
}
std::cout << userMessage;
return 0;
}
CodePudding user response:
The first character of 2nd element of the vector encryptionKey 'ß' is equal to 2 bytes. So that when you enter 'a' it returns '├' and when you enter b it returns 'ş'. You can try with another character instead of 'ß'.
CodePudding user response:
If your intention was indeed to store non-ASCII characters, it would have been more advantageous to use a lookup table.
The table could be a std::unordered_map<char, wchar_t>
to map the English letters to the encrypted characters:
#include <iostream>
#include <string>
#include <unordered_map>
int main()
{
// Strings
const char encryptionKeyA[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZT.,<>!? - '";
const wchar_t encryptionKeyW[] = L"ß?pl ,;0=}okm9)]ijN8([uhb7/{zgv6&ctf%xdrys4$e3w|<2Q>1! #ä-:*GnB";
// Create the lookup table bassed on the above strings
std::unordered_map<char, wchar_t> encryptionMap;
for (int i = 0; i < sizeof(encryptionKeyA); i)
encryptionMap[encryptionKeyA[i]] = encryptionKeyW[i];
// Test
std::string userMessage = "abcTest";
// The output string
std::wstring encryptedString;
// Now go through each character of the userMessage
for(auto ch : userMessage)
{
// If the character exists, append the associated encrypted character
auto iter = encryptionMap.find(ch);
if (iter != encryptionMap.end())
encryptedString = iter->second;
else
encryptedString = L' '; // Just append a space if it didn't exist
}
std::wcout << encryptedString;
}
Output:
ss?p1 N8
Note that the output is what is displayed if the locale is English. If the terminal/output were set to German, I would assume that the output would be:
ß?p1 N8
since the first character is the "double-s".
Also note that I am assuming that both the original and encrypted character strings are of the same size (in terms of the number of characters) when building the map. If they're not the same size, then the loop to build the map should be adjusted accordingly.