Chapter 6 – Control Structures (C++)
Control Structures – General Overview
- A C++ program is rarely a single linear sequence; instead it needs to
- Repeat certain instructions (iteration)
- Choose between alternative paths (selection / decision-making)
- Constructs that provide these capabilities are collectively called control structures.
- Every control structure ultimately manipulates the program counter (the instruction pointer) so that execution jumps forward, backward, or conditionally.
- Introduction of control structures brings a new syntactic unit: the compound statement / block.
Compound Statements (Blocks)
- Definition: A block is a group of C++ statements treated as one.
- Written inside braces .
- Each inner statement ends with a semicolon as usual.
- Example syntax:
cpp { statement1; statement2; statement3; }
- Usage rules:
- Wherever a single statement is allowed syntactically, a block can be substituted.
- If only one instruction should run, braces are optional; if many, braces are mandatory.
- Practical implication: Always consider braces for clarity, even for single-line bodies, to avoid logical errors when adding lines later (industry best practice).
Conditional Structure: if
- Purpose: Execute a statement / block only if a boolean condition evaluates to .
- Syntax:
if (condition)
statement; // may be a single instruction or a block
- Flow (high-level algorithm):
- Evaluate .
- If → run .
- Else → skip and continue after the
if.
- Simple example:
if (x == 100)
cout << "x is 100";
- Multi-statement body example (using a block):
if (x == 100) {
cout << "x is ";
cout << x;
}
- Complete applied program (division guard):
#include <iostream>
using namespace std;
int main() {
int dividend, divisor;
cout << "Please enter two integers to divide:";
cin >> dividend >> divisor;
if (divisor != 0)
cout << dividend << "/" << divisor << " = "
<< dividend / divisor << '\n';
return 0;
}
- Demonstrates guarding against divide-by-zero error; if the division is executed.
- Nested
if: Anifinside anotherifto create hierarchical checks.
- Nested
if (value >= 0)
if (value <= 10)
cout << "In range";
cout << "Done\n";
- Logic: Only prints In range when .
Conditional Structure: if … else
- Allows one action on branch and an alternative on branch.
- Syntax:
if (condition)
statement1; // executes when condition true
else
statement2; // executes when condition false
- Example:
if (x == 100)
cout << "x is 100";
else
cout << "x is not 100";
- Multi-statement bodies require blocks.
- Extended program (revisited division):
if (divisor != 0) {
cout << dividend << "/" << divisor << " = "
<< dividend / divisor << '\n';
} else {
cout << "Division by zero is not allowed\n";
}
Conditional Structure: Nested / Cascaded if … else if … else
- Purpose: Check multiple mutually exclusive conditions in sequence.
- Generic syntax:
if (cond1)
stmt1;
else if (cond2)
stmt2;
...
else
stmtN;
- Multi-category sign example:
if (x > 0)
cout << "x is positive";
else if (x < 0)
cout << "x is negative";
else
cout << "x is 0";
- Full program translating integers to into words:
if (value < 0) cout << "Too small";
else if (value == 0) cout << "zero";
else if (value == 1) cout << "one";
else if (value == 2) cout << "two";
else if (value == 3) cout << "three";
else if (value == 4) cout << "four";
else if (value == 5) cout << "five";
else cout << "Too large";
Iteration Structures (Loops) – Overview
- A loop repeats a statement / block while or until a condition holds.
- Motivation: Avoid code duplication; central for algorithms such as searching, sorting, numerical methods.
- C++ provides three native loop constructs, each best suited for particular scenarios:
forloop – counter-controlled, known iteration count.whileloop – condition-controlled, unknown/variable count.do … whileloop – post-test version, guarantees at least one execution.
for Loop
- Syntax:
- Sequence:
- Execute once.
- Check . If → exit loop.
- Execute (body).
- Execute .
- Repeat from step .
- Countdown example:
for (int n = 10; n > 0; n--) {
cout << n << ", ";
}
cout << "END!";
- Output:
- Omitted fields: Any of the three fields may be empty but semicolons remain.
- Example:
for (; n < 10; )(no init, no update).
while Loop
- Syntax: ```cpp
while (expression)
statement;
- Semantics: Entry-controlled; body executes **only if** is .
- Custom countdown program:
cpp
int n;
cin >> n;
while (n > 0) {
cout << n << ", ";
--n; // crucial to avoid infinite loop
}
cout << "DONE!";
- Vital design note: Ensure something inside the loop eventually makes the condition .
## `do … while` Loop
- Syntax:
cpp
do
statement;
while (condition);
- Semantics: Exit-controlled; body runs **at least once**.
- Echo program:
cpp
unsigned long n;
do {
cout << "Enter number (0 to end): ";
cin >> n;
cout << "You entered: " << n << "\n";
} while (n != 0);
- Use-case guideline: Best when the termination condition depends on body interaction (e.g., reading user input inside the loop).
# Jump Statements
- Purpose: Alter the normal sequential flow instantly.
- Four in C++: `break`, `continue`, `return`, `goto`.
## `break`
- Immediately exits **innermost** loop or `switch`.
- Early-abort countdown:
cpp
for (int n = 10; n > 0; n--) {
cout << n << ", ";
if (n == 3) {
cout << "countdown aborted!";
break;
}
}
- Practical application: Emergency termination, searching until found, menu exit.
## `continue`
- Skips remaining body statements **only for the current iteration**, proceeds with next.
- Skipping in countdown:
cpp
for (int n = 10; n > 0; n--) {
if (n == 5) continue; // jump to next iteration
cout << n << ", ";
}
cout << "DONE!";
## `goto`
- Unconditional jump to a **label** within same function.
- Example:
cpp
int n = 10;
loop:
cout << n << ", ";
if (--n > 0) goto loop;
cout << "DONE!";
- Warnings / best practice:
- Breaks structured programming;
- Can create *spaghetti code*; avoid unless interfacing with low-level constructs or generated code.
## `return`
- Immediately exits the **current function**, optionally providing a return value.
- In `main`, `return 0;` conventionally signals normal termination.
## `exit()` Function
- Prototype: `void exit(int exitcode);` from `<cstdlib>`.
- Terminates **entire** program, bypassing stack unwinding.
- Use for normal termination; non-zero for error signalling.
- Distinction: `exit` executes static object destructors and `atexit` handlers, whereas some low-level aborts do not.
# Selective Structure: `switch`
- Designed for multi-way branching based on **integral** constant values (chars, ints, enums).
- Syntax skeleton:
cpp
switch (expression) {
case constant1:
statements1;
break;
case constant2:
statements2;
break;
…
default:
default_statements;
}
- Operational steps:
1. Evaluate once.
2. Compare with each `case` label in order.
3. Jump into first matching label; execute downward until `break` or end of `switch`.
- Equivalence example (shows relation to `if-else if` chain):
cpp
switch (x) {
case 1: cout << "x is 1"; break;
case 2: cout << "x is 2"; break;
default: cout << "value of x unknown";
}``
is semantically identical to nestedif/else if` shown earlier.
- Fall-through behavior:
- Omitting
breaklets execution continue into subsequent cases. - Allows grouping of labels:
cpp switch (x) { case 1: case 2: case 3: cout << "x is 1, 2 or 3"; break; default: cout << "x is not 1, 2 nor 3"; }
- Omitting
- Limitations:
caselabels must be compile-time constants – no variables, no ranges.- For ranges or complex predicates, revert to
if/else if.
Practical, Philosophical & Ethical Notes
- Safety & correctness: Guarding against divide-by-zero, infinite loops, and other runtime errors is both a practical and ethical imperative (prevents crashes, data loss).
- Maintainability: Using structured constructs (
for,while,switch) rather thangotopromotes readable, verifiable code – aligning with professional standards and collaborative development norms. - Resource considerations: Infinite loops or forgotten
breakstatements can hog CPU cycles; responsible coding conserves shared computational resources. - User experience: Clear prompts and graceful exits (
exit(0), informative error messages) respect users’ time and trust. - Historical context: Early languages relied heavily on
goto; modern best practice ("structured programming" movement by Dijkstra) discourages it – foundational principle for subsequent object-oriented paradigms.
Quick Reference (Cheat Sheet)
- → single-branch decision
- → dual-branch decision
- → multi-branch decision
- → constant multi-branch selection, uses labels &
- → counter loop
- → pre-test loop
- → post-test loop (executes at least once)
- → terminate loop / switch
- → skip to next iteration
- → exit function
- → unconditional jump (avoid)
- → terminate program immediately (from
)
Connections to Earlier / Foundational Material
- Relies on Boolean logic (true / false) previously introduced in expressions chapter.
- Uses operators such as , , >, < covered in relational-operator lecture.
- Loop counters and conditions typically utilize variables, assignment, and arithmetic operations from basic C++ syntax lessons.
Real-World Relevance & Examples
- Input validation (e.g., checking ) mirrors production systems preventing crashes.
- Menus in console apps often implemented with
switch. - Sensor polling loops in embedded systems often require
while(true)with internalbreakupon condition. - Game loops commonly exploit
whilefor main update cycle, combined withcontinuefor frame-skipping logic.
Common Pitfalls & Best Practices
- Forgetting braces in nested
ifstructures → danglingelseproblem. - Off-by-one errors in loop bounds (e.g., last iteration executed times instead of ).
- Infinite loops due to non-mutated condition variable.
- Neglecting
breakinswitchcausing unintended fall-through. - Prefer pre-increment/ decrement (
++i) where semantics allow to potentially optimize. - Consider using range-based
forin modern C++ for container iteration.
Formulas & Symbolic Reminders
- Loop counter update: in countdown examples.
- Guard condition pattern: where → eventually.
- Division guard: before evaluating .
Summary
- Control structures empower programs to make decisions and perform repetition, forming the backbone of algorithmic logic in C++.
- Mastery involves understanding syntax, flow of control, and the nuanced differences between constructs so the most expressive, safe, and efficient tool is chosen for each task.