Delphi repeat until описание

Обновлено: 02.07.2024

На прошлом уроке мы познакомились с циклами и разобрались, как использовать цикл по переменной. Сегодня мы разберём оставшиеся два вида циклов - цикл с предусловием и цикл с постусловием. Они очень похожи и просты в использовании.

Цикл WHILE - цикл с предусловием

Цикл WHILE (англ. "пока") - цикл, в котором условие находится перед телом цикла, а сам цикл выполняется до тех пор, пока условие не станет ложным.

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

Особенностью цикла с предусловием является то, что он может не выполниться ни разу - это произойдёт, если указанное условие изначально будет ложным. При этом, цикл может и стать "вечным" - если условие никогда не примет значения False. Именно поэтому следует следить за тем, чтобы всегда присутствовали условия для завершения работы цикла.

Решение задачи с помощью цикла WHILE

Вернёмся к нашей задаче. С помощью цикла с предусловием задача решается очень просто. Во-первых, нам потребуется переменная, в которой будет храниться текущее обрабатываемое число - это будут числа 1, 2, 3 и т.д. Во-вторых, ещё одна переменная потребуется для хранения суммы кубов чисел. Всё, этого достаточно. Теперь разберёмся, что писать в теле цикла. Там мы должны: а) увеличивать переменную-счётчик на единицу, чтобы последовательно проходить числа; б) увеличивать сумму на куб текущего числа. Условием цикла будет главное условие нашей задачи - достижение суммой 50000. Вот что получается:

В данном случае процесс "повешен" на кнопку (Button1), а результат выводится в текстовую метку (Label1). Вы спросите, почему выводится i-1, а не само число i ? Всё просто. Ведь переменная-счётчик увеличивается после того, как проверяется условие цикла, а значит и результат получится на единицу больше. Удостовериться в этом можно, добавив в тело цикла вывод промежуточных результатов (в примере - в текстовое поле Memo1):

Подводим итог

Итак, мы познакомились с циклами - специальными конструкциями языка для многократного выполнения одних и тех же команд. Как правило, циклы встречаются практически везде, даже в простых на первый взгляд программах. Что уж говорить о каких-либо вычислениях или работе с базами данных.

Эта конструкция чаще всего используется, когда заранее известно количество выполняемых операций. Рассмотрим синтаксис. Он выглядит так:

Цикл for существует до тех пор, пока счетчик находится в пределах между начального и конечного значений.

Эта программа просто в цикле выводит числа от 1 до 10, то есть счетчик цикла, который при каждом проходе цикла увеличивается на 1. Вот вторая похожая программа:

Она выведет все четные числа от 20 до -20. Это получается, когда мы умножаем счетчик на 2, он с каждым проходом цикла уменьшается на 1, а выводимое число уменьшается на 2. Вот еще одна программа, в ней мы выведем числа от -5 до 5 в прямом и обратном порядке.

Последняя программа по циклу for. Пусть пользователь задаст число кубиков и длину одной его стороны, а программа выведет объем каждого из них.

Теперь напишем программу, которая будет вычислять квадрат чисел от 20 до 1.

Здесь просто после инициализации переменно а выводится строка с самим числом и его квадратом, после чего с помощью процедуры dec() значение переменной a уменьшается на 1. Вот пример цикла While при работе со строками.

Она просто считает строку и выведет ее на экран, конечно, вывод можно было сделать просто writeln(st); но этот цикл может быть полезен, когда Вам нужно что-то подсчитать с строке или изменить, например, давайте подсчитаем количество цифр. Вот ее код:

Сначала компьютер по очереди выполняет операторы, стоящие после слова repeat, пока не дойдет до слова until, после чего проверяет истинность условия, стоящего после until. Если условие ложно, то компьютер снова по очереди выполняет эти операторы и снова проверяет истинность условия и т.д.

Если условие оказывается истинным, то работа оператора repeat прекращается и компьютер переходит к выполнению следующего по порядку оператора. Заметим, что цикл repeat выполниться всегда хотя бы один раз, независимо от условия, ведь сначала выполняются операторы внутри самого цикла, а только потом проверяется условие.

Как и в случае инструкции while, инструкция repeat Delphi применяется тогда, когда нужно провести повторные вычисление (осуществить организацию цикла), однако количество повторений в процессе создания программы заранее неизвестно, и поэтому это число можно определить лишь в момент выполнения программы, то есть количество зависит от хода вычислений.

Команды Break и Continue

Команда Break , выполняющая досрочный выход из цикла, работает не только в цикле FOR, но и в циклах WHILE и REPEAT. Аналогично, команда Continue , немедленно запускающая следующую итерацию цикла, может использоваться в циклах WHILE и REPEAT.

Последовательность цикла repeat Delphi:

Последовательность выполнения инструкции repeat в языке Delphi такова:

  1. На первом этапе осуществляется выполнение находящихся между служебными словами repeat и untilинструкций тела цикла.
  2. Далее определяется, какое значение примет выражение условие. Если это условие оказалось ложным (то есть условие приняло значение False), то происходит повторное выполнение инструкций тела цикла.
  3. Если же условие оказалось истинным (то есть оказалось равным True), то цикл repeat завершает свое выполнение.

В итоге получаем, что инструкции цикла, которые находятся между зарезервированными словами repeat и until, повторяются, пока условие является ложным (то есть пока условие принимает значение False).

Цикл repeat Delphi

Представим алгоритм (рис. ниже), который реализует инструкцию repeat:

Заметка. Инструкции цикла, располагающиеся между служебными словами repeat и until, должны выполняться минимум один раз. Чтобы цикл завершил свое выполнение, нужно следить за тем, чтобы инструкции цикла repeat, размещающиеся между зарезервированными словами repeat и until, в конце концов, изменяли значения переменных, которые входят в состав выражения условие.

Задача

Определить количество натуральных чисел, рассматривая их в порядке возрастания, сумма кубов которых не превышает 50000. Т.е. мы должны последовательно суммировать кубы чисел 1, 2, 3, . и делать это до тех пор, пока сумма не достигнет 50000, а в результате должны узнать, сколько чисел было пройдено.

Понятно, что решить задачу лучше использованием цикла. Но будет ли решение с циклом FOR оптимальным? Конечно, можно задать диапазон пробегаемых значений от 1 до 50000 - количество чисел точно будет найдено (очевидно, это кол-во будет даже менее 50, ведь 50^3 >> 50000). Но в этом случае придётся ставить дополнительное условие на значение суммы и выполнение команды Break.

Есть способ проще!

Как остановить цикл?

Очень часто спрашивают, как написать такой цикл, который можно было бы остановить нажатием кнопки на форме, или, к примеру, клавишей [Esc]. В простейшем случае реализовать такой механизм достаточно просто. Однако, данный метод является не совсем верным - есть более удобные и правильные средства для организации таких операций. Тем не менее, рассмотрим пример.

Задание: при нажатии кнопки "Старт" программа начинает генерировать случайные комбинации из латинских букв (верхнего регистра) длиной 10 символов и все эти комбинации отображаются в текстовом поле TMemo. При нажатии кнопки "Стоп" генерация должна быть прекращена.

Каким образом решить поставленную задачу? Сначала сделаем акцент на механизме остановки. Понятно, что в данном случае нужно задать вечный цикл, да-да, самый настоящий, но каким образом предусмотреть его остановку? Очевидно, что выбор падает либо на WHILE, либо на REPEAT. Остановить цикл можно либо изменив значение логического выражения, заданного для цикла, либо вызвав команду Break. Вопрос стоит теперь в том, как при нажатии кнопки "Стоп" изменить условие цикла, описанного в обработчике кнопки "Старт". Ответ прост - использовать ту память, которая доступна обработчикам обеих кнопок. Итак, заведём глобальную переменную, которая будет видна во всей программе. Глобальные переменные описываются над словом implementation модуля, там, где идёт описание формы:

В этой логической переменной мы будем хранить состояние процесса. Изначально будет стоять значение "ложь", а когда пользователь щёлкнет по кнопке "Стоп", мы изменим его в "истина".

На форме разместим Memo1 (TMemo) и 2 кнопки: Button1 ("Старт"), Button2 ("Стоп"). У кнопки "Стоп" поставим Enabled = False, т.е. выключим её.

Сразу приведу обработчики обеих кнопок, после чего подробно разберём их работу:

Начнём с кнопки "Стоп" (Button2). При её нажатии:
1) Значение переменной Stop устанавливается в True, т.е. мы подаём сигнал, что нужно остановиться;
2) Кнопку "Стоп" мы снова выключаем;
3) Кнопку "Старт" - наоборот, включаем.

Теперь кнопка "Старт" (Button1):
1) Кнопка "Стоп" включается, кнопка "Старт" выключается;
2) Переменной Stop присваивается значение False (если этого не сделать, то запустить процесс генерации второй раз будет невозможно);
3) Цикл с генерацией строки с условием на переменную Stop - цикл будет работать до тех пор, пока переменная Stop имеет значение False. Как только значение станет True, цикл сам завершит свою работу.

А теперь более подробно о том, что происходит в теле цикла. Начнём с генерации строки символов. Напомню, что строки можно складывать. Если сложить строку 'A' со строкой 'B', то получится строка 'AB'. Именно этот приём здесь и использован. Сначала мы делаем строку пустой, а затем последовательно добавляем в неё 10 произвольных символов. Как происходит добавление. Ну естественно с помощью цикла на 10 итераций. А вот выбор случайной из латинских букв не совсем прост и не для всех очевиден. Конечно, можно было заранее записать все буквы куда-либо (например, в массив, или в другую строковую переменную), а затем брать их оттуда. Но это не совсем хорошо, ведь можно сделать гораздо проще. В данном случае решающим фактором является то, что латинские буквы в кодовой таблице символов идут по порядку. Т.е. 'A' имеет некоторый код n, 'B' имеет код n+1 и т.д. - весь алфавит идёт последовательно, без разрывов. Убедиться в этом можно с помощью программы "Таблица символов", которая есть в Windows.

Вернёмся к нашей задаче. Мы должны выбрать случайную из букв 'A'..'Z'. Так как коды этих символов последовательны, то мы должны выбрать произвольное число от код_символа_A до код_символа_Z. Напомню, что для выбора случайного числа используется функция Random(n), возвращающая случайное число от 0 до n-1. Недостаток функции в том, что она берёт числа всё время от нуля, а код символа 'A' уж явно не 0. Но и здесь ничего сложного нет: сначала узнаём "ширину" диапазона кодов - из кода символа 'Z' вычитаем код символа 'A'. Не забываем прибавить 1, иначе буква 'Z' никогда не попадёт в строку, т.к. число берётся от 0 до n-1. Ну и дальше мы делаем сдвиг числа на код символа 'A'.
На буквах: от 'A' до 'Z' p позиций. Сама 'A' стоит в позиции n. Очевидно, 'Z' стоит в позиции p+n. Берём случайное число от 0 до p, а прибавив n получаем число из интервала от n до n+p. Простая арифметика, которая не для всех кажется простой.
Итак, код символа мы получили - осталось только добавить соответствующий символ в нашу строку. Функция Chr() возвращает символ с указанным кодом.

Для справки: очень часто, глядя на такой код, говорят, что он неоптимален - мол, коды символов будут постоянно рассчитываться (речь о функции Ord). Однако знающие люди никогда этого не скажут, ведь в Delphi есть маленькая хитрость: компилятор вычислит эти значения ещё на этапе компиляции и в программе они будут просто константами. Т.е. Ord('Z') и Ord('A') в программе не будут считаться никогда - там будут стоять вполне реальные числа, а значит никакого избытка вычислений идти не будет. Более того, даже вычитание будет произведено на этапе компиляции, ведь оба слагаемых являются константами. Мы пишем Ord('A') и Ord('Z') только из-за того, чтобы не лезть в кодовую таблицу, и не смотреть вручную коды этих символов. Кроме того, если вместо этого записать реальные коды, другой человек может испытать затрудение при чтении кода - он ведь не знает, откуда вы взяли эти числа и не помнит всю кодовую таблицу, чтобы определить, каким символам эти числа соответствуют.

Далее полученная строка s добавляется в Memo1 уже известным способом. А вот последняя строка в теле цикла - это маленькая хитрость. В одном из уроков об этой команде уже упоминалось. Дело в том, что при отсутствии этой команды программа просто зависнет с точки зрения пользовательского интерфейса - никаких изменений в Memo видно не будет, да и само окно перестанет реагировать на щелчки. На самом деле, конечно, программа будет работать, в памяти генерация строк будет идти полным ходом. Команда Application.ProcessMessages заставляет приложение обработать всю очередь задач, в том числе по отрисовке окна программы и элементов формы. Если при генерации каждой строки это будет происходить, программа будет выглядеть вполне живой - можно будет легко переместить окно по экрану и, что самое главное, нажать на заветную кнопку "Стоп". Ради эксперимента попробуйте убрать эту строку, и посмотреть, что получится.

Как было сказано ранее, такой способ является не совсем верным. В серьёзных программах программировать процессы таким образом не допускается. Для параллельного выполнения операций, которые не должны мешать друг другу, существуют потоки, т.е. когда процессы работают одновременно, а сама программа при этом ими управляет. У потоков очень много преимуществ - поток можно легко остановить, можно задать его приоритет и др. Работа с потоками достаточно сложна для начинающих программистов, поэтому мы пока ограничимся тем примером, что был приведён выше. В конце концов, наш урок посвящён циклам.

Работа сайта временно приостановлена

Хостинг сайта временно приостановлен

Если вы владелец данного ресурса, то для возобновления работы сайта вам необходимо продлить действие услуги хостинга.

В случае, если приостановка работы сайта вызвана нарушением условий Договора на абонентское обслуживание, то для возобновления работы вам необходимо обратиться в Службу поддержки . Мы будем рады вам помочь!

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

Цикл REPEAT - цикл с постусловием

Завершает тройку циклов цикл с постусловием - REPEAT (англ. "повтор"). Примечательно, что этого цикла во многих языках программирования нет - есть только FOR и WHILE. Между тем, цикл с постусловием очень удобен.

Работает цикл точно так же, как и WHILE, но с одним лишь отличием, следующим из его названия - условие цикла располагается после тела цикла, а не до него.

Есть несколько моментов, на которые стоит обратить внимание. Во-первых, в качестве условия задаётся уже условие выхода из цикла, в то время как в цикле WHILE задаётся условие продолжения цикла. Во-вторых, при наличии нескольких команд, которые помещаются в тело цикла, заключать их в блок BEGIN .. END не нужно - зарезервированные слова REPEAT .. UNTIL сами составляют аналогичный блок.

Цикл с постусловием, в отличие от цикла с предусловием, всегда выполняется хотя бы один раз! Но, как и цикл WHILE, при неверно написанном условии цикл станет "вечным".

Решение задачи с помощью цикла REPEAT

Решение нашей задачи практически не изменится - всё останется, только условие будет стоять в конце, а само условие изменится на противоположное:

Общий вид цикла repeat Delphi:

Общий вид инструкции repeat Delphi представлен ниже:

откуда условие есть выражение типа Boolean, которое определяет условия завершения цикла.

Пример программы с циклом repeat Delphi:

Создадим программу, использующую инструкцию repeat, которая бы проводила проверку числа (введенного пользователем с клавиатуры), является ли данное число простым. Из математики известно, что число именуется простым в случае, когда оно делится только на само себя и на единицу, например, число 42 является обычным, поскольку делится на 42, на 1, на 2, на 3, на 6, на 7, на 21, а число 11 как раз и является простым (делится только на 13 и на 1.

В программе, чтобы проверить число n, является ли оно простым, можно при помощи деления числа n на 2, на 3 и т.д. до n и последующей проверкой остатка, появляющегося после каждого деления. Когда очередное деление завершилось появлением нулевого остатка, то это значит, что определено число, на которое число n делится нацело без остатка.

Читайте также: