PDA

View Full Version : [C++] Flushing cin buffer



babyhuey
October 7th, 2008, 03:06 AM
What is the best way to flush cin after it fails?

For example:


int variable;
cin >> variable;
...


In this case cin would create an infinite loop if the user entered a character; It fails until you get the buffer flushed.
I'm worried about someone entering other data types, not the range of integers.

cabalas
October 7th, 2008, 03:28 AM
Checking out http://cppreference.com/wiki/io/start should be helpful, now I haven't tested the following code so it may not work



int v = 0;

cin >> v; // I think you can also wrap this in a if statement

if(cin.fail())
cin.flush()

babyhuey
October 7th, 2008, 03:30 AM
I don't think its that simple.(though it should be)
cin.flush() only flushes the failed state flag, and returns it to true.

Nevermind, I had cin.flush() and cin.clear() mixed up.
cin.flush() doesn't seem to in iostream, I'm guessing its not part of standard c++

cabalas
October 7th, 2008, 03:42 AM
I don't think its that simple.(though it should be)
cin.flush() only flushes the failed state flag, and returns it to true.

You are right, it's been a while since I wrote a commandline c++ app where I've needed to check user input. Had a bit of downtime so I ran up a simple example which works for me:



#include <iostream>

int main()
{
int in = 0;
do {
std::cout << "Enter a number (10 to exit): ";
std::cin >> in;

if(std::cin.fail()) {
in = 0;
std::cin.clear();
std::cin.get();
}
} while(in != 10);

return 0;
}

babyhuey
October 7th, 2008, 03:53 AM
Thanks, that last one works. Though I swear I tried that almost exactly. :)

dwhitney67
October 7th, 2008, 03:57 AM
You are right, it's been a while since I wrote a commandline c++ app where I've needed to check user input. Had a bit of downtime so I ran up a simple example which works for me:



#include <iostream>

int main()
{
int in = 0;
do {
std::cout << "Enter a number (10 to exit): ";
std::cin >> in;

if(std::cin.fail()) {
in = 0;
std::cin.clear();
std::cin.get();
}
} while(in != 10);

return 0;
}


The get() won't work unless the erroneous input is a single character.

The better option is to use ignore().



...
int number = 0;

while ( true )
{
std::cout << "Enter a number: ";
std::cin >> number;

if ( !std::cin.fail() )
break;

std::cin.clear(); // clear the flags
std::cin.ignore( 1024, '\n' ); // ignore at most 1024 chars until '\n' found
}
...

babyhuey
October 7th, 2008, 04:12 AM
The get() won't work unless the erroneous input is a single character.

The better option is to use ignore().



...
int number = 0;

while ( true )
{
std::cout << "Enter a number: ";
std::cin >> number;

if ( !std::cin.fail() )
break;

std::cin.clear(); // clear the flags
std::cin.ignore( 1024, '\n' ); // ignore at most 1024 chars until '\n' found
}
...



Just found this out myself and came back here to post it :lolflag:

babyhuey
October 7th, 2008, 05:25 AM
In an attempt to streamline this process I tried this:


int number = 0;
cin >> number;
while(cin.fail()){
cin.clear();
cin.ignore(1024, '\n');
cin >> number;
}

I don't see why this would start an infinite loop. Any ideas?
I can't believe I'm having such trouble with the smallest tasks of the program :(

dwhitney67
October 7th, 2008, 09:29 AM
Your streamlined effort works for me; I cannot understand what problem you are having. Would you care elaborate more?

I tried entering "abc" and the code worked as expected. When I entered an integer, the while-loop terminated.

P.S. Streamlining is wonderful, however in this case, it would be better to point out the operator's error and prompt them again as to what you want entered. Hence the code snippet I submitted earlier is probably your best bet.

hod139
October 7th, 2008, 05:30 PM
Is this what you are looking for: http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.3



while(!(std::cin >> variable))
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
}

gnusci
October 7th, 2008, 08:00 PM
In an attempt to streamline this process I tried this:


int number = 0;
cin >> number;
while(cin.fail()){
cin.clear();
cin.ignore(1024, '\n');
cin >> number;
}

I don't see why this would start an infinite loop. Any ideas?
I can't believe I'm having such trouble with the smallest tasks of the program :(

It works fine for me too... Which version of the compiler do you use?, post the output of this command:

$ gcc --version

babyhuey
October 7th, 2008, 11:21 PM
Your streamlined effort works for me; I cannot understand what problem you are having. Would you care elaborate more?

I tried entering "abc" and the code worked as expected. When I entered an integer, the while-loop terminated.

P.S. Streamlining is wonderful, however in this case, it would be better to point out the operator's error and prompt them again as to what you want entered. Hence the code snippet I submitted earlier is probably your best bet.

Well, after coming back today it worked just fine. Apparently something was being wonky until I did a reboot. I ended up making a generic function sense it was going to be called many times.


void cinflush(){
//made it a loop in case for some god awful reason the buffer
//is over 1024bytes
while(cin.fail()){
cin.clear();
cin.ignore(1024, '\n');
cout << "Input invalid, try again\n";
}
}


For example, call it by:


int number;
cout << "Enter a number";
cin >> number;
while(cin.fail()){
cinflush();
cin >> number;
}