L3. Cấu Trúc Điều Khiển trong C++

Phần 1: Cấu Trúc Rẽ Nhánh

1. Khái Niệm Câu Lệnh và Khối Lệnh

Câu lệnh (Statement):

  • Xác định một công việc mà chương trình phải thực hiện
  • Các câu lệnh được ngăn cách bằng dấu ;
int n;
cout << "Nhap vao so nguyen n = ";
cin >> n;
cout << "So n = " << n;

Khối lệnh (Block):

  • Dãy các câu lệnh được bao bởi cặp dấu { }
{
    int n;
    cout << "Nhap vao so nguyen n = ";
    cin >> n;
    cout << "So n = " << n;
}

2. Phạm Vi Hoạt Động Của Biến

Tất cả các biến phải được khai báo trước khi sử dụng.

Biến cục bộ (Local variable):

  • Được khai báo trong một khối { }
  • Chỉ có tác dụng trong khối đó
  • Bị xóa khi ra khỏi khối

Biến toàn cục (Global variable):

  • Được khai báo bên ngoài các khối
  • Có phạm vi toàn chương trình
  • Chỉ bị xóa khi chương trình kết thúc
#include <iostream>
using namespace std;

int x = 3;  // Biến toàn cục

void main() {
    cout << x;      // 3
    int x = 5;      // Biến cục bộ che biến toàn cục
    {   
        cout << x;  // 5
        int x = 7;  // Biến cục bộ trong khối con
        cout << x;  // 7
        cout << ::x; // 3 (truy cập biến toàn cục)
    }
    cout << x;      // 5
    cout << ::x;    // 3
}

3. Giới Thiệu Cấu Trúc Điều Khiển

graph TD A[Cấu trúc điều khiển] --> B[Cấu trúc tuần tự] A --> C[Cấu trúc rẽ nhánh] A --> D[Cấu trúc lặp] C --> E[if, if-else] C --> F[switch-case] D --> G[for] D --> H[while] D --> I[do-while]

Biểu diễn sơ đồ:

graph LR A[Cấu trúc tuần tự] --> B[S1] --> C[S2] --> D[S3]
graph TD A[Cấu trúc rẽ nhánh] --> B{Điều kiện C} B -->|Đúng| C[S1] B -->|Sai| D[S2]
graph TD A[Cấu trúc lặp] --> B{Điều kiện C} B -->|Đúng| C[S1] C --> B B -->|Sai| D[Kết thúc]

4. Cấu Trúc Rẽ Nhánh if

Cú pháp:

if (biểu_thức_điều_kiện) 
    Lệnh_A;

Lưu đồ:

graph TD A{btđk ≠ 0} -->|Đúng| B[Lệnh A] A -->|Sai| C[Tiếp tục] B --> C

Ví dụ:

int a = 10, b = 15, c = 8;
int m;

// Cách 1: Sử dụng if đơn
m = a;
if (b < m) m = b;
if (c < m) m = c;
cout << "Gia tri be nhat m = " << m;

5. Cấu Trúc Rẽ Nhánh if-else

Cú pháp:

if (biểu_thức_điều_kiện) 
    Lệnh_1;
else 
    Lệnh_2;

Lưu đồ:

graph TD A{btđk ≠ 0} -->|Đúng| B[Lệnh 1] A -->|Sai| C[Lệnh 2] B --> D[Tiếp tục] C --> D

Ví dụ:

// Cách 2: Sử dụng if-else lồng nhau
int a = 10, b = 15, c = 8;
int m;

if (a < b)
    if (a < c) 
        m = a;
    else 
        m = c;
else
    if (b < c) 
        m = b;
    else 
        m = c;
        
cout << "Gia tri be nhat m = " << m;
// Cách 3: Sử dụng toán tử điều kiện
int a = 10, b = 15, c = 8;
int m = (a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c);
cout << "Gia tri be nhat m = " << m;

6. Cấu Trúc Rẽ Nhánh switch-case

Cú pháp:

switch (biểu_thức_điều_kiện) {
    case hằng_số_1: 
        câu_lệnh_1;
        break;
    case hằng_số_2: 
        câu_lệnh_2;
        break;
    ...
    default: 
        câu_lệnh_default;
}

Ví dụ 1:

#include <iostream>
using namespace std;

void main() {
    char ch;
    cout << "Nhap gia tri ch = ";
    cin >> ch;
    
    switch (ch) {
        case 'a': 
            cout << "Ki tu a da duoc nhap"; 
            break;
        case 'b': 
            cout << "Ki tu b da duoc nhap"; 
            break;
        default: 
            cout << "Ki tu khac a va b da duoc nhap";
    }
}

Ví dụ 2:

#include <iostream>
using namespace std;

void main() {
    int a;
    printf("Nhap a: ");
    scanf("%d", &a);
    
    switch (a) {
        case 1: 
            printf("Mot"); 
            break;
        case 2: 
            printf("Hai"); 
            break;
        case 3: 
            printf("Ba"); 
            break;
        default: 
            printf("Ko biet doc");
    }
}

Bài Tập Bắt Buộc - Rẽ Nhánh


Phần 2: Cấu Trúc Lặp

1. Đặt Vấn Đề

Vấn đề:

  • Xuất các số từ 1 đến 10 → 10 câu lệnh cout
  • Xuất các số từ 1 đến 1000 → 1000 câu lệnh cout?

Giải pháp: Sử dụng cấu trúc lặp - lặp lại một hành động trong khi còn thỏa điều kiện.

3 loại vòng lặp:

  • for
  • while
  • do...while

2. Cấu Trúc Lặp for

Cú pháp:

for ([ForInit]; [ForExpression]; [PostExpression])
    [Action];

Các thành phần:

  • ForInit: Khởi tạo biến đếm
  • ForExpression: Điều kiện lặp
  • PostExpression: Cập nhật biến đếm
  • Action: Câu lệnh hoặc khối lệnh thực hiện

Ví dụ:

// In ra các số từ 0 đến 2
for (int i = 0; i < 3; ++i) {
    cout << "i = " << i << endl;
}
cout << "all done" << endl;

Output:

i = 0
i = 1
i = 2
all done

Truy vết thực thi:

graph TD A[i = 0] --> B{i < 3?} B -->|true| C[cout i] C --> D[++i] D --> B B -->|false| E[all done]
BướciĐiều kiệnHành độngOutput
100 < 3 = truecouti = 0
211 < 3 = truecouti = 1
322 < 3 = truecouti = 2
433 < 3 = false-all done

3. Cấu Trúc Lặp while

Cú pháp:

while (Expression) {
    Action;
}

Thực thi:

  1. Kiểm tra Expression
  2. Nếu true: thực thi Action, quay lại bước 1
  3. Nếu false: kết thúc vòng lặp

Lưu đồ:

graph TD A{Expression} -->|true| B[Action] B --> A A -->|false| C[Kết thúc]

Ví dụ: Tính trung bình

int n = 4;
int count = 0;
double sum = 0;

while (count < n) {
    double value;
    cin >> value;
    sum += value;
    count++; 
}

double average = sum / count;
cout << "Average: " << average << endl;

Nhập: 1 5 3 1

Truy vết:

BướccountsumvalueĐiều kiệnHành động
100-0 < 4Nhập value
2001-sum += 1
31111 < 4Nhập value
4115-sum += 5
52652 < 4Nhập value
6263-sum += 3
73933 < 4Nhập value
8391-sum += 1
941014 < 4 = falseKết thúc

Average: 10 / 4 = 2.5

4. So Sánh for và while

Cấu trúc for có thể viết lại bằng while:

// Vòng for
for (ForInit; ForExpression; PostExpression) {
    Action;
}

// Tương đương với while
{
    ForInit;
    while (ForExpression) {
        Action;
        PostExpression;
    }
}

5. Cấu Trúc Lặp do-while

Cú pháp:

do {
    Action;
} while (Expression);

Đặc điểm:

  • Thực thi Action ít nhất một lần
  • Kiểm tra điều kiện sau khi thực thi

Lưu đồ:

graph TD A[Action] --> B{Expression} B -->|true| A B -->|false| C[Kết thúc]

Ví dụ:

char Reply;
do {
    cout << "Selection (y, n): ";
    if (cin >> Reply)
        Reply = tolower(Reply);
    else
        Reply = 'n';
} while ((Reply != 'y') && (Reply != 'n'));

6. Câu Lệnh break và continue

break:

  • Kết thúc vòng lặp ngay lập tức
  • Thoát ra khỏi vòng lặp

continue:

  • Bỏ qua lần lặp hiện tại
  • Tiếp tục với lần lặp tiếp theo
// Ví dụ break
for (int i = 0; i < 10; i++) {
    if (i % 2 == 0)
        break;  // Dừng ngay khi gặp số chẵn
    printf("%d\n", i);
}
// Output: (không in gì vì i=0 là số chẵn)

// Ví dụ continue
for (int i = 0; i < 10; i++) {
    if (i % 2 == 0)
        continue;  // Bỏ qua số chẵn
    printf("%d\n", i);
}
// Output: 1 3 5 7 9

Bài Tập Bắt Buộc - Vòng Lặp