Reputation: 2983
If I use a break
statement, it will only break inner loop and I need to use some flag to break the outer loop. But if there are many nested loops, the code will not look good.
Is there any other way to break all of the loops? (Please don't use goto stmt
.)
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 1000; j++) {
if (condition) {
// both of the loops need to break and control will go to stmt2
}
}
}
stmt2
Upvotes: 148
Views: 356243
Reputation: 68
You can use a flag, a rookie mistake is to exit a single loop, remember the double break, another practice that is not recommended but necessary in very high performance processes is to use goto and my favorite, a function with a return.
#include <iostream>
// Dont clone vars, use references, for performance
int calc(int &row, int &cols, int &max) {
int sum = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < cols; j++) {
sum += i + j;
if (sum > max) {
return sum;
}
}
}
return sum;
}
int main() {
int rows = 1000;
int cols = 1000;
int max = 1000;
int result = calc(rows, cols, max);
std::cout << "Result: " << result;
return 0;
}
Alternative version, a little more modular:
#include <iostream>
// Dont clone vars, use references, for performance
void calc(int &row, int &cols, int &max, int &result) {
int sum = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < cols; j++) {
sum += i + j;
if (sum > max) {
result = sum;
return;
}
}
}
result = sum;
}
int main() {
int rows = 1000;
int cols = 1000;
int max = 1000;
int result = 0;
calc(rows, cols, max, result);
std::cout << "Result: " << result;
return 0;
}
GOTO example, completely discouraged today:
#include <iostream>
int main() {
int rows = 1000;
int cols = 1000;
int max = 1000;
int result = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
result += i + j;
if (result > max) {
goto end;
}
}
}
end:
std::cout << "Result: " << result;
return 0;
}
Another example:
#include <iostream>
int main() {
int rows = 1000;
int cols = 1000;
int max = 1000;
int result = 0;
bool done = false;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
result += i + j;
if (result > max) {
done = true;
break;
}
}
if (done) {
break;
}
}
std::cout << "Result: " << result;
return 0;
}
Upvotes: -2
Reputation: 8204
I note that the question is simply, "Is there any other way to break all of the loops?" I don't see any qualification but that it not be goto
, in particular the OP didn't ask for a good way. So, how about we longjmp
out of the inner loop? :-)
#include <stdio.h>
#include <setjmp.h>
int main(int argc, char* argv[]) {
int counter = 0;
jmp_buf look_ma_no_goto;
if (!setjmp(look_ma_no_goto)) {
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 1000; j++) {
if (i == 500 && j == 500) {
longjmp(look_ma_no_goto, 1);
}
counter++;
}
}
}
printf("counter=%d\n", counter);
}
The setjmp
function returns twice. The first time, it returns 0 and the program executes the nested for loops. Then when the both i
and j
are 500, it executes longjmp
, which causes setjmp
to return again with the value 1, skipping over the loop.
Not only will longjmp
get you out of nested loops, it works with nested functions too!
Upvotes: 1
Reputation: 28837
A different approach is to refactor the code from two for loops into a for loop and one manual loop. That way the break in the manual loop applies to the outer loop. I used this once in a Gauss-Jordan Elimination which required three nested loops to process.
for (int i = 0; i < 1000; i++)
{
int j = 0;
MANUAL_LOOP:;
if (j < 1000)
{
if (condition)
{
break;
}
j++;
goto MANUAL_LOOP;
}
}
Upvotes: 0
Reputation: 2633
I think goto
will solve the problem
for(int i = 0; i < 1000; i++) {
for(int j = 0; j < 1000; j++) {
if (condition) {
goto end;
}
}
}
end:
stmt2
Upvotes: 28
Reputation: 73608
No, don't spoil the fun with a break
. This is the last remaining valid use of goto
;)
If not this then you could use flags to break out of deep nested loops.
Another approach to breaking out of a nested loop is to factor out both loops into a separate function, and return from that function when you want to exit.
Summarized - to break out of nested loops:
goto
Couldn't resist including xkcd here :)
Goto's are considered harmful but as many people in the comments suggest it need not be. If used judiciously it can be a great tool. Anything used in moderation is fun.
Upvotes: 289
Reputation: 2853
Caution: This answer shows a truly obscure construction.
If you are using GCC, check out this library.
Like in PHP, break
can accept the number of nested loops you want to exit.
You can write something like this:
for(int i = 0; i < 1000; i++) {
for(int j = 0; j < 1000; j++) {
if(condition) {
// break two nested enclosing loops
break(2);
}
}
}
Upvotes: 8
Reputation: 41
for(int i = 0; i < 1000; i++) {
for(int j = 0; j < 1000; i++) {
if(condition) {
func(para1, para2...);
return;
}
}
}
func(para1, para2...) {
stmt2;
}
Upvotes: -3
Reputation: 5444
bool stop = false;
for (int i = 0; (i < 1000) && !stop; i++)
{
for (int j = 0; (j < 1000) && !stop; j++)
{
if (condition)
stop = true;
}
}
Upvotes: 49
Reputation: 145839
Use this wise advice from LLVM team:
"Turn Predicate Loops into Predicate Functions"
See:
http://llvm.org/docs/CodingStandards.html#turn-predicate-loops-into-predicate-functions
Upvotes: 14
Reputation: 47
If you need the values of i and j, this should work but with less performance than others
for(i;i< 1000; i++){
for(j; j< 1000; j++){
if(condition)
break;
}
if(condition) //the same condition
break;
}
Upvotes: 3
Reputation: 1864
int i = 0, j= 0;
for(i;i< 1000; i++){
for(j; j< 1000; j++){
if(condition){
i = j = 1001;
break;
}
}
}
Will break both the loops.
Upvotes: -3
Reputation: 724
i = 0;
do
{
for (int j = 0; j < 1000; j++) // by the way, your code uses i++ here!
{
if (condition)
{
break;
}
}
++i;
} while ((i < 1000) && !condition);
Upvotes: -4
Reputation: 24895
One way is to put all the nested loops into a function and return from the inner most loop incase of a need to break out of all loops.
function()
{
for(int i=0; i<1000; i++)
{
for(int j=0; j<1000;j++)
{
if (condition)
return;
}
}
}
Upvotes: 66
Reputation: 4357
for(int i = 0; i < 1000; i++) {
for(int j = 0; j < 1000; i++) {
if(condition) {
goto end;
}
}
end:
Upvotes: 4
Reputation: 133577
You'll need a boolean variable, if you want it readable:
bool broke = false;
for(int i = 0; i < 1000; i++) {
for(int j = 0; j < 1000; i++) {
if (condition) {
broke = true;
break;
}
}
if (broke)
break;
}
If you want it less readable you can join the boolean evaluation:
bool broke = false;
for(int i = 0; i < 1000 && !broke; i++) {
for(int j = 0; j < 1000; i++) {
if (condition) {
broke = true;
break;
}
}
}
As an ultimate way you can invalidate the initial loop:
for(int i = 0; i < size; i++) {
for(int j = 0; j < 1000; i++) {
if (condition) {
i = size;
break;
}
}
}
Upvotes: 30