- •17. Проектирование последовательного потока управления.
- •17.1. Оператор case.
- •17.1.1. Примеры операторов case.
- •13.1. Определение оператора case.
- •17.2. Оператор for.
- •17.2.1. Примеры для оператора for.
- •17.2.2. Определения для оператора for.
- •17.2.3. Псевдографика.
- •17.2.4. Анализ для операторов for.
- •17.3. Оператор repeat.
- •17.4. Заключение.
17.1.1. Примеры операторов case.
Операторы CASE особенно полезны с перечислимыми типами. Процедура WriteMonth записывает строковое хначение, соотвествующее значению перечислимого типа Month.
PROCEDURE WriteMonth(VAR Fout: TEXT; Mo: Month);
{Fout.3=W and Mo<>NoMonth -->
записываем три символа соответствущих значению Mo в Fout.1}
BEGIN {WriteMonth}
CASE Mo OF
Jan: WRITE(Fout, ‘Jan’);
Feb: WRITE(Fout, ‘Feb’);
Mar: WRITE(Fout, ‘Mar’);
Apr: WRITE(Fout, ‘Apr’);
May: WRITE(Fout, ‘May’);
Jun: WRITE(Fout, ‘Jun’);
Jul: WRITE(Fout, ‘Jul’);
Aug: WRITE(Fout, ‘Aug’);
Sep: WRITE(Fout, ‘Sep’);
Oct: WRITE(Fout, ‘Oct’);
Nov: WRITE(Fout, ‘Nov’);
Dec: WRITE(Fout, ‘Dec’);
END;
END; {WriteMonth}
WriteMonth пердполагает, что Mo было присвоено одно из константных значений типа Month и явно исключает из своей области определения NoMonth. Более robust версия WriteMonth может проверять, что Mo имеет одно из двенадцати значений типа Month перед выполнением оператора CASE.
IF Mo IN [Jan .. Dec]
THEN
CASE Mo OF
Jan: WRITE(Fout, ‘Jan’);
Feb: WRITE(Fout, ‘Feb’);
Mar: WRITE(Fout, ‘Mar’);
Apr: WRITE(Fout, ‘Apr’);
May: WRITE(Fout, ‘May’);
Jun: WRITE(Fout, ‘Jun’);
Jul: WRITE(Fout, ‘Jul’);
Aug: WRITE(Fout, ‘Aug’);
Sep: WRITE(Fout, ‘Sep’);
Oct: WRITE(Fout, ‘Oct’);
Nov: WRITE(Fout, ‘Nov’);
Dec: WRITE(Fout, ‘Dec’);
END;
Защищая оператор CASE таким способом, программист может быть уверен, что он всегда (на всех Паскаль-машинах) будет выполняться корректно.
Операторы CASE также полезны при работе с типами данных, содержащими много значений, если одрабатываются небольшие наборы возможных вариантов. Например, процедура, которая считывает символы и выполняет специальные действия для некоторых символов, может быть написана с использованием следующего шаблона.
WHILE NOT EOF
DO
BEGIN
READ(Ch);
IF Ch IN [‘+’, ‘-‘, ‘*’, ‘/’]
THEN
CASE Ch OF
‘+’, ‘-‘:
BEGIN
WRITELN(‘Обнаружен аддитивный оператор’);
CASE Ch OF
‘+’: NumPlus := NumPlus + 1;
‘-‘: NumMinus := NumMinus + 1
END
END;
‘*’, ‘/‘: WRITELN(‘Обнаружен мультипликативный оператор’);
END
ELSE
NumOther := NumOther + 1;
END
Обратите внимание на вложенный оператор CASE в котором действия группируются и вновь разбиваются. Похожим образом несколько вариантов неограниченного типа могут быть удобно обработаны:
IF AnswerCount <= 1
THEN
CASE AnswerCount OF
0: WRITE(‘There are none.’);
1: WRITE(‘There is 1.’);
END
ELSE
WRITE(‘There are ’, AnswerCount:3)
13.1. Определение оператора case.
Синтаксические правила для оператора CASE представлены ниже
<оператор CASE> ::= CASE <выражение> OF <список вариантов> END
<список вариантов>::= <список вариантов>, <вариант> | <вариант>
<вариант> ::= <список констант> : <выражение>
<список констант> ::= <список констант>, <константа> | <константа>
Для оператора CASE, как и для оператора IF может быть определено значение как объединение функций.
Пусть E будет выражение возвращающее значение порядкового типа, и C1, C2, C3 не равные друг другу константы того же типа и S1, S2 – операторы. Тогда оператор CASE S:
CASE E OF
C1, C2: S1;
C3: S2;
END
имеет значение:
S = {<u, S1(u)>: E(u) = C1(u) OR E(u) = C2(u)} {<u, S2(u)>: E(u) = C3(u) }
Обобщение до большего количества меток и операторов очевидно. Необходимо обратить внимание, что если ни один из вариантов не имеет значение E, функция S не определена.
