Thread: Is there something like break(2) (multiple break) ?

  1. #1
    Registered User
    Join Date
    Apr 2009
    Posts
    8

    Is there something like break(2) (multiple break) ?

    Suppose I have
    Code:
    for (y=0; y<100; y++)
    {
      for (x=0; x<100; x++)
      {
        if (something(x,y))
        {
          break(2); // ??  I want to break out of the x AND y loop!
        }
      }
    }
    The method I'd use normally would be setting some flag, then break from the x loop, and the y loop checks if the flag is set, and then breaks there as well.

    Or, if I don't need the resulting y, I could do "y=101; break;" in the x loop.

    But is there a better way to do a "nested" break, i.e. from multiple levels?

    Same for this example:
    Code:
    for (i=0; i<n; i++)
    {
      x = something(i);
      switch(x)
      {
      case 1: /* ... */ break;
      case 2: /* ... */ break;
      case 666: break(2); // here I want to break not only out of the switch case, but out of the i loop as well!
      case 1000: /* ... */ break; 
      // etc..
      }
    }
    Again, I can easily make a workaround, but I'm wondering of there's a better solution.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    No, there is no such thing. There are a few options:
    1. Change the condition on your loop, and set a flag.
    2. Restructure the code in general.
    3. Use return/goto to jump further.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    DESTINY BEN10's Avatar
    Join Date
    Jul 2008
    Location
    in front of my computer
    Posts
    804
    Quote Originally Posted by Phuzzillogic View Post
    Suppose I have
    Again, I can easily make a workaround, but I'm wondering of there's a better solution.
    There is no such thing called break(2). If you want to get out of the nested loop then i think goto is the only possible solution and it is the only place where goto is really useful(to get out of the nested loop).
    I don't know if there is a better solution than goto in case of nested loops. But always there are multiple ways to solve a problem.
    HOPE YOU UNDERSTAND.......

    By associating with wise people you will become wise yourself
    It's fine to celebrate success but it is more important to heed the lessons of failure
    We've got to put a lot of money into changing behavior


    PC specifications- 512MB RAM, Windows XP sp3, 2.79 GHz pentium D.
    IDE- Microsoft Visual Studio 2008 Express Edition

  4. #4
    Registered User
    Join Date
    May 2007
    Posts
    147
    You've got the first answer, break and the concept of break only works on the containing level (nothing propagates outward to containing loops).

    I'd like to address the design and thought process behind your question.

    I start with the function "something" as in " x = something( i ); " and similar.

    This function represents a concept, determining x relative to i, or some other decision process as indicated by if ( something(x,y ) ) in your other example.

    That's good thinking. Functions should do a job, and do that job well. We all have the tendency to think in terms of a linear statement list, where we end up with large functions that have a meandering series of statements, loops - which, upon broader examination, tend to group into phases, or in the case of the infamous and ubiquitous master switch of a Win32API style message loop, a kind of table.

    This constitutes a mess in the long run. It's a habit of development, and can be hard to break. The temptation is to think that these kinds of functions are easier, because everything is right there. It's like my own personal filing system - I have none. My desk is piled with every page and form I've handled since the last time I chucked everything in the trash. I know where everything is - it's right here, somewhere - but it's not an organized collection.

    In simpler examples, like those you've shown, the mess isn't obvious. It's just like a few pages, a couple of letters and the napkin left from yesterday's lunch. Not too bad. The problem is, as I continue to get deeply involved in everything else, the clutter tends to build.

    The same thing happens in our code when this habit persists.

    One key is to think differently about the problem you're inquiring. It's common for people to think there ought to be some language construct to solve "this problem" or "that problem" - as in why not a 'break(2)' or some such construct. It's humbling to contemplate that hundreds, perhaps thousands, of PhD's have considered these puzzles at deep levels, and have rather intricate reasoning behind the absence or presence of a particular language construct. We know they're not perfect either ( template parameters in typedefs were an admitted omission of an obvious feature, for example ), but this one has a reasonable answer.

    For one, if you used "break(2)" - and then later had to add an outer loop to your logic, it would have to become 'break(3)', but nothing obvious would guide you to review these breaks to know that until you have a bug to track down.

    The better solution is to construct in such a way that this is no longer a question to be asked. So, I return to

    x = something( i );

    This contains a decision.

    Doing something about that decision could also be contained.

    if ( !DoSomething( i ) ) break;


    In this case, DoSomething would contain both the call to "x = something( i )" and the switch that does something with x. DoSomething returns a state, or at least a reply, that processing should continue or not continue.

    This notion factors out the decisions being considered. Instead of combining multiple decisions (that of stopping everything from even the outer loop), it separates these otherwise unrelated notions so they operate independently.

    Stated another way, the problem of determining x in terms of i is the job of "something", and the decision of what to do based on x should be the job of "DoSomething", while the job of driving this in terms of i is the outer loop. In the inquiry about "break(2)" as a solution, you have 'mixed' the act of determining the break of the outer loop in terms of i with the decision about what to do with x. They have no other relationship at that point (once you know x in terms of i, i is no longer part of the problem within the switch).

    It is the mixing of these two separate concepts that is the same as the mixed up pile of papers on my desk.

    It may seem quite trivial, but small examples tend to seem less convincing because the problem exposed is nothing more than a break and a flag. As this kind of implementation habit proceeds in more complex work, however, the tendency to think this way creates ever more complicated interactions between groups of logic that otherwise have no relationship to each other.

    Separating these units of logic, so they have less tendency to interfere or interact, is part of the main focus of the paradigms of both function oriented programming (C), and object oriented programming (C++). In more obvious code it may make more sense than in something like this, but the thought process and theory still applies.


    The problem with my entire point is illustrated by:

    Code:
    for (y=0; y<100; y++)
    {
      for (x=0; x<100; x++)
      {
        if (something(x,y))
        {
          break(2); // ??  I want to break out of the x AND y loop!
        }
      }
    }
    In this code, y and x are indeed related to each other. While it may be reasonable to make a function that performs the x loop in terms of a single y (row), so that the break I'm describing is cleanly separated, there is a significant performance reason to avoid this. Plus, we can clearly see this loop is not likely to ever expand. This entire concept is unified - we're processing a 2d matrix. While there is some logic to think that x is looped in terms of y (the columns of a row), the overhead of a function is undesirable, and the unity of x and y comprising a coordinate is obvious.

    We could simply set y to the maximum so the outer loop is already finished by the time we've decided a 'break(2)' is desired. We could resort to goto (which I never do, BTW).

    Setting y to maximum is at least working with the concept of the y loop. A break(2) has the same problem I mentioned before (if another loop encloses this one, we have to change it to break(3), and that is a reasonable alteration to expect). Changing Y to maximum, at least, leaves the concept related between the decision and the loop control, but we still have the problem of the outer loop if it is ever added. Would it also be broken, or is THAT loop supposed to continue (it would likely be an entirely unrelated concept to y and x - probably a loop through objects in a 2D game engine, or multiple pages in a book of grids). This tells me that this loop is a concept that should be IN a function that returns state or result (meaning the loop stopped for a reason, or completed and things should simply go on). That way, any changes outside this are entirely separated from this small unit.

    In other words, there are occasions when nested loops are a unified concept, and the break(2) question may apply, but usually this is in terms of the concept - and if that concept is in a function by itself, you can just call return with a result value, instead of considering break(2).


    Code:
    bool fgrid( w, h )
    {
    
     for (y=0; y<h; y++) 
     {
      for (x=0; x<w; x++)
      {
        if (something(x,y))
        {
          return false; // ??  I want to break out of the x AND y loop!
        }
      }
     }
    
     return true;
    }

    I smell an object here.....

    Width and Height imply that there's a larger concept. If this grid is a 2d object, width and height are part of it's definition, there are likely also other notions that combine to comprise the data of the object, and this loop is likely part of the object's operation.

    There's an opportunity in that point for further organization of this code.
    Last edited by JVene; 05-07-2009 at 06:45 AM.

  5. #5
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    The common solution is to put the loops into their own function and use a return statement instead. But yes I am also one to have set the outer loop variable such that that loop will terminate and then use a single break.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  6. #6
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by iMalc View Post
    The common solution is to put the loops into their own function and use a return statement instead. But yes I am also one to have set the outer loop variable such that that loop will terminate and then use a single break.
    That is sometimes possible, but on occasion you want to know the ACTUAL value of the outer loop counter after breaking the loop. In that case you need a separate flag.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  7. #7
    Registered User
    Join Date
    May 2007
    Posts
    147
    That is sometimes possible, but on occasion you want to know the ACTUAL value of the outer loop counter after breaking the loop. In that case you need a separate flag.
    Or, the function might be the member of an object which tracks the state of the outer loop - in which case you only need to return.

  8. #8
    Registered User
    Join Date
    Jan 2009
    Posts
    31
    If the loop bodies are small, then a goto may be appropriate...

    Code:
    for(int x = 0; x < w; x++) {
        for(int y = 0; y < h; y++) {
             if(something(x, y)) goto end;
        }
    }
    end:;
    By the way, perl has the feature that you're looking for...

    Code:
    OUTER: for(my $x = 0; $x < $w; $x++) {
        for(my $y = 0; $y < $h; $y++) {
           last OUTER if something($x, $y);
        }
    }

  9. #9
    Not stupid, just stupider yaya's Avatar
    Join Date
    May 2007
    Location
    Earthland
    Posts
    204
    You always go the easy way out and replace break(2); with x = y = 200;.

  10. #10
    Registered User
    Join Date
    May 2009
    Posts
    37
    or a more structured solution is perhaps:

    Code:
    for (x = 0; (x < 100) && (flag); x++){
       for(y = 0; (y < 100) && (flag); y++){
       ...
       }
    }

  11. #11
    Registered User
    Join Date
    Apr 2009
    Posts
    8
    Thanks for all your answers. JVene, regarding the last remark in your detailed reply:
    Quote Originally Posted by JVene View Post
    I smell an object here.....

    Width and Height imply that there's a larger concept. If this grid is a 2d object, width and height are part of it's definition, there are likely also other notions that combine to comprise the data of the object, and this loop is likely part of the object's operation.

    There's an opportunity in that point for further organization of this code.
    Suppose my object is an image, and for some reason I want to check if some upper left rectangle (of custom width and height) is empty (in this context, that is: contains only black pixels). And "something(x,y)" means "pixel(x,y)!=black". How would you further organize that?

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    If you want to check if a particular region (x, y, h, w) is a single colour, then I suggest you write a function that checks that area for that colour - it can then return when it finds a pixel of a different colour. Obviously, if x, y are always zero and the colour always black, then you do not need to pass those parameters into the function - but it often helps to make a function more generic, so that you can check ANY rectangle for any colour.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. I need help with variables, please
    By JOCAAN in forum C++ Programming
    Replies: 39
    Last Post: 12-08-2007, 04:16 PM
  2. game window rejected painting !
    By black in forum Windows Programming
    Replies: 4
    Last Post: 03-27-2007, 01:10 AM
  3. MDICLIENT Problem
    By loko in forum Windows Programming
    Replies: 7
    Last Post: 01-16-2005, 10:42 PM
  4. Keypress reading
    By geek@02 in forum Windows Programming
    Replies: 1
    Last Post: 06-16-2004, 12:16 PM

Tags for this Thread