Важная информация
Страница 1 из 3 123 ПоследняяПоследняя
Показано с 1 по 10 из 22

Тема: Оператор выхода из цикла - дурной тон?

  1. #1 Оператор выхода из цикла - дурной тон? 
    Гуру Аватар для Абадябер
    Регистрация
    09.12.2010
    Адрес
    Беларусь, Минск
    Сообщений
    1,219
    Сказал(а) спасибо
    302
    Поблагодарили 176 раз(а) в 144 сообщениях
    Записей в блоге
    5
    Категорически не соглашусь с тем, что выход из цикла exit do является дурным тоном. В некоторых случаях это необходимый инструмент управления, мало того, он никоим образом не портит наглядность программы. А в том же turbo pascal есть процедура continue, которая имеет ту же природу - служит для удобства управления циклом.
    А вот циклы while wend давно являтся устаревшими (что говорит даже справка по qb), и необходимость в них почти отсутствует.о являтся устаревшими (что говорит даже справка по qb), и необходимость в них почти отсутствует.
    Дружба-магия-радость!
    Ответить с цитированием  
     

  2. #2  
    Модератор Аватар для pingvin
    Регистрация
    11.02.2011
    Сообщений
    389
    Сказал(а) спасибо
    80
    Поблагодарили 75 раз(а) в 48 сообщениях
    Хоть цикл while wend и считается устаревшим, но он очень удобный и полезный. В С он играет большую роль. Этот цикл очень удобен и полезен
    На этом месте могло быть Ваше "Спасибо"
    Ответить с цитированием  
     

  3. Пользователь сказал cпасибо:

    Dimon012 (21.08.2011)

  4. #3  
    Профи Аватар для Dimon012
    Регистрация
    09.02.2011
    Адрес
    Владивосток
    Сообщений
    850
    Сказал(а) спасибо
    29
    Поблагодарили 130 раз(а) в 108 сообщениях
    Записей в блоге
    3
    Цитата Сообщение от pingvin Посмотреть сообщение
    Хоть цикл while wend и считается устаревшим, но он очень удобный и полезный. В С он играет большую роль. Этот цикл очень удобен и полезен
    Вот абсолютно и полностью согласен!!! И сам всегда пользуюсь, т.к. просто.
    Ответить с цитированием  
     

  5. #4  
    Профи Аватар для Dimon012
    Регистрация
    09.02.2011
    Адрес
    Владивосток
    Сообщений
    850
    Сказал(а) спасибо
    29
    Поблагодарили 130 раз(а) в 108 сообщениях
    Записей в блоге
    3
    Цитата Сообщение от Абадябер Посмотреть сообщение
    Категорически не соглашусь с тем, что выход из цикла exit do является дурным тоном. В некоторых случаях это необходимый инструмент управления, мало того, он никоим образом не портит наглядность программы.
    Позвольте мне так же не согласиться! Во первых все же наглядность портит, ведь при структурных отступах видно начало DO и конец LOOP, а вот EXIT нужно искать в тексте. И кроме этого по моему скромному мнению цикл он по тому и цикл, что всегда выполняется целиком, и потом следует проверка повторения цикла! Да бывает удобно, если какое то дополнительное условие не было предусмотрено своевременно и всплыло потом, вот его удобно купировать выходом из середины... С моей точки зрения цикл это как функция, есть начало и конец и никаких выходов из середины (может быть несколько входов, но выход один). Или наконец представьте себе цикл FOR...NEXT, с выходом из середины, ведь может же пригодиться
    Последний раз редактировалось Dimon012; 21.08.2011 в 13:09.
    Ответить с цитированием  
     

  6. #5  
    Гуру Аватар для Абадябер
    Регистрация
    09.12.2010
    Адрес
    Беларусь, Минск
    Сообщений
    1,219
    Сказал(а) спасибо
    302
    Поблагодарили 176 раз(а) в 144 сообщениях
    Записей в блоге
    5
    Цикл while wend полностью заменяется аналогичным do while. При этом остается возможность сделать exit do. имхо в qb поддержка цикла с wend избыточна, и осталась лишь для совместимости с программами на старых версиях бейсика, вроде gw.
    Exit for также существует
    Если в цикле обрабатывается лишь пара условий, то конечно лучше проверять их в условии цикла. А если в цикле таких условий порядка 10-20, то оператор exit уже необходим
    Дружба-магия-радость!
    Ответить с цитированием  
     

  7. #6  
    Профи Аватар для Dimon012
    Регистрация
    09.02.2011
    Адрес
    Владивосток
    Сообщений
    850
    Сказал(а) спасибо
    29
    Поблагодарили 130 раз(а) в 108 сообщениях
    Записей в блоге
    3
    Цитата Сообщение от Абадябер Посмотреть сообщение
    Цикл while wend полностью заменяется аналогичным do while.
    Да я полностью согласен его называют устаревшим и его можно заменить DO WHILE, но он проще в написании, и в месте с циклом FOR охватывает 90-95% всех требующихся в программе циклов.
    Цитата Сообщение от Абадябер Посмотреть сообщение
    Если в цикле обрабатывается лишь пара условий, то конечно лучше проверять их в условии цикла. А если в цикле таких условий порядка 10-20, то оператор exit уже необходим
    Ну это вы батенька хватили! Я конечно не претендую на гордое звание программиста, но по моему скромному мнению, 10-20 условий выхода из цикла, говорят лишь о непродуманности структуры цикла и программы. Я еще соглашусь с таким количеством условий в SQL, но это отдельная песня, а для обычной программы думаю это перебор.

    Вообще как то мы увлеклись, боюсь от таких разговоров, наш новичок может уйти в перезагрузку
    Последний раз редактировалось Dimon012; 22.08.2011 в 07:44.
    Ответить с цитированием  
     

  8. #7  
    Гуру Аватар для Абадябер
    Регистрация
    09.12.2010
    Адрес
    Беларусь, Минск
    Сообщений
    1,219
    Сказал(а) спасибо
    302
    Поблагодарили 176 раз(а) в 144 сообщениях
    Записей в блоге
    5
    Цитата Сообщение от Dimon012 Посмотреть сообщение
    по моему скромному мнению, 10-20 условий выхода из цикла, говорят лишь о непродуманности структуры цикла и программы.
    По правде говоря, такая ситуация действительно существует. Фактически условий хоть и действительно много, но почти все они однотипные в моей программе. Я сам хоть и не считаю дурным тоном выход из цикла, однако согласен с тем, что гораздо гармоничнее цикл будет выглядеть без таковых. Сейчас я приведу вам пример своего цикла из моей программы LInt2. Если понадобиться, могу написать это же на бейсике. Если вы подскажете, как переписать этот же цикл, не используя выходы из цикла, или ограничив их применение, я с радостью возьму свои слова назад, посколько текущий вид этой подпрограммы с кучей дублирующихся кусков OnError Break меня самого не радует
    Фактически там 2 цикла, один наружный и один вложенный в него. Цикл не весь - его пришлось сократить, а то не отправлялось сообщение Этот цикл выполняет сгенерированный до этого байт-код программы на языке СТЕПЛЕР. В качестве оператора выхода из цикла служит Break, причем выходим мы из цикла For =). Сам факт, что если произошла ошибка, и была вызвана процедура OnError, то мы не можем продолжать исполнение цикла ни на команду, т.к в противном случае могут быть выполнены ошибочные действия, которые могут привести к краху программы. Не подскажете, как можно организовать работу подобного цикла таким образом, чтобы свести применение break к минимуму?

    Код pascal:
    While PI < BSI Do Begin
            Inc(PI);
            StI:= 1; Stack^[StI]:= 0;
            For I:= 1 To C_StrLen Do Begin
                Case BCode^[PI]^[I].FCode Of
                  TBC_None:
                    ;
                  TBC_IncStack:
                    Begin
                        Inc(StI);
                        If StI > C_StackSize Then Begin
                            OnError(E_StackOverflow);
                            Break;
                        End;
                        Stack^[StI]:= 0;
                    End;
                  TBC_AssignVar:
                    Begin
                        If StI < 2 Then Begin
                            OnError(E_StackEmpty);
                            Break;
                        End;
                        Dec(StI);
                        SetVar(Stack^[StI + 1], Stack^[StI]);
                        If Err <> E_Ok Then Break;
                    End;
                  TBC_ReadVar:
                    Begin
                        If StI < 1 Then Begin
                            OnError(E_StackEmpty);
                            Break;
                        End;
                        Stack^[StI]:= GetVar(Stack^[StI]);
                        If Err <> E_Ok Then Break;
                    End;
                  TBC_Random:
                    Begin
                        If StI < 1 Then Begin
                            OnError(E_StackEmpty);
                            Break;
                        End;
                        Stack^[StI]:= Random(Stack^[StI]);
                    End;
                  TBC_Add:
                    Begin
                        If StI < 2 Then Begin
                            OnError(E_StackEmpty);
                            Break;
                        End;
                        Stack^[StI - 1]:= Stack^[StI - 1] + Stack^[StI];
                        Dec(StI);
                    End;
                  TBC_Sub:
                    Begin
                        If StI < 2 Then Begin
                            OnError(E_StackEmpty);
                            Break;
                        End;
                        Stack^[StI - 1]:= Stack^[StI - 1] - Stack^[StI];
                        Dec(StI);
                    End;
                  TBC_Mul:
                    Begin
                        If StI < 2 Then Begin
                            OnError(E_StackEmpty);
                            Break;
                        End;
                        Stack^[StI - 1]:= Stack^[StI - 1] * Stack^[StI];
                        Dec(StI);
                    End;
                  TBC_Div:
                    Begin
                        If StI < 2 Then Begin
                            OnError(E_StackEmpty);
                            Break;
                        End;
                        If Stack^[StI] = 0 Then Begin
                            OnError(E_DivByZero);
                            Break;
                        End;
                        Stack^[StI - 1]:= Stack^[StI - 1] Div Stack^[StI];
                        Dec(StI);
                    End;
                  TBC_Mod:
                    Begin
                        If StI < 2 Then Begin
                            OnError(E_StackEmpty);
                            Break;
                        End;
                        If Stack^[StI] = 0 Then Begin
                            OnError(E_DivByZero);
                            Break;
                        End;
                        Stack^[StI - 1]:= Stack^[StI - 1] Mod Stack^[StI];
                        Dec(StI);
                    End;
                  TBC_Exe:
                    Begin
                        TempI:= Stack^[StI];
                        Dec(StI);
                        If StI < 1 Then Begin
                            OnError(E_StackEmpty);
                            Break;
                        End;
                        OldCode:= BCode^[PI]^[I];
                        OldCodeI:= I;
                        Case Char(TempI) Of
                          CT_Zero..CT_Nine:
                            Begin
                                BCode^[PI]^[I].FCode:= TBC_PushVal;
                                BCode^[PI]^[I].FOp:= TempI - Byte(CT_Zero);
                            End;
                          CT_IncStack, CT_IncStack2:
                            BCode^[PI]^[I].FCode:= TBC_IncStack;
                          CT_Add:
                            BCode^[PI]^[I].FCode:= TBC_Add;
                          CT_Sub:
                            BCode^[PI]^[I].FCode:= TBC_Sub;
                          CT_Mul:
                            BCode^[PI]^[I].FCode:= TBC_Mul;
                          CT_Div:
                            BCode^[PI]^[I].FCode:= TBC_Div;
                          CT_Mod:
                            BCode^[PI]^[I].FCode:= TBC_Mod;
                          CT_10:
                            BCode^[PI]^[I].FCode:= TBC_10;
                          CT_SqR:
                            BCode^[PI]^[I].FCode:= TBC_SqR;
                          CT_Power:
                            BCode^[PI]^[I].FCode:= TBC_Power;
                          CT_Sign:
                            BCode^[PI]^[I].FCode:= TBC_Sign;
                          CT_Random:
                            BCode^[PI]^[I].FCode:= TBC_Random;
                          CT_Let:
                            BCode^[PI]^[I].FCode:= TBC_ReadVar;
                          Else
                            Begin
                                OnError(E_UnknownModifyCmd);
                                Break;
                            End;
                        End;
                        Dec(I);
                    End;
                  TBC_Sign:
                    Begin
                        If StI < 1 Then Begin
                            OnError(E_StackEmpty);
                            Break;
                        End;
                        If Stack^[StI] > 0 Then
                            Stack^[StI]:= 1
                        Else
                            If Stack^[StI] < 0 Then Stack^[StI]:= -1;
                    End;
                  TBC_10:
                    Begin
                        If StI < 1 Then Begin
                            OnError(E_StackEmpty);
                            Break;
                        End;
                        Stack^[StI]:= Integer(Stack^[StI] = 0);
                    End;
                  TBC_SqR:
                    Begin
                        If StI < 1 Then Begin
                            OnError(E_StackEmpty);
                            Break;
                        End;
                        If Stack^[StI] < 0 Then Begin
                            OnError(E_DivByZero);
                            Break;
                        End;
                        Stack^[StI]:= Round(SqRt(Stack^[StI]));
                    End;
                  TBC_Power:
                    Begin
                        If StI < 2 Then Begin
                            OnError(E_StackEmpty);
                            Break;
                        End;
                        Stack^[StI - 1]:= IntPower(Stack^[StI - 1], Stack^[StI]);
                        Dec(StI);
                    End;
                  TBC_CondJump:
                    Begin
                        If StI < 1 Then Begin
                            OnError(E_StackEmpty);
                            Break;
                        End;
                        If Stack^[StI] = 0 Then Begin
                            TempI:= BCode^[PI]^[I].FOp;
                            If (TempI < 1) Or (TempI > BSI) Then OnError(E_WrongJmpAddr);
                            PI:= TempI;
                            Break;
                        End;
                    End;
                  TBC_WriteLn:
                    Begin
                        TempI:= BCode^[PI]^[I].FOp;
                        WriteLn(Copy(Prog^[Strs^[TempI].FSI], Strs^[TempI].FBegin, Strs^[TempI].FLen));
                    End;
                  TBC_EOL:
                    Break;
                  Else
                    Begin
                        OnError(E_UnknownCmd);
                        Break;
                    End;
                End;
            End;
            If OldCodeI <> 0 Then Begin
                BCode^[PI]^[OldCodeI]:= OldCode;
                OldCodeI:= 0;
            End;
            If Err <> E_Ok Then Break;
        End;

    Только что еще раз просмотрел весь цикл, и появилась идея, как избавиться от этой кучи, и оставить в цикле только 1 Break =) А именно, добавить после каждой команды If условие Then Begin OnError(...) Break End; ветку Else. Придется еще в конце цикла For добавить одно условие по выходу break: If Err <> E_Ok Then Break; Это лучше чем много, да и запись скорее всего будет короче, хоть и несколько медленнее будет работать программа. С другой стороны, есть ли возможность выразить этот цикл вообще без break? =)
    Последний раз редактировалось Абадябер; 23.08.2011 в 01:33.
    Дружба-магия-радость!
    Ответить с цитированием  
     

  9. #8  
    Профи Аватар для Dimon012
    Регистрация
    09.02.2011
    Адрес
    Владивосток
    Сообщений
    850
    Сказал(а) спасибо
    29
    Поблагодарили 130 раз(а) в 108 сообщениях
    Записей в блоге
    3
    Ну конечно же, я не говорю о том, что применение выхода из середины цикла, нельзя применять никогда! Жизнь слишком разнообразна, что бы можно было изобрести какие либо правила, а потом всю жизнь им спокойно следовать. (в данном случае я трактую программирование как элемент жизни) Но продолжим, все мы (ну большинство) призываем писать "красивые" программы, не помню, кто сказал "красота это целесообразность!", вот из этого и следует исходить, в Вашей программе множество выходов из тела цикла, но с другой стороны все они оформлены единообразно, следовательно разобравшись с одним элементом можно по шаблону действовать с другим. С другой стороны эта часть программы излишне сложна, я не пророк, но видимо эта часть не проектировалась заранее, а будучи вначале простой, в дальнейшем получала неоднократные уточнения, которые вели к усложнению и в итоге мы имеем то что имеем. Думаю если сейчас переосмыслить работу этого куска то можно сделать все гораздо проще, однако целесообразно ли это делать если и так все работает? Вот если Вас попросят подправить это программу лет через пять, тогда возникает другая целесообразность. В целом я исхожу из того, что слишком сложный код (или же сложный агрегат, или же сложная система) это место появления сложно обнаруживаемых ошибок, и все из за сложности анализа функционирования системы. Есть замечательная книга Эдварда Хатчингсома, о американском физике Феймане, которая так и называется "Вы, конечно, шутите, Мистер Фейнман!", вот в ней описан эпизод, когда этот физик приезжает на завод, работающий на создание ядерной бомбы, ему показывают чертежи, а он наугад тыкая пальцем показывает два клапана и специалисты приходят к мнению, что это приведет к взрыву. После этого все считают его гением, который понял принцип работы системы за 5 минут... В последствии Фейман объяснял, что он ничего не понял, посто исходил из того что система сложна и анализ взаимодействия всех ее элементов невозможен. Будем проще
    Последний раз редактировалось Dimon012; 23.08.2011 в 04:48.
    Ответить с цитированием  
     

  10. 2 пользователя(ей) сказали cпасибо:

    pingvin (23.08.2011), Абадябер (23.08.2011)

  11. #9  
    Супер модератор Аватар для >Quiet Snow<
    Регистрация
    11.04.2011
    Адрес
    Планета земля
    Сообщений
    3,911
    Сказал(а) спасибо
    1,841
    Поблагодарили 976 раз(а) в 834 сообщениях
    Записей в блоге
    1
    Дурной тон, не дурной тон, каждый пишет как ему удобнее, рамок тут нет и не надо никого загонять в рамки, функционал есть - есть, ВСЁ, разговор окончен. Кто хочет, чтобы его программа читалась, сделает, комментарии кому? Отступы кому? Запрещено перед каждой функцией кратко описывать алгоритм её работы? По поводу старости, сам QB уже история, что вы хотите от компилятора 80-х годов. По поводу структуры: тому кто хочет "идеальную", "вылизанную" программу, думаю стоит попариться, ибо кодирование это фигня по сравнению с алгоритмизацией, придумать хороший алгоритм и грамотно его структурировать действительно сложно.

    по моему скромному мнению, 10-20 условий выхода из цикла, говорят лишь о непродуманности структуры цикла и программы.
    В теории всё так: и GOTO во вред и непродуманность, а на практике? Перестроить логику мелкой проги строк на 200-300 и средней на несколько тысяч? Даже мелкую долго реструктурировать, да и велика вероятность наделать багов. У кого-то много лишнего времени?
    Давайте взглянем правде в глаза, кому нужен весь этот фетиш, когда основная задача написать полезную программу, в коде которой никто рыться не будет(т.е. с закрытым кодом или просто без расчёта на это, т.е. нужен только исполняемый .exe).
    Ответить с цитированием  
     

  12. Пользователь сказал cпасибо:

    Абадябер (24.08.2011)

  13. #10  
    Профи Аватар для Dispetcher14
    Регистрация
    12.12.2010
    Адрес
    Раменское
    Сообщений
    597
    Сказал(а) спасибо
    35
    Поблагодарили 68 раз(а) в 56 сообщениях
    Записей в блоге
    13
    Собственно вопрос такой: а с чего вы взяли, что exit - дурной тон? Всмысле откуда пошла вообще такая инфа?
    "Спокойно, Маша, я Дубровский" (с) Дубровский, "Дубровский".
    Ответить с цитированием  
     

Страница 1 из 3 123 ПоследняяПоследняя
Информация о теме
Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. Графы. Поиск простого цикла
    от amor1k в разделе C/C++
    Ответов: 5
    Последнее сообщение: 27.09.2012, 04:41
  2. Очень надо,помогите!Оператор CASE
    от FOTE в разделе Turbo Pascal
    Ответов: 6
    Последнее сообщение: 14.02.2012, 22:28
  3. Оператор WINDOW
    от pingvin в разделе QBasic
    Ответов: 2
    Последнее сообщение: 11.02.2011, 21:21
Ваши права
  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •