C++ cin.getline appears to be skipped - c++

I can't quite figure out why my program below is skipping over "cin.getline(staffMember, 100);". If I add a delimiter like 'q' for instance, it works as expected. I'm not sure why it's acting as if a new line is being entered automatically. Could somebody please explain to me why this is happening?
#include "stdafx.h"
#include <iostream>
#include <string>
#include <fstream> // Allow use of the ifstream and ofstream statements
#include <cstdlib> // Allow use of the exit statement
using namespace std;
ifstream inStream;
ofstream outStream;
void showMenu();
void addStaffMember();
void showMenu()
{
int choice;
do
{
cout
<< endl
<< "Press 1 to Add a New Staff Member.\n"
<< "Press 2 to Display a Staff Member.\n"
<< "Press 3 to Delete a Staff Member.\n"
<< "Press 4 to Display a Report of All Staff Members.\n"
<< "Press 5 to Exit.\n"
<< endl
<< "Please select an option between 1 and 5: ";
cin >> choice;
switch(choice)
{
case 1:
addStaffMember();
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
default:
cout << "You did not select an option between 1 and 5. Please try again.\n";
}
} while (choice != 5);
}
void addStaffMember()
{
char staffMember[100];
cout << "Full Name: ";
cin.getline(staffMember, 100);
outStream.open("staffMembers.txt", ios::app);
if (outStream.fail())
{
cout << "Unable to open staffMembers.txt.\n";
exit(1);
}
outStream << endl << staffMember;
outStream.close();
}
int main()
{
showMenu();
return 0;
}

When the user enters a choice, they type a number and then press enter. This puts that input including a \n character into the input stream. When you do cin >> choice, characters will be extracted until the \n is found and then those characters will be interpreted as an int. However, the \n is still in the stream.
Later, when you do cin.getline(staffMember, 100), it reads up to the \n and appears as though you entered a new line without actually typing anything.
To get around this, extract up to the next new line by using ignore:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
This will extract everything up until and including the next \n character and discard it. So in fact, this will even handle when the user inputs something like 1banana. The 1 will be extracted by cin >> choice and then the rest of the line will be ignored.

When doing cin >> choice; the newline is left by cin. So when you do getline next, it reads up to this newline and returns empty (or whitespace) string.

Use
scanf("%d\n", &choice);
OR you can use a dummy getchar() after cin>>choice;
Right now, the \n is skipped, as explained in few answers.

cin is mixed with getline() - try not to mix both in the same code.
Try using this instead?
char aa[100];
// After using cin
std::cin.ignore(1);
cin.getline(aa, 100);
//....

Related

C++ istream (cin) and problem with waiting for a ENTER key press

Please, is there a way I can wait for a single ENTER key press in all of the below cases? It works fine except when the std::getline() is used, which consumes the \n, and the ENTER needs to be pressed twice.
The code below works fine:
#include <iostream>
#include <limits>
using std::cout;
using std::cin;
using std::string;
void waitForENTERKeyPress();
int main ()
{
char c;
string s;
cout << "Enter c:"; cin >> c;
waitForENTERKeyPress();
cout << "Enter c:"; c = cin.get();
waitForENTERKeyPress();
cout << "Enter s:"; cin >> s;
waitForENTERKeyPress();
cout << "Enter s:"; std::getline(cin, s);
waitForENTERKeyPress();
return 0;
}
void waitForENTERKeyPress()
{
// Does not work with std::getline(...)
cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n');
cout << "Press an ENTER to continue...\n";
cin.get();
}
====[UPDATE]============================================
Let me rephrase what I am looking for: The way how to make the waitForENTERKeyPress() function working in both cases – with \n in the buffer, when cin operator >> or cin.get() is used and also in cases the std::getline() is used.
From what I understand it is not possible as there is not a way how to detect if the \n is still in the buffer or not.
I have tried to use cin.rdbuf()->in_avail(), but it always returns 0.

why do two getline() lead to no input?

I am creating a simple login program.
#include <iostream>
#include <string>
using namespace std;
void showRegister()
{
string user;
string pw;
cout << "Enter your username:";
getline(cin, user);
cout << "Enter your password:";
getline(cin, pw);
cout << "You have successfully registered!" << endl;
writeIntoFile(user, pw);
showMenu();
}
void showMenu() {
int select;
do {
cout << "1. Register"<<endl;
cout << "2. Login" << endl;
cout << "3. Exit" << endl;
cout << "Enter your choice: ";
cin >> select;
} while (select > 3);
switch (select)
{
case 1:
showRegister();
break;
case 2:
showLogin();
break;
case 3:
default:
break;
}
}
int main()
{
showMenu();
return 0;
}
This is the result when I choose 1:
As you see, I can not enter username. In function showRegister(), when I add cin.ignore() before getline(cin, user), this is the result:
As I understand, getline() reads a line until it reaches character \n and skip the rest. So why in this case, two successive getline() commands (getline(cin, user) and getline(cin, pw) lead to the fact that I can not enter username?
The fact is getline takes input from buffer if something exists in buffer else it ask the user for value. What actually happens in your code is as soon as you enter value for select which is not greater than 3 it comes out of the loop after with a value you entered for select and the entered (which stands for \n) that you pressed get stored in buffer. So know when you come to getline for user it sees '\n' from the buffer as getline first check in buffer, so it skip the value insertion and buffer gets emptied and now when you come to getline that is used for password it ask the user for password as buffer was empty.
This will happen always after an switch from a formatted input to an unformatted input. Like from std::cin >> select to std::getline
The formatted input will read your integer "select", but not the following CR LF. (You pressed the enter key).
To solve that problem, you can simply write:
getline(cin >> std::ws, user);
std::ws will first consume the leading white space. Then the std::getline will work as expected.
Please read here about std::ws and do not forget to include <iomanip>
There are more severe bugs in your code. Like a cicrular call to "showMenu"

How do I use the enter key to create new line, rather than inputting string?

I have to write a program that allows the user to enter a multiline poem, pressing the enter key to create a new line in the poem. All lines of the poem need to be stored in a single string, and I'm not sure how to concatenate the "\n" to user input. Additionally, once the user is done with the poem, I'm not sure how to then move on and execute further code in the program.
Here is the code I have so far:
/*
Poetry In Motion; Cortez Phenix
This program allows the user to make a poem, and the program contains a
poem game. The most notable features are loops controlled by the user.
*/
#include <string>
#include <iostream>
using namespace std;
void makePoem()
{
string user_input;
cout << "Enter a poem of your own creation, one line at a time.\n";
cout << "Type 'quit' to exit the program.\n\n";
cout << "Type your poem, pressing the enter key to create a new line.\n\n";
cin >> user_input;
if (user_input == "quit")
{
cout << "\nGoodbye! Have a great day.\n";
}
else
{
getline(cin, user_input);
}
}
int main()
{
makePoem();
return 0;
}
Apologies if this question is too vague or such. Thanks for the help.
You need to read the user's input in a loop, appending each line to your target string, eg:
/*
Poetry In Motion; Cortez Phenix
This program allows the user to make a poem, and the program contains a
poem game. The most notable features are loops controlled by the user.
*/
#include <string>
#include <iostream>
using namespace std;
void makePoem()
{
string poem;
string user_input;
cout << "Enter a poem of your own creation, one line at a time.\n";
cout << "Type 'quit' to exit the program.\n\n";
cout << "Type your poem, pressing the enter key to create a new line.\n\n";
while (getline(cin, user_input))
{
if (user_input == "quit")
break;
poem += user_input;
poem += '\n';
}
cout << "\nGoodbye! Have a great day.\n";
}
int main()
{
makePoem();
return 0;
}
This looks like a homework problem so I wont give you actual code but here are some clues :
You need a loop that keeps going until the user enters "quit"
You then simply add the user input to the user_input string using the += operator
To add a newline to a string you add "\n" ex : user_input += "\n";

C++ can't have cin.ignore() after cin?

I'm having an issue using cin.ignore(), if I use it after a cin >> statement it doesn't seem to work and ends the program instead.
Here's my code:
#include "stdafx.h"
#include <iostream>
using namespace std;
int number ;
int main () {
cin >> number;
cout << number;
cin.ignore()
return 0;
}
I am typing " 4 " (without quotes) at the prompt. I'm expecting it to prompt for an int (which it does) and then display that int until the user presses enter again. However as soon as I press enter on the first prompt the program closes. If I replace the cin.ignore() with a new cin >> then it waits until I enter data at that prompt before closing, however this way I have to put data into the prompt, I can't just press enter to close it.
I read about putting cin.clear() after the cin input but that didn't help. If I replace cin.ignore() with cin >> num2; then it works fine.
What am I doing wrong?
You can reset your input stream and ignore the rest of it if for example your user did not enter a valid int type as input. The while loop will not exit until number contains an actual integer. After that, if you want the program to wait until the user presses "Enter" or any other key, you can just call ignore again.
#include <limits>
#include <iostream>
int main()
{
int number;
// we need to enforce that the input can be stored as `int` type
while(!(std::cin >> number))
{
std::cout << "Invalid value! Please enter a number." << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
std::cout << "Your number is: " << number << std::endl;
// wait for user to press Enter before exiting
// you can do this with ignore() x2 once for the newline
// and then again for more user input
std::cout << "Press Enter to exit." << std::endl;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
return 0;
}

Program that takes a sentence and outputs # of vowels, consonants, etc

enter code here
int main()
{
std::string input;
std::cin >> input;
while (input != "quit")
{
// do stuff
std::cin >> input; // get another input
}
return EXIT_SUCCESS; // if we get here the input was quit
The problem is, it isn't prompting the user to enter words at all. If I enter "quit", it ends, so that's working fine. Otherwise, if I enter in anything else, then enter quit, it just quits as well. What should I do to rectify that?
Through my research, I was able to find a similar program here which uses case, but that seems a bit tedious to me. I have been instructed to use the isalpha function, which accepts a single character as a parameter and returns a Boolean indicator as to whether or not the character is a letter.
Try this small illustrative program:
#include <iostream>
#include <cstdlib>
int main(void)
{
std::cout << "This is a prompt, enter some text:\n";
std::string the_text;
std::getline(std::cout, the_text); // Input the text.
std::cout << "\n"
<< "The text you entered:\n";
std::cout << the_text;
std::cout << "\n";
// Pause the program, if necessary.
std::cout << "\n\nPaused. Press Enter to continue...\n";
std::cin.ignore(10000000, '\n');
// Return status to the Operating System
return EXIT_SUCCESS;
}
As you can see, outputting an instructional phrase before an input is known as prompting the User.
Edit 1: Prompting in a while loop
In your case, you need to prompt the user before the input:
while (input != "quit")
{
// Do stuff
std::cout << "Enter text or \"quit\" to quit: ";
std::cout.flush(); // Flush buffers to get the text on the screen.
std::cin >> input;
}