Programming Fundamentals Using C++

L11 · From Problem to Algorithm: IPO Charts, Decomposition, Pseudocode, Flowcharts

Module 6 — Problem-Solving and Algorithm Design · Week 6 · Lecture 11 of 32 · 120 minutes Outcomes: CLO-4 · PF-6.1, PF-6.2 · LEARNING_OUTCOMES.md

Learning objectives

  1. Produce an IPO chart (Input–Processing–Output) with typed inputs, ordered processing steps, and precise output formats from a problem statement (PF-6.1).
  2. Decompose a multi-step problem into a main task plus named subtasks, drawn as a structure/hierarchy chart (PF-6.2).
  3. Express the refined algorithm in numbered pseudocode and as a flowchart using the four standard symbols, and argue the refinement steps from naive to final (PF-6.2).

Prerequisites

M1–M5 (all control-flow constructs — now students can read any algorithm they design; that's what makes this module the consolidation point).

Concept sequence

  1. Why design precedes code (bug-cost asymmetry; the "just start typing" trap)
  2. IPO analysis: contract thinking
  3. Decomposition: subtasks and hierarchy charts
  4. Pseudocode: structured English with our control vocabulary
  5. Flowcharts: the four symbols (process, decision, I/O, terminator)
  6. Stepwise refinement: naive → correct → good

Teaching topics (detailed)

C++ examples required

FileRole
(design-only, then built) loop_patterns.cpp ✅the ACCUMULATE pattern re-derived from its IPO chart — code shown as the end of the design pipeline
(live) payroll_design.md sketch on board → payroll.cpp skeletonIPO → pseudocode → skeleton mapping demonstrated live

Common student misconceptions

Conceptual explanation (beginner-first)

Everything so far taught vocabulary: variables, branches, loops. This lecture is about the grammar of solving — what experienced programmers do between reading a problem and typing code. The process:

  1. Understand — restate the problem in your own words; identify

inputs and outputs. 2. Plan — write the steps in plain language (pseudocode) and trace them by hand. 3. Code — translate pseudocode line by line. 4. Test — including the nasty cases. 5. Refine — improve names, structure, and check edge cases. Most beginner failures are step-1 or step-2 failures, not C++ failures.

Hand tracing is the core skill. Before running anything, we play computer: a table with one column per variable, one row per step. If the trace is wrong, the plan is wrong — fix it on paper, where it costs seconds, not hours. And when the plan is right but the program isn't, incremental development keeps you sane: write two lines, compile, run; add a bit, compile, run. Never write 50 lines and then compile for the first time.

Terminology and definitions

TermDefinition
PseudocodePlain-language steps describing an algorithm, no syntax
AlgorithmA finite sequence of unambiguous steps that solves a problem
Trace / dry runExecuting an algorithm on paper, recording every variable
Edge caseA boundary input: empty, one item, zero, maximum, negative
Incremental developmentBuild, compile, and run in tiny verified steps
DecompositionBreaking a problem into smaller subproblems
Refinement (top-down)Expanding a high-level step into more detailed steps
Desk checkingVerifying logic on paper before compiling
RegressionA previously-working behavior broken by a change
Minimum viable programThe smallest program that does one verifiable thing

Syntax and C++ examples

The example walks the full process on one classic problem: read n scores, print the highest and its position.

Pseudocode plan (shown in the file, then coded):

read n
read first score -> best, bestPos = 1
for pos from 2 to n:
    read score
    if score > best: best = score, bestPos = pos
print best, bestPos

Then the translation to C++ — one pseudocode line per statement — with the trace table for input 5 42 87 87 13 60 filled in as a comment: best moves 42 → 87 (pos 2), and the later 87 does not move it (strict > keeps the first occurrence).

int n{};
std::cin >> n;
int best{}, bestPos{1};
std::cin >> best;                        // first score seeds the max
for (int pos{2}; pos <= n; ++pos)
{
    int score{};
    std::cin >> score;
    if (score > best)
    {
        best = score;
        bestPos = pos;
    }
}
std::cout << best << ' ' << bestPos << '\n';   // 87 2

Line-by-line code explanation

The best-so-far program (above, mirrored in examples/loop_patterns.cpp):

  1. std::cin >> best seeds the maximum with the first value — not 0, which fails for all-negative scores. This is an edge case decision made in the planning stage.
  2. The loop starts at pos = 2 because position 1 is already consumed.
  3. if (score > best) — strict inequality: ties keep the earliest position. Change to >= and the last tie wins; neither is wrong, but the choice must be deliberate.
  4. Every pseudocode line maps to exactly one statement or small group — the code reads like the plan, which makes desk checking possible.

Output prediction questions (with answers)

  1. Input 5 42 87 87 13 60 — ? — 87 2 (first of the two 87s).
  2. Same program with >= instead of > — ? — 87 3 (last tie wins).
  3. Input 1 followed by -5 — ? — -5 1; seeding with 0 would have printed 0 1 — a wrong answer for all-negative data.
  4. Trace pseudocode x=1; while x < 10: x = x * 2 — ? — x: 1, 2, 4, 8, 16 — four passes, exits at 16.
  5. A plan with no step to read n before the loop — what breaks? — the loop bound is garbage; the trace table exposes it immediately.

Common errors and debugging examples

ErrorSymptomFix
Coding before planning50 broken lines, no idea where it went wrongPseudocode + trace first
Compile-only-at-the-endDozens of errors at once, morale collapseIncremental development
No edge cases testedWorks on samples, fails on 0 / 1 / emptyTest the boundary list every time
Seeding max/min with 0Wrong answer for all-negative (or all-positive min) inputSeed with the first real value
Off-by-one in "positions"bestPos doesn't match the valueKeep position and value updated together
Silent scope creep"Small change" breaks working codeRe-run the old test cases (regression)

Classroom demonstrations

  1. Live pseudocode → code: solve "sum the even numbers from 1 to n" on the board: plan, trace with n = 10 (2+4+6+8+10 = 30), then code — the whole method in eight minutes.
  2. Seed-the-max trap: run the best-so-far program on all-negative input with a 0 seed, then with first-value seeding — edge cases made visible.
  3. Break-it bingo: hand out a working program; teams compete to list the most inputs that break it (empty, one, huge, negative, non- numeric) — testing as an active skill.

Guided student activities

Plan-before-code relay (25 min): teams get a problem statement; station 1 writes the IPO chart, station 2 writes pseudocode, station 3 hand-traces it on a given input, station 4 codes it; traces are exchanged between teams for desk-checking before any code runs.

Practice problems

Summary

Programming is a process: understand, plan, trace, code, test, refine. Pseudocode makes thinking cheap; tracing makes plans verifiable on paper; incremental development keeps compile-run cycles short; edge cases are checked by list, not by luck. The best-so-far pattern seeds with the first value — an edge-case decision that belongs in the plan. Next (L12): turning a plan into testable units — the assert-style mindset and building blocks of algorithm design.

Exit ticket / formative assessment

  1. List the six steps of the problem-solving process in order.
  2. Trace: s = 0; for i in 1..4: s += i — give the (i, s) table.
  3. Why is seeding the maximum with 0 a bug for the input -3 -7 -2, and what is the fix?
  1. What are the three columns of an IPO chart?
  2. Convert one pseudocode step into a sentence a non-programmer could verify.
  3. Which pseudocode step hides a subtask too big for one box? (Given sample.)

Estimated time allocation (120 min)

SegmentMinutes
Recall (patterns quiz) + why design first10
IPO + decomposition + hierarchy charts35
Break10
Pseudocode + flowcharts + stepwise refinement35
Design-a-thon + peer review20
Exit ticket + L12 preview10
Programming Fundamentals Using C++ · C++17 · 16 weeksBack to top ↑