Общие пояснения
1. Программы циклической структуры используются, когда необходимо несколько раз выполнить однотипные действия с различными данными. Если количество повторений тела цикла известно перед началом цикла, он называется арифметическим, если нет – итеративным. Для организации арифметического цикла в блок-схеме алгоритма используется блок "модификатор", а в программе – соответствующий ему оператор "for...".
Итеративный цикл строится с использованием блока "решение", в котором один из альтернативных путей представляет выход из тела цикла. В программе такой цикл может выполняться с помощью специальных операторов итеративных циклов или оператора условного перехода. В данной работе будет использоваться только "if..." оператор.
Рассмотрим сначала арифметический цикл. Оператор состоит из заголовка и тела цикла. Заголовок имеет вид:
for <имя параметра цикла> := <начальное значение> to <конечное значение> do
Далее идет тело цикла: простой или составной оператор (до символа ";"). Если оператор составной, он заключается в операторные скобки begin ... end;
В качестве параметра цикла можно использовать любую целочисленную переменную, в которой в это время не хранится нужное в дальнейшем значение. Эта переменная изменяется в цикле автоматически. Параметр цикла – это переменная, обычно играющая роль не только счетчика количества выполненных повторений цикла, но одновременно служащая порядковым номером обрабатываемого числа или элемента массива.
Начальное и конечное значения параметра цикла могут быть выражениями, но они вычисляются только один раз – при первом входе в цикл. В теле цикла они не должны меняться. При каждом возврате к заголовку в цикле, счетчик автоматически увеличивается на единицу.
Тело цикла выполняется, пока счетчик не станет больше конечного значения (если счетчик равен конечному значению – цикл выполняется). Если требуется организовать цикл, в котором параметр уменьшается на единицу с каждым возвратом, то используют ключевое слово "downto", вместо "to".
Примеры написания оператора:
for i:=1 to 25 do write('*'); {вывод строки из 25 *}
for k:=L+1 to N-1 do { значения L и N должны }
begin { быть определены до цикла }
. . .
end;
for i:=N downto 2 do S:=S+i; {Сумма целых чисел 2..N}
Если нужно менять счетчик с другим шагом (не один), используют второй счетчик, изменяющийся в теле цикла по рекуррентной формуле, например j:=j+3; или вычисляемый через первый счетчик, например: j:= 2+(i-1)*3;
Итеративные циклы для завершения требуют проверки такого условия, результат которого может измениться в процессе выполнения тела цикла. По выполнении этого условия осуществляется переход на оператор, следующий за телом цикла. Возврат на начало тела цикла в этом случае выполняется оператором безусловного перехода. В программе при такой организации цикла требуется иметь две метки:
Start:
. . .
if A=Priznak then goto Finish;
. . .
goto Start;
Finish: . . .
Часто проверяют условие продолжения цикла, и по его выполнению возвращаются на начало тела цикла, иначе цикл заканчивается. В этом случае достаточно обычно одной метки:
Start:
. . .
if A<>Priznak then goto Start;
. . .
Тело итеративного цикла при таких способах построения в скобки begin ... end заключать не обязательно.
2. Циклические процессы почти всегда требуют некоторых подготовительных действий, выполняемых до начала цикла. Это связано с использованием в теле цикла так называемых "рекуррентных соотношений", в которых некоторая переменная вычисляется с использованием своего старого значения, например:
N:=N-1; P:=-2*P/i; S:=S+A и т.д.
Все такие переменные перед циклом должны получить определенные значения, чтобы правильно вычисляться внутри цикла. Например, при вычислении суммы последовательно вводимых слагаемых, ячейка (переменная) для суммы должна обнуляться; переменная для накопления произведения делается равной единице (или первому сомножителю).
Поиск максимумов (минимумов) или их порядковых номеров в рядах значений также выполняется по рекуррентным зависимостям (если новая величина больше максимума, сделаем максимум равным...) – сперва используется старое значение максимума, чтобы создать новое значение.
При поисках максимума можно использовать два варианта начального задания: или в качестве максимума берется первое рассматриваемое значение (и цикл начинает выполняться начиная со второго числа), или в качестве начального задается фиктивное значение – гарантированно меньшее, чем любое число сравниваемого ряда (т.е. теоретически минимальное возможное число). При этом циклическая обработка одинаково выполняется для всех чисел, начиная с первого.
3. Если в программе требуется обрабатывать нечисловые данные, для них можно заводить переменные нечисловых типов, которые также необходимо включить в блок описаний. Для символьных переменных используется описатель char, а для логических – описатель boolean. Например:
VAR
i,j :integer;
A,S :real;
C,Sim :char;
Q,Priz:boolean;
. . .
Символьные переменные можно сравнивать с символьными константами и между собой с помощью всех операций отношений (=,<,>, и т.д.), например:
if Sim > 'A' then ... или
if C = Sim then ...
Логические переменные можно использовать в условных операторах, причем не нужно записывать if Q=TRUE then..., а просто if Q then... , так как само значение Qможет быть TRUE или FALSE.
Наконец несколько замечаний по контролю за вводимыми величинами. Поскольку в программе предполагается ввод исходных данных пользователем программы путем набора значений на клавиатуре, в программе должны быть предусмотрены выводы на экран запросов на ввод того или иного параметра, нужного программе. Эти запросы представляют собой операторы вывода некоторого текста, например:
Writeln(' Сколько чисел будет обрабатываться?'); или
Writeln(' Вводи очередной сомножитель');
Такие запросы должны быть перед каждым оператором ввода данных с клавиатуры. Другой момент, который следует отметить, это необходимость контроля за вводимыми величинами. Недопустимое значение может не только привести к неправильному ответу, но и просто "подвесить" программу или привести к ее аварийному снятию операционной системой. Поэтому все данные, на которые по их смыслу (или по возможностям реализованного метода решения) накладываются ограничения, должны проверяться после их ввода на попадание в допустимый диапазон.
Обычно считается, что можно найти сумму нуля и большего количества слагаемых, произведение одного или более сомножителей, выбрать наибольшее или найти среднее значение из одного или нескольких чисел, вычислить факториал нуля или большего целого числа и т.д. Иногда ограничения накладываются не только снизу, но и сверху.
Если, например, допустимый диапазон для значений переменной A ограничен числами –0.5 и 11.0, то проверку на ошибочное значение можно осуществить оператором:
if (A > 11.0) or (A < -0.5) then ...
Если такая проверка даст значение TRUE (т.е. A имеет недопустимое значение), тогда нужно выдать сообщение об этом и либо закончить выполнение программы, либо (что более разумно) вернуться к оператору запроса ввода этой величины еще раз. Так как оба эти действия следует выполнять по срабатыванию одного и того же условия, операторы, задающие эти действия следует поместить в скобки begin ... end, например:
if (A > 11.0) or (A < -0.5) then
begin
Writeln(' Вы задали недопустимое значение');
goto Vvod_A;
end; { здесь Vvod_A – метка перед оператором запроса на ввод параметра, соответствующего переменной A }
Наконец, следует помнить, что не при всяких наборах исходных данных задача может иметь решение. Если по каким-либо причинам ответ выдать невозможно, следует об этом сообщить в понятной форме, а не выводить неправильное или невозможное для ответа значение. Например, если в задаче требуется делить что-то на сумму нескольких чисел с разными знаками, то сумма может случайно оказаться равной нулю, после чего деление невозможно и решения у задачи не окажется.
Тогда выдача результата может выглядеть так:
. . .
if Sum = 0 then
Writeln(' Нет решения, так как сумма равна 0')
else
begin
R:=.../Sum;
Writeln(' Отношение =', R:...);
end;
Разбор контрольного варианта