Home > Back-end >  std::stringstream's seekg does not work after while loop
std::stringstream's seekg does not work after while loop

Time:05-07

I have this std::stringstream object whose contents I have to read (only) twice. For this I thought I could use its seekg member function to repeat the reading. But I can't make it work. Here's a MWE that reproduces the issues I'm having (adapted from the example in the docs).

#include <iostream>
#include <string>
#include <sstream>

int main()
{
    const char *str = "Hello, world";
    std::stringstream ss(str);

    std::string word1 = "asdf";
    std::string word2 = "qwer";
    std::string word3 = "zxcv";
    std::string word4 = "yuio";

    ss >> word1;
    ss.seekg(0); // rewind
    ss >> word2;
    while (ss >> word3) { }
    ss.seekg(0); // rewind
    ss >> word4;

    std::cout << "word1 = " << word1 << '\n'
              << "word2 = " << word2 << '\n'
              << "word3 = " << word3 << '\n'
              << "word4 = " << word4 << '\n';
}

I expect the contents to be:

word1 = Hello,
word2 = Hello,
word3 = world
word4 = Hello,

since the call ss.seekg(0) after the while loop should put ss at the beginning of its contents. Why do I not get the expected output, but rather this?

word1 = Hello,
word2 = Hello,
word3 = world
word4 = yuio

This means that word4 is never updated, thus the statement ss >> word4 has no effect. But in this case, then the ss.seekg(0) does not have any effect either.

Is the while loop causing the ss object to fail to "rewind"? Perhaps the ss tried to read too much and now is in an error state (I have no idea).

How can I fix this? That is, how can I make the statement ss >> word4 read Hello,?

I'm using g (Ubuntu 11.1.0-1ubuntu1~20.04) 11.1.0 on C 17.

CodePudding user response:

seekg first constructs and checks the sentry object (used by cppstreams to represent any stream failure), if that sentry object represents any failure then the function just returns without doing anything.

After the while loop, ss's failbit and eofbit will be set. The call to seekg will behave as described before (won't do anything).

For seekg to take any affect, you will have to clear the failure bits by calling ss.clear()before calling seekg itself after the while loop. Then, the sentry object won't represent any failure and seekg will behave as expected.

Relevant links:

https://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt2

https://en.cppreference.com/w/cpp/io/basic_istream/seekg

  • Related