Обсуждаем контроллеры компании Atmel.
Ответить

"break to out" from for/switch

Чт дек 09, 2021 11:08:54

добрый день.
разбираю код (обычный си-код, без крестов):

1. switch вложен в for
2. выброс реализован "хаком" условия for

все работает, но при "обычном" многостраничном операторе switch-case такой выход "неочевиден".

вопрос: можно-ли как ни-будь красиво/очевидно/локонично реализовать выход из цикла

Код:
for(i=1; i<RET; i++)
{
...
switch(i)
  {
  case 10:
  if()
    {
    ...
    RET = 11; // break to out
    }
  break;
  ...
  case 20:
  if()
    {
    ...
    RET = 21;
    }
  break;
  ...
  case 30:
  if()
    {
    ...
    RET = 31;
    }
  break;
  }   // switch()
}     // for()

Re: "break to out" from for/switch

Чт дек 09, 2021 11:20:53

Можно флаг взводить. И после switch его проверять, с бреком на выход.
Или всеми нелюбимый goto :)

Re: "break to out" from for/switch

Чт дек 09, 2021 11:38:09

Можно его завернуть в другое название:
#define break_of_switch break

и применять к месту в коде, суть от этого не изменится, но глазам будет легче...
(можно и наоборот "цикловой" брейк передефайнить...)

Re: "break to out" from for/switch

Чт дек 09, 2021 11:40:16

В условиях цикла написать что-то вроде (i<RET)&&(RUN)
Перед циклом взводить RUN в единицу, а внутри switch устанавливать его в ноль, когда нужно выйти.

Re: "break to out" from for/switch

Чт дек 09, 2021 12:28:28

Аlex писал(а):Можно флаг взводить. И после switch его проверять, с бреком на выход.
>TEHb< писал(а):В условиях цикла написать что-то вроде (i<RET)&&(RUN)
Перед циклом взводить RUN в единицу, а внутри switch устанавливать его в ноль, когда нужно выйти.
Те же яйца, только в профиль :))

Добавлено after 58 seconds:
sunjob, воткните goto и не мучайтесь :))

Re: "break to out" from for/switch

Чт дек 09, 2021 12:37:30

неправильно вопрос понял...
тогда или добавлять ещё условие или модифицировать операторы в имеющемся:
*или изменять счётчик - я, например, если надо сохранить его значение и счетчик не насчитывает более 127 просто сделал бы i|=1<<7; и получил бы выход из цикла по нарушению условия, а после цикла, сделав i&=~(i<<7); восстановил значение счётчика
*или написав вместо while(i<15)... x=15; while(i<x), а в теле, когда надо досрочно выйти сделал бы х=0;
*можно и 2е условие в цикл дописать
*можно ГоТо... но, я бы не стал - компилятор (кодевижен) иногда его некорректно отрабатывает и не всегда отслеживает неправильность его применения... можно глюк поймать, можно только в сжатии потерять...
Последний раз редактировалось Ivanoff-iv Чт дек 09, 2021 12:50:33, всего редактировалось 1 раз.

Re: "break to out" from for/switch

Чт дек 09, 2021 12:42:56

Ivanoff-iv :о) да, именно так и выкрутился... и ни чего не надо "перехерачивать" в коде

но глазам будет легче...
именно из-за этого весь сыр-бор :))
Последний раз редактировалось sunjob Чт дек 09, 2021 13:03:03, всего редактировалось 1 раз.

Re: "break to out" from for/switch

Чт дек 09, 2021 12:55:22

Так-то ещё циклы while, там условия выхода не выглядят как нечто чужеродное.

Аlex писал(а):Те же яйца, только в профиль


Так-то да, плюс-минус. Только стараюсь делать так, что б циклы выходились эмм... Самостоятельно что ли. Тем более, что сложностей-то никаких.

Аlex писал(а):воткните goto и не мучайтесь


Ох и осторожно же надо этим пользоваться! Есть шанс намучиться ещё сильнее.

Re: "break to out" from for/switch

Чт дек 09, 2021 13:04:58

Так-то ещё циклы while ...

в данном случае for() используется из-за инкриментной переменной :)

Re: "break to out" from for/switch

Чт дек 09, 2021 13:13:12

в данном случае for() используется из-за инкриментной переменной :)
насколько мне известно, для мк результат не будет отличаться хоть for хоть while (){.......i++;};

Добавлено after 45 seconds:
да и в фор никто i теребить изнутри цикла не запрещает...

Re: "break to out" from for/switch

Чт дек 09, 2021 13:20:07

да ешкин-код! есть нормальный цикл for(), нахрена извращаться с while() и плодить шушностей?!
все же уже найдено, самое оптимальное :kill:
или че?! :dont_know:

Re: "break to out" from for/switch

Чт дек 09, 2021 13:43:53

Каждой задаче свой инструмент. Например, при ожидании какого-нибудь события цикл for городить как-то не особо, а вот написать что-то в духе while(PINB.4){}; вполне себе наглядно и лаконично. Конкретно в вашем примере рискну предположить, что цикл выполняется не менее одного раза, тогда связка do ... while() выглядит суперчитаемой. Постусловие же. Вот и получается как просили
sunjob писал(а):красиво/очевидно/локонично


Если не нравится так, то себе делайте как душа лежит :beer: . Разве ж кто-то может запретить?

Re: "break to out" from for/switch

Чт дек 09, 2021 13:45:57

goto, естественно, - единственный лаконичный и вменяемый вариант.

Re: "break to out" from for/switch

Чт дек 09, 2021 14:08:52

тогда связка do ... while() выглядит суперчитаемой. Постусловие же. Вот и получается как просили
sunjob писал(а):красиво/очевидно/локонично

Если не нравится так, то себе делайте как душа лежит :beer: . Разве ж кто-то может запретить?

дак в том и дело, нужно было "залитовать" многостраничный нахреновенчанный код, что бы не ахрененть от переделок и ни чего не сломать... случано... :facepalm:

вот и получается всего два очевидных варианта (коТ на скору лапу, мож че и спЁр лишнего)
Код:
for(i=1; i<BREAK; i++)
{
...
switch(i)
  {
  case 10:
  if()
    {
    ...
    BREAK = 0; // видим слово BREAK - значить это "то, что надо"
    }
  break;
...
}

либо

#define BREAK 0

for(i=1; i<CNT; i++)
{
...
switch(i)
  {
  case 10:
  if()
    {
    ...
    CNT = BREAK; // тут вообще все очевидно :о)
    }
  break;
...
}

Re: "break to out" from for/switch

Пт дек 10, 2021 14:54:32

Если красиво - то флаг и брек цикла в конце.
Если оптимизация скорости и экономия байтов - то гото.
Но гото хуже читаем, а экономии при отказе от флага - ну от силы десяток команд.

Re: "break to out" from for/switch

Пт дек 10, 2021 16:00:55

goto, естественно, - единственный лаконичный и вменяемый вариант.

Угу. Если делать только одну точку в пределах функции/метода то никаких проблем. У меня большой проект так сделан - в каждой функции точка exit: есть. Подсмотрел в библиотеке LwIP, а ее не дураки писали.

Re: "break to out" from for/switch

Пт дек 10, 2021 18:45:33

Можно сделать через массив указателей
Код:
#define N_ELEMENTS(x)       (sizeof(x) / sizeof(*(x))) // возвращаем количество элементов в массиве

//========================
// Заглушка, т.к. case c нулём нет
//========================
unsigned char Dummy(unsigned char *ret)
{
    return(1);   // будет break
}

//========================
// действия 1 case switch
//========================
unsigned char Num_1(unsigned char *ret)
{
    unsigned char res = 0;
    *ret = 5;    // меняем значение ret (работаем через указатель)
//    if()
    res = 1;   // без break
    return(res); // условие выхода: если 0-выходим, если 1 то не выходим
}

//========================
// действия 2 case switch
//========================
unsigned char Num_2(unsigned char *ret)
{
    unsigned char res = 0;
    *ret = 6;
//    if()
    res = 1;
    return(res); // условие выхода: если 0-выходим, если 1 то не выходим
}

//========================
// действия 3 case switch
//========================
unsigned char Num_3(unsigned char *ret)
{
    unsigned char res = 0;
    *ret = 7;
//    if()
    res = 0;
    return(res); // условие выхода: если 0-выходим, если 1 то не выходим
}

//========================
// список case switch
//========================
unsigned char (* const Nums[])(unsigned char *ret) =
{
    Dummy,  // заглушка
    Num_1,   // действия в 1 case
    Num_2,   // действия в 2 case
    Num_3,   // действия в 3 case
};


//========================
// Главная процедура (Reset)
//========================
void main(void)
{
    unsigned char i;
    unsigned char RET=5;
   
    while(1)
    {
        for(i=1; i<RET; i++)
        {
            if(i < N_ELEMENTS(Nums))   // проверяем, чтобы не вышли за диапазон массива
            {
                if(!Nums[i](&RET)) break; // вызываем case по номеру i и возвращаем изменённое значение RET, если результат выполнения функции 0, то break
            }
        }
    }
}
 

Re: "break to out" from for/switch

Пт дек 10, 2021 19:33:00

Как все сложно, еще и указатели влепили.
Если цикл for находится в функции да просто return выполнить и усе, типа такого
Спойлер
Код:
void cel ( ) {
   for(i=1; i<10; i++)
   {
      switch(i)
      {   
         case 1:  break;
         case 2:  break;
         case 3:  break;
         case 4: if(x == чего-то там) return; break;
         case 5:  break;
         case 6:  break;
         case 7:  break;   
      }
   }
}

Re: "break to out" from for/switch

Сб дек 11, 2021 00:33:37

Если вначале добавить #define XBATUT return то читаемость ещё увеличится.
Кажется, мы несколько по-разному восприняли задачу.

Re: "break to out" from for/switch

Сб дек 11, 2021 07:06:54

Dimon456, фишка в том, что весь этот код
- чужой
- раскидан на несколько страниц
- напихан математико/эмпиричекими закидонами, нахреноверчен до нечитабельности

поэтому все "дополнения", "тяжелые модернизации" - ни как не катят, можно легко "сломать" математику, да и просто редактирвоать это "нечто" очень тяжело

поэтому (я для себя) выбрал наименьшее вмешательство

п.с. понятно дело, с нуля писать, это не разбираться в чужом коде :kill:

Ярослав555, согласен, если goto локальный :)
Ответить