0

I wrote the following code for Ceaser cypher in C++. I am using a while loop hereenter code here because when a user encrypts/decrypts a message there should be a loop for trying it again. But when I run the code, for the first iteration it is working perfectly fine, but when it runs for the second time it does not take the input string. Here is my code

#include <conio.h>
#include <stdio.h>

#include <iostream>

using namespace std;

int main() {
  char x = 'y';
  int k, option;
  string msg;
  string encrypt;
  string decrypt;

  while (x != 'n')  // run until user selects n
  {
    cout << "Please enter your message: ";
    getline(cin, msg);  // gets input message

    cout << "\nEnter number for the key between 1-25: ";
    cin >> k;

    while (k < 1 || k > 25) {
      cout << "\nPlease select valid key between 1 and 25 ";
      cin >> k;
    }

    cout << "\nSelect option: "
         << "\n1 for Encrypt "
         << "\n2 for Decrypt "
         << "\n";
    cin >> option;
    while (option != 1 && option != 2) {
      cout << "\nSorry wrong option. Please select again\n ";
      cin >> option;
    }

    switch (option) {
      case 1:  // for encryption
        for (int i = 0; i < msg.length(); i++) {
          if (isalpha(msg[i])) {
            if (islower(msg[i])) {
              encrypt[i] = (((msg[i] - 97) + k) % 26) + 97;
              cout << encrypt[i];
            }
          }
          if (isupper(msg[i])) {
            encrypt[i] = (((msg[i] - 65) + k) % 26) + 65;
            cout << encrypt[i];
          }
        }
        break;

      case 2:  // for decryption

        for (int i = 0; i < msg.length(); i++) {
          if (islower(msg[i])) {
            decrypt[i] = ((((msg[i] - 97) - k) + 26) % 26) + 97;
            cout << decrypt[i];
          }
          if (isupper(msg[i])) {
            decrypt[i] = ((((msg[i] - 97) - k) + 26) % 26) + 97;
            cout << decrypt[i];
          }
        }
        break;
    }
    cout << "\nDo you want to try again?(Y/N) ";  // asking user if he wants to
                                                  // encrypt or decrypt again
    cin >> x;
  }
}
Sergii P
  • 690
  • 8
  • 21
  • Before this statement getline(cin, msg); use std::cin.ignore( std::numeric_limits::max(), '\n' ); You need to include the header limits – Vlad from Moscow Dec 30 '19 at 21:55
  • Fyi, [`std::getline`](https://en.cppreference.com/w/cpp/string/basic_string/getline) requires inclusion of ``. Just saying. – WhozCraig Dec 30 '19 at 21:55
  • You also have undefined behavior because you are accessing `encrypt` and `decrypt` out-of-bounds. Both are empty and you index them. You need to `.push_back` (or `+=`) on them or `.resize` them to the required size first. – walnut Dec 30 '19 at 22:04
  • After `cin >> x` at the end try adding `cin.ignore()` to flush the newline character. – jignatius Dec 30 '19 at 22:05
  • Recommendation: Write less code before testing. It sucks to writer out a couple hundred lines of code and then find that all or most of that work is rendered garbage because of an error in the first few lines. If step one is get data from the user, write and test the user input code. Don't waste your time writing anything else until you know the input is correct. – user4581301 Dec 30 '19 at 22:28
  • You seem to be assuming the `'a'` is `97`. That is not always true, and it is far clearer if you use the literal `'a'` in your code rather than the magic number `97`. Similarly, use `'A'` instead of `65` – William Pursell Dec 31 '19 at 08:13

2 Answers2

0
#include <string>

Change it to this:

getline(cin, msg);  // gets input message
if (msg == "") getline(cin, msg);

also, you cannot address uninitialized strings...

encrypt[i] = ... to encrypt += ...

decrypt[i] = ... to decrypt += ...

The secound decrypt is a duplicate, change it to:

decrypt += ((((msg[i] - 65) - k) + 26) % 26) + 65;
Onyrew
  • 126
  • 7
  • 1
    Sidenote: refrain from using a 65 where an `'A'` is more appropriate. It usually makes the code easier to read and is a bit more portable. – user4581301 Dec 31 '19 at 00:39
0

You need to flush the buffer at the end of your code right after cin >> x. This is one of the ways to do It

...                                         

cin.clear();

cin.ignore(numeric_limits<streamsize>::max(), '\n');`

Also doesn't forget to include #include <limits> for for numeric_limits.

Here is the post that you might find helpful How do I flush the cin buffer?

Updated: As I was corrected in the comment section the cin.clear(); is only necessary if bad input set an error flag in the stream.

Sergii P
  • 690
  • 8
  • 21
  • 1
    Terminology note: this is not flushing. This is just removing selected data. – user4581301 Dec 30 '19 at 22:24
  • 1
    the `cin.clear();` is only necessary if bad input set an error flag in the stream. – user4581301 Dec 30 '19 at 22:25
  • @user4581301 noted. you are correct! – Sergii P Dec 30 '19 at 22:27
  • Thank you for your help. It solved my problem. Another problem that I am facing is that when I enter a string having spaces in it, and try to encrypt it, the encrypted message doesn't have space in it. While I think the encrypted/decrypted message also has space as there was in the original string. Can you please help me with that? – Warda Khan Jan 03 '20 at 18:32