Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use goto to break a nested loop

Tags:

c++

for-loop

goto

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?

like image 764
Josh Avatar asked Sep 27 '12 00:09

Josh


People also ask

Does goto break loop?

@MatheusRocha Yes, it does. In fact, C++ has special rules about goto that prevent programmers from making improper jumps, e.g. jumping over initialization.

How do you break a loop in nested?

Using break in a nested loop In a nested loop, a break statement only stops the loop it is placed in. Therefore, if a break is placed in the inner loop, the outer loop still continues. However, if the break is placed in the outer loop, all of the looping stops.

Is nesting of goto statement is possible?

This article demonstrates that local goto statements create RAII for C code. The code is neat an easy to follow. Imagine that as a series of nested if statements. I understand that goto is taboo in many other languages because their exists other control mechanisms like try/catch etc, however, in C it seems appropriate.


4 Answers

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;
like image 199
Sergey Kalinichenko Avatar answered Oct 02 '22 02:10

Sergey Kalinichenko


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
}
like image 32
bitmask Avatar answered Oct 05 '22 02:10

bitmask


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.

like image 35
Cheers and hth. - Alf Avatar answered Oct 04 '22 02:10

Cheers and hth. - Alf


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;
    }
}
like image 41
Sion Sheevok Avatar answered Oct 03 '22 02:10

Sion Sheevok