Общие пояснения
Требования к программе.
- Программа должна обрабатывать данные указанного типа в количестве до 100 чисел, если в программе не указано иное ограничение. Конкретное количество чисел вводить в программу с клавиатуры. Массивы не использовать.
- Все значения, на которые по смыслу накладываются ограничения, должны при вводе проверяться.
- Если в результате обработки данных результат не получен, при выводе программа должна сообщать об этом в понятной форме.
- При выводе на экран использовать длину выводимой строки не более 76 символов.
- Остальные требования – как и в предыдущих лабораторных работах.
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;
Разбор контрольного варианта
Задание
Таблица 12. Данные к заданию 31 варианта
№ вар. | Задание | Остановить обработку при… | Тип обрабат. данных |
Нахождение номера последнего числа, превышающего значение 10.5 в последовательности вводимых произвольных чисел. | …вводе заказанного количества чисел | Вещественые |
Решение задачи следует начинать с разбора задания и выделения объектов, упоминающихся или подразумевающихся в задании. Для каждого найденного объекта определяется его тип и придумывается имя (идентификатор) для последующего программирования. Имена, типы и назначения сводятся в таблицу идентификаторов.
Для данной задачи можно выделить: номер последнего числа, превышающего значение 10.5; количество чисел (N); вводимое число. Для запоминания искомого номера нужно знать порядковый номер вводимого числа. В задании оговорено, что вводимые числа – произвольные, т.е. могут быть как целыми, так и дробными, для их хранения в ЭВМ нужно иметь переменную (ячейку) вещественного типа. Текущий номер и искомый номер – величины целые и, вообще говоря, положительные. Для них можно завести или целые или беззнаковые переменные. Общее количество чисел также должно быть целым и больше нуля, иначе задача не имеет смысла. Таким образом, имеем таблицу:
Таблица 13. Идентификаторы программы 31-го варианта
Имя | Тип | Размер, байт | Назначение | |||
N | Целый | Количество чисел | ||||
I | Целый | Текущий номер | ||||
Num | Целый | Номер последнего числа, которое > 10.5 | ||||
A | Вещественый | Текущее число | ||||
Исходными данными в задаче являются, во-первых, количество чисел, а во-вторых, сами числа, последовательно вводимые в переменную A. Результатом будет порядковый номер последнего из чисел, которое превышает 10.5. Возможно, что среди вводимых чисел не найдется ни одного такого числа. В этом случае в конце необходимо выдать об этом сообщение, а не номер числа.
Контроль допустимости вводимых данных необходим только для количества чисел: оно должно быть не меньше единицы.
Алгоритм задачи состоит из трех последовательных обобщенных шагов: ввода данных, определения искомого номера и вывода результата.
В части ввода данных программа должна получить от пользователя значение количества чисел (N). Так как ввод данных выполняет человек с помощью клавиатуры, программа должна сообщить, что от него требуется.