Процедура break и оператор goto

Но в Delphi есть и более элегантные средства для прерывания любых цик­лов - достаточно в нужном месте тела цикла записать слова breakили goto.

Слегка изменим последний пример:


repeat i:= i+1;
if i > 5 then break; until FALSE;
frmMain.lstProtokol.Items.add(inttostr(i));

Мы избавились от флага, и теперь при наступлении нужного нам события (i> 5) выполняется процедура break, и цикл заканчивается.

Действие процедуры breakв цикле whileрассмотрите самостоятельно, а цикл forпрерывается ещё проще:


for i:= 1 to 20 do begin if i > 5 then break;
end;  
frmMain.lstProtokol.Items.add(inttostr(i));

 

Пример из школьной жизни. Нам нужно определить, под каким номером записан Ваня Ургант в классном журнале. Как учит нас Президент Медведев, вся документация должна вестись в элек­тронном виде. Значит, классный журнал можно представить себе как массив, в котором записаны все ученики (числом 30 голов). Всё - начинаем перебирать массив:


for i:= 1 to 30 do begin
if name = ’Ваня Ургант’ then begin n:= i; break; end; end;
frmMain.lstProtokol.Items.add(inttostr(n));

Как только мы найдём в журнале нашего Ваню, дальше искать смысла нет - Ваня Ургант единственный и неповторимый! В пере­менной nпосле окончания цикла мы и найдём номер Вани в класс­ном журнале. И хотя фамилия Вани начинается на букву «у», скорее всего это будет номер 1, ведь Ваня даже на Первом первый!

 

Можно привести и другие примеры - уже из спортивной жизни. Один удачный удар - нокаут, и бой между Николаем Валуевым и Ваней Ургантом преждевременно заканчивается. Такая же досада случилась и у хоккеистов сборной России по хоккею в матче с фин­нами, когда эти горячие парни забили нам шайбу в дополнитель­ном периоде. Есть и более огорчительные для мужского достоин­ства примеры, но упоминать их было бы неспортивно!

 

Вместо breakвы можете использовать оператор goto, который передаёт управление какому-нибудь оператору за пределами цикла. Этот оператор должен быть обозначен меткой (иначе получится, как в сказке, пойди ту­да, не знаю куда!), которая должна быть объявлена в процедуре:


procedure _cycl; label vyhod;
var
i: integer; flag: boolean;
while TRUE do begin
i:= i + 1;
if i > 5 then goto vyhod;
end;
vyhod: frmMain.lstProtokol.Items.add(inttostr(i));
 

 

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


И последнее: при выходе из цикла с помощью gotoс программой ничего не случится, но никогда не запрыгивайте извне внутрь цикла! 

 

Процедура exit

 

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

Например, если при выполнении цикла whileсработала процедура exit,


while TRUE do begin i:= i + 1;
if i > 5 then exit;
end;
frmMain.lstProtokol.Items.add(inttostr(i));
end;

то число 6 в окне списка напечатано не будет, поскольку мы сразу же «уле­тим» в запроцедурное пространство. Такие «полные улёты» бывают по­лезны при выходе из вложенных циклов. 

В последних версиях Delphiпроцедура exitможет возвращать значение то­го же типа, что и функция пользователя.

Так действует оператор returnв языках C# и C++.

Если функция exitне возвращает никакого значения, то ни круглые скобки, ни аргумент указывать не нужно.

Например, «по старинке» мы можем написать вот такую функцию GetRandom, которая возвращает случайное целое число в диапазоне iLo..iHi\


Function GetRandom(iLo, iHi: Integer): Integer;
begin
GetRandom := iLo + (Random (iHi - iLo + 1))
end;
Или
Function
GetRandom(iLo, iHi: Integer):
Integer;
begin 
Result:= iLo + (Random (iHi - iLo +1))
end;
 

 

Эту же функцию мы можем обновить, возвращая случайное значение как аргумент функции exit:


Function GetRandom(iLo, iHi: Integer): Integer;
begin
exit(iLo + (Random (iHi - iLo + 1)));
end;

Естественно, в этой функции нет особого резона возвращать значение с помощью процедуры exit. Мы это сделали только для примера. Правильнее использовать процедуру exitименно для досрочного завершения функции.

Процедура continue

Процедура continue прерывает только текущую итерацию, и тело цикла выполняется с начала.

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


n:=0;
for i:= 1 to 30 do begin
if uspev = 2 then continue; n:= n+1; end;
frmMain.lstProtokol.Items.add(inttostr(n));

Как только мы наткнёмся на двоечника, сразу же переходим к следующему ученику, а троечников, хорошистов и отличников валим в одну кучу. Те­перь классный руководитель точно знает, сколько билетов ему заказывать для поездки в Италию. Плюс ещё один билет - для Вани.

Более серьёзные и полезные примеры с процедурой continueвы найдёте дальше в этой книге. 

 Выводы 

Используйте оператор for, когда число итераций известно заранее, а опе­раторы whileи repeat- если не известно.

Если вы уверены, что цикл может быть выполнен хотя бы 1 раз, исполь­зуйте repeat, в противном случае while.

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

Для досрочного выхода из цикла пользуйтесь процедурами breakи exit, а также оператором goto.

������� ������ ��� dle ������� ��������� ������

Помоги проекту! Расскажи друзьям об этом сайте: