Concepts / Formatting Output with Manipulators

Formatting Output with Manipulators

The scientific manipulator is sent through the same << operator, but it does not add characters of its own.

  • Programming

Predicting a Line Before Running It

This article follows one small, complete program. Before any explanation, read the code and keep track of what happens at each line. The key question is simple: where does each piece of text go, and when does it reach the screen? The answer to that question explains almost every surprising result you will see with string streams.

cpp
Notes on the code
  • ostringstream oss declares a string stream named oss
  • Each << writes a piece into oss; none of them print to the screen
  • scientific is a manipulator that changes how the value written after it is formatted
  • The final cout line is the only statement that sends text to the screen

What do you think happens?

What does show() print to the screen?

  • {temperature, 123.4567890}

  • {temperature, 123.457}

  • {temperature, 1.234568e+02}

  • 123.4567890{temperature, }

Reveal answer
Answer:

{temperature, 1.234568e+02}

The text is written into oss first, then scientific is applied, then the number is written in scientific style with the default precision of six digits. The closing brace is written last. Nothing reaches the screen until cout prints oss.str(), followed by a newline.

Tracing the Buffer Line by Line

An ostringstream collects text and values written to it with the << operator, in the order they are written. Think of oss as a single buffer. Every << appends its contents to the end of that buffer, and nothing is removed or reordered. The chain in the example is read from left to right, so the buffer receives its pieces in exactly the order they appear on the line.

{temperature,text, 1st writeoss bufferaccumulated in ordercoutprints the stringscientificmanipulator, no characters123.4567890number, 3rd write}text, 4th writeappendedsets formatappendedappendedoss.str()
When several values are written with <<, each piece is appended to the same buffer in order, and cout receives the finished string only when oss.str() is requested.

Notice that the buffer grows only through text and numbers. The scientific manipulator is sent through the same << operator, but it does not add characters of its own. Its job is to change how the value after it is formatted. The text pieces written before it are not affected by it at all.

Worked example

Tracing show() statement by statement

Track the contents of oss and the format state after each statement in show(), and say at which point the printed result is determined.

  1. 1
    Statement 1: oss << "{temperature, "

    The buffer now holds {temperature, . The stream is still in its default format state, so no special notation applies yet.

  2. 2
    Statement 2: << scientific

    No characters are added to the buffer. The format state of the stream changes so that values written after this point use scientific notation.

  3. 3
    Statement 3: << 123.4567890

    The number is formatted in scientific style and appended. The buffer now holds {temperature, 1.234568e+02 with no closing brace yet.

  4. 4
    Statement 4: << "}"

    The closing brace is appended. The buffer is now the complete string {temperature, 1.234568e+02}.

  5. 5
    Statement 5: cout << oss.str() << '\n'

    oss.str() returns the finished string, cout sends it to the screen, and the newline character ends the line. This is the first moment anything is visible.

Result

The printed line is {temperature, 1.234568e+02}, and it is determined entirely by the order of the << operations before cout runs.

How a Manipulator Changes the Number

A manipulator is a value you send through << to change how the stream formats what comes after it. The scientific manipulator formats numbers in scientific notation. It affects the values written after it in the chain, and only those. Its position in the chain therefore matters: placing scientific before the number changes that number, while placing it after the number would leave the number formatted as it was before.

Before
oss << "{temperature, " << 123.4567890 << "}";

Without scientific, the number is written in the stream's default style, which prints 123.457 with six significant digits.

After
oss << "{temperature, " << scientific << 123.4567890 << "}";

With scientific applied before the number, the same value is written as 1.234568e+02.

123.4567890default output: 123.457123.4567890scientific output:1.234568e+02
The value 123.4567890 is identical in both cases. Only its written form changes once the scientific manipulator is applied before it in the chain.
default formatscientific format<< scientific
The stream starts in its default format state. Applying scientific changes the state, and values written from that point on are formatted in scientific style.

Reading str() and the cout Line

The str() method returns the string built inside an ostringstream. The statement cout << oss.str() << '\n'; takes that finished string, sends it to cout, and then adds a newline character. The output of cout is therefore the complete string built by the earlier << operations, followed by a line break. Writing to oss does not print anything. Only the cout statement sends text to the screen.

ossostringstream bufferstd::stringreturned by str()coutprints the textstr()<< oss.str()
str() gives the program a string containing the text accumulated so far. The stream itself keeps its contents, so the buffer and the returned string are related but separate values.
Featurecoutostringstream oss
Where the text goesDirectly to the screenInto an in-memory buffer inside the stream
When it becomes visibleAs soon as it is writtenOnly after oss.str() is sent to cout
Role in the exampleOnly the final line uses itEvery << in the chain writes into it
Effect of a manipulatorFormats values written after itFormats values written after it before str() is taken

Comparing the two output destinations

Because the buffer holds everything until str() is called, a line that looks wrong on screen is usually caused by the order of the << chain or by the cout statement that prints oss.str(), not by the text written into oss.

Mistakes That Make the Output Look Wrong

  • Common mistake

    Expecting oss << lines to print to the screen

    What it looks like

    oss << "hello"; with no cout afterward, followed by a check of the terminal.

    Why it fails

    Text written into an ostringstream stays in the buffer. Nothing is sent to the screen until cout prints oss.str().

    Do this instead

    Send the finished string to cout with cout << oss.str() when you want to see it.

  • Common mistake

    Placing scientific after the number it should affect

    What it looks like
    oss << "{temperature, " << 123.4567890 << scientific << "}";
    Why it fails

    A manipulator affects only the values written after it in the chain. The number was already written before scientific was applied.

    Do this instead

    Put scientific before the number, as in << scientific << 123.4567890.

  • Common mistake

    Assuming a manipulator adds characters to the output

    What it looks like

    Looking for the word scientific in the printed line.

    Why it fails

    scientific changes the format of the value that follows it. It does not write any characters of its own.

    Do this instead

    Read the printed line for the changed number, such as 1.234568e+02, and not for the manipulator name.

  • Common mistake

    Reading the chain in the wrong order

    What it looks like

    Assuming the number is printed before the opening text because the cout line appears last.

    Why it fails

    The << operator applies in order from left to right, so the pieces enter the buffer in the order they are written.

    Do this instead

    Trace the chain from left to right, then follow oss.str() into cout.

  • Common mistake

    Forgetting the trailing newline when expecting the next output to begin on a new line

Practicing a Trace on a New Chain

MEDIUM

Suppose a function writes into an ostringstream named oss with the chain oss << "[" << scientific << 0.5 << "]"; and then prints cout << oss.str() << '\n';. Trace the buffer after each << and state the exact line the program prints. Then say which part of the chain would change if scientific were moved to after 0.5.

Hints
  • Start with an empty buffer and append each piece in order from left to right.
  • scientific adds no characters; it only changes how 0.5 is written.
  • Moving scientific after 0.5 leaves that number in the default style, so compare the default and scientific forms of the same value.
EASY

Explain, in one or two sentences, why cout shows nothing until the final line of a function runs, even though several << statements have already executed.

Hints
  • Think about where the text is stored between each << and the cout statement.
  • The cout statement is the only step that sends text to the screen.

Key Takeaways

  • An ostringstream collects text and values written to it with the << operator, in the order they are written, and holds them in an in-memory buffer.
  • The str() method returns the string built inside the ostringstream, and cout << oss.str() prints that string.
  • A manipulator such as scientific changes how the values written after it are formatted, so its position in the chain matters and it adds no characters of its own.
  • To find a wrong printed line, trace the << chain from left to right and then check the cout statement that outputs oss.str().

Related concepts

More concepts starting with F