Страница 1 из 2

"break to out" from for/switch

Добавлено: Чт дек 09, 2021 11:08:54
sunjob
добрый день.
разбираю код (обычный си-код, без крестов):

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
Аlex
Можно флаг взводить. И после switch его проверять, с бреком на выход.
Или всеми нелюбимый goto :)

Re: "break to out" from for/switch

Добавлено: Чт дек 09, 2021 11:38:09
Ivanoff-iv
Можно его завернуть в другое название:
#define break_of_switch break

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

Re: "break to out" from for/switch

Добавлено: Чт дек 09, 2021 11:40:16
>TEHb<
В условиях цикла написать что-то вроде (i<RET)&&(RUN)
Перед циклом взводить RUN в единицу, а внутри switch устанавливать его в ноль, когда нужно выйти.

Re: "break to out" from for/switch

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

Re: "break to out" from for/switch

Добавлено: Чт дек 09, 2021 12:42:56
sunjob
Ivanoff-iv :о) да, именно так и выкрутился... и ни чего не надо "перехерачивать" в коде
но глазам будет легче...
именно из-за этого весь сыр-бор :))

Re: "break to out" from for/switch

Добавлено: Чт дек 09, 2021 12:55:22
>TEHb<
Так-то ещё циклы while, там условия выхода не выглядят как нечто чужеродное.
Аlex писал(а):Те же яйца, только в профиль
Так-то да, плюс-минус. Только стараюсь делать так, что б циклы выходились эмм... Самостоятельно что ли. Тем более, что сложностей-то никаких.
Аlex писал(а):воткните goto и не мучайтесь
Ох и осторожно же надо этим пользоваться! Есть шанс намучиться ещё сильнее.

Re: "break to out" from for/switch

Добавлено: Чт дек 09, 2021 13:04:58
sunjob
[uquote=">TEHb<",url="/forum/viewtopic.php?p=4138031#p4138031"]Так-то ещё циклы while ...[/uquote]
в данном случае for() используется из-за инкриментной переменной :)

Re: "break to out" from for/switch

Добавлено: Чт дек 09, 2021 13:13:12
Ivanoff-iv
[uquote="sunjob",url="/forum/viewtopic.php?p=4138039#p4138039"]в данном случае for() используется из-за инкриментной переменной :)[/uquote] насколько мне известно, для мк результат не будет отличаться хоть for хоть while (){.......i++;};

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

Re: "break to out" from for/switch

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

Re: "break to out" from for/switch

Добавлено: Чт дек 09, 2021 13:43:53
>TEHb<
Каждой задаче свой инструмент. Например, при ожидании какого-нибудь события цикл for городить как-то не особо, а вот написать что-то в духе while(PINB.4){}; вполне себе наглядно и лаконично. Конкретно в вашем примере рискну предположить, что цикл выполняется не менее одного раза, тогда связка do ... while() выглядит суперчитаемой. Постусловие же. Вот и получается как просили
sunjob писал(а):красиво/очевидно/локонично
Если не нравится так, то себе делайте как душа лежит :beer: . Разве ж кто-то может запретить?

Re: "break to out" from for/switch

Добавлено: Чт дек 09, 2021 13:45:57
Eddy_Em
goto, естественно, - единственный лаконичный и вменяемый вариант.

Re: "break to out" from for/switch

Добавлено: Чт дек 09, 2021 14:08:52
sunjob
[uquote=">TEHb<",url="/forum/viewtopic.php?p=4138073#p4138073"]тогда связка do ... while() выглядит суперчитаемой. Постусловие же. Вот и получается как просили
sunjob писал(а):красиво/очевидно/локонично
Если не нравится так, то себе делайте как душа лежит :beer: . Разве ж кто-то может запретить?[/uquote]
дак в том и дело, нужно было "залитовать" многостраничный нахреновенчанный код, что бы не ахрененть от переделок и ни чего не сломать... случано... :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
GoldenAndy
Если красиво - то флаг и брек цикла в конце.
Если оптимизация скорости и экономия байтов - то гото.
Но гото хуже читаем, а экономии при отказе от флага - ну от силы десяток команд.

Re: "break to out" from for/switch

Добавлено: Пт дек 10, 2021 16:00:55
Ярослав555
[uquote="Eddy_Em",url="/forum/viewtopic.php?p=4138076#p4138076"]goto, естественно, - единственный лаконичный и вменяемый вариант.[/uquote]
Угу. Если делать только одну точку в пределах функции/метода то никаких проблем. У меня большой проект так сделан - в каждой функции точка exit: есть. Подсмотрел в библиотеке LwIP, а ее не дураки писали.

Re: "break to out" from for/switch

Добавлено: Пт дек 10, 2021 18:45:33
technik-1017
Можно сделать через массив указателей

Код: Выделить всё

#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
Dimon456
Как все сложно, еще и указатели влепили.
Если цикл 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
>TEHb<
Если вначале добавить #define XBATUT return то читаемость ещё увеличится.
Кажется, мы несколько по-разному восприняли задачу.

Re: "break to out" from for/switch

Добавлено: Сб дек 11, 2021 07:06:54
sunjob
Dimon456, фишка в том, что весь этот код
- чужой
- раскидан на несколько страниц
- напихан математико/эмпиричекими закидонами, нахреноверчен до нечитабельности

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

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

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

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