tags:

views:

174

answers:

3

Sorry for the noobish question here, but I am just learning C++ and I am looking for the standard way of dealing with this problem. I am using VS2005.

Given a program:

#include <iostream>

using namespace std;

int main( )
{
    while ( true )
    {    
        cout << "enter anything but an integer and watch me loop." << endl;  
        int i;
        cin >> i;      
    }
    return 0;
}

If you enter anything but an integer the program will never allow you to enter anything again. Now, I realize that this is because there is input left on the stream after the format fails, so each call to cin << i just reads up to the next end line (I think). How do you guys clear out the stream or deal with this problem? It must be pretty common.

A: 

cin.ignore(int num_bytes_to_ignore); will do it.

You can also use stdio, fflush(fd); where fd is one of stdout,stderr,stdin.

tim
I don't see an "flush" member function, and calling ignore before the cin >> i doesn't fix the problem.
Ed Swangren
I may just be using ignore( ) incorrectly, so an example would be nice.
Ed Swangren
Sorry, cin.flush doesn't exist indeed, fflush(stdin) is the one you want.
tim
I tried adding fflush( stdin ) before the call to cin and it still loops. There must be a standard way of dealing with formatted input, right?
Ed Swangren
fflush is undefined behavior on input stream.
AProgrammer
+2  A: 

surround the cin call with an if.

The cin will return false if wrong data is read.

so:

if (!cin >> i) {
  cin.clear();
  cin.ignore(INT_MAX, '\n');
  cout << "Haha, your looping efforts have been thwarted dear sir\n";
}

cin.flush() should do the trick (according to cppreference.com) but not on VS apparently.

cin.clear() resets all flags to a good state. cin.ignore with a large number and until '\n' should work.

NomeN
It returns a stream, which can be converted to a void*, which can be converted to true or false, but still I have to ask how to cope? Sure, I can detect the bad input, but then what? It is still on the stream
Ed Swangren
flush is not a member function of istream...
Ed Swangren
I should have mentioned that I am using VS2005
Ed Swangren
Well, I am using iostream, but cin is an istream
Ed Swangren
Yeah... that doesn't work, I've tried it. Are you testing this stuff?
Ed Swangren
sorry, can't at this time... So i'm using my google fu... add the cin.clear, and the consensus on the web is that it does the job.
NomeN
As suspected works perfectly for me.
Martin York
thank you, please upvote then ;-)
NomeN
After the last edit, yes, it does, but it is still not the proper way to do it. I found a better answer.
Ed Swangren
Honestly, while I do appreciate the effort, it is not the best way to handle the situation.
Ed Swangren
agreed, your answer is better
NomeN
Rather that INT_MAX I would use 'std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');'
Martin York
+1  A: 

Alright, I found the answer. The answer is...

Don't do this. Do not mix formatted and unformatted input using operator >>. Here is a good article on the subject:

http://www.cplusplus.com/forum/articles/6046/

Basically, the code changes to:

#include <iostream>
#include <string>
#include <stream>

using namespace std;

int main( )
{
    while ( true )
    {           
        cout << "enter anything but an integer and watch me loop." << endl;     
        string input;
        getline( cin, input );
        int i;
        stringstream stream( input );
        if ( stream >> i ) break;                       
    }
    return 0;
}
Ed Swangren
You could indeed have made i into a string and convert that.
NomeN
Yeah, I was looking for the canonical way to guard against bad input in C++. This seems to be it.
Ed Swangren
go ahead and accept the answer! And remove the downvotes, the answers are not actually wrong (anymore ;-)). But this one, although the code is ugly, works better and more professionally. good find!
NomeN
I didn't downvote anyone...
Ed Swangren
I have to wait 2 days before I can accept it. Thanks again (and yes, darn ugly code)
Ed Swangren
weird, people placing a downvote, should either upvote the right answer or supply a better one if they know better. At least add a comment...sheesh
NomeN