Concept Lesson
Beginner
4 min

Learning Objective

Understand Foundations well enough to explain it, recognize it in C++, and apply it in a small task.

Why It Matters

This concept is part of the foundation that later lessons and projects assume you already understand.

FoundationsTable Of ContentsControl Flow DiagramSequential ExecutionConditional Statements
Private notes
0/8000

Notes stay private to your browser until account sync is configured.

README
3 min read18 headings

Control Flow in C++

Table of Contents


Introduction

Control flow determines the order in which statements are executed in a program. C++ provides three fundamental control flow mechanisms:

┌─────────────────────────────────────────────────────────────┐
│                    CONTROL FLOW TYPES                       │
├─────────────────────────────────────────────────────────────┤
│  1. Sequential    - Statements execute one after another    │
│  2. Selection     - Choose between different paths          │
│  3. Iteration     - Repeat a block of code                  │
└─────────────────────────────────────────────────────────────┘

Control Flow Diagram

          ┌─────────────┐
          │    Start    │
          └──────┬──────┘
                 │
         ┌───────▼───────┐
         │  Statement 1  │     Sequential
         └───────┬───────┘
                 │
         ┌───────▼───────┐
    ┌────│  Condition?   │────┐
    │    └───────────────┘    │    Selection
   Yes                        No
    │                         │
┌───▼───┐                ┌───▼───┐
│ Path A │                │ Path B │
└───┬───┘                └───┬───┘
    │    ┌───────────────┐    │
    └────►  Merge Point  ◄────┘
         └───────┬───────┘
                 │
         ┌───────▼───────┐
    ┌───►│   Loop Body   │    Iteration
    │    └───────┬───────┘
    │            │
    │    ┌───────▼───────┐
    │    │  Continue?    │────No──►
    │    └───────┬───────┘
    │           Yes
    └────────────┘

Sequential Execution

By default, C++ executes statements in order from top to bottom.

#include <iostream>
using namespace std;

int main() {
    cout << "Step 1" << endl;  // Executes first
    cout << "Step 2" << endl;  // Executes second
    cout << "Step 3" << endl;  // Executes third
    return 0;
}

Conditional Statements

if Statement

Executes a block of code if a condition is true.

     ┌──────────────┐
     │  Condition   │
     └──────┬───────┘
            │
       ┌────▼────┐
      Yes       No
       │         │
   ┌───▼───┐     │
   │ Code  │     │
   └───┬───┘     │
       └────┬────┘
            │
     Continue...

Syntax:

if (condition) {
    // code to execute if condition is true
}

Examples:

int age = 20;

if (age >= 18) {
    cout << "You are an adult." << endl;
}

// Single statement (braces optional but recommended)
if (age >= 18)
    cout << "You can vote." << endl;

// Checking multiple conditions with logical operators
int score = 85;
if (score >= 80 && score <= 100) {
    cout << "Excellent performance!" << endl;
}

if-else Statement

Choose between two paths based on a condition.

     ┌──────────────┐
     │  Condition   │
     └──────┬───────┘
            │
       ┌────▼────┐
      Yes       No
       │         │
   ┌───▼───┐ ┌───▼───┐
   │ True  │ │ False │
   │ Block │ │ Block │
   └───┬───┘ └───┬───┘
       └────┬────┘
            │
     Continue...

Syntax:

if (condition) {
    // code if condition is true
} else {
    // code if condition is false
}

Examples:

int number = 7;

if (number % 2 == 0) {
    cout << number << " is even." << endl;
} else {
    cout << number << " is odd." << endl;
}

// Using ternary as alternative for simple cases
string result = (number % 2 == 0) ? "even" : "odd";
cout << number << " is " << result << endl;

if-else-if Ladder

Check multiple conditions in sequence.

int score = 75;
char grade;

if (score >= 90) {
    grade = 'A';
} else if (score >= 80) {
    grade = 'B';
} else if (score >= 70) {
    grade = 'C';
} else if (score >= 60) {
    grade = 'D';
} else {
    grade = 'F';
}

cout << "Grade: " << grade << endl;  // Output: Grade: C

Key Points:

  • Conditions are evaluated top to bottom
  • Only the first true condition's block executes
  • else is optional and catches all remaining cases

Nested if Statements

if statements inside other if statements.

int age = 25;
bool hasLicense = true;

if (age >= 18) {
    cout << "You are an adult." << endl;

    if (hasLicense) {
        cout << "You can drive." << endl;
    } else {
        cout << "You need a license to drive." << endl;
    }
} else {
    cout << "You are a minor." << endl;
}

Warning: Deeply nested if statements can be hard to read. Consider refactoring:

// Better: Early return pattern
void checkDriving(int age, bool hasLicense) {
    if (age < 18) {
        cout << "You are a minor." << endl;
        return;
    }

    cout << "You are an adult." << endl;

    if (hasLicense) {
        cout << "You can drive." << endl;
    } else {
        cout << "You need a license to drive." << endl;
    }
}

switch Statement

Select one of many code blocks to execute.

int day = 3;

switch (day) {
    case 1:
        cout << "Monday" << endl;
        break;
    case 2:
        cout << "Tuesday" << endl;
        break;
    case 3:
        cout << "Wednesday" << endl;
        break;
    case 4:
        cout << "Thursday" << endl;
        break;
    case 5:
        cout << "Friday" << endl;
        break;
    case 6:
    case 7:
        cout << "Weekend" << endl;
        break;
    default:
        cout << "Invalid day" << endl;
}

Key Points:

  • Expression must be integral type (int, char, enum)
  • break prevents fall-through to next case
  • default handles unmatched values
  • Multiple cases can share the same code block

Fall-through Example:

char grade = 'B';

switch (grade) {
    case 'A':
    case 'B':
    case 'C':
        cout << "Pass" << endl;
        break;
    case 'D':
    case 'F':
        cout << "Fail" << endl;
        break;
    default:
        cout << "Invalid grade" << endl;
}

C++17 Init Statement in switch:

switch (int x = getValue(); x) {
    case 1:
        cout << "One" << endl;
        break;
    case 2:
        cout << "Two" << endl;
        break;
    default:
        cout << "Other: " << x << endl;
}

Loops

for Loop

Best for known number of iterations.

     ┌─────────────────┐
     │  Initialize     │
     └────────┬────────┘
              │
     ┌────────▼────────┐
     │   Condition?    │───No──► Exit
     └────────┬────────┘
             Yes
              │
     ┌────────▼────────┐
     │   Loop Body     │
     └────────┬────────┘
              │
     ┌────────▼────────┐
     │   Update        │
     └────────┬────────┘
              │
              └───────────────┐
                              │
     ┌────────────────────────┘
     │
     ▼ (Back to Condition)

Syntax:

for (initialization; condition; update) {
    // loop body
}

Examples:

// Basic counting loop
for (int i = 0; i < 5; i++) {
    cout << i << " ";  // Output: 0 1 2 3 4
}
cout << endl;

// Counting backward
for (int i = 5; i > 0; i--) {
    cout << i << " ";  // Output: 5 4 3 2 1
}
cout << endl;

// Step by 2
for (int i = 0; i <= 10; i += 2) {
    cout << i << " ";  // Output: 0 2 4 6 8 10
}
cout << endl;

// Multiple variables
for (int i = 0, j = 10; i < j; i++, j--) {
    cout << "i=" << i << ", j=" << j << endl;
}

// Infinite loop (use with caution)
for (;;) {
    // runs forever unless break
}

while Loop

Best when number of iterations is unknown.

while (condition) {
    // loop body
}

Examples:

// Basic while loop
int count = 0;
while (count < 5) {
    cout << count << " ";
    count++;
}
cout << endl;  // Output: 0 1 2 3 4

// Input validation
int number;
cout << "Enter a positive number: ";
cin >> number;

while (number <= 0) {
    cout << "Invalid! Enter a positive number: ";
    cin >> number;
}

// Reading until sentinel value
int input;
int sum = 0;
cout << "Enter numbers (0 to stop): " << endl;

while (cin >> input && input != 0) {
    sum += input;
}
cout << "Sum: " << sum << endl;

do-while Loop

Executes at least once, then checks condition.

     ┌────────────────┐
     │   Loop Body    │◄────┐
     └───────┬────────┘     │
             │              │
     ┌───────▼────────┐     │
     │  Condition?    │    Yes
     └───────┬────────┘     │
            No              │
             │    └─────────┘
             │
          Exit

Syntax:

do {
    // loop body
} while (condition);

Examples:

// Guaranteed at least one execution
int count = 0;
do {
    cout << count << " ";
    count++;
} while (count < 5);
cout << endl;  // Output: 0 1 2 3 4

// Menu system
int choice;
do {
    cout << "\n=== Menu ===" << endl;
    cout << "1. Option A" << endl;
    cout << "2. Option B" << endl;
    cout << "3. Exit" << endl;
    cout << "Enter choice: ";
    cin >> choice;

    switch (choice) {
        case 1: cout << "You chose A" << endl; break;
        case 2: cout << "You chose B" << endl; break;
        case 3: cout << "Goodbye!" << endl; break;
        default: cout << "Invalid choice" << endl;
    }
} while (choice != 3);

// Difference from while
int x = 10;
do {
    cout << "do-while executes" << endl;
} while (x < 5);  // Prints once

while (x < 5) {
    cout << "while does not execute" << endl;  // Never prints
}

Range-based for Loop (C++11)

Simplest way to iterate over containers.

Syntax:

for (declaration : container) {
    // use element
}

Examples:

#include <vector>
#include <array>
#include <string>

// Iterate over array
int arr[] = {1, 2, 3, 4, 5};
for (int x : arr) {
    cout << x << " ";  // Output: 1 2 3 4 5
}
cout << endl;

// Iterate over vector
vector<string> names = {"Alice", "Bob", "Charlie"};
for (const string& name : names) {
    cout << name << " ";
}
cout << endl;

// Iterate over string
string text = "Hello";
for (char c : text) {
    cout << c << "-";  // Output: H-e-l-l-o-
}
cout << endl;

// Modify elements (use reference)
vector<int> nums = {1, 2, 3, 4, 5};
for (int& n : nums) {
    n *= 2;  // Double each element
}

// With auto
for (auto& n : nums) {
    cout << n << " ";  // Output: 2 4 6 8 10
}
cout << endl;

// Initializer list
for (int x : {10, 20, 30, 40}) {
    cout << x << " ";  // Output: 10 20 30 40
}

Jump Statements

break Statement

Exits the innermost loop or switch immediately.

// Break out of loop
for (int i = 0; i < 10; i++) {
    if (i == 5) break;
    cout << i << " ";  // Output: 0 1 2 3 4
}
cout << endl;

// Search example
int target = 7;
int arr[] = {2, 4, 6, 7, 8, 10};
bool found = false;

for (int i = 0; i < 6; i++) {
    if (arr[i] == target) {
        cout << "Found at index " << i << endl;
        found = true;
        break;
    }
}

if (!found) {
    cout << "Not found" << endl;
}

continue Statement

Skips the rest of current iteration and continues with next.

// Skip even numbers
for (int i = 0; i < 10; i++) {
    if (i % 2 == 0) continue;
    cout << i << " ";  // Output: 1 3 5 7 9
}
cout << endl;

// Skip negative numbers
int nums[] = {3, -1, 4, -1, 5, -9, 2};
int sum = 0;

for (int n : nums) {
    if (n < 0) continue;
    sum += n;
}
cout << "Sum of positives: " << sum << endl;  // Output: 14

goto Statement

Jumps to a labeled statement (use sparingly).

// goto example (avoid in modern code)
int i = 0;

loop_start:
    if (i >= 5) goto loop_end;
    cout << i << " ";
    i++;
    goto loop_start;

loop_end:
    cout << endl;  // Output: 0 1 2 3 4

// Legitimate use: breaking out of nested loops
for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
        if (i * j > 25) {
            goto exit_loops;
        }
        cout << "(" << i << "," << j << ") ";
    }
}

exit_loops:
    cout << "Exited nested loops" << endl;

Warning: goto makes code hard to follow. Prefer structured alternatives.

return Statement

Exits the current function.

int findFirst(int arr[], int size, int target) {
    for (int i = 0; i < size; i++) {
        if (arr[i] == target) {
            return i;  // Exit function, return index
        }
    }
    return -1;  // Not found
}

// Early return for validation
bool processData(int value) {
    if (value < 0) {
        cout << "Error: negative value" << endl;
        return false;
    }

    // Process value...
    cout << "Processing: " << value << endl;
    return true;
}

Nested Loops

Loops inside other loops.

// Multiplication table
for (int i = 1; i <= 5; i++) {
    for (int j = 1; j <= 5; j++) {
        cout << setw(4) << i * j;
    }
    cout << endl;
}
/*
Output:
   1   2   3   4   5
   2   4   6   8  10
   3   6   9  12  15
   4   8  12  16  20
   5  10  15  20  25
*/

// Pattern printing
int n = 5;
for (int i = 1; i <= n; i++) {
    for (int j = 1; j <= i; j++) {
        cout << "* ";
    }
    cout << endl;
}
/*
Output:
*
* *
* * *
* * * *
* * * * *
*/

// Breaking out of nested loops
bool found = false;
int matrix[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

for (int i = 0; i < 3 && !found; i++) {
    for (int j = 0; j < 3 && !found; j++) {
        if (matrix[i][j] == 5) {
            cout << "Found 5 at [" << i << "][" << j << "]" << endl;
            found = true;
        }
    }
}

// Alternative: Use a function
auto findInMatrix = [](int mat[][3], int rows, int target) -> pair<int, int> {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 3; j++) {
            if (mat[i][j] == target) {
                return {i, j};
            }
        }
    }
    return {-1, -1};
};

auto [row, col] = findInMatrix(matrix, 3, 5);

Loop Control Patterns

Counter-Controlled Loop

for (int i = 0; i < 10; i++) {
    // Process item i
}

Sentinel-Controlled Loop

int value;
while (cin >> value && value != -1) {
    // Process value until -1 is entered
}

Flag-Controlled Loop

bool done = false;
while (!done) {
    // Process...
    if (someCondition) {
        done = true;
    }
}

Infinite Loop with Break

while (true) {
    // Process...
    if (shouldExit) {
        break;
    }
}

Common Algorithms

int linearSearch(int arr[], int size, int target) {
    for (int i = 0; i < size; i++) {
        if (arr[i] == target) {
            return i;
        }
    }
    return -1;
}

Finding Maximum

int findMax(int arr[], int size) {
    int maxVal = arr[0];
    for (int i = 1; i < size; i++) {
        if (arr[i] > maxVal) {
            maxVal = arr[i];
        }
    }
    return maxVal;
}

Sum of Array

int sum(int arr[], int size) {
    int total = 0;
    for (int i = 0; i < size; i++) {
        total += arr[i];
    }
    return total;
}

Count Occurrences

int countOccurrences(int arr[], int size, int target) {
    int count = 0;
    for (int i = 0; i < size; i++) {
        if (arr[i] == target) {
            count++;
        }
    }
    return count;
}

Reverse Array

void reverseArray(int arr[], int size) {
    for (int i = 0; i < size / 2; i++) {
        swap(arr[i], arr[size - 1 - i]);
    }
}

Check Prime

bool isPrime(int n) {
    if (n <= 1) return false;
    if (n <= 3) return true;
    if (n % 2 == 0 || n % 3 == 0) return false;

    for (int i = 5; i * i <= n; i += 6) {
        if (n % i == 0 || n % (i + 2) == 0) {
            return false;
        }
    }
    return true;
}

Factorial

unsigned long long factorial(int n) {
    unsigned long long result = 1;
    for (int i = 2; i <= n; i++) {
        result *= i;
    }
    return result;
}

Fibonacci

int fibonacci(int n) {
    if (n <= 1) return n;

    int a = 0, b = 1;
    for (int i = 2; i <= n; i++) {
        int temp = a + b;
        a = b;
        b = temp;
    }
    return b;
}

Best Practices

1. Always Use Braces

// Bad
if (condition)
    doSomething();

// Good
if (condition) {
    doSomething();
}

2. Keep Loops Simple

// Bad: Multiple responsibilities
for (int i = 0; i < n; i++) {
    process(arr[i]);
    validate(arr[i]);
    log(arr[i]);
    save(arr[i]);
}

// Good: Single responsibility
for (int i = 0; i < n; i++) {
    handleItem(arr[i]);
}

void handleItem(int item) {
    process(item);
    validate(item);
    log(item);
    save(item);
}

3. Prefer Range-based for

// Old style
for (size_t i = 0; i < vec.size(); i++) {
    cout << vec[i] << " ";
}

// Modern style
for (const auto& item : vec) {
    cout << item << " ";
}

4. Avoid Infinite Loops

// Ensure loop termination
while (condition) {
    // Make sure condition eventually becomes false
    // or use break
}

5. Use Meaningful Loop Variables

// Bad
for (int i = 0; i < users.size(); i++) { }

// Better
for (size_t userIndex = 0; userIndex < users.size(); userIndex++) { }

// Best
for (const auto& user : users) { }

6. Limit Nesting Depth

// Bad: Deep nesting
if (a) {
    if (b) {
        if (c) {
            if (d) {
                // code
            }
        }
    }
}

// Good: Early returns
if (!a) return;
if (!b) return;
if (!c) return;
if (!d) return;
// code

Common Mistakes

1. Off-by-One Errors

// Wrong: Accesses arr[size], which is out of bounds
for (int i = 0; i <= size; i++) {
    arr[i] = 0;
}

// Correct
for (int i = 0; i < size; i++) {
    arr[i] = 0;
}

2. Infinite Loop

// Wrong: i never changes
int i = 0;
while (i < 10) {
    cout << i << endl;
    // Missing: i++
}

// Wrong: Condition always true
for (int i = 10; i > 0; i++) {  // Should be i--
    cout << i << endl;
}

3. Missing Break in Switch

// Wrong: Falls through to next case
switch (x) {
    case 1:
        cout << "One" << endl;
        // Missing break!
    case 2:
        cout << "Two" << endl;
        break;
}

// Correct
switch (x) {
    case 1:
        cout << "One" << endl;
        break;
    case 2:
        cout << "Two" << endl;
        break;
}

4. Modifying Loop Variable

// Dangerous: Modifying i inside loop
for (int i = 0; i < 10; i++) {
    if (condition) {
        i += 2;  // May cause unexpected behavior
    }
}

5. Assignment Instead of Comparison

// Wrong: Assignment, always true
if (x = 5) { }

// Correct: Comparison
if (x == 5) { }

6. Empty Loop Body

// Wrong: Semicolon creates empty loop
for (int i = 0; i < 10; i++);  // Loop does nothing
{
    cout << i << endl;  // Error: i is out of scope
}

// Correct
for (int i = 0; i < 10; i++) {
    cout << i << endl;
}

Summary

Control StructureUse When
ifSingle condition to check
if-elseTwo mutually exclusive paths
if-else-ifMultiple conditions to check sequentially
switchSingle variable with multiple discrete values
forKnown number of iterations
whileUnknown iterations, check before
do-whileUnknown iterations, execute at least once
range-forIterating over containers
breakExit loop early
continueSkip to next iteration
returnExit function

Loop Selection Guide

┌────────────────────────────────────────────────────────────┐
│                WHICH LOOP SHOULD I USE?                    │
├────────────────────────────────────────────────────────────┤
│ Know iteration count?                                      │
│   YES → Use for loop                                       │
│   NO  → Do you need at least one iteration?               │
│          YES → Use do-while                               │
│          NO  → Use while                                  │
│                                                            │
│ Iterating over container?                                  │
│   YES → Use range-based for loop                          │
└────────────────────────────────────────────────────────────┘

Compilation

g++ -std=c++17 -Wall -Wextra examples.cpp -o examples
./examples


Master control flow to write powerful and efficient C++ programs!

Skill Check

Test this lesson

Answer 4 quick questions to lock in the lesson and feed your adaptive practice queue.

--
Score
0/4
Answered
Not attempted
Status
1

Which module does this lesson belong to?

2

Which section is covered in this lesson content?

3

Which term is most central to this lesson?

4

What is the best way to use this lesson for real learning?

Your answers save locally first, then sync when account storage is available.
Practice queue