Лічильник
Сьогодні Разом
Відвідувань 13 5257411
Авторізацій 1 420118
Користувачів 1 2680
Статья

17. Оператор цикла while


Для многократного повторения одного и того же фрагмента алгоритма (тела цикла) используются циклы (повторения).

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

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

В зависимости от задачи программист решает, какой тип цикла следует использовать для построения эффективного алгоритма.

В данном разделе остановимся на цикле с предусловием - цикл while.

В Pascal синтаксис цикла while:
while <условие> do
  <тело цикла>;
Цикл будет выполнятся до тех пора, пока условие выполняется (результат логического выражения равен true). Поэтому условие в цикле while иногда называют условием входа.

Например, требуется вывести все натуральные числа, пока их значение не превысит 100:
i := 1;
while (i <= 100) do begin
  writeln(i);
  i := i + 1;
end;
У нас появилась необходимость использовать операторные скобки begin end, так как тело цикла состоит из более, чем одного действия (оператора). Напомним, что группа операторов, объединенных операторными скобками называется составной оператор и рассматривается компилятором, как один оператор.

18. Чтение последовательности до нуля


Например, дана числовая последовательность которая заканчивается нулем (ноль является признаком завершения последовательности и не является ее элементом). Определить количество элементов в последовательности.

Пример входных данных: 4 6 23 564 1 23 0

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

Решим эту задачу с использованием цикла с предусловием.
var a: longint; // Значение текущего элемента
    n: longint; // Количество элементов

begin
 // Читаем первое значение из входного потока
 read(a);
 // Обнуляем счетчик элементов
 n := 0;
 // Пока мы не прочтем нулевое значение, повторяем
 while a <> 0 do
  begin
   n := n + 1; // Увеличить счетчик на единицу
   read(a);    // Читаем следующее значение
  end;
 // Выводим результат
 writeln(n)
end.

19. Индекс первого положительного элемента


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

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

Фрагмент программы, в котором осуществляется поиск индекса первого положительного элемента:
 i := 1;
 while a[i] <= 0 do
  i := i + 1;
Мы начинаем с первого элемента, проверяем его знак, и если это не положительный - переходим к следующему элементу.

Не трудно изменить выше описанный фрагмент программы для нахождения индекса последнего положительного элемента.

20. Индекс первого положительного элемента, но его может и не быть


Усложним задачу, убрав в условии гарантию того, что такой элемент обязательно существует. В этом случае, кроме проверки знака элемента, следует проверить и значение индекса элемента массива, сравнивая его с количеством всех элементов массива.

В этом случае поиск индекса первого положительного элемента может выглядеть так:
i := 1;
while (i <= n) and (a[i] <= 0) do
  i := i + 1;
Возникает вопрос: а имеет ли значение в каком порядке записывать простые условия, формируя составное? Что будет, если написать такой вариант решения задачи?
i := 1;                            // Внимание!
while (a[i] <= 0) and (i <= n) do  // Это плохой алгоритм,
  i := i + 1;                      // может привести к фатальной ошибке
Предположим, что положительного элемента в массиве не существует. В этом случае, наступит момент, когда значение переменной i станет равным n + 1, и при этом значении i будет попытка вычислить значение логического выражения оператором while: (a[i] <= 0) and (i <= n), что приведет к ошибке, так как i + 1 элемента массива не существует. Поэтому, правильно будет проверить первым условие (i <= n) на наличие самого элемента, и только в случае положительного результата такой проверки, проверить знак этого элемента.

Будем называть условие (i <= n) более сильным и поэтому ставим его на первое место. Это условие проверяет сам факт существования элемента. А проверка условия (a[i] <= 0) может быть сделана, только после того, как мы установили, что элемент существует.