8

How can I use a "goto" statement to break out of a loop

for(i = 0; (i < 9); i++)
    {
        for(j = 0; j < 9; j++)
        {
            //cout << " " << Matrix[i][j];
            //cout << "i: " << i << endl;
            if(Matrix[i][j] == 0)
            {
                //temp = 10;
                [goto] ;
                //break;
            }
        }
    }

I wanted to keep the values at which i and j were when I left the nested for loop. How can I use a goto statement for that?

4 Answers 4

17

Like this:

int i,j;
for(i = 0; i < 9; i++)
{
    for(j = 0; j < 9; j++)
    {
        //cout << " " << Matrix[i][j];
        //cout << "i: " << i << endl;
        if(Matrix[i][j] == 0)
        {
            //temp = 10;
            goto end;
            //break;
        }
    }
}
end:
cout << i << " " << j << endl;
Sign up to request clarification or add additional context in comments.

2 Comments

I know this is old, but... Does a goto to out of the current scope (specially a loop's scope) finishes it properly?
@MatheusRocha Yes, it does. In fact, C++ has special rules about goto that prevent programmers from making improper jumps, e.g. jumping over initialization.
7

Just as you use goto in any other situation. As long as you don't cross scopes with local variables in them, you can actually think of it as "goto this and that line":

for (/* ... */) {
  /* ... */
  if (/* ... */)
    goto finalise;
}
finalise:
  foo = bar; //...

However, there are many situations when goto is an indicator for not well designed code. By no means always, but often.

I suggest you use gotos big brother return and factor out your code into a function:

inline std::pair<int,int> findZeroEntry(std::vector matrix) {
  for (int i = 0; i < 9; i++)
    for (int j = 0; j < 9; j++)
      if (Matrix[i][j] == 0)
        return std::make_pair(i,j);
  return std::make_pair(9,9); // error
}

5 Comments

+1 you beat me to it. this is what the OP should have selected as "the solution". well ok i planned on using a local lambda, but anyway.
@Downvoter: Could you offer any indication what is wrong here?
no, no, no factoring into a solution is just stupid so many times, you break temporal logic flow and force user to navigate somewhere else, especially in many situations where it's simply a complex function and Should Not Be Broken Up. there are many, many situations where goto is the RIGHT way to design the code, but nobody in CS academia has ever experienced those so they handwave and cause countless problems for noobs like me that wasted years trying to avoid goto in my embedded code.
@Rancur3p1c: As Alf points out, factoring out a function can be done using a lambda as well. If it's logically sensible to have the "to-be-factored-out" function close to the surrounding code, use an anonymous lambda. I'm sorry that academics gave you poor advise and wasted your time and agree that it is unreasonable to think in absolutes as "gotos are evil, never use them".
@paIncrease Coud you point to some examples of such complex functions? E.g. on Github.
2

Well, @bitmask's answer has already said most of what I thought of saying when I read the question.

But for completeness, here's another technique:

Matrix              m;
Index2D< 9, 9 >     pos;

for( ; pos < pos.end();  ++pos )
{
    if( m( pos.x(), pos.y() ) == 0 )
    {
        break;
    }
}
cout << pos.x() << " " << pos.y() << endl;

IMHO this is far more clear code.

Also, the matrix can then be made to support indexing via Index2D values, thus reducing the above to just …

Matrix              m;
Index2D< 9, 9 >     pos;

for( ; pos < pos.end();  ++pos )
{
    if( m[pos] == 0 )
    {
        break;
    }
}
cout << pos.x() << " " << pos.y() << endl;

Since there’s nothing like Index2D in the standard library, it needs to be defined somewhere, e.g. like

template< int width, int height >
struct Index2D
{
    int         i_;

    int x() const { return i_ % width; }
    int y() const { return i_ / width; }

    void operator++() { ++i_; }

    bool operator<( Index2D const& other ) const
    {
        return (i_ < other.i_);
    }

    Index2D(): i_( 0 ) {}

    Index2D( int const x, int const y )
        : i_( width*y + x )
    {}

    static const Index2D endValue;
    static Index2D end() { return endValue; }
};

template< int width, int height >
Index2D< width, height > const Index2D< width, height >::endValue( 0, height );

But then it can be reused everywhere that you need this functionality.

1 Comment

I like the idea of a 2d iterator. Just one nit: I'd make endValue local to end().
0

You don't need goto to leave the nested for loop and save off those variables. Merely, you want to break out of each loop successively. Just have a boolean at the appropriate scope level that you check to know if need to break out of the loops.

Corrected example

IE:

bool HasFoundZero = false;
for(i = 0; i < 9; i++)
{
    for(j = 0; j < 9; j++)
    {
        //cout << " " << Matrix[i][j];
        //cout << "i: " << i << endl;
        if(Matrix[i][j] == 0)
        {
            //temp = 10;
                HasFoundZero = true;
        }
        if(HasFoundZero)
        {
            break;
        }
    }
    if(HasFoundZero)
    {
        break;
    }
}

5 Comments

you mean hasfound"zero" = true :D
All this does is hide the fact that you are using goto. It's still a goto, just with a boolean to obfuscate and slow things down. Why obfuscate? Just use goto. I'd prefer to see that verboten goto used to break out of an inner loop over a boolean that hides the fact that a goto is being used. Other languages provide a multi-level break. C/C++ does not. That C/C++ does not is a language defect.
Besides the fact that this is not that much better than the goto, and it has extra cost (one test per iteration in each of the loops), this answer does not comply with the requirement that he wants the values of i and j where the object was found (i in this case will be the location plus one)
@Josh: Woops. What I get for typing it up in Notepad++. @DavidHammen: By that logic, why use a for loop? It's just hiding your gotos. In fact, why ever use break, by that logic? break is safer in usage. There's a reason why it exists. Your logic could even extend to switch or while being unnecessary... @DavidRodríguez-dribeas: I corrected the example. Any good compiler will optimize further. More importantly, this is easier to maintain than gotos and labels. As well, in this simple example, is there anything to suggest that one condition test is a performance concern?
@SionSheevok Literally the stupidest answer I've ever seen. Now you've introduced TWO entire checks that have to be executed. If the loops are tight and executed a lot, this is going to cost you HUGELY in terms of performance. This is simply like the IDEAL case for a goto. I mean, what is your objection to them? And don't say spaghetti code, because we're WAY past that silly argument. Moreover, how is it more maintainable to use MORE code to break out of nested loops, when the goto is perfectly clear in terms of what it does.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.