Операторы повторения (циклы) предусматривают выполнение некоторых операторов несколько раз. В языке Паскаль имеются три различных оператора, с помощью которых можно запрограммировать повторяющиеся фрагменты программ:
· while (цикл с предусловием)
· repeat (цикл с постусловием)
· for (цикл со счетчиком)
Если число повторений оператора (составного оператора) заранее неизвестно, а задано лишь условие его повторения (или окончания), используются операторы while, repeat. Оператор for используется, если число повторений заранее известно.
Следует знать:
- самым универсальным из всех операторов цикла считается while, поэтому в случае затруднений с выбором можно отдать предпочтение ему;
- цикл repeat имеет очень простой и понятный синтаксис, поэтому с него удобно начинать изучение циклов;
- цикл for обеспечивает удобную запись циклов с заранее известным числом повторений;
- при неумелом использовании циклов любого типа возможна ситуация, когда компьютер не сможет нормально закончить цикл (в таком случае говорят, что программа "зациклилась"). Для выхода из подобной ситуации используется комбинация клавиш Ctrl+Break. Если это не помогает, есть и крайнее средство Ctrl+Alt+Delete.
Оператор repeat
Оператор repeat называют оператором цикла с постусловием за то, что условие проверяется после выполнения тела цикла.
Формат:
repeat < тело цикла >until < условие окончания цикла >;
где repeat, until – зарезервированные слова (обозначают "повторяй", "пока" соответственно);
<условие> – булевское выражение: простое выражение отношения или сложное логическое выражение;
<тело цикла> – оператор или последовательность операторов.
Вначале выполняется тело цикла, затем проверяется условие завершения цикла. Именно поэтому цикл, организованный с помощью оператора repeat, в любом случае выполнится хотя бы один раз. Если результат булевского выражения равен false (ложь), то тело цикла выполняется еще раз, если же результат – true (истина), происходит выход из цикла. Операторы будут выполняться, пока условие будет оставаться ложным (false). На рисунке 3.2 приведена блок-схема оператора повтора repeat.
Рис. 3.2
Например, в приведенном ниже фрагменте программы наращивание переменной S произойдет один раз, так как условие имеет значение true:
S:=27;
repeat S:=S+1 until S>0;
Write(S);
Для успешного завершения цикла repeat в его теле обязательно должны присутствовать операторы, оказывающие влияние на условие выполнения операторов цикла. Пользователь сам должен позаботиться об изменении переменных, определяющих условие выхода, иначе цикл получится бесконечным. Например:
S:=2;
repeat k:=k+S;untilS>30;
Write(k);
В данном случае произойдет зацикливание, т.к. условие 2>30 всегда будет иметь значение false и выхода из цикла не произойдет.
Оператор repeat может использоваться для проверки правильности ввода исходных данных. Например, по условию задачи исходное данное должно быть двузначным числом. Программа будет повторять запрос на его ввод до тех пор, пока не получит то, что ей требуется. Рассмотрим соответствующий фрагмент программы:
Var x: integer;
begin
. . .
repeat Write('Введите двузначное число '); Readln(х);
until (x>9) and (x<100);
. . .
end.
Пример: Составить программу, которая определяет количество и сумму цифр для любого натурального числа, не превосходящего maxint (см. табл.4).
Program Maximum ;
Var k, s, x: integer;
n: longint;
begin
Write('Введите натуральное число <= ',maxint,' : ');
Readln(n);
s:=0; {сумма цифр}
k:=0; {количество цифр}
repeat {начало тела цикла}
x:= n mod 10;
s:=s+x;
k:=k+1;
n:=n div 10
until n=0; {условие окончания цикла}
Writeln('Число цифр: ',k,', сумма цифр: ', s);
end.
В начале выполнения программы обнуляются значения счетчика k для определения количества цифр введенного натурального числа n и суммы S. Затем зарезервированным словом repeat объявляется цикл, после чего следуют операторы тела цикла: переменной х присваивается значение последней цифры введенного числа, на это значение увеличивается значение суммы S, увеличивается на единицу значение счетчика цифр k и переменная n получает новое значение (последняя цифра введенного числа отбрасывается).
В конце цикла оператор until n=0 проверяет условие окончания цикла. Если условие - true (истина), то цикл завершится, а управление в программе будет передано на оператор, находящийся за словом until, т.е первый оператор за границей цикла repeat. Это вызов процедуры Write, которая напечатает значение переменной S и k.
Пример: Протабулировать функцию y=sin(x) на отрезке [-π; π] с шагом h= π/5. Результаты вычислений вывести на экран в виде таблицы. Найти максимальное и минимальное значения функции на этом отрезке.
Program TabZnach;
Var x, y, h, max, min: real;
begin
h:=Pi/5;
х:=-Pi; {начальное значение аргумента функции}
max:=sin(x); {предполагается максимум в первой точке}
min:=sin(x); {предполагается минимум в первой точке}
Writeln(' x у');
Repeat
x:=x+h;
y:=sin(x);
Writeln(x:7:2,y:7:2);
if y>max then max:=y; {определяется максимум функции}
if y<min then min:=y {определяется минимум функции}
until x> Pi; {проверяется условие выхода из цикла}
Writeln;
Write (‘max=‘, max:5:2, ‘min=‘, min:5:2);
end.
Перед началом цикла необходимо вычислить значение функции в первой точке (т.е. в точке х=-Pi) и принять его за максимальное и минимальное значения.
В теле цикла выполняются следующие действия: вычисляется значение функции в соответствующей точке, выводится в виде таблицы значение аргумента и функции при помощи процедуры Writeln, с помощью первого условного оператора определяется максимальное значение функции, а с помощью второго условного оператора - минимальное значение функции.
После завершения цикла на экране будут выведены максимальное и минимальное значения функции.
Рассмотрим пример, когда число повторений заранее неизвестно.
Пример: По заданному натуральному числу а вычислить минимальное такое n, при котором n!≥a. Число а задается вводом.
Эта задача была рассмотрена в Главе 1, приведем для нее программу.
Program Factorial;
Var F, n, a: integer;
begin
Write('Введите число ');
Readln(a);
F:=1;
n:=1;
repeat
F:=F*n;
n:=n+1
until F>=a;
Writeln(n-1);
end.
Оператор while
Оператор while часто называют оператором цикла с предусловием за то, что проверка условия выполнения тела цикла производится в самом начале оператора.
Формат:
while<условие выполнения цикла>do<оператор>;
где while, do – зарезервированные слова (обозначают "пока выполняется условие" и "делать" соответственно);
<условие> – выражение логического типа: простое или сложное выражение отношения, которое может принимать одно из двух значений: true или false;
<оператор> – тело цикла.
Если требуется выполнить после do несколько операторов, они обрамляются операторными скобками begin и end, образуя тем самым, составной оператор.
Перед каждым выполнением тела цикла вычисляется значение выражения условия. Если результат значения выражения равен true (истина), то тело цикла выполняется и снова вычисляется выражение условия. Так продолжается до тех пор, пока значение условия выполнения цикла не станет равно false (ложь). Если результат равен false, происходит выход из цикла и переход к первому оператору после while. На рисунке 3.3 приведена блок-схема оператора повтора while.
Рис. 3.3
Так как while — это цикл с предусловием, то операторы тела цикла вообще могут быть не выполнены ни разу, если проверяемое условие ложно с самого начала. Например:
S:=27;
while S<0 do S:=S+1;
Write(S);
В данном случае наращивание S не произойдет, так как условие с самого начала имеет значение false.
Для успешного завершения цикла while (также как и в repeat) в его теле обязательно должны присутствовать операторы, оказывающие влияние на условие выполнения операторов цикла.
Обратите внимание - в операторе цикла while точка с запятой никогда не ставится после зарезервированного слова do (наличие точки с запятой означает присутствие в теле цикла пустого оператора, т.е. в цикле никаких действий не выполнится).
Для управления циклами while и repeat удобно использовать функции succ или pred и процедуры inc или dec.
Например, рассмотрим следующую программу, которая выводит целые числа от 0 до 10 в прямой и обратной последовательности:
Program Primer;
Var i: integer;
begin
i:=0;
while i<10 do begin i:=succ(i); { или inc(i); или i:=i+1;}
Write (i,' '); end;
Writeln;
i:=10;
while i>0 do begin Write(i,' ');
i:=pred(i); {или dec(i); или i:=i-1;}
end;
end.
Результат выполнения программы:
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
Пример: Заданы 10 произвольных чисел. Вычислить сумму этих чисел.
Program Sum;
Var ch, b, S: integer;
begin
S:=0; {сумма чисел}
ch:=0; {счетчик чисел}
while ch<10 do {условие выполнения цикла}
begin
ch:=ch+1;
Write(‘Введите‘,ch,‘–е целое число‘);
Readln(b); {ввод с клавиатуры очередного числа}
S:=S+b;
end;
Write (‘ Сумма введенных чисел равна‘, S);
end.
В начале выполнения программы обнуляются значения счетчика введенных чисел ch и их суммы S. Оператор while проверяет условие ch<10. Если условие - верно, то выполняется составной оператор в теле цикла, в котором вводится значение очередного числа, и на это значение увеличивается значение суммы.
Как только значение переменной ch станет равно 10, и условие ch<10 будет false, выполнение цикла завершится, а управление в программе будет передано на оператор, находящийся за словом end, т.е. первый оператор за границей while. Это вызов процедуры Write, которая выведет сообщение «Сумма введенных чисел равна» и напечатает значение переменной S.
Пример: Табулирование функции. Составить таблицу значений аргумента х и функции y=Sin(x) на отрезке [0; 3,1] с шагом h=0,1. Вычислить сумму значений функции больших, чем 0,1 и меньших, чем 0,6.
Program Tab;
uses crt;
Var x,Y, S: real;
begin
ClrScr;
S:=0; {сумма значений функции}
х:=0; {начальное значение аргумента функции}
Writeln('x':5,' ':4,'у':4);
Writeln('_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _' ) ;
while x<=3.1 do
begin
Y:=sin(x);
Writeln(x:4:1,' ':4,y:4:1);
if (Y>0.1) and (Y<0.6) then S:=S+Y;
x:=x+0.1;
end;
Writeln;
Write (‘ Сумма значений функции равна‘, S:3:1);
end.
Оператор while проверяет условие х<=3,1 и пока это условие – true выводится таблица значений аргумента х и функции Y. В цикле для нахождения суммы значений функции на заданном интервале используется условный оператор if … then. После окончания цикла выводится значение переменной S.
Рассмотрим пример, когда число повторений заранее неизвестно.
Пример: Вычислить сумму элементов бесконечно убывающей знакопеременной последовательности, где , удовлетворяющих условию , n=1,2,… Вывести на экран результаты вычислений.
Program Sum;
uses crt;
const e=0.001;
Var Summa, x, a: real;
n, z: integer;
begin
ClrScr;
Write(‘Введите число х’);
Readln(x);
Summa:=0; {сумма элементов последовательности}
a:=1;
n:=1; {счетчик элементов последовательности}
z:=-1; {знак элемента последовательности}
while abs(a)>e do
begin
a:=a*(2*x)/n; {элемент последовательности}
Summa:=Summa+a*z;
n:=n+1;
z:=-z; {вычисляем (-1)n+1}
end;
Writeln;
Write (‘ Сумма =‘, Summa:3:1);
end.
Цикл while завершится, когда абсолютное значение элемента последовательности превысит заданное значение e.
Приведем сравнительную характеристику двух операторов повтора.
while
repeat
· Число повторений операторов цикла определяется в ходе работы программы и во многих случаях заранее неизвестно
· Переменная, которая участвует в условии выхода из цикла, обязательно должна изменяться в теле цикла
· Выйти из цикла можно, минуя вычисление выражения условия, с помощью оператора goto
· Оператор цикла может быть вложенным
· Операторы цикла while будут выполняться, пока условие будет оставаться истинным (true)
· Операторы цикла repeat будут выполняться, пока условие будет оставаться ложным (false)
· После слова while записывается условие продолжения цикла
· После слова until записывается условие завершения цикла
· Тело цикла может не выполнится ни разу
· Тело цикла выполнится хотя бы один раз
· Необходимо использовать операторные скобки, если тело цикла содержит более одного оператора
· Использование операторных скобок не требуется
Оператор For
Оператор повтора for часто называют оператором цикла с параметром, так как число повторений задается переменной, называемой параметром цикла, или управляющей переменной, которая на каждом шаге цикла автоматически изменяет свое значение ровно на единицу – поэтому ее и называют счетчиком.
Оператор повтора for применяется в случаях, когда число повторений заранее известно.
Оператор повтора for состоит из заголовка (строка, содержащая for…do ) и тела цикла. Существует два вида оператора.
Вариант 1 (с увеличением счетчика)
Формат:
for < параметр цикла >:=А to B do < оператор >;
где for, do – зарезервированные слова (обозначают "для", "выполняй" соответственно);
А и В – выражения, определяющие соответственно начальное и конечное значение параметров цикла;
< оператор > - тело цикла.
Если требуется выполнить после do несколько операторов, они обрамляются операторными скобками begin и end, образуя тем самым составной оператор.
Оператор со счетчиком работает следующим образом:
· при первом обращении к оператору for вначале вычисляются выражения А, В и осуществляется присваивание <параметр цикла>:= А;
· затем проверяется условие <параметр цикла> <= B;
· если условие выполнено, оператор for продолжает работу (выполняется оператор в теле цикла);
· если условие не выполнено, оператор for завершает работу и управление передается на оператор, следующий за циклом;
· значение управляющей переменной изменяется на +1.
Оператор повтора for обеспечивает выполнение тела цикла до тех пор, пока не будут перебраны все значения параметра цикла от начального до конечного. На рисунке 3.4 приведена блок-схема оператора повтора for.
Рис. 3.4
Операторы тела цикла выполняются столько раз, сколько определяет выражение (КонечноеЗначение — НачальноеЗначение) + 1. Это соответствует всем значениям счетчика от начального до конечного включительно.
Например,
for i:=10 to 14 do Write(i: 3);
выведет на экран последовательность цифр в виде:
10 11 12 13 14
Если начальное значение больше, чем конечное значение, то операторы тела цикла не выполняются ни разу.
Вариант 2 (с уменьшением счетчика)
Формат:
for < параметр цикла >:= Аdownto B do < оператор >;
Операторы тела цикла выполняются столько раз, сколько определяет выражение (НачальноеЗначение — КонечноеЗначение) + 1.
Например,
for i:=14 downto 10 do Write(i: 3);
выведет на экран последовательность цифр в виде:
14 13 12 11 10
Если начальное значение меньше, чем конечное значение, то операторы тела цикла не выполняются ни разу.
Если переменная - счетчик имеет символьный тип char, то оператор:
for ch:= 'a' to 'e' do Write (ch: 2);
выведет на экран последовательность букв в следующем виде:
a b с d e
Таким образом, заголовок оператора повтора for определяет:
· диапазон изменения управляющей переменной и одновременно число повторений оператора, содержащегося в теле цикла;
· направление изменения параметра цикла (возрастание на единицу – to или убывание на единицу – downto).
Например,
for k:=1 to 25 do Read(a[k]); {чтение элементов массива от 1 до 25}
for k:=25 downto 1 do Write(a[k]); {вывод элементов массива от 25 до 1}
Следует знать:
· начальное и конечное значения параметра цикла могут быть константами, переменными, выражениями и должны принадлежать к одному и тому же типу данных;
· начальное и конечное значения параметра цикла нельзя изменять во время выполнения цикла.
Например, рассмотрим фрагмент программы, в котором предпринята попытка "обмануть" оператор for и получить изменение параметра i на 2 на каждом шаге цикла (единица прибавляется автоматически и еще одна единица прибавляется в теле цикла).
for i:= 1 to 10 do
begin write {i: 4); i := i + 1; end;
В данном случае на экране будут выведены числа 13579.
Однако настоятельно не рекомендуем пользоваться таким приемом. Стоит только немного видоизменить заголовок цикла предыдущего примера и взять в качестве конечного значения 9, а не 10, как ваша программа не сможет нормально выйти из цикла — "зациклится", т. к. в момент проверки компьютером условия выхода из цикла i никогда не будет равно 9 (сначала 8, а потом сразу 10).
Приведем характеристику оператора повтора for
· Число повторений операторов цикла во многих случаях заранее известно или определяется в ходе работы программы
· в теле цикла запрещается явное изменение значения переменной-счетчика (например, оператором присваивания)
· переменная-счетчик должна быть порядкового типа: чаще — integer, реже — char, boolean или одного из пользовательских типов. Использование вещественного типа недопустимо
· Выйти из цикла можно, минуя вычисление выражения условия, с помощью оператора goto
· Оператор цикла может быть вложенным
· количество повторений цикла определяется начальным и конечным значениями переменной-счетчика. Оператор for обеспечивает выполнение тела цикла до тех пор, пока не будут перебраны все значения параметра цикла: от начального до конечного
· Необходимо использовать операторные скобки, если тело цикла содержит более одного оператора
Пример: Вычислить сумму гармонического ряда
Program SumR;
uses crt;
Var S: real;
k, n: integer;
begin
ClrScr;
Readln(n);
S:=0;
for k:=1 to n do S:=S+1/k;
Writeln;
Write (‘S=‘, S:4:2);
end.
В теле цикла лишь один оператор, поэтому операторные скобки begin и end не нужны.
Суммирование можно начать с n-го члена. Тогда первое слагаемое 1/n, а n будет уменьшаться на единицу: n = n-1.
Program SumR;
uses crt;
Var S: real;
k, n: integer;
begin
ClrScr;
Readln(n);
S:=0;
for k:=n downto 1 do
S:=S+1/k;
Writeln;
Write (‘S=‘, S:4:2);
end.
Пример: Табулирование функции. Составить таблицу значений аргумента х и функции y=Sin(x) на отрезке [0; 3,1] с шагом h=0,1.
Для решения данной задачи можно использовать оператор for,предварительно подсчитав количество повторений цикла по формуле приведенной в Главе 1.
для нашего случая количество повторений
Program Tablica;
uses crt;
Var x, y: real;
k: integer;
begin
ClrScr;
x:=0;
for k:=1 to 32 do
begin
y:=Sin(x);
Writeln(x:3:1,’ ‘:5,y:4:2);
x:=x+0.1;
end;
end.
Пример: Определить средний рост студентов в группе.
Исходной информацией для решения этой задачи является число студентов в группе и рост каждого студента. Число студентов в группе обозначим n. В переменной S будем накапливать сумму. Подсчет номера студента будем осуществлять в переменной i.
Ввод роста каждого студента и накопление суммы всех значений ростов студентов производится в цикле n раз. После завершения цикла определяем средний рост по формуле S=S/n.
Program SredRost;
uses crt;
Var S, r: real;
i, n: integer;
begin
ClrScr;
Readln(n);
S:=0;
for i:=1 to n do
begin
Read(r);
S:=S+r;
end;
S:=S/n;
Write(‘S=‘, S:4:2);
end.
Пример: Определить количество студентов в группе, имеющих рост выше среднего.
Исходные данные: количество студентов k и рост каждого студента r. Первая половина алгоритма разработана в предыдущей задаче – определен средний рост. Далее рост каждого сравнивается со средним.
Если вводимое значение роста студента превышает среднее значение, то в счетчик числа таких студентов необходимо добавить единицу k=k+1.
В блок-схеме имеется один недостаток: рост студентов в группе вводится дважды. При решении задачи на ПК, придется вводить одну и ту же информацию дважды. Этот недостаток можно устранить с использованием одномерного массива (см. Глава 4).
Program SredRost;
uses crt;
Var S, r: real;
i, n, k: integer;
begin
ClrScr;
Readln(n);
S:=0;
for i:=1 to n do
begin
Read(r);
S:=S+r;
end;
S:=S/n;
k:=0;
for i:=1 to n do
begin
Read(r);
If r>S then k:=k+1;
end;
Write(‘k=‘, k);
end.
Контрольные вопросы
1. Какие процедуры служат в Паскале для выполнения операций ввода-вывода?
2. В чем заключается отличие процедуры Readln от процедуры Read.
3. Для чего в процедурах вывода Write и Writeln определяется ширина поля вывода? Какие обозначения используются в форматах вывода?
4. Составьте программу, которая выводит на экран компьютера заставку, аналогичную следующей:
*
****************************************
*
*
*
*
Программа
*
*
вычисления суммы чисел
*
*
Автор: Петров В.И.
*
*
*
*
****************************************
*
5. Напишите программу, которая вводит значения четырех переменных A, B, C, D типа integer и выводит их сумму. Ввод пары значений A и B произвести на одной строке, C и D – на другой. Результат вывести на отдельную строку, и курсор оставить на той же строке.
6. Напишите программу ввода значений A, B, C в одной строке и выведите результат выражения в той же строке.
7. Напишите программу вычисления площади прямоугольного треугольника, значения катетов которого A и B вводятся с клавиатуры. Результат вывести в следующем виде: “Для значений катетов 4 и 6 площадь прямоугольного треугольного треугольника равна 12”.
8. Напишите программу получения следующей формы:
*****************************************
* A * B * A+B * A-B * A/B *
*****************************************
6 2 8 4 3.0
*****************************************
9. Что будет напечатано в результате работы программы:
Program Vivod;
var X, Y, С : real;
begin
Readln (X, Y);
С:=sqrt(sqr(X)-4*Y);
Writeln(‘ x1=‘, (-X+C)/2,
‘ x2=‘, (-X-C)/2)
end.
если в качестве исходных данных ввели 10 и -20 ?
10. Что будет напечатано в результате работы программы :
Program Vivod;
var X, Y : integer;
begin
Read (X, Y, X);
С:=sqrt(sqr(X)-4*Y);
Writeln(X, Y:2, X:5)
end.
если последовательно ввели три числа 10, -2, 8721?
11. Что такое оператор? Чем отличаются простые и структурные операторы?
12. Какие из этих операторов присваивания неверные:
Program Pr;
var X : integer;
Y: byte;
Z, Z1 : real;
C: char;
D, D1: boolean;
begin
Read (X, Y);
Z:=sqr(X)-4*Y;
C:=65;
D:=X+Y;
Y:=Z-X;
Z1:= X mod Z;
D1:=X<Z;
end.
13. Где ошибка в следующей программе?
Program Lab;
var X , Y, Z : real;
begin
Read (X, Y);
Z:=sqr(X)-4*Y;
If X > Z then goto M2;
Z:=Z-X;
M2:
end.
14. В чем особенности пустого оператора? Нужен ли он в данной программе?
Program P_O;
var X , Y : real;
i: integer;
begin
Read (X);
For i:=1 to 5 do ;
Y:=Y+X;
end.
15. Что представляет собой составной оператор? Где ошибка в данной программе?
Program S_O;
var X , Y , Z: real;
begin
Read (X, Y);
if Y<>0 then Z:=X/Y; Write (Z) else Write(‘Деление на ноль ‘)
end.
16. Где ошибки (их четыре) в следующей программе?
Program Usl_Op;
const
X , Y , Z: real
begin
Read (X, Y);
if X<Y then Z:=X-Y; else X>Y then Z:=X+Y;
Write(Z)
end.
17. Найдите значение переменной Z при заданных исходных данных
1) X=12, Y=7
2) X=-2, Y=3
Program Viсhisl;
var X , Y , Z: integer;
begin
Read (X, Y);
if X<Y then if X>0 then Z:=Y-X else Z:=X+Y else Z:=X-Y;
Write(Z)
end.
18. Каковы отличия оператора выбора case от оператора условия if ? Какие правила должны выполняться при использовании оператора выбора case?
19. Где ошибки (их три) в следующей программе?
Program Grib;
var X : real;
begin
Readln (X);
case X of
1, 21, 31 : Write(‘ Мы нашли ‘, X, ‘ гриб‘ );
2..4, 22..24 : Write(‘ Мы нашли ‘, X, ‘ гриба‘ );
5.. 20, 25..30 : Write(‘ Мы нашли ‘, X, ‘ грибов‘ );
else Write(‘ Мы нашли много грибов‘ );
end.
20. Каково назначение операторов повтора?
21. В чем отличия операторов повтора while и repeat?
22. В каких случаях предпочтительнее использовать для организации циклов оператор повтора for? Что записывается в заголовке этого оператора?
23. Каким образом в оператор повтора for описывается направление изменения значения параметра цикла?
24. Какие ограничения налагаются на использование управляющей переменной (параметра цикла) в цикле for?
25. Данную программу перепишите с помощью операторов повтора repeat и for:
Program Vichislenie;
var X, Y : real;
begin
X:=2;
while X<=11 do
begin Y:=sin(X)/cos(X);
Writeln(X:5:2, Y:7:2);
X:=X+0.5
end
end.
26. Напечатать таблицу значений функций sinx и cosx на отрезке [0, 1] с шагом 0,1 в следующем виде:
27. Найдите значение переменной Z при заданных исходных данных
1) Y=7
2) Y=23
Program Povtor;
var i, Y , Z: byte;
begin
i:=2; read(Y);
repeat Z:=Y+i;
Y:=Y+1
until Y>15; Write(Z)
end.
28. Где ошибки (их четыре) в следующей программе?
Program Parametr;
var i , Y : real;
begin
For i:=1.1 to 5 do
begin Y:=Y+i;
i:=i+0.1 ;
Writeln(Y:4:1)
end.
29. Напишите программу печати таблицы перевода расстояний из дюймов в сантиметры (1 дюйм = 2,5 см) для значений длин от 1 до 20 дюймов.
30. Найдите значение переменной Z при заданных исходных данных
1) Y=7
2) Y=28
Program Cikl;
var i, Y , Z: byte;
begin
read(Y);
for i:=25 downto Y do Z:=Y+i;
Write(Z)
end.
ГЛАВА 4
Массивы
Массив - это упорядоченная последовательность величин, имеющих один и тот же тип и объединённых одним именем.
Число элементов массива задаётся при описании и в процессе выполнения программы не меняется. Имя массива образуется аналогично имени любой другой величины. Отдельные величины, составляющие массив, называются элементами массива. При обращении к элементу массива, необходимо указывать его имя, а в квадратных скобках его индексы.
Для работы с массивами как единым целым используется имя массива без указания индекса в квадратных скобках. Массив может участвовать только в операциях отношения "равно и не равно" и в операторе присваивания. Массивы, участвующие в этих действиях, должны быть тождественны по структуре или иметь одинаковые типы индексов и одинаковые типы компонентов.
Элементы массива могут быть использованы так же, как и простые переменные. Например, они могут находиться в выражениях в качестве операндов, использоваться в операторах for, while, repeat,входить в качестве параметров в операторы Read, Write, им можно присваивать любые значения, соответствующие их типу. Индексы массива должны быть целого типа, и индексы могут иметь как положительные, так и отрицательные значения, а также индексы могут быть нулями.
Если элемент массива имеет только один индекс, массив называется одномерным, если два индекса - двухмерным.
4.1 ОДНОМЕРНЫЕ МАССИВЫ
В математике такие структуры называются векторами. Массив имеет фиксированное количество однородных компонент. При описании массива, указывается количество и тип этих компонент. Значения такого типа хранятся в оперативной памяти. К каждой компоненте можно обращаться непосредственно.
Формат:
<имя> : array[n .. m] of <тип>;
где имя – имя переменной-массива;
array – зарезервированное слово, обозначающее, что переменная является массивом;
n, m – нижний и верхний индексы, целые константы, определяющие диапазон изменения индексов элементов массива (т.е. размер массива);
тип– тип элементов массива.
Описание одномерных массивов можно произвести в следующих разделах:
· В разделе объявления переменных
Var a: array[1..100] of integer; {100 элементов – целые числа}
b: array[1..50] of char; {51 элемент - символы}
c: array[-3..4] of boolean; {8 элементов – логические значения}
Обратите внимание: при выполнении программы вовсе не обязательно заполнять все ячейки данными, т.е. реальное количество элементов в массиве может быть меньше, чем указано при описании, но ни в коем случае не должно быть больше.
· В разделе констант
Const i=14;
Var a: array[1..i] of real;
Употребление констант при описании массива предпочтительно, т.к. в случае изменения размеров массива не нужно будет вносить исправления по всему тексту программы, достаточно только один раз изменить значение именованной константы.
· В разделе описания типов
Type d=array[1..23] of real;
Var a, b, c: d;
Приведем примеры неправильного описания массивов:
a: array [ ] of real; {не определены размерность и границы диапазонов}
b: array [10..1] of integer; {значение нижней границы массива превышает значение верхней}
c: array [1..a+b] of real; {границы массива необходимо задать константой, а не выражением}
d: array [1.0..100.0] of integer; {недопустимо использовать вещественные числа для границ индексов}
Чтобы непосредственно обратиться к некоторому элементу массива, нужно указать имя массива, а в квадратных скобках указать номер элемента.
Например,дан массив B из 3 элементов (b1=3, b2= -14, b3=25), тогда, чтобы обратиться ко второму элементу, нужно записать: b[2].
Запись В(3) означает, что массив B состоит из трёх элементов. Часто вместо слова “массив”, используют понятие “последовательность чисел”. Например: дан массив S(4) и дана последовательность чисел S1, S2, S3, S4 - это означает одно и тоже, поэтому и описываются совершенно одинаково.
Необходимо четко различать индекс элемента массива и значение элемента. Например, в операторе a[3]:=1; число 3 – это индекс (номер) элемента массива, а 1 – значение, которое ему присваивается.
Примеры ошибочного обращения к элементам массивов:
var f: array [1..10] of real;
…
f [5.0]… {использование вещественного индекса запрещено}
f [1,4]… {несоответствие размерности – к вектору обращаются как к матрице}
Следует знать:
· границы изменения индексов должны быть константами, причем очень удобно использовать именованные константы;
· нижняя граница индекса чаще всего равна 1, т.е. обычно элементы массива нумеруются, начиная с единицы (иногда нумерация начинается с нуля);
например,
var x: array [0..50] of integer; {массив содержит 6 элементов, номера с нулевого по пятый}
· для ввода, вывода и обработки массивов удобно применять циклы (особенно удобен в этих случаях цикл for, т.к. номера элементов следуют по порядку друг за другом с единичным шагом).
· массивы, идентичные по структуре, т.е. с одинаковыми типами индексов и элементов, могут участвовать в операторе присваивания без указания индекса.
4.2 ДВУМЕРНЫЕ МАССИВЫ
Массивы с двумя индексами называют в математике матрицами.
Двумерным массивом называется совокупность данных, каждое значение которых зависит от двух чисел, которые можно рассматривать как индекс строки и индекс столбца в матрице.
Формат:
<имя> : array[n1..n2, m1..m2] of <тип>;
Здесь величины n1 и n2 (индексы строки), m1 и m2 (индексы столбца) являются целочисленными константами.
Описание двумерных массивов производится аналогично описанию одномерных массивов:
· в разделе описания типов
Type zatrat = array[1..5, 1..5] of real;
Var a : zatrat;
· в разделе констант
Const i=5; j=7;
Var S: array[ 1..i, 1..j ] of integer;
· в разделе объявления переменных
Var А: array[1..5, 1..6] of real;
Запись А(5,7) означает, что речь идёт о двумерном массиве, в котором 5 строк и 7 столбцов.
Запись А[5,7]означает, что речь идёт об элементе двумерного массива, который находится в пятой строке и в седьмом столбце массива А.
4.2.1 Квадратные матрицы
Квадратные матрицы (число строк равно числу столбцов) имеют главную и побочную диагонали.
а11 а12 а13
А = а21 а22 а23
а31 а32 а33
Если:
· i = j - элементы расположены на главной диагонали (а11, а22, а33).
· i < j - элементы расположены выше главной диагонали (а12, а13, а23).
· i > j - элементы расположены ниже главной диагонали (а21, а31, а32).
· i + j = n + 1 (n – размерность матрицы) — элементы расположены на побочной диагонали (а13, а22, а31).
· i + j < n + 1— элементы расположены над побочной диагональю.
· i + j > n + 1— элементы расположены под побочной диагональю.
4.3 ДЕЙСТВИЯ НАД МАССИВАМИ
Если указываются в квадратных скобках индексы, то такое обращение к массиву называется поэлементным. Но с массивом можно работать и как с единым объектом. При работе с массивом как с единым целым используется имя массива без указания индекса в квадратных скобках. При этом к массиву может применять только операции отношения “равно”, “не равно” и оператор присваивания. Массивы, участвующие в этих действиях, должны иметь одинаковые типы индексов и одинаковые типы компонент.
Например, если массивы А и В описаны как:
Var A: array[1..16,1..5] of real;
B: array[1..16,1..5] of real;
то применение к ним допустимых операций даст следующий результат:
¨ А=В
Результатом данного сравнения будет истина, если значение каждого элемента массива А совпадает со значением соответствующего элемента массива В. В противном случае результат будет ложным.
¨ А<>B
Результат данного сравнения будет истинным, если хотя бы одно значение элемента массива А не равно значению соответствующего элемента массива В. результат будет ложным, если все элементы массива А равны соответствующим элементам массива В.
¨ A:=B
Согласно правилам работы оператора присваивания, в результате работы данного оператора, элементам массива А присвоятся значения соответствующих элементов массива В.
4.4 ДЕЙСТВИЯ НАД ЭЛЕМЕНТАМИ МАССИВА
Рассмотрим два массива, описанных в разделе констант:
Const k=4; n=12; m=23;
Var A: array[1..k] of real;
D: array[ 1..n,1..m] of real;
i, j: integer;
4.4.1 Ввод элементов массива
Под вводом массива понимается получение от пользователя во время работы программы значений элементов массива.
I способ – ввод элементов последовательно через клавиатуру:
для одномерного массива
for i:=1 to k do read(A[i]);
для двумерного массива
for i:=1 to n do
for j:=1 to m do read(D[i,j])
II способ – вычисление значений элементов массива по заданным формулам:
для одномерного массива
for i:=1 to k do A[i]:=f(x);
для двумерного массива
for i:=1 to n do
for j:=1 to m do D[i,j] :=f(x);
III способ – задание массива с помощью функции-генератора случайных чисел:
Под выводом массива понимается вывод всех значений элементов массива с использованием операторов Write, Writeln.
Вывод элементов для одномерного массива (вектора):
- в одну строку, через пробел-разделитель:
for i := 1 to k do Write(A[i], ‘ ‘);
- в столбец:
for i := 1 to k do Writeln(A[i]);
- с заданием формата, где под каждый элемент отводится 4 позиции:
for i := 1 to k do Write(A[i]:4);
Вывод элементов для двумерного массива (матрицы)
- вывод элементов массива в одну строку
for i := 1 to n do
for i := 1 to m do Write(D[i,j]:4);
- вывод элементов массива в один столбец
for i:=1 to n do
for j:=1 to m do Writeln(D[i,j]);
- вывод элементов массива в стандартной форме записи – по строкам и столбцам - выполняется при помощи оператора Writeln (без параметра). Он используется после вывода текущей строки матрицы для перевода курсора в начало следующей строки экрана:
for i:=1 to n do
begin
for j:=1 to m do write(D[i,j]:4);
writeln {переход на новую строку}
end;
Задание формата вывода помогает расположить матрицу на экране ровными столбцами.
4.4.3 Обработка элементов одномерного массива
· Вычисление суммы элементов
S:=0;
for i:=1 to k do S:=S+A[i]; {обычное накопление суммы в S}
· Вычисление произведения элементов
S:=1;
for i:=1 to k do S:=S*A[i]; {накопление произведения в S}
· Подсчет количества элементов, удовлетворяющих какому-либо условию
r:=0;
for i:=1 to k do
if A[i] mod 2 =0 then r:=r+1; {увеличиваем на 1 счетчик четных чисел}
· Поиск максимального элемента и его номера
Переменные max – хранит значение максимума,
p – его номер в массиве.
max:=a[1]; {поиск начинаем с первого элемента}
p:=1;
for i:=2 to k do {перебираем элементы, начиная со второго}
if A[i] >max then
begin
max:=A[i]; p:=i; {запоминаем значение и номер элемента, который больше всех предыдущих}
end;
· Перестановка элементов в массиве
При перестановке элементы массива меняются местами друг с другом, их значения при этом не изменяется, но изменяется порядок следования элементов. Для выполнения перестановок обычно используется третья переменная, которая служит для временного хранения одного из элементов и играет роль буфера обмена.
buf:=A[1];
A[1]:=A[2];
A[2]:=buf;
4.4.4 Обработка элементов двумерного массива
· Суммирование элементов каждой строки
for i:=1 to n do
begin
S:=0;
for j:=1 to m do S:=S+D[i,j];
end;
· Суммирование элементов каждого столбца вычисляется аналогично. Для этого внешний цикл необходимо сделать по переменной j (номер столбца), а внутренний – по i (номер в строке).
for j:=1 to m do
begin
S:=0;
for i:=1 to n do S:=S+D[i,j];
end;
· Поиск минимального элемента всей матрицы и его номера.
Переменные min – хранит значение минимального элемента,
p – номер строки, h - номер столбца, где он находится.
min:=D[1,1];
p:=1;
h:=1;
for i:=1 to n do
for j:=1 to m do
if D[i,j] <min then begin min:=D[i,j]; p:=i; h:=j end;
4.5 ПРИМЕРЫ ЗАДАЧ НА МАССИВЫ
Пример.Дан целочисленный массив С(15). Найти сумму элементов C1+C2+…+C15.
program Summa ;
Var C : array[1..15] of integer;
s, i : integer;
Begin
S:=0;
for i:=1 to 15 do
begin
read(C[i]); {ввод массива}
s:=s+C[i]; {суммирование элементов массива}
end;
Write(s)
end.
В программе организован цикл для ввода одномерного массива с клавиатуры, в нем же производится в переменной S накапливание суммы элементов массива. После окончания цикла выводится значение переменной S.
Пример.Заполнить массив, применив для его заполнения следующее значение: a[i]=(x*i2)/(i+x). Найти сумму элементов массива, имеющих нечетные номера.
program Sozd_massiv ;
Const n=10;
Var a : array[1..n] of real;
i : integer; x, S : real;
begin
Write(‘Введите значение х:‘);
Readln(x);
for i:=1 to n do
begin
a[i]:=x*sqr(i)/(i+x);{создание массива}
Write(a[i]:8:4)
end;
S:=0;
for i:=1 to n do
if i mod 2<>0 then S:=S+a[i];
Write(‘Сумма = ‘, S:4:2)
end.
Перед оператором ввода Readln(x) выполняется оператор вывода Write(‘Введите значение х:‘), который представляет собой подсказку для пользователя при вводе исходной информации.
В программе организованы два цикла, в первом из которых производится вычисление каждого элемента массива по заданной формуле и вывод их на экран в одну строку с заданием формата. Во втором цикле в переменной S происходит накапливание суммы элементов массива, имеющих нечетные номера. Определение нечетного номере элемента производится при помощи целочисленной операции mod.
Пример.Заполнить массив из пятнадцати элементов случайным образом целыми значениями, лежащими в диапазоне от -10 до 10. В этом массиве удалить k-й элемент массива.
Вывод S
program Delete;
Const n=15;
Var a : array[1..n] of integer;
i , k : integer;
begin
Randomize;
for i:=1 to n do
begin
a[i]:=random(21)-10;
Write(a[i]:8)
end;
Writeln;
Write(‘Введите номер элемента для удаления‘);
Readln(k);
for i:=k to n-1 do a[i]:=a[i+1];
a[n]:=0;
for i:=1 to n-1 do Write(a[i]:8)
end.
В программе организован цикл для ввода одномерного массива с использованием функции-генератора случайных чисел. Напомним, что случайные целые числа, принадлежащие отрезку [а,b], вычисляют по формуле a+random(b-a+1).
В операторе Readln(k) вводится номер удаляемого элемента массива. Под удаление элемента понимается его исключение из массива путем смещения всех следующих за ним элементов влево на одну позицию и присваивание последнему элементу массива значения ноль, если нет других оговорок. Поэтому в последнем цикле производится вывод элементов массива, исключая последний элемент.
Пример: Определить количество студентов в группе, имеющих рост выше среднего.
Program SredRost;
Uses crt;
Const n=25;
Var r : array[1..n] of real;
S: real; i, k: integer;
begin
ClrScr;
S:=0;
for i:=1 to n do
begin
Read(r[i]);
S:=S+r[i];
end;
S:=S/n;
k:=0;
for i:=1 to n do
begin
If r[i]>S then k:=k+1;
end;
Write(‘k=‘, k);
end.
Эта задача была ранее разобрана в Главе 3. Недостаток ввода одной и той же информации дважды устранили с использованием одномерного массива, элементами которого являются рост каждого студента r[i].
Пример:Найти минимальный и максимальный элементы последовательности а, состоящей из десяти элементов.
Program MinMax;
Uses crt;
Const n=10;
Type d=array[1..n] of integer;
Var a : d;
i, min, max: integer;
begin
ClrScr;
for i:=1 to n do
begin
Write(‘Введите’,i,’-й элемента массива‘);
Readln(a[i]);
end;
min:=a[1];
max:=min;
for i:=2 to n do
begin
If a[i]>max then max:=a[i];
If a[i]<min then min:=a[i];
end;
Write(‘max=‘,max, ‘min=’,min);
end.
Перед оператором ввода Readln(a[i]) выполняется оператор вывода Write(‘Введите’,I,’-й элемента массива‘), который представляет подсказку для пользователя при вводе исходной информации.
При i=1 на экране высветится: Введите 1-й элемент массива,
курсор остановится в конце выведенной строки, ПК приостановит выполнение программы до момента ввода пользователя численной информации.
При i=2 на экране высветится: Введите 2-й элемент массива и так далее до конца выполнения цикла.
Присвоим переменной min и max значение первого элемента, и далее будем перебирать все элементы последовательности от 2 до n, сравнивая a[i] с max и с min. Если a[i] окажется больше, чем max, то max присваивается значение a[i]. Если a[i] окажется меньше, чем min, то min присваивается значение a[i]. По окончании цикла max примет значение наибольшего элемента последовательности, а min - наименьшего.
Пример:Заполнить двумерный массив случайным образом целыми значениями, лежащими в диапазоне от -25 до 50 и вывести его в стандартном виде (в виде матрицы).
Program Matrica;
Const n=5; m=6;
Var B: array[1..n,1..m] of integer;
i, j : integer;
begin
for i:=1 to n do
begin
for j:=1 to m do
begin
B[i,j]=random(76)-25;
Write(B[i,j]:4)
end;
Writeln
end;
end.
Решение этой задачи включает в себя: формирование элементов массива при помощи функции – генератора случайных чисел и вывод их в виде матрицы.
Индексы i и j определяют номер строки и столбца.
Вывод элементов массива в виде матрицы выполняется при помощи оператора Writeln (без параметра), который используется после вывода текущей строки матрицы для перевода курсора в начало следующей строки экрана.
Пример:Найти количество ненулевых элементов вещественного массива А(12,10).
Начало
Program Kolvo;
Var a: array[1..12,1..10] of real;
i, j, k : integer ;
begin
for i:=1 to 12 do
for j:=1 to 10 do read (a[i,j]);
k:=0;
for i:=1 to 12 do
for j:=1 to 10 do
if a[i, j]<>0 then k:=k+1;
Write('Количество =', k)
end.
Решение задачи содержит следующие этапы: ввод элементов исходной матрицы с клавиатуры, подсчет количества ненулевых элементов и вывод результата на экран.
Пример:Дан массив C(15,55). Найти сумму положительных элементов в каждом столбце данного массива.
+
_-
Program stolbec;
Var C: array[1..15,1..55] of real;
i, j : integer ; S: real;
begin
for i:=1 to 15 do
for j:=1 to 55 do read(C[i, j]);
for j:=1 to 55 do
begin
S:=0;
for i:=1 to 15 do
if C[i , j]>0 then S:=S+C[i, j];
writeln(’ В’, j, ’-ом столбце сумма=:’, S)
end
end.
Решение задачи содержит два этапа: ввод элементов исходной матрицы с клавиатуры и подсчет суммы положительных элементов каждого столбца.
На втором этапе внешним циклом является цикл по индексу j (по столбцам). Тело внешнего цикла содержит следующие действия: задание нулевого значения суммы; выполнение внутреннего цикла от начального до конечного значения параметра i (по строкам) для подсчета суммы положительных элементов при неизменном значении параметра внешнего цикла; вывод значения суммы данного столбца. Затем j - параметр внешнего цикла изменяется на единицу, и опять от начала и до конца выполняется тело цикла.
Пример:Определить среднее арифметическое элементов побочной диагонали в заданном массиве А(8,8).
Program Sred_ar;
Const n=8;
Var A: array[1..n,1..n] of integer;
i, j , S: integer ;
begin
S:=0; k:=0;
for i:=1 to n do
for j:=1 to n do
begin
Read(A[i, j])
if i+j< n+1 then
begin
S:=S+A[i, j];
k:=k+1;
end;
end;
Writeln(’Среднее арифметическое элементов над побочной диагональю’,
S/k:4:2)
end.
В переменной S будем накапливать сумму элементов, расположенных над побочной диагональю, а в переменной k подсчет количества этих элементов. После завершения цикла определяем среднее арифметическое по формуле S=S/k.
Пример:Сформировать квадратную матрицу порядка n по формуле . Составить одномерный массив S из положительных элементов главной диагонали введенной матрицы.
Program Sred_ar;
Const n=10;
Var A: array[1..n,1..n] of real;
S: array[1..n*n] of real;
i, j , k: integer ;
begin
k:=0;
for i:=1 to n do
begin
for j:=1 to n do
begin
A[i, j]:=Sin((sqr(i)-sqr(j))/n);
Write(A[i, j]:6:2);
if (i=j) and (A[i, j]>0) then
begin
k:=k+1;
S[k]:= A[i,j]
end;
end;
Writeln;
end;
for i:=1 to k do Write(S[i]:6:2)
end.
Решение задачи содержит два этапа: вычисление элементов квадратной матрицы по формуле и создание нового одномерного массива из двумерного согласно заданному условию.
При описании массива необходимо указывать фиксированное количество компонент. Так как размерность нового одномерного массива заранее неизвестно, то в описании указывается максимально возможное количество элементов, которое не будет превышать размерности матрицы. А реальное количество элементов в новом массиве будет определяться переменной k.
4.6 СОРТИРОВКА ОДНОМЕРНОГО МАССИВА
Сортировка – это процесс упорядочивания набора данных одного типа по возрастанию или убыванию значения какого-либо признака.
При сортировке элементы массива меняются местами таким образом, что их значения оказываются упорядоченными или по возрастанию, или по убыванию. Если в массиве есть одинаковые элементы, то говорят о сортировке по неубыванию или по невозрастанию.
Существует целый класс алгоритмов сортировки:
· Линейная сортировка (сортировка методом прямого выбора)
Идея линейной сортировки по неубыванию заключается в том, чтобы, последовательно просматривая весь массив, отыскать наименьший элемент и поменять местами его с первым элементом. Затем просматриваются элементы массива, начиная со второго, снова находится наименьший, который меняется местами со вторым и т.д., пока не будет отсортирован весь массив.
· Сортировка методом прямого обмена («пузырьковый» метод)
Метод основан на том, что весь массив просматривается с конца и в том случае, если из двух соседних элементов «нижний