newline character left in the cin.get() buffer - c++

I am using cin.get(input).ignore(INT_MAX, '\n'); in my code. this statement is being called in a while loop to choose an option in a menu.
Although I am using ignore chained with cin.get() for every input I am reading in, sometimes a newline character remains in the cin buffer and I should press an extra 'Enter' to go to the normal process of the while loop for choosing an option.
what should I do to solve this problem?
int Menu::getChoice(int menuNum) // getChoice() returns users menu choice
{
int i = 0;
char input;
while(0 == i) // As long as users choice not valid
{
cout << "Make your choice: ";
cin.get(input).ignore(INT_MAX, '\n');
if (!cin.good())
{
cin.clear();
cin.ignore(INT_MAX, '\n');
}
i = atoi(&input);
if (menuNum == 1)
{
if (i < 1 || i > 2)
{
cout << "Not a valid choice!" << endl;
i = 0;
}
}
}
return i;
}

If I understand correctly, this issue is that sometimes in order for the code to move past cin, and to get the assignment for input, two new line characters are needed. If this is correct, than if you replace:
cin.get(input).ignore(INT_MAX, '\n');
with this:
cin >> input;
the issue will be resolved.

Related

Cin wants two inputs

In my code, a certain cin asks for two inputs(values or enter and values) instead of one, despite using cin.clear and cin.ignore. Anyone have an idea what the problem is?
PS Yes, there are 16 other functions and main() where you can choose which one you want to run. None of them have such a issue.
int fun;
char choice;
do {
cout << "text" << endl;
cin.clear();
cin.ignore( 255, '\n');
cin >> fun; // <<< THIS ONE
switch (fun) {
case 1:
twoNums();
break;
default:
cout << "wrong" << endl;
return 0;
}
cout << "text" << endl;
cin >> choice;
}
while(choice != 'n');
cout << "Quit." << endl;
return 0;
your use of cin.ignore is incorrect. move it to the spot where it is really required. In this case the new line has to be ignored just after the last integer has been read so that you can read in the choice.
Something like:
cout << "text" << endl;
cin >> fun; // <<< THIS ONE
switch (fun) {
case 1:
twoNums();
break;
default:
cout << "wrong" << endl;
return 0;
}
cout << "text" << endl;
cin.ignore( 255, '\n'); //move it here
cin >> choice;
Also take a look at this SO thread
When and why do I need to use cin.ignore() in C++?
Short answer:
You are misusing cin.ignore() and cin.clear(). Remove those two lines.
Long answer:
Let's go step by step through your code.
cin.clear();
First, you ask to clear flags on cin. There were not flags set, so it doesn't do anything.
cin.ignore( 255, '\n');
You ask to skip next 255 characters or up until '\n' is reached. The stream is empty, so none of these conditions is met until the end of input data. From documentation on std::basic_istream::ignore(), eof flag is set on stream and input characters are left in stream.
cin >> fun;
You try to extract data from stream, but eof flag is set. Extraction fails silently, fun becomes 0 if you are using C++11 standard or newer, or is left unitialized if you are using old compiler. I'm assuming modern compiler later on.
switch (fun) { }
case 0: or default: will be executed.
cin >> choice;
Again, eof bit set, extraction failed. choice is zeroed.
} while(choice != 'n');
'\0' != 'n', continue the loop.
Now comes the fun part, why it starts working at second loop iteration?
Lets go through the loop again:
cin.clear();
You clear the eof flag set in previous iteration, stream is non-empty and in good() state.
cin.ignore( 255, '\n');
You ignore the values inputted in the previous iteration. Depending on how you input values, but it will skip until first \n.
cin >> fun;
If the next value in the stream is integer, you have successful extraction! From now on, if values inputted are valid for the data type, the loop will work correctly.

Detect blank input on integer type variable?

I am currently working on a text based adventure game as a project for class. I have mostly everything started and working fine. The only problem is when I ask the user which room they want to change to, if they enter a blank input, then a message should output saying "You must choose a room." For the life of me I cannot figure it out. Any help is much appreciated.
Code:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
bool game_play = true;
bool game_start = true;
int room_change;
int room_current = 0;
while (game_play == true) {
if (game_start == true) {
srand((unsigned int)time(NULL));
room_change = rand() % 2 + 1;
game_start = false;
}
else {
for (bool check = false; check == false;) { // Check if input is invalid
cin >> room_change;
if (cin.fail()) {
cout << "Choose an existing room.";
cin.clear();
cin.ignore();
}
else if (room_change == room_current) {
cout << "You're already in that room.";
}
else {
check = true;
}
}
}
switch (room_change) {
case 1:
cout << "You are in room 1.";
room_current = 1;
break;
case 2:
cout << "You are in room 2.";
room_current = 2;
break;
case 3:
game_play = false;
break;
default:
cout << "That room doesn't exist.";
}
}
return 0;
}
I just ran your code and when you hit enter, it will keep waiting until you enter a number or something invalid such as a character or a string. I did find that if you change your code from
cin >> room_change;
to
cin >> noskipws >> room_change;
when the user inputs a blank, it will cause the cin.fail() to return true and then proceed to print "Choose an existing room."
In your situation, the while loop will keep getting called until we have valid input. The "Choose an existing room" does get repeated because room_change is an integer, so when we hit enter, the '\n' will be left in the buffer. The while loop on the next iteration then reads that '\n' and executes the cin.fail() before letting you input something else. One solution I found is to use more cin.ignore() statements.
for (bool check = false; check == false;) { // Check if input is invalid
cin >> noskipws >> room_change;
if (cin.fail()) {
cout << "Choose an existing room.";
cin.clear();
cin.ignore();
} else if (room_change == room_current) {
cout << "You're already in that room.";
cin.ignore();
} else {
check = true;
cin.ignore();
}
}
The reason is because we want to get rid of that '\n' so that the cin.fail() does not execute. However, I did find that when you input a character, it will print "Choose an existing room" twice. It will print the first time because a character is not an integer, and a second time because of that '\n'.
The only problem is when I ask the user which room they want to change to, if they enter a blank input, then a message should output saying "You must choose a room."
Using std::getline and then extracting the number from the line using a std::istringstream is a better strategy for that.
std::string line;
std::cout << "Choose an existing room. ";
while ( std::getline(std::cin, line) )
{
// Try to get the room_change using istringstream.
std::istringstream str(line);
if ( str >> room_change )
{
// Successfully read the room.
break;
}
// Problem reading room_change.
// Try again.
std::cout << "Choose an existing room. ";
}
#include <iostream>
using namespace std;
int main(){
int room_change=200;
cout<<"Enter Blank";
cin>>room_change;
if(room_change==NULL){
cout<<"There is NO-THING"<<endl;
}
if(room_change!=NULL){
cout<<"There is something and that is :"<<room_change<<endl;
}
return 0;
}
But a much simpler approach to this would be to use Strings. If this is a Homework of sort and you are limited to Integer variable only. Its much more complicated if you want to detect if an Buffer is empty or not. Regardless of homework limitation, the OS layer input is String based. How can I use cin.get() to detect an empty user input?

How to skip 'enter' in cin.ignore()

I write a code to check char 'exit' in int cin. But I find that I need to set delimiters in cin.ignore such as '\n' and input it when running command and I think that is not friendly.
How can I change the code to skip the extracting step , maybe using other code instead of cin.ignore?
Sorry for everyone who try to read my English and answer as I not a native English user.
I mean cin.ignore is to extracts and discards characters until the given character is found, is it have a way to clear the cin buffer in C++ with discarding characters without extracting?
void checkcin(int &y)
{
string input = "", ans;
cin.clear();
cin.ignore(INT_MAX, '\n');
getline(cin, input);
while (input == "exit")
{
cout << "Are you sure to exit: ";
cin >> ans;
if (ans == "yes")
{
cout << "Bye." << endl;
exit(0);
}
else if (ans == "no")
{
cout << "Then welcome back!";
cout << "Input again: ";
cin >> input;
}
}
y = std::stoi(input);
}
The first parameter in the "std::cin.ignore()" that you are using just comes down to a very large number. This should be the maximum number of characters that the input buffer can hold. This number may be different on different systems or even header files for different compilers.
You need to press enter twice because there is nothing in the buffer to ignore. It is waiting for something to be entered to ignore. some people will use this to pause the program before the "return 0;".

Not handling user input correctly

So, this program I am working on is not handling incorrect user input the way I want it to. The user should only be able to enter a 3-digit number for use later in a HotelRoom object constructor. Unfortunately, my instructor doesn't allow the use of string objects in his class (otherwise, I wouldn't have any problems, I think). Also, I am passing the roomNumBuffer to the constructor to create a const char pointer. I am currently using the iostream, iomanip, string.h, and limits preprocessor directives. The problem occurs after trying to enter too many chars for the roomNumBuffer. The following screenshot shows what happens:
The relevant code for this problem follows:
cout << endl << "Please enter the 3-digit room number: ";
do { //loop to check user input
badInput = false;
cin.width(4);
cin >> roomNumBuffer;
for(int x = 0; x < 3; x++) {
if(!isdigit(roomNumBuffer[x])) { //check all chars entered are digits
badInput = true;
}
}
if(badInput) {
cout << endl << "You did not enter a valid room number. Please try again: ";
}
cin.get(); //Trying to dum- any extra chars the user might enter
} while(badInput);
for(;;) { //Infinite loop broken when correct input obtained
cin.get(); //Same as above
cout << "Please enter the room capacity: ";
if(cin >> roomCap) {
break;
} else {
cout << "Please enter a valid integer" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
for(;;) { //Infinite loop broken when correct input obtained
cout << "Please enter the nightly room rate: ";
if(cin >> roomRt) {
break;
} else {
cout << "Please enter a valid rate" << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
}
Any ideas would be greatly appreciated. Thanks in advance.
Read an integer and test whether it's in the desired range:
int n;
if (!(std::cin >> n && n >= 100 && n < 1000))
{
/* input error! */
}
Although Kerrek SB provide an approach how to address the problem, just to explain what when wrong with your approach: the integer array could successfully be read. The stream was in good state but you didn't reach a space. That is, to use your approach, you'd need to also test that the character following the last digit, i.e., the next character in the stream, is a whitespace of some sort:
if (std::isspace(std::cin.peek())) {
// deal with funny input
}
It seems the error recovery for the first value isn't quite right, though. You probably also want to ignore() all characters until the end of the line.

How do I prevent a runaway input loop when I request a number but the user enters a non-number?

I need to know how to make my cin statement not appear to 'remove' itself if you input the wrong type. The code is here:
int mathOperator()
{
using namespace std;
int Input;
do
{
cout << "Choose: ";
el();
cout << "1) Addition";
el();
cout << "2) Subtraction";
el();
cout << "3) Multiplication";
el();
cout << "4) Division";
el();
el();
cin >> Input;
}
while (Input != 1 && Input != 2 && Input!=3 && Input!=4);
return Input;
}
Execute, enter, for example, a character, and it loops nonstop acting as though the cin statement isn't there.
You must check that input succeeded and handle when it doesn't:
int mathOperator() {
using namespace std;
int Input;
do {
cout << "Choose: ";
el();
cout << "1) Addition";
el();
cout << "2) Subtraction";
el();
cout << "3) Multiplication";
el();
cout << "4) Division";
el();
el();
while (!(cin >> Input)) { // failed to extract
if (cin.eof()) { // testing eof() *after* failure detected
throw std::runtime_error("unexpected EOF on stdin");
}
cin.clear(); // clear stream state
cin.ignore(INT_MAX, '\n'); // ignore rest of line
cout << "Input error. Try again!\n";
}
} while (Input != 1 && Input != 2 && Input!=3 && Input!=4);
return Input;
}
If you don't check that extraction succeeded, then cin is left in a failed state (cin.fail()). Once in a failed state, later extractions will immediately return instead of trying to read from the stream, effectively making them no-ops – leading to your infinite loop.
Unless you're quite certain about the input being in the proper format, you rarely want to use operator>> directly from the input stream.
It's usually easier to read a line with std::getline, put that into a std::istringstream, and read from there. If that fails, you print/log an error message, throw away the remainder of the line and (possibly) go on to the next line.
After reading in a bad value, cin is in a "failed" state. You have to reset this.
You must both clear the error flag and empty the buffer. thus:
cin.clear();
cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
The second call "flushes" the input buffer of any data that might be there, to get you ready for the next "cin" call.
If you find yourself writing these 2 lines "all over your code" you could write a simple inline function to replace it.
inline void reset( std::istream & is )
{
is.clear();
is.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
}
Although I have made this function take any istream, most of the time it would only be used for cin where a user is entering and enters something invalid. If it's an invalid file or stringstream input, there is no way to fix it and you would do best to just throw an exception.
don't read int, read char so cin will pass any invalid character
char Input;
do
{
// same code
}
while (Input != '1' && Input != '2' && Input != '3' && Input!='4');
return Input;
[EDIT]
If you want convert char to int you can use this piece of code
int i = (Input - 48);
I agree that a char is just as handy, since you can always cast to int, to answer your question as to why this is happening, when a cin input is exected as an int but a char is entered, the input is kept in the input stream for the duration of the loop, which is why it seems to "disappear."
For more information: see the post from Narue at http://www.daniweb.com/forums/thread11505.html