3

I am finding it difficult to wrap my head around working of stringstream. Why the second while loop in the below code does not work? If stream object is getting emptied at the end of the first while loop is there any workaround to restore it back to initial condition?

// input is string of numbers separated by spaces (eg. "22 1 2 4")
    std::string input;
    std::getline(std::cin, input); 

    stringstream stream (input);

    // print individual numbers
    while (stream >> n)
    {
        cout << n << endl;
    }

    // print individual numbers again
    while (stream >> n)
    {
        cout << n << endl;
    }
Siddhesh
  • 472
  • 1
  • 9
  • 24

3 Answers3

2

stringstream is a subclass of istream, so stream >> n (std::istream::operator>>) returns a reference to istream

stream can be converted to bool (std::ios::operator bool): it converts to false when it no longer has any data (reached end-of-file)

You have finished reading stream in your first loop - it no longer has any data.

If stream object is getting emptied at the end of the first while loop is there any workaround to restore it back to initial condition?

You need to store values on your own and then reuse them - copying streams is not allowed (it doesn't make sense for them really) - Why copying stringstream is not allowed?

Adam Kotwasinski
  • 4,377
  • 3
  • 17
  • 40
2

It's not emptied, but once you reach the end, you're stuck at the end – just like with other streams.

You need to clear the error flags (stream.clear()) and then either rewind (stream.seekg(0)) or reset the input string (stream.str(input)).

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
  • In the existing code, `failbit` will also be set because it tries to read again after eof is reached. Calling `seekg` does _not_ reset that. – Useless Nov 16 '18 at 11:14
1

You need to create the stringstream first, in order to make multiple passes over what you have read into input. input itself is just a string not stream. #include <sstream> and then after reading input create the stringstream with:

std::stringstream stream (input);

You can then read with your first while loop, but the second while will not work because the stream position is left at the end of the stringsteam after the first while and eofbit is set.

You need call stream.seekg(0) to "rewind" the file and clear eofbit, see: std::basic_istream::seekg before the second while loop.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85