Если вычислительный процесс зависит от определенных условий и реализуется по одному из нескольких заранее предусмотренных направлений, он называется разветвляющимся вычислительным процессом, а каждое из этих направлений – ветвью вычислений. Для выбора ветви вычислений в Паскале используются операторы IF и.. Однако прежде, чем перейти к рассмотрению этих операторов, необходимо познакомиться с понятиями составного оператора, логическими операциями и выражениями.
Составной оператор
Составной оператор предписывает выполнение составляющих его операторов в порядке их написания. Зарезервированные слова BEGIN и END являются операторными скобками. Формат оператора:
BEGIN {Начало составного оператора}
<Оператор 1;>
< Оператор 2;>
…
< Оператор n>
END; {Конец составного оператора}
Составной оператор используется в тех конструкциях, где по синтаксису языка должен быть только один оператор, а для решения задачи требуется более одного. В составном операторе все операторы 1, 2,..., n выполняются последовательно ДРУГ за другом.
Логические выражения
Одним из нечисловых видов данных является тип BOOLEAN. Булевы (логические) переменные имеют только два значения: FALSE (ложь), TRUE (истина). Существует несколько форм конструирования логического выражения:
• константа, описанная в разделе CONST;
• переменная, которой можно присвоить булевы значения (например FLAG:= TRUE);
• отношение между переменными скалярных и некоторых структурированных
типов.
В Паскале допускаются отношения, перечисленные в таблице 16.
Таблица 16
Отношение | Содержание | Отношение | Содержание |
= | равно | о | не равно |
> | больше, чем | >= | больше, чем... или равно |
< | меньше, чем | <= | меньше, чем... или равно |
|
Пример 6.
Пусть заданы вещественные переменные А, В и логическая переменная FLAG. Требуется построить примеры простых логических выражений, содержащих отношения между А и В.
Если:
VAR
FLAG, FLAG1, FLAG2: BOOLEAN;
А, В: REAL;
тогда допустимы выражения вида:
FLAG:= А <= В;
Значение TRUE 'истина' присваивается переменной FLAG, если А меньше или равно В.
FLAG 1:= А <> В;
Значение TRUE 'истина' присваивается переменной FLAG1, если А не равно В.
FLAG2:= А = В;
Значение TRUE 'истина' присваивается переменной FLAG2, если А равно В.
Помимо указанных выше отношений (таблица 16), логические выражения конструируются с помощью булевых операций, описанных в таблице 17.
Таблица 17
Математическое обозначение | Название | Обозначение в Паскале |
Логическое отрицание НЕ | NOT | |
˄ | Логическая конъюнкция И | AND |
˅ | Логическая дизъюнкция ИЛИ | OR |
Исключающее ИЛИ | XOR |
Пример 8.
Сформулировать логическое условие попадания точки с координатами (х, у) в область S (рисунок 2).
Пусть:
VAR FLAG: BOOLEAN;
Уравнение окружности, которая ограничивает область S в первом и втором квадранте системы координат XOY имеет вид:
.
Тогда величину FLAG, которая принимает значение TRUE в том случае, когда точка с координатами (х, у) принадлежит области S, можно найти по формуле:
FLAG:= (Х>=-A) AND (Х<=А) AND (((Y<=SQRT(A*A-X*X)) AND (Y>=0)) OR ((Y<0) AND (Y>=B)));
В языке Паскаль логическое выражение просчитывается до тех пор, пока результат не становится очевидным. После чего вычисления прекращаются. Так в нашем случае используется конъюнкция трех условий: X больше - А, X меньше А и ограничение на значение Y. Достаточно любой логической величине принять значение FALSE и остальные величины, стоящие правее в логическом выражении, уже не просчитываются, так как переменная FLAG независимо от значений оставшихся отношений будет равна FALSE. В нашем случае это удобно! Потому, что уравнение окружности определено для значений X, удовлетворяющих условию -А < X < А. Именно это условие и проверяется в двух левых отношениях, поэтому используемое логическое выражение Y<=SQRT(А* А - Х*Х) для расчета переменной FLAG корректно для любых значений X.
|
PROGRAM PR8;
VAR
А, В, X, Y: REAL;
FLAG: BOOLEAN;
BEGIN
WRITELN('Введите параметры А и В');
READLN(A, В);
WRITELN('Введите координаты X и Y); READLN(X, Y);
FLAG:= (X>—A) AND (X<=A) AND (((Y<=SQRT(A*A - X*X)) AND (Y>-0))
OR ((Y<0) AND (Y>~B)));
IF FLAG THEN WRITELN('Tочкa в области S')
ELSE WRITELN('Toчкa вне области S')
END.
В стандартном Паскале предусмотрен порядок старшинства операций в булевых выражениях: Высший - (скобки); NOT; AND; (OR, XOR); (>, =, >-, <-, <>) - низший. Однако в различных версиях языка эти требования могут и не соблюдаться, поэтому надежнее использовать скобки для уточнения последовательности вычислений.
Существуют встроенные булевы функции, наиболее известные из которых ODD(X), EOF(F), EOLN(F), описание которых приведено в таблице 10.
Логическое выражение может быть достаточно сложным и включать в себя арифметические и логические функции, например:
FLAG:= ODD(I*3+K) AND ((SQR(C) > SIN(D/2)) OR (A = 5));
Переменная FLAG принимает значение TRUE, если целочисленное выражение
I*3 + К принимает нечетное значение и квадрат С больше, чем синус D, деленной пополам, или А равно 5. В противном случае FLAG принимает значение FALSE.
|
В приведенных примерах в правой части оператора присваивания расположено логическое выражение, а в левой части – логическая переменная.
Организация условного перехода. Оператор IF
Для программирования разветвляющихся процессов, содержащих две ветви, используется оператор IF условного перехода (ветвления), имеющий две конструкции.
Сокращенная форма (Алгоритм: блок-схема – рисунок 3.а, структурограмма – рисунок 4.а):
IF < Условие >
THEN < Оператор >;
В качестве условия можно использовать переменную или выражение логического типа. В этой конструкции Оператор выполняется в том случае, когда логическое выражение принимает значение TRUE. Вторая ветвь процесса, содержащая пустой оператор и в явном виде не описываемая, соответствует значению условия FALSE.
Другая, полная форма этого оператора имеет синтаксическую структуру (Алгоритм: блок-схема – рисунок 3.б, структурограмма – рисунок 4.б):
IF < Условие >
THEN < Оператор 1>
ELSE < Оператор 2>;
Здесь обе ветви процесса значимы. При значении логического выражения (переменной) TRUE выполняется Оператор 1, который всегда располагается за ключевым словом THEN, при FALSE – выполняется Оператор 2 (ветвь ELSE). Если в одну из ветвей требуется включить более одного оператора, то их следует объединить составным оператором BEGIN... END.
Вложенная конструкция операторов условного перехода используется в случае, если существует более двух ветвей в вычислительном процессе. В случае вложенной конструкции Оператор 1, или Оператор 2, или оба вместе представляют собой также операторы условного перехода. В этих случаях легко запутаться при отладке программы. Но следует помнить, что ELSE всегда относится к ближайшему слева THEN.
Пример 9. Для заданного с клавиатуры значения X вычислить Y по формуле:
Эту задачу можно решить двумя способами.
Первый способ предусматривает использование трех операторов IF сокращенной формы. Алгоритм решения достаточно прост (структурограмма на рисунке 5.а). Последовательно проверяется три взаимно исключающих друг друга условия, образующих полную группу событий. Для любого X только одно условие примет значение TRUE, остальные два условия равны FALSE. Таким образом, оператор присвоения выполнится только один раз и этот оператор будет соответствовать условию, имеющему значение TRUE. Программная реализация — PR9_1.
Второй способ предусматривает использование двух вложенных операторов IF полной формы. Алгоритм этого способа реализован в виде блок-схемы на рисунке 5.б. Программная реализация — PR9_2.
Сравнительный анализ этих двух способов показывает, что первый проще в понимании и легче в отладке. Второй способ более сложный, однако более компактный и более быстрый.
Конечно, при одной реализации вычислительного процесса это преимущество не столь существенно, но если таких реализаций десятки тысяч, то несколько секунд можно сэкономить.
PROGRAM PR9_1; VAR X, Y: REAL; BEGIN WRITELN('ВВЕДИТЕ X'); READLN(X); IF X>= 1 THEN Y:= EXP(LN(X)/3)/2; IF (X>0) AND (X<1) THEN Y:= X*X*0.33; IF X<=0 THEN Y:= EXP(LN(ABS(X))/4)/4; WRITELN('Y=',Y:10:6) END. | PROGRAM PR9_2; VAR X, Y: REAL; BEGIN WRITELN('ВВЕДИТЕ X'); READLN(X); IF X<=0 THEN Y:= EXP(LN(ABS(X))/4)/4 ELSE IF X>= 1 THEN Y:= EXP(LN(X)/3)/2 ETSE Y:=X*X*0.33; WRITELN('Y=', Y) END. |
Ввести X |
X>=1 |
True |
0<X<1 |
True |
X<=0 |
True |
Вывод Y |
Пример 10. Составить программу, которая по введенному значению X вычисляет и выводит значение Y - F(X), где F(X) задана графически на рисунке 6.
Эта задача отличается от задачи, описанной в предыдущем примере, только тем, что нужно самому составить формулу для функции F(X). В предыдущей задаче эта формула была задана в качестве исходных данных. Таким образом, от вас требуют сделать формальную, математическую постановку задачи, которая в данном случае сводится к составлению по графику формулы.
Глядя на график, нетрудно увидеть, что на нем изображена кусочно-линейная функция, содержащая три прямых линии. Первая прямая имеет уравнение Y=-X-1 и определена для X < 0. Вторая линия определена на отрезке 0 < X < 1 и имеет уравнение Y = X - 1. Третья прямая линия имеет уравнение Y = 0 и определена для X > 1. С учетом вышесказанного искомая формула будет иметь вид:
Текст программы составим по аналогии с программой PR9_2, которая подробно описана в предыдущем примере.
PROGRAM PR10;
VAR X,Y: REAL;
BEGIN
WRITELN('BBEДИTE X'); READLN(X);
IF X<=0 THEN Y:= -X-l
ELSE IF X >=1 THEN Y:= 0
ELSE Y:=X- 1;
WRITELN(Y=', Y)
END.
Пример 11. Найти расстояние от внешней, произвольной точки М с координатами (X, Y) до контура геометрической фигуры, изображенной на рисунке 7.
В этом задании нужно рассмотреть чертеж геометрической фигуры. Нетрудно заметить, что во втором квадранте декартовой системе координат изображен сектор круга, центр которого расположен в центре системы координат. Радиус сектора равен R. Для решения поставленной задачи требуется выделить области и для каждой из них написать уравнение, с помощью которого можно вычислить расстояние D до контура фигуры. На чертеже выделено шесть областей, в каждой из которых поставлена одна произвольная точка Мк. Номер точки К соответствует номеру области. Любая точка в области М1, имеет кратчайшее расстояние до дуги сектора, вычисляемое по формуле:
Вторая область, помеченная точкой М2, имеет кратчайшее расстояние до точки с координатами (- R, 0). Это расстояние можно найти по формуле:
Третья область, помеченная точкой М3, имеет кратчайшее расстояние равное расстоянию до оси абсцисс. Это расстояние легко найти по формуле:
D = |Y|, 0≥X≥-R, Y≤0.
Четвертая область, которой соответствует точка M4, имеет кратчайшее расстояние равное расстоянию до начала координат. Это расстояние находится по формуле:
Пятая область, помеченная точкой М5, имеет кратчайшее расстояние равное расстоянию до оси ординат. Это расстояние легко найти по формуле:
D = X, 0≤Х, R≥Y≥0.
Последняя шестая область, помеченная точкой М6, имеет кратчайшее расстояние до верхней точки сектора с координатами (0, R). Это расстояние можно найти по формуле:
На основании вышесказанного, математическая постановка задачи будет такой. Если точка находится вне сектора, изображенного на рисунке 7, то будет ложно условие:
.
Учитывая приведенные выше формулы, можно найти кратчайшее расстояние до контура фигуры по формуле:
Теперь, когда формальная постановка задачи сделана и найдены формулы, можно перейти к этапу алгоритмизации (Самостоятельно) и написания программы:
PROGRAM PR11;
VAR
X, Y, R, D: REAL;
BEGIN
WRITELN('BBEДИТЕ РАДИУС СЕКТОРА R');
READLN(R);
WRITELN('BBEДИТЕ КООРДИНАТЫТОЧКИ X, Y');
READLN(X, Y);
IF (X<0) AND (Y>0) AND (SQRT(X*X + Y*Y)<R)
THEN WRITELN('ТОЧКА РАСПОЛОЖЕНА ВНУТРИ СЕКТОРА')
ELSE
BEGIN
IF (X<=0) AND (Y>=0)
THEN D:= SQRT(X*X + Y*Y)-R;
IF (X<=-R) AND (Y<0)
THEN D:= SQRT(SQR(X + R)+Y*Y);
IF (X<=0) AND (X>=-R) AND (Y<=0)
THEN D:= ABS(Y);
IF (X>=0) AND (Y<=0)
THEN D:= SQRT(X*X + Y*Y);
IF (X>=0) AND (Y<=R) AND (Y>=0)
THEN D:= X;
IF (X>=0) AND (Y>=R)
THEN D:= SQRT(X*X + SQR(Y-R))
END;
WRITELN('PACCTOMHHE ДО КОНТУРА СЕКТОРА D=', D:5:2)
END.
Оператор варианта CASE
Иногда его называют также оператором выбора. Это оператор CASE, который является обобщением оператора IF и позволяет сделать выбор из произвольного числа имеющихся вариантов. Формат оператора варианта:
CASE <Выражение-селектор> OF
< Список 1>: <Оператор 1 >;
<Список 2>: <Оператор 2 >;
…
<Список N>: <Оператор N >
[ ELSE <Оператор N+1> ];
END;
В этой конструкции < Выражение селектор > может быть любого перечисляемого типа: стандартного (INTEGER, BOOLEAN, CHAR и т.д.) или пользовательского. < Список i > представляет собой подмножество значений, разделенных через запятую, выражения-селектора при которых следует выполнить < оператор i >. Оператор ELSE может отсутствовать. Если выражение-селектор принимает значение, которое не входит ни в один из списков 1,2,N, то в этом случае выполняется оператор N+1, стоящий за ELSE. Когда оператор ELSE отсутствует, вместо оператора N+1 выполняется пустой оператор. Далее приведен алгоритм оператора CASE... OF:
Вариант, помеченный словом ' Иначе ', соответствует ветке ELSE оператора CASE. Если ELSE отсутствует, то в блок-схеме нет этой ветви. Оператор CASE... OF работает следующим образом:
• Вычисляется значение выражения селектора – G.
• Значение G сравнивается с множеством значений, представленных в списке 1. Если в списке есть такое значение, то выполняется оператор 1.
• Если в списке 1 нет значения G, то проверяется список 2. Если найдено в списке 2 значение G, то выполняется оператор 2 и т.д.
• Если значение G не найдено ни в одном из списков с номерами 1, 2, 3,..., N, то выполняется оператор N + 1.
• Если в операторе CASE нет ветки ELSE и значение G не найдено ни в одном из списков 1, 2, 3,..., N, то выполняется пустой оператор.
Пример 12. Составить программу для вычисления площади одной из пяти геометрических фигур (прямоугольника, треугольника, трапеции, круга и сектора).
PROGRAM PR12;
VAR
S, А, В, Н, R, FI: REAL; N: INTEGER;
BEGIN
WRITELN('l - прямоугольник');
WRITELN('2 — треугольник');
WRITELN('3 - трапеция');
WRITELN('4 - круг');
WRITELN('5 - сектор');
READLN(N);
S:=0;
CASE N OF
1: BEGIN
WRITELN('Введите стороны - А, В');
READ(A, В);
S:= A*B;
END;
2: BEGIN
WRITELN('Введите основание и высоту - А, Н');
READ(A, Н);
S:=A*H/2;
END;
3: BEGIN
WRITELN('Введите основания и высоту - А, В, Н');
READ(A, В, Н);
S:= (А + В)*Н/2;
END;
4: BEGIN
WRITELN('Введите радиус – R');
READ(R);
S:= PI*R*R;
END;
5: BEGIN
WRITELN('Введите радиус и угол, град - R, FI');
READ(R, FI);
S:=PI*R*R*FI/360;
END;
END; {CASE}
WRITELN(фигуры = ', S:8:2)
END.
В этой программе оператор CASE используется для организации простейшего меню для выбора фигуры по предлагаемому номеру из списка номеров. Оператор указывает номер фигуры, и управление передается соответствующей ветви вычислительного процесса.
Пример 13. Для заданного целого положительного K и значения вещественного числа X вычислить Y = F(X) по формуле:
PROGRAM PR13;
VAR X, Y: REAL; К: INTEGER;
BEGIN WRITELN('Введите X и К');
READLN(X, K);
CASE К OF
2, 3: Y:= EXP(K *LN(X)) + X + 1; { Список 1}
4.. 6: Y:= 1/ABS(X+1); {Список 2}
ELSE Y:= SQRT(ABS(X +K))+SQRT(ABS(X-K)) { В противном случае}
END; { CASE}
WRITELN('Y = ',Y:5:1)
END.
В примерах 12, и 13 не следует путать метки — значения выражения селектора CASE с метками, используемыми оператором GOTO. Попытка войти в метку оператора CASE оператором безусловного перехода приведет к ошибке.
2.3. Программирование циклов
Цикл — это последовательность операторов, которая может выполняться более одного раза. В языке Паскаль разработано три механизма для конструирования циклов, использующих операторы FOR, WHILE, REPEAT.
Оператор безусловного перехода
Иногда его называют просто оператором перехода. Он имеет вид GOTO < Метка >, где метка это идентификатор, описанный в разделе LABEL. Метка ставится перед оператором, на выполнение которого нужно передать управление и отделяется от него двоеточием. Использование оператора GOTO в Паскале сильно ограничено и не рекомендуется. Так, нельзя входить извне в такие сложные операторы как IF, CASE, FOR, WHILE, REPEAT, BEGIN... END, процедуры, функции и другие, хотя транслятор может и не обнаружить ошибки. Переходы рекомендуется осуществлять внутри одного уровня или при выходе на более высокий уровень.
Областью действия метки является тот блок, где она описана, и переходы по этой метке возможны только в этом блоке. С помощью операторов IF и GOTO можно организовать циклический процесс. Поскольку операторы в теле программы выполняются последовательно друг за другом, то необходимо один из операторов пометить меткой, а затем с помощью оператора GOTO повторно вернуться на выполнение помеченного оператора. Чтобы этот возврат был управляемым, то есть для избегания бесконечных циклов, необходим анализ определенных условий, именно для этого и нужен условный оператор IF.
Пример 14. Вычислить:
.
Вычисления закончить при выполнении условия | Y - 0,5 |< EPS.
Алгоритм программы, в которой предполагается использование операторов безусловного перехода GOTO, с помощью структурограмм представить невозможно. Для графического
отображения таких программ используют только блок-схемы. В блок-схеме оператору GOTO < метка > соответствует графический объект - стрелка. Эта стрелка передает управление блоку, который помечен в верхнем левом углу меткой. В нашем случае идентификатором метки является цифра 1.
Циклический алгоритм программы приведен на рисунке 8. На рисунке 8 видно, что блок 1 повторяется до тех пор, пока условие имеет значение TRUE. Как только условие станет равным FALSE, искомая величина Y и номер текущей итерации I будут выведены на экран монитора.
PROGRAM PR14;
LABEL 1;
VAR
Y, EPS: REAL;
I: INTEGER;
BEGIN
WRITELN(,BBEДИTE EPS');
READLN(EPS);
Y:= 0;
I:= 0;
1: I:=I + 1;
Y:=Y + 1/(2*I- 1)/(2*I+ 1);
IF ABS(Y - 0.5) >= EPS THEN GOTO 1;
WRITELN('I = ', I,', Y = ', Y:6:4)
END.
Следует отметить, что организация циклов с помощью операторов GOTO не рекомендуется. Причина кроется в том, что именно использование этого оператора приводит к основной доле ошибок, которые допускает программист. Но эти ошибки, к тому же, самые трудные в диагностике и отладке программы. Именно для борьбы с этими ошибками использовали такую трудоемкую процедуру, как трассировка программы. Для борьбы с использованием оператора GOTO идеологами структурного программирования были предложены так называемые структурированные операторы циклов FOR, WHILE и REPEAT.
Циклы с параметром. Оператор FOR
Эти циклы организуются в программах, где заранее известно число повторений. При этом повторное выполнение сопровождается изменением управляющего параметра (переменной цикла).
FOR < Идентификатор параметра цикла >:= < Выражение 1 >
{ТО | DOWNTO} <Выражение 2> DO <Оператор>;
< Выражение 1 > определяет первое значение параметра, а < Выражение 2 > задает последнее значение параметра цикла. Параметр цикла, первое и последнее значения могут быть только одного любого перечисляемого типа. Напомним, что вещественный тип к перечисляемым типам не относится. < Выражение 1 > и < Выражение 2 > вычисляются один раз при вхождении в цикл и не могут изменяться внутри цикла. Служебное слово ТО означает выбор следующего значения параметра. Для множества целых чисел выбор следующего значения тождественен увеличению параметра на единицу (функция SUCC (s)). Служебное слово DOWNTO означает выбор предыдущего значения параметра, что для целых чисел адекватно сложению с -1 (функция PRED (s)). Служебное слово DO распространяется только на один оператор (тело цикла), следующий за ним, поэтому в качестве этого оператора часто используется составной оператор. Для пояснения алгоритма работы оператора FOR (рисунок 9), примем обозначения: I — идентификатор параметра цикла; М — значение выражения 1; N — значение выражения 2.
Итерационные циклы
Если число повторений заранее не известно и решение о завершении цикла
принимается на основе анализа некоторого условия, то такой повторяющийся вычислительный процесс называется итерационным циклом.
В Паскале для организации итерационных циклов предусмотрено две алгоритмические структуры. Первая структура называется «цикл с предусловием» и использует оператор WHILE... DO (рисунок 10. а). Вторая структура носит название «цикл с постусловием» и реализуется оператором REPEAT... UNTIL (рисунок 10. б).
Цикл с предусловием. Оператор WHILE ... DO
Синтаксическая структура оператора цикла с предусловием имеет вид:
WHILE < Логическое выражение, или переменная > DO < Оператор >;
Как видно из блок-схемы (рисунок 10.а), перед каждым выполнением цикла анализируется логическое выражение или переменная. При значении TRUE выполняется оператор, составляющий тело цикла. При значении FALSE управление передается следующему за циклом оператору. Если условие ложно с самого начала, то оператор не выполняется ни разу.
Цикл с постусловием. Оператор REPEAT... UNTIL
Недостатком оператора WHILE является то, что в цикле можно выполнить только один оператор, поэтому приходится в большинстве случаев использовать операторные скобки BEGIN...END. Этого недостатка лишен оператор цикла с постусловием (иногда его называют оператором «повтора», рисунок 10. б), имеющим следующий вид:
REPEAT
<Оператор 1>;
<Оператор 2>;
…
< Оператор К>
UNTIL <Условие>;
Ключевые слова REPEAT и UNTIL этого оператора играют роль операторных
скобок BEGIN... END. Поэтому эта конструкция тоже один оператор.
Break, Continue
В циклах FOR, REPEAT, WHILE можно использовать процедуры BREAK и CONTINUE. Первая процедура позволяет досрочно выйти из цикла, не дожидаясь выполнения условий выхода. Вторая процедура позволяет начать новую итерацию цикла даже в том случае, если предыдущая итерация не завершена. Использование этих процедур ускоряет работу программы в рамках принципа структурного программирования.