2

I need to try to peek multiple characters from a std::istream (which could be std::cin), so I wrote a simple loop to call get() lots of times and then putback() lots of times:

std::vector<char> peek_many(std::istream& is, int N) {
    std::vector<char> data;
    data.reserve(N);

    for (int i = 0; i < N; ++i) {
        data.push_back(is.get());
    }   

    for (int i = 0; i < N; ++i) {
        is.putback(data[N-i-1]);
    }

    return data;
}

Is this guaranteed to work on all istreams (whether I'm reading a file, cin, istringstream, etc)? If not, why not?

Barry
  • 286,269
  • 29
  • 621
  • 977
  • `std::istringstream` is input-only, it can only be read from, you can't `putback()` data into it. – Remy Lebeau May 04 '16 at 21:04
  • 1
    Off topic, wouldn't it be better to return a shorter vector if `EOF` was reached, instead of returning a vector with trailing `EOF`s? – LogicStuff May 04 '16 at 21:10
  • @Remy Citation needed – Alan Stokes May 04 '16 at 21:38
  • 1
    @AlanStokes: Run the example code at http://en.cppreference.com/w/cpp/io/basic_istream/putback. The `putback()` fails on an `std::istringstream`, and is commented as such. – Remy Lebeau May 04 '16 at 21:42
  • 3
    @RemyLebeau You can't *modify* it - but you can put the same characters back - which is what I'm trying to do. – Barry May 04 '16 at 21:46

2 Answers2

2

It is only safe to assume 1 character "wide" put back buffer. You will have to add additional layer of abstraction to provide more put back space.

Alternatively, if your stream is seekable, you can remember the position before you start tentatively parsing and then seek back to the remembered position.

wilx
  • 17,697
  • 6
  • 59
  • 114
  • What would such an abstraction look like? – Barry May 04 '16 at 21:24
  • 2
    An extra level of buffering in your code. You read data from the stream into your own buffer of sufficient size, and then you can read/peek data from the buffer as needed without trying to put the data back into the stream. – Remy Lebeau May 04 '16 at 21:44
  • Or you could call `[pub]setbuf` to tell the `streambuf` that you want a bigger buffer - except that sadly in general that has no useful well-defined behaviour. – Alan Stokes May 04 '16 at 22:20
1

putback calls sputback which only works if a putback position is available. Nothing guarantees that there is an indefinite number of such positions.

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64