I am using a istringstream to read a string word by word. However, when my condition fails I need to be able to revert the istringstream to before the previous word was read. My example code works, but I want to know if there is a more direct way to use streams to accomplish this.
std::string str("my string");
std::istringstream iss(str);
std::ostringstream ossBackup << iss.rdbuf(); // Writes contents of buffer and in the process changes the buffer
std::string strBackup(ossBackup.str()); // Buffer has been saved as string
iss.str(strBackup); // Use string to restore iss's buffer
iss.clear(); // Clear error states
iss >> word; // Now that I have a backup read the 1st word ("my" was read)
// Revert the `istringstream` to before the previous word was read.
iss.str(strBackup); // Restore iss to before last word was read
iss.clear(); // Clear error states
iss >> word; // "my" was read again
You can use tellg() and seekg() to save and restore your position if you like:
#include <string>
#include <sstream>
int main()
{
std::istringstream iss("some text");
std::string word;
// save the position
std::streampos pos = iss.tellg();
// read a word
if(iss >> word)
std::cout << word << '\n';
iss.clear(); // clear eof or other errors
iss.seekg(pos); // move to saved position
while(iss >> word)
std::cout << word << '\n';
}
This is really only guaranteed to work for stringstream's, but you can repeatedly call unget() until you've reached a space character:
#include <iostream>
#include <sstream>
template <int n>
std::istream& back(std::istream& is)
{
bool state = is.good();
auto& f = std::use_facet<std::ctype<char>>(is.getloc());
for (int i = 0; i < n && is; ++i)
while (is.unget() && !f.is(f.space, is.peek()));
if (state && !is)
is.clear();
return is;
}
int main()
{
std::stringstream iss("hello world");
std::string str;
std::cout << "Value Before: ";
iss >> str;
std::cout << str << std::endl;
iss >> back<1>; // go back one word
std::cout << "Value after: ";
iss >> str;
std::cout << str;
}
Live Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With