C++ Control Flow
🔁 Vòng lặp for, while và do-while
Vòng lặp giúp chương trình thực hiện một công việc nhiều lần mà không lặp lại code. Bài học trình bày cơ chế từng bước, biến đếm, điều kiện dừng, biến tích lũy, break/continue, vòng lặp lồng nhau và lỗi vòng lặp vô hạn.
forThường dùng khi biết số lần
whileLặp khi điều kiện còn đúng
do-whileChạy ít nhất một lần
O(n)Một lượt qua n phần tử
🎯 Mục tiêu bài học
Cần hiểu
- Bốn bước: khởi tạo, kiểm tra, thực hiện, cập nhật.
- Khác nhau giữa
for,while,do-while. - Biến đếm, biến tích lũy.
break,continue.- Độ phức tạp vòng lặp.
Cần làm được
- In dãy theo quy luật.
- Tính tổng, tích, đếm.
- Xử lý đến điều kiện dừng.
- Viết vòng lặp lồng nhau.
- Phát hiện vòng lặp vô hạn.
1. Đặt vấn đề
Bài toán mở đầu.
Nhập số nguyên dương n. Hãy in các số từ 1 đến n và tính tổng của chúng.
Nhập số nguyên dương n. Hãy in các số từ 1 đến n và tính tổng của chúng.
1.1. Nếu không dùng vòng lặp
cout << 1 << ' ';
cout << 2 << ' ';
cout << 3 << ' ';
// Phải viết tiếp đến nKhi n thay đổi hoặc rất lớn, không thể viết sẵn từng câu lệnh.
1.2. Tìm phần giống nhau
- Công việc lặp lại: in i và cộng i vào tổng.
- Giá trị thay đổi: i tăng từ 1 đến n.
- Điều kiện dừng: i vượt quá n.
Khởi tạo i → kiểm tra → chạy thân → cập nhật i → quay lại kiểm tra
Kết luận: Vòng lặp mô tả một quy trình lặp, không chỉ là cách viết code ngắn hơn.
2. Vòng lặp for
for (khởi_tạo; điều_kiện; cập_nhật) { thân_vòng_lặp }
Khởi tạo
int i = 1Điều kiện
i <= nCập nhật
i++2.1. Mô phỏng từng bước
i?
i ≤ n?
Hành động?
Cập nhật?
Output
for (int i = 1;
i <= n;
i++) {
cout << i << ' ';
}
3. Vòng lặp while
while (điều_kiện) { thân_vòng_lặp; cập_nhật; }
Khi nào dùng?
- Chưa biết trước số lần lặp.
- Lặp đến dữ liệu dừng.
- Biến đổi một số cho đến 0.
Ví dụ
while (n > 0) {
digitSum += n % 10;
n /= 10;
}3.1. Mô phỏng tổng chữ số
n?
n % 10?
sum0
n > 0?
4. Vòng lặp do-while
do {
// công việc
} while (condition);Điều kiện được kiểm tra sau thân vòng lặp, nên thân chạy ít nhất một lần.
Ví dụ phù hợp: hiển thị menu ít nhất một lần rồi hỏi có tiếp tục hay không.
5. Biến đếm và biến tích lũy
Đếm
count++;Tổng
sum += x;Tích
product *= x;5.1. Mô phỏng tổng 1 đến n
Bất biến: Sau khi xử lý xong i,
sum bằng tổng từ 1 đến i.6. break và continue
break
Dừng ngay vòng lặp gần nhất.
if (x == target) break;continue
Bỏ phần còn lại của lượt hiện tại.
if (x < 0) continue;Trong while: nếu
continue xảy ra trước câu lệnh cập nhật, biến điều khiển có thể không đổi và gây vòng lặp vô hạn.7. Vòng lặp lồng nhau
Vòng trong chạy đầy đủ cho mỗi lượt của vòng ngoài.
Vòng ngoài n lần, vòng trong m lần mỗi lượt → O(nm)
8. Phân tích thuật toán
| Mẫu | Số lượt | Độ phức tạp | Ví dụ |
|---|---|---|---|
for(i=0;i | n | O(n) | Duyệt mảng. |
for(i=1;i<=n;i*=2) | ≈ log₂n | O(log n) | Nhân đôi biến. |
| Hai vòng liên tiếp | n+n | O(n) | Hai lượt duyệt. |
| Hai vòng lồng n×n | n² | O(n²) | Duyệt mọi cặp. |
| while chia n cho 10 | Số chữ số | O(log₁₀n) | Xử lý chữ số. |
9. Code mẫu
#include
using namespace std;
int main(){
int n; cin >> n;
for(int i=1;i<=n;i++) cout << i << ' ';
} long long n, sum = 0;
cin >> n;
for(long long i=1;i<=n;i++) sum += i;
cout << sum;long long n;
cin >> n;
n = llabs(n);
int digitSum = 0;
do {
digitSum += n % 10;
n /= 10;
} while(n > 0);
cout << digitSum;for(int i=0;i> x;
if(x < 0) continue;
if(x == target) { found = true; break; }
} for(int i=1;i<=rows;i++) {
for(int j=1;j<=columns;j++) {
cout << '(' << i << ',' << j << ") ";
}
cout << '
';
}10. Giải thích code
10.1. Vì sao for có thể không chạy lần nào?
Điều kiện được kiểm tra trước thân vòng lặp. Nếu sai ngay từ đầu, thân không chạy.
10.2. Vì sao tổng khởi tạo bằng 0?
0 là phần tử trung hòa của phép cộng.
10.3. Vì sao tích khởi tạo bằng 1?
Nếu bằng 0 thì mọi lần nhân sau vẫn bằng 0.
10.4. Vì sao tổng chữ số dùng do-while?
Với n=0, vẫn cần xử lý một chữ số 0.
10.5. For có nhanh hơn while không?
Không. Hiệu năng phụ thuộc số lượt và công việc bên trong, không phụ thuộc tên vòng lặp.
11. Lỗi thường gặp
- Nhầm
ivới i<=n. - Quên cập nhật biến trong while.
- Đặt dấu
;sau for/while. - Khởi tạo tổng hoặc tích sai.
- Dùng int cho tổng lớn.
- Continue làm bỏ qua cập nhật.
- Cho rằng hai vòng liên tiếp là O(n²).
- Vòng lặp lồng quá lớn gây TLE.
12. Quiz và bài tập
Câu 1. Vòng nào chạy thân ít nhất một lần?
Câu 2.
for(int i=0;i chạy bao nhiêu lượt? Câu 3. Hai vòng O(n) liên tiếp có tổng độ phức tạp?
📘 Cơ bản
- In 1..n và n..1.
- Tổng số chẵn ≤n.
- Đếm chữ số.
📗 Trung bình
- Tính n!.
- Kiểm tra số nguyên tố.
- UCLN bằng Euclid.
📙 Nâng cao
- Bảng cửu chương.
- Vẽ hình.
- Đếm ước O(√n).
🐣 Học tiếp
- Mảng.
- Chuỗi.
- Độ phức tạp.
💳 Quét mã ủng hộ tuỳ tâm nhé!