Reputation: 3
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
Upvotes: 0
Views: 77
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
#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
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
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