Персональная страничка
Диканева Тараса
Викторовича

Главная \ Преподавательское \ Программирование для начинающих

5. Вложенные циклы

Предыдущий раздел:

Следующий раздел:

5.1. Вложенные циклы: теория

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

Пример 1. Напечатать числа в виде следующей таблицы

    3 3 3 3 3
    3 3 3 3 3
    3 3 3 3 3
    3 3 3 3 3

Данная таблица состоит из четырех строчек, в каждой из которых число 3 напечатано 5 раз. Строчку из пяти чисел можно напечатать с помощью одного цикла for:

  for i:=1 to 5 do
    write(3, '   ');

Чтобы повторить вывод строчки 4 раза, вставляем этот цикл внутрь другого:

  for k:=1 to 4 do
  {4 раза делаем то, что написано между begin’ом и end’ом}
  begin
    for i:=1 to 5 do
      write(3, '   ');	{Выводим одну строку}
    writeln;	{Переводим курсор на следующую строку}
  end;

Типичная ошибка, когда в качестве счетчиков вложенных циклов (i и k в приведенном примере) используется одна и та же переменная. То есть нельзя в каждом из циклов использовать одну переменную i. Помнить об этом особенно важно, поскольку данная ошибка не обнаруживается на этапе компиляции. Ваша программа запустится, но делать будет вовсе не то, что вы от нее ждете. В приведенном примере (если допустить ошибку, заменив переменную k на i) внешний цикл выполнится всего 1 раз вместо 4-х. Возможна также ситуация, когда такая ошибка приведет к зацикливанию: внешний цикл будет выполняться бесконечно долго – программа зависнет.

Рассмотрим еще один пример.

Пример 2. Напечатайте числа в виде следующей таблицы:

    1  2  3  4
    5  6  7  8
    9  10 11 12
    13 14 15 16

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

  n:=1;
  for i:=1 to 4 do
  begin
    for k:=1 to 4 do
    begin
      write(n, '   ');
      n:=n+1;
    end;
    writeln;
  end;

Дополнительная переменная-счетчик (n) здесь введена для большей прозрачности алгоритма. Заметив, что всегда выполняется n = (i-1)*4+k, можно обойтись без нее.

Разумеется, ту же задачу можно решить без вложенных циклов (вообще говоря, обойтись без них можно всегда). Например, заметив, что числа, стоящие в конце каждой строки делятся на 4, делаем так:

  for n:=1 to 16 do
  begin
    write(n, '   ');
    if n mod 4 = 0 then
      writeln;
  end;

Однако решения, основанные на вложенных циклах, как правило, интуитивно понятнее, их проще придумывать. Это связано с такой фундаментальной идеей программирования как разделение задачи на подзадачи. Выделяется отдельная часть решения задачи (вывод одной строки в приведенных примерах), затем с помощью внешнего цикла она выполняется много раз.

Типичные ошибки при написании вложенных циклов:

1. Наиболее частая ошибка – использование одной и той же переменной-счетчика для внешнего и внутреннего циклов. Выше она уже упоминалась.

2. При решении некоторых задач необходимо, чтобы одна переменная-счетчик на каждом шаге увеличивалась, а другая при этом уменьшалась. Следуя непостижимыми (для человека наделенного формально-логическим складом ума) путями интуитивного мышления многие студенты для решения этой задачи приходят к конструкции вида:

  for i:=1 to n do
    for k:=n downto 1 do …

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

Напомним, что в качестве пределов изменения переменной-счетчика цикла можно использовать произвольное выражение, дающее результат целого типа:

  for i:=<произвольное выражение> to <произвольное выражение> do …

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

Пример 3: Напечатайте числа в виде следующей таблицы:

    1 2 3 4  5
    3 4 5 6  7
    5 6 7 8  9
    7 8 9 10 11

Решение:

  for i:=1 to 4 do
  begin
    for k:=2*i-1 to (2*i-1)+4 do
      write(k, '   ');
    writeln;
  end;

Поскольку внутри цикла может находиться все, что угодно, то ничто не мешает разместить там два цикла. Например, так:

  for i:=1 to 10 do
  begin
    …
    for k:=1 to 10 do
    begin
      ...
    end;
    for n:=1 to 10 do
    begin
      ...
    end;
    …
  end;

Или так:

  for i:=1 to 10 do
    for k:=1 to 10 do
      for n:=1 to 10 do …

В заключение небольшое замечание, касающееся правильного стиля написания программы, содержащей множество циклов (в частности вложенных). Следует избегать одновременного использования в качестве счетчиков пар переменных с именами i и j, а также p и q. На вид они очень похожи, что часто приводит к трудно обнаруживаемым ошибкам.

Следующий раздел:

Предыдущий раздел:

Добавить комментарий