Как разорвать бесконечный цикл (;;) в C? - PullRequest
10 голосов
/ 13 февраля 2012

У меня есть жизненно важный бесконечный цикл, который позволяет датчику постоянно обновлять свои значения. Однако я хотел бы прервать этот цикл, когда другой датчик вводит новые значения. Как я могу переключиться с одного бесконечного цикла на другой?

Текущий код:

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);

    }

Что бы я хотел добавить:

Если Sensor2 возвращает чтение (например, Sensor2 > 20), я хочу разорвать цикл и перейти к другому бесконечному циклу for, чтобы начать новую функцию.

Ответы [ 7 ]

28 голосов
/ 13 февраля 2012

Если вы ищете «переключение между 2 бесконечными циклами» , оно может быть «обернуто» третьим циклом, и это «переключение» может быть выполнено простым break.

Но так как вы хотите, чтобы ваша программа когда-нибудь остановилась, этот цикл можно поместить в функцию, и вы можете использовать return; для его завершения:

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;
        }
    }
}

А где-то вы просто вызываете:

myMagicLoop();

Надеюсь, это поможет.

8 голосов
/ 13 февраля 2012

Это переключит между контуром A и контуром B.

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

    }

    // Loop  B
    for (;;)
    {

        if WANT_TO_SWITCH
        {
            break;
        }

    }
}
5 голосов
/ 13 февраля 2012

В качестве альтернативы вы могли бы рассмотреть возможность переписать это с помощью подхода, управляемого событиями. Это, конечно, будет зависеть от того, на что способно ваше оборудование, но, по крайней мере, вы сможете создавать некоторые события таймера.

Тогда код будет выглядеть примерно так:

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;
}

(Прежде чем комментировать переменные volatile, , пожалуйста обратите внимание, что volatile существует для предотвращения опасных оптимизаций компилятора, а not для защиты мьютекса / атомарного доступа / барьера памяти и т. Д. ) * +1010 *

5 голосов
/ 13 февраля 2012

Вы используете break;, чтобы разорвать петлю и передать управление за ее закрывающую скобку. Например

for(;;) {
   if( whatever ) {
      break;
   }
}
//break gets you here
4 голосов
/ 13 февраля 2012

Команда "break" должна делать то, что вам нужно?

2 голосов
/ 14 февраля 2012

Другим вариантом может быть использование сигналов (SIGUSR1, SIGUSR2) для переключения с одной петли на другую.Что-то в этом роде:

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);
   ...
}
2 голосов
/ 13 февраля 2012

Лучший способ сделать это - изменить выражение for на что-то вроде:

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

В качестве альтернативы вы можете изменить его с for на while оператор:

while (Sensor2 <= 20) {
...

Если это не соответствует вашим потребностям, вы всегда можете использовать break.

...