When you want to remove extraneous characters from an input stream in C++, it's usually because you mixed formatted and unformatted input methods. The formatted method would leave a newline in the stream and the unformatted method would consume it and terminate successfully, but fail completely to do what you wanted.

#include <iostream>

int main()
{
  std::cout<<"Enter the letter A: ";
  std::cin.get();
  std::cout<<"Enter the letter B: ";
  std::cin.get();
  std::cout<<"Too late, you can't type anymore\n";
}

Often this question stems from another question, which is how to pause a program before it terminates. Using cin.get() works only when there are no characters left in the stream. The instant you throw a cin>> foo; in the code, suddenly the solution fails. You need to clear out any leftover characters from the stream before it'll work again.

So how do you fix the problem? The good news is that unless you want to get picky, it's as simple as a loop:

#include <istream>

void ignore_line ( std::istream& in )
{
  char ch;

  while ( in.get ( ch ) && ch != '\n' )
    ;
}

This loop simply reads characters until end-of-file or a newline is read. It's generally assumed that interactive input in C++ is line-oriented and you're guaranteed to have a clean buffer after reading a newline. While that's not true (input doesn't have to be line-oriented), it's wide spread enough that we can assume it for the purposes of this thread.

So what's wrong with this approach? Nothing. In fact, this is about as good as it gets unless you want to dig down and fix the subtle problems. But before we look at the problems, here's an alternative solution that does the same thing in a different way:

#include <ios>
#include <istream>
#include <limits>

void ignore_line ( std::istream& in )
{
  in.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' );
}

The ignore member function of std::istream will read and discard up to N characters or until a delimiter. In the above example, N is represented by the largest value of the streamsize data type, and the delimiter is a newline. It works equally well with just a large value (80 is common):

in.ignore ( 80, '\n' );

However, the streamsize data type is more likely to be an accurate representation of the size of the buffer that the stream is using, and it's more likely to work all of the time. This is the solution that I recommend.

[author's note]
If you don't care about the advanced stuff and the above solves your problem, you can stop reading here.
[/author's note]

So what's wrong with this? There are two notable problems. The first is easy to fix, and it stems from the fact that istream isn't very flexible. istream is actually a typedef for basic_istream. If you want a wide stream to work with ignore_line, you're SOL with istream. So the trick is to use basic_istream<> instead:

#include <ios>
#include <istream>
#include <limits>

template <typename CharT>
void ignore_line ( std::basic_istream<CharT>& in )
{
  in.ignore ( std::numeric_limits<std::streamsize>::max(), in.widen ( '\n' ) );
}

Now ignore_line is a template function that will derive the type of characters that the stream contains from the first argument. You can pass any stream that derives from or specializes basic_istream, and the problem is gone. Instead of just '\n', it's a good idea to use widen on the literal so that it will be properly converted to a wider type if necessary. Nice and easy.

The second problem is harder. Much harder. It's harder because standard iostreams seem to block your way at every turn with lack of portability or undesired features. In fact, it's impossible to completely fix the problem. The problem is that the behavior is different depending on the contents of the stream. For example:

#include <iostream>
#include <ios>
#include <istream>
#include <limits>

template <typename CharT>
void ignore_line ( std::basic_istream<CharT>& in )
{
  in.ignore ( std::numeric_limits<std::streamsize>::max(), in.widen ( '\n' ) );
}

int main()
{
  std::cout<<"First input: ";
  std::cin.get();
  std::cout<<"Clearing cin.\n";
  std::cin.clear();
  ignore_line ( std::cin );
  std::cout<<"All done.\n";
}

Run this program three times:

Input: "asdf"
Output: The program finishes without any more input from you.

Input: Just hit Enter
Output: The program waits for you to hit Enter one more time.

Input: Signal EOF
Output: The program waits for you to hit Enter one more time.

The problem is that the stream is empty. If you hit Enter immediately, a newline is placed on the stream and consumed by cin.get. Likewise with signaling EOF. At that point there's nothing left in the stream and cin.ignore stops everything until you type more characters. This is because cin.ignore is a blocking read. If there's nothing to read, it waits.

What we'd like it to do is not block for any of those three cases. The good news is that the iostream library supports some possible solutions. The bad news is that these are dead ends. Here are two common ones:

The sync member function

The istream class supports a member function called sync. Why it has such a function is under debate, because nobody can agree on what it should be doing. Even Bjarne Stroustrup himself incorrectly stated that it discards all characters in the stream:

#include <iostream>

int main()
{
  std::cout<<"First input: ";
  std::cin.get();
  std::cout<<"Clearing cin.\n";
  std::cin.clear();
  std::cin.sync();
  std::cout<<"All done.\n";
}

When this works, it works beautifully. The bad news is that the C++ standard doesn't require sync to do anything like discarding extraneous characters. This solution is non-portable.

The in_avail member function

The next step is to look at the in_avail member function of istream's stream buffer. At first glance it looks like this member function will tell you how many characters are in the stream, and if it returns 0, you can refrain from calling ignore:

#include <iostream>
#include <ios>
#include <istream>
#include <limits>

template <typename CharT>
void ignore_line ( std::basic_istream<CharT>& in )
{
  if ( in.rdbuf()->in_avail() > 0 )
    in.ignore ( std::numeric_limits<std::streamsize>::max(), in.widen ( '\n' ) );
}

int main()
{
  std::cout<<"First input: ";
  std::cin.get();
  std::cout<<"Clearing cin.\n";
  std::cin.clear();
  ignore_line ( std::cin );
  std::cout<<"All done.\n";
}

As with sync, when this works, it works great. But once again, the standard raises a wall by saying that in_avail isn't required to give you an accurate representation of the characters in the stream. In fact, some popular implementations have a strictly conforming in_avail that always returns 0. Not very useful. Now we have to get creative.

The putback member function

#include <iostream>
#include <ios>
#include <istream>
#include <limits>

template <typename CharT>
void ignore_line ( std::basic_istream<CharT>& in )
{
  if ( !in.putback ( in.widen ( '\n' ) ) )
    in.ignore ( std::numeric_limits<std::streamsize>::max(), in.widen ( '\n' ) );
  else
    in.ignore();
}

int main()
{
  std::cout<<"First input: ";
  std::cin.get();
  std::cout<<"Clearing cin.\n";
  std::cin.clear();
  ignore_line ( std::cin );
  std::cout<<"All done.\n";
}

This looks very promising because at first glance, it seems that you can attempt to push back a newline. If the operation fails, the last read character wasn't a newline and you're free to call ignore without blocking. If the operation succeeds, the newline is back and you can remove it with a single character ignore.

Sadly, it doesn't work. putback isn't not required to do any of this predictably, which raises the question of why it's even available. :rolleyes:

But putback actually takes us close to a solution that seems plausible enough to work most of the time. Instead of relying on putback to fail or not, we can guarantee that the last read character is put back by using the sungetc member function of the stream's buffer. The trick is to unget the last character, then read it again and test it against a newline:

#include <iostream>
#include <ios>
#include <istream>
#include <limits>

template <typename CharT>
void ignore_line ( std::basic_istream<CharT>& in )
{
  if ( in.rdbuf()->sungetc() != std::char_traits<CharT>::eof()
    && in.get() != in.widen ( '\n' ) )
  {
    in.ignore ( std::numeric_limits<std::streamsize>::max(), in.widen ( '\n' ) );
  }
}

int main()
{
  std::cout<<"First input: ";
  std::cin.get();
  std::cout<<"Clearing cin.\n";
  std::cin.clear();
  ignore_line ( std::cin );
  std::cout<<"All done.\n";
}

The reason we use sungetc instead of istream's unget is because unget returns the stream, but sungetc returns either the character that was pushed back, or EOF. This way we can tell if the function failed or not more easily.

If sungetc fails, one of the following will be true:

  1. The stream is in an error state.
  2. There are no characters to unget.
  3. The stream doesn't support ungetting characters.

If sungetc succeeds, there will always be a character to read and test against the newline. If that character matches a newline, then the last read character was also a newline and we don't need to call ignore. If the character doesn't match, then a full line hasn't been read and we can safely call ignore without blocking.

If the stream is in an error state, that's something the calling code has to deal with. If there are no characters to unget, then that's precisely what this solution is designed to properly handle. But, if the stream doesn't support ungetting characters, that's an issue. The ignore_line function will always fail to discard characters, so for those implementations that don't support ungetting characters, we can add a flag that forces an ignore. It's sometimes useful to know how many characters were ignored as well, so let's add that too and we have the final solution:

#include <ios>
#include <istream>
#include <limits>

template <typename CharT>
std::streamsize ignore_line (
  std::basic_istream<CharT>& in, bool always_discard = false )
{
  std::streamsize nread = 0;

  if ( always_discard
    || ( in.rdbuf()->sungetc() != std::char_traits<CharT>::eof()
    && in.get() != in.widen ( '\n' ) ) )
  {
    // The stream is good, and we haven't
    // read a full line yet, so clear it out
    in.ignore ( std::numeric_limits<std::streamsize>::max(), in.widen ( '\n' ) );
    nread = in.gcount();
  }

  return nread;
}

Just for good measure, I'll also include a manipulator that calls ignore_line and also a manipulator that uses ignore_line to pause the program. That way the unwashed masses can stop using system ( "PAUSE" ) and getch():

class ignoreline {
  bool _always_discard;
  mutable std::streamsize _nread;
public:
  ignoreline ( bool always_discard = false )
    : _always_discard ( always_discard ), _nread ( 0 )
  {}

  std::streamsize gcount() const { return _nread; }

  template <typename CharT>
  friend std::basic_istream<CharT>& operator>> (
    std::basic_istream<CharT>& in, const ignoreline& manip )
  {
    manip._nread = ignore_line ( in, manip._always_discard );
    return in;
  }
};

class pause {
  ignoreline _ignore;
public:
  pause ( bool always_discard = false )
    : _ignore ( always_discard )
  {}

  std::streamsize gcount() const { return _ignore.gcount(); }

  template <typename CharT>
  friend std::basic_istream<CharT>& operator>> (
    std::basic_istream<CharT>& in, const pause& manip )
  {
    if ( !( in>> manip._ignore ) )
      in.clear();

    std::cout<<"Press Enter to continue . . .";

    return in.ignore();
  }
};

Now all three cases behave identically:

int main()
{
  std::cout<<"First input: ";
  std::cin.get();
  std::cout<<"Clearing cin.\n";
  std::cin>> ignoreline();
  std::cout<<"All done.\n";
  std::cin>> pause();
}

And the moral of the story is: It's never as simple as it seems, writing portable code that does what you want is extremely difficult, and the iostream library is a huge mess.p.s. While I haven't yet discovered a portability issue with this solution in the standard, it doesn't mean that one doesn't exist. However, I'm confident enough in my ability to parse the legalese in the standard document that I don't foresee any problems presently.

This has been a public announcement from your friendly neighborhood C++ hacker. We now return you to your regularly scheduled programming.

SpS commented: Amazing +4
Dave Sinkula commented: You will save me much typing. +11

Recommended Answers

All 30 Replies

Member Avatar for iamthwee

I'd much rather read everything in as a string then convert to ints or doubles wherever necessary.

>I'd much rather read everything in as a string then convert to ints or doubles wherever necessary.
You're so boring, iamthwee. Why do things the conventional way when you can flex your brainy muscles and solve a problem the hard way? :)

Member Avatar for iamthwee

Well there you go, maybe this might also be better submitted as a tutorial as opposed to a random one off thread?

About flush the input stream, I'll check it out, Thank you for your work.


Daniweb - Friendly online community for C++ learners with accurate tutorials.

Works great! Thanks so much!

works great for windows. I saved it as ignoreline.h and use it as an include.

Doesn't work in linux. Anyone know why?

Compile time error message:

clearTheStream.cpp: In function ‘int main()’:
clearTheStream.cpp:24: error: ambiguous overload for ‘operator>>’ in ‘std::cin >> pause()’
/usr/include/c++/4.2/istream:131: note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>& (*)(std::basic_istream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] <near match>
/usr/include/c++/4.2/istream:135: note:                 std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>] <near match>
/usr/include/c++/4.2/istream:142: note:                 std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>] <near match>
/usr/include/c++/4.2/istream:250: note:                 std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = char, _Traits = std::char_traits<char>] <near match>
/usr/include/c++/4.2/backward/ignoreline.h:54: note:                 std::basic_istream<CharT, std::char_traits<_CharT> >& operator>>(std::basic_istream<CharT, std::char_traits<_CharT> >&, const ignoreline&) [with CharT = char]
/usr/include/c++/4.2/backward/ignoreline.h:72: note:                 std::basic_istream<CharT, std::char_traits<_CharT> >& operator>>(std::basic_istream<CharT, std::char_traits<_CharT> >&, const pause&) [with CharT = char]

What is abiguous overload? And is there a known bug with istream in linux?

after looking up ambiguous, I'm wondering if this code could or should be rewritten so it can be called as a member function instead of as cin >> pause(). Don't know, just throwing the idea out there. I don't even know how to begin doing that. I just copy and pasted but don't fully understand the above code yet.
Like I said it works in windows compiled with dev c++, just not in linux with g++.

Thanks for the code. I'll be able to use it in windows apps till I find out the problem with linux.

You're so boring, iamthwee. Why do things the conventional way when you can flex your brainy muscles and solve a problem the hard way?

Why should you complicate things while there is a easy way out, I mean C++ alone is complicated

looks like Naure covered a lot of bases with one class of functions which is great.

I appreciate your comedy ruotine Traicey, but if there is an easier way to be able to flush,empty,ignore (what ever you want to call it, it accomplishes the goal), would you please explain and post the code?

Again if anyone knows why I'm getting the compile error posted above when using g++ in linux (ubuntu) would you please help me out?

Thanks :-)

>Again if anyone knows why I'm getting the compile error posted above when
>using g++ in linux (ubuntu) would you please help me out?

I had nothing better to do, so I decided to screw around with the code Narue posted. You're correct in that g++ gives an error when compiling the 'pause' class. Try renaming the entire 'pause' class to something else, perhaps pause2 (in other words, do an entire find and replace with 'pause'), and it'll compile fine. I asked Narue about this on IRC, and she figured it was probably some gcc/g++ extension that was messing things up (which is obviously the only real possibility here).

commented: ? +0

Thank you John A and Narue.

I never would have thought of something like that since I'm a noob. I don't know enough to decide between windows, linux and the different compilers who is complying with c++ standards and who is not fully compliant. You are a real help.
Thanks for the hard work coding this and thanks for looking into my g++ problem.

commented: I think Windows is more practic but the truth is that Linux is more safe is you want to keep your file well saved +0

That's why Edward puts as much code as possible in namespaces. Compilers are bad about including all kinds of unexpected stuff in the standard headers, so even if you don't include unistd.h yourself, iostream or another standard header might do it for you and create a name conflict.

commented: I hope you return! =) +5

I can not find unistd.h anywhere on my system.

So let me see if I understand this.

POSIX is the linux API just like there's a Windows API.

By changing pause to pause2, we have something that complies to c++ standards, Windows API standards, and POSIX standards.

Is that how it works? I guess just learning c++ will not be enough if I want to program cross platform?

Is one or the other of the above mentioned not 100% following standards or is that just the way it works?

Sorry so many questions but I don't understand this type of issue yet. Tell me if I'm way off in my way of thinking. Is this even a standards issue or something else?

Thanks

hmm nice topic. i leart the way...thanks to all.. :)

commented: Random useless comments just to get a link in the message. -2

Don't know how useful this is to anyone else, but I made a pdf set up for easy reading on my Irex Iliad digital book reader. I'm sure some of you have some Kindles or Sony Readers or whatever.

Anyway, here you go, my pdf I made of Narue's post. (By the way if you feel this is in some way a violation of your work feel free to remove it)

C++ string and getline are your friends so get to know them well :)

// flushinput.cpp
// A test program to test flushing input specifically cin
// Last Modified: 20081208

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <exception>
#include <stdexcept>
#include <new>
using namespace std;

int main()
{
cout << "flushinput" << endl;
cout << "A test program to test flushing input specifically cin." << endl;
string input1 = "";
string input2 = "";
cout << endl;
cout << "There are 5 input tests:" << endl;
cout << "1. Type 1 or more characters and then press Enter." << endl;
cout << "2. Just hit Enter(don't type any characters, just press Enter)." << endl;
cout << "3. Signal EOF(don't type any characters, Linux - just press Ctrl+D. Windows - just press Ctrl+Z and then Enter)." << endl;
cout << "4. Type 1 or more characters and then Signal EOF and then press Enter(Windows - press Enter a second time)." << endl;
cout << "5. Type 1 or more characters and then Signal EOF twice(Windows - press Enter twice after signalling EOF twice)." << endl;
cout << endl;
cout << "Correct solution would be that the program waits for you to enter the 2nd input regardless of what you entered for the 1st input." << endl;
cout << "Incorrect solution would be that the program finishes without asking for the 2nd input." << endl;
cout << endl;
cout << "Enter 1st input: ";
getline(cin, input1);
cerr << endl;// Input tests 1 - 5: L - Linux, W - Windows		L   L   L   L   LW
cerr << "cin.bad()=" << cin.bad() << endl;// Results:			0	0	0	0	00
cerr << "cin.eof()=" << cin.eof() << endl;//					0	0	1	0	10
cerr << "cin.fail()=" << cin.fail() << endl;//					0	0	1	0	00
cerr << "cin.good()=" << cin.good() << endl;//					1	1	0	1	01
cerr << "input1.size()=" << input1.size() << "!" << endl;//		3	0	0	3	33
	if(!cin.good())// Input tests 3(Windows & Linux) & 5(Linux only) put cin into an error state.
	{
	cin.clear();// Reset the cin status flags to their default.
	}
cout << endl;
cout << "Enter 2nd input: ";
getline(cin, input2);
cout << "Program finished." << endl;
return 0;
}

There are some minor differences between Linux and Windows which I have documented. For input tests 1, 4, & 5 I used:
abc
for the 1st input.

cout.flush ????

cout.flush ????

This is a discussion about flush the INPUT buffer....so this is a completely pointless post, before making a suggestion at least make it a viable suggestion

Chris

Why should you complicate things while there is a easy way out, I mean C++ alone is complicated

I totally agree with you, all you want to get is one line of string and see what you are supposed to do, as if it is rocket science..

I love it! Would it be possible to make cin.get() save the string as well as the escape character (commonly '\n'). This way it wouldn't ever be 'nothing' because you'd always get the \n character at least. I also have much use for the \n character because its easy to remove and sometimes annoying to re-add.

have you tried cin.ignore();

here's an example

#include <iostream>
using namespace std;

	int main(){
		int num = 0;

		//literal output
		cout << "enter a number";
		//input from keyboard(includes /n when enter is pressed)
		cin >> num;
		//variable output
		cout << "you entered: "<< num;
		//pause so output can be read
		cin.ignore();   //CLEAR INPUT STREAM
		cin.get();   //read any input
	}

Forget iostream.

#include <conio.h>
#define IOFLUSH {while(_kbhit())_getch();}
#define PAUSE {if(!_getch())_getch();}
commented: That's horrible advice -3

USe fflush() see it helps??

commented: "Survey says?" XXX -1

>have you tried cin.ignore();
That solution is incomplete, hence the existence of this thread. Did you even bother reading it?

>Forget iostream.
>USe fflush() see it helps??

Please don't riddle my thread with bad advice. If you don't understand why your solutions are hideous, you have no business suggesting them to other people. Learn first, then teach.

I think this thread has enough "advice" replied to the original post. Time for a lock.

that's the good question
i have just read about the output buffer
now i will work on this
thankx

I am not able to flush stdin here,is there a way to flush stdin?If not then how to make getchar() to take a character as input from user, instead of a "\n" left by scanf in the input buffer??

#include "stdio.h"
#include "stdlib.h"

int main(int argc,char*argv[]) {
    FILE *fp;
    char another='y';
    struct emp {
        char name[40];
        int age;
        float bs;
    };
    struct emp e;
    if(argc!=2) {
        printf("please write 1 target file name\n");
    }
    fp=fopen(argv[1],"wb");
    if(fp==NULL) {
        puts("cannot open file");
        exit(1);
    }
    while(another=='y') {
        printf("\nEnter name,age and basic salary");
        scanf("%s %d %f",e.name,&e.age,&e.bs);
        fwrite(&e,sizeof(e),1,fp);

        printf("Add another record (Y/N)");
        fflush(stdin);
        another=getchar();
    }
    fclose(fp);
    return 0;
}

I am not able to flush stdin here,is there a way to flush stdin?

The only portable way in C (ie. using the stdio library) is to read characters until a newline or end-of-file is found. Of course, this ends up causing a blocking read if the stream is already empty, which you'll find was one of the hurdles for a complete solution in Narue's original post. C++ offers a posibility to work around it, but C does not.

If not then how to make getchar() to take a character as input from user, instead of a "\n" left by scanf in the input buffer??

The '\n' left by scanf is a character as input from the user. Recognizing that when you type the Enter key a newline is placed in the stream is an important concept when working with stream I/O.

fflush(stdin);

Not such a hot idea. fflush is only defined for output streams. On one compiler fflush(stdin) may work fine and flush the stream. On another, it may not do jack diddly. On another, it might crash your computer, delete critical system files, or cause demons to fly out your nose. In other words, fflush(stdin) invokes undefined behavior.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.