10

I have a vital infinite for loop that allows a sensor to keep updating its values. However I would like to break that for loop when another sensor brings in new values. How can I switch from one infinite for loop to another?

Current code:

for(;;){

    SON_Start();
    // Wait 65ms for max range time
    delay10ms(7);
    // Read Range
    i = SON_Read(SON_ADDRESSES[sonarReading]);
    // pause
    delayMs(100);
        if(i<15)
        drive(200, RadCW);

    }

What I would like to add:

If Sensor2 returns a reading (e.g. Sensor2 > 20), then I want to break the loop and goto another infinite for loop to begin a new function.

palacsint
  • 28,416
  • 10
  • 82
  • 109
NLed
  • 1,845
  • 14
  • 39
  • 68
  • 1
    Please don't close this question, folks. And, in future, if you have this kind of situation crop up again, flag for moderator attention. We prefer to try and salvage a situation rather than repost questions. –  Feb 13 '12 at 13:45

7 Answers7

28

If you are looking for "switching between 2 infinite loops" it could be "wrapped" by third loop and this "switching" could be done by simple break.

But since you want your program to stop some day, this loop could be placed within the function and you could use return; for ending it:

void myMagicLoop()
{
    for(;;)
    {
        for(;;)
        {
            if ( I should stop )
                return;

            if ( I should switch to second loop )
                break;
        }
        for(;;)
        {
            if ( I should stop )
                return;

            if ( I should switch back to first loop)
                break;
        }
    }
}

And somewhere you just call:

myMagicLoop();

Hope this helps.

LihO
  • 41,190
  • 11
  • 99
  • 167
  • Can you please expand the idea behind return for this example ? Can you implement a quick example code ?? I just cant get it to work. – NLed Feb 13 '12 at 11:37
  • @Fendi : I have updated my answer. Should be perfectly clear now. – LihO Feb 13 '12 at 11:42
  • Thank you ! The `I should stop` if statement would return a value, this value can be used to terminate the loop or used in other if statements ? – NLed Feb 13 '12 at 11:45
  • @Fendi : function `myMagicLoop` could return some value, then you would replace `return;` by `return value;` and yes, you would be able to use this value in code where you call this function: `value = myMagicLoop(); if (value...) ...`. If it's what you ask. – LihO Feb 13 '12 at 11:49
  • Thank you very much I got it ! One more thing, if I do not use `value = myMagicLoop();` , what will the `return` commands be used for in `I should stop` if statements ? – NLed Feb 13 '12 at 11:53
  • `return value;` does **not** mean that you **have to use this return value**. If you need this function to return value in some cases, it is ok if you `return value;` but still call it simple as `myMagicLoop();`. Also you can define some special value indicating problem (for example `-1` if you plan to return `int`) but I would rather use exceptions in that case. – LihO Feb 13 '12 at 11:58
  • Not to suggest something heretical, but if you don't want to put this all in a function, you could replace `return;` with `goto END;` and put `END:` after the outer loop. I think using `goto` to perform nested-loop `break`ing is perfectly acceptable. `goto` is really only dangerous when you start jumping backwards. – Chris Lutz Feb 24 '12 at 10:12
  • 1
    @ChrisLutz: There are many people that consider using `goto` "acceptable" and there are also many people that rather change their code in order to avoid using it. Lets say I belong to the second group. – LihO Feb 24 '12 at 10:13
  • @LihO - Fair enough, but I would argue that your "function" isn't really a function, just a block of code that's being unnecessarily isolated from the area where it's used. Unless you needed to run this loop multiple times, in which case yes, it is a function. But ultimately it's a religious argument. You're still conceptually jumping, but if using `return` instead of `goto` helps you sleep at night... ;) – Chris Lutz Feb 24 '12 at 10:16
  • I can't say that I didn't think of using `goto`, it seems reasonable. But this method works perfectly so I'm happy ! :D – NLed Feb 26 '12 at 17:48
8

This will switch between loop A and loop B.

for (;;)
{
    // Loop  A
    for (;;)
    {
        if WANT_TO_SWITCH
        {
            break;
        }

    }

    // Loop  B
    for (;;)
    {

        if WANT_TO_SWITCH
        {
            break;
        }

    }
}
Joe
  • 46,419
  • 33
  • 155
  • 245
5

You use break; to break a loop and pass control beyond its closing brace. For example

for(;;) {
   if( whatever ) {
      break;
   }
}
//break gets you here
sharptooth
  • 167,383
  • 100
  • 513
  • 979
5

Alternatively you could consider rewriting this with an event-driven approach. This will of course depend on what your hardware is capable of, but at the very least you should be able to produce some timer events.

Then the code would go something like this:

static volatile bool sensor_1_ready;
static volatile bool sensor_2_ready;

for(;;)
{
  switch(state_machine)
  {
    case READING_SENSOR_1:
      if(sensor_2_ready)
      {
        state_machine = READING_SENSOR_2;
      }
      else if(sensor_1_ready)
      {
        process sensor 1
      }
      break;

    case READING_SENSOR_2:

      if(!sensor_2_ready && some_timeout_etc)
      {
        state_machine = READING_SENSOR_1;
      }
      else if(sensor_2_ready)
      {
        process sensor 2
      }
      break;
  }
}

void callback_sensor_1 (void)  // some sort of interrupt or callback function
{
  sensor_1_ready = true;
}

void callback_sensor_2 (void)  // some sort of interrupt or callback function
{
  sensor_2_ready = true;
}

(Before commenting on the volatile variables, please note that volatile is there to prevent dangerous compiler optimizations and not to serve as some mutex guard/atomic access/memory barrier etc.)

Lundin
  • 195,001
  • 40
  • 254
  • 396
4

The "break" command should do what you need?

FreudianSlip
  • 2,870
  • 25
  • 24
2

The best way to do that is to change the for statement to something like:

for (; Sensor2 <= 20;) {
...

Alternatively you can change it from a for to a while statement:

while (Sensor2 <= 20) {
...

If that doesn't suite your needs you can always use a break instead.

onemasse
  • 6,514
  • 8
  • 32
  • 37
2

Another option could be to use signals (SIGUSR1,SIGUSR2) to switch from one loop to another. Something of this sort:

void sensor2(int signum)
{
   for (; ;)
      ...
      /* Need to process sensor 1 now */
      kill(pid, SIGUSR1);
}

void sensor1(int signum)
{
    for (; ;)
      ...
      /* Need to process sensor 2 now */
      kill(pid, SIGUSR2);
}


int main()
{
   /* register the signal handlers */
   signal(SIGUSR1,  sensor1);
   signal(SIGUSR2,  sensor2);
   ...
}
user138645
  • 772
  • 1
  • 7
  • 18