Із завданням дострокового виходу із кратних циклів зв'яжемо вивчення раніше невикористовуваного нами оператора безумовного переходу. Його загальний вид наступний:
Goto Мітка;
Тут Мітка – спеціальним образом зазначене місце в програмі. Дія Goto дуже просто: незалежно від яких-небудь умов він здійснює передачу керування на оператор, що випливає за міткою (звідси назва оператора). Кожна мітка має вигляд
m:
де m – ім'я, побудоване за звичайними правилами або цілочисельна константа від 0 до 9999 включно. Мітку недостатньо поставити перед потрібним оператором – її потрібно ще й оголосити в розділі описів оператором
label m;
Можна оголосити й кілька міток відразу, розділивши їх імена комами. Прийнято розташовувати оператор опису міток до оператора var. Таким чином, мітки й оператор goto дозволяють розв'язати завдання швидкого безпосереднього перехід до потрібного місця в програмі:
Label 10,20;
Var i,j:integer;
Begin
Write ('Уведіть значення I (i>2)');
Readln (i);
If i<3 then goto 10;
j:=2;
20:
if i mod j = 0 then write (j,' ');
j:=j+1;
if j<i then goto 20;
10:
End.
Ця нескладна програма дозволяє користувачеві ввести число i, більше двох, після чого друкує всі числа від 2 до i-1, на які i ділиться без залишку (перевірка залишку від розподілу i на j виконана операцією mod). У випадку введення користувачем неприпустимого значення i (меншого трьох) відбувається перехід на мітку 10:, розташовану перед закриваючим оператором end. – таким чином, програма відразу ж завершується. Мітка 20: дозволяє організувати цикл без використання операторів while, repeat або for. Дійсно, перед міткою 20: змінна j одержує початкове значення 2, потім, якщо i ділиться на j без залишку, значення j виводиться на екран, потім збільшується на одиницю й, якщо значення i не досягнуте, відбувається перехід на мітку 20:, що перевіряє вже нове значення j. Однак, і тієї, і іншої мети можна було досягтися без використання goto, застосовуючи тільки оператори циклу й break;.
Із правомірністю використання простого оператора goto зв'язані складні й багаторічні суперечки. Безсумнівно, що програму завжди можна написати, не прибігаючи до goto (іноді структурне програмування називають навіть "програмуванням без goto"), не викликає сумніву також, що використання міток і goto порушує й ускладнює сприйняття структури програми людиною. Однак авторові представляється надмірним вимога вигнати goto зовсім – у ряді ситуацій він просто зручніше, чим інші засоби. Представимо, що нам потрібно достроково вийти з подвійного (або взагалі кратного) циклу. Оператор break;, розташований у внутрішньому циклі, перерве його виконання, але виконання зовнішнього циклу продовжиться з наступного кроку. Без goto вийти " із усіх циклів відразу" можна хіба що із застосуванням спеціальних змінних-прапорів:
Var flag:boolean; {описали змінну-прапор}
. . .
Flag:=false; { до подвійного циклу прапор установлений в "неправду"}
While true do begin {почали зовнішній цикл}
While true do begin {почали внутрішній цикл}
. . .
If Умова then begin
{трапилося щось, що вимагає виходу з обох циклів відразу!}
Flag:=true; {ставимо прапор, повідомляючи зовнішньому циклу, що
потрібне завершення}
Break; {вихід із внутрішнього циклу}
End;
End;
If Flag=true then break;
{зовнішній цикл на кожному кроці повинен відслідковувати стан прапора!}
End;
Якщо цикл потрійний – при такому підході знадобиться вже два прапори, і так далі. Альтернативний шлях – установити максимальні значення керуючих змінних зовнішніх циклів – також не відповідає канонам структурного програмування. З goto усе виглядає простіше й естественней:
Label go1;
. . .
While true do begin {почали зовнішній цикл}
While true do begin {почали внутрішній цикл}
. . .
If Умова then goto go1; {вийшли із двох циклів відразу!}
End;
End;
Go1:
. . .
Другий аспект можливого використання goto пов'язаний з написанням складних підпрограм (див. главу 18), здатних завершуватися в різні моменти свого виконання. Найчастіше зручніше, щоб підпрограма мала всього одну "крапку виходу" – свій останній оператор, а достроковий вихід здійснюється установкою значення, що вертається, і переходом на останній оператор за допомогою goto.
Обмеження на використання goto наступні: мітка повинна перебувати в тому ж блоці програми, що й оператор goto. Таким чином, не можна перейти з однієї частини складної програми (такий, як процедура або функція, досліджувані в главі 18) в іншу. Безсумнівно, що ці обмеження введені розроблювачами, щоб не ускладнювати й без того складне сприйняття програм, що зловживають даним оператором.