Цикл (програмування)

Цикл — різновид керівної конструкції у високорівневих мовах програмування, призначений для організації багаторазового виконання набору інструкцій (команд). Також циклом може називатися будь-яка багатократно виконувана послідовність команд, організована будь-яким чином (наприклад, із допомогою умовного переходу).

Визначення

Послідовність інструкцій, призначена для багаторазового виконання, називається тілом циклу. Одноразове виконання тіла циклу називається ітерацією. Вираз, що визначає чи буде вчергове виконуватися ітерація, чи цикл завершиться, називається умовою виходу або умовою завершення циклу (або умовою продовження) залежно від того, як інтерпретується його істинність — як ознака необхідності завершення чи продовження циклу. Змінна, в якій зберігається номер поточної ітерації, називається лічильником ітерацій циклу або просто лічильником циклу. Цикл не обов’язково містить лічильник, також лічильник не забов’язаний бути одним — умова виходу із циклу може залежати від декількох змінюваних в циклі змінних, а може визначатися зовнішніми умовами (наприклад, настанням певного часу), в останньому випадку лічильник взагалі не знадобиться.

Частинами виконання будь-якого циклу є початкова ініціалізація змінних циклу, перевірка умови виходу, виконання тіла циклу та оновлення змінної циклу на кожній ітерації. Крім того, більшість мов програмування надають засоби для дострокового керування циклом, наприклад, оператори завершення циклу, тобто виходу з циклу незалежно від істинності умови виходу (в мові С — break) і оператори пропущення ітерації (в мові С — continue).

Різновиди циклів

Безумовні цикли

Іноді в програмах використовуються цикли, вихід з яких не передбачено логікою програми. Такі цикли називаються безумовними або нескінченними. Особливих синтаксичних засобів для створення таких циклів, через їхню нетиповість, мови програмування не передбачають, тому такі цикли створюються за допомогою конструкцій призначених для створення звичайних (або умовних) циклів. Для забезпечення нескінченного повторення перевірка умови в такому циклі відсутня (якщо дозволяє синтаксис, як, наприклад, у циклі LOOP … END LOOP мови Ада), або замінюється константним значенням (while true do … в Паскаль).

Цикл з передумовою

Цикл з передумовою — цикл, що виконується доки істинна деяка умова, вказана перед його початком. Ця умова перевіряється до початку виконання тіла циклу, тому тіло може бути не виконане жодного разу (якщо умова з початку хибна). У більшості процедурних мов програмування здійснюється за допомогою інструкції while, звідси його друга назва — while-цикл.

На мові Паскаль цикл з передумовою має такий вигляд:

while <умова> do
begin 
  <тіло циклу> 
end;

На мові Сі:

while(<умова>)
{
   <тіло циклу>
}

Цикл з післяумовою

Докладніше: Цикл do 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 (цикл)

Цикл з лічильником — цикл, в якому деяка змінна змінює своє значення від заданого початкового значення до кінцевого значення з деяким кроком, і для кожного значення цієї змінної тіло циклу виконується один раз. В більшості процедурних мов програмування реалізується оператором 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)
{
  ... тіло циклу
}

фактично являє собою інший варіант запису конструкції[1]:

i = 0;
while (i < 10)
{
  ... тіло циклу
  ++i;
}

Тобто в конструкції for спочатку пишеться довільне речення ініціалізації циклу, потім — умова продовження і, насамкінець, виконувана після кожного тіла циклу деяка операція (це не обов’язково має бути зміна лічильника; це може бути модифікація вказівника або будь-яка зовсім стороння дія). Для мов такого типу вищезазначена проблема розв'язується дуже просто: змінна-лічильник поводиться цілком передбачувано і по завершені циклу зберігає своє останнє значення.

Цикл по колекції (foreach)

Ще одним варіантом є цикл, який пробігає елементи з деякої множини без явного задання порядку перебору цих об’єктів. Такі цикли являють собою формальний запис інструкції виду: «Виконати дію X для всіх елементів множини M». Теоретично такий цикл ніяким чином не визначає, в якому порядку буде застосовуватись дія до елементів множини, хоча певні мови програмування, звісно, можуть встановлювати конкретний порядок перебору елементів. Довільність дає можливість оптимізації виконання циклу за рахунок організації доступу в найвигіднішому порядку, а не в порядку зазначеному програмістом. За наявності можливості паралельного виконання декількох операцій можливо навіть розподілення виконання циклу по колекції, коли одна і та сама операція одночасно виконується на різних обчислювальних модулях для різних об’єктів, при тому що логічно програма залишається послідовною.

Цикли по колекції реалізовано в деяких мовах програмування (C#, Eiffel, Java, JavaScript, Perl, Python, PHP, LISP, Tcl, C++11 та ін.) — вони дають змогу цикл по всіх елементах даної колекції об'єктів. У визначенні такого циклу треба вказати лише колекцію об’єктів і змінну, якій в тілі циклу буде присвоєне значення оброблюваного в цей час об’єкта (чи посилання на нього). В різних мовах програмування синтаксис оператора різний:

C#:

foreach (type item in set) 
{
    //використання item
}


C++, стандарт 2011 року:

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
}


Eiffel:

across set as cursor loop
    -- використання cursor.item
end


Java:

for (type item : set) 
{
    //використання item
}


JavaScript:

for (txtProperty in objObject)
  {
  /*
  використання:
  objObject [txtProperty]
  */
  }


PHP:

foreach ($arr as $item) {
    /* використання $item*/
}


Visual Basic.NET:

For Each item As type In set
    'використання item
Next item


Windows PowerShell:

foreach ($item in $set) {
  # використання $item
}

або

$set | ForEach-Object {
  # використання $_
}

Python

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. Деякі мови програмування, наприклад, Модула-2, просто не мають оператора безумовного переходу, тому в них подібна ситуація неможлива.
  • Альтернатива — використовувати штатні засоби завершення циклів, у випадку необхідності встановлюючи особливі прапорці, що вимагають негайного завершення обробки. Недолік — ускладнення коду, зниження продуктивності без яких-небудь переваг, окрім теоретичної «правильності» через відмову від 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

Цикли з декількома гілками із вартами

Цикл Дейкстри

В теорії програмування відома ще одна форма циклічної конструкції, яка принципово відрізняється від «класичних», яка отримала назву «цикл Дейкстри», за ім'ям Едсгера Дейкстри, який першим її описав. В класичному дейксрівському описі вона має такий вигляд:

 do
   P1 → S1,
     …
   Pn → Sn
 od

Тут do — позначка початку конструкції циклу, od — позначка завершення конструкції циклу, Pi — i-та варта (логічний вираз, який може мати значення «істина» або «хиба»), Si — i-а команда під вартою. Цикл складається з однієї чи декількох гілок, кожна з яких являє собою пару з варти і команди (в дійсності команда може бути складною).

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

Хоча цикл Дейкстри був винайдений ще в 1970-х, спеціальних конструкцій для його створення в мовах програмування не існує. Єдиним винятком став нещодавно створений Оберон-07 — перша реальна мова програмування, що явно підтримує цикл з декількома гілками з вартами. Втім, цикл Дейкстри може бути без особливих труднощів змодельований за допомогою звичайних конструкцій мов програмування. Ось один з можливих прикладів його реалізації на мові Ада:

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 з'явився в інтересах практичної зручності використання[2].

Див. також

Методи оптимизації циклів

Примітки

  1. Строго кажучи, тотожність не повна, бо інакше буде працювати оператор continue.
  2. Оберон — воплощение мечты Никлауса Вирта

Read other articles:

Joko Slamet Pa Sahli TK II Bidang Intekmil Sahli Bidang Intekmil Dan Siber Panglima TNIMasa jabatan2022–2022 PenggantiM. Daradjat Informasi pribadiLahir0 April 1964 (umur 59)Madiun, Jawa TimurSuami/istriNy. Vera SyilviaAnak1. Letda Inf. Rovi Ardya Prawira, S.Tr.(Han).2. Ipda Pol. Rizki Ardiza Prawira, S.Tr., K,M.H.3.Alya Viera ShafiraAlma materAkademi Militer (1989)Karier militerPihak IndonesiaDinas/cabang TNI Angkatan DaratMasa dinas1989—2022Pangkat Brigadir Jenderal TNISa...

 

The list of shipwrecks in 2014 includes ships sunk, foundered, grounded, or otherwise lost during 2014. This is a dynamic list and may never be able to satisfy particular standards for completeness. You can help by adding missing items with reliable sources. table of contents ← 2013 2014 2015 → Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec References January 1 January List of shipwrecks: 1 January 2014 Ship State Description Peace  Cambodia The cargo ship issued ...

 

Italo Calvino nel 1961 Italo Calvino (Santiago de Las Vegas de La Habana, 15 ottobre 1923 – Siena, 19 settembre 1985) è stato uno scrittore e paroliere italiano. Intellettuale di grande impegno politico, civile e culturale, è stato uno dei narratori italiani più importanti del secondo Novecento. Ha seguito molte delle principali tendenze letterarie a lui coeve, dal neorealismo al postmoderno, ma tenendo sempre una certa distanza da esse e svolgendo un percorso di ricerca personale e coer...

U.S. airbase Andrews Field redirects here. For other uses, see Andrews Field (disambiguation). For the Philippine Air Force base, see Edwin Andrews Air Base. Andrews Air Force BaseCamp Springs, Maryland in the United States of AmericaPresident John F. Kennedy speaks with Secretary of State, Dean Rusk and Military Aide to the President, General Chester V. Clifton, upon his arrival aboard Air Force One at Andrews Air Force Base, Maryland, following Easter vacation in Palm Beach, Florida, 2...

 

James FortenBiographieNaissance 2 septembre 1766PhiladelphieDécès 4 mars 1842 (à 75 ans)PhiladelphieSépulture Eden Cemetery (en)Nationalité américaineActivités Entrepreneur, abolitionnisteConjoint Charlotte Vandine Forten (en)Enfants Margaretta Forten (en)Harriet Forten Purvis (en)Sarah Louisa Forten PurvisVue de la sépulture.modifier - modifier le code - modifier Wikidata James Forten, né le 2 septembre 1766 à Philadelphie, dans l'État de la Pennsylvanie et mort le 4 mars 184...

 

Luigi MussoLahir(1924-07-28)28 Juli 1924Meninggal6 Juli 1958(1958-07-06) (umur 33)Karier Kejuaraan Dunia Formula SatuKebangsaan ItaliaTahun aktif1953–1958TimFerrari, MaseratiJumlah lomba25 (24 start)Juara Dunia0Menang1Podium7Total poin44Posisi pole0Lap tercepat1Lomba pertamaGrand Prix Italia 1953Menang pertamaGrand Prix Argentina 1956Menang terakhirGrand Prix Argentina 1956Lomba terakhirGrand Prix Prancis 1958 Luigi Musso (28 Juli 1924 – 6 Juli 1958) adalah seorang pemb...

Ulsan Hyundai FC울산 현대 FCNama lengkapUlsan Hyundai Football Club울산 현대 축구단JulukanHorangi (The Tigers)Gangs of AsiaThe Iron MacesBerdiri1983; 41 tahun lalu (1983), sebagai Hyundai Horang-i FCStadionUlsan Munsu Football Stadium (Big Crown)(Kapasitas: 44,466)Pemilik Hyundai Heavy IndustriesKetua Kwon Oh-GabManajer Cho Min-KookLiga K League 12022JuaraSitus webSitus web resmi klub Kostum kandang Kostum tandang Musim ini Ulsan Hyundai Football Club (Indonesia: Tim Sepa...

 

1807 Siege during the Franco-Swedish War This article is about the 1807 battle. For other battles, see Battle of Stralsund. Siege of StralsundPart of the Franco-Swedish WarPrise de Stralsund, by Hippolyte LecomteDate24 July – 24 August 1807LocationStralsund, Swedish PomeraniaResult French victoryTerritorialchanges Sweden loses Swedish PomeraniaBelligerents French Empire Spain Kingdom of Holland SwedenCommanders and leaders Édouard Mortier Guillaume Brune Jean de Kindelan Gustav IV Adolf Ha...

 

Canadian journalist Christie BlatchfordBlatchford on November 21, 2008BornChristie Marie Blatchford[1](1951-05-20)May 20, 1951[2]Rouyn-Noranda, Quebec, CanadaDiedFebruary 12, 2020(2020-02-12) (aged 68)Toronto, Ontario, CanadaAlma materRyerson UniversityOccupation(s)newspaper columnist, writer and broadcasterYears active1972-2019Notable credit(s)Toronto Sun, National Post, The Globe and MailSpouses Jim Oreto ​ ​(m. 1977; div. ...

2004 filmMoolaadéDirected byOusmane SembèneWritten byOusmane SembèneProduced byOusmane Sembène Thierry LenouvelStarringFatoumata CoulibalyHélène DiarraCinematographyDominique GentilEdited byAbdellatif RaïssMusic byBoncana NaigaRelease date 15 May 2004 (2004-05-15) (Cannes Film Festival) Running time124 minutesCountrySenegal / France / Burkina Faso / Cameroon / Morocco / TunisiaLanguagesBambaraFrenchBox officeUS$434,600[1] Moolaadé (magical protection) is a ...

 

Soccer Stadium in Columbus, Ohio Crew Stadium redirects here. For the new stadium opened in 2021, see Lower.com Field. Historic Crew StadiumAerial view of the stadium, 2018Former namesColumbus Crew Stadium (1999–2015)Mapfre Stadium (2015–2020)Address1 Black and Gold BoulevardLocationColumbus, OhioCoordinates40°0′34″N 82°59′28″W / 40.00944°N 82.99111°W / 40.00944; -82.99111OperatorColumbus CrewCapacity22,555 (1999–2008)20,145 (2008–2015)19,968 (2015�...

 

Lemuel dan ibunya Lemuel (Ibrani: לְמוּאֵל Ləmû’ēl) adalah nama dari seorang raja yang disebutkan dalam Amsal 31:1 dan 4, namun identitasnya masih tak jelas.[1] Spekulasi menyatakan bahwa Lemuel adalah Hezekiah, Salomo, seorang raja Massa, atau fiksi.[2] Referensi ^  Herbermann, Charles, ed. (1913). Lemuel. Catholic Encyclopedia. New York: Robert Appleton Company.  ^ Reagan, David (2018). King Lemuel (dalam bahasa Inggris). Learn the Bible. Diakses t...

Jasmine VillegasInformasi latar belakangNama lahirJasmine Marie VillegasNama lainJasmine VLahir7 Desember 1993 (umur 30)AsalSan Jose, California, A.S.GenreR&B, pop, soulPekerjaanPenyanyi, aktris, modelInstrumenVokalTahun aktif2003–sekarangLabelInterscope RecordsSitus webwww.jasminevmusic.com Jasmine Marie Villegas (lahir 7 Desember 1993), lebih dikenal sebagai Jasmine V, adalah penyanyi R&B dan pop Amerika Serikat. Setelah bertahun-tahun mengejar karier di musik, ia menandatang...

 

数学上の未解決問題 偶数の完全数は無数にあるか。また、奇数の完全数は存在するか。 完全数(かんぜんすう、英: perfect number)とは、自分自身が自分自身を除く正の約数の和に等しくなる自然数のことである。完全数の最初の4個は 6 (= 1 + 2 + 3)、28 (= 1 + 2 + 4 + 7 + 14)、496 (= 1 + 2 + 4 + 8 + 16 + 31 + 62 + 124 + 248)、8128 (= 1 + 2 + 4 + 8 + 16 + 32 + 64 + 127 + 254 + 508 + 1016 + 2032 + 4064) で�...

 

Artikel ini sebatang kara, artinya tidak ada artikel lain yang memiliki pranala balik ke halaman ini.Bantulah menambah pranala ke artikel ini dari artikel yang berhubungan atau coba peralatan pencari pranala.Tag ini diberikan pada Januari 2023. With the Century PengarangKim Il-sungNegaraKorea UtaraBahasaKoreaSubjek Kim Il-sung Kepala negara, Korea (Utara), biografi Gerakan pemberontakan Korea 1905–1945 GenreAutobiografiDiterbitkan1992 (1992) (edisi Korea)PenerbitPyongyang: Rumah Penerb...

Sports season2018 Suncorp Super Netball seasonLeagueSuncorp Super NetballSportNetballDuration28 April – 26 August 2018Number of teams8TV partner(s)Nine NetworkRegular season  Minor premiersGiants NetballSeason MVPJhaniele FowlerTop scorerJhaniele Fowler (WCF: 783 goals)FinalsChampionsSunshine Coast Lightning  Runners-upWest Coast FeverSeasons← 20172019 → The 2018 Suncorp Super Netball season was the second season of the premier netball league in Australia....

 

Defensive strategy in basketball This article includes a list of general references, but it lacks sufficient corresponding inline citations. Please help to improve this article by introducing more precise citations. (July 2010) (Learn how and when to remove this message) The amoeba defense is a defensive strategy in the game of basketball. History The amoeba defense was developed by Fran Webster, an assistant for the Pittsburgh Panthers men's basketball team.[1] In the 1970s, Webster ...

 

Painting by Peter Paul Rubens The Four ContinentsArtistPeter Paul RubensYear1612–1614 or 1615MediumOil on canvasDimensions209 cm × 284 cm (82 in × 112 in)LocationKunsthistorisches Museum, Vienna The Four Continents, also known as The Four Rivers of Paradise or The Four Corners of the World, is a painting by Flemish artist Peter Paul Rubens, made between 1612 and 1615. Rubens painted this piece during a time of truce in the Eighty Years' War known ...

إتي  خريطة الموقع تقسيم إداري البلد اليونان  [1] التقسيم الأعلى بالاماس  خصائص جغرافية إحداثيات 39°27′26″N 22°09′53″E / 39.4573°N 22.1648°E / 39.4573; 22.1648   الارتفاع 98 متر  السكان التعداد السكاني 959 (resident population of Greece و إحصاء السكان) (2021)1288 (resident population of Greece و إحصاء ...

 

Fifth season of the Victorian Football League (VFL) 1901 VFL premiership seasonEssendon 1901 VFL premiership teamDate4 May—7 September 1901Teams8PremiersEssendon 2nd premiershipMinor premiersGeelong 2nd minor premiershipLeading goalkicker medallistFred Hiskins (Essendon)(34 goals)Matches played71← 19001902 → The 1901 VFL season was the fifth season of the Victorian Football League (VFL), the highest-level senior Australian rules football competition in Victoria. The se...