Resetting a Stringstream

resetting a stringstream

This is the way I usually do it:

ss.str("");
ss.clear(); // Clear state flags.

How do you clear a stringstream variable?

For all the standard library types the member function empty() is a query, not a command, i.e. it means "are you empty?" not "please throw away your contents".

The clear() member function is inherited from ios and is used to clear the error state of the stream, e.g. if a file stream has the error state set to eofbit (end-of-file), then calling clear() will set the error state back to goodbit (no error).

For clearing the contents of a stringstream, using:

m.str("");

is correct, although using:

m.str(std::string());

is technically more efficient, because you avoid invoking the std::string constructor that takes const char*. But any compiler these days should be able to generate the same code in both cases - so I would just go with whatever is more readable.

how to reuse stringstream

You didn't clear() the stream after calling str(""). Take another look at this answer, it also explains why you should reset using str(std::string()). And in your case, you could also reset the contents using only str(szLine).

If you don't call clear(), the flags of the stream (like eof) wont be reset, resulting in surprising behaviour ;)

How to clear stringstream?

Typically to 'reset' a stringstream you need to both reset the underlying sequence to an empty string with str and to clear any fail and eof flags with clear.

parser.str( std::string() );
parser.clear();

Typically what happens is that the first >> reaches the end of the string and sets the eof bit, although it successfully parses the first short. Operations on the stream after this immediately fail because the stream's eof bit is still set.

C++ - Does resetting stringstream not reset the get position or clear flags?

If you look at the state of the stream, this should be a bit clearer.

int main()
{
std::vector<std::string> words = { "10", "55", "65" };
std::istringstream word;
for (const auto &in : words)
{
word.str(in);
std::cout << "stream state:"
<< (word.rdstate() & std::ios::badbit ? " bad" : "")
<< (word.rdstate() & std::ios::failbit ? " fail" : "")
<< (word.rdstate() & std::ios::eofbit ? " eof" : "")
<< std::endl;
int number;
word >> number;

if (word.fail()) {
std::cerr << "Failed to read int" << std::endl;
return 1;
}

std::cout << in << ' ' << number << std::endl;
std::cout << "stream state:"
<< (word.rdstate() & std::ios::badbit ? " bad" : "")
<< (word.rdstate() & std::ios::failbit ? " fail" : "")
<< (word.rdstate() & std::ios::eofbit ? " eof" : "")
<< std::endl;
}
}

Which will result in:


stream state:
10 10
stream state: eof
stream state: eof
Failed to read int

So initially none of the flags are set, but reading the number reaches the end of the stream, setting eofbit. std::istringstream::str is defined as if to call rdbuf()->str(new_str). That says nothing about clearing flags.

Calling clear() will of course clear the eofbit, but so does calling seekg in C++11 or newer. "
Before doing anything else, seekg clears eofbit. (since C++11)".

Note that if you had say "10 20", that it will just discard the " 20", and not detect an error.


stream state:
10 20 10
stream state:
stream state:
55 55
stream state: eof
stream state: eof
Failed to read int

So you might actually want to check that eof flag to see if you read the entire stream.

As noted by others, of course constructing a new stream object each loop also means no concerns over previous flags/states.

Resetting std::stringstream format flags

How to reset stringstream?

Format flags are sticky.

You can save the old format flags to restore them later:

std::stringstream ss;
auto oldFlags = ss.flags(); // <<

ss << "0x" << std::uppercase << std::hex << 15;
std::cout << ss.str() << std::endl;

ss.flags(oldFlags); // <<

ss << 15;
std::cout << ss.str() << std::endl;

how to reset stringstream object

If you want a new ostringstream object each time through the loop, the obvious solution is to declare a new one at the top of the loop. All of the ostream types contain a lot of state, and depending on context, it may be more or less difficult to reset all of the state.

C++ stringstream how to reset it on 2nd loop

Do ss.str("") to make it empty.

But it is better to define ss inside the loop, so that each time it's a new variable:

for(/*.....*/)
{
stringstream ss;
ss << /*....*/ ;
}

That is, make it a scope variable, e.g function-scope or block-scope, so that when it goes out of scope it is destructed, and when it comes back, it gets created again.

Making it a scope variable is less error prone than using ss.str("") to make it empty. I mean, what if you forgot to do ss.str("")? In many cases, when you need to write ss.str("") indicates that you actually need to make it a scope variable, so that you could define it again, either in a loop (as shown above), or entirely a new variable, probably with a different name.

Stringstream clearing trouble

After

ss >> tmp;

ss is at EOF. None of the reads after that work. You can add a line

ss.clear();

after

ss.str("");

to clear its internal state. It will start to work. I used an if statement to test the hypothesis.

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cctype>

int main() {
std::ifstream input("input.txt");
std::string str = "", line;
std::stringstream ss;
int tmp;
while (std::getline(input, line)) {
for (int i = 0, l = line.size(); i < l; i++) {
if (isdigit(line[i]))
str += line[i];
}
ss << str;
// gets int from stringstream
ss >> tmp;
std::cout << str << ' ' << tmp << std::endl;
str = "";
// stringstream clearing

if (ss.eof())
{
std::cout << "ss is at eof\n";
}

ss.str("");
ss.clear();

}

return 0;
}


Related Topics



Leave a reply



Submit