-1

I've got a nested loop construct like this:

for(int i =0; i<3; i++ ){
    for(int j=0; j<4; j++)
    {
        if( ar[i][j]==0){
            flag=true; continue;        
        }else{
            flag=false; break;
        }       
    }

Now how can I break out of both loops. I've looked at similar questions,but the answers were available in java i want i c++.

Arif H-Shigri
  • 1,086
  • 12
  • 27
  • You can use `goto` to effect a multiple-loop break, but I would instead consider refactoring the loop into a separate function so you can just use `return`. – cdhowie Jan 05 '15 at 21:38
  • @cHao And that's really sad for it.. – Maroun Jan 05 '15 at 21:39
  • 3
    @MarounMaroun: Psh. `goto` is less of a problem than most of the contortions people go through to avoid using it. – cHao Jan 05 '15 at 21:40
  • @cHao Language primitives, like *functions*, aren't "contortions"; `goto` hides away the real problem of this not being a subroutine. – Bartek Banachewicz Jan 05 '15 at 21:45
  • thnax alot .. goto is working fine ,@cdhowie – Arif H-Shigri Jan 05 '15 at 21:45
  • @BartekBanachewicz: They most certainly *can be*, if the only reason you're defining a function is to avoid saying `goto`. – cHao Jan 05 '15 at 21:45
  • @cHao The reason to define a function is to put a part of the code in a separate unit, structuring it better. Not having to use `goto` is an added benefit. – Bartek Banachewicz Jan 05 '15 at 21:46
  • @BartekBanachewicz: And if that function will only ever be "called" from that one place, one could pretty convincingly argue that it's *less* structured. Now you have to yoyo around to trace the computer's steps through the code. – cHao Jan 05 '15 at 21:49
  • You could return, but returning in the middle of a function is poor form. Add && !flag to the conditions of both for loops. – Johan Snowgoose Jan 05 '15 at 21:49
  • 1
    @JohanSnowgoose Why returning in the middle of a function is poor form? – Bartek Banachewicz Jan 05 '15 at 21:50
  • @cHao nonsense. By this logic, if the code has only parts that are ran once, it shouldn't be divided into functions whatsoever. – Bartek Banachewicz Jan 05 '15 at 21:50
  • @BartekBanachewicz: In some cases, it shouldn't be. Another function == another entry point, and another place for changes to cause breakage. – cHao Jan 05 '15 at 21:51
  • @cHao What are the cases you speak of? Your previous comment suggested that there are no such cases. Can you elaborate on "place for changes to cause breakage"? – Bartek Banachewicz Jan 05 '15 at 21:55
  • @BartekBanachewicz: A function is there to be called. You might have intended for it to be called in exactly one place, but now it may eventually get used from elsewhere. So any change to the function now has to consider other callers. Frankly, a function for its own sake is closer to an old-school `goto` than `goto` itself is these days. – cHao Jan 05 '15 at 22:09
  • @cHao "Other callers"? If there appears a need to tailor the function for a different call site, the function was badly designed to begin with! Ideally, a total function doesn't possibly have any option to call it in a "wrong" way. Of course it's hard to write total functions in languages as limited in this regard as C++, nevertheless striving towards that is certainly a good idea. Also, functions don't exist for their own sake. They exist for the caller, even if only for one. – Bartek Banachewicz Jan 05 '15 at 22:43
  • 1
    @BartekBanachewicz: The mere *existence* of the function may well be bad design, if what it does and how it does it is not useful (or needs more than a tiny bit of tweaking to be useful) outside of its one known caller. This isn't Haskell; functions can have side effects. Sometimes that's *by design*. – cHao Jan 05 '15 at 23:11
  • @cHao Sure. Neither am I suggesting anyone writes functions like that; in this case, a functional `fold` (a.k.a. `reduce`) would be a much better solution, if only an appropriate (foldable) data structure has been used. Given that the structure doesn't allow such operation, an adapter could be made instead, but that *could* be an overkill. A simple wrapper function taking a lambda *could* be a nice way to solve that particular folding problem, but not given rest/planned usage, it's hard to pick a proper solution here. IOW, the question is badly formed. – Bartek Banachewicz Jan 05 '15 at 23:18
  • @cHao: re _"less of a problem"_ yes absolutely. use http://stackoverflow.com/a/7334968/560648 to prove it :) – Lightness Races in Orbit Jan 06 '15 at 11:57

4 Answers4

6

You can check for the flag inside the for-conditions (check other answers) or use a goto.

flag=true;
for(int i =0; i<3; i++ )
{   for(int j=0; j<4; j++)
    {   if( ar[i][j]!=0)
        {   flag=false;
            goto out;
        }       
    }
}
out:
// code continues here
Quentin
  • 62,093
  • 7
  • 131
  • 191
mrk
  • 3,061
  • 1
  • 29
  • 34
  • Whoever downvoted..why? – mrk Jan 05 '15 at 21:47
  • 1
    Thre is some noise in the code (`flag`) – anatolyg Jan 05 '15 at 21:49
  • Because `goto` is the mark of the beast or something. Here's an upvote to compensate. – Quentin Jan 05 '15 at 21:49
  • @saadtaame I downvoted because in my opinion you should at least mention the fact that if a part of code needs a `goto` statement, it should be restructured to not need it. IOW it hides a more important problem with the code. – Bartek Banachewicz Jan 05 '15 at 21:49
  • @BartekBanachewicz that's an extra..this answers the question and you know it. downvote is meaningless, sorry :) – mrk Jan 05 '15 at 21:50
  • I would suggest however removing the `continue` (the loop body ends anyway) and pull `flag = true` out of the loop instead of repeatedly assigning it. – Quentin Jan 05 '15 at 21:51
  • @anatolyg flag is declared before the nested loops, i don't know if he's going to use it afterwards or not..that's why i kept it. – mrk Jan 05 '15 at 21:51
  • @saadtaame no, the downvote isn't meaningless; Downvotes are meant as a measure of expressing disagreement with (parts of) the answer, or when a voter thinks the answer isn't good enough. That's exactly the case here and I've told you what you should do to improve it. – Bartek Banachewicz Jan 05 '15 at 21:51
  • @BartekBanachewicz feel free to edit, better than downvoting i guess. – mrk Jan 05 '15 at 21:52
  • @BartekBanachewicz you're suggesting a different answer altogether, not an improvement on this one. – Quentin Jan 05 '15 at 21:57
  • @Quentin well then, apparently there's no way for me to retract my downvote. – Bartek Banachewicz Jan 05 '15 at 22:43
  • With `flag` no longer constantly being set and reset, the `goto` here becomes merely a performance tweak. Offended cultists can easily remove it and get the same answer. But there's not much point in doing so. – cHao Jan 06 '15 at 14:03
4

You can put a more complicated expression in the for loop to terminate the loop early.

for(int i =0; i<3 && flag; i++ ){
    flag = false;
    for(int j=0; j<1 && !flag; j++)
    {
        if( ar[i][j]==0){
            flag=true; continue;        
        }else{
            flag=false; break;
        }       
    }
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Doesn't work with new loops: for(auto item: list) {} – Jacques Jan 29 '23 at 01:58
  • @Jacques that is unfortunately true. But I never claimed it did. The new loop syntax is simpler for the typical case, but sometimes you don't have a typical case. – Mark Ransom Jan 29 '23 at 04:42
2

Assuming that flag will only ever be false when you want to break out, just do this:

for(int i =0; i<3; i++ ){
    for(int j=0; j<1; j++)
    {
        if( ar[i][j]==0){
            flag=true; continue;        
        }else{
            flag=false; break;
        }       
    }
    if( !flag ) { break; }
}
mbgda
  • 787
  • 5
  • 8
  • yp its working fine. but goto is the best solution – Arif H-Shigri Jan 05 '15 at 21:44
  • 1
    @BartekBanachewicz Sorry. For me, the idea of using goto is so ridiculous I always assume people are joking when they say it's a good option. – mbgda Jan 05 '15 at 21:55
  • @Arif H-Shigri. Just keep in mind that a goto kills all optimizations by waiting for the CPU's cycles to flush what's still in its pipe by forcing the compiler to add nop ASM opcodes before the goto. In short: it is a performance killer. – Jacques Jan 29 '23 at 01:59
  • @mbgda That's kind of sectarianism. A break and a continue is a goto written with other letters. – Jacques Jan 29 '23 at 02:01
1

What you're doing here is essentially reimplementing std::any_of (or std::all_of); you could use that instead. Of course that might mean either nesting any_of calls to iterate it over dimensions, or using a single-dimensional array instead, or presenting any_of with single-dimensional view of your array.


Alternatively, if you really want to reinvent the wheel:

Call those as a subroutine and return the result:

bool flag = [&ar]{
    for(int i =0; i<3; i++ ){
        for(int j=0; j<4; j++)
        {
            if( ar[i][j]==0){
                continue;        
            } else {
                return false;
            }       
        }
    }
    return true;
}();

Alternatively, give that subroutine a name and simply call it.

Bartek Banachewicz
  • 38,596
  • 7
  • 91
  • 135
  • This is not better than the normal `goto` solution; it also doesn't work for the case of 3 nested loops. – anatolyg Jan 05 '15 at 21:47
  • @anatolyg why doesn't it work? Did you downvote? If yes, is the *is not better* a reason to downvote? – Bartek Banachewicz Jan 05 '15 at 21:48
  • See the question [here](http://stackoverflow.com/q/6077718/509868). Also, *I think* this solution is bad enough to downvote; someone else may think otherwise. It's not brilliant either way. – anatolyg Jan 05 '15 at 21:53
  • 1
    This episode in *Overkilling Goto* : single-use lambdas ! I guess that's slightly "better" than single-use functions... – Quentin Jan 05 '15 at 21:58
  • @anatolyg what's bad about it? – Bartek Banachewicz Jan 05 '15 at 22:40
  • @BartekBanachewicz: For one thing, it's not quite clear til the end (of a relatively long statement) that you're immediately calling the function you just defined. I'm not a fan of named functions that'll only get called once, but at least that call makes itself evident pretty quickly. – cHao Jan 05 '15 at 22:52
  • @cHao How is it not clear, given the first line? `bool flag = []{` is a dead giveaway of immediate call, because you can't save a lambda into a variable of type `bool`. – Bartek Banachewicz Jan 05 '15 at 22:54
  • @BartekBanachewicz: The first line doesn't say that. At best, it says that after all is said and done, the entire expression will evaluate to something that fits in a `bool`. It doesn't specify how. – cHao Jan 05 '15 at 22:59
  • 2
    To say it more formally, it's a total overkill just to avoit writing "`goto`". This should be at least accompanied by an explanation of why you would choose such a far-fetched structure over a tool that is specifically designed for this purpose. – Quentin Jan 05 '15 at 22:59
  • @Quentin `goto` isn't specifically designed for this purpose; that's the misconception you're spreading. It's just a remnant of an unconditional jump, represented on most architectures as `jmp` assembly instruction. Using an immediately evaluated function is a common practice in pretty much every modern programming language nowadays, and I don't see why anyone writing modern C++ should cater to what people used to ancient C or assembly use to think about problems, not recognizing any developments in language design whatsoever. And again, avoiding `goto` is just a side-effect here. – Bartek Banachewicz Jan 05 '15 at 23:14
  • Well, an unconditional jump is exactly what you need here. `goto` is a venerable tool, but it does the job cleanly. So, even if a newer tool *can* do it too, it must have a clear advantage over it, especially when it's as convoluted as the usual alternatives. Is it objectively clearer ? I'd say no, stuffing in a function so you can misuse the `return` statement to do the jump is not clearer. Note : I've personally never seen that pattern considered idiomatic in any language, except those that force it onto you by not having a jump statement at all, but examples are welcome. – Quentin Jan 05 '15 at 23:30
  • (cont.) That is to say, please add arguments other than "`goto` is old". – Quentin Jan 05 '15 at 23:32
  • @Quentin I think it's easiest to explain why I see it as bad here by going back to what is to be achieved by this code. In plain english it simply states *set the flag to true if any of the elements is 0*. In a functional language, this could be written as `any (== 0) ar`. Since this is C++, a language with quite strong functional capabilities and a Standard Library with the same (`std::any_of`), it could be viewed as more idiomatic to express it closer to the standard approach; in this case, `return`ing the value of that expression can hardly be seen as an abuse. – Bartek Banachewicz Jan 06 '15 at 00:18
  • @Quentin cont. Of course that just assumes the Standard Library approach should be preferred here; one might question its choices, and rightfully so. So what's gained with that approach? For one, the fact that `ar` isn't modified by the loops is more clearly expressed when using an appropriate algorithm. This might seem less clear in my answer, because I capture `ar` by reference into lambda scope. [Unfortunately, it's impossible to capture by `const&` in C++11](http://stackoverflow.com/questions/3772867/lambda-capture-as-const-reference), but I believe it changes in C++14. – Bartek Banachewicz Jan 06 '15 at 00:20
  • Just so it's said: the flag is true if *all* elements are 0. If any are not 0, it should be false. – cHao Jan 06 '15 at 02:06
  • @cHao `all equal to zero` or `any non-equal to 0`. I made a mistake, yeah. – Bartek Banachewicz Jan 06 '15 at 11:41