Concepts / Debugging Output Programs

Debugging Output Programs

The ostream library defines output for every built-in type, so basic values can be sent to cout directly.

  • Programming
Interactive lab

Try it: Debug by Tracing Execution

How to debug a program that runs but gives the wrong answer: compare expected and actual output, trace the lines in the order they really run with a variable watch table (or an inserted debug print), find the first line where a value goes wrong, then choose a fix and re-run to check it.

How it works

  1. State the expected output from the specification, run the program and compare: a difference is the evidence you debug from.
  2. Trace in execution order, not file order: loops repeat lines, if/elif picks one branch, and the watch table records every variable before each line runs.
  3. An inserted print('debug: ...', value) shows the same state in the output; it must not change what the program itself prints.
  4. Look for the first place a value differs from what it should be (an off-by-one range, > instead of >=, a total reset inside the loop, two names for one list, a str from input()). Where the wrong value shows up is only the symptom.
  5. Change one thing with a reason, re-run, and compare again: a fix that makes an error disappear can still leave the output wrong.

Default run (14 steps): Sum 1..n: Add up the whole numbers from 1 to n (n included) and print the sum. Press Play to trace it line by line. … Finished, but the output is wrong: got sum of 1 to 5 is 10, expected sum of 1 to 5 is 15.

Simplified: The lab's own small Python interpreter runs fixed, hand-written programs (you pick the program, the fix and a value; your text is never executed). Every program the lab can show was run in CPython 3.12 and the lab reproduces its output, its traceback text and its line-by-line trace. Six short programs, one editable value each; input() receives the value you type in the lab. Lines starting with "debug:" are ignored when comparing the output with the expected output.

Educational simulation

Loading the simulation…

Predicting a Printed Number

Most of the first programs you write in C++ do something visible. They report a result, echo a value, or show a message. In C++ that visible behavior comes from output operations, and the simplest of them send a built-in value, such as a whole number, to the program's standard output. When the printed text is wrong, the bug is usually hiding in the exact characters that were printed, not in the number the program was meant to show. This article therefore starts with a prediction about a single statement and then traces the mechanism that produced the result.

What do you think happens?

The statement cout << 10; sends the literal 10 to standard output. What characters appear on the output?

  • The single character for the value ten

  • The characters 1 and 0

  • The number 10 stored as a binary value

Reveal answer
Answer:

The characters 1 and 0

The output stream can carry only characters. When a built-in value is written to cout, it is first converted to a sequence of characters. The number ten has two decimal digits, so two characters are placed on the stream: the digit for one, followed by the digit for zero.

Tracing a Literal Through cout

Consider the statement below. The number is written as a value in the source code, but the output stream does not receive a quantity in the mathematical sense. It receives characters, and those characters are what you see on the screen.

cpp
Output
10
Notes on the code
  • cout is the output stream object that represents standard output
  • << is read as put to: it places the value 10 on the stream
  • The characters placed on the stream are the digit 1 followed by the digit 0
Worked example

Following the characters for a literal

What characters does the stream receive for the statement cout << 10; and in what order?

  1. 1
    Identify the value

    The operand after << is the built-in value ten.

  2. 2
    Convert to characters

    Because a stream carries only characters, the value is converted to its decimal text form, which has two digits.

  3. 3
    Place the characters in order

    The digit for one is placed first and the digit for zero second, so the stream receives 1 and then 0.

Result

The characters 1 and 0 appear on standard output.

How the ostream Library Handles Built-In Types

The ostream part of the library is what makes this work. The header named ostream defines output for every built-in type. This is why a basic type such as int needs no special setup before you can send it to cout. The << operator is the piece of code that accepts a value on its right and places it on the stream on its left. Its name is read as put to, and each use of it adds one value to the output.

The same conversion applies when the value comes from a variable rather than a literal. An int variable that holds the value ten is also written as the characters 1 and 0. The output mechanism cares about the value being displayed, not about the name of the variable that held it. The diagram below shows the three parts involved: the value, the operator, and the stream that carries the characters to standard output.

int value 10right operand of <<<< operatorput tocoutostream objectStandard outputcharacters 1 and 0given toplaces value oncharacters appear
What is the relationship between the value, the << operator, the cout object, and the standard output where the characters finally appear?

Chaining << for Mixed Types

A single output statement often needs to print text and a variable together, such as a label followed by a number. Output of different types combines in the obvious way: each value is given to the stream with its own << operator, and the operators are written one after another in the same statement. The general pattern is a sequence of values separated by << symbols, ending with a semicolon.

cpp
Output
Count is 10
Notes on the code
  • The text "Count is " is written first, character by character
  • The << after the text returns the stream so the next value can follow
  • The variable ten is converted to the characters 1 and 0 and placed after the text

Read left to right, the chain behaves like a series of separate placements. Each << takes the stream produced by the previous one, adds one value to it, and passes the stream along, so the next value follows in the order the operators were written. The diagram below traces that sequence for the statement above.

cout << "Count is "text placed on stream first<< tenvalue 10 becomes 1 and 0Standard outputCount is 10stream passed oncharacters written in order
How does cout << "Count is " << ten evaluate step by step, and what does each << pass along to the next value?

The same characters reach cout whether they arrive in one statement or several. The stream does not care how the values were grouped, only that they arrive in sequence. The two forms below therefore produce identical output, and the choice between them is about readability.

cpp
Output
Count is 10
Notes on the code
  • Three separate statements send the same characters as the single chained statement
  • The stream receives the text first, then the digits 1 and 0

Finding Where Output Departs

When a printed result is wrong, the fastest debugging method is to compare the output one operation at a time against your prediction. Work through each << in the statement, write down the characters it adds to the stream, and mark the first point where the text you wrote down disagrees with what appeared. That point is the location of the fault. Output is exact: the stream does not insert spaces or punctuation that you did not write, so a difference is usually a character that was missing or a value that was converted differently than you assumed.

cpp
Output
Total:10
Notes on the code
  • The author expected the printed text to be Total: 10 with a space after the colon
  • The first operation that adds characters is the text "Total:", which contains no trailing space
  • The value 10 is printed correctly, so the fault is the text, not the number
OperationExpected characters addedCharacters actually added
cout << "Total:"Total: (with a space)Total: (no space)
<< total1010

Walking the statement one << at a time. The first row that disagrees is the location of the fault.

  • Common mistake

    Assuming a number is printed as a quantity rather than as characters

    What it looks like

    Expecting cout << 10; to show the single symbol for ten

    Why it fails

    The stream carries only characters, so the value is converted to its digits, which are 1 and 0.

    Do this instead

    Predict the digits that will be written, not the quantity the value represents.

  • Common mistake

    Expecting the stream to add spaces between values

    What it looks like

    Writing cout << "Total:" << total; and expecting Total: 10

    Why it fails

    Each value is written exactly as its characters are produced, so only the characters in the text and the digits of the value appear.

    Do this instead

    Put any required spaces inside the text literal, such as "Total: " with a trailing space.

  • Common mistake

    Checking only the final number instead of each operation

    What it looks like

    Seeing 10 in the output and concluding that the whole line is correct

    Why it fails

    The text before the number may be wrong even when the number is right.

    Do this instead

    Compare the characters added by each << in order, and stop at the first mismatch.

  • Common mistake

    Using cerr for ordinary results when cerr is reserved for reporting errors

Practice: Predicting a Chained Line

EASY

A program sets int ten = 10; and then runs cout << "Count is " << ten; What exact characters appear on standard output? Then say which operation you would check first if the printed line were Count is1 0 instead.

Hints
  • Write the characters added by each << in order, from left to right.
  • The variable ten is converted to the characters 1 and 0 and nothing else.
  • Compare your list with the printed text one operation at a time and stop at the first disagreement.

Key Takeaways

  • The ostream library defines output for every built-in type, so a value such as an int can be sent to cout directly.
  • A built-in value written to cout is converted to characters first; the number 10 appears as the characters 1 and 0.
  • Each << places one value on the stream, and chaining several << operators prints the values in the order they are written.
  • To debug printed text, compare the characters added by each << with your prediction and stop at the first point of disagreement.

Related concepts

More concepts starting with D