C++ Программирование в среде С++ Builder 5

Циклы


В языке С структуры многократного повторения реализуются тремя разновидностями операторов цикла. Это циклы while, do... while и for.

Цикл while

Синтаксис оператора while выглядит так:

while (условие продолжения) оператор

Сначала оценивается условие_продолжения. Если оно истинно, выполняется оператор, после чего управление возвращается заголовку цикла, и все повторяется снова. Когда условие оказывается ложным, управление передается следующему после цикла оператору.

Как обычно, одиночный оператор тела цикла можно заменить блоком, заключенным в фигурные скобки:

whi1е (условие_продолжения)

{

операторы_тела цикла

}

Используя этот оператор, можно было бы переписать предыдущий пример (со структурой switch) следующим образом:



int main(int argc, char* argv[ ])

{

int key, done = 0;

while (!done) {

printf("\nEnter command (F, M or Q): ");

key = getche(); // Прочитать клавишу.

switch (key) ( // Определение команды... case 'f':

case 'F':

printf("\n\"File\" command selected.\n");

break;

case 'm':

case 'M':

printf("\n\"Message\" command selected.\n");

break;

case 'q':

case 'Q':

printf("\n\"Quit\" command selected.\n");

done = 1; // Завершить цикл.

break; default:

printf("\nlnvalid command!\n") ;

}

} printf("\nPress a key to Exit...");

getch() ;

return 0; // Возврат в Windows.

}

Это более “грамотная” версия цикла обработки команд. Пока done равняется нулю, цикл продолжает выполняться. Когда нажимают клавишу 'q', done присваивается единица и при очередной оценке условия оно оказывается ложным; цикл завершается.

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

Цикл do—while

Этот цикл имеет такой вид:

do оператор while (условие продолжения);

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


Отличие от предыдущей конструкции очевидно — тело цикла do... while исполняется хотя бы один раз вне зависимости от каких-либо условий, в то время как в цикле while при ложном условии тело не исполняется вообще. Хотя конкретную программную задачу можно решить, применив любую из этих конструкций, чаще всего одно из двух решений оказывается более экономным.



Цикл for



Цикл for, наиболее универсальный из всех циклов языка С, выглядит так:

for ([инициализация]; [условие]; [модификация]) оператор

Прежде всего выполняется инициализация цикла; секция инициализации может содержать любое выражение. Инициализация производится только один раз перед началом работы цикла.

Оценивается выражение условия. Если оно истинно, выполняется оператор тела цикла; если условие ложно, происходит выход из цикла и управление передается следующему оператору.

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

Как видно из синтаксического описания, любую секцию заголовка цикла for можно опустить, но разделители — точки с запятой — все равно должны присутствовать. Если опущено условие, цикл будет выполняться бесконечно.

Простейшей и самой популярной конструкцией на основе цикла for является цикл с управляющей переменнои-счетчиком:

int i;

for (i =0; i < REPEAT; i++)

DoSomething (i);

Счетчик инициализируется значением 0. В начале каждого прохода цикла проверяется, не достиг ли он значения REPEAT. Как только i станет равным REPEAT, тело цикла пропускается и управление передается следующему оператору. В конце каждого прохода i увеличивается на единицу. Как нетрудно подсчитать, тело цикла выполняется для значений i от О до REPEAT-1, т. е. REPEAT раз.



Любую конкретную структуру повторения, требуемую для решения некоторой задачи, можно реализовать на основе любого из циклов С, однако всегда какой-то из них подходит к данному случаю наилучшим образом, позволяя написать более ясный и компактный код. Так, если необходимое число итераций цикла известно заранее (как при обработке массива), проще всего применить цикл for. Если же число итераций заранее определить нельзя, как в нашем примере обработки команд (момент завершения цикла определяется пользователем) или при операциях поиска в списке, применяют цикл while или do. . .while.



У структур повторения в ряде ситуаций есть альтернатива. Это рекурсия, заключающаяся в том, что функция вызывает саму себя. Естественно, такой вызов должен быть условным, т. е. обязательно должен наступить такой момент, когда на очередном шаге рекурсивного вызова не происходит. Есть классический пример рекурсии — вычисление факториала:

unsigned Fac(unsigned n)

{

if (n)

return n * Fac(n - 1);

else

return 1;

}

Когда аргумент в очередном вызове оказывается равен 0, рекурсия завершается — функция возвращает 1. До этого момента не происходило, по существу, реальных вычислений (умножений). На стеке накапливались вызовы Fac () с последовательно уменьшающимися аргументами. Теперь стек начинает “разматываться”, и возвращаемые на каждом шаге значения умножаются на последовательно увеличивающиеся n. Глубина рекурсии ограничивается только размером стека программы.

Факториал, конечно, вообще никто никогда не вычисляет, во всяком случае, подобным образом. Однако существуют задачи, для которых метод рекурсии оказывается естественным решением и реализуется намного проще, чем это можно

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

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


Содержание раздела