Home > Software engineering >  In C, how do i break out of a nested inner loop but continue the outer loop?
In C, how do i break out of a nested inner loop but continue the outer loop?

Time:11-30

This is my first time posting a coding question on any website, so apologies if i dont do a great job. Constructive feedback is very welcome. I am working on the tideman problem in cs50, if that is meaningful to anyone.

I cant figure out a way to break out of the inner nested loop but continue the outer loop. As in, if is_cycle is true, the lines:

locked[pairs[i].winner][pairs[i].loser] = true;
num_locked  ;

need to be skipped for that current iteration of the outer loop.

Thank you so much.

// Lock pairs into the candidate graph in order, without creating cycles
void lock_pairs(void)
{
    int num_locked = 0;
    //loop through pairs
        //has loser won before?
            //if no, lock the pair
            //if yes, call is_cycle on pair. if its not a cycle lock the pair
    for (int i = 0; i < pair_count; i  )
    {
        //has the loser won before?
        for (int j = 0; j < i; j  )
        {
            if (pairs[i].loser == pairs[j].winner)
            {
                //if the loser has won before and it creates a cycle, break the inner loop, continue outer
                if (is_cycle(pairs[i], pairs[j], num_locked))
                {
                    break;
                }
            }
        }
        //this is incorrect this will lock the pair each time
        locked[pairs[i].winner][pairs[i].loser] = true;
        num_locked  ;
    }

    return;
}

I have tried searching through stack overflow. Some mentioned a goto function but most people said that is bad programming. someone else mentioned creating a separate function and using return statements but i need that outer loop to continue, not stop. And one other answer suggested using flags, which after more searching i still dont get how that could help.

CodePudding user response:

Although goto should generally be avoided if there is a better alternative, for breaking out of a nested loop or continuing an outer loop, I do recommend using goto, as there is no clearly better alternative.

// Lock pairs into the candidate graph in order, without creating cycles
void lock_pairs(void)
{
    int num_locked = 0;
    //loop through pairs
        //has loser won before?
            //if no, lock the pair
            //if yes, call is_cycle on pair. if its not a cycle lock the pair
    for (int i = 0; i < pair_count; i  )
    {
        //has the loser won before?
        for (int j = 0; j < i; j  )
        {
            if (pairs[i].loser == pairs[j].winner)
            {
                //if the loser has won before and it creates a cycle, break the inner loop, continue outer
                if (is_cycle(pairs[i], pairs[j], num_locked))
                {
                    goto continue_outer_loop;
                }
            }
        }
        //this is incorrect this will lock the pair each time
        locked[pairs[i].winner][pairs[i].loser] = true;
        num_locked  ;

    continue_outer_loop:
        continue;
    }

    return;
}

CodePudding user response:

A flag is just a variable that lets you keep track of how things went, and adapt:

// Lock pairs into the candidate graph in order, without creating cycles
void lock_pairs(void)
{
  int num_locked = 0;
  //loop through pairs
  //has loser won before?
  //if no, lock the pair
  //if yes, call is_cycle on pair. if its not a cycle lock the pair
  for (int i = 0; i < pair_count; i  )
  {
    //has the loser won before?
    bool found = false;
    for (int j = 0; j < i; j  )
    {
        if (pairs[i].loser == pairs[j].winner)
        {
            //if the loser has won before and it creates a cycle, break the inner loop, continue outer
            if (is_cycle(pairs[i], pairs[j], num_locked))
            {
                found = true;
                break;
            }
        }
    }
    if (!found)
    {
      locked[pairs[i].winner][pairs[i].loser] = true;
      num_locked  ;
    }
  }
}

Also note that there is no need to return at the end of a void function, it's okay to just fall off the end. :)

CodePudding user response:

One way is to add a test after the inner loop to check whether it was broken out of early. E.g.:

// Lock pairs into the candidate graph in order, without creating cycles
void lock_pairs(void)
{
    int num_locked = 0;
    //loop through pairs
        //has loser won before?
            //if no, lock the pair
            //if yes, call is_cycle on pair. if its not a cycle lock the pair
    for (int i = 0; i < pair_count; i  )
    {
        int j;
        //has the loser won before?
        for (j = 0; j < i; j  )
        {
            if (pairs[i].loser == pairs[j].winner)
            {
                //if the loser has won before and it creates a cycle, break the inner loop, continue outer
                if (is_cycle(pairs[i], pairs[j], num_locked))
                {
                    break;
                }
            }
        }
        if (j < i)
        {
            continue;
        }
        locked[pairs[i].winner][pairs[i].loser] = true;
        num_locked  ;
    }

    return;
}

The scope of the j variable needed to be changed so that it could be accessed outside the inner loop.

  • Related