continue
Sau bài này bạn sẽ làm được
- Dùng continue để bỏ qua các phần tử không hợp lệ
- Giải thích bẫy continue làm mất bước tăng biến trong while
- Phân biệt rõ break với continue
continue bỏ qua phần còn lại của lượt lặp hiện tại và nhảy sang lượt tiếp theo. Nó rất tiện khi lọc dữ liệu, nhưng có một cạm bẫy làm vòng lặp while chạy vô hạn mà nhiều người mất khá lâu mới tìm ra.
#Ý nghĩa
for (int i = 1; i <= 10; ++i) {
if (i % 2 == 0) {
continue; /* bỏ qua số chẵn */
}
printf("%d ", i);
}
/* In ra: 1 3 5 7 9 */Khi gặp continue, luồng nhảy thẳng tới phần cập nhật của vòng lặp, tức là ++i, rồi kiểm tra điều kiện và bắt đầu lượt mới. Mọi câu lệnh phía dưới trong thân vòng lặp bị bỏ qua.
Cách viết này tương đương với việc bọc phần thân trong một if, nhưng nó giữ mã ở mức thụt lề thấp, đúng tinh thần guard clause đã học ở Bài 5.4.
for (size_t i = 0; i < n; ++i) {
if (a[i] >= 0) {
if (a[i] < 100) {
if (a[i] % 2 == 0) {
xu_ly(a[i]);
}
}
}
}for (size_t i = 0; i < n; ++i) {
if (a[i] < 0) continue;
if (a[i] >= 100) continue;
if (a[i] % 2 != 0) continue;
xu_ly(a[i]);
}#Bẫy trong while
Đây là nội dung quan trọng nhất của bài. Với for, phần cập nhật nằm ở đầu vòng lặp nên continue vẫn chạy qua nó. Với while, phần cập nhật nằm trong thân, nên continue bỏ qua luôn.
int i = 0;
while (i < 10) {
if (i % 2 == 0) {
continue; /* i KHÔNG BAO GIỜ tăng */
}
printf("%d ", i);
i++;
}
/* Vòng lặp vô hạn.
Khi i bằng 0, continue nhảy về đầu,
i vẫn bằng 0, lại continue, mãi mãi. */int i = 0;
while (i < 10) {
int hien_tai = i;
i++; /* tăng TRƯỚC khi có thể continue */
if (hien_tai % 2 == 0) {
continue;
}
printf("%d ", hien_tai);
}#So sánh với break
| break | continue | |
|---|---|---|
| Tác dụng | Thoát hẳn vòng lặp | Sang lượt lặp tiếp theo |
| Dùng được trong switch | Có | Không |
| Số tầng thoát | Một tầng gần nhất | Một tầng gần nhất |
| Trong for | Không chạy phần cập nhật | CÓ chạy phần cập nhật |
| Trong while | Thoát ngay | Bỏ qua mọi thứ còn lại, kể cả phần tăng biến |
for (int i = 0; i < 5; ++i) {
if (i == 2) {
continue;
}
printf("%d ", i);
}
printf("\n");
/* In ra: 0 1 3 4 (bỏ qua 2, vẫn chạy hết) */
for (int i = 0; i < 5; ++i) {
if (i == 2) {
break;
}
printf("%d ", i);
}
printf("\n");
/* In ra: 0 1 (dừng hẳn tại 2) */#Khi nào nên dùng
continue hữu ích nhất khi bạn muốn lọc bỏ một số phần tử và phần xử lý chính khá dài.
char dong[256];
size_t so_dong = 0, so_bo_qua = 0;
while (fgets(dong, sizeof dong, f)) {
++so_dong;
dong[strcspn(dong, "\n")] = '\0';
if (dong[0] == '\0') {
++so_bo_qua;
continue; /* bỏ qua dòng trống */
}
if (dong[0] == '#') {
++so_bo_qua;
continue; /* bỏ qua dòng chú thích */
}
/* Phần xử lý chính, có thể dài vài chục dòng,
và nó không bị thụt lề thêm tầng nào. */
phan_tich_dong(dong);
}Tự làm thử
- In các số từ 1 tới 50 nhưng bỏ qua những số chia hết cho 3 hoặc chia hết cho 5.
- Tái hiện vòng lặp vô hạn bằng
continuetrongwhile, rồi sửa bằng hai cách khác nhau. - Viết chương trình đọc file, đếm số dòng có nội dung, bỏ qua dòng trống và dòng bắt đầu bằng dấu thăng.
- Tính trung bình cộng của các số dương trong mảng, dùng
continueđể bỏ qua số âm và số 0. - Viết một vòng lặp có cả
breakvàcontinue, giải thích luồng chạy bằng lời. - Đặt
continuetrongswitchnằm trongwhile, quan sát nó tác động lên vòng lặp chứ không phải switch.
Trình chấm điểm tự động sẽ được bổ sung ở giai đoạn sau. Hiện tại bạn tự chạy thử trên máy.
Tóm tắt
- continue bỏ qua phần còn lại của lượt lặp và sang lượt tiếp theo.
- Trong
for, phần cập nhật vẫn chạy. Trongwhile, nó bị bỏ qua luôn. - Đây là nguyên nhân vòng lặp while có continue dễ chạy vô hạn.
- Khi có biến đếm, dùng for để phần cập nhật không bao giờ bị bỏ sót.
continuetrongswitchtác động lên vòng lặp bao ngoài, không phải lên switch.- Dùng continue khi cần lọc bỏ và phần xử lý chính dài. Thân ngắn thì if thuận rõ hơn.