Question
How can I completely clear a std::stringstream in C++ so that it no longer contains its previous text and can be reused?
I tried the following, but neither achieves the result I want:
std::stringstream m;
m.empty();
m.clear();
Short Answer
By the end of this page, you will know that a std::stringstream has both stored text and stream state flags. You will learn how to reset both correctly with str("") and clear(), and when each operation is necessary.
Concept
A std::stringstream is a stream backed by an internal std::string. It is useful when you want to write values into text, read values back from text, or convert between text and other types.
There are two different things that may need resetting:
- The buffered text — the characters currently stored in the stream.
- The stream state — flags such as
eofbitandfailbitthat record whether reading succeeded.
Use these operations for their separate jobs:
stream.str(""); // Remove the stored characters.
stream.clear(); // Clear error/end-of-file state flags.
To fully reset a stream for reuse, use both:
stream.str("");
stream.clear();
clear() does not erase text. It only resets state flags. This matters because a stream that reached the end of its input, or failed to parse a value, may refuse later input operations until its error state is cleared.
std::stringstream does not have an empty() member function. To check whether its current text is empty, retrieve the string first with str() and then call empty() on that string.
Mental Model
Think of a std::stringstream as a reusable notepad with a status light.
str("")erases everything written on the notepad.clear()turns off warning lights such as end reached or reading failed.
Erasing the notepad does not automatically turn off the warning light, and turning off the warning light does not erase the notepad. When reusing the stream, usually do both.
Syntax and Examples
The primary operations are:
#include <sstream>
#include <string>
std::stringstream stream;
stream.str("Hello"); // Replace the stream's stored text.
std::string text = stream.str(); // Get a copy of the stored text.
stream.str(""); // Erase stored text.
stream.clear(); // Reset eof/fail/bad state flags.
Here is a complete example that reuses one stream:
#include <iostream>
#include <sstream>
#include <string>
int main() {
std::stringstream stream;
stream << "Order #" << 42;
std::cout << stream.str() << '\n';
// Reset before building different text.
stream.str("");
stream.clear();
stream << "Order #" << 43;
std::cout << stream.str() << '\n';
}
Output:
Order #42
Order #43
If you omit stream.str(""), the second write appends to the existing buffer and produces Order #42Order #43.
Step by Step Execution
Consider parsing one value and then reusing the stream for another:
#include <iostream>
#include <sstream>
int main() {
std::stringstream input("25");
int first = 0;
input >> first;
int unused = 0;
input >> unused; // No more input: eofbit and/or failbit is set.
input.str("90"); // Replace old text with new text.
input.clear(); // Allow extraction again by resetting state flags.
int second = 0;
input >> second;
std::cout << first << ", " << second << '\n';
}
Execution flow:
inputstarts with the text"25".input >> firstreads25, sofirstbecomes25.- The next extraction cannot read another integer because there is no more input. The stream enters a failed/end state.
input.str("90")replaces"25"with"90", but it does not guarantee that previous failure flags are removed.input.clear()resets those flags.input >> secondcan now read90.- The output is
25, 90.
A reliable reuse order is:
input.str("");
input.clear();
Then write or assign the next content.
Real World Use Cases
std::stringstream reset patterns appear in many everyday C++ tasks:
- Formatting log messages: Build a message, send it to a logger, then reset the stream for the next message.
- Parsing CSV-like fields: Put each field into a stream, parse it, and reuse the same stream for the next field.
- Converting strings to numbers: Parse user input such as
"123"into anint, then reset before validating another input. - Building API payload fragments: Assemble JSON-like or query-string text in a loop.
- Tests: Reuse an input stream to test several parsing cases without constructing a new object each time.
For simple one-time formatting, constructing a new local std::ostringstream is often clearer. Resetting is most useful when reuse is intentional, such as inside a loop.
Real Codebase Usage
In real projects, developers usually choose one of two patterns.
Create a fresh local stream
This is the clearest option when the stream is used once per operation:
std::string formatUser(int id, const std::string& name) {
std::ostringstream out;
out << "id=" << id << ", name=" << name;
return out.str();
}
The stream is destroyed when the function returns, so no reset is needed.
Reuse a stream in a loop
If profiling shows that repeated stream creation is undesirable, reset the stream explicitly:
std::stringstream parser;
for (const std::string& field : fields) {
parser.str(field);
parser.clear();
int value = 0;
if (parser >> value) {
// Use value.
} else {
// Handle invalid field.
}
}
Validate the entire input
Successful extraction does not always mean the entire string was valid. For example, "12abc" can initially extract 12. Check for trailing content:
std::stringstream parser("12abc");
int value = 0;
char extra = '\0';
if ((parser >> value) && !(parser >> extra)) {
// The input contains exactly one integer.
} else {
// Invalid or trailing characters found.
}
When parsing in production code, always check the stream state rather than assuming extraction succeeded.
Common Mistakes
Calling clear() to erase text
This does not erase the internal buffer:
std::stringstream stream;
stream << "old text";
stream.clear();
// stream.str() is still "old text"
Use stream.str("") to erase the text.
Calling empty() directly on a stringstream
This is invalid because std::stringstream has no empty() member:
std::stringstream stream;
// stream.empty(); // Error: no such member function
Check a copy of the underlying string instead:
if (stream.str().empty()) {
// No buffered characters.
}
Clearing text but leaving failure flags set
After a failed extraction, replacing the text alone may not make a later read work:
std::stringstream stream("not-a-number");
int number = 0;
stream >> number; // Fails.
stream.str("42");
// stream >> number; // May still fail because failbit remains set.
Fix it by resetting both aspects:
stream.str("42");
stream.clear();
stream >> number;
Forgetting that output appends
Writing with << adds characters at the current output position. If you reuse an output stream without resetting its text, old content remains:
std::ostringstream out;
out << "first";
out << "second";
// out.str() is "firstsecond"
Call out.str("") before building an unrelated message.
Assuming str() returns a reference
stream.str() returns a std::string value. Editing that returned value does not edit the stream:
std::stringstream stream("hello");
std::string copy = stream.str();
copy = "changed";
// stream still contains "hello"
Use the setter form to replace stream content:
stream.str("changed");
Comparisons
| Operation | What it changes | Does it remove buffered text? | Typical use |
|---|---|---|---|
stream.str("") | The internal string buffer | Yes | Start a new message or input value |
stream.clear() | Error/state flags | No | Recover after EOF or a failed read |
stream.str() | Returns a copy of buffered text | No | Get the generated or stored text |
stream.seekg(0) | Read position | No | Read existing content again from the start |
stream.seekp(0) | Write position | No | Change where output is written |
seekg() and seekp() are not replacements for clearing. They move positions within existing content; they do not remove that content.
| Stream type | Supports reading (>>) | Supports writing (<<) | Best for |
|---|---|---|---|
std::istringstream | Yes | No | Parsing a string |
std::ostringstream | No | Yes | Building a string |
std::stringstream | Yes | Yes | Reading and writing the same string buffer |
Cheat Sheet
#include <sstream>
std::stringstream stream;
| Task | Code |
|---|---|
| Get buffered text | std::string text = stream.str(); |
| Replace buffered text | stream.str("new text"); |
| Erase buffered text | stream.str(""); |
Reset eofbit / failbit | stream.clear(); |
| Fully reset for reuse | stream.str(""); stream.clear(); |
| Check whether stored text is empty | stream.str().empty() |
| Check whether parsing succeeded | if (stream >> value) { /* ... */ } |
Key rule: str("") clears characters; clear() clears state flags.
For a stream that has failed and must be reused:
stream.str("");
stream.clear();
FAQ
Does std::stringstream::clear() erase the string?
No. clear() resets stream state flags such as failbit and eofbit. Use str("") to erase stored characters.
How do I completely reset a std::stringstream?
Use both operations:
stream.str("");
stream.clear();
This removes text and clears error state.
Why does reading from my stringstream still fail after I assign new text?
A previous read may have set failbit or eofbit. After assigning text with str(...), call clear() before reading again.
Does std::stringstream have an empty() function?
No. Use stream.str().empty() to check whether its current buffered string contains no characters.
Should I use std::stringstream, std::istringstream, or std::ostringstream?
Use istringstream for reading text, ostringstream for creating text, and stringstream only when you need both reading and writing.
Do I need to clear a newly created stringstream?
No. A newly constructed stream has an empty buffer and a good state. Resetting is only needed when reusing an existing stream.
Can I reuse a stream after parsing invalid input?
Yes. Replace or erase its text with str(...), then call clear() to remove the failed state before the next parse.
Mini Project
Description
Build a small command parser that reads integer values from several text commands. The project demonstrates how to reuse one std::stringstream safely after both successful and failed parsing attempts.
Goal
Parse commands such as "add 12" and report whether each command contains a valid integer value.
Requirements
Use one reusable std::stringstream for every command.
Reset the stream before parsing each new command.
Accept commands containing exactly an action and one integer.
Reject commands with a missing, invalid, or extra value.
Print a useful result for every command.
Keep learning
Related questions
Advantages of Brace Initialization in C++
Learn why C++ brace initialization is often clearer and safer than other object initialization styles, with examples and common pitfalls.
Basic Rules and Idioms for Operator Overloading in C++
Learn the core rules, syntax, and common idioms for operator overloading in C++, including member vs non-member operators.
C++ Aggregates, Trivial Types, Trivially Copyable Types, and PODs Explained
Learn what aggregates, trivial types, trivially copyable types, and PODs mean in C++, how they differ, and why they matter.