| | |
How do I flush the input stream?
Please support our C++ advertiser: Intel Parallel Studio Home
![]() |
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.
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
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:
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:
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):
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<char>. 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:
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:
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:
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:
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
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.
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:
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:
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
Now all three cases behave identically:
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.
C++ Syntax (Toggle Plain Text)
#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"; }
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:
C++ Syntax (Toggle Plain Text)
#include <istream> void ignore_line ( std::istream& in ) { char ch; while ( in.get ( ch ) && ch != '\n' ) ; }
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:
C++ Syntax (Toggle Plain Text)
#include <ios> #include <istream> #include <limits> void ignore_line ( std::istream& in ) { in.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' ); }
C++ Syntax (Toggle Plain Text)
in.ignore ( 80, '\n' );
[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<char>. 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:
C++ Syntax (Toggle Plain Text)
#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' ) ); }
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:
C++ Syntax (Toggle Plain Text)
#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"; }
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:
C++ Syntax (Toggle Plain Text)
#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"; }
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:
C++ Syntax (Toggle Plain Text)
#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"; }
The putback member function
C++ Syntax (Toggle Plain Text)
#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"; }
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.
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:
C++ Syntax (Toggle Plain Text)
#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"; }
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:
C++ Syntax (Toggle Plain Text)
#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; }
system ( "PAUSE" ); and getch();: C++ Syntax (Toggle Plain Text)
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(); } };
C++ Syntax (Toggle Plain Text)
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(); }
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.
Last edited by Narue; Feb 12th, 2008 at 5:26 pm.
I'm here to prove you wrong.
•
•
Join Date: Mar 2008
Posts: 25
Reputation:
Solved Threads: 0
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:
What is abiguous overload? And is there a known bug with istream in linux?
Doesn't work in linux. Anyone know why?
Compile time error message:
C++ Syntax (Toggle Plain Text)
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?
•
•
Join Date: Mar 2008
Posts: 25
Reputation:
Solved Threads: 0
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.
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.
•
•
•
•
Originally Posted by Naure
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?
Some people get so rich they lose all respect for humanity. That's how rich I want to be.
•
•
Join Date: Mar 2008
Posts: 25
Reputation:
Solved Threads: 0
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 :-)
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 :-)
![]() |
Similar Threads
- Do/While Loop help (C++)
- convert lower case letters to uppercase and vice-versa (C++)
- overloaded input stream help (C++)
- Noob : Input Stream Trouble (Java)
- string input not working as expected (C++)
- Print_Zero Function (C)
- Question:: reading from an input stream. (C++)
- How do I pause a Prorgam? (C++)
Other Threads in the C++ Forum
- Previous Thread: OpenPictureDialog killing LoadFromFile
- Next Thread: CalcOpticalFlowBM function in OpenCv
| Thread Tools | Search this Thread |
api array based beginner binary bitmap c++ c/c++ calculator char class classes code coding compile compiler console conversion count database delete deploy desktop developer directshow dll download dynamic dynamiccharacterarray email encryption error file forms fstream function functions game givemetehcodez google graph gui homeworkhelp homeworkhelper iamthwee ifstream int integer java lib linkedlist linker linux list loop looping loops map math matrix memory multiple news node number output parameter pointer problem program programming project python read recursion recursive reference return rpg string strings struct temperature template templates test text text-file tree unix url variable vector visualstudio win32 windows winsock word wordfrequency wxwidgets





