Bỏ qua để đến nội dung

Break và continue trong Rust

break và continue cho phép bạn ngắt vòng lặp sớm thay vì lúc nào cũng phải chạy đến cuối. Chúng hoạt động giống nhau trong cả ba loại vòng lặp: loop, while và for.

break dừng vòng lặp ngay lập tức, và chương trình nhảy tới dòng code nằm ngay sau vòng lặp:

fn main() {
for i in 1..=10 {
if i == 5 {
break;
}
println!("{i}");
}
}

Kết quả:

1
2
3
4
▶ Tự chạy thử

Dù range đi tới 10, vòng lặp dừng ngay khi i chạm 5.

continue bỏ qua phần còn lại của lượt hiện tại và nhảy thẳng sang lượt tiếp theo, chứ không dừng hẳn vòng lặp:

fn main() {
for i in 1..=10 {
if i % 2 == 0 {
continue; // bỏ qua số chẵn
}
println!("{i}");
}
}

Kết quả:

1
3
5
7
9
▶ Tự chạy thử

Mọi số chẵn đều bị bỏ qua — continue được kích hoạt, và vòng lặp chuyển thẳng sang giá trị tiếp theo của i mà không chạy println!.

Khi bạn lồng một vòng lặp vào trong vòng lặp khác, break/continue thông thường chỉ tác động lên vòng lặp trong cùng. Nếu bạn cần thoát khỏi vòng lặp ngoài từ bên trong vòng lặp lồng, hãy đặt cho vòng lặp ngoài một nhãn (label, viết dạng 'name:):

fn main() {
'outer: for x in 1..=3 {
for y in 1..=3 {
if x * y > 4 {
break 'outer;
}
println!("{x} x {y} = {}", x * y);
}
}
}

Kết quả:

1 x 1 = 1
1 x 2 = 2
1 x 3 = 3
2 x 1 = 2
2 x 2 = 4
▶ Tự chạy thử

Nếu không có nhãn, break chỉ dừng vòng lặp y bên trong, còn x vẫn tiếp tục. break 'outer; dừng cả hai cùng lúc. continue 'outer; cũng hoạt động tương tự, nếu bạn muốn nhảy sang lượt tiếp theo của vòng lặp ngoài thay vì dừng hẳn.

Trong vòng lặp for, giá trị tiếp theo tự động đến từ range, nên continue luôn an toàn. Vòng lặp while thì khác: bạn tự cập nhật bộ đếm, thường là ở cuối thân vòng lặp. Nếu continue nhảy qua lệnh cập nhật đó, bộ đếm không bao giờ thay đổi và vòng lặp chạy mãi mãi.

Phiên bản này cố bỏ qua số 3, nhưng nó bị treo. Đừng chạy nó:

fn main() {
let mut i = 0;
while i < 5 {
if i == 3 {
continue; // ❌ nhảy lên lại mà không đổi i
}
println!("{i}");
i += 1;
}
}

Khi i bằng 3, continue quay lại điều kiện. i vẫn là 3, nên continue lại được kích hoạt, rồi lại nữa, mãi mãi. Cách sửa là cập nhật bộ đếm trước mọi thứ có thể gọi continue:

fn main() {
let mut i = 0;
while i < 5 {
i += 1; // cập nhật trước, để continue không thể bỏ qua nó
if i == 3 {
continue;
}
println!("{i}");
}
}

Kết quả:

1
2
4
5
▶ Tự chạy thử

Đưa i += 1 lên đầu làm các số dịch đi một: vòng lặp này in từ 1 đến 5 thay vì từ 0 đến 4, nên hãy chỉnh điểm bắt đầu hoặc điều kiện nếu bạn cần khoảng cũ. Tốt hơn nữa, nếu bạn chỉ đang đếm, hãy dùng vòng lặp for qua một range và vấn đề này không thể xảy ra.

In các số từ 1 đến 10, nhưng bỏ qua mọi bội số của 3. Gợi ý: một số là bội số của 3 khi n % 3 == 0. Dùng continue để bỏ qua nó.

Xem lời giải
fn main() {
for n in 1..=10 {
if n % 3 == 0 {
continue;
}
println!("{n}");
}
}

Kết quả:

1
2
4
5
7
8
10
▶ Tự chạy thử

Dùng hai vòng lặp for lồng nhau, x và y, cả hai đều chạy qua 1..=9. Tìm cặp đầu tiên mà x * y == 24, in nó ra và dừng cả hai vòng lặp. Gợi ý: đặt nhãn cho vòng lặp ngoài và dùng break 'outer;.

Xem lời giải
fn main() {
'outer: for x in 1..=9 {
for y in 1..=9 {
if x * y == 24 {
println!("Tìm thấy: {x} x {y} = 24");
break 'outer;
}
}
}
println!("Đã tìm xong");
}

Kết quả:

Tìm thấy: 3 x 8 = 24
Đã tìm xong
▶ Tự chạy thử

Thử đổi break 'outer; thành break; thông thường. Lúc này chỉ vòng lặp trong dừng lại, nên việc tìm kiếm vẫn tiếp tục và còn in ra 4 x 6, 6 x 4 và 8 x 3.

  • break thoát khỏi vòng lặp ngay lập tức.
  • continue bỏ qua phần còn lại của lượt hiện tại và chuyển sang lượt tiếp theo.
  • Một nhãn ('outer:) cho phép break/continue nhắm tới vòng lặp ngoài từ bên trong vòng lặp lồng.
  • Trong vòng lặp while, hãy cập nhật bộ đếm trước mọi continue, nếu không vòng lặp có thể kẹt mãi mãi.

Kiểm tra nhanh

1. continue làm gì bên trong một vòng lặp?

2. Viết nhãn cho vòng lặp thế nào để break có thể nhắm tới nó từ một vòng lặp lồng?

3. Một vòng lặp while có continue không bao giờ kết thúc. Nguyên nhân khả dĩ nhất là gì?

Điểm: 0 / 3