Цикл — різновид керівної конструкції у високорівневих мовах програмування, призначений для організації багаторазового виконання набору інструкцій (команд). Також циклом може називатися будь-яка багатократно виконувана послідовність команд, організована будь-яким чином (наприклад, із допомогою умовного переходу).
Визначення
Послідовність інструкцій, призначена для багаторазового виконання, називається тілом циклу. Одноразове виконання тіла циклу називається ітерацією. Вираз, що визначає чи буде вчергове виконуватися ітерація, чи цикл завершиться, називається умовою виходу або умовою завершення циклу (або умовою продовження в залежності від того, як інтерпретується його істинність — як ознака необхідності завершення чи продовження циклу. Змінна, в якій зберігається номер поточної ітерації, називається лічильником ітерацій циклу або просто лічильником циклу. Цикл не обов’язково містить лічильник, також лічильник не забов’язаний бути одним — умова виходу із циклу може залежати від декількох змінюваних в циклі змінних, а може визначатися зовнішніми умовами (наприклад, настанням певного часу), в останньому випадку лічильник взагалі не знадобиться.
Частинами виконання будь-якого циклу є початкова ініціалізація змінних циклу, перевірка умови виходу, виконання тіла циклу та оновлення змінної циклу на кожній ітерації. Крім того, більшість мов програмування надають засоби для дострокового керування циклом, наприклад, оператори завершення циклу, тобто виходу з циклу незалежно від істинності умови виходу (в мові С — break
) і оператори пропущення ітерації (в мові С — continue
).
Різновиди циклів
Безумовні цикли
Іноді в програмах використовуються цикли, вихід з яких не передбачено логікою програми. Такі цикли називаються безумовними або нескінченними. Особливих синтаксичних засобів для створення таких циклів, через їхню нетиповість, мови програмування не передбачають, тому такі цикли створюються за допомогою конструкцій призначених для створення звичайних (або умовних) циклів. Для забезпечення нескінченного повторення перевірка умови в такому циклі відсутня (якщо дозволяє синтаксис, як, наприклад, у циклі LOOP … END LOOP
мови Ада), або замінюється константним значенням (while true do …
в Паскаль).
Цикл з передумовою
Цикл з передумовою — цикл, що виконується доки істинна деяка умова, вказана перед його початком. Ця умова перевіряється до початку виконання тіла циклу, тому тіло може бути не виконане жодного разу (якщо умова з початку хибна). У більшості процедурних мов програмування здійснюється за допомогою інструкції while
, звідси його друга назва — while-цикл.
На мові Паскаль цикл з передумовою має такий вигляд:
while <умова> do begin <тіло циклу> end;
На мові Сі:
while(<умова>) { <тіло циклу> }
Цикл з післяумовою
Цикл з післяумовою — цикл, в якому умова перевіряється після виконання тіла циклу. Звідси випливає, що тіло циклу завжди виконується хоча б один раз. У мові Паскаль такий цикл здійснює інструкція repeat … until;
у Сі — do … while
.
На мові Паскаль цикл з післяумовою має такий вигляд:
repeat <тіло циклу> until <умова>
На мові Сі:
do { <тіло циклу> } while(<умова>)
У трактуванні умови циклу з післяумовою в різних мовах є розбіжності. У Паскалі і мовах похідних від нього умова такого циклу трактується як умова виходу (цикл завершується, коли умова істинна), а в Сі та його нащадках — як умова продовження (цикл завершується, коли умова хибна).
Цикл з виходом з середини
Цикл з виходом з середини — найзагальніший тип умовного циклу. Синтаксично такий цикл оформляється за допомогою трьох інструкцій: початок циклу, кінець циклу та інструкції (команди) виходу з циклу. Інструкція початку позначає точку програми, з якої починається тіло циклу, інструкція кінця — точку, де тіло закінчується. Всередині тіла має бути присутня команда виходу з циклу, при виконанню якої цикл завершується і керування передається на оператор, наступний після інструкції кінця циклу. Природно, щоб цикл виконався більш ніж один раз, команда виходу має викликатися не безумовно, а тільки при виконанні умови виходу.
Принциповою відмінністю такого різновиду циклу від розглянутих вище є те, що частина тіла циклу, розташована після початку циклу і до команди виходу, виконується завжди (навіть якщо умова виходу з циклу істинна при першій ітерації), а частина тіла циклу, наступна за командою виходу, не виконується при останній ітерації.
Легко побачити, що за допомогою циклу з виходом з середини легко утворити як цикл з передумовою (розташувавши команду виходу на початку тіла циклу), так і цикл з післяумовою (розташувавши команду виходу в кінці тіла циклу).
Частина мов програмування містить особливі інструкції для утворення циклу з виходом з середини. Так, у мові Ада для цього використовується конструкція LOOP … END LOOP
і команда виходу EXIT
або EXIT WHEN
:
LOOP ... Частина тіла циклу EXIT WHEN <умова виходу>; ... Частина тіла циклу IF <умова виходу> THEN EXIT; END; ... Частина тіла циклу END LOOP:
Тут всередині циклу може бути будь-яка кількість команд виходу обох типів. Самі команди виходу принципово не відрізняються, зазвичай EXIT WHEN
застосовують, коли перевіряється тільки умова виходу, а просто EXIT
— коли вихід з циклу здійснюється в одному з варіантів складного умовного оператора.
У тих мовах, де подібних конструкцій не передбачено, цикл з виходом з середини може бути побудований за допомогою будь-якого умовного циклу та інструкції дострокового виходу з циклу (такого, як break
в Сі, exit
в Турбо Паскалі т.п.), або інструкції безумовного переходу goto
.
Цикл з лічильником
Цикл з лічильником — цикл, в якому деяка змінна змінює своє значення від заданого початкового значення до кінцевого значення з деяким кроком, і для кожного значення цієї змінної тіло циклу виконується один раз. В більшості процедурних мов програмування реалізується оператором for
, в якому вказується лічильник (так звана «змінна циклу»), потрібна кількість проходів (або граничне значення лічильника) і, можливо, крок, з яким змінюється лічильник. Наприклад, в мові Оберон-2 такий цикл має вигляд:
FOR v := b TO e BY s DO ... тіло циклу END
(тут v
— лічильник, b
— початкове значення лічильника, e
— межове значення лічильника, s
— крок).
Неоднозначне питання про значення змінної по завершенні циклу, в якому ця змінна використовувалась як лічильник. Наприклад, якщо в програмі на мові Паскаль зустрінеться конструкція вигляду:
i := 100; for i := 0 to 9 do begin ... тіло циклу end; k := i;
виникає питання: яке значення буде в підсумку присвоєне змінній k
: 9, 10, 100, може якесь інше? А якщо цикл завершиться достроково? Відповіді залежать від того, чи збільшується значення лічильника після ітерації і чи не змінює транслятор це значення додатково. Ще одне запитання: що буде, якщо всередині циклу лічильнику буде явно присвоєне нове значення?
Різні мови програмування мають різні підходи до цього питання. В деяких поведінку лічильника чітко регламентовано. В інших, наприклад, Паскалі, стандарт мови не визначає ані кінцевого значення лічильника, ані наслідків його явної зміни в циклі, але не радиться змінювати значення лічильника явно і використовувати його після завершення циклу без повторної ініціалізації. Програма на Паскалі, що ігнорує цю пораду, матиме невизначену поведінку, тобто може давати різні результати при виконанні на різних системах чи при використанні різних трансляторів або навіть різних режимів оптимізації одного й того ж транслятора.
Радикально вирішене питання в мові Ада: лічильник вважається описаним в заголовку циклу та поза циклом просто не існує. Навіть якщо ім’я лічильника вже використовується в програмі, всередині циклу як лічильник використовується окрема змінна. Лічильнику заборонено явно присвоювати будь-які значення, він може змінюватись лиш внутрішнім механізмом оператора циклу. В результаті конструкція
i := 100; for i in (0..9) loop ... тіло циклу end loop; k := i;
зовнішньо аналогічна вищенаведеному циклу на Паскалі, трактується однозначно: змінній k
буде присвоєно значення 100, оскільки змінна i
, використовувана поза межами даного циклу, не має жодного стосунку до лічильника циклу i
, який змінюється всередині циклу. Подібне відокремлення лічильника зручне і безпечне: не потрібен окремий опис для нього та мінімізується ймовірність випадкових помилок, пов’язаних із випадковим руйнуванням зовнішніх стосовно циклу змінних. Якщо програмісту потрібно включити в готовий код цикл з лічильником, то його не турбує чи існує змінна з ім’ям, яке він обрав для лічильника, і йому не потрібно додавати опис свого лічильника. Він просто пише код зі змінною-лічильником, ім’я якої йому зручне, і може бути впевненим, що ніякої колізії імен не відбудеться.
Цикл з лічильником завжди можна написати як умовний цикл, перед початком якого лічильнику присвоюється початкове значення, а умовою виходу з циклу є досягнення лічильником кінцевого значення; в тіло циклу при цьому додається оператор зміни лічильника на потрібний крок. Однак спеціальні оператори циклу з лічильником можуть ефективніше транслюватися, бо формалізований вигляд такого циклу дозволяє використовувати спеціальні процесорні команди організації циклів.
В деяких мовах, наприклад, Сі та інших, похідних від неї, цикл for
, незважаючи на синтаксичну форму циклу з лічильником, в дійсності є циклом з передумовою. Тобто в Сі конструкція циклу:
for (i = 0; i < 10; ++i) { ... тіло циклу }
фактично являє собою інший варіант запису конструкції:
i = 0; while (i < 10) { ... тіло циклу ++i; }
Тобто в конструкції for
спочатку пишеться довільне речення ініціалізації циклу, потім — умова продовження і, насамкінець, виконувана після кожного тіла циклу деяка операція (це не обов’язково має бути зміна лічильника; це може бути модифікація вказівника або будь-яка зовсім стороння дія). Для мов такого типу вищезазначена проблема розв'язується дуже просто: змінна-лічильник поводиться цілком передбачувано і по завершені циклу зберігає своє останнє значення.
Цикл по колекції (foreach)
Ще одним варіантом є цикл, який пробігає елементи з деякої множини без явного задання порядку перебору цих об’єктів. Такі цикли являють собою формальний запис інструкції виду: «Виконати дію X для всіх елементів множини M». Теоретично такий цикл ніяким чином не визначає, в якому порядку буде застосовуватись дія до елементів множини, хоча певні мови програмування, звісно, можуть встановлювати конкретний порядок перебору елементів. Довільність дає можливість оптимізації виконання циклу за рахунок організації доступу в найвигіднішому порядку, а не в порядку зазначеному програмістом. За наявності можливості паралельного виконання декількох операцій можливо навіть розподілення виконання циклу по колекції, коли одна і та сама операція одночасно виконується на різних обчислювальних модулях для різних об’єктів, при тому що логічно програма залишається послідовною.
Цикли по колекції реалізовано в деяких мовах програмування (C#, Eiffel, Java, JavaScript, Perl, Python, PHP, LISP, Tcl, та ін.) — вони дають змогу цикл по всіх елементах даної колекції об'єктів. У визначенні такого циклу треба вказати лише колекцію об’єктів і змінну, якій в тілі циклу буде присвоєне значення оброблюваного в цей час об’єкта (чи посилання на нього). В різних мовах програмування синтаксис оператора різний:
C#:
foreach (type item in set) { //використання item }
:
const char *str[] = {"one", "two", "forty-four"}; for (const char *p: str) { std::cout << p << std::endl; }
Perl:
foreach (@set) { #використання $_ }
або
for(@set) { #використання $_ }
або
foreach $item(@set) { #використання $item }
across set as cursor loop -- використання cursor.item end
Java:
for (type item : set) { //використання item }
for (txtProperty in objObject) { /* використання: objObject [txtProperty] */ }
PHP:
foreach ($arr as $item) { /* використання $item*/ }
For Each item As type In set 'використання item Next item
foreach ($item in $set) { # використання $item }
або
$set | ForEach-Object { # використання $_ }
for item in iterator_instance: # використання item
Достроковий вихід і пропуск ітерації
Багато-які з мов програмування, що мають в своєму синтаксисі циклічні конструкції, мають також особливі команди, які дозволяють порушити порядок роботи цих конструкцій: команду дострокового виходу з циклу та команду пропуску ітерації.
Достроковий вихід з циклу
Команда дострокового виходу застосовується, коли необхідно перервати виконання циклу, в якому умови виходу ще не досягнуто. Таке буває, наприклад, коли під час виконання циклу зустрічається помилка, після якої подальше виконання циклу не має сенсу.
Команда дострокового виходу зазвичай називається EXIT
або break
, а її дія аналогічна дії команди безумовного переходу (goto
) на команду, розміщену безпосередньо за циклом, всередині якого ця команда знаходиться. Так у мові Сі два нижченаведених цикли працюють цілком однаково:
// Застосування оператора break while(<умова>) { ... оператори if (<помилка>) break; ... оператори } ... продовження програми // Аналогічний уривок без break while(<умова>) { ... оператори if (<помилка>) goto break_label; ... оператори } break_label: ... продовження програми
В обох випадках, якщо в тілі циклу виконується умова <помилка>, буде виконаний перехід на оператори, позначені як «продовження програми». Таким чином, оператор дострокового виходу з циклу, за суттю, просто маскує безумовний перехід, однак використанню break
варто віддати перевагу перед використанням goto
, оскільки поведінка break
чітко задана мовою, потенційно менш небезпечна (немає, наприклад, імовірності помилитися з розташуванням або назвою мітки переходу). Окрім того, явний достроковий вихід з циклу не порушує засад структурного програмування.
Звичайний оператор дострокового виходу перериває роботу того циклу, в якому він безпосередньо знаходиться. В багатьох мовах програмування функціональність цього оператора розширена, він дозволяє виходити з декількох вкладених циклів (див. нижче). У таких випадках цикл, з якого треба вийти, позначається міткою, а в операторі дострокового виходу вказується ця мітка.
Пропуск ітерації
Даний оператор застосовується, коли в поточній ітерації циклу необхідно пропустити всі команди до кінця тілу циклу. При цьому сам цикл не переривається, умови продовження або виходу обчислюються звичайним чином.
У мові Сі та її мовах-нащадках як команда пропуску ітерації використовується оператор continue
в конструкції циклу. Дія цього оператора аналогічна безумовному переходу на рядок всередині тіла циклу, наступний за останньою його командою. Наприклад, код на Сі, який знаходить суму всіх додатних елементів масиву, може мати такий вигляд:
int arr[ARRSIZE]; ... // Сумування окремо всіх і тільки додатних // елементів масиву arr із застосуванням continue. int sum_all = 0; int sum_pos = 0; for (int i = 0 ; i < ARRSIZE; ++i) { sum_all += arr[i]; if (arr[i] <= 0) continue; sum_pos += arr[i]; } // Те саме з goto int sum_all = 0; int sum_pos = 0; for (int i = 0 ; i < ARRSIZE; ++i) { sum_all += arr[i]; if (arr[i] <= 0) goto cont_label; sum_pos += arr[i]; cont_label: }
З другого уривку ясно видно, як працює continue
: він просто передає виконання за останню команду циклу, із пропуском команди сумування, якщо черговий елемент масиву не задовільняє умові. Таким чином, в sum_pos
накопичується сума тільки додатних елементів масиву.
Необхідність
З погляду структурного програмування команди дострокового виходу з циклу і продовження ітерації є надлишковими, оскільки їх дія може бути легко змодельована чисто структурними засобами. Більш того, на думку ряда теоретиків програмування (зокрема, Едсгера Дейкстри), сам факт використання в програмі неструктурних засобів, чи це класичний безумовний перехід чи будь-яка з його спеціальних форм, на кшталт break
або continue
, є свідченням недостатньо пропрацьованого алгоритму розв’язання задачі.
Однак на практиці код програми часто є записом наявного, раніш сформульваного алгоритму, перепрацьовувати який недоцільно за чисто технічними причинами. Спроба замінити в такому коді команду дострокового виходу на структурні конструкції часто виявляється неефективною або громіздкою. Наприклад, вищеподаний уривок коду може бути записаний без використання команди break
так:
// достроковий вихід з циклу без break bool flag = false; // прапорець дострокового завершення while(<умова> && !flag) { ... оператори if (<помилка>) { flag = true; } else { ... оператори } } ... продовження програми
Легко переконатись, що цей уривок працюватиме так само, як і попередній, різниця лиш в тому, що в місці перевірки на помилку замість безпосереднього виходу з циклу встановлюється прапорець дострокового виходу, який перевіряється потому в штатній умові продовження циклу. Однак для відмови від команди дострокового виходу довелось додати в програму опис прапорця і другу гілку умовного оператора, до того ж відбулося «розмиття» логіки програми (рішення про достроковий вихід приймається в одному місці, а виконується в іншому). В результаті програма не стала ані простішою, ані коротшою, ані зрозумілішою.
Дещо інакше стоїть справа з командою пропуску ітерації. Вона, як правило, дуже легко замінюється на умовний оператор. Наприклад, поданий вище уривок сумування масиву можна записати так:
int arr[ARRSIZE]; ... // Сумування окремо всіх і тільки додатніх // елементів масиву arr із заміною continue int sum_all = 0; int sum_pos = 0; for (int i = 0 ; i < ARRSIZE; ++i) { sum_all += arr[i]; if (arr[i] > 0) // Умова замінена на протилежну! { sum_pos += arr[i]; } }
Як бачимо, достатньо було замінити умову на протилежну та помістити заключну частину частину тіла циклу в умовний оператор. Можна зауважити, що програма стала коротшою (за рахунок видалення команди пропуску ітерації) і одночасно більш логіно (із коду безпосередньо видно, що сумуються додатні елементи).
Незважаючи на обмежену корисність і можливість заміни на інші мовні конструкції, команди пропуску ітерації і, особливо, дострокового виходу з циклу в окремих випадках виявляються вкрай корисними, саме через це вони зберігаються в сучасних мовах програмування.
Вкладені цикли
Існує можливість утворити цикл всередині тіла другого циклу. Такий цикл зветься вкладеним циклом. Вкладений цикл щодо циклу в тіло якого він вкладений буде йменуватися внутрішнім циклом, і навпаки цикл в тілі якого існує вкладений цикл буде йменуватись зовнішнім щодо вкладеного. Всередині вкладеного циклу може бути наступний вкладений цикл, утворюючи наступний рівень вкладеності і так далі. Кількість рівнів вкладеності, як правило, не обмежується.
Повна кількість виконання тіла внутрішнього циклу не перевищує добутку кількості ітерацій внутрішнього і всіх зовнішніх циклів. Наприклад взяв три вкладених один в одного цикли, кожний по 10 ітерацій, отримаємо 10 виконань тіла зовнішнього циклу, 100 для циклу другого рівня і 1000 в найбільш вкладеному циклі.
Одна з проблем, пов’язаних із вкладеними циклами — організація дострокового виходу з них. В багатьох мовах програмуванняє оператор дострокового завершення циклу (break
у Сі, exit
у Паскалі, last
в Perl і т. ін.), але він, як правило, забезпечує вихід лише з циклу того рівня, звідки викликаний. Виклик його у вкладеному циклі призведе до завершення лиш цього вкладеного циклу, зовнішній цикл продовжить виконання. Проблема може здатися надуманою, але вона дійсно іноді виникає при програмуванні складної обробки даних, коли алгоритм вимагає негайного переривання за певних умов, наявність яких можна перевірити тільки в глубоко вкладеному циклі.
Розв’язків проблеми виходу з вкладених циклів декілька.
- Найпростіший — використати оператор безумовного переходу
goto
для виходу в точку програми, наступну безпосередньо за вкладеним циклом. Цей варіант критикується прихильниками структурного програмування, як і всі конструкції, що вимагають використанняgoto
. Деякі мови програмування, наприклад, , просто не мають оператора безумовного переходу, тому в них подібна ситуація неможлива. - Альтернатива — використовувати штатні засоби завершення циклів, у випадку необхідності встановлюючи особливі прапорці, що вимагають негайного завершення обробки. Недолік — ускладнення коду, зниження продуктивності без яких-небудь переваг, окрім теоретичної «правильності» через відмову від
goto
. - Розташування вкладеного циклу в процедурі. Ідея полягає в тому, щоб всю дію, в якій може виникнути потреба дострокового переривання, оформити у вигляді окремої процедури, і для дострокового виходу викликати оператор виходу з процедури (якщо такий в наявності в мові програмування) В мові Сі, наприклад, можна побудувати функцію з вкладеним циклом, а вихід з нею організувати за допомогою оператора
return
. Недолік — виділення уривка коду в окрему процедуру не завжди обґрунтоване, і не всі мови мають штатні засоби для дострокового завершення процедур. - Скористатись механізмом генерації і обробки виняткив (виняткових ситуацій), який зараз наявний у більшості мов високого рівня. В цьому випадку в нештатній ситуації код у вкладеному циклі створює виняткову ситуацію, а блок обробки винятків, в якому знаходиться вкладений цикл, перехоплює та обробляє його. Недолік — реалізація механізму обробки винятків у більшості випадків така, що швидкість роботи програми зменшується. Правда, в сучасних умовах це не особливо важливо: практично втрата продуктивності така мала, що має значення лиш для зовсім небагатьох застосунків.
- Насамкінець, існують спецальні мовні засоби для виходу з вкладених циклів. Так в мові Ада програміст може позначити зовнішній цикл позначкою, і в команді дострокового завершення циклу вказати цю позначку. Вихід відбудеться не з поточного циклу, а з усіх вкладених циклів до позначеного, включно:
loop_y : FOR y IN 1..MAXY DO BEGIN FOR x IN 1..MAXX DO BEGIN ... EXIT loop_y WHEN object_found(x,y); END END
Цикли з декількома гілками із вартами
Цикл Дейкстри
В теорії програмування відома ще одна форма циклічної конструкції, яка принципово відрізняється від «класичних», яка отримала назву «цикл Дейкстри», за ім'ям Едсгера Дейкстри, який першим її описав. В класичному дейксрівському описі вона має такий вигляд:
do P1 → S1, … Pn → Sn od
Тут do
— позначка початку конструкції циклу, od
— позначка завершення конструкції циклу, Pi — i-та варта (логічний вираз, який може мати значення «істина» або «хиба»), Si — i-а команда під вартою. Цикл складається з однієї чи декількох гілок, кожна з яких являє собою пару з варти і команди (в дійсності команда може бути складною).
При виконанні циклу Дейкстри в кожній ітерації відбувається обчислення варт. Якщо, хоча б одна з них істинна, виконується відповідна команда, після чого починається нова ітерація (якщо істинні декілька вартових умов, виконується лиш одна команда). Якщо всі варти хибні, цикл завершується. Неважко зауважити, що цикл Децкстри з однією вартою і однією командою являє собою звичайний цикл з передумовою.
Хоча цикл Дейкстри був винайдений ще в 1970-х, спеціальних конструкцій для його створення в мовах програмування не існує. Єдиним винятком став нещодавно створений — перша реальна мова програмування, що явно підтримує цикл з декількома гілками з вартами. Втім, цикл Дейкстри може бути без особливих труднощцв змодельований за допомогою звичайних конструкцій мов програмування. Ось один з можливих прикладів його реалізації на мові Ада:
loop if P1 then S1; ... elsif Pn then Sn; else exit; end if; end loop;
Тут P1-Pn — вартові умови (варти), а S1-Sn — відповідні команди.
Цикл Дейкстри зручний при реалізації специфічних обчислень, які повторюються і, які незручно описувати за допомогою традиційніших циклічних конструкцій. Наприклад, цим циклом природно представляється скінченний автомат — кожна гілка відповідає одному стану автомата, варти вибудовуються так, щоб в поточній ітерації обиралась гілка, відповідна поточному стану автомата, а код варти забезпечує виконання обчислень в поточному стані і перехід в наступне (тобто така зміна змінних, після якої на наступній ітерації буде істиною варта потрібної гілки).
Цикл «павук»
Легко бачити, що цикл Дейкстри не містить явної умови продовження або виходу з циклу, що не всіма теоретиками програмування розглядається як благо. Тому було запропонована ускладнена конструкція циклу Дейкстри, яка отримала назву «цикл-'павук'». У тій же нотації вона має такий вигляд:
do P1→S1, … Pn→Sn out Q1→T1, … Qn→Tn else E od
Тут після позначки out
додано гілки завершення, утворені з умов виходу Qi і команд завершення Ti. Окрім того, додано гілку альтернативного завершення else
з командою E.
Цикл-'павук' виконуються таким чином:
- Обчислюються вартові. Якщо існує істинний вартовий, виконується відповідна команда.
- Обчислюється умови виходу. Якщо існує істинна умова виходу, виконується відповідна команда завершення, після чого виконання циклу завершується. Якщо всі умови виходу хибні, починається наступна ітерація, але тільки в тому випадку, якщо в потсчній ітерації був істинним хоча б один з вартових.
- Якщо в даній ітерації виявились хибними і всі вартові, і всі умови виходу, виконується команда альтернативного завершення E, після чого виконання циклу переривається.
Структура циклу-'павука' дозволяє гранично-строго описати умови виконання циклу. Згідно з теоретичними положеннями, гілка альтенативного завершення не повинна використовуватися як один із варіантів коректного припинення роботи циклу (всі такі варіанти мають бути оформлені в вигляді відповідних гілок завершення з явною умовою), вона слугує лиш для того, щоб відслідкувати ситуацію, коли за якихось причин цикл почав виконуватись нештатно. Тобто команда альтернативного завершення може лише аналізувати причини помилки та подавати результати розбору.
Хоч явної підтримки на рівні синтаксису мови для цього циклу не існує в жодній мові програмування, цикл-'павук', як і цикл Дейкстри, може бути змодельованим за допомогою традиційних структурних конструкцій.
Цікаві факти
- Ніклаус Вірт свого часу називав цикл з лічильником «маргинальним», стверджуючи, що така конструкція є надлишковою і має бути виключена з синтаксису мов програмування як несистемна. Згідно з його представленням у мові програмування Оберон циклу з лічильником не було. Однак у мові Оберон-2, створеній Віртом і Мьоссенбьоком як розвиток Оберона, цикл з лічильником
FOR
з'явився в інтересах практичної зручності використання.
Див. також
Методи оптимизації циклів
Примітки
- Строго кажучи, тотожність не повна, бо інакше буде працювати оператор
continue
. - Оберон — воплощение мечты Никлауса Вирта
Це незавершена стаття про мови програмування. Ви можете проєкту, виправивши або дописавши її. |
Ця стаття не містить . (червень 2011) |
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
Cikl riznovid kerivnoyi konstrukciyi u visokorivnevih movah programuvannya priznachenij dlya organizaciyi bagatorazovogo vikonannya naboru instrukcij komand Takozh ciklom mozhe nazivatisya bud yaka bagatokratno vikonuvana poslidovnist komand organizovana bud yakim chinom napriklad iz dopomogoyu umovnogo perehodu ViznachennyaPoslidovnist instrukcij priznachena dlya bagatorazovogo vikonannya nazivayetsya tilom ciklu Odnorazove vikonannya tila ciklu nazivayetsya iteraciyeyu Viraz sho viznachaye chi bude vchergove vikonuvatisya iteraciya chi cikl zavershitsya nazivayetsya umovoyu vihodu abo umovoyu zavershennya ciklu abo umovoyu prodovzhennya v zalezhnosti vid togo yak interpretuyetsya jogo istinnist yak oznaka neobhidnosti zavershennya chi prodovzhennya ciklu Zminna v yakij zberigayetsya nomer potochnoyi iteraciyi nazivayetsya lichilnikom iteracij ciklu abo prosto lichilnikom ciklu Cikl ne obov yazkovo mistit lichilnik takozh lichilnik ne zabov yazanij buti odnim umova vihodu iz ciklu mozhe zalezhati vid dekilkoh zminyuvanih v cikli zminnih a mozhe viznachatisya zovnishnimi umovami napriklad nastannyam pevnogo chasu v ostannomu vipadku lichilnik vzagali ne znadobitsya Chastinami vikonannya bud yakogo ciklu ye pochatkova inicializaciya zminnih ciklu perevirka umovi vihodu vikonannya tila ciklu ta onovlennya zminnoyi ciklu na kozhnij iteraciyi Krim togo bilshist mov programuvannya nadayut zasobi dlya dostrokovogo keruvannya ciklom napriklad operatori zavershennya ciklu tobto vihodu z ciklu nezalezhno vid istinnosti umovi vihodu v movi S break i operatori propushennya iteraciyi v movi S continue Riznovidi ciklivBezumovni cikli Inodi v programah vikoristovuyutsya cikli vihid z yakih ne peredbacheno logikoyu programi Taki cikli nazivayutsya bezumovnimi abo neskinchennimi Osoblivih sintaksichnih zasobiv dlya stvorennya takih cikliv cherez yihnyu netipovist movi programuvannya ne peredbachayut tomu taki cikli stvoryuyutsya za dopomogoyu konstrukcij priznachenih dlya stvorennya zvichajnih abo umovnih cikliv Dlya zabezpechennya neskinchennogo povtorennya perevirka umovi v takomu cikli vidsutnya yaksho dozvolyaye sintaksis yak napriklad u cikli LOOP END LOOP movi Ada abo zaminyuyetsya konstantnim znachennyam while true do v Paskal Cikl z peredumovoyu Cikl z peredumovoyu cikl sho vikonuyetsya doki istinna deyaka umova vkazana pered jogo pochatkom Cya umova pereviryayetsya do pochatku vikonannya tila ciklu tomu tilo mozhe buti ne vikonane zhodnogo razu yaksho umova z pochatku hibna U bilshosti procedurnih mov programuvannya zdijsnyuyetsya za dopomogoyu instrukciyi while zvidsi jogo druga nazva while cikl Na movi Paskal cikl z peredumovoyu maye takij viglyad while lt umova gt do begin lt tilo ciklu gt end Na movi Si while lt umova gt lt tilo ciklu gt Cikl z pislyaumovoyu Dokladnishe Cikl do while Cikl z pislyaumovoyu cikl v yakomu umova pereviryayetsya pislya vikonannya tila ciklu Zvidsi viplivaye sho tilo ciklu zavzhdi vikonuyetsya hocha b odin raz U movi Paskal takij cikl zdijsnyuye instrukciya repeat until u Si do while Na movi Paskal cikl z pislyaumovoyu maye takij viglyad repeat lt tilo ciklu gt until lt umova gt Na movi Si do lt tilo ciklu gt while lt umova gt U traktuvanni umovi ciklu z pislyaumovoyu v riznih movah ye rozbizhnosti U Paskali i movah pohidnih vid nogo umova takogo ciklu traktuyetsya yak umova vihodu cikl zavershuyetsya koli umova istinna a v Si ta jogo nashadkah yak umova prodovzhennya cikl zavershuyetsya koli umova hibna Cikl z vihodom z seredini Cikl z vihodom z seredini najzagalnishij tip umovnogo ciklu Sintaksichno takij cikl oformlyayetsya za dopomogoyu troh instrukcij pochatok ciklu kinec ciklu ta instrukciyi komandi vihodu z ciklu Instrukciya pochatku poznachaye tochku programi z yakoyi pochinayetsya tilo ciklu instrukciya kincya tochku de tilo zakinchuyetsya Vseredini tila maye buti prisutnya komanda vihodu z ciklu pri vikonannyu yakoyi cikl zavershuyetsya i keruvannya peredayetsya na operator nastupnij pislya instrukciyi kincya ciklu Prirodno shob cikl vikonavsya bilsh nizh odin raz komanda vihodu maye viklikatisya ne bezumovno a tilki pri vikonanni umovi vihodu Principovoyu vidminnistyu takogo riznovidu ciklu vid rozglyanutih vishe ye te sho chastina tila ciklu roztashovana pislya pochatku ciklu i do komandi vihodu vikonuyetsya zavzhdi navit yaksho umova vihodu z ciklu istinna pri pershij iteraciyi a chastina tila ciklu nastupna za komandoyu vihodu ne vikonuyetsya pri ostannij iteraciyi Legko pobachiti sho za dopomogoyu ciklu z vihodom z seredini legko utvoriti yak cikl z peredumovoyu roztashuvavshi komandu vihodu na pochatku tila ciklu tak i cikl z pislyaumovoyu roztashuvavshi komandu vihodu v kinci tila ciklu Chastina mov programuvannya mistit osoblivi instrukciyi dlya utvorennya ciklu z vihodom z seredini Tak u movi Ada dlya cogo vikoristovuyetsya konstrukciya LOOP END LOOP i komanda vihodu EXIT abo EXIT WHEN LOOP Chastina tila ciklu EXIT WHEN lt umova vihodu gt Chastina tila ciklu IF lt umova vihodu gt THEN EXIT END Chastina tila ciklu END LOOP Tut vseredini ciklu mozhe buti bud yaka kilkist komand vihodu oboh tipiv Sami komandi vihodu principovo ne vidriznyayutsya zazvichaj EXIT WHEN zastosovuyut koli pereviryayetsya tilki umova vihodu a prosto EXIT koli vihid z ciklu zdijsnyuyetsya v odnomu z variantiv skladnogo umovnogo operatora U tih movah de podibnih konstrukcij ne peredbacheno cikl z vihodom z seredini mozhe buti pobudovanij za dopomogoyu bud yakogo umovnogo ciklu ta instrukciyi dostrokovogo vihodu z ciklu takogo yak break v Si exit v Turbo Paskali t p abo instrukciyi bezumovnogo perehodu goto Cikl z lichilnikom Dokladnishe For cikl Cikl z lichilnikom cikl v yakomu deyaka zminna zminyuye svoye znachennya vid zadanogo pochatkovogo znachennya do kincevogo znachennya z deyakim krokom i dlya kozhnogo znachennya ciyeyi zminnoyi tilo ciklu vikonuyetsya odin raz V bilshosti procedurnih mov programuvannya realizuyetsya operatorom for v yakomu vkazuyetsya lichilnik tak zvana zminna ciklu potribna kilkist prohodiv abo granichne znachennya lichilnika i mozhlivo krok z yakim zminyuyetsya lichilnik Napriklad v movi Oberon 2 takij cikl maye viglyad FOR v b TO e BY s DO tilo ciklu END tut v lichilnik b pochatkove znachennya lichilnika e mezhove znachennya lichilnika s krok Neodnoznachne pitannya pro znachennya zminnoyi po zavershenni ciklu v yakomu cya zminna vikoristovuvalas yak lichilnik Napriklad yaksho v programi na movi Paskal zustrinetsya konstrukciya viglyadu i 100 for i 0 to 9 do begin tilo ciklu end k i vinikaye pitannya yake znachennya bude v pidsumku prisvoyene zminnij k 9 10 100 mozhe yakes inshe A yaksho cikl zavershitsya dostrokovo Vidpovidi zalezhat vid togo chi zbilshuyetsya znachennya lichilnika pislya iteraciyi i chi ne zminyuye translyator ce znachennya dodatkovo She odne zapitannya sho bude yaksho vseredini ciklu lichilniku bude yavno prisvoyene nove znachennya Rizni movi programuvannya mayut rizni pidhodi do cogo pitannya V deyakih povedinku lichilnika chitko reglamentovano V inshih napriklad Paskali standart movi ne viznachaye ani kincevogo znachennya lichilnika ani naslidkiv jogo yavnoyi zmini v cikli ale ne raditsya zminyuvati znachennya lichilnika yavno i vikoristovuvati jogo pislya zavershennya ciklu bez povtornoyi inicializaciyi Programa na Paskali sho ignoruye cyu poradu matime neviznachenu povedinku tobto mozhe davati rizni rezultati pri vikonanni na riznih sistemah chi pri vikoristanni riznih translyatoriv abo navit riznih rezhimiv optimizaciyi odnogo j togo zh translyatora Radikalno virishene pitannya v movi Ada lichilnik vvazhayetsya opisanim v zagolovku ciklu ta poza ciklom prosto ne isnuye Navit yaksho im ya lichilnika vzhe vikoristovuyetsya v programi vseredini ciklu yak lichilnik vikoristovuyetsya okrema zminna Lichilniku zaboroneno yavno prisvoyuvati bud yaki znachennya vin mozhe zminyuvatis lish vnutrishnim mehanizmom operatora ciklu V rezultati konstrukciya i 100 for i in 0 9 loop tilo ciklu end loop k i zovnishno analogichna vishenavedenomu ciklu na Paskali traktuyetsya odnoznachno zminnij k bude prisvoyeno znachennya 100 oskilki zminna i vikoristovuvana poza mezhami danogo ciklu ne maye zhodnogo stosunku do lichilnika ciklu i yakij zminyuyetsya vseredini ciklu Podibne vidokremlennya lichilnika zruchne i bezpechne ne potriben okremij opis dlya nogo ta minimizuyetsya jmovirnist vipadkovih pomilok pov yazanih iz vipadkovim rujnuvannyam zovnishnih stosovno ciklu zminnih Yaksho programistu potribno vklyuchiti v gotovij kod cikl z lichilnikom to jogo ne turbuye chi isnuye zminna z im yam yake vin obrav dlya lichilnika i jomu ne potribno dodavati opis svogo lichilnika Vin prosto pishe kod zi zminnoyu lichilnikom im ya yakoyi jomu zruchne i mozhe buti vpevnenim sho niyakoyi koliziyi imen ne vidbudetsya Cikl z lichilnikom zavzhdi mozhna napisati yak umovnij cikl pered pochatkom yakogo lichilniku prisvoyuyetsya pochatkove znachennya a umovoyu vihodu z ciklu ye dosyagnennya lichilnikom kincevogo znachennya v tilo ciklu pri comu dodayetsya operator zmini lichilnika na potribnij krok Odnak specialni operatori ciklu z lichilnikom mozhut efektivnishe translyuvatisya bo formalizovanij viglyad takogo ciklu dozvolyaye vikoristovuvati specialni procesorni komandi organizaciyi cikliv V deyakih movah napriklad Si ta inshih pohidnih vid neyi cikl for nezvazhayuchi na sintaksichnu formu ciklu z lichilnikom v dijsnosti ye ciklom z peredumovoyu Tobto v Si konstrukciya ciklu for i 0 i lt 10 i tilo ciklu faktichno yavlyaye soboyu inshij variant zapisu konstrukciyi i 0 while i lt 10 tilo ciklu i Tobto v konstrukciyi for spochatku pishetsya dovilne rechennya inicializaciyi ciklu potim umova prodovzhennya i nasamkinec vikonuvana pislya kozhnogo tila ciklu deyaka operaciya ce ne obov yazkovo maye buti zmina lichilnika ce mozhe buti modifikaciya vkazivnika abo bud yaka zovsim storonnya diya Dlya mov takogo tipu vishezaznachena problema rozv yazuyetsya duzhe prosto zminna lichilnik povoditsya cilkom peredbachuvano i po zaversheni ciklu zberigaye svoye ostannye znachennya Cikl po kolekciyi foreach She odnim variantom ye cikl yakij probigaye elementi z deyakoyi mnozhini bez yavnogo zadannya poryadku pereboru cih ob yektiv Taki cikli yavlyayut soboyu formalnij zapis instrukciyi vidu Vikonati diyu X dlya vsih elementiv mnozhini M Teoretichno takij cikl niyakim chinom ne viznachaye v yakomu poryadku bude zastosovuvatis diya do elementiv mnozhini hocha pevni movi programuvannya zvisno mozhut vstanovlyuvati konkretnij poryadok pereboru elementiv Dovilnist daye mozhlivist optimizaciyi vikonannya ciklu za rahunok organizaciyi dostupu v najvigidnishomu poryadku a ne v poryadku zaznachenomu programistom Za nayavnosti mozhlivosti paralelnogo vikonannya dekilkoh operacij mozhlivo navit rozpodilennya vikonannya ciklu po kolekciyi koli odna i ta sama operaciya odnochasno vikonuyetsya na riznih obchislyuvalnih modulyah dlya riznih ob yektiv pri tomu sho logichno programa zalishayetsya poslidovnoyu Cikli po kolekciyi realizovano v deyakih movah programuvannya C Eiffel Java JavaScript Perl Python PHP LISP Tcl C 11 ta in voni dayut zmogu cikl po vsih elementah danoyi kolekciyi ob yektiv U viznachenni takogo ciklu treba vkazati lishe kolekciyu ob yektiv i zminnu yakij v tili ciklu bude prisvoyene znachennya obroblyuvanogo v cej chas ob yekta chi posilannya na nogo V riznih movah programuvannya sintaksis operatora riznij C foreach type item in set vikoristannya item C standart 2011 roku const char str one two forty four for const char p str std cout lt lt p lt lt std endl Perl foreach set vikoristannya abo for set vikoristannya abo foreach item set vikoristannya item Eiffel across set as cursor loop vikoristannya cursor item end Java for type item set vikoristannya item JavaScript for txtProperty in objObject vikoristannya objObject txtProperty PHP foreach arr as item vikoristannya item Visual Basic NET For Each item As type In set vikoristannya item Next item Windows PowerShell foreach item in set vikoristannya item abo set ForEach Object vikoristannya Python for item in iterator instance vikoristannya itemDostrokovij vihid i propusk iteraciyiBagato yaki z mov programuvannya sho mayut v svoyemu sintaksisi ciklichni konstrukciyi mayut takozh osoblivi komandi yaki dozvolyayut porushiti poryadok roboti cih konstrukcij komandu dostrokovogo vihodu z ciklu ta komandu propusku iteraciyi Dostrokovij vihid z ciklu Komanda dostrokovogo vihodu zastosovuyetsya koli neobhidno perervati vikonannya ciklu v yakomu umovi vihodu she ne dosyagnuto Take buvaye napriklad koli pid chas vikonannya ciklu zustrichayetsya pomilka pislya yakoyi podalshe vikonannya ciklu ne maye sensu Komanda dostrokovogo vihodu zazvichaj nazivayetsya EXIT abo break a yiyi diya analogichna diyi komandi bezumovnogo perehodu goto na komandu rozmishenu bezposeredno za ciklom vseredini yakogo cya komanda znahoditsya Tak u movi Si dva nizhchenavedenih cikli pracyuyut cilkom odnakovo Zastosuvannya operatora break while lt umova gt operatori if lt pomilka gt break operatori prodovzhennya programi Analogichnij urivok bez break while lt umova gt operatori if lt pomilka gt goto break label operatori break label prodovzhennya programi V oboh vipadkah yaksho v tili ciklu vikonuyetsya umova lt pomilka gt bude vikonanij perehid na operatori poznacheni yak prodovzhennya programi Takim chinom operator dostrokovogo vihodu z ciklu za suttyu prosto maskuye bezumovnij perehid odnak vikoristannyu break varto viddati perevagu pered vikoristannyam goto oskilki povedinka break chitko zadana movoyu potencijno mensh nebezpechna nemaye napriklad imovirnosti pomilitisya z roztashuvannyam abo nazvoyu mitki perehodu Okrim togo yavnij dostrokovij vihid z ciklu ne porushuye zasad strukturnogo programuvannya Zvichajnij operator dostrokovogo vihodu pererivaye robotu togo ciklu v yakomu vin bezposeredno znahoditsya V bagatoh movah programuvannya funkcionalnist cogo operatora rozshirena vin dozvolyaye vihoditi z dekilkoh vkladenih cikliv div nizhche U takih vipadkah cikl z yakogo treba vijti poznachayetsya mitkoyu a v operatori dostrokovogo vihodu vkazuyetsya cya mitka Propusk iteraciyi Danij operator zastosovuyetsya koli v potochnij iteraciyi ciklu neobhidno propustiti vsi komandi do kincya tilu ciklu Pri comu sam cikl ne pererivayetsya umovi prodovzhennya abo vihodu obchislyuyutsya zvichajnim chinom U movi Si ta yiyi movah nashadkah yak komanda propusku iteraciyi vikoristovuyetsya operator continue v konstrukciyi ciklu Diya cogo operatora analogichna bezumovnomu perehodu na ryadok vseredini tila ciklu nastupnij za ostannoyu jogo komandoyu Napriklad kod na Si yakij znahodit sumu vsih dodatnih elementiv masivu mozhe mati takij viglyad int arr ARRSIZE Sumuvannya okremo vsih i tilki dodatnih elementiv masivu arr iz zastosuvannyam continue int sum all 0 int sum pos 0 for int i 0 i lt ARRSIZE i sum all arr i if arr i lt 0 continue sum pos arr i Te same z goto int sum all 0 int sum pos 0 for int i 0 i lt ARRSIZE i sum all arr i if arr i lt 0 goto cont label sum pos arr i cont label Z drugogo urivku yasno vidno yak pracyuye continue vin prosto peredaye vikonannya za ostannyu komandu ciklu iz propuskom komandi sumuvannya yaksho chergovij element masivu ne zadovilnyaye umovi Takim chinom v sum pos nakopichuyetsya suma tilki dodatnih elementiv masivu Neobhidnist Z poglyadu strukturnogo programuvannya komandi dostrokovogo vihodu z ciklu i prodovzhennya iteraciyi ye nadlishkovimi oskilki yih diya mozhe buti legko zmodelovana chisto strukturnimi zasobami Bilsh togo na dumku ryada teoretikiv programuvannya zokrema Edsgera Dejkstri sam fakt vikoristannya v programi nestrukturnih zasobiv chi ce klasichnij bezumovnij perehid chi bud yaka z jogo specialnih form na kshtalt break abo continue ye svidchennyam nedostatno propracovanogo algoritmu rozv yazannya zadachi Odnak na praktici kod programi chasto ye zapisom nayavnogo ranish sformulvanogo algoritmu perepracovuvati yakij nedocilno za chisto tehnichnimi prichinami Sproba zaminiti v takomu kodi komandu dostrokovogo vihodu na strukturni konstrukciyi chasto viyavlyayetsya neefektivnoyu abo gromizdkoyu Napriklad vishepodanij urivok kodu mozhe buti zapisanij bez vikoristannya komandi break tak dostrokovij vihid z ciklu bez break bool flag false praporec dostrokovogo zavershennya while lt umova gt amp amp flag operatori if lt pomilka gt flag true else operatori prodovzhennya programi Legko perekonatis sho cej urivok pracyuvatime tak samo yak i poperednij riznicya lish v tomu sho v misci perevirki na pomilku zamist bezposerednogo vihodu z ciklu vstanovlyuyetsya praporec dostrokovogo vihodu yakij pereviryayetsya potomu v shtatnij umovi prodovzhennya ciklu Odnak dlya vidmovi vid komandi dostrokovogo vihodu dovelos dodati v programu opis praporcya i drugu gilku umovnogo operatora do togo zh vidbulosya rozmittya logiki programi rishennya pro dostrokovij vihid prijmayetsya v odnomu misci a vikonuyetsya v inshomu V rezultati programa ne stala ani prostishoyu ani korotshoyu ani zrozumilishoyu Desho inakshe stoyit sprava z komandoyu propusku iteraciyi Vona yak pravilo duzhe legko zaminyuyetsya na umovnij operator Napriklad podanij vishe urivok sumuvannya masivu mozhna zapisati tak int arr ARRSIZE Sumuvannya okremo vsih i tilki dodatnih elementiv masivu arr iz zaminoyu continue int sum all 0 int sum pos 0 for int i 0 i lt ARRSIZE i sum all arr i if arr i gt 0 Umova zaminena na protilezhnu sum pos arr i Yak bachimo dostatno bulo zaminiti umovu na protilezhnu ta pomistiti zaklyuchnu chastinu chastinu tila ciklu v umovnij operator Mozhna zauvazhiti sho programa stala korotshoyu za rahunok vidalennya komandi propusku iteraciyi i odnochasno bilsh logino iz kodu bezposeredno vidno sho sumuyutsya dodatni elementi Nezvazhayuchi na obmezhenu korisnist i mozhlivist zamini na inshi movni konstrukciyi komandi propusku iteraciyi i osoblivo dostrokovogo vihodu z ciklu v okremih vipadkah viyavlyayutsya vkraj korisnimi same cherez ce voni zberigayutsya v suchasnih movah programuvannya Vkladeni cikliIsnuye mozhlivist utvoriti cikl vseredini tila drugogo ciklu Takij cikl zvetsya vkladenim ciklom Vkladenij cikl shodo ciklu v tilo yakogo vin vkladenij bude jmenuvatisya vnutrishnim ciklom i navpaki cikl v tili yakogo isnuye vkladenij cikl bude jmenuvatis zovnishnim shodo vkladenogo Vseredini vkladenogo ciklu mozhe buti nastupnij vkladenij cikl utvoryuyuchi nastupnij riven vkladenosti i tak dali Kilkist rivniv vkladenosti yak pravilo ne obmezhuyetsya Povna kilkist vikonannya tila vnutrishnogo ciklu ne perevishuye dobutku kilkosti iteracij vnutrishnogo i vsih zovnishnih cikliv Napriklad vzyav tri vkladenih odin v odnogo cikli kozhnij po 10 iteracij otrimayemo 10 vikonan tila zovnishnogo ciklu 100 dlya ciklu drugogo rivnya i 1000 v najbilsh vkladenomu cikli Odna z problem pov yazanih iz vkladenimi ciklami organizaciya dostrokovogo vihodu z nih V bagatoh movah programuvannyaye operator dostrokovogo zavershennya ciklu break u Si exit u Paskali last v Perl i t in ale vin yak pravilo zabezpechuye vihid lishe z ciklu togo rivnya zvidki viklikanij Viklik jogo u vkladenomu cikli prizvede do zavershennya lish cogo vkladenogo ciklu zovnishnij cikl prodovzhit vikonannya Problema mozhe zdatisya nadumanoyu ale vona dijsno inodi vinikaye pri programuvanni skladnoyi obrobki danih koli algoritm vimagaye negajnogo pererivannya za pevnih umov nayavnist yakih mozhna pereviriti tilki v gluboko vkladenomu cikli Rozv yazkiv problemi vihodu z vkladenih cikliv dekilka Najprostishij vikoristati operator bezumovnogo perehodu goto dlya vihodu v tochku programi nastupnu bezposeredno za vkladenim ciklom Cej variant kritikuyetsya prihilnikami strukturnogo programuvannya yak i vsi konstrukciyi sho vimagayut vikoristannya goto Deyaki movi programuvannya napriklad prosto ne mayut operatora bezumovnogo perehodu tomu v nih podibna situaciya nemozhliva Alternativa vikoristovuvati shtatni zasobi zavershennya cikliv u vipadku neobhidnosti vstanovlyuyuchi osoblivi praporci sho vimagayut negajnogo zavershennya obrobki Nedolik uskladnennya kodu znizhennya produktivnosti bez yakih nebud perevag okrim teoretichnoyi pravilnosti cherez vidmovu vid goto Roztashuvannya vkladenogo ciklu v proceduri Ideya polyagaye v tomu shob vsyu diyu v yakij mozhe viniknuti potreba dostrokovogo pererivannya oformiti u viglyadi okremoyi proceduri i dlya dostrokovogo vihodu viklikati operator vihodu z proceduri yaksho takij v nayavnosti v movi programuvannya V movi Si napriklad mozhna pobuduvati funkciyu z vkladenim ciklom a vihid z neyu organizuvati za dopomogoyu operatora return Nedolik vidilennya urivka kodu v okremu proceduru ne zavzhdi obgruntovane i ne vsi movi mayut shtatni zasobi dlya dostrokovogo zavershennya procedur Skoristatis mehanizmom generaciyi i obrobki vinyatkiv vinyatkovih situacij yakij zaraz nayavnij u bilshosti mov visokogo rivnya V comu vipadku v neshtatnij situaciyi kod u vkladenomu cikli stvoryuye vinyatkovu situaciyu a blok obrobki vinyatkiv v yakomu znahoditsya vkladenij cikl perehoplyuye ta obroblyaye jogo Nedolik realizaciya mehanizmu obrobki vinyatkiv u bilshosti vipadkiv taka sho shvidkist roboti programi zmenshuyetsya Pravda v suchasnih umovah ce ne osoblivo vazhlivo praktichno vtrata produktivnosti taka mala sho maye znachennya lish dlya zovsim nebagatoh zastosunkiv Nasamkinec isnuyut specalni movni zasobi dlya vihodu z vkladenih cikliv Tak v movi Ada programist mozhe poznachiti zovnishnij cikl poznachkoyu i v komandi dostrokovogo zavershennya ciklu vkazati cyu poznachku Vihid vidbudetsya ne z potochnogo ciklu a z usih vkladenih cikliv do poznachenogo vklyuchno loop y FOR y IN 1 MAXY DO BEGIN FOR x IN 1 MAXX DO BEGIN EXIT loop y WHEN object found x y END ENDCikli z dekilkoma gilkami iz vartamiCikl Dejkstri V teoriyi programuvannya vidoma she odna forma ciklichnoyi konstrukciyi yaka principovo vidriznyayetsya vid klasichnih yaka otrimala nazvu cikl Dejkstri za im yam Edsgera Dejkstri yakij pershim yiyi opisav V klasichnomu dejksrivskomu opisi vona maye takij viglyad do P1 S1 Pn Sn od Tut do poznachka pochatku konstrukciyi ciklu od poznachka zavershennya konstrukciyi ciklu Pi i ta varta logichnij viraz yakij mozhe mati znachennya istina abo hiba Si i a komanda pid vartoyu Cikl skladayetsya z odniyeyi chi dekilkoh gilok kozhna z yakih yavlyaye soboyu paru z varti i komandi v dijsnosti komanda mozhe buti skladnoyu Pri vikonanni ciklu Dejkstri v kozhnij iteraciyi vidbuvayetsya obchislennya vart Yaksho hocha b odna z nih istinna vikonuyetsya vidpovidna komanda pislya chogo pochinayetsya nova iteraciya yaksho istinni dekilka vartovih umov vikonuyetsya lish odna komanda Yaksho vsi varti hibni cikl zavershuyetsya Nevazhko zauvazhiti sho cikl Deckstri z odniyeyu vartoyu i odniyeyu komandoyu yavlyaye soboyu zvichajnij cikl z peredumovoyu Hocha cikl Dejkstri buv vinajdenij she v 1970 h specialnih konstrukcij dlya jogo stvorennya v movah programuvannya ne isnuye Yedinim vinyatkom stav neshodavno stvorenij persha realna mova programuvannya sho yavno pidtrimuye cikl z dekilkoma gilkami z vartami Vtim cikl Dejkstri mozhe buti bez osoblivih trudnoshcv zmodelovanij za dopomogoyu zvichajnih konstrukcij mov programuvannya Os odin z mozhlivih prikladiv jogo realizaciyi na movi Ada loop if P1 then S1 elsif Pn then Sn else exit end if end loop Tut P1 Pn vartovi umovi varti a S1 Sn vidpovidni komandi Cikl Dejkstri zruchnij pri realizaciyi specifichnih obchislen yaki povtoryuyutsya i yaki nezruchno opisuvati za dopomogoyu tradicijnishih ciklichnih konstrukcij Napriklad cim ciklom prirodno predstavlyayetsya skinchennij avtomat kozhna gilka vidpovidaye odnomu stanu avtomata varti vibudovuyutsya tak shob v potochnij iteraciyi obiralas gilka vidpovidna potochnomu stanu avtomata a kod varti zabezpechuye vikonannya obchislen v potochnomu stani i perehid v nastupne tobto taka zmina zminnih pislya yakoyi na nastupnij iteraciyi bude istinoyu varta potribnoyi gilki Cikl pavuk Legko bachiti sho cikl Dejkstri ne mistit yavnoyi umovi prodovzhennya abo vihodu z ciklu sho ne vsima teoretikami programuvannya rozglyadayetsya yak blago Tomu bulo zaproponovana uskladnena konstrukciya ciklu Dejkstri yaka otrimala nazvu cikl pavuk U tij zhe notaciyi vona maye takij viglyad do P1 S1 Pn Sn out Q1 T1 Qn Tn else E od Tut pislya poznachki out dodano gilki zavershennya utvoreni z umov vihodu Qi i komand zavershennya Ti Okrim togo dodano gilku alternativnogo zavershennya else z komandoyu E Cikl pavuk vikonuyutsya takim chinom Obchislyuyutsya vartovi Yaksho isnuye istinnij vartovij vikonuyetsya vidpovidna komanda Obchislyuyetsya umovi vihodu Yaksho isnuye istinna umova vihodu vikonuyetsya vidpovidna komanda zavershennya pislya chogo vikonannya ciklu zavershuyetsya Yaksho vsi umovi vihodu hibni pochinayetsya nastupna iteraciya ale tilki v tomu vipadku yaksho v potschnij iteraciyi buv istinnim hocha b odin z vartovih Yaksho v danij iteraciyi viyavilis hibnimi i vsi vartovi i vsi umovi vihodu vikonuyetsya komanda alternativnogo zavershennya E pislya chogo vikonannya ciklu pererivayetsya Struktura ciklu pavuka dozvolyaye granichno strogo opisati umovi vikonannya ciklu Zgidno z teoretichnimi polozhennyami gilka altenativnogo zavershennya ne povinna vikoristovuvatisya yak odin iz variantiv korektnogo pripinennya roboti ciklu vsi taki varianti mayut buti oformleni v viglyadi vidpovidnih gilok zavershennya z yavnoyu umovoyu vona sluguye lish dlya togo shob vidslidkuvati situaciyu koli za yakihos prichin cikl pochav vikonuvatis neshtatno Tobto komanda alternativnogo zavershennya mozhe lishe analizuvati prichini pomilki ta podavati rezultati rozboru Hoch yavnoyi pidtrimki na rivni sintaksisu movi dlya cogo ciklu ne isnuye v zhodnij movi programuvannya cikl pavuk yak i cikl Dejkstri mozhe buti zmodelovanim za dopomogoyu tradicijnih strukturnih konstrukcij Cikavi faktiNiklaus Virt svogo chasu nazivav cikl z lichilnikom marginalnim stverdzhuyuchi sho taka konstrukciya ye nadlishkovoyu i maye buti viklyuchena z sintaksisu mov programuvannya yak nesistemna Zgidno z jogo predstavlennyam u movi programuvannya Oberon ciklu z lichilnikom ne bulo Odnak u movi Oberon 2 stvorenij Virtom i Mossenbokom yak rozvitok Oberona cikl z lichilnikom FOR z yavivsya v interesah praktichnoyi zruchnosti vikoristannya Div takozhNeskinchennij cikl RekursiyaMetodi optimizaciyi ciklivRozmotuvannya cikluPrimitkiStrogo kazhuchi totozhnist ne povna bo inakshe bude pracyuvati operator continue Oberon voploshenie mechty Niklausa Virta Ce nezavershena stattya pro movi programuvannya Vi mozhete dopomogti proyektu vipravivshi abo dopisavshi yiyi Cya stattya ne mistit posilan na dzherela Vi mozhete dopomogti polipshiti cyu stattyu dodavshi posilannya na nadijni avtoritetni dzherela Material bez dzherel mozhe buti piddano sumnivu ta vilucheno cherven 2011