Reading from a String Stream
An ostringstream collects text and values written to it with the << operator, in the order they are written.
Predicting Where the Text Goes
When a program builds a line of output, it often combines pieces of text and numbers before anything reaches the screen. A string stream gives you a place to collect those pieces. You write into it the same way you write to cout, using the << operator, but nothing appears on the screen while you are writing. The finished result is kept as a string until your program asks for it.
Keep one question in mind as you read this article: if a function writes several pieces into a string stream and then prints the finished string, at which point does the screen actually receive any text, and what text does it receive? You will return to that question once you have traced an example.
Where an ostringstream Collects Its Text
An ostringstream collects text and values written to it with the << operator, in the order they are written.
The key phrase is in the order they are written. The stream does not rearrange, sort, or print anything. Each << operation appends the next piece to what is already stored, so the final text is the concatenation of the pieces in exactly the sequence your code wrote them.
Writing into oss does not send text to the screen. The text stays inside the stream until you ask for it. The str() method is how you ask. It returns the string built inside the ostringstream, and you can pass that string to cout to display it.
cout << oss.str() << '\n';Read this statement from left to right. oss.str() produces the accumulated string, cout sends it to the screen, and '\n' adds a newline character after it. The visible output is therefore the complete string built by the earlier << operations, followed by a line break.
Tracing a Temperature Example
The following small function is a complete example. It writes several pieces of text and a number into an ostringstream named oss, then prints the finished string. Read it carefully before you look at the explanation, and track what the function is doing on each line.
- The ostringstream oss is created empty
- Three << writes add the text, the manipulator, and the number to the stream
- The final cout statement is the only place text is sent to the screen
Notice that the function never prints inside the oss << line. Everything written with << goes into oss. Only the last cout statement sends anything to the screen, and it sends the whole stored string in one step.
Now trace the chain of << operators in order. The text {temperature, is written first. Next, std::scientific, which is a manipulator, is sent through the stream. Then the number 123.4567890 is written. Last, the closing brace } is written. Because the operators are applied in order, the stream receives the pieces in exactly the order they appear on the line.
The diagram shows the buffer as it grows. Each << adds to the end of what is already there, and the manipulator adds no visible characters of its own. It only changes how the number that follows is written. The place where the manipulator appears is therefore the place where its effect begins.
One line is printed: an opening brace, the word temperature, the number 123.4567890 written in scientific notation, a closing brace, and then a newline. The exact digits shown for the number depend on the stream's formatting settings, which this example does not spell out.How Manipulators Change Later Writes
A manipulator is a value you send through << to change how the stream formats what comes after it. In the example, scientific is a manipulator that formats numbers in scientific notation. It appears in the chain before 123.4567890, so the number that follows is written in that style.
Because the effect applies to what follows, the position of the manipulator in the chain matters. Text pieces written without it are not affected by it, and a number written before it keeps its earlier formatting. This is why you should trace the << chain from left to right rather than assuming the manipulator applies to the whole line.
Mistakes When Printing an ostringstream
Common mistake Expecting the << writes to print to the screen immediately
What it looks likeoss << "{temperature, "; with no cout line afterward, nothing appears on screen.
Why it failsText written into an ostringstream stays in the stream until it is requested.
Do this insteadSend oss.str() to cout when you want the text displayed.
Common mistake Assuming a manipulator affects text written before it
What it looks likeoss << 123.4567890 << std::scientific << "}"; expects the number to change.
Why it failsA manipulator affects only the values written after it in the chain.
Do this insteadPlace the manipulator before the number whose format should change.
Common mistake Printing the stream object instead of its string
What it looks likecout << oss; when you wanted the built text.
Why it failsThe text is retrieved from the stream with
str(), so the string itself is what should be sent to cout.Do this insteadUse cout << oss.str() << '\n';
If a printed line looks wrong, trace the << chain in order and then check the cout statement that outputs oss.str(). Most differences between what you expected and what appeared come from either the order of the writes or a missing or wrong manipulator placement.
Reading Text Into an istringstream
Programs often receive text that was not typed directly into a console. A graphical user interface, or GUI, may hand the program a string, which is simply a sequence of characters. That string is ready to be stored, but it is not yet split into the values a program needs, such as a number followed by another number.
An istringstream is a class for reading from a string stream, so it is the right choice when a program needs to interpret a string.
Once a string has been placed into an istringstream, the formatted input operations you already know can pull values out of it. The string never has to be treated as one block of characters that you parse by hand. The most important point is the direction of the data: the text goes into the stream first, and then the program takes pieces of it out.
- 1The string arrives from the GUI.
- 2The program places that string into an istringstream.
- 3Formatted input operations read values out of that stream and into the program's variables.
- 4The program can then use those variables as ordinary typed values.
The result an istringstream holds can also be read using str(). This returns the text as a whole rather than as separate values. Formatted input with >> takes values out one piece at a time, while str() gives back the entire string the stream holds.
Roles of the Two String Streams
The two classes face opposite directions. An ostringstream is a place you write into: values go in with <<, and the finished text comes out with str(). An istringstream is a place you read from: text goes in first, and then formatted input takes values out. The source also notes a common use for an ostringstream, which is formatting something before passing the resulting string to a GUI.
| Aspect | ostringstream | istringstream |
|---|---|---|
| Direction of data | Values are written into a string | Text is read out into values |
| Main operator | << writes pieces in order | >> extracts typed values one at a time |
| Role of str() | Returns the string built inside the stream | Returns the text held by the stream as a whole |
| Typical use | Formatting output before it is given to a GUI or printed | Interpreting a string received from a GUI |
The two string stream classes set side by side
Practice Tracing the Stream
Using the printTemperature function from this article, suppose the chain were rearranged so that the number 123.4567890 was written before std::scientific. Before reasoning further, decide which pieces of the output would change, and where the first changed piece would be found in the stream's text.
Hints
- Trace the << chain strictly from left to right.
- A manipulator affects only the values written after it.
- Ask which single cout statement sends text to the screen.
Write a short function that builds the text Score: followed by a whole number and a newline inside an ostringstream, then prints the result using cout with oss.str(). Then describe, in one sentence each, what the stream holds after the first write and after the last write.
Hints
- Create the ostringstream empty first.
- Only the final cout line should produce screen output.
Key Takeaways
- An ostringstream collects text and values written with << in the order they are written, and it sends nothing to the screen until its contents are requested.
str()returns the string built inside an ostringstream, and cout <<oss.str()prints it.- A manipulator such as scientific formats only the values written after it, so its position in the << chain matters.
- An istringstream is a source you read from: a string, such as one handed over by a GUI, is placed into it and then read with formatted input operations.
str()on an istringstream returns the whole held text, while >> extracts separate typed values one at a time.