Fundamental control–flow tools that let a program “decide” (selection) or “repeat” (iteration)
Real–world metaphor introduced with the “egg preparation” steps that grew from a single-path recipe to:
Add a quality check (selection → throw away rotten egg vs cook)
Add a repetition over all eggs in a box (iteration)
Lecture scope
Selection keywords: if, else, else if, switch
Iteration keywords: while, do-while, for
Robust testing with both valid & invalid data
Curly braces {} group statements into a block; languages with C-style syntax (C, C++, C#, Java, etc.) rely on them
{
// This is a code block
int x = 10;
}
Nesting rules determine scope
Variables declared in an inner block are invisible outside it
Re-declaring a name in an inner block that is already declared in an outer block is illegal
Readability conventions
Sometimes braces are used for compatibility, sometimes to enable specific scoping, sometimes simply for clarity
Example of scope error
int i1 = 1;
{
int j1 = 2;
}
Console.WriteLine(j1); // ERROR – j1 out of scope
Keyword: bool (system type ext{System.Boolean}, size 1 byte)
bool isValid = true;
bool hasPermission = false;
Only two legal literal values: true and false (case–insensitive when read as text)
Relational operators: <, >, <=, >=, ==, !=
Produce a Boolean result, e.g. 7 >= 3 \rightarrow \text{true}
int a = 5, b = 10;
bool isEqual = (a == b); // isEqual is false
bool isGreater = (b > a); // isGreater is true
Logical operators (binary): AND (&&, &), OR (||, |), XOR ^; unary NOT !
Truth table snapshot: both operands true → AND true, OR true, XOR false
bool p = true, q = false;
bool andResult = p && q; // andResult is false
bool orResult = p || q; // orResult is true
bool notP = !p; // notP is false
Conversion / I/O
string s = Console.ReadLine();
bool b1 = Convert.ToBoolean(s); // or Boolean.Parse(s)
Console.WriteLine(b1);
Importance: completes the set of primitive types; cornerstone of selection constructs
Purpose
Take a different execution path once (simple if) or twice (if + else)
Guard against invalid states/data
Syntax
if (CONDITION) {
// STATEMENTS
}
// or single-statement form without braces
if (CONDITION) STATEMENT;
Example task – “Perfect day proposal”
Constant ext{PERFECT}=24 °C
Compare user-entered temperature
Single-path variant (only act when perfect) and dual-path variant (else → “Better luck tomorrow.”)
int temperature = 24;
const int PERFECT = 24;
if (temperature == PERFECT) {
Console.WriteLine("It's a perfect day!");
}
if (temperature == PERFECT) {
Console.WriteLine("Perfect!");
} else {
Console.WriteLine("Better luck tomorrow.");
}
Idioms & anti-idioms
Use Boolean variable directly: if(isPerfect)
not if(isPerfect==true)
Empty statement after condition: if(!isPerfect);
executes nothing – almost always an error
Logical negation patterns
if (temperature != PERFECT) {...}
// VS logically equivalent but verbose
if (!(temperature == PERFECT)) {...}
Adopt software-engineering pipeline (Waterfall model) – devise test plan in analysis/design phase
Typical test categories
Normal values
Boundary values (just above/below threshold)
Equivalence (exact threshold)
Test-case table example for “hot day ≥ 30 °C”
ID | Type | Input | Expected | |
---|---|---|---|---|
3 | Boundary | 31 | Phwoar! Hot day | |
else supplies an alternative path
if (score >= 90) {
Console.WriteLine("Excellent");
} else if (score >= 70) {
Console.WriteLine("Good");
} else {
Console.WriteLine("Needs improvement");
}
- **else if** provides multiple mutually-exclusive branches
- Ordering matters – first true condition wins; ensure comparisons go from most specific to most general to avoid “shadowing” cases
- Temperature classification exercise (Hot/Warm/Perfect…)
- Constants: HOT=30,\,WARM=25,… etc.
- Testing revealed bug when order was incorrect (`temperature >= WARM` placed before `>= HOT`)
- Take-home: Flexibility vs complexity; requirement of exhaustive tests
An if
inside another if
for multi-dimension decisions
Example: Temperature (>20) AND windiness
int temp = 25;
bool isWindy = true;
if (temp > 20) {
if (isWindy) {
Console.WriteLine("It's warm but windy!");
} else {
Console.WriteLine("It's warm and calm.");
}
} else {
Console.WriteLine("It's not warm enough.");
}
Readability trade-off—as complexity grows, an else-if ladder or even switch often clearer
Avoid deep nesting as shown in the “VERY confusing code. Don’t do it!” slide
Best used when second condition only relevant after first one passes/fails
Multi-way selection for discrete integral-like values (numeric, char, string, bool)
Structure
switch(expr) {
case C1: ... break;
case C2: // no statements → fall-through
case C3: ... break;
default: ... break;
}
“Quarter of AFL game” example: 1\rightarrow first quarter … default → error
int quarter = 2;
switch (quarter) {
case 1:
Console.WriteLine("First quarter");
break;
case 2:
Console.WriteLine("Second quarter");
break;
case 3:
case 4: // Fall-through: Same action for Q3 and Q4
Console.WriteLine("Second half");
break;
default:
Console.WriteLine("Invalid quarter");
break;
}
Fall-through technique: stack multiple case labels above one body
Non-integral notes
Floats allowed (with suffix, e.g. 3.14f) but seldom recommended
Strings: beware of typos and culture-specific comparisons (“hell” vs “hello”)
Booleans: legal but conventional if/else
clearer
Comparison with if/else
(summary slide)
if
supports full relational operators and ranges
switch
only equality but often more readable for many discrete options
Both structures give multiple paths
Key differences
Condition types & operator set
Mechanisms for “else” path (else vs default)
switch
enables intentional fall-through
Definition: executing a block repeatedly until a condition terminates
Real-world cues (Lisa eating apples, store owner counting sales)
Two big families
Condition-controlled loops – while
, do-while
Counter-controlled loops – for
Syntax: while(CONDITION){ BODY }
Pre-test: body may execute zero times
Typical architecture
Control variable declared outside, updated inside body
int count = 0;
while (count < 5) {
Console.WriteLine($"Count is {count}");
count++;
}
Apple-eating examples
Unknown number of apples; ask “Are you hungry?” until answer false
Variant with daily limit – compound condition numApples < MAXAPPLES
Test-case design same triad: equivalence, boundary, normal
Take-home: Use when repeat count unknown; think of it as “repeating if”
Post-test loop – body executes at least once
Syntax ends with semicolon: do{...} while(cond);
int num = 0;
do {
Console.WriteLine("Enter a number greater than 0:");
num = Convert.ToInt32(Console.ReadLine());
} while (num <= 0);
Console.WriteLine($"You entered: {num}");
Apple task guaranteeing one apple/day
Risks: off-by-one errors if the “at least once” property is unintended
Ideal when repeat count known or easily derivable
Header packs init, condition, change in one line ⇒ easy auditing
for(int i=0; i<MAX; i++)
for (int i = 1; i <= 5; i++) {
Console.WriteLine($"Iteration {i}");
}
Control variable scope
Declared in header → limited to loop, can reuse same name in later loops
Declared outside if its value needed afterwards
Variants
Count down for(i=MAX;i>MIN;i--)
Char iteration for(char c='a'; c<='j'; c++)
Case study: summing apple sales over n days (user-supplied)
Control var: day index d, condition d < numDays, change d++
Warning: rewriting a clear for
as while
spreads change far from condition, increasing bug risk
break
– exit entire loop immediately; common for sentinel or error escape
for (int i = 0; i < 10; i++) {
if (i == 5) {
break; // Exits the loop when i is 5
}
Console.WriteLine(i);
}
continue
– skip rest of current iteration, jump to condition check
for (int i = 0; i < 5; i++) {
if (i == 2) {
continue; // Skips printing 2, moves to next iteration
}
Console.WriteLine(i);
}
Infinite loop patterns
Explicit while(true)
or for(;;)
Missing update of control variable; braces omission in single-line loops causing logic leak
Example safe sentinel: echo input until user types “exit” → inside infinite loop with break
Good testing & code reviews are antidotes to accidental infinite loops
Real programs must reject/handle unacceptable inputs (e.g. negative apples or day counts)
Technique stack:
Guard with if
before loop start (e.g. numDays<0 → abort via return
)
Inside loop, embed a validation sub-loop (do-while
) to re-prompt until valid
Design rationale slide: choose loop type based on need to ask at least once vs zero-times possibility
Comprehensive test plans cover both invalid and valid scenarios; Gradescope etc. grade on this
Categories: Normal, Boundary, Equivalence, Invalid
Always draft test table before coding, update when requirements or code change
Passing all visible test cases does not guarantee absence of hidden bugs ⇒ reason about logic
Boolean type with relational & logical ops underpins all decision logic
Selection options
Simple fork: if/else
Multi-branch discrete: switch
Multi-condition range: else if
ladder
Carefully test branch order & completeness
Iteration options
for
when repeat count known \rightarrow header shows init+cond+change
while
when count unknown, may execute 0 times
do-while
when body must run once minimum
Guard against invalid data with early if
checks + inner validation loops
Debug aids
Extensive test tables (normal/boundary/invalid)
Avoid deep nesting; prefer clear, flat structures
Watch for missing brace or update – classic infinite-loop source
Principle: DRY (Don’t Repeat Yourself) – loops replace copy-pasted blocks; selection removes redundant paths