9.3 Programming Logic, Control Flow & Data Structures
Key Takeaways
- Organizational design techniques conceptualize program execution before coding: Algorithms specify finite, deterministic step-by-step logic; Pseudocode outlines structured logic in human-readable notation; Flowcharts visually map execution flow using ANSI/ISO symbols (terminators, processes, decisions, and I/O).
- Boolean logic evaluates compound conditional statements using Logical AND (&&), Logical OR (||), and Logical NOT (!) operators alongside relational comparisons (==, !=, <, >, <=, >=).
- Control flow branching mechanisms direct program execution paths: single-path if statements, alternative-path if-else statements, cascading multi-branch evaluations, and switch/case statements for multi-branch discrete matching.
- Iterative loop constructs automate repetitive execution: count-controlled for loops execute a predetermined number of iterations; pre-test while loops evaluate conditions before loop execution (can execute zero times); post-test do-while loops evaluate conditions after loop execution (guaranteed to execute at least once).
- Fundamental data structures store collections in memory: contiguous fixed-size zero-indexed Arrays, dynamically resizable Lists/Vectors, and key-value Dictionaries; modular programming uses functions with local/global scoping and Object-Oriented Programming (OOP) classes and objects.
Programming Logic, Control Flow & Data Structures
Core Foundation: Computer software achieves meaningful work by directing how instructions execute over time. By default, computer programs execute sequentially from top to bottom, one statement after another. To solve complex problems, developers introduce control flow structures: branching logic to make decisions, loops to repeat operations, data structures to organize related information, and subroutines to structure code modularly.
Organizational Techniques: Algorithms, Pseudocode & Flowcharts
Before writing code in a formal programming language, software engineers organize their logic using standardized design abstractions that are independent of any specific language syntax.
1. Algorithms
An algorithm is a finite, unambiguous, step-by-step sequence of instructions designed to solve a specific problem, perform a computational calculation, or process data.
- Properties of a Valid Algorithm:
- Finiteness: The algorithm must terminate after a countable, finite number of steps; it cannot loop indefinitely.
- Definiteness: Every individual instruction must be clear, precise, and completely unambiguous.
- Input & Output: Accepts zero or more clearly defined inputs and produces one or more verified outputs.
- Effectiveness: Every operation must be feasible and computationally possible on standard hardware.
2. Pseudocode
Pseudocode is a high-level, human-readable representation of program logic that combines structured programming constructs with plain English natural language. It allows developers to design algorithms without worrying about strict language syntax, semicolons, or memory declarations.
ALGORITHM CalculateInvoiceTotal
INPUT: subtotal, customerState
OUTPUT: finalTotal
SET taxRate = 0.0
IF customerState == "CA" THEN
SET taxRate = 0.0725
ELSE IF customerState == "NY" THEN
SET taxRate = 0.08875
ELSE
SET taxRate = 0.05
END IF
SET calculatedTax = subtotal * taxRate
SET finalTotal = subtotal + calculatedTax
RETURN finalTotal
END ALGORITHM
3. Flowcharts
A flowchart is a standardized diagrammatic representation that visualizes the sequential steps, decisions, and data movements of a program algorithm. Standardized by the American National Standards Institute (ANSI) and the International Organization for Standardization (ISO), flowcharts use specific geometric shapes to represent different operational tasks:
- Oval / Rounded Rectangle (Terminator): Signifies the entry (Start) or exit (End / Stop) point of an entire program or a discrete subroutine.
- Rectangle (Process): Represents an internal computational action, data transformation, or variable assignment (e.g.,
SET total = count * price). - Diamond (Decision): Represents a conditional evaluation or branching question that tests a logical predicate. It has one incoming flowline and two or more outgoing flowlines labeled with outcomes (typically
True/FalseorYes/No). - Parallelogram (Input / Output): Represents an operation that receives external input into the system (e.g., reading keyboard entry, capturing a barcode scan) or sends output to an external destination (e.g., displaying text on a monitor, sending a page to a printer).
- Directed Arrows (Flowlines): Connect symbols to indicate the precise chronological sequence of execution.
| Flowchart Symbol | Geometric Shape | Operational Meaning | Real-World Software Example |
|---|---|---|---|
| Terminator | Oval / Rounded Rectangle | Program initiation or termination | START or RETURN 0 |
| Process | Rectangle | Computational calculation, internal assignment | tax = subtotal * 0.08 |
| Decision | Diamond | Conditional evaluation with branching paths | isPasswordCorrect? (Yes / No) |
| Input / Output | Parallelogram | User input or display output | PROMPT user for PIN / PRINT receipt |
| Flowline | Directed Arrow | Directional control flow path | Connects Decision to Process |
Comments, Documentation & Sequence
Comments explain intent for human readers and are normally ignored by the compiler or interpreter. Good comments record why a non-obvious choice exists; they should not merely repeat a clear statement, and they must be updated when code changes. Broader documentation may describe inputs, outputs, dependencies, error conditions, algorithms, and setup procedures so another developer can safely maintain the program.
Sequence is the default logic pattern: statements execute in their written order unless a branch, loop, function call, exception, or other control transfer changes the path. In a flowchart, ordinary process boxes connected top-to-bottom demonstrate sequence; a decision diamond introduces branching.
Boolean Logic, Relational Operators & Truth Tables
Computer decision-making relies on Boolean logic, evaluating expressions that resolve strictly to either true or false.
1. Relational (Comparison) Operators
Relational operators compare two values or expressions and return a boolean truth state:
==(Equal To): Returnstrueif operands have identical values (5 == 5istrue).!=(Not Equal To): Returnstrueif operands have different values (5 != 3istrue).<(Less Than) and>(Greater Than): Tests relative numeric magnitude.<=(Less Than or Equal To) and>=(Greater Than or Equal To): Inclusive boundary tests.
2. Logical Operators
Logical operators combine multiple relational comparisons into compound logical expressions:
- Logical AND (
&&orAND): Evaluates totrueonly if BOTH operands are true. If either operand is false, the entire expression evaluates tofalse. - Logical OR (
||orOR): Evaluates totrueif AT LEAST ONE operand is true. It evaluates tofalseonly if both operands are false. - Logical NOT (
!orNOT): A unary operator that inverts the logical truth state. If an expression is true, NOT makes itfalse; if false, NOT makes ittrue.
Standard Boolean Truth Table
| Operand A | Operand B | A AND B (A && B) | A OR B (A || B) | NOT A (!A) |
|---|---|---|---|---|
true | true | true | true | false |
true | false | false | true | false |
false | true | false | true | true |
false | false | false | false | true |
- Compound Expression Walkthrough: Consider the security rule:
(userAge >= 18 && hasPhotoID == true) || hasAdminOverride == true.- If
userAgeis 16 andhasPhotoIDis true, the left sub-expression(16 >= 18 && true)evaluates to(false && true) = false. - However, if
hasAdminOverrideis true, the overarching expression evaluates tofalse || true, resolving successfully totrue.
- If
- Short-Circuit Evaluation: Modern programming runtimes optimize boolean evaluation through short-circuiting. In an
ANDexpression, if the first operand evaluates tofalse, the system skips evaluating subsequent operands because the expression can never be true. In anORexpression, if the first operand istrue, subsequent evaluations are bypassed immediately.
Control Flow: Branching & Conditional Logic
Branching structures allow a computer to choose different execution paths depending on the evaluation of boolean conditions.
1. if and if-else Branching
- Single-Path
ifStatement: Tests a condition; iftrue, it executes an inner block of code. Iffalse, the block is bypassed entirely. - Two-Path
if-elseStatement: Provides a fork in execution. If the condition istrue, theifblock executes; if the condition isfalse, the alternativeelseblock executes. - Cascading
if-else if-elseLadder: Evaluates a series of mutually exclusive conditions sequentially until one evaluates totrue. If none evaluate to true, the final fallbackelseblock executes.
2. switch / case Statements
When a program must evaluate a single discrete variable against dozens of possible constant values, cascading if-else ladders become unreadable and inefficient. A switch statement evaluates an expression once and branches directly to the matching case block.
- The
breakStatement: At the end of eachcaseblock, abreakkeyword transfers control immediately outside the switch structure. Omitting abreakstatement causes fall-through, where execution cascades into the next case's instructions regardless of whether that case matches. - The
defaultBlock: Functions like the final fallbackelseclause, executing only when none of the explicit case values match the evaluated variable.
SWITCH (userRole)
CASE "Admin":
GRANT fullSystemAccess()
BREAK
CASE "Manager":
GRANT reportingAccess()
BREAK
CASE "Guest":
GRANT readOnlyAccess()
BREAK
DEFAULT:
DENY allAccess()
LOG securityAlert("Unrecognized role")
END SWITCH
Iterative Structures: Loops & Hazards
Iterative structures (loops) automate repetitive computational tasks by executing a block of code multiple times until a terminating condition is met.
1. Count-Controlled Loops: The for Loop
A for loop is a count-controlled loop used when the program knows in advance how many times an operation must execute (such as iterating through every element in an array of 50 items).
- Three Control Expressions:
- Initialization: Initializes a loop counter variable (e.g.,
let i = 0). - Condition: Evaluated before every iteration; the loop continues as long as this evaluates to
true(e.g.,i < 10). - Step / Increment: Modifies the counter at the end of every iteration (e.g.,
i = i + 1ori++).
- Initialization: Initializes a loop counter variable (e.g.,
2. Condition-Controlled Loops: while vs. do-while
Condition-controlled loops repeat based strictly on a boolean condition, rather than a fixed counter.
-
The
whileLoop (Pre-Test Loop):- Evaluates its terminating condition BEFORE executing the loop body.
- If the condition is
falseon the very first check, the loop body executes zero times. - Use Case: Reading data from a network stream where the stream may already be empty upon arrival.
-
The
do-whileLoop (Post-Test Loop):- Executes the loop body first, and evaluates the terminating condition AFTER the loop body finishes.
- Because the check occurs at the end, the loop body is guaranteed to execute AT LEAST ONCE, regardless of whether the condition is true or false initially.
- Use Case: Prompting a user to enter their password or PIN on an ATM screen. The keypad and prompt must display at least once before testing whether the entered PIN matches.
3. Loop Control Statements
break: Terminates the entire loop immediately, transferring execution to the first statement following the loop.continue: Immediately halts the remainder of the current iteration, jumping directly to the condition test and increment step for the next iteration.
4. The Infinite Loop Hazard
An infinite loop occurs when a loop's terminating condition never evaluates to false. This typically happens when the developer forgets to increment the counter variable, writes a faulty comparison, or hardcodes a static while (true) loop without an internal break exit.
- Consequences: The loop locks an entire CPU core thread at 100% utilization, starves other processes of processor cycles, causes the application to freeze, and can lead to out-of-memory crashes.
| Loop Construct | Loop Category | Condition Evaluation Point | Minimum Iteration Count | Primary Use Case |
|---|---|---|---|---|
for Loop | Count-controlled | Pre-test (before each iteration) | 0 times | Iterating through known collections or fixed numeric ranges |
while Loop | Condition-controlled | Pre-test (before loop body) | 0 times | Polling a sensor or socket while a condition remains true |
do-while Loop | Condition-controlled | Post-test (after loop body) | 1 time (Guaranteed) | User input prompts, menu selections, ATM PIN entry |
Core Data Structures: Organizing Information in Memory
Data structures define how related data values are organized, linked, and accessed within computer memory.
1. Arrays
An array is a fixed-size, sequential collection of elements of the same data type stored in contiguous (adjacent) physical memory locations.
- Zero-Indexed Access: Arrays are indexed starting at zero (
0). For an array of size $N$, the first element is located at index[0], the second element at index[1], and the final element at index[N - 1]. - Instant Random Access ($O(1)$ Time): Because elements are stored in contiguous memory and have identical bit sizes, the processor can calculate the exact physical memory address of any element instantly using the formula:
- Limitation: In static languages, an array's size is fixed at allocation. An array created with 10 elements cannot expand to hold an 11th element.
2. Lists and Vectors (Dynamic Arrays)
A list (or vector / dynamic array) is a linear collection of elements that can dynamically grow and shrink in size during program execution.
- When elements are appended to a list that has reached its internal memory threshold, the runtime engine automatically allocates a larger contiguous memory buffer, copies existing elements over, and frees the old buffer.
- Example: Python
list, JavaArrayList, or C++std::vector.
3. Key-Value Pairs / Dictionaries / Hash Maps
A dictionary (also known as a hash map, associative array, or key-value store) organizes data into pairs of unique keys mapped to specific values.
- Unlike arrays (which access data using sequential numeric integers
0, 1, 2), dictionaries access data using unique descriptive keys (typically strings). - Example:
userProfile = { "username": "alex99", "email": "alex@corp.com", "role": "Auditor" }. AccessinguserProfile["role"]returns"Auditor"instantly.
Modular Programming: Subroutines, Scope & Object-Oriented Concepts
To build maintainable software, engineers break monolithic programs into smaller, reusable building blocks.
1. Subroutines: Functions and Methods
A function (or procedure / subroutine) is a named, self-contained block of reusable code that performs a specific operational task.
- Parameters vs. Arguments:
- Parameters: The formal variable names declared in the function's definition signature (e.g.,
function calculateTax(price, rate)). - Arguments: The actual, concrete values passed into the function when it is invoked (e.g.,
calculateTax(100.0, 0.08)).
- Parameters: The formal variable names declared in the function's definition signature (e.g.,
- Return Values: When a function completes its execution, it sends a value back to the calling statement via a
returnkeyword.
2. Variable Scope: Local vs. Global
Scope defines the visibility and operational lifetime of a variable within a program's codebase:
- Local Scope: Variables declared inside a function or block. They are created on the thread's call stack when the function begins and destroyed when the function exits. They cannot be accessed or altered by code outside that function.
- Global Scope: Variables declared outside all functions at the root program level. They remain in memory throughout the entire execution lifetime of the application and are accessible from any subroutine.
- Engineering Best Practice: Overusing global variables is a major technical antipattern. Global variables create tight coupling, unpredictable side effects, and race conditions in multithreaded applications. Developers should prioritize local scoping.
3. Object-Oriented Programming (OOP) Concepts
Object-Oriented Programming (OOP) is an industry-standard programming paradigm that organizes software design around data entities—called objects—rather than procedural functions and standalone logic.
- Class (The Blueprint): A class is an abstract template, definition, or prototype that specifies what data an entity will contain and what actions it can perform. A class does not occupy active object memory; it is merely the structural blueprint.
- Object (The Instance): An object is a concrete, individual entity instantiated in active memory from a class blueprint. Creating an object is termed instantiation (e.g.,
let account1 = new BankAccount();). - Attributes / Fields (State Data): Variables defined within a class that store the internal state or characteristics of an object (e.g.,
accountNumber,accountBalance,ownerName). - Methods (Behaviors): Functions defined within a class that define the actions or behaviors an object can execute, often manipulating its internal attributes (e.g.,
deposit(amount),withdraw(amount)).
+-------------------------------------------------------------------------+
| CLASS: BankAccount |
| |
| ATTRIBUTES (State / Fields): |
| - accountNumber: String |
| - balance: Float |
| |
| METHODS (Behavior / Functions): |
| + deposit(amount) |
| + withdraw(amount) |
+-------------------------------------------------------------------------+
│
Instantiates (Creates in RAM)
▼
+-------------------------------------------------------------------------+
| OBJECT: account1 (Instance) |
| accountNumber = "ACT-8841" |
| balance = $1,450.00 |
+-------------------------------------------------------------------------+
Practical Diagnostic Scenarios & Exam Pitfalls
- Trap 1: The Off-by-One Array Index Error. In zero-indexed languages, the last element of an array with 10 elements is at index
[9], not[10]. Attempting to accessarray[10]results in anIndexOutOfBoundsExceptionor memory violation crash. - Trap 2: Confusing
whilewithdo-whileExecution Counts. Remember that a pre-testwhileloop can execute 0 times if the condition evaluates to false immediately. A post-testdo-whileloop is guaranteed to execute at least 1 time because the condition is evaluated at the end. - Trap 3: Omitting
breakin aswitchStatement. Forgetting abreakkeyword at the end of acaseblock causes accidental "fall-through," executing subsequent cases until a break is encountered. - Trap 4: Confusing a Class with an Object. A class is the non-physical architectural blueprint (like the schematic drawing of a building); an object is the tangible, memory-consuming entity instantiated from that blueprint (like the physical skyscraper itself).
In a standardized system flowchart mapping a user authentication workflow, which geometric shape must be used to represent the conditional evaluation: "Is the entered password valid?"
A developer is writing an automated cash dispensing subroutine for an ATM. The user interface must present the PIN prompt and capture numeric input at least once before testing whether the entered PIN matches the bank records. Which looping structure is specifically engineered to guarantee at least one execution of its loop body?
An array containing five employee names is declared in a program as: employees = ["Alice", "Bob", "Charlie", "David", "Emma"]. In a standard zero-indexed programming language, which expression accesses the first element ("Alice"), and what is the index of the final element ("Emma")?
In Object-Oriented Programming (OOP), what is the foundational technical distinction between a class and an object?