Skip to content

🔀 Control Flow — Điều khiển luồng

Control flow quyết định thứ tự thực thi của code. Hiểu rõ if/else, switch, và loops là nền tảng để viết logic phức tạp.

if / else — Cơ bản

cpp
#include <iostream>

int main() {
    int score = 85;
    
    if (score >= 90) {
        std::cout << "Grade: A" << std::endl;
    } else if (score >= 80) {
        std::cout << "Grade: B" << std::endl;
    } else if (score >= 70) {
        std::cout << "Grade: C" << std::endl;
    } else {
        std::cout << "Grade: F" << std::endl;
    }
    
    return 0;
}

if với Initializer (C++17)

C++17 cho phép khai báo biến trong điều kiện if:

cpp
#include <iostream>
#include <map>
#include <string>

int main() {
    std::map<std::string, int> ages = {{"Alice", 25}, {"Bob", 30}};
    
    // C++17: if với initializer
    if (auto it = ages.find("Alice"); it != ages.end()) {
        std::cout << "Found: " << it->first << " = " << it->second << std::endl;
    } else {
        std::cout << "Not found" << std::endl;
    }
    // 'it' không tồn tại ngoài scope này — clean!
    
    return 0;
}

📌 Best Practice

Dùng if với initializer khi biến chỉ cần tồn tại trong scope của if/else. Giúp code clean hơn và tránh biến thừa.


switch / case

cpp
#include <iostream>

int main() {
    int day = 3;
    
    switch (day) {
        case 1:
            std::cout << "Monday" << std::endl;
            break;
        case 2:
            std::cout << "Tuesday" << std::endl;
            break;
        case 3:
            std::cout << "Wednesday" << std::endl;
            break;
        case 4:
        case 5:
            std::cout << "Thursday or Friday" << std::endl;
            break;
        default:
            std::cout << "Weekend" << std::endl;
    }
    
    return 0;
}

[[fallthrough]] Attribute (C++17)

Khi cố ý không dùng break, dùng [[fallthrough]] để thông báo cho compiler (và người đọc):

cpp
#include <iostream>

int main() {
    int level = 3;
    
    std::cout << "Rewards for level " << level << ":" << std::endl;
    
    switch (level) {
        case 3:
            std::cout << "  - Legendary Sword" << std::endl;
            [[fallthrough]];  // C++17: Cố ý fall-through
        case 2:
            std::cout << "  - Epic Armor" << std::endl;
            [[fallthrough]];
        case 1:
            std::cout << "  - Basic Potion" << std::endl;
            break;
        default:
            std::cout << "  - Nothing" << std::endl;
    }
    
    return 0;
}

Output (level = 3):

Rewards for level 3:
  - Legendary Sword
  - Epic Armor
  - Basic Potion

⚠️ Không có [[fallthrough]] → Compiler Warning

Nếu bạn quên break mà không có [[fallthrough]], nhiều compilers sẽ cảnh báo:

warning: unannotated fall-through between switch labels

for Loop — Vòng lặp cơ bản

C-style for loop

cpp
#include <iostream>

int main() {
    // Cú pháp: for (init; condition; increment)
    for (int i = 0; i < 5; ++i) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
    // Output: 0 1 2 3 4
    
    // Đếm ngược
    for (int i = 5; i > 0; --i) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
    // Output: 5 4 3 2 1
    
    return 0;
}

++i vs i++

cpp
// Trong vòng lặp, dùng ++i (pre-increment) thay vì i++ (post-increment)
// Lý do: ++i không tạo bản sao tạm thời → Hiệu quả hơn

for (int i = 0; i < n; ++i) { ... }  // ✅ Preferred
for (int i = 0; i < n; i++) { ... }  // ❌ Tạo bản sao không cần thiết

while và do-while

while — Kiểm tra trước

cpp
#include <iostream>

int main() {
    int count = 0;
    
    while (count < 3) {
        std::cout << "Count: " << count << std::endl;
        ++count;
    }
    
    return 0;
}

do-while — Thực hiện ít nhất 1 lần

cpp
#include <iostream>

int main() {
    int input;
    
    do {
        std::cout << "Nhập số từ 1-10: ";
        std::cin >> input;
    } while (input < 1 || input > 10);
    
    std::cout << "Bạn nhập: " << input << std::endl;
    
    return 0;
}

📌 Khi nào dùng do-while?

  • Input validation: Cần nhập ít nhất 1 lần
  • Menu loops: Hiển thị menu ít nhất 1 lần trước khi check điều kiện thoát

break và continue

cpp
#include <iostream>

int main() {
    // break: Thoát khỏi vòng lặp
    for (int i = 0; i < 10; ++i) {
        if (i == 5) {
            break;  // Dừng hoàn toàn
        }
        std::cout << i << " ";
    }
    std::cout << std::endl;  // Output: 0 1 2 3 4
    
    // continue: Bỏ qua iteration hiện tại
    for (int i = 0; i < 10; ++i) {
        if (i % 2 == 0) {
            continue;  // Bỏ qua số chẵn
        }
        std::cout << i << " ";
    }
    std::cout << std::endl;  // Output: 1 3 5 7 9
    
    return 0;
}

Nested Loops và Labels

cpp
#include <iostream>

int main() {
    // Tìm cặp (i, j) đầu tiên có tổng = 5
    bool found = false;
    
    for (int i = 0; i < 5 && !found; ++i) {
        for (int j = 0; j < 5; ++j) {
            if (i + j == 5) {
                std::cout << "Found: i=" << i << ", j=" << j << std::endl;
                found = true;
                break;  // Chỉ thoát inner loop
            }
        }
    }
    
    return 0;
}

💡 C++ không có labeled break

Không giống Java/JavaScript, C++ không có break label;. Thay vào đó:

  • Dùng flag variable (found)
  • Dùng goto (không khuyến khích)
  • Extract thành function và dùng return

Infinite Loops

cpp
#include <iostream>

int main() {
    // Cách 1: for(;;)
    // for (;;) {
    //     // infinite loop
    // }
    
    // Cách 2: while(true)
    // while (true) {
    //     // infinite loop
    // }
    
    // Ví dụ: Server main loop
    int requestCount = 0;
    while (true) {
        std::cout << "Processing request " << ++requestCount << std::endl;
        
        if (requestCount >= 3) {
            std::cout << "Shutting down..." << std::endl;
            break;
        }
    }
    
    return 0;
}

🐛 Bug Hunt Challenge

🐛 Bug Hunt

Đoạn code sau có bug gì?

cpp
#include <iostream>

int main() {
    int i = 0;
    
    while (i < 10);
    {
        std::cout << i << std::endl;
        ++i;
    }
    
    return 0;
}
💡 Gợi ý

Chú ý dấu ; sau while (i < 10).

🔍 Giải thích

Bug: Dấu ; sau while tạo một empty loop body!

cpp
while (i < 10);  // Loop body là empty statement!

Vòng while chạy mãi mãi (i luôn = 0 < 10) vì block {} phía sau không phải là body của while.

Fix:

cpp
while (i < 10) {  // Bỏ dấu ;
    std::cout << i << std::endl;
    ++i;
}

📚 Tổng kết

ConceptUsage
if with initializerC++17 — clean scope cho biến tạm
[[fallthrough]]C++17 — đánh dấu fall-through có chủ đích
++i vs i++Prefer ++i trong loops
breakThoát hoàn toàn khỏi loop
continueBỏ qua iteration hiện tại
do-whileChạy ít nhất 1 lần

➡️ Tiếp theo

Tiếp theo: Modern Loops — Range-based for loop và tại sao nó tốt hơn C-style loops.