9
#include <iostream>
int main( )
{
   using namespace std;
   cout << cin.rdbuf()->in_avail() << endl;
   cin.putback(1);
   cin.putback(1);
   cout << cin.rdbuf()->in_avail() << endl;
   return 0;
} //compile by g++-4.8.1

I think this will output 0 and 2

but when I run the code, it output 0 and 0, why?

or if I change cin.putback(1); to int a; cin >> a; with input 12 12;

it still outputs 0 and 0

miskcoo
  • 185
  • 1
  • 6
  • My guess is that it is because there was nothing in the stream at all, so it cannot 'putback' anything. Also, you might want to check the return value of putback() to see if it succeeded. – PeterK Jul 04 '13 at 15:58
  • @PeterK but if I do this --> int a; cin >> a; with input: 12 1222; I still get output 0 and 0 – miskcoo Jul 04 '13 at 16:00
  • Example showing that it happens even though `putback` succeeded: http://ideone.com/dUq3RF – interjay Jul 04 '13 at 16:15
  • 1
    Looking at the libstdc++ implementation, `putback` is implemented in such a way that here, it resolves to the C library function `ungetc`, and the buffer associated with `cin` has no knowledge of any pending characters. Looking at the standard, I cannot see the justification for this. –  Jul 04 '13 at 16:17
  • 3
    @hvd: It may be related to 27.5.3.4p3, which states that when `sync_with_stdio(true)` is in effect, `ungetc` has the same effect as `rdbuf()->sputbackc`. – interjay Jul 04 '13 at 16:23
  • 1
    @interjay I think you're right that that's related, and after `cin.sync_with_stdio(false);`, the behaviour changes. But it appears (note: appearances can be deceiving) to simply be implemented incorrectly, then... –  Jul 04 '13 at 16:49

2 Answers2

8

Apparently it's a bug/feature of some compiler implementations Insert the line

cin.sync_with_stdio(false);

somewhere near the beginning of code, and that should fix it

EDIT: Also remember that in_avail will always return 1 more than the number of chars in the input because it counts the end of input character.

EDIT2: Also as I just checked, putback does not work unless you have attempted to read something from the stream first, hence the "back" in "putback". If you want to insert characters into the cin, this thread will provide the answer: Injecting string to 'cin'

Community
  • 1
  • 1
MadOgre
  • 501
  • 6
  • 15
2

What must have happened is that your putback didn't find any room in the streambuf get area associated with std::cin (otherwise a read position would have been available and egptr() - gptr() would have been non-zero) and must have gone to an underlying layer thanks to pbackfail.

in_avail() will call showmanyc() and zero (which is the default implementation of this virtual function) is a safe thing to return as it means that a read might block and it might fail but isn't guaranteed to do either. Obviously it is possible for an implementation to provide a more helpful implementation for showmanyc() in this case, but the simple implementation is cheap and conformant.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656