Использование циклов - известный прием, позволяющий программисту выполнить миллиарды процессорных инструкций буквально в несколько строчек кода. Вместе с кажущейся простотой, циклы часто становятся камнями преткновения и взаимонедопонимания между компилятором и программистом.
И даже хрен с ними, с синтаксическими ошибками, это не страшно (компилятор носом тыкнет в них), самое страшное ошибки логические. Ведь скомпилив программу, затестив ее на скорую руку, программист объявляет цикл рабочим, и идет строчить программу дальше. Возможно, что в большинстве случаев, цикл сработает как надо, без вопросов. Но остается вероятность того, что условие (или условия) необходимые для прекращения цикла никогда не произойдет. Что будет в этом случае?
В этом случае будет беда... Программа впадет в бесконечный цикл. И это не так уж и страшно. В самом деле - бесконечный цикл очень легко обнаружить (программа подвисает, время отклика возрастает и т.д.). Хуже если в программе что-то "перемкнуло", и выполнение цикла пошло в совершенно другую степь. При этом программа вполне нормально (с виду) работает, выполняет операции, и неизвестно, когда и в каком месте всплывет ошибка программиста, и когда ее обнаружит пользователь программного продукта.
Это все было сказанно к тому, что следует очень внимательно относится к более-менее сложным циклам, и тщательно, очень тшательно тестировать каждый из них!
Виды циклов
В основном циклы классифицируются по типу условия Способы разнообразить интимную жизнь как сделать свою интимную жизнь. . Циклы бывают с предусловием и постусловием. Также весьма часто встречается цикл с параметром, в котором переменная целочисленного типа используется вместо счетчика. Рассмотрим подробнее.
Цикл с постусловием:
Пост - значит прошедшее время. То есть цикл сначала выполняется, а потом сверяется с условием выхода из него - продолжать цикл, или уже можно выходить. Структура цикла такова:
repeat
...
...
// код \\
...
until (условие);
В цикле repeat until код идущий после слова repeat будет выполняется до тех пор, пока условие не станет истинным значением. Пример - составить цикл, который будет увеличивать значение целочисленной переменной до тех пор, пока она не достигнет определенного значения. Код:
procedure RepeatUntilP;
var x:integer;
begin
x:=0; //Обнуляем переменную
//Пошел цикл
repeat
inc(x);
until x=50;
end;
Этот цикл завершится ровно тогда, когда в переменной x окажется число 50. inc (increment) увеличивает значение на одну еденицу. Пример бесконечного цикла:
procedure RepeatUntilP;
var x:integer;
begin
x:=0; //Обнуляем переменную
//Пошел цикл
repeat
inc(x);
until x=-50;
end;
Конечно, мы ведь увеличиваем значение переменной, а не уменьшаем! Она никогда не примет значение -50, а стало быть условие для выхода из цикла никогда не произойдет. Еще один пример:
procedure RepeatUntilP;
var x:integer;
begin
randomize;
x:=0; //Обнуляем переменную
//Пошел цикл
repeat
x:=random(50);
until x=30;
end;
Пока сгенерированное псевдослучайное число не примет значение 50, цикл не завершится. Условием может быть любой набор операторов, который позволяет проверить истинность ложность значения. Например перед нами стоит задача сгенерировать строку состоящую из цифр определенной длинны. Для этих целей вполне подойдет цикл такого вида:
procedure RepeatUntilP;
var x:string;
begin
randomize;
x:=''; //Обнуляем переменную
//Пошел цикл
repeat
x:=x+random(IntToStr(random(999)));
until Length(x)=100;
end;
Этот цикл будет выполнятся до тех пор, пока длинна строки не составит 100 символов.
Цикл с параметром
Последняя задача на генерацию строки определенной длинны нелохо выполнилась циклом с постусловием, это точно, но все таки в данном случае (когда заранее известно сколько раз нужно выполнить операцию), нам больше подойдет цикл с параметром. Он имеет такой вид:
For i:=0 to X do
.. действие
Первый параметр указывает - какое значение задать переменной в начале цикла. При каждом выполнении цикла, значение переменной - счетчика увеличивается. Второй параметр как указывает на то, когда следует завершить выполнение цикла. Например для решения предыдущей задачи вполне подойдет такой цикл:
procedure RepeatUntilP;
var i:integer;
x:string;
begin
randomize;
For i:=0 to 100 do
x:=x+random(50);
end;
Коротко и изящно. Следует отметить, что если вторым параметром идет отрицательное число, вместо оператора to следует указывать downto. Если в цикле идет несколько строчек кода, то просто необходимо взять их в операторные скобки begin... end. Так:
for i:=0 to 5 do
begin
...
несколько операций
...
end;
Цикл с предусловием.
От первого цикла он отличается лишь тем, что проверка условия происходит непосредственно перед выполнением цикла. Имеет такой вид:
while |условие| do
операция
или
while |условие| do
begin
...
несколько операций
...
end;
Следует учесть: в данном цикле условие служит не для выхода из цикла, а для его продолжения.
Циклы можно (и нужно) комбинировать и осуществлять вхождение одного цикла в другой. Они все вместе весьма хорошо уживаются, если все грамотно сделать. Например у нас есть такая задача:
Представим, что нам нужно срочно составить лист паролей, а под рукой нет необходимых инструментов. Это не беда - ведь мы владеем навыком программирования. Вот код, составляющий лист паролей дней рождения:
procedure TForm1.Button1Click(Sender: TObject);
var i,j,year:integer;
begin
year:=1930;
While year<2010 do
begin
inc(year);
For i:=1 to 12 do
For j:=1 to 31 do
memo1.lines.add(IntToStr(year)+IntToStr(i)+IntToStr(j));
end;
end;
Как мы видим - цикл выполняется довольно долго. Из-за чего? Из-за вывода на экран! Если бы мы запоминали значение в какой-нибудь невизуальный TstringList тогда бы на все про все ушло несколько секунд.
На последок хочу предостеречь начинающих программистов от использования слишком сложных циклов, особенно, если там присутсвуют ветвления
if ... then
или
case x of
y:..
y:..
end;
потому как с точки зрения оптимизации и скорости выполнения программы все проверки лучше по возможности вынести за цикл. Ведь в цикле выполняются миллиарды инструкций, не хорошо, если проверка будет осуществлятся в каждом шаге цикла. Но в сущности - это мелочи...