liaforu
liaforu

Reputation: 3

How to repeat a program when user prompted y/n

This program is supposed to encrypt and decrypt the string "myWord". Once received, it passes through the two methods to encrypt and decrypt and then returns to main. I have been trying to make it prompt the user if they want to continue or not. If they enter "n" then the loops stops and the program ends. if they enter "y" then it will repeat and they will be able to encrypt again after they are prompted for their name again. I've tried many different ways but the output continues to end up like this after I enter y:

#include <iostream>
#include <string>

using namespace std;

void encrypt(string);
void decrypt(string);

int main() {
    string myWord;

    char choice = 'y';
    while (choice == 'y') {
        cout << "Enter a name: ";
        getline(cin, myWord);
        encrypt(myWord);
        cout << "Would you like to encrypt again? (y/n): ";
        cin >> choice;
        if(choice == 'n') {
            return 0;
        }
        system("pause");
    }
    return 0;
}

void encrypt(string encrypting) { 
    for (int i = 0; encrypting[i] != '\0'; i++) {
        encrypting[i] = encrypting[i] + 1;
    }
    cout <<"Encrypted: " << encrypting << endl;
    decrypt(encrypting);
}

void decrypt(string decrypting) {
    for (int i = 0; decrypting[i] != '\0'; i++) {
        decrypting[i] = decrypting[i] - 1;
    }
    cout << "Decrypted: " << decrypting << endl;
    return;
}

My output

1

Upvotes: 0

Views: 77

Answers (3)

arfneto
arfneto

Reputation: 1765

Well, as people here told you it is not safe to mix char, strings, getline() and cin stuff...

You may find it simpler to just go on C++ fashion and use only getline() and string an in this

Example

#include <iostream>
#include <string>

using namespace std;

void decrypt(string);
void encrypt(string);

int main(void)
{
    string  choice;
    do
    {
        string  myWord; // only exists here
        cout << "Enter a name: ";
        getline( cin, myWord );
        encrypt(myWord);
        cout << "Would you like to encrypt again? (y/n): ";
        getline( cin, choice );
        
    }   while (choice == "y");
    return 0;
}

void encrypt(string encrypting) { 
    for (int i = 0; encrypting[i] != '\0'; i++) {
        encrypting[i] = encrypting[i] + 1;
    }
    cout <<"Encrypted: " << encrypting << endl;
    decrypt(encrypting);
}

void decrypt(string decrypting) {
    for (int i = 0; decrypting[i] != '\0'; i++) {
        decrypting[i] = decrypting[i] - 1;
    }
    cout << "Decrypted: " << decrypting << endl;
    return;
}

That shows

PS C:\test> g++ -o x -Wall x.cpp
PS C:\test> ./x  
Enter a name: A test
Encrypted: B!uftu
Decrypted: A test
Would you like to encrypt again? (y/n): y
Enter a name: Another test
Encrypted: Bopuifs!uftu
Decrypted: Another test
Would you like to encrypt again? (y/n): y
Enter a name: Last One
Encrypted: Mbtu!Pof
Decrypted: Last One
Would you like to encrypt again? (y/n): n
PS C:\test> 

Upvotes: 0

Casey
Casey

Reputation: 10936

Your issue is switching between whitespace-delimited input and line-oriented input. Since std::cin leaves the '\n' in the stream, the next call to std::getline sees that and skips ahead too.

You need to skip to the end of the stream:

See https://en.cppreference.com/w/cpp/string/basic_string/getline for more information.

This should fix your problem:

#include <limits>
#include <ios>

//...

cout << "Enter a name: ";
getline(cin, myWord);
encrypt(myWord);
cout << "Would you like to encrypt again? (y/n): ";
cin >> choice;
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

Upvotes: 2

ph3rin
ph3rin

Reputation: 4838

Mixing formatted input (e.g. std::cin >> x) and unformatted input (e.g. std::getline) is hard to get right.

In your example, the cin >> choice line would extract a character from stream (ignoring leading whitespace). The next character in the stream (assume you typed y then enter) would be the newline character \n.

For example, your input sequence might look like this name\ny\nanother_name.

The first getline call extracts name\n, giving you the string name and discarding \n (it is still extracted, just not added to the string), leaving y\nanother_name.

Then cin >> choice extracts y, leaving \nanother_name.

Then you call getline again, it looks at the beginning of a stream, see a \n, and thinks it gets an empty line. So it extracts \n and discards it... You wanted it to read another_name, but it reads an empty line.

The simplest possible solution is to do a cin >> std::ws before you call std::getline. This extracts all the leading whitespace from the input stream and discards them (that includes the spurious empty line)

In your example, it will be:

cout << "Would you like to encrypt again? (y/n): ";
cin >> choice;     
cin >> std::ws; // Note the added std::ws here
if(choice == 'n') {
    return 0;
}

Upvotes: 0

Related Questions