Страница 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() и плодить шушностей?!
все же уже найдено, самое оптимальное
или че?!

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

. Разве ж кто-то может запретить?
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 писал(а):красиво/очевидно/локонично
Если не нравится так, то себе делайте как душа лежит

. Разве ж кто-то может запретить?[/uquote]
дак в том и дело, нужно было "залитовать" многостраничный нахреновенчанный код, что бы не ахрененть от переделок и ни чего не сломать... случано...
вот и получается всего два очевидных варианта (коТ на скору лапу, мож че и спЁр лишнего)
Код: Выделить всё
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, фишка в том, что весь этот код
- чужой
- раскидан на несколько страниц
- напихан математико/эмпиричекими закидонами, нахреноверчен до нечитабельности
поэтому все "дополнения", "тяжелые модернизации" - ни как не катят, можно легко "сломать" математику, да и просто редактирвоать это "нечто" очень тяжело
поэтому (я для себя) выбрал наименьшее вмешательство
п.с. понятно дело, с нуля писать, это не разбираться в чужом коде
Ярослав555, согласен, если
goto локальный
