Selection, Iteration, and Program ControlIntroductionEngineering programs rarely execute as a simple sequence of instructions. A controller may switch a motor off when its temperature exceeds a limit, a measurement system may repeat sampling until sufficient data are collected, and a diagnostic program may select one action from several possible fault conditions. These behaviors are implemented through program control: the mechanisms that determine which statements execute, how often they execute, and when execution terminates. This chapter develops the use of Boolean expressions, conditional statements, loops, nesting, state tracing, and termination conditions. Examples use C-like pseudocode so that the ideas transfer readily to C, C++, Java, Python, MATLAB, and embedded-system languages. Learning ObjectivesBy the end of this chapter, you should be able to: - Construct and evaluate Boolean expressions using relational and logical operators.
- Select appropriate
if, if–else, and multiway conditional structures. - Design
while, for, and do–while loops with correct initialization, update, and termination logic. - Trace program state systematically through nested decisions and iterations.
- Identify and prevent infinite loops, off-by-one errors, unreachable branches, and unsafe control logic.
- Apply selection and iteration to an engineering monitoring problem.
1. Boolean Expressions and ConditionsA Boolean expression evaluates to either true or false. In some languages, true and false are represented explicitly; in others, an integer value of zero represents false and a nonzero value represents true. Relying on implicit integer meanings can reduce readability and should be avoided when explicit Boolean values are available. 1.1 Relational operatorsRelational operators compare values: | Operator | Meaning |
|---|
== | equal to | != | not equal to | < | less than | > | greater than | <= | less than or equal to | >= | greater than or equal to |
The assignment operator = is not the same as the equality operator ==. Writing x = 5 changes the value of x; writing x == 5 tests whether x currently equals 5. For floating-point measurements, direct equality is often unreliable because of rounding. Instead of testing a == b, use a tolerance condition such as: |a − b| ≤ ε Here, ε is a nonnegative tolerance expressed in the same units as a and b. This test is appropriate when the acceptable measurement or numerical-computation error is known. 1.2 Logical operatorsLogical operators combine conditions: | Operator | Meaning | Example |
|---|
&& | AND; both conditions must be true | temperature > 80 && fanOn | | ` | | ` | ! | NOT; reverses truth value | !enabled |
The expression A && B is true only when both A and B are true. The expression A || B is true when either or both are true. Parentheses should be used to make intended grouping explicit, especially when several operators are combined. For example: if ((voltage < Vmin || voltage > Vmax) && systemEnabled)
raiseAlarm()This means that an alarm is raised only when the voltage is outside its permitted range and the system is enabled. Many languages use short-circuit evaluation. In A && B, if A is false, B may not be evaluated because the complete expression cannot become true. In A || B, if A is true, evaluation may stop immediately. Short-circuiting is useful for safe expressions: if (index >= 0 && index < length && array[index] == target) The array is accessed only after the index bounds have been checked. 1.3 Truth tablesA truth table specifies the result of a logical operation: | A | B | A AND B | A OR B |
|---|
| false | false | false | false | | false | true | false | true | | true | false | false | true | | true | true | true | true |
For NOT, !true is false and !false is true. Truth tables are useful when verifying safety interlocks, alarm logic, and compound conditions before implementation. 2. Selection StructuresSelection allows a program to choose among alternative paths. The selected path depends on a condition evaluated during execution. 2.1 The if statementAn if statement executes its body only when its condition is true: if (current > maximumCurrent)
disableConverter()If the condition is false, execution continues after the body. Braces should normally be used even for a one-statement body because they prevent accidental changes when additional statements are later added. if (current > maximumCurrent) {
disableConverter()
recordFault()
}2.2 The if–else statementAn if–else statement chooses exactly one of two alternatives: if (temperature >= limit)
turnFanOn()
else
turnFanOff()The two branches are mutually exclusive. A good condition partitions the possible input states clearly. If the condition is based on a boundary, decide deliberately whether equality belongs to the upper or lower region. 2.3 Multiple alternativesAn else if chain is appropriate when several mutually exclusive ranges or categories exist: if (error < 0.01)
status = "excellent"
else if (error < 0.05)
status = "acceptable"
else if (error < 0.10)
status = "warning"
else
status = "failure"Conditions are tested from top to bottom. Therefore, the ordering matters. In this example, an error of 0.03 reaches the second branch because it is not less than 0.01 but is less than 0.05. A switch or case structure is often clearer when one discrete expression is compared with fixed constant values: switch (mode) {
case 0: initialize(); break
case 1: measure(); break
case 2: transmit(); break
default: reportInvalidMode()
}The exact syntax varies by language. A default branch is valuable for unexpected input. In languages where an explicit break is required, omitting it may cause unintended fall-through into the next case. 2.4 Nested selectionA conditional inside another conditional is a nested selection. Nesting can represent dependent decisions: if (systemEnabled) {
if (temperature > limit)
disableHeater()
else
maintainTemperature()
} else {
remainIdle()
}Deep nesting can become difficult to read. It may be simplified with guard clauses, combined Boolean expressions, or functions that each perform one decision. The simplification must preserve the original logic. 3. Iteration and RepetitionIteration repeats a group of statements. Every reliable loop has three conceptual components: - Initialization: establishes the initial state.
- Continuation condition: determines whether another iteration is permitted.
- Progress update: changes state so that termination can eventually occur.
A loop that lacks a valid progress mechanism may never terminate. 3.1 The while loopA while loop is a pre-test loop. Its condition is tested before every iteration, so its body may execute zero times. count = 0
while (count < 5) {
process(count)
count = count + 1
}The loop executes for count = 0, 1, 2, 3, 4, and stops when count becomes 5. If count initially equals 5, the body does not execute. A while loop is suitable when the number of repetitions is not known in advance, such as waiting for a sensor event or reading records until end-of-file. 3.2 The for loopA for loop presents initialization, condition, and update in one line: for (i = 0; i < N; i = i + 1) {
sum = sum + sample[i]
}If N is a nonnegative integer and indexing begins at zero, this processes indices 0 through N − 1. The number of iterations is N, provided N does not change inside the loop and the update increases i by one. A common error is using i <= N when the final valid index is N − 1. This produces one extra iteration and may access memory outside the array. 3.3 The do–while loopA do–while loop is a post-test loop. Its body executes at least once: do {
command = readCommand()
} while (command != "QUIT")It is appropriate when an operation must occur before its continuation condition can be evaluated, such as displaying a menu and reading the first selection. It is inappropriate when invalid initial state must prevent the body from executing. 3.4 Sentinel-controlled loopsA sentinel is a special value indicating termination: value = readValue()
while (value != END_MARKER) {
process(value)
value = readValue()
}The sentinel must be distinguishable from valid data. For a stream of real measurements, a special negative value may be unsuitable if negative measurements are physically possible. End-of-file status or a separate validity flag is then safer. 3.5 Counter- and condition-controlled loopsA counter-controlled loop terminates after a planned number of iterations. A condition-controlled loop terminates when a state condition changes. The latter is common in control and communications, but termination must be designed carefully. For a convergence loop, a typical condition is: while (residual > tolerance && iterations < maximumIterations) {
updateEstimate()
residual = calculateResidual()
iterations = iterations + 1
}The tolerance provides an accuracy termination condition; the iteration limit provides a safety termination condition. Both are important because an algorithm may fail to converge. 4. State Tracing and Loop InvariantsState tracing records variable values after each significant statement. It is a practical method for detecting logic errors. Consider: x = 2
for (k = 1; k <= 3; k = k + 1) {
x = 2 * x + k
}A trace table is: | Point | k | x |
|---|
| Before loop | 1 | 2 | | After iteration 1 | 2 | 5 | | After iteration 2 | 3 | 13 | | After iteration 3 | 4 | 29 | | Termination test | 4 | 29 |
The final value is x = 29. Notice that the update of k occurs after the third body execution, so the termination test sees k = 4. A loop invariant is a property that remains true at a specified point during every iteration. For the summation loop: sum = 0
for (i = 0; i < N; i = i + 1)
sum = sum + sample[i]An invariant before each iteration is that sum equals the sum of elements with indices 0 through i − 1. Initially, no elements have been processed and sum = 0. Each iteration adds sample[i], preserving the invariant. When i = N, all elements have been included. Invariants support systematic reasoning about correctness rather than relying only on sample tests. 5. Termination, Correctness, and Common Errors5.1 Infinite loopsAn infinite loop occurs when the continuation condition never becomes false. Typical causes include a missing update, an update in the wrong direction, or a condition that is always true: i = 0
while (i < 10) {
process(i)
// Missing: i = i + 1
}Some infinite loops are intentional in embedded firmware, but they must contain a safe scheduling structure, watchdog strategy, and controlled exit or reset behavior. 5.2 Off-by-one errorsAn off-by-one error processes one item too many or too few. For N zero-based array elements, the standard range is 0 ≤ i < N. Boundary tests should include N = 0, N = 1, and the largest permitted value. 5.3 Unreachable and overlapping branchesA branch is unreachable when an earlier branch captures every case that could reach it: if (x > 0) ...
else if (x > 10) ... The second branch can never execute. Conversely, overlapping conditions may be valid, but their order must express the intended priority. 5.4 Floating-point boundariesA computed value near a threshold may be slightly above or below it because of finite precision. Engineering software should define tolerances, units, and boundary behavior explicitly. A tolerance should be selected from sensor accuracy, numerical error, and system requirements—not chosen arbitrarily. 5.5 Safety-oriented control logicIn a safety-related system, the absence of a valid measurement should not silently be treated as a safe value. Programs should distinguish among valid data, stale data, sensor failure, and communication failure. A fail-safe action, alarm, event log, and independent hardware protection may be required depending on the application and applicable standards. 6. Applied Case: Temperature Protection in a Motor DriveBackgroundConsider an illustrative motor-drive controller that samples winding temperature once per second. Normal operation is allowed below 80 °C. Between 80 °C and 95 °C, the controller commands reduced power and activates a fan. At 95 °C or above, it disables the drive and records a fault. ProblemThe controller must distinguish valid samples from sensor failure, apply the correct operating mode, and continue monitoring until the operator requests shutdown. A simple sequence of independent if statements could issue conflicting commands, so mutually exclusive selection is preferable. Approachmode = "RUN"
while (mode != "SHUTDOWN") {
temperature, valid = readTemperature()
if (!valid) {
mode = "FAULT"
disableDrive()
record("Temperature sensor failure")
}
else if (temperature >= 95.0) {
mode = "FAULT"
disableDrive()
fanOn()
record("Overtemperature")
}
else if (temperature >= 80.0) {
mode = "DERATED"
reducePower()
fanOn()
}
else {
mode = "RUN"
normalPower()
fanOff()
}
if (operatorRequestsShutdown())
mode = "SHUTDOWN"
}The ranges are mutually exclusive because the conditions are evaluated from highest priority to lowest. A reading of 95 °C enters the fault branch, while a reading of 80 °C enters the derated branch. The sensor-validity test has priority over temperature comparisons because an invalid value must not be interpreted as a physical measurement. Analysis and outcomeThe loop is condition-controlled by the shutdown request. Each iteration obtains a new sample, and the external system state changes through sensor input or operator input. A real implementation should also address sampling-period control, stale-data detection, watchdog recovery, actuator feedback, hysteresis, and persistent fault reset policy. Hysteresis may be needed to prevent rapid switching near 80 °C; for example, power reduction could begin at 80 °C but normal operation would resume only below a lower threshold. The exact thresholds must be established by thermal design and safety requirements. Learning points- Validate inputs before using them in control decisions.
- Order branches according to safety priority.
- Make boundary behavior explicit.
- Use a loop termination mechanism appropriate to the system.
- Separate control state from raw sensor values when the system has persistent modes.
7. Engineering Practice and Contemporary ToolsControl logic should be developed from a clear specification, state diagram, or decision table before coding. Unit tests should cover normal, boundary, invalid, and extreme cases. Static analyzers can detect suspicious assignments in conditions, unreachable branches, uninitialized variables, and some loop defects. Debuggers and simulation tools support state tracing without requiring immediate deployment to hardware. AI-assisted programming tools can generate candidate conditions or loops, but generated code must be reviewed against requirements, tested with boundary cases, and checked for unsafe assumptions. In engineering contexts, traceability from requirement to implementation and test is more important than merely producing code quickly. Sensitive firmware, proprietary control logic, and safety-related code should not be submitted to external services without authorization. Chapter SummarySelection and iteration provide the fundamental mechanisms for non-sequential program behavior. Boolean expressions combine relational comparisons with logical operators, and parentheses improve clarity. if, if–else, multiway conditionals, and switch structures select actions; their ordering and boundary conditions determine correctness. while, for, and do–while loops differ in when they test their continuation conditions and how naturally they express unknown, known, or at-least-once repetition. Reliable loops have initialization, a valid continuation condition, and progress toward termination. State tracing and loop invariants provide systematic methods for verifying behavior. Common defects include infinite loops, off-by-one errors, floating-point boundary problems, unreachable branches, and unsafe treatment of invalid data. In engineering applications, control logic should prioritize safety, specify failure behavior, and be supported by testing, static analysis, and requirement traceability. Key TermsBoolean expression: An expression whose result is true or false. Relational operator: An operator that compares two values. Logical operator: An operator that combines or negates Boolean conditions. Short-circuit evaluation: Stopping logical evaluation when the final result is already known. Selection: Choosing one execution path from alternatives. Conditional statement: A statement whose execution depends on a condition. Nested selection: A conditional structure placed inside another conditional structure. Iteration: Repeated execution of a group of statements. Pre-test loop: A loop that tests its condition before executing its body. Post-test loop: A loop that executes its body before testing its condition. Sentinel: A special value or event that indicates termination. Loop invariant: A property that remains true at a defined point during each iteration. Termination condition: A condition that causes a loop or program region to stop. Infinite loop: A loop that does not terminate under the given execution conditions. Off-by-one error: A boundary error causing one extra or one missing iteration. Guard clause: An early condition that handles an exceptional or terminating case. Hysteresis: Different thresholds for entering and leaving an operating state. Fail-safe behavior: A response designed to reduce danger when a fault occurs. State tracing: Recording program-variable values as execution proceeds. Review QuestionsShort Answer Questions- What is the difference between assignment
= and equality testing ==? - Why is a
for loop often suitable for processing an array? - What is the principal difference between a
while loop and a do–while loop? - Define a loop invariant.
- Give two causes of infinite loops.
Long Answer Questions- Explain how relational and logical operators combine to form a Boolean expression. Include a truth-table example.
- Compare
if–else, else if, and switch structures, including suitable engineering applications. - Explain initialization, continuation, and progress in a correctly designed loop.
- Discuss off-by-one errors and methods for detecting them.
- Explain why invalid sensor data should be handled before applying physical threshold tests.
Analytical / Application Questions- Design pseudocode for reading nonnegative measurements until a sentinel is entered, while computing the largest valid measurement. State how you prevent the sentinel from being included in the result.
- Trace the values of
i and sum for a loop that adds five array elements using zero-based indexing. Identify the termination test and the final value of i. - Modify the motor-drive case so that normal operation resumes only when temperature falls below 75 °C after derating. Explain how this hysteresis changes the control logic.
Multiple Choice Questions with AnswersQuestion 1Which expression is true when both A and B are true, but false when either is false? A. A || B B. A && B C. !A && B D. A != B Correct Answer: B. A && B Question 2What is the main difference between a while loop and a do–while loop? A. A while loop cannot contain conditions. B. A do–while loop always executes its body at least once. C. A while loop always executes its body at least once. D. A do–while loop cannot terminate. Correct Answer: B. A do–while loop always executes its body at least once. Question 3For an array containing N elements with zero-based indexing, which condition processes all valid indices exactly once when i starts at zero and increases by one? A. i <= N B. i < N C. i > N D. i == N Correct Answer: B. i < N Question 4What is the purpose of a sentinel in a loop? A. To increase the loop counter B. To identify an error in every iteration C. To indicate that repetition should terminate D. To force every branch to execute Correct Answer: C. To indicate that repetition should terminate Question 5In the sequence if (x > 0) ... else if (x > 10) ..., why is the second branch unreachable? A. The comparison operators are invalid. B. Every value greater than 10 already satisfies x > 0. C. The else keyword prevents comparisons. D. The variable x cannot contain 10. Correct Answer: B. Every value greater than 10 already satisfies x > 0. Question 6Which three elements are essential to reliable counter-controlled iteration? A. Input, output, and storage B. Initialization, continuation condition, and progress update C. A switch statement, a sentinel, and recursion D. A function, a class, and an array Correct Answer: B. Initialization, continuation condition, and progress update Question 7If x = 2 and the loop body executes x = 2*x + k for k = 1, 2, 3, what is the final value of x? A. 13 B. 21 C. 29 D. 32 Correct Answer: C. 29 Question 8Why can direct equality comparison of floating-point measurements be unreliable? A. Floating-point variables cannot be compared. B. Rounding can make mathematically equal results differ slightly. C. Equality always means approximate inequality. D. Relational operators work only with integers. Correct Answer: B. Rounding can make mathematically equal results differ slightly. Question 9In the motor-drive case, why is sensor validity checked before temperature thresholds? A. Invalid data should be treated as a valid zero temperature. B. The validity test makes the loop execute faster in every case. C. A failed sensor must not be interpreted as a physical temperature. D. Temperature thresholds are never used in control systems. Correct Answer: C. A failed sensor must not be interpreted as a physical temperature. Question 10What is a loop invariant? A. A property that remains true at a specified point during iterations B. A value that must change randomly in each iteration C. A condition that guarantees an infinite loop D. A syntax rule for switch statements Correct Answer: A. A property that remains true at a specified point during iterations
|