Поток управления

редактировать

В информатике, поток управления (или поток управления ) - это порядок, в котором в отдельных инструкции, инструкции или вызовы функций из императивной программы выполнено или оценено. Акцент на явном потоке управления отличает язык императивного программирования от языка декларативного программирования.

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

Набор операторов, в свою очередь, обычно структурирован как блок , которые включают группирования также определяют лексическую область .

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

На уровне машинного языка или языка ассемблера инструкции потока управления обычно работают путем изменения программного счетчика. Для некоторых центральных процессоров (ЦП) единственными доступными инструкциями потока управления условными или безусловными инструкциями перехода, также называемые переходами.

Содержание

  • 1 Категории
  • 2 Примитивы
    • 2.1 Метки
    • 2.2 Goto
    • 2.3 Подпрограммы
    • 2.4 Последовательность
  • 3 Минимальный структурированный поток управления
  • 4 Управляющие структуры на практике
  • 5 Выбор
    • 5.1 Операторы If-then- (else)
    • 5.2 Операторы Case и Switch
  • 6 Циклов
    • 6.1 Циклы с управлением счетом
    • 6.2 Циклы с управлением по условию
    • 6.3 Циклы, управляемые коллекцией
    • 6.4 Общая итерация
    • 6.5 Бесконечные циклы
    • 6.6 Продолжение со следующей итерацией
    • 6.7 Повторить текущую итерацию
    • 6.8 Повторный запуск цикла
    • 6.9 Ранний выход из циклов
    • 6.10 Цикл варианты и инварианты
    • 6.11 Подъязыкный цикл
    • 6.12 Таблица перекрестных ссылок системы цикла
  • 7 Структурированный нелокальный поток управления
    • 7.1 Условия
    • 7.2 Исключения
    • 7.3 Продолжение
    • 7.4 Асинхрон
    • 7.5 Генераторы
    • 7.6 Сопрограммы
    • 7.7 Перекрестная ссылка нелокального потока управления
  • 8 Предлагаемые уп равляющие структуры
    • 8.1 Цикл с тестом в середине
    • 8.2 Множественный ранний выход / выход из вложенных циклов
  • 9 Безопасность
  • 10 См. Также
  • 11 Ссылки
  • 12 Дополнительная литература
  • 13 Внешние ссылки

Категории

A блок-схема, показывающая поток управления.

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

  • Продолжение в другом операторе (безусловное ветвление или переход)
  • Выполнение набора операторов только при соблюдении некоторого условия (выбор - т. е. условная ветвь )
  • Выполнение набора операторов ноль или более раз, пока не будет выполнено какое-либо условие (например, цикл - то же, что условная ветвь )
  • Выполнение набора удаленных операторов после потока управления обычно возвращает (подпрограммы, сопрограммы и продолжения )
  • Остановка программы, предотвращение продолжения (безусловная остановка)

Примитивы

Метки

A метка - это явное имя или номер, присвоенный фиксированной позиции в исходном коде, который может ссылаться поток управления операторы, появляющиеся в другом месте исходного кода. Метка отмечает позицию в исходном коде и не имеет никакого другого эффекта.

Номера строк альтернативной именованной метке, используемой на некоторых языках (например, BASIC ). Это целые числа, помещенные в начало каждой строки текста в исходном коде. Языки в каждой строке, которые они используются, часто накладывают ограничение. Например, в BASIC:

10 LET X = 3 20 PRINT X

На других языках, таких как C и Ada, метка является указателем , обычно появляется в начале строки и сразу после него ставится двоеточие. Например, в C:

Успех: printf («Операция прошла успешно. \ N»);

На языке АЛГОЛ 60 ены как целые числа, так и разрешатели в качестве меток (оба связаны двоеточиями со следующим утверждением), но немногие, если вообще любые другие варианты АЛГОЛ допускают целые число. Ранние компиляторы Fortran допускают только целые числа в качестве меток. Начиная с Fortran-90, также разрешены буквенно-цифровые метки.

Goto

Оператор goto (комбинация английских слов go и до и произносится соответствующим образом) является основным формой безусловного передачи управления.

Используемое слово может быть в или нижнем регистре в зависимости от языка, обычно оно записывается как:

goto label

Эффект оператора goto заключается в том, чтобы вызвать выполнение следующего оператора, который должен быть оператором появляющимся на (или сразу после) данным оператором.

операторы Goto считались компьютерщиками, особенно Дейкстра.

Подпрограммы

Терминология для подпрограмм рассматривается; в качестве альтернативы они могут называться подпрограммами, процедурами, функциями (особенно если они возвращают результаты) или методами (если они принадлежат к классам или классам типов ).

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

Сегодня подпрограммы часто используются, чтобы помочь сделать более структурированной структуры, например, путем изоляции некоторого алгоритма или сокрытия некоторого метода доступа к данным. Если над одной программой работают многие программисты, подпрограммы включают один из видов модульности, который может помочь разделить работу.

Последовательность

В структурированном программировании упорядоченная последовательность последовательных команд считается одной из базовых структур управления, которая используется как строительный блок для программ наряду с итерацией, рекурсией и выбором.

Минимальный структурированный поток управления

В мае 1966 года Бём и Якопини опубликовали статью в «Коммуникациях ACM», в которой было показано, что любую программу с goto можно преобразовать в форма без включения, включающая только выбор (ЕСЛИ ТО ЕЩЕ) и циклы (WHILE условие DO xxx), возможно, с дублированным кодом и / или добавлением логических чисел (флаги true / false). Позднее авторы показывают, что выбор можно заменить циклами (и тем более логическими переменными).

То, что такой минимализм возможен, не означает, что он обязательно желателен; в конце концов, компьютерам теоретически требуется только одна машинная инструкция (вычтите одно число из другого и выполните переход, если результат отрицательный), но на практике компьютеры имеют десятки или даже сотни машинных инструкций.

Статья Бема и Якопини показала, что все программы могут быть без перехода. Другое исследование показывает, что управляющие структуры с одним входом намного легче понять, чем любую другую форму управления. Другими словами, их можно было компоновать. (Более поздние разработки, такие как нестрогуемие языки программирования - в последнее время составные программные транзакции - продолжили эту стратегию, компоненты программ еще более свободно компонентами.)

Некоторые ученые избрали пуристический подход к результату, что даже такие инструкции, как breakи returnиз середины цикла, являются плохой практикой, поскольку они не нужны в доказательстве Бема- Якопини, и поэтому они выступали за то, чтобы все петли имели первую точку выхода. Этот пуристический подход воплощен на языке Pascal (использовать в 1968–1969), который до середины 1990-х годов был предпочтительным инструментом для обучения вводному программированию в академических кругах. Прямое применение теоремы Бема-Якопини может привести к введению дополнительных локальных чисел в структурированную диаграмму, а также может привести к некоторому дублированию кода . На Паскаль влияет обе эти проблемы, и согласно эмпирическим исследованиям, процитированным Эриком С. Робертсом, студентам-программистам было трудно определить правильные решения на Паскале для нескольких проблем, включая написание функций для поиска элемента в массив. Исследование 1980 года Генри Шапиро, цитируемое Робертсом, показало, что было дано только 20% испытуемых, в то время как один из испытуемых не написал неправильный код для проблемы, если бы разрешили написать ответ из середина цикла.

Управляющие структуры на практике

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

  • Без последнего ключевого слова: АЛГОЛ 60, C, C ++, Haskell, Java, Pascal, Perl, PHP, PL / I, Python, PowerShell. Таким языкам нужен какой-то способ группировки операторов вместе:
  • Последнее ключевое слово: Ada, ALGOL 68, Modula-2, Fortran 77, Visual Basic. Формы последнего ключевого слова различаются:
    • Ada: последнее ключевое слово - end+ пробел + начальное конкретное слово, например, if... конец, если, цикл... конец цикла
    • АЛГОЛ 68, Mythryl: начальное слово в обратном порядке, например, if... fi, case... esac
    • Fortran 77: последнее слово END+ начальное специальное слово, например, IF... ENDIF, DO... ENDDO
    • Modula-2: то же самое последнее слово ENDдля всего
    • Visual Basic: каждая структура управления имеет собственное ключевое слово. Если... Конец Если; Для... Далее; Do... Цикл; While... Wend

Choice

Операторы If-then- (else)

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

  • ЕСЛИ..ПЕРЕЙТИ. Форма, найденная в неструктурированных языках, имитирующая типичная инструкция машинного кода, перескакивает на (GOTO) метку или номер строки при выполнении условий.
  • ЕСЛИ..ТОГДА.. (ENDIF). Вместо того, чтобы ограничиваться переходом, любой простой оператор или вложенный блок может следовать за ключевым словом THEN. Это структурированная форма.
  • ЕСЛИ..ТЕН..ЭЛЬСЕ.. (КОНЕЦ). Должно быть выполнено то же, что и выше, но со вторым наступлением, которое должно быть выполнено, если условие ложно. Это одна из самых распространенных форм с множеством вариаций. Некоторым требуется терминал ENDIF, другим - нет. C и родственные языки не требуют ключевого слова терминала или 'then', но требуют скобок вокруг условий.
  • Условные операторы могут быть и часто вложены в другие условные операторы. Некоторые языки позволяют объединять ELSEи IFв ELSEIF, избегая необходимости иметь серию ENDIFили других заключительных операторов в конценого оператора.
Паскаль :Ада :C :Сценарий оболочки :Python :Лисп :
если a>0, то Writeln ("да") else Writeln ("нет");
если a>0, то Put_Line ("да"); иначе Put_Line ("нет"); конец, если;
если (а>0) {printf ("да"); } else {printf ("нет"); }
если [$ a -gt 0]; затем эхо "да" иначе эхо "нет" fi
если a>0: print ("да") else: print ("нет")
(princ (if (plusp a) "да" "нет"))

Менее распространенные варианты включают:

  • Некоторые языки, такие как Fortran, имеют трехстороннюю арифметику или , если, проверка того, является ли числовым положительным или отрицательным. или ноль.
  • На некоторых языках есть функциональная форма оператора если, например cond.
  • На некоторых языках есть оператор форма оператора if, такая как тернарный оператор языка C.
  • Perl дополняет C-стиль ifс , когдаи , if.
  • Smalltalk не использует сообщения ifTrueи ifFalseдля реализации условных выражений, а не любую фундаментальную языковую конструкцию.

Операторы case и switch

Switch операторы (или операторы case, или многосторонние ветви) сравнивают заданное значение с указанными константами и предпринимают действия в соответствии с первой совпадающей константой. Обычно существует положение о том, что действие по умолчанию («иначе», «иначе») должно быть, если совпадение не было успешным. Операторы Switch могут допускать оптимизацию компилятора, например, таблицы поиска. В динамических языков могут не ограничиваться константными выражениями и распространяться на сопоставление с образцом, как в примере сценария оболочки справа, где *)реализует регистр по умолчанию как glob, соответствующий любой строке. Логика регистратора также может быть реализована в функциональной форме, как в инструкции декодироватьв SQL.

Паскаль :Ада :C :Сценарий оболочки :Лисп :
case someChar of 'a': actionOnA; 'x': действиеOnX; 'y', 'z': actionOnYandZ; еще действиеOnNoMatch; конец;
case someChar - это когда 'a' =>actionOnA; когда 'x' =>actionOnX; когда 'y' | 'z' =>actionOnYandZ; когда другие =>actionOnNoMatch; конец;
переключатель (someChar) {case 'a': actionOnA; перемена; case 'x': actionOnX; перемена; case 'y': case 'z': actionOnYandZ; перемена; по умолчанию: actionOnNoMatch; }
case $ someChar в a) actionOnA ;; x) actionOnX ;; [yz]) actionOnYandZ ;; *) actionOnNoMatch ;; esac
(case some-char ((# \ a) action-on-a) ((# \ x) action-on-x) ((# \ y # \ z) action-on-y-and- z) (иначе действие при отсутствии совпадения))

Циклы

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

на языках функционального программирования, таких как Haskell и Scheme, циклы могут быть выражены с помощью рекурсии или с фиксированной точкой. итерация, а не явные конструкции цикла. Хвостовая рекурсия - это частный случай рекурсии, который можно легко преобразовать в итерацию.

Циклы с управлением счетчиком

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

ДЛЯ I = 1 TO N | для I: = 1 toN doначало xxx | xxx NEXT I | конец ; -------------------------------------------------- ---------- DO I = 1, N | для (I = 1; I <=N; ++I) { xxx | xxx END DO | }

В этих примерах, если N < 1 then the body of loop may execute once (with I having value 1) or not at all, depending on the programming language.

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

для X: = 0,1, шаг 0,1 до 1,0 do

может повторяться 9 или 10 раз, в зависимости от ошибок округления и / или версии оборудования и / или компилятора. Кроме того, если приращение X происходит путем повторного сложения, накопленные округления означать означать, что значение X на каждой итерации может значительно отличаться от ожидаемой последовательности. 0.1, 0.2, 0.3,..., 1.0.

Циклы, управляемые условием

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

ДЕЛАТЬ ПОКА (тест) | повторить ххх | xxx LOOP | до испытания; ---------------------------------------------- пока (тест) {| делать ххх | xxx} | в то время как (тест);

A Control Break - это метод обнаружения изменений значения, используя в обычных циклах для запуска обработки для групп значений. Значения отслеживаются в цикле, и изменение перенаправляет поток программы на обработку связанного с ними группового события.

DO UNTIL (конец файла) IF new-zipcode <>current-zipcode display_tally (current-zipcode, zipcount) current-zipcode = new-zipcode zipcount = 0 ENDIF zipcount ++ LOOP

Циклы, управляемые коллекцией

Несколько языков программирования (например, Ada, D, C ++ 11, Smalltalk, PHP, Perl, Object Pascal, Java, C#, MATLAB, Visual Basic, Ruby, Python, JavaScript, Fortran 95 и новее) имеют специальные конструкции, которые позволяют неявный цикл по всем элементам массива или всем членам набора или коллекции.

someCollection do : [: eachElement | xxx].
для Элемент в Коллекции doначало xxx конец ; foreach (item; myCollection) {xxx} foreach someArray {xxx} foreach ($ someArray as $ k =>$ v) {xxx} Коллекция coll; для (String s: coll) {} foreach (string s inmyStringCollection) {xxx} someCollection | ForEach-Object {$ _}
forall (index = first: last: step...)

Scala имеет for-expression, которые обобщают циклы, управляемые коллекцией, а также поддерживает другие варианты использования, такие как асинхронное программирование. Haskell имеет do-выражения и понимания, которые вместе предоставляют функции, аналогичные функциям for в Scala.

Общая итерация

Могут использоваться общие конструкции итерации, такие как для оператораязыка C и doформы Common Lisp для выражения любого из вышеперечисленных видов циклов и других, таких как параллельный цикл по некоторому количеству коллекций. Там, где может использоваться более конкретная конструкция цикла, она обычно предпочтительнее общей конструкции итерации, поскольку она часто делает цель выражения более ясной.

Бесконечные циклы

Бесконечные циклы используются для обеспечения того, чтобы программный сегмент зацикливался вечно или до тех пор, пока не возникнет исключительное условие, такое как ошибка. Например, программа, управляемая событиями (такая как сервер ), должна зацикливаться вечно, обрабатывая события по мере их возникновения,останавливаясь только тогда, когда процесс завершается оператором.

Бесконечные циклы могут быть реализованы с использованием других конструкций потока управления. Чаще всего в неструктурированном программировании это возврат вверх (goto), тогда как в структурированном программировании это неопределенный цикл (цикл while), для которого задано никогда не заканчиваться, либо путем исключения условий, либо путем явной установки его в true, как пока (правда).... На некоторых языках есть специальные конструкции для бесконечных циклов, обычно путем исключения условий из неопределенного цикла. Примеры включают Ada (цикл... конец цикла), Fortran (DO... END DO), Go (для {...}), и Ruby (цикл do... end).

Часто бесконечный цикл непреднамеренно создается из-за ошибки программирования в управляемом условием, при этом условии цикла переменные, которые никогда не изменяются внутри цикла.

Продолжение со следующей итерацией

Иногда в тележурнале возникает пропустить оставшуюся часть тела и продолжить следующую итерацию цикла. Некоторые языки предоставляют такой оператор, как продолжить(для многих языков), пропуститьили следующий(Perl и Ruby), которые будут делать это. Результатом является преждевременное завершение самого внутреннего цикла, а затем возобновление в обычном режиме со следующей итерацией. Результатом будет досрочное завершение всего цикла.

Повторить текущую итерацию

Некоторые языки, такие как Perl и Ruby, имеют оператор redo, который перезапускает текущую итерацию с самого начала.

Цикл перезапуска

Ruby имеет оператор retry, который перезапускает весь цикл с начальной итерации.

Ранний выход из циклов

При использовании цикла с управляемым счетчиком для поиска по таблице может быть желательно поиск остановить, как только будет найден требуемый элемент. Некоторые языки программирования программирования такие инструкции, как break(для многих языков), Exit(Visual Basic) или last(Perl), результатом является завершение текущего цикла немедленно и передать управление оператору сразу после этого цикла. Другой термин для циклов раннего выхода - половина цикла.

Следующий пример выполнен в Ада, поддерживает как ранний выход из циклов, так и циклы с тестом в среднем. Сравнение обоих фрагментов кода покажет разницу: ранний выход должен сочетаться с оператором, если, в то время как условие в середине является автономной конструкцией.

с Ada.Text IO; с Ada.Integer Text IO; процедура Print_Squares - X: Integer; begin Read_Data: loop Ada.Integer Text IO.Get (X); выйти из Read_Data, когда X = 0; Ada.Text IO.Put (X * X); Ada.Text IO.New_Line; конец цикла Read_Data; конец Print_Squares;

Python поддерживает условное выполнение кода в зависимости от того, был ли цикл завершен раньше (с помощью оператора break) или нет с помощью предложения else с циклом. Например,

для n в set_of_numbers: if isprime (n): print («Набор содержит простое число») break else: print («Набор не содержит простых чисел»)

else Предложениев В приведенном выше примере используется оператором для, а не с внутренним оператором , если. Оба цикла Python дляи , в то время какпериод такое предложение else, которое выполняется только в том случае, если не произошло раннего выхода из цикла.

Некоторые циклы выход из вложенных; в теоретических кругах это называется многоуровневыми перерывами. Один из распространенных способов использования - поиск в многомерной таблице. Это можно сделать либо с помощью многоуровневых разрывов (из N уровней), как в bash и PHP, либо с помощью помеченных разрывов (разрыв и продолжение с заданной меткой), как в Java и Perl. Альтернативы многоуровневым разрывам включают одиночные разрывы вместе с выходным состоянием, который проверяется для выхода на другой уровень; исключения, которые вылавливаются на разбитом уровне; размещение вложенных циклов в функции и использование возврата для завершения всего вложенного цикла; или используя метку и инструкцию goto. C не включает многоуровневый разрыв, и обычная альтернатива - использовать goto для реализации помеченного разрыва. Python не имеет многоуровневого прерывания или продолжения - это было предложено в PEP 3136 и отклонено на том основании, что дополнительная сложность не стоит редкого законного использования.

Понятие многоуровневого -уровневые разрывы некоторый интерес в теоретической информатике, потому что они порождают то, что сегодня называется иерархией Косараджу. В 1973 С. Рао Косараджу уточнил теорему о структурированной программе, что можно избежать добавления дополнительных чисел в структурированном программировании, если разрешены многоуровневые разрывы произвольной глубины из циклов. Существующая программа строгой иерархии программ: для каждого целого числа существует программа, содержащая многоуровневый разрыв, которую нельзя переписать с многоуровневыми разрывами глубже, меньше без добавления дополнительных переменных.

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

В своем учебнике 2004 года Дэвид Ватт использует понятие секвенсора Теннента, чтобы объяснить сходство между многоуровыми разрывами и операторами возврата. Уотт отмечает, что класс секвенсоров, известные как управляющие секвенсоры, определяемый как «секвенсор, который завершает выполнение команды или процедуры, содержащий текст», включает как разрывы из циклов (включая многоуровневые разрывы), так и операторы возврата. Однако, как обычно реализовано, секвенсоры могут также не возвращать (возвращаемое) значение, тогда как секвенсор прерывания, реализованный на современных языках, обычно не может.

Варианты и инварианты цикла

Варианты цикла и инварианты цикла используются для выражения правильности циклов.

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

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

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

подъязыке цикла

диалекты Лиспа специальный обширный подъязык для описания циклов. Ранний пример можно найти в Конверсионном Лиспе Интерлиспе. Common Lisp предоставляет цикл цикла, который реализует такой подъязык.

Таблица перекрестных ссылок системы цикла

Язык программирования условныйциклранний выходпродолжение циклаповторитьповторитьсредства исправления
началосерединаконецколичествосборобщийбесконечныйвариантинвариант
Ada ДаДаДаДамассивыНетДаглубоко вложенныеНет
APL ДаНетДаДаДаДаДас глубокой вложенностьюДаНетНет
C ДаНетДаНетНетДаНетглубоко вложенныйглубоко вложенныйНет
C ++ ДаНетДаНетДаДаНетглубоко вложенныйглубоко вложенныйНет
C# ДаНетДаНетДаДаНетглубоко вложенныйглубоко вложенный
COBOL ДаНетДаДаНетДаНетглубоко вложенныйглубоко вложенныйНет
Common Lisp ДаДаДаДатолько встроенныйДаДаглубоко вложенныйНет
D ДаНетДаДаДаДаДаглубоко вложенныйглубоко вложенныйНет
Eiffel ДаНетНетДаДаДаНетодин уровеньНетНетНеттолько целое числоДа
F# ДаНетНетДаДаНетНетНетНетНет
FORTRAN 77 ДаНетНетДаНетНетНетодин уровеньДа
Fortran 90 ДаНетНетДаНетНетДаглубоко вложенныйДа
Fortran 95 и более поздние версииДаНетНетДамассивыНетДаглубоко вложенныеДа
Haskell НетНетНетНетДаНетДаНетНетНет
Java ДаНетДаНетДаДаНетНет вложенныйглубоко вложенныйНетнероднойнеродной
JavaScript ДаНетДаНетДаДаНетглубоко вложенныйглубоко вложенныйНет
ЕстественныйДаДаДаДаНетДаДаДаДаДаНет
OCaml ДаНетНетДамассивы, спискиНетНетНетНетНет
PHP ДаНетДаНетДаДаНетглубоко вложенныйглубоко вложенныйНет
Perl ДаНетДаНетДаДаНетглубоко вложенныйглубоко вложенныйДа
Python ДаНетНетНетДаНетНетглубоко вложенныйглубоко вложенныйНет
REBOL НетДаДаДаДаНетДаодин уровеньНетНет
Руби ДаНетДаДаДаНетДаглубоко вложенныйглубоко вложенныйДаДа
Standard ML ДаНетНетНетмассивы, спискиНетНетНетНетНет
Visual Basic.NET ДаНетДаДаДаНетДаодин уровень на типе петлиодин уровень на типе петли
PowerShell ДаНетДаНетДаДаНет?Да
  1. while (true)не считается бесконечным циклом для этой цели, потому что это не специальная языковая структура.
  2. C for (init; контрольная работа; инкремент)цикл - это общая конструкция цикла, а не подсчет, хотя он часто используется для этого.
  3. Глубокие разрывы могут быть выполнены в APL, C, C ++ и C # с помощью меток и переходов.
  4. Итерация по объектам была добавлена ​​ в PHP 5.
  5. Цикл подсчета можно смоделировать, перебирая увеличивающийся список или генератор, например, Python range ().
  6. Deep разрывы могут быть выполнены с помощью обработки исключений.
  7. Не существует специальной конструкции, поскольку для этого можно использовать функцию while.
  8. Специальной конструкции нет, но пользователи могут определять общие функции цикла.
  9. Стандарт C ++ 11 представил на основе диапазона для. В STL есть функция std::for_eachtemplate, которая может выполнять итерацию по контейнерам STL и вызывать унарный функция для каждого элемента. Функциональные возможности также могут быть сконструированы как макрос для этих контейнеров.
  10. Цикл, управляемый подсчетом, осуществляется путем итерации через целочисленный интервал; ранний выход путем включения дополнительного условия для выхода.
  11. Eiffel поддерживает зарезервированное слово retry, однако оно используется в обработке исключений, а не в управлении циклом.
  12. Требуется Язык моделирования поведения Java Modeling Language (JML).
  13. Требует, чтобы варианты цикла были целыми числами; трансфинитные варианты не поддерживаются. [1]
  14. D поддерживает бесконечные коллекции и возможность итерации по этим коллекциям. Для этого не требуется никакой специальной конструкции.
  15. Глубокие разрывы могут быть достигнуты с помощью GO TOи процедур.
  16. Common Lisp предшествует концепции универсального типа коллекции.

Структурированный нелокальный поток управления

Многие языки программирования, особенно те, которые предпочитают более динамические стили программирования, предлагают конструкции для нелокального потока управления. Это заставляет поток выполнения выскакивать из заданного контекста и возобновляться в какой-то заранее заявленный момент. Условия, исключения и продолжения - это три распространенных типа нелокальных управляющих конструкций; существуют и более экзотические, такие как генераторы, сопрограммы и ключевое слово async.

Условия

PL / I имеет около 22 стандартных условий (например, ZERODIVIDE SUBSCRIPTRANGE ENDFILE), которые могут быть вызваны и которые могут быть перехвачены: могут быть условия ON; Программисты также могут определять и использовать свои собственные именованные условия.

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

К сожалению, некоторые реализации использовали значительные накладные расходы как в пространство, так и во времени (особенно SUBSCRIPTRANGE).

Общие примеры синтаксиса:

ONусловие GOTO метка

Исключения

На современных языках есть специализированная структурированная конструкция для обработки исключений, которая не зависит от использование GOTOили (многоурового) прерывает или возвращает. Например, в C ++ можно написать:

try {xxx1 // Где-то здесь xxx2 // use: '' 'throw' '' someValue; xxx3} catch (someClass someId) {// поймать значение someClass actionForSomeClass} catch (someType anotherId) {// поймать значение someType actionForSomeType} catch (...) {// поймать то, что еще не было поймано actionForAnythingElse}

Любое количество и разнообразие предложений catchможно использовать выше. Если нет catch, соответствующему конкретному throw, управление просачивается обратно через вызовы подпрограмм и / или вложенные блоки до тех пор, пока не будет найден соответствующий catchили до конца сообщением об ошибке.

Благодаря влиянию C ++, catch- ключевое слово, зарезервированное для объявления обработчика исключений сопоставления с образцом в других популярных сегодня языках, таких как Java или C #. Некоторые другие языки, такие как Ada, используют ключевое слово исключениедля введения обработчика исключений, а могут даже использовать другое слово (прив Ada) для сопоставления с образцом. Некоторые языки, такие как AppleScript, включают заполнители в синтаксис обработчика исключений для автоматического извлечения фрагментов информации при возникновении исключения. Пример подхода такой конструкции конструкции при ошибкеиз AppleScript:

пример установить для myNumber значение myNumber / 0 при ошибке e число от f до t частичный результат pr if (e = «Невозможно разделить на ноль»), затем отобразите диалоговое окно «Вы не должны этого делать» end try

В учебнике Дэвида Ватта 2004 г. также анализируется обработка исключений в этой статье в разделе о раннем выходе из циклов. Ватт отмечает, что ненормальная ситуация, обычно представленная арифметическим переполнением или ошибками ввода / вывода вывода, например, файл не найден, является своего рода ошибкой, которая «создается в некотором программном модуле низкого уровня, но [для которой] »Например, программа может содержать несколько программ для чтения файлов, но действие, которое выполняется выполнить, когда файл не найден, зависит от этой (цели), о котором идет речь в программе, и, следовательно, процедура обработки ненормальной ситуации не может находиться в системном коде нижнего уровня. Уоттс далее отмечает, что введение тестирования флагов состояния в вызывающей программе, как это повлечет за структурированное программирование с одним выходом или секвенсоры возврата (с выполнением выходами), приводит к ситуации, когда «приложение имеет тенденцию быть загроможденным тестированием флагов состоян ия» и что «программист может по забывчивости или лениво пропустить проверку флага состояния. Фактически, ненормальные ситуации, представленные флагами состояния, по умолчанию игнорируются! »Ватт отмечает, что в отличие от тестирования флагов состояния, исключают противоположное поведение по умолчанию , вызывая завершение программы, если программист явно не обработан исключение каким-либо образом, возможно, добавлен явный код для его игнорирования. Основываясь на этих аргументах, ватт приходит к выводу, что секвенсоры перехода или управляющие не подходят, как выделенный секвенсор исключений с семантикой, рассмотренной выше.

В Object Pascal, D, Java, C # и Python a наконец, предложениеможно добавить в конструкцию публикации. Независимо от того, как контроль оставляет iPad, код внутри предложения наконецгарантированно выполнится. Это полезно при написании кода, который должен освободить дорогостоящий ресурс (например, открытый файл или соединение с базой данных) после завершения обработки:

FileStream stm = null; // Пример C # try {stm = new FileStream ("logfile.txt", FileMode.Create); вернуть ProcessStuff (stm); // может вызвать исключение} finally {if (stm! = null) stm.Close (); }

Мне этот шаблон распространен, C # имеет особый синтаксис:

using (var stm = new FileStream ("logfile.txt", FileMode.Create)) {return ProcessStuff (stm); // может вызвать исключение}

После выхода из с помощью-блока компилятор, что объект stmосвобожден, эффективно привязывая переменную к файловый поток, абстрагируясь от побочных эффектов инициализации и освобождения файла. Python с оператороми аргумент блока Ruby для File.openиспользуются с аналогичным эффектом.

Все указанные выше параметры определяют стандартные исключения и обстоятельства, при которых они возникают. Пользователи могут создать собственные исключения; на самом деле C ++ позволяет вводить и ловить практически любой тип, включая базовые типы, такие как int, тогда как другие языки, такие как Java, не столь разрешительны.

Продолжения

Async

В C # 5.0 появилось слово async для поддержки асинхронного ввода-вывода в «прямом стиле».

Генераторы

Генераторы, также известные как полупрограммы, используемое временное управление методуителя, обычно используя слово yield(yield description ). Подобно ключевому слову async, он поддерживает программирование в «прямом стиле».

Сопрограммы

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

Сопрограммы могут быть реализованы как библиотека, если язык программирования либо продолжения, либо генераторы, различные программы между сопрограммами и генераторами на практике технических деталью.

Перекрестная ссылка нелокального потока управления

Язык программирования условияисключениегенераторы / сопрограммыasync
Ada НетДа??
C НетНетНетНет
C ++ НетДада, с помощью BOOST?
C# НетДаДаДа
COBOL ДаДаНетНет
Common Lisp ДаНет??
D НетДаДа?
Эйфель НетДа??
Эрланг НетДаДа?
F# НетДаДаДа
Go НетДаДа?
Haskell НетДаДаНет
Java НетДаНетНет
JavaScript ?ДаДа, ES6Да, этап 3
Objective-C НетДаНет?
PHP НетДаДа?
PL / I ДаНетНетНет
Python НетДаДаДа
REBOL ДаДаНет?
Руби НетДаДа?
Ржавчина НетДаэкспериментальныйДа
Scala НетДачерез экспериментальное расширениечерез экспериментальное расширение
Tcl через трассировкиДаДачерез цикл событий
Visual Basic.NET ДаДаНет?
PowerShell НетДаНет?

Предлагаемые управляющие структуры

Подделкой В статье Данные 1973 года Р. Лоуренс Кларк оператором используя оператор GOTO COMEFROM и привел несколько интересных примеров. COMEFROM был реализован на одном эзотерическом языке программирования, названном INTERCAL.

в статье Дональда Кнута 1974 года «Структурированное программирование с использованием агента», в котором определены две ситуации, которые не были охвачены системой управления. структур, перечисленных выше, и привели примеры структур управления, которые могут справиться с этой ситуацией. Несмотря на их полезность, эти конструкции еще не нашли своего применения в основных языках программирования.

Цикл с тестом в середине

Следующее было предложено Далем в 1972 году:

цикл цикл xxx1 чтение (char) ; в то время как тест; в то время как не atEndOfFile; xxx2 запись (символ); повторить ; repeat ;

Если xxx1 опущено, мы получаем цикл с тестом наверху (цикл while ). Если xxx2 опущено, мы получаем цикл с тестом внизу, эквивалентный циклу do while на многих языках. Если в то время как опущено, мы получим бесконечный цикл. Конструкцию здесь можно представить как цикл сделать с проверкой пока в середине. Следовательно, эта единственная конструкция может заменить несколько конструкций в большинстве языков программирования.

Языки, в которых отсутствует эта конструкция, обычно эмулируют ее, используя эквивалентную идиому бесконечного цикла с прерыванием:

, в то время как (верно) {xxx1 if(не тест) break xxx2}

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

В Ada указанная выше конструкция цикла (цикл - в то время как - повторение ) может быть представлен С использованием стандартного бесконечного цикла (цикл - конец цикла ), имеющий в середине предложение выход, когда (не путать с оператором выход, когда в в следующем разделе).

с Ada.Text_IO; с Ada.Integer_Text_IO; процедура Print_Squares - X: Integer; начало Read_Data: цикл Ada.Integer_Text_IO.Get (X); выйти из Read_Data, когда X = 0; Ada.Text IO.Put (X * X); Ada.Text IO.New_Line; конец цикла Read_Data; конец Print_Squares;

Именование цикла (например, Read_Data в этом примере) необязательно, но позволяет выйти из внешнего цикла нескольких вложенных циклов.

Множественный ранний выход / выход из вложенных циклов

Это было предложено Зан в 1974 году. Здесь представлена ​​модифицированная версия.

exitwhen EventA или EventB или EventC; xxx exits EventA: actionA EventB: actionB EventC: actionC endexit ;

exitКогда используется для указаний событий, которые могут произойти в пределах xxx, их появление указано с помощью имени события как заявление. Когда какое-либо событие все же происходит, выполняется соответствующее действие, а затем управление переходит сразу после endexit . Эта конструкция обеспечивает очень четкое разделение между определением того, что определенная ситуация применима, и действия, которые необходимо предпринять в этой ситуации.

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

Следующий простой пример включает поиск определенного элемента в двумерной таблице.

выйти, если найдено, или отсутствует; для I: = 1 toN doдля J: = 1 toM doifтаблица [I, J] = цель, затем найдено; отсутствует; выходит из найдено: print («элемент находится в таблице»); отсутствует: print («товар отсутствует в таблице»); endexit ;

Безопасность

Один из способов атаки на часть программного обеспечения - перенаправить поток выполнения программы. Разнообразные методы целостности потока управления, включая канарейки стека, защиту от переполнения буфера, теневые стеки и проверка указателя vtable, используются для защиты от этих атак.

См. также

Ссылки

Дополнительная литература

  • Hoare, CAR «Раздел: алгоритм 63,» »Быстрая сортировка: алгоритм 64» и «Найти алгоритм 65 ». Comm. ACM 4, 321-322, 1961.

Внешние ссылки

В Wikibook Программирование на Ada есть страница по теме: Control
Wikibook Компьютерное программирование имеет страницу на тему: Управление
Последняя правка сделана 2021-05-15 11:06:58
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте