Có thể sử dụng break
chức năng để thoát khỏi một số for
vòng lặp lồng nhau ?
Nếu vậy, làm thế nào bạn sẽ làm điều này? Bạn cũng có thể kiểm soát bao nhiêu vòng break
thoát?
Có thể sử dụng break
chức năng để thoát khỏi một số for
vòng lặp lồng nhau ?
Nếu vậy, làm thế nào bạn sẽ làm điều này? Bạn cũng có thể kiểm soát bao nhiêu vòng break
thoát?
Câu trả lời:
AFAIK, C ++ không hỗ trợ các vòng lặp đặt tên, giống như Java và các ngôn ngữ khác. Bạn có thể sử dụng một goto hoặc tạo một giá trị cờ mà bạn sử dụng. Vào cuối mỗi vòng lặp kiểm tra giá trị cờ. Nếu nó được đặt thành true, thì bạn có thể thoát ra khỏi lần lặp đó.
goto
nếu đó là lựa chọn tốt nhất.
goto
: Lập trình viên tồi và lập trình viên thực dụng. Các cựu là tự giải thích. Loại thứ hai, mà bạn sẽ phù hợp nếu bạn chọn sử dụng chúng tốt, sử dụng khái niệm được gọi là "xấu xa" khi nó là ít hơn (hai) tệ nạn. Đọc phần này để hiểu rõ hơn về một số khái niệm C ++ mà thỉnh thoảng
goto
hiếm khi là lựa chọn tốt nhất. Tại sao không đặt các vòng lặp vào chức năng của riêng họ ( inline
, nếu bạn quan tâm đến tốc độ) và return
từ điều này?
Không, đừng làm hỏng nó với a break
. Đây là thành trì cuối cùng còn lại để sử dụng goto
.
Chỉ cần thêm một câu trả lời rõ ràng bằng lambdas:
for (int i = 0; i < n1; ++i) {
[&] {
for (int j = 0; j < n2; ++j) {
for (int k = 0; k < n3; ++k) {
return; // yay we're breaking out of 2 loops here
}
}
}();
}
Tất nhiên mẫu này có một số hạn chế nhất định và rõ ràng chỉ có C ++ 11 nhưng tôi nghĩ nó khá hữu ích.
Một cách tiếp cận khác để thoát ra khỏi một vòng lặp lồng nhau là đưa cả hai vòng lặp vào một chức năng riêng biệt và return
từ chức năng đó khi bạn muốn thoát.
Tất nhiên, điều này đưa ra lập luận khác về việc bạn có nên dứt khoát return
từ một chức năng ở bất kỳ nơi nào khác ngoài cuối không.
continue_processing
) điều khiển việc thực thi các khối mã nằm sâu hơn trong hàm.
phá vỡ sẽ chỉ thoát khỏi vòng lặp trong cùng có chứa nó.
Bạn có thể sử dụng goto để thoát ra khỏi bất kỳ số vòng lặp.
Tất nhiên goto thường được coi là có hại .
Có đúng không khi sử dụng chức năng ngắt [...]?
Sử dụng break và goto có thể làm cho khó khăn hơn để suy luận về tính đúng đắn của một chương trình. Xem ở đây để thảo luận về điều này: Dijkstra không điên .
break
hoặc return
.
break
và return
có lợi thế hơn goto
là bạn không cần phải tìm nhãn để tìm nơi họ đến. Vâng, bên dưới họ là một số loại goto
, nhưng một loại rất hạn chế. Chúng dễ dàng giải mã hơn rất nhiều bởi bộ não phù hợp với lập trình viên so với bộ não không bị hạn chế goto
. Vì vậy, IMO họ thích hợp hơn.
goto
.
Mặc dù câu trả lời này đã được trình bày, tôi nghĩ rằng một cách tiếp cận tốt là làm như sau:
for(unsigned int z = 0; z < z_max; z++)
{
bool gotoMainLoop = false;
for(unsigned int y = 0; y < y_max && !gotoMainLoop; y++)
{
for(unsigned int x = 0; x < x_max && !gotoMainLoop; x++)
{
//do your stuff
if(condition)
gotoMainLoop = true;
}
}
}
gotoMainLoop
được kiểm tra mỗi chu kỳ
goto
làm cho lõi dễ đọc hơn và hoạt động tốt hơn.
Còn cái này thì sao?
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
//Some statement
if (condition)
{
j=50;
k=50;
}
}
}
}
Một ví dụ mã sử dụng goto
và nhãn để thoát ra khỏi vòng lặp lồng nhau:
for (;;)
for (;;)
goto theEnd;
theEnd:
Một cách hay để thoát ra khỏi một số vòng lặp lồng nhau là cấu trúc lại mã của bạn thành một hàm:
void foo()
{
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
// If condition is true
return;
}
}
}
}
goto có thể rất hữu ích cho việc phá vỡ các vòng lặp lồng nhau
for (i = 0; i < 1000; i++) {
for (j = 0; j < 1000; j++) {
for (k = 0; k < 1000; k++) {
for (l = 0; l < 1000; l++){
....
if (condition)
goto break_me_here;
....
}
}
}
}
break_me_here:
// Statements to be executed after code breaks at if condition
Tôi nghĩ rằng một goto
là hợp lệ trong trường hợp này:
Để mô phỏng a break
/ continue
, bạn muốn:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
goto theEnd;
}
}
}
theEnd:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
i++;
goto multiCont;
}
}
multiCont:
}
i
. Do đó i++
trước goto
Các ngôn ngữ khác như PHP chấp nhận một tham số cho break (tức là break 2;) để chỉ định mức độ vòng lặp lồng nhau mà bạn muốn thoát ra, tuy nhiên C ++ thì không. Bạn sẽ phải xử lý nó bằng cách sử dụng boolean mà bạn đặt thành false trước vòng lặp, đặt thành true trong vòng lặp nếu bạn muốn ngắt, cộng với ngắt điều kiện sau vòng lặp lồng nhau, kiểm tra xem boolean có được đặt thành true không và phá vỡ nếu có.
Tôi biết đây là bài cũ. Nhưng tôi sẽ đề nghị một câu trả lời hợp lý và đơn giản hơn.
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < conditionj; j++)
{
for(unsigned int k=0; k< conditionk ; k++)
{
// If condition is true
j= conditionj;
break;
}
}
}
j = conditionj
sẽ không hoạt động nếu bạn có một vị từ phức tạp thay vì j < conditionj
.
Phá vỡ bất kỳ số vòng lặp chỉ bằng một bool
biến xem bên dưới:
bool check = true;
for (unsigned int i = 0; i < 50; i++)
{
for (unsigned int j = 0; j < 50; j++)
{
for (unsigned int k = 0; k < 50; k++)
{
//Some statement
if (condition)
{
check = false;
break;
}
}
if (!check)
{
break;
}
}
if (!check)
{
break;
}
}
Trong mã này, break;
tất cả các vòng lặp.
Tôi không chắc nó có đáng hay không, nhưng bạn có thể mô phỏng các vòng lặp có tên của Java bằng một vài macro đơn giản:
#define LOOP_NAME(name) \
if ([[maybe_unused]] constexpr bool _namedloop_InvalidBreakOrContinue = false) \
{ \
[[maybe_unused]] CAT(_namedloop_break_,name): break; \
[[maybe_unused]] CAT(_namedloop_continue_,name): continue; \
} \
else
#define BREAK(name) goto CAT(_namedloop_break_,name)
#define CONTINUE(name) goto CAT(_namedloop_continue_,name)
#define CAT(x,y) CAT_(x,y)
#define CAT_(x,y) x##y
Ví dụ sử dụng:
#include <iostream>
int main()
{
// Prints:
// 0 0
// 0 1
// 0 2
// 1 0
// 1 1
for (int i = 0; i < 3; i++) LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << i << ' ' << j << '\n';
if (i == 1 && j == 1)
BREAK(foo);
}
}
}
Một vi dụ khac:
#include <iostream>
int main()
{
// Prints:
// 0
// 1
// 0
// 1
// 0
// 1
int count = 3;
do LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << ' ' << j << '\n';
if (j == 1)
CONTINUE(foo);
}
}
while(count-- > 1);
}
Bạn có thể sử dụng thử ... bắt.
try {
for(int i=0; i<10; ++i) {
for(int j=0; j<10; ++j) {
if(i*j == 42)
throw 0; // this is something like "break 2"
}
}
}
catch(int e) {} // just do nothing
// just continue with other code
Nếu bạn phải thoát ra khỏi một số vòng lặp cùng một lúc, thì đó thường là một ngoại lệ.
Việc thoát ra khỏi vòng lặp for là một điều kỳ lạ đối với tôi, vì ngữ nghĩa của vòng lặp for thường chỉ ra rằng nó sẽ thực thi một số lần xác định. Tuy nhiên, nó không tệ trong mọi trường hợp; nếu bạn đang tìm kiếm thứ gì đó trong bộ sưu tập và muốn phá vỡ sau khi bạn tìm thấy nó, điều đó hữu ích. Tuy nhiên, việc thoát ra khỏi các vòng lặp lồng nhau là không thể có trong C ++; đó là trong các ngôn ngữ khác thông qua việc sử dụng một dấu ngắt. Bạn có thể sử dụng nhãn và goto, nhưng điều đó có thể khiến bạn ợ nóng vào ban đêm ..? Có vẻ như là lựa chọn tốt nhất mặc dù.