Debugging Output Programs
The ostream library defines output for every built-in type, so basic values can be sent to cout directly.
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
- State the expected output from the specification, run the program and compare: a difference is the evidence you debug from.
- 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.
- An inserted print('debug: ...', value) shows the same state in the output; it must not change what the program itself prints.
- 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.
- 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.
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?
Reveal 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.
10- 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
Following the characters for a literal
What characters does the stream receive for the statement cout << 10; and in what order?
- 1Identify the value
The operand after << is the built-in value ten.
- 2Convert to characters
Because a stream carries only characters, the value is converted to its decimal text form, which has two digits.
- 3Place 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.
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.
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.
Count is 10- 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.
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.
Count is 10- 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.
Total:10- 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
| Operation | Expected characters added | Characters actually added |
|---|---|---|
| cout << "Total:" | Total: (with a space) | Total: (no space) |
| << total | 10 | 10 |
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 likeExpecting cout << 10; to show the single symbol for ten
Why it failsThe stream carries only characters, so the value is converted to its digits, which are 1 and 0.
Do this insteadPredict 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 likeWriting cout << "Total:" << total; and expecting Total: 10
Why it failsEach 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 insteadPut 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 likeSeeing 10 in the output and concluding that the whole line is correct
Why it failsThe text before the number may be wrong even when the number is right.
Do this insteadCompare 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
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.