0

I am making a cypher program for my C++ project. My approach is to declare and initialise two strings, the first one being alphabet and the other being key, as shown below.

string alphabet {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"}; string key {"ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba"}; 

I want to pair all these 52 letters to one another in the cypher. That is, small a is replaced with capital Z, small b with Y and so on.

The user will be prompted to enter a string, which will be stored in input. My idea is to loop through the input string and match it with alphabet, and hence find out its pair in key string. This is easy, since the pairs will have the same index. However, how do I swap them? I can use a loop in swap(input[i], key[i]) but that will just make every string as ZYXW... I am not able to write the logic here... Below is my code till now in entirety.

#include <iostream> #include <string> using namespace std; int main() { string alphabet {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"}; string key {"ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba"}; int choice {}; cout<<"Welcome to the Cypher Program"; cout<<"\nYou can encode and decode your messages to make sure they remain secret!"; cout<<"\nWould you like to encode(Press 1) or decode(Press 2) a message?"<<endl; cin>>choice; //Encoding if (choice == 1) { string input {}; cout<<"Enter a string to encrypt"<<endl; getline(cin.ignore(), input); //testString cout<<"Your encrypted message is: "<<endl; for(int i {0}; i<input.length(); i++){ swap(input[i], key[i]); } cout<<input; //ZYXWVUTSRQ } return 0; } 

What I really want to do is:

  • Get input from user
  • For each letter in input, find out its index in alphabet
  • Using this index, swap the character with key.
  • Display the new string back to user.
4
  • 2
    You’re missing the “find the index” part here. Add that. And don’t swap, replace. You don’t want to change they key. Commented Dec 28, 2019 at 5:50
  • @SamiKuhmonen Oh ok, I will use replace instead of swap. But how do I find the index? I am not able to think of any sort of logic yet :-/ Commented Dec 28, 2019 at 5:52
  • Since you want to find the character in a string then std::string’s find() method will be useful Commented Dec 28, 2019 at 5:59
  • Why do you need swapping? The key should be constant and it shall not be changed while encoding/decoding. Commented Dec 28, 2019 at 6:08

3 Answers 3

1

I'm going to discuss two simple approaches here.

  1. First is to just do what you've suggested in the first place, find the index of the letter from alhphabet and use that index to find encoded letter from key.

  2. You can use a simple trick here by observing the pattern in your encoding. Whenever it's an uppercase letter, you can just subtract 'A' from its ASCII value to get offset and subtract that offset from ASCII value of z to get encoded letter. You can notice similar pattern when it's a lowercase letter.

Below is the sample code for both approaches.

#include <iostream> #include <string> using namespace std; int main(){ string alphabet {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"}; string key {"ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba"}; string input1 {"testString"}, input2 {"testString"}; cout<<"Your encrypted message is (Approach 1) : "<<endl; // Approach 1 for(int i {0}; i<input1.length(); i++){ int idx; for(idx=0;idx<alphabet.length();idx++) // find index from alphabet if(input1[i]==alphabet[idx]) break; input1[i] = key[idx]; // replace with key } cout<<input1<<endl; //GVHGhGIRMT // Approach 2 cout<<"Your encrypted message is (Approach 2) : "<<endl; for(int i {0}; i<input2.length(); i++){ if(input2[i] >= 'A' && input2[i]<='Z') input2[i] = 'z' - (input2[i]-'A'); else if(input2[i] >= 'a' && input2[i]<='z') input2[i] = 'A' + ('z'-input2[i]); } cout<<input2; //GVHGhGIRMT return 0; } 

Output

Your encrypted message is (Approach 1) : GVHGhGIRMT Your encrypted message is (Approach 2) : GVHGhGIRMT 
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, but will the approach 2 be still valid if I try to incorporate other characters such as whitespace and underscores?
It depends on what your encoded key is, for those characters. If alphabet-key have a relation/pattern among them, like in case lowercase and uppercase letters, then Approach 2 can be modified to incorporate those characters too. Otherwise, no.
1

Step 1: Find index of character in original string

if (input[i] >= 97) { index = input[i]-97; } else { index = (input[i]-65) + 26; } 

now use

input[i] = key[index]; 

Comments

1

Hm, your original code was not that bad. You just need to replace the swap with an assignment. That leaves you originla data untouched.

input[i] = key[alphabet.find(input[i])]; 

Youd should add const before "alphabet" and "key" then the compiler would have prevented your code.

By the way, with this symmetric key, encoding and decoding is the same.

Not sure why you are writing getline(cin.ignore(), input); instead of getline(cin, input);. That should be corrected.

The calculation approach has the advantage that the key string will not be in exe file. You could calculate the result also with XOR 255 (result += input[i] ^255, which flips all bits, or with 256-input[i];

Below a "more modern" C++ solution using the std::transform-algorithm

#include <iostream> #include <string> #include <algorithm> int main() { // The encoding alphabet and key constexpr std::string_view alphabet{ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ _" }; constexpr std::string_view key{ "ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba_ " }; // String to encrypt std::string message{"Hello world"}; // Here we will store the result std::string result; std::transform(message.begin(), message.end(), std::back_inserter(result), [&key, &alphabet](const char c) { size_t pos{ alphabet.find(c) }; return (pos != std::string::npos) ? key[pos] : '_'; }); // Show result std::cout << "\nEncrypted: " << result << "\n"; message = result; result.clear(); std::transform(message.begin(), message.end(), std::back_inserter(result), [&key, &alphabet](const char c) { size_t pos{ alphabet.find(c) }; return (pos != std::string::npos) ? key[pos] : '_'; }); // Show result std::cout << "\nDecrypted: " << result << "\n"; return 0; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.