Может пример немного неудачен, но можно написать так:Результат будет тем же
А кто говорит, что требуется именно результат? Может задача стоит в том, чтобы научиться прерывать цикл. Например все тот же код, но несколько измененный:
j := 0;
for i := 0 to 10 do
begin
inc(j);
if j = d then break
end;
(Извините, не удержался. Не люблю конструкции типо x:=x+1, я предпочитаю inc/dec) А
d может изменяться перед вызовом этого куска кода.
У меня до сих пор от таких "простых выходов" бросает в дрожь. Как представлю, что потом надо будет блок-схему чертить XD
Сразу видно, кто тут АСМа не нюхал.
Нарисуй блок-схему проги на асме и ты поймешь, что ты еще только в песочнице, а на стройку тебе еще рано.
Касаемо
goto - согласен. Моя первая программа на пасе (лет 10 назад) после АСМа содержала порядка 80(!) меток, но работала стабильно (+ метки я привык обзывать тематически, поэтому всегда понятно что и куда). Сейчас уже лет 8 как в моих программах метки если встречаются, то только в ассемблерных вставках, и то, стараюсь все делать линейно.
Например, надо выйти из куска кода, если ни одно условие не выполнено. Казалось бы, заюзай
goto и будет тебе счастье, так ведь нет - дурной тон. Ок, второй вариант -
break, но он работает только для циклов. Тогда приходится делать так:
var ok:boolean;
// Наш код
...
// Точка входа в кусок кода, который и проверяет что-то
while true do begin
ok:=false;
if (....) then break;
// Чтонить делаем и еще проверяем
if (....) then break;
// Еще чтото сделаем
if (....) then break;
// Делаем
....
// Выход из секции
ok:=true;
break;
end;
// Проверяем, выполнен ли весь инит?
if ok then begin
// Все ОК, работаем
end else begin
// Чтото обломалось, скажем юзеру
end;
В принципе все понятно, ведь правда? И гораздо аккуратнее и более читабельнее, чем вложенные условия. Если вложенных циклов несколько, то все будет так же:
// Наш код
while a<b do begin
ok:=false;
// Код
for d:=0 to 30 do begin
// Код
if (....) then break;
if (....) then ok:=true;
// Еще код
end;
if not ok then break;
// Продолжающийся код
end;
Ну, в общем идея понятна, да? Работаем с флагами. Кстати, прием хорошо работает и на асме.
В случае с
case'ом все по другому. Как и в циклах, там есть жесткое ограничение типов переменных, которые можно использовать. Например, можно использовать любые целые числа и делать условия:
var a:integer(byte, word, longint, dfword, etc...);
case a of
0 : // Код
3 : // Код
8..10 : // Код
else // Код
end;
Третье условие показывает диапазон значений, а
else сработает только если не сработает ни одно из условий.
case - это однопроходная структура, нужно помнить, что срабатывает только одно из условий и остальные не выполняться. Можно использовать даже
char:
var key,ext:char;
key:=readkey;
case key of
'Y','y' : //Код
#10 : //Код
#0 : begin ext:=readkey;
case ext of
#$33 : // код
end;
end;
end;
Видно, что я читаю код нажатой клавиши и делаю какие-то действия. Если код клавиши =0 (это символ, поэтому это будет chr(0) или #0), то надо дополнительно считать код расширенной клавиши и обработать вложенным
case, так опрашивают курсоры, функционалы и нумпад.
Можно использовать перечисления:
type TMode = (mdIdle, mdRun, mdStop);
var Mode:TMode;
key:char;
// Наш код
key:=readkey;
case key of
'R','r' : Mode:=mdRun;
'S','s' : Mode:=mdStop;
else Mode:=mdIdle;
// Теперь заюзаем наш флаг
case Mode of
mdIdle : sleep(1000);
mdStop : // Код
mdRun : // Код
else Mode:=mdIdle; // На всякий атас
end;
Понятно? Кстати, булево так и описано:
type boolean = (false, true);. Перечисления - на самом деле обычный байт (если их много, то больше: слово). Поэтому, первое обозначение получает код 0, второе 1 и т.д. Т.е. этот код эквивалентен предыдущему:
const mdIdle = 0;
mdRun = 1;
mdStop = 2;
var Mode:byte;
key:char;
// Наш код
key:=readkey;
case key of
'R','r' : Mode:=mdRun;
'S','s' : Mode:=mdStop;
else Mode:=mdIdle;
// Теперь заюзаем наш флаг
case Mode of
mdIdle : sleep(1000);
mdStop : // Код
mdRun : // Код
else Mode:=mdIdle; // На всякий атас
end;
Но первый более элегантен.