- •Часть V. Проектирование программ в o Pascal.
- •19. Составные типы данных в o Pascal.
- •19.1. Массивы.
- •Design Part 1
- •19.1.1. Синтаксис и семантика для массивов.
- •19.1.2. Параметры-массивы.
- •19.2. Реализация абстрактных типов данных с помощью массивов.
- •19.2.1. Текстовые файлы ограниченного размера.
- •19.2.1. Стек ограниченного размера.
19.1.2. Параметры-массивы.
Целые массивы компонентов могут появляться как фактические параметры в программах. Как и другие составные типы Паскаля, массивы обычно передаются по ссылке как параметры-переменные по соображениям эффективности. Если массив передается как параметр-значение, неявно присутствующая операция копирования должна будет скопировать каждый компонент. Однако, компоненты массивов могут эффективно связываться как с параметрами-значениями так и с параметрами-переменными. Определения раздела 9.1.4 не адекватны для случая алиасинга между индексным идентификатором и компонентом массива с таким индексом, переданным в параметре-значении.
Следующая программа обозначает некоторые сложности, которые могут возникнуть. Index передается параметру First, а Arr[Index] передается параметру Second. Таким образом, возникает алиасинг Second (через индекс Index) к First. First (или Index) инкрементируется до использования Second (или Arr[Index]). Однако, именно значение Arr[2], а не Arr[3] будет изменено, потому что связывание имени фактического параметра с именем формального параметра происходит при вызове процедуры, а не когда параметр-переменная используется.
PROGRAM Bind(INPUT, OUTPUT);
VAR
Arr: ARRAY [1..5] OF INTEGER;
Index: INTEGER;
PROCEDURE IncreaseParams(VAR First, Second: INTEGER);
BEGIN {IncreaseParams}
First := First + 1;
Second := Second + 1;
END; {IncreaseParams}
BEGIN {Bind}
FOR Index := 1 TO 5
DO
BEGIN
Arr[Index] := 1
END
Index := 2;
IncreaseParams(Index, Arr[Index]);
WRITELN(‘Index is’, Index:2);
FOR Index := 1 TO 5
DO
BEGIN
WRITELN(‘Arr[‘, Index:1, ‘] is ‘, Arr[Index] :2)
END
END. {Bind}
Выполнение:
OUTPUT: Index is 3
Arr[1] is 1
Arr[2] is 2
Arr[3] is 1
Arr[4] is 1
Arr[5] is 1
В этом особом случае, когда индекс в массиве и компонент с таким же индексом переданы как параметры-переменные, фактический параметр скопированный в тело процедуры должен иметь его индекс вычисленный в состоянии вызова, а не последующее состояние вычисленное в теле процедуры.
19.2. Реализация абстрактных типов данных с помощью массивов.
Абстракции данных, где конкретные объекты могут быть фиксированного размера, может быть эффективно реализована с использованием массивов.
Типа данных массив реализует конечные списки с эффективным произвольным доступом к любому элементу. Файловый тип данных позволяет доступ к любому элементу, но только в последовательном порядке. Если требуемый элемент не находится в голове списка будущего файла, потребуется много операций READ, чтобы его считать.
19.2.1. Текстовые файлы ограниченного размера.
19.2.1. Стек ограниченного размера.
Стек ограниченного размера может быть реализован с помощью массива и целочисленного индекса. Индекс равен нулю, если стек пуст, иначе он является указателе на верхний элемент в стеке, оставшиеся размещаются в позициях с меньшими индексами до позиции с индексом 1. Поскольку количество компонентов массива ограничено, только ограниченное количество элементов может быть помещено в стек реализованный таким способом.
В следующем примере первые Depth входных символов реверсируются помещением их значений в стек, затем распечатываются после извлечения их из стека.
PROGRAM Reverse(INPUT, OUTPUT);
{Выводит первые Depth символов в INPUT в обратном порядке}
CONST
Depth = 20;
TYPE
EltType = CHAR;
Stack = RECORD
Val: ARRAY [1..Depth] OF EltType;
StackTop: 0..Depth
END;
VAR
S: Stack;
Elt: EltType;
PROCEDURE NewStack(VAR S: Stack);
{S := <>}
BEGIN {NewStack}
S.StackTop := 0;
END; {NewStack}
PROCEDURE Push(VAR S: Stack, E: EltType);
{S := S & <E>}
BEGIN {Push}
IF S.StackTop >= Depth
THEN
WRITELN(‘** OVERFLOW **’)
ELSE
BEGIN
S.StackTop := S.StackTop + 1;
S.Val[S.StackTop] := E
END
END; {Push}
PROCEDURE Pop(VAR S:Stack);
{Существуют Stack X, EltType E, такие что
S = X & <E> --> S := X}
BEGIN {Pop}
IF S.StackTop <= 0
THEN
WRITELN(‘** UNDERFLOW **’)
ELSE
S.StackTop := S.StackTop - 1
END; {Pop}
Function Top(VAR S: Stack);
{Существуют Stack X, EltType E, такие что
S = X & <E> --> Top := E}
BEGIN {Top}
IF S.StackTop <= 0
THEN
BEGIN
WRITELN(‘** READING EMPTY STACK **’);
Top := 0;
END
ELSE
Top := S.Val[S.StackTop]
END; {Top}
FUNCTION Empty(VAR S: Stack): BOOLEAN;
{Empty := (S = <>)}
BEGIN {Empty}
Empty := S.StackTop <= 0
END; {Empty}
FUNCTION Full(VAR S: Stack): BOOLEAN;
{Full := (Length(S) = Depth)}
BEGIN {Full}
Full := S.StackTop >= Depth
END; {Full}
BEGIN {Reverse}
NewStack(S);
WHILE NOT EOF AND NOT Full(S)
DO
BEGIN
Read(Elt);
Push(S, Elt);
END;
WHILE NOT Empty(S)
DO
BEGIN
WRITE(Top(S));
Pop(S)
END;
WRITELN
END. {Reverse}
Выполнение:
INPUT: abcdefghijklmnopqrstuvwxyz
OUTPUT: zyxwvutsrqponmlkjihgfedcba
