16837

Массивы указателей

Лекция

Информатика, кибернетика и программирование

6. Массивы указателей С помощью массивов указателей можно формировать большие массивы и коллекции массивов любых типов. Работа с большими массивами Размер одного массива данных должен быть не более 64 Кбайт. Но в реальных задачах могут использоваться массивы требую...

Русский

2013-06-26

1.37 MB

1 чел.

6. Массивы указателей

С помощью массивов указателей можно формировать большие  массивы и коллекции массивов любых типов.

Работа с большими массивами

Размер одного массива данных должен быть не более 64 Кбайт. Но в реальных задачах могут использоваться массивы, требующие ОП, большей, чем 64 Кбайт. Например, массив данных типа Real из 300 строк и 200 столбцов потребует для размещения 300 * 200 * 6 = 360000 байт = 357,56 Кбайт.

Для решения поставленной задачи можно использовать динамическое выделение ОП для каждой строки матрицы. Строка матрицы не должна превышать 64 Кбайт. В вышеприведенном примере ОП для строки составляет всего 1200 байт. Для выделения ОП из кучи каждая строка должна иметь указатель. Для всех строк надо объявить массив указателей, по одному для каждой строки. Затем каждой строке массива выделить ОП, присвоив каждому элементу массива указателей адрес начала размещения строки в ОП, и заполнить этот массив.

В листинге 23 представлена программа для работы с большим массивом целых значений: из 300 строк и 200 столбцов. Для размещения он требует: 200 * 300 * 2 = 120 000 байт. При формировании большого массива применяется А - массив указателей. В программе используются:

TMAS200 - - массива на 200 значений;

PTRMAS200 - имя типа - указателя на тип TMAS200;

TMASPTR - имя типа - массива на 300 указателей;

А - имя переменной типа TMASPTR; массив указателей статический;

I, J - переменные для перебора номеров строк и номеров столбцов массива.

Листинг 23. Формирование большого массива в основной программе. Используется статический массив указателей.

PROGRAM P36;

USES CRT;

TYPE { Имена типов: }

TMAS200 = ARRAY[1..200] OF INTEGER; { - массива на 200 значений }

PTRMAS200 = ^ТМА3200; { - указателя на массив }

TMASPTR=ARRAY[1..300] OF PTRMAS200; {-массива указателей}

VAR А : TMASPTR;{ - массив указателей на строки  }

I, J : INTEGER; {   двумерного массива данных    }

BEGIN  CLRSCR;

{ Запрос ОП для А[1]^ - I - строки большого массива: } FOR I := 1 ТО 300 DO NEW ( A[I] );

RANDOMIZE; { - запуск генератора случайных чисел }

FOR I := 1 ТО 300 DO

FOR J := 1 ТО 200 DO   BEGIN

A[I]^[J] := RANDOM (100); { - заполнение массива данными } WRITE(A[I]^[J]: 5); IF J MOD 10 = 0 THEN WRITELN;

END;

FOR I:=1 TO 300 DO DISPOSE(A[I]); {-освобождение ОП А[I]^} END.

Схематично  взаимосвязь указателей - элементов  массива А и  значений элементов динамического массива А представлена на рис. 11.

Рис. 11

Схема взаимосвязи элементов массива указателей и значений элементов большого массива А

В листинге 24 представлена программа для работы с большим массивом целых значений, аналогичная программе листинга 23. Но массив указателей в ней заполняется с помощью процедуры FORMUK.

Листинг 24. Формирование большого массива в процедуре. Используется статический массив указателей.

PROGRAM P38;

USES CRT;

CONST M = 300; N = 200;   { - количество строк и столбцов массива }

TYPE { Имена типов: }

TMAS200 = ARRAY[1..N] OF INTEGER;   { - массива на 200 значений }

PTRMAS200 = ^TMAS200; { - указателя на массив }

TMASPTR = ARRAY [1..M] OF PTRMAS200;    { - массива указателей. }

VAR     A : TMASPTR; { - массив указателей на строки }

M, N, I, J : INTEGER; {   двумерного массива данных }

{ ПРОЦЕДУРА ФОРМИРОВАНИЯ МАССИВА УКАЗАТЕЛЕЙ   }

PROCEDURE FORMUK ( VAR В : TMASPTR; M : INTEGER);

BEGIN   { Запрос ОП для В[I]^ - I - строки большого массива: }

FOR I := 1 TO M DO   NEW ( В[I]); END;

{ - - Основная программа  }

BEGIN  CLRSCR;

FORMUK ( A, M );     { - вызов процедуры выделения ОП } RANDOMIZE; FOR I := 1 TO M DO

FOR J := 1 TO  N DO   BEGIN

A[I]^[J]:=RANDOM(100); { - заполнение массива данными } WRITE (A[I]^[J]: 5); IF J MOD 10 = 0 THEN WRITELN;

END;

FOR I:=1 TO M DO DISPOSE(A[I]); { - освобождение ОП массива А[1]^ }

END.

Свободные массивы (коллекции массивов)

Свободный массив (коллекция одномерных массивов) - это двумерный массив (матрица), размер каждой из строк которого может быть различным. Коллекции массивов можно организовать с помощью массивов записей, каждая из которых содержит размеры экземпляра коллекции и указатель на начало массива.

Свободный массив или коллекция одномерных массивов может быть любого типа, в том числе integer, real, char, string и записей. Представим его как двумерный массив, в котором количество строк задается в процессе выполнения программы, а длины его строк могут быть различными. Для работы со свободными, так же как и для работы с большими, массивами используются массивы указателей. Каждый элемент массива указателей содержит адрес начала строки значений свободного массива, т. е. одномерного массива из коллекции массивов. ОП выделяется для каждой строки свободного массива (для каждого массива коллекции) динамически с помощью процедуры GetMem и освобождается процедурой FreeMem. Объем ОП, выделенной каждому массиву коллекции, определяется в процессе выполнения программы. Для того чтобы выделить и освободить ОП, надо определить количество элементов в строке, например ввести его из файла с исходными данными или получить его значение в режиме диалога с пользователем.

Для свободных арифметических массивов в первом элементе каждой строки свободного массива можно хранить jk - число, равное количеству элементов данной строки.

Рис. 12

Схематичное представление свободного массива целых значений

Пример свободного массива целых чисел приведен на рис. 12.

В массиве, представленном на рис. 12, три строки; в первом столбце каждой строки стоит количество элементов данной строки. Далее - значения элементов строки матрицы.

Массив указателей на арифметические данные

В листинге 25 приведена программа и исходные данные для ввода в свободный массив данных типа BYTE. В программе используется массив указателей на данные IK строк массива. Из первой строки файла исходных данных вводится IK. В каждой из последующих строк в первом столбце расположено количество элементов данной строки, а затем - значения её элементов, т. е. очередного одномерного массива коллекции массивов. Первыми значениями строк файла являются:

IK = 3 - количество строк динамического массива;

JK = 2 - количество столбцов в 1-й строке;

JK = 3 - количество столбцов   во 2-й;

JK = 1 - количество столбцов в 3-й строке.

Листинг 25. Формирование свободного массива данных типа BYTE. Используется статический массив указателей.

TYPE {   Имена  типов:    }

ТМВ = ARRAY [1..20] OF BYTE;{- массива на 20 значений}

РМВ = ^МВ; {-  указателя  на массив }

TMUK = ARRAY [1..10] OF РМВ;{- массива указателей}

VAR

MUK:TMUK;  {Переменная - указатель на статический массив из 10 указателей:}

I,J,IK,JK : INTEGER;

BEGIN

ASSIGN (INPUT,'MASUKAZ.DAT'); RESET (INPUT);

READLN (IK);{-   ввод  количества   строк   }

WRITELN ('КОЛИЧЕСТВО  СТРОК  МАТРИЦЫ = ',  IK);

FOR  I:= 1 TO IK DO

BEGIN

READ (JK ); {- ввод количества столбцов I-строки }

WRITELN ('КОЛИЧЕСТВО ЗНАЧЕНИЙ В',I,'-СТРОКЕ= ',JK);

{Запрос ОП для MUK[I]^ - JK+1 значения I-строки: } GETMEM (MUK[I],(JK+1)*SIZEOF(BYTE));

MUK[I]^[1] := JK; {- запоминание JK I-строки } WRITELN  ('ВВОДИТСЯ   ',    I,    '-   СТРОКА');

FOR   J:=2   TO  JK + 1   DO

BEGIN READ (MUK[I]^[J]); WRITE(MUK[I]^[J]:4); END; WRITELN;

END; CLOSE(INPUT);

{Освобождение ОП MUK[I]^ - I-строки свободного массива  данных:}

FOR I:=1 TO IK DO FREEMEM(MUK[I],(МиК[1]^[1]+1));

END.

Исходные данные для ввода в свободный массив:

3 -   количество   строк массива;

234

3456

18

В программе листинга 25 используются:

1) имена типов:

ТМВ - одномерного массива на 20 элементов типа BYTE; РМВ - указателя на одномерный массив из 20 элементов; TMUK - массива указателей на тип РМВ;

2) переменные:

MUK - массив указателей на одномерные массивы данных; массив указателей - статический;

I, J - номера строк и столбцов свободного массива; IK, JK -s количество строк и столбцов свободного массива.

Для статического массива MUK отводится ОП для 10 указателей на значения типа BYTE, по одному указателю на каждую из 10 строк свободного массива, т. е. он может содержать не более 10 одномерных массивов, каждый из которых может содержать не более 20 значений (объявлено). После определения JK - количества элементов I-строки - с помощью процедуры GetMem им выделяется ОП и формируется значение MUK[I] - указателя, который адресует область ОП на (JK+1) значение. Только после этого вводятся значения элементов I-строки свободного массива.

Схематично взаимосвязь указателей и значений элементов свободного массива программы листинга 25 представлена на рис. 13.

Рис. 13

Схема взаимосвязи массива указателей и значений элементов свободного массива MUK

На рис. 13 свободный арифметический массив представлен в виде ряда строк. Реально ОП - это линейная последовательность перенумерованных байт. Поэтому значения элементов строк массива могут быть расположены подряд или отрезками ОП, выделенной для них. Упрощенная схема размещения элементов массива дана на рис. 14.

Рис. 14

Упрошенная схема размещения отрезков ОП для размещения элементов свободного массива

На рис. 15 представлена схема взаимосвязи указателей, адресов и значений свободного массива, сформированного с помощью MUK массива указателей программы листинга 25.

Рис. 15Схема взаимосвязи указателей, адресов и значений свободного массива арифметических данных. Массив указателей статический

В листинге 26 приведена программа для формирования свободного массива данных типа BYTE. В программе используется динамический массив данных и динамический массив указателей: ОП для массива данных и для массива указателей выделяется с помощью процедуры GetMem. Исходные данные и действия программы листинга 26 аналогичны действиям программы листинга 25. В программе листинга 26 используются:

ТМВ, РМВ, TMUK, I, J, IK, JK - того же назначения, что и в программе листинга 25;

PTMUK - тип указателя на данные типа TMUK;

PMUK - переменная типа PTMUK, указатель на динамический массив указателей.

На рис. 16 представлена схема взаимосвязи указателя на массив указателей, массива указателей и значений элементов свободного массива арифметических данных программы листинга 26.

Рис. 16

Схема взаимосвязи указателей и значений сформированного динамического свободного массива арифметических данных. Используется динамический массив указателей,

т. е. указатель на массив указателей

Листинг 26. Формирование свободного массива данных типа BYTE. Используется динамический массив указателей

TYPE {   Имена  типов:   }

ТМВ = ARRAY [1..20] OF  BYTE;{- арифметический  массив}

РМВ  = ^МВ; {-указатель на арифметический массив}

TMUK = ARRAY[1..10] OF РМВ; {- массив из 10 указателей}

PTMUK = ^ТМUК; {- указатель на массив из 10 указателей}

VAR {Переменная - указатель на динамический массив указателей: }

PMUK : PTMUK;I,J,IK,JK : INTEGER;

BEGIN

ASSIGN (INPUT,'MASUKAZ.DAT'); RESET (INPUT);

READLN (IK);{   -   ввод  количества   строк   }

WRITELN ('КОЛИЧЕСТВО  СТРОК МАТРИЦЫ  =   ',    IK);

{Запрос ОП для PMUK^ - массива из IK указателей на тип  РМВ:}

GETMEM (PMUK, IK * SIZEOF(PMB));

FOR I := 1 TO IK DO

BEGIN READ(JK); { - ввод количества столбцов I-строки } WRITELN ('КОЛИЧЕСТВО ЗНАЧЕНИЙ В', I, '- СТРОКЕ = ',JK); { Запрос ОП для РМUК^[I]^ - JK+1 значения I-строки: } GETMEM ( PMUK^[I],   (JK+1) * SIZEOF(BYTE) );

РМUK^[I]^[1] := JK; { запоминание значения JK } WRITELN ('ВВОДИТСЯ ',I, ' - СТРОКА ');

FOR J := 2 ТО JK+1 DO

BEGIN READ  (РМUK^[I]^[J]); { - ввод элемента I-строки J-столбца }

WRITE (PMUK^[I]^[J]:4); { - вывод I,J - элемента }

END ;  WRITELN;

END;  CLOSE (INPUT);

{ Освобождение ОП РМUK^[I]^ - I-строки свободного массива данных: }

FOR I:=1 ТО IK DO FREEMEM (PMUK^[I],(PMUK^[I]^[1]+1));

{Освобождение ОП РМUK^ - динамического массива указателей: }

FREEMEM ( PMUK, IK * SIZEOF(РМВ));

END.

В связи с тем что арифметические одномерные динамические массивы с выражениями для определения индекса можно использовать для представления массивов любой размерности, с помощью рассмотренных массивов указателей можно формировать и использовать коллекции массивов любой размерности.

Массив указателей на строки

В листинге 27 приведена программа формирования MUK - свободного массива строк (строк разной длины), количество элементов которого должно быть не более 10. В программе используются:

PSTR - имя типа - указателя на данные типа STRING;

TMUK - имя типа - массива указателей типа PSTR;

MUK - переменная типа TMUK, массив указателей на строки; массив указателей - статический;

К - количество строк, которые будут введены;

I, J - номер вводимой строки и символа в строке.

ОП для нулевого элемента строки выделяется автоматически.

Листинг 27. Формирование свободного массива строк. Используется статический массив указателей.

TYPE { Имена типов: }

PSTR = -^STRING; { - указателя на тип STRING }

TMUK = ARRAY[1..10] OF PSTR;  { - массива из 10 указателей }

VAR MUK : TMUK;   { - переменная - статический массив указателей }

I, J, К : INTEGER;

STROKA:STRING; {-рабочая переменная для ввода строки } BEGIN

ASSIGN ( INPUT,  'MASUKSTR.DAT'); RESET (INPUT);

READLN ( К ); { - ввод количества строк }

WRITELN (#10#13, 'КОЛИЧЕСТВО СТРОК = ', К);

FOR I := 1 ТО К DO

BEGIN READLN (STROKA); { - ввод очередной строки }

{ Запрос  ОП  для MUK[I]^ - I  - строки:   }

GETMEM   (  MUK[I],  LENGTH (STROKA) );

MUK [I]^ := STROKA; {-  формирование I-строки   }

WRITE (MUK[I]^);{   -   вывод   1-строки   }

WRITE   ( '   Посимвольно:  ');

FOR J:=1 ТО LENGTH (MUK[I]^) DO WRITE (MUK[I]^[J]);
WRITELN;
END; CLOSE   (INPUT);

{  Освобождение  ОП MUK[I]^   -   1-строки:}

FOR I:=1 TO К DO FREEMEM (MUK[I],LENGTH(MUK[I]^));

END.

Пример исходных данных для ввода:

3

AAAAAAAAA

BBBBB

CCCCCCCCCCCCCC

На рис.17 представлена схема взаимосвязи указателей и значений динамического массива, сформированного с помощью MUK – массива указателей на строки программы листинга 27.

Рис. 17

Схема взаимосвязи указателей и значений свободного массива строк. Используется статический массив указателей

В листинге 28 приведена программа для формирования свободного массива строк. В программе используется динамический массив строк и динамический массив указателей, ОП для массива строк и для массива указателей выделяется с помощью процедуры GetMem.

На рис. 18 представлена схема взаимосвязи указателя на массив указателей, массива указателей и значений элементов свободного массива строк программы листинга 28.

Рис. 18

Схема взаимосвязи указателя на массив указателей, массива указателей и значений свободного массива строк. Используется динамический массив указателей

Листинг 28. Формирование свободного массива строк. Используется динамический массив указателей.

TYPE         { Имена  типов:  }

PSTR = ^STRING;  {- указателя  на  тип  STRING   }

TMUK = ARRAY[1 ..10] OF PSTR; { -  массива  указателей}

PTMUK = ^TMUK; { -  указателя  на массив  указателей   }

VAR PMUK : PTMUK;  { - переменная  -  указатель   на массив  указателей   }

I,J,К : INTEGER; { - номер строки, символа и  количество  строк }

STROKA : STRING; { - рабочая переменная для ввода троки}

BEGIN

ASSIGN ( INPUT, 'MASUKSTR.DAT'); RESET (INPUT);

READLN ( К ); { - ввод количества строк }

WRITELN (#10#13, 'КОЛИЧЕСТВО СТРОК = ', К);

{ Запрос ОП для массива РМUК^ - из К указателей: }

GETMEM ( PMUK, К * SIZEOF ( PSTR ));

FOR I := 1 ТО К DO  BEGIN

READLN  ( STROKA ); { - ввод очередной строки }

{ Запрос ОП для РМUK^[I]^ - I-строки: }

GETMEM ( РМUK^[I], LENGTH ( STROKA ) );

РМUK^[I]^ := STROKA; { - формирование I-строки }

WRITE ( PMUK^[I]^ ); { - вывод I-строки }

WRITE ( ' Посимвольно: ');

FOR J:=1 ТО LENGTH(РМUK^[I]^) DO WRITE (PMUK^[I]^[J] ); WRITELN;         END ;

CLOSE (INPUT) ;

{ Освобождение ОП РМUK^[I]^ - I-строки: }

FOR I:=1 TO К DO FREEMEM(PMUK^[I], LENGTH (РМUK^[I]^));

{Освобождение ОП РМUK^ - для массива из К указателей :}

FREEMEM ( PMUK, К * SIZEOF ( PSTR ));

END.

Массив указателей на записи

Коллекция записей представляет собой двумерный массив записей, в каждой строке которого расположено количество записей, заданное в массиве количества записей в строках. Массив указателей на записи и массив количеств могут быть статическими или динамическими.

Пример программы для формирования свободного массива записей дан на листинге 29. Для формирования коллекции записей используются статические массивы указателей на записи и количества записей в строках. В примере рассмотрено формирование свободного массива со сведениями о студентах. Количество групп, т. е. одномерных массивов записей, вводится в качестве исходных данных. Затем для каждой группы вводится количество ее студентов и сведения о них. Для каждой группы формируется одномерный массив заданного количества записей, т. е. студентов в группе.

В качестве исходных данных вводятся:

N =  2 - количество строк с массивами записей;

К[I] - количество записей в I-строке массива записей;

Z [ I ]^ [ J ] - значение J-записи I-строки.

В программе используются:

MSTRUC - тип - массив записей со сведениями о студентах;

PMSTRUC - тип - указатель на массив записей о студентах;

MUK - тип - массив указателей на массив записей;

N - переменная - количество строк (студенческих групп) с динамическими массивами записей;

Z - переменная - массив указателей на массивы записей;

К - массив количества записей в каждой строке массива записей;

I - номер строки свободного массива записей;

J - номер записи в I-строке свободного массива записей.

Листинг 29. Формирование свободного массива записей.

Используются статические массивы указателей на записи и количества записей в строке.

PROGRAM  LR6;  USES  CRT; {   Имена   типов: }

TYPE ST=ARRAY [1..7] OF STRING[55]; {- массива строк}

ST1     =   STRING[12];

STRUG  =  RECORD {  -  записи  в   составе: }

NZ   :   96100..96200; {        -  номер  зачетки, }

GR   :   STRING[6]; {        -  группа, }

FIO   :   ST1; {            фамилия, }

RS : REAL; {   - размер стипендии.}

END;

MSTRUC = ARRAY [1..10] OF STRUG; { - массива записей}

PMSTRUC = MSTRUC;  { - указателя на массив записей }

MUK = ARRAY[1..5] OF PMSTRUC; {- массива указателей }

CONST С : ST = (                { - шапка таблицы }

' СВЕДЕНИЯ О СТУДЕНТАХ ' ,

'    НОМЕР ! ГРУППА ! ФАМИЛИЯ,     | РАЗМЕР       ',

'  ЗАЧЕТНОЙ КНИЖКИ |      ! ИНИЦИАЛЫ | СТИПЕНДИИ   ',);

VAR Z MUK; { - массив указателей на массивы записей }

N INTEGER; { - количество строк с массивами записей }

К ARRAY[1..5] OF BYTE; {-количество записей в строках } I, J   1 ..60;

FI,FR:TEXT; {- текстовые файлы исходных данных и результатов }

В : CHAR;

{    Вывод одной строки таблицы   }

PROCEDURE P;

BEGIN

WRITELN (FR,'!',Z[I]^[J].NZ:10,'|':8,' ',Z[I]^[J],GR, '!':2,' ', Z[I]^[J].FIO,'!',Z[I]^[J].RS:9:2,'|':4 );

IF I = N THEN WRITELN ( FR, С[7] )

ELSE WRITELN ( FR, С[6] ) ; END;

{   Основная программа   }

BEGIN    CLRSCR;

ASSIGN (FI,'LR6MUK.DAT'); ASSIGN (FR,'LR6.RES');

RESET  (FI);  REWRITE ( FR );

FOR I:=1 TO 5 DO WRITELN (FR,C[I]); { - вывод шапки таблицы }

READLN ( FI, N ); { - ввод количества групп с массивами записей }

FOR I := 1 ТО N DO BEGIN

{Ввод и вывод количества записей в I-группе студентов:} READLN ( FI, К [I] );   WRITELN ('K[',I,']=', К[I]:5 ); { Запрос ОП для Z[I]^ - К[I] записей 1-строки: }

GETMEM ( Z[I],K[I] * SIZEOF (STRUC)); { Ввод и вывод записей I-строки: }

FOR J := 1 ТО K[I]   DO    WITH  Z[I]^[J]  DO BEGIN READLN ( FI, NZ, B, GR, B, FIO, RS );   P  END;

END;

CLOSE ( FI );      CLOSE (FR);

{ Освобождение ОП для Z[I]^ - К[I] записей 1-строки: } FOR I := 1 TO N DO  BEGIN

FREEMEM ( Z[I], К[I]*SIZEOF(STRUC));  Z[I] := NIL;

END 

END.

Исходные данные для свободного массива записей:

2   - количество студенческих групп с одномерными массивами записей

2 - количество студентов в 1-й группе, 1-м массиве записей

88103 ЭВМ1-1 ИВАНОВ И.И.   4000

88104 ЭВМ1-1 ИВНОВ И.И.    3000

3 - количество студентов во 2-й группе, 2-м массиве записей

88150 ЭВМ1-2 ПЕТРОВ П.П.   5000

88151 ЭВМ1-2 ПИТРОВ П.П.   2000
88200 ЭВМ1-3 СИДОРОВ С.С.  70.55

7. Указатели и подпрограммы

Переменная в Паскале может быть типа функции или процедуры. Механизм процедурных типов и указателей процедурных типов предоставляет программисту весьма широкие и удобные возможности при разработке программ. Идеи создания нового типа - объект были заложены при введении процедурных типов параметров и возможности использовать имя подпрограммы как одну из переменных программы.

Для работы с процедурами и функциями можно использовать типовые и бестиповые указатели. Вызов подпрограмм можно произвести, используя:

  1.  имя подпрограммы;
  2.  переменную типа подпрограммы;
  3.  типовый или бестиповый указатель на подпрограмму.

Вызов подпрограмм с помощью скалярной переменной типа "имя полпрограммы"

Процедурный тип переменной - это тип, значениями которого могут быть имена конкретных процедур или функций. Определить тип процедурной переменной можно в разделе переменных или в разделе типов.

Форма объявления переменной типа процедуры или функции:

имя-переменной : имя-типа;

Значением переменной типа процедура или функция может быть имя конкретной процедуры или функции.

Для вызова различных подпрограмм с помощью одной и той же процедурной переменной надо ее объявить. Для использования этой переменной надо присвоить ей значение имени конкретной подпрограммы, процедуры или функции. Процедурные типы, совместимые по присваиванию, должны иметь одинаковые спецификации, определенные при объявлении процедурных переменных, т. е. одинаковое количество и совместимые типы соответствующих параметров. У функций должны совпадать также типы возвращаемых ими значений.

Простейший способ объявления переменной, значением которой может быть процедура:

Var P : procedure; { - переменная типа процедуры без параметров }

Примеры объявления функционального типа:

Type Func = Function ( х, у : integer ) : real;

FUN = Function:integer; {- тип функции без параметров }

Примеры объявления переменных типа функции:

Var F1,F2: Func; F : FUN; { - Func и FUN - имена типов } Var F3, F4 : Function ( a, b : real ) : real;

где     типы F3 и F4 определены при объявлении переменных.

Правила использования имен процедур и функций в качестве значений переменных типа процедуры и функции:

  1.  они должны компилироваться с директивой {$F+}, для этого можно перед
    текстом этих подпрограмм установить директиву {$
    F+}, а после их текста
    - директиву {$
    F-};

они не должны:

а) быть стандартной процедурой или функцией;

б) быть вложены в другие подпрограммы;

в) иметь спецификации interrupt и inline.

Рассмотрим использование скалярной переменной процедурного типа функции на примере программы с вызовами различных функций.

Пример. Вызвать последовательно функции PLUS, MINUS и MUL для вычисления суммы, разности и произведения параметров. Программа примера приведена в листинге 30. В ней используются:

имена функций: PLUS, MINUS, MUL;

TFUN - имя типа - функции, возвращающей значение типа REAL; функция имеет 2 параметра типа REAL;

VFUN - имя переменной типа TFUN;

PRINT - имя подпрограммы, которая использует глобальную переменную VFUN для вызова различных функций и вывода результатов их выполнения.

Листинг 30. Использование переменной процедурного типа для вызова различных функций.

TYPE TFUN = FUNCTION (X,Y:REAL):REAL;{- тип функции}

VAR VFUN:TFUN;{- глобальная  переменная  типа  TFUN}

{ или:  VAR VFUN:FUNCTION(X,Y:REAL):REAL;}

{Функции, имена которых присваиваются переменной VFUN:}

{$F+} {- или FAR; после заголовка каждой функции} FUNCTION   PLUS  (А, В : REAL) : REAL;

BEGIN PLUS:= A+ В        END;

FUNCTION  MINUS  (А,В : REAL) : REAL;

BEGIN  MINUS :=A - В  END;

FUNCTION  MUL  ( А,В : REAL)  : REAL;

BEGIN  MUL  := A * В  END;

{$F-}

{Процедура вызова функции с помощью глобальной переменной VFUN:  }

PROCEDURE PRINT  ( S :  STRING);

BEGIN   WRITELN ( S, VFUN(5,3) : 3 : 0 );     END;

{   Основная программа   }

BEGIN VFUN := PLUS;    PRINT (' A + В = ');

VFUN := MINUS;   PRINT (' A - В = ');

VFUN := MUL;     PRINT (' A * В = ');

{ Вызов функции с помощью переменной VFUN из списка данных WRITELN: }

WRITELN (' А * В = ', VFUN(4, 5) : 4:1); END.

Вызов подпрограмм с помощью типовых и бестиповых указателей

Пример программы с использованием имени функции, типового и бестипового указателя и преобразования его к определенному типу приведен в листинге 31. В программе используются:

FN - имя типа - функции с двумя параметрами типа INTEGER, возвращающей результат типа INTEGER;

PF1, PF2 - переменные типа FN;

ТР - типовый указатель на функцию;

Р - бестиповый указатель.

Листинг 31. Вызов функиии с помощью имени функции, типового и бестипового указателя.

USES  CRT;

TYPE FN = FUNCTION ( X, Y : INTEGER) : INTEGER;

VAR PF1,PF2:FN;{ - переменные типа FN - имя функции }

ТР : ^FN;{ - типовый указатель на функцию }

Р : POINTER; { - бестиповый указатель }

R : INTEGER;

{$F+} {Функции, имена которых присваиваются переменным типа FN:}

FUNCTION PLUS(X,Y:INTEGER):INTEGER; BEGIN PLUS:=X+Y END;

FUNCTION MINUS( X,Y: INTEGER) : INTEGER; BEGIN MINUS := X - Y END;

{$F-}

{  Основная программа  }

BEGIN   ClrScr;

{   Использование имени переменной типа функции:  }

R = PLUS (5,2); WRITELN (PLUS(5, 2)); { - вызов PLUS }

PFl  = PLUS;{ - PF1 присвоено значение PLUS }

R =PF1(5,2); WRITELN(PF1(5,2)); {-вызов PLUS через PF1}
PF2 = MINUS;{ - PF2 присвоено значение MINUS }

R=PF2(5,2); WRITELN(PF2(5,2)); {-вызов MINUS через PF2}
PF1 = PF2; { - пересылка значений переменных }

R=PF1(5,2); WRITELN(PF1(5,2)); {-вызов MINUS через PF1}

{   Использование ТР - типового указателя:   }

ТР := @MINUS;{ - ТР присвоено значение @MINUS }

{ТР преобразуется к типу FN для вызова функции MINUS: }

R:=FN(TP)(5,4); WRITELN(FN(TP)(5,4));{- вызов MINUS через ТР}
FN(TP):= PLUS;{- указателю ТР присвоено значение @PLUS}

R:=FN(TP)(5,3); WRITELN(FN(TP)(5,3)); {-вызов PLUS через ТР}
@
PF1 := ТР;{ - PF1 присвоено значение имени функции PLUS }

R  := PF1 (5,2);   WRITELN ( PF1(5, 2) );     { - вызов PLUS через PF1 }
TP.:= @PF2; { - ТР присвоен адрес значения PF2 = @MINUS }

R = FN(TP) (5,2); WRITELN ( FN(TP)(5,2) ); { - вызов MINUS через ТР}

FN(TP) := PF1; { - ТР присвоен адрес значения из PF1 = @PLUS }

R   = FN(TP) (5,1); WRITELN ( FN(TP) (5,1) ); { - вызов PLUS через ТР}

P  = ТР; {-пересылка указателей: Р присвоено значение указателя ТР}

R   = FN(P) (5,3);  WRITELN (FN(P)(5,3));    { - вызов PLUS через Р }

{   Использование Р - бестипового указателя:   }

Р  = @MINUS;  { - Р присвоено значение @MINUS }

R = FN(P)(5,3); WRITELN(FN(P)(5,3)); { - вызов MINUS через Р }

FN(P) := PLUS; {- указателю Р присвоено значение @PLUS }

R = FN(P)(5,2); WRITELN(FN(P)(5,2)); { - вызов PLUS через Р }

@PF1 :=Р; {- PF1 присвоено значение имени функции PLUS }

R = PF1(5,2); WRITELN(PF1(5,2)); {-вызов PLUS через PF1}

P = @PF2;{ - Р присвоен адрес из значения PF2 = @MINUS }

R = FN(P)(5,1); WRITELN( FN(P)(5,1) ); {- вызов MINUS через Р}

FN(P) := PF1; {-P присвоен адрес значения из PF1= @PLUS}

R  = FN(P)(1,2);  WRITELN ( FN(P)(1,2) );      { - вызов PLUS через Р }

ТР = Р; {-пересылка указателей: ТР присвоено значение указателя Р}

R   = FN(TP) (5,1); WRITELN (FN(TP)(5,1));  { - вызов PLUS через ТР}
END.

Из программы листинга 31 очевидна одинаковая форма вызова функций с помощью типовых и бестиповых указателей.

Если PLUS - имя конкретной функции, выражение @PLUS возвращает адрес функции PLUS. Если PF1 - имя процедурной переменной, @PF1 преобразует значение переменной PF1 в бестиповый указатель (pointer), содержащий адрес ее значения.

В окне просмотра оказываются идентичными значения:

PLUS = @PLUS; PF2 = @PF2.

В листинге 32 приведена программа для использования имен процедур в качестве значений скалярных процедурных переменных и их адресов в качестве значений типовых и бестиповых указателей.

Листинг 32. Вызов процедуры с помошью имени процедуры, типового и бестипового указателя.

USES CRT; {  Имена типов:  }

TYPE PR = PROCEDURE;    { - процедура без параметров }

PPR = ^РК; { - указатель на процедуру без параметров.}

VAR VP : PR; { - переменная типа имя процедуры }

РТ : PPR;        { - типовый указатель на процедуру }

ВР : POINTER;     { - бестиповый указатель }

I : INTEGER; {$F+}

PROCEDURE SOZ; BEGIN WRITELN ( 'СОЗДАНИЕ'); END; PROCEDURE DOP; BEGIN WRITELN ( 'ДОПОЛНЕНИЕ'); END; PROCEDURE CHT; BEGIN WRITELN ( 'ЧТЕНИЕ'); END; PROCEDURE KOR; BEGIN WRITELN ( 'КОРРЕКТИРОВКА'); END; {$F-}

BEGIN  CLRSCR;

{ Присвоить переменной VP имя процедуры SOZ: }

VP:=SOZ; VP;{- вызов процедуры SOZ с помощью скалярной VP}
{Указателю РТ присвоить значение адреса процедуры
DOP:}
РТ := @
DOP;  PR(PT);  { - преобразование к типу PR для вызова DOP }
{ Присвоить указателю РТ адрес процедуры СНТ: }
PR(PT) := CHT; PR(PT); { - вызов СНТ через РТ  }

{ Присвоить переменной VP значение имени процедуры по значению указателя в РТ: }

@VP  =  РТ;    VP; { - вызов СНТ через VP  }

{Присвоить указателю РТ адрес значения переменной VP: }

РТ  = @VP;  PR(PT); { - вызов СНТ через РТ  }

PR(PT)  =  VP;  PR(PT); { "      }

{ Пересылка значений указателей: из типового в бестиповый: }

ВР = РТ;   PR(BP); { - вызов СНТ через ВР  }

{ То же для бестипсвого указателя на процедуру: }

ВР  = @KOR; PR(BP); { - вызов процедуры KOR через ВР }

PR(BP) = СНТ; PR(BP); { - вызов процедуры СНТ через ВР }

@VP  =  ВР;     VP; { -    "      "      "    "   VP }

ВР   =  @VP; PR(BP); { - "      "    "   ВР }

PR(BP)  =   VP; PR(BP); { - "      "    "   ВР }

{ Пересылка значений указателей: из бестипового в типовый: }

РТ := ВР;   PR(PT); { - вызов процедуры СНТ через РТ }

END.

Правила использования указателей и подпрограмм.

При использовании имен переменных типа подпрограмма надо:

1) присвоить переменной типа подпрограмма значение имени конкретной
подпрограммы:

VP   :=  SOZ;   PF1   := PLUS;   PF1   :=  PF2; - тривиальным способом; @VP   := РТ;   @PF1   := ТР; - из значения указателя;

2) вызвать с ее помощью подпрограмму для выполнения:

а) процедуру: VP;;

б) функцию: R   := PF1(5,2);.

При использовании указателей для вызова подпрограмм надо:

1) присвоить указателю значение адреса конкретной подпрограммы:

а) без операции явного преобразования типа:
ТР   :=  @
PLUS;   Р   :=  @PF2; - для функции;
РТ   : =  @  
DOP;   РТ   : =  @VP; - для процедуры;

б) с помощью операции явного преобразования типа:
FN(TP)    :=   PLUS;   FN(P)    :=   PF2;- ДЛЯ функции;
PR(PT)   :=  СНТ;   PR(PT)   := VP   ; - для процедуры;

2) вызвать подпрограмму для выполнения с помощью указателя - с преобра
зованием к типу подпрограммы:

R   : = FN (ТР) ( 5 , 4) /   R   : = FN (Р) ( 5 ,4 ) ; - для функции; PR   (РТ) ;   PR(BP) ; - для процедуры.

При вызове подпрограмм с помощью указателей обязательно явное преобразование к типу вызываемой подпрограммы, независимо от того, типовые это или бестиповые указатели. Приведение (преобразование) типа не производит никаких операций над переменной, а просто позволяет трактовать переменную одного типа как переменную другого типа.

Чтобы получить адрес самой процедурной переменной, а не адрес подпрограммы, который в ней сохранен, надо дважды использовать операцию извлечения адреса @@. В соответствии с этим в окно Watch можно вывести:

VP - значение процедурной переменной, равное адресу ее значения;

@VP - результат преобразования значения переменной VP в бестиповый

указатель - адрес подпрограммы; значение VP = @VP; @@VP - физический адрес размещения в ОП процедурной переменной VP.

Процедурный тип возвращаемого значения подпрограммы

Результатом выполнения подпрограммы могут быть: имя подпрограммы и указатель на подпрограмму. С помощью параметров подпрограмм можно возвратить значение как имени подпрограммы так и указателя на подпрограмму. Результатом, возвращаемым функцией, может быть скалярное значение любого простого типа, в том числе указатель на данные любого типа. С помощью функции можно возвратить только указатель на подпрограмму; нельзя возвратить имя подпрограммы. В качестве параметра подпрограммы может быть скалярное имя подпрограммы, имя указателя на подпрограмму, массив имен и указателей на подпрограммы.

В листинге 33 приведена программа, подпрограммы которой возвращают значения имен подпрограмм и указатели на подпрограммы. Возвращаемые значения формируются из имен и адресов функций PLUS и MINUS.

Листинг 33. Подпрограммы, возвращающие результат - имя функции или указатель на функцию.

USES  CRT; {   Имена  типов:   }

TYPE TFUN =FUNCTION (X,Y:INTEGER):INTEGER; {-  имя  функции }
PTFUN  = ^TFUN; {   -  указатель   на  функцию   }

VAR  FUNV:TFUN;{ -  переменные  типа:   -      TFUN   }

VPF : PTFUN; {   -   PTFUN   }

{$F+}

FUNCTION  PLUS (А,В:INTEGER) : INTEGER;

BEGIN  PLUS:=A+В END;

FUNCTION  MINUS (А,В:INTEGER): INTEGER;

BEGIN  MINUS := A - В     END;

{$F-}

{      Процедура  возвращает имя функции:       }

PROCEDURE VZI (VAR F:TFUN; N:INTEGER);

BEGIN 

IF N = 1 THEN F := PLUS   { - формирование значения  

                                       возвращаемого }

ELSE F := MINUS; {   результата - имени функции } END;

{   Процедура возвращает указатель на функцию:  }

PROCEDURE VZP ( VAR F : PTFUN; N:INTEGER );

BEGIN    { Формирование результата - адреса функции: }

CASE  N OF  1: F := @PLUS;

    2: F := @MINUS;  END;

END;

{   Функция возвращает указатель на функцию:   }

FUNCTION FVZ ( N : INTEGER) : PTFUN;

BEGIN

IF N = 1 THEN FVZ := @PLUS

ELSE FVZ := @MINUS;

END;

{FUNCTION FVZP ( F: TFUN ) : TFUN; - нельзя ! }

{      - Основная программа   }

BEGIN CLRSCR;

{ Возврат из процедуры в переменную FUNV значения имени функции = PLUS: }

VZI ( FUNV,1 ); { Вызов PLUS с помощью FUNV: }

WRITELN ( ' FUNV(1,2) = ', FUNV(1,2) ); { Возврат из процедуры в VPF значения указателя - адреса функции PLUS: }

...

VZP ( VPF, I );

WRITELN (' TFUN (VPF) (2,3) = ', TFUN(VPF) (2,3) ) ;   { - вызов VPF }

{ Возврат из функции FVZ значения указателя - адреса функции MINUS: }

VPF := FVZ (2); { Вызов MINUS с помощью VPF: }

WRITELN (' TFUN(VPF) (8,4) = ', TFUN(VPF) (4,5));

END.

В листинге 34 приведена программа, подпрограммы которой также возвращают значения имен подпрограмм и указатели на подпрограммы. Но возвращаемые значения формируются из параметров - имен функций и указателей на функции. Параметры и возвращаемые значения подпрограмм листинга 34 даны в табл. 4.

Листинг 34. Подпрограммы, использующие параметр и результат в виде имени функции или указателя на функцию.

USES  CRT; {   Имена   типов:   }

TYPE  TFUN=FUNCTION (X,Y:INTEGER):INTEGER; {- имя   функции }
PTFUN  = ^TFUN;{   -  указатель   на  функцию   }

VAR  FUNV:TFUN;{ -  переменная  типа:   -      TFUN   }

VPF : PTFUN; {   -   PTFUN   }

{$F+}

FUNCTION PLUS (А, В:INTEGER ):INTEGER;

BEGIN  PLUS  :=A + В  END;

FUNCTION  MINUS (А,В :INTEGER) : INTEGER;

BEGIN  MINUS := A - В   END;

{$F-}

{       Процедура  возвращает  имя  функции:       }

PROCEDURE  VZI (VAR F : TFUN;  FV : TFUN );

BEGIN

F := FV {  -  результат  -  имя  функции  }

END;

{   Процедура возвращает указатель на функцию:   }

PROCEDURE  VZP   (VAR F :PTFUN; FP : TFUN );

BEGIN

F := @FP; { - результат -  адрес функции  }

END;

{      Функция возвращает указатель  на функцию: }

FUNCTION  FVZ   ( FP : TFUN  ) : PTFUN;

BEGIN     {   -   параметр     -  имя  функции        }

FVZ := @ FP { - результат -  адрес функции   } END;

{   Функция возвращает указатель на функцию: }

FUNCTION  FVZP   ( FPP : PTFUN ) :  PTFUN;

BEGIN{   -  параметр   -  указатель   на  функцию   }

FVZP :=  FPP {   -   результат   - " " }

END;

{   Основная программа   }

BEGIN CLRSCR;

{ Возврат в переменной FUNV значения имени функции = PLUS:}

VZI ( FUNV, PLUS ); {  Вызов PLUS с помощью FUNV: }

WRITELNC FUNV (1,2) = ', FUNV (1,2)); { Возврат в VPF значения указателя - адреса функции PLUS: }

VZP ( VPF, PLUS ); { Вызов PLUS с помощью VPF: }

WRITELN (' FUNT(VPF)(2,3) = ', TFUN ( VPF )(2,3));

{ Возврат .из FVZ  значения указателя - адреса функции MINUS: }

VPF := FVZ ( MINUS ); { Вызов MINUS с помощью VPF: }

WRITELN (' FUNT(VPF) (6, 4) = ', TFUN ( VPF )(6,4));

{ Возврат из FVZP значения указателя - адреса функции MINUS: }

VPF := FVZP ( @MINUS ); { Вызов MINUS с помощью VPF: }

WRITELN (' FUNT(VPF) (6, 4) = ', TFUN ( VPF )(7,4)); END.

Таблица 4. Параметры и возвращаемые значения подпрограмм программы листинга 34

Подпрограмма 

Параметр 

Возвращаемый результат 

VZI - процедура 

FV - имя функции 

F = FV - имя функции 

VZP - процедура 

FP - имя функции 

F = @FP - адрес функции 

FVZ - функция 

FP - имя функции 

@FP - адрес функции 

FVZP - функция 

FPP - имя указателя на функцию 

FPP - адрес функции 

В листинге 35 приведена программа, подпрограммы которой также возвращают значения имен подпрограмм и указатели на подпрограммы. Но возвращаемые значения формируются из параметров - массивов имен функций и указателей на функции. В качестве параметра подпрограмм используется I -номер требуемой подпрограммы.

Листинг 35. Подпрограммы, использующие параметр в виде массива имен или массива адресов (указателей) функций и результат в виде имени функции или указателя на функцию.

USES  CRT; {   Имена   типов:   }

TYPE TFUN= FUNCTION (X,Y :INTEGER):INTEGER; {- имя   функции }
PTFUN = ^TFUN;{   -  указатель   на  функцию   }

MS=ARRAY[1..3] OF TFUN;{ -  массив  имен  функций   }

MU  =  ARRAY   [1   ..   3]   OF  PTFUN; {   -  массив   типовых  указателей   }

VAR  FUNV:TFUN;{-  переменная   типа:   -      TFUN   }

VPF  :  PTFUN; {   -   PTFUN   }

I  :  INTEGER;

{$F+}

FUNCTION PLUS(А,В :INTEGER ): INTEGER;

BEGIN  PLUS  := A + В   END;

FUNCTION MINUS (А,В : INTEGER ) : INTEGER;  

BEGIN  MINUS := A - В  END;

FUNCTION   MUL (А,  В : INTEGER ) : INTEGER;

BEGIN    MUL := A * В  END;

{$F-}

{ Константные массивы: }

CONST M:MS =(PLUS,MINUS,MUL);  { - имен функций       }

CMU : MU = ( @PLUS, @MINUS, @MUL ); { - типовых указателей }

{Процедура возвращает имя элемента массива имен функций:     }

PROCEDURE VZI ( VAR F : ТFUN; I : INTEGER; FV : MS ); BEGIN

F := FV[I]      { - результат - имя 1-функции } END;

{  Процедура возвращает указатель на I - имя массива имен функций: }

PROCEDURE VZP ( VAR F : PTFUN; I : INTEGER; FP : MS ); BEGIN

F := @ FP[I];     { - результат - адрес I - имени функции } END;

{ Функция возвращает указатель на I - имя массива имен функций:    }

FUNCTION FVZ ( FP : MS; I : INTEGER ) : PTFUN;

BEGIN { - параметр - имя массива имен функций }

FVZ :=  @ FP[I]   { - результат - адрес I - имени функции } END;

{ Функция возвращает указатель на I - имя массива имен функций:    } FUNCTION FVZP ( FPP : MU; I : INTEGER ) : PTFUN;

BEGIN { - параметр  - массив указателей функций }

FVZP :=  FPP[I]    { - результат - указатель на I - имя   } END;

{   Основная программа   }

BEGIN CLRSCR;

Writeln( 'Возврат из процедуры VZI в переменной FUNV значения I -',

' имени функции: ');   VZI(FUNV, I, М) ; { Вызов PLUS с помощью FUNV: }

WRITELNC FUNV (1,2) - ', FUNV (1,2));

{ Вызов поочередно всех функций массива М - имен функций: }

FOR I := 1 ТО 3 DO BEGIN

VZI (FUNV,I,M) ;   WRITELN('FUNV(1,2)= ',FUNV(1,2));

END;

Writeln(#10#13, 'Возврат из процедуры VZP в VPF значения указателя', ' - адреса I-функции:');    

VZP (VPF, 1, М) ; { Вызов PLUS с помощью VPF: }

WRITELN ('TFUN(VPF) (2,3) = ', TFUN (VPF) (2 , 3) ) ; { Вызов поочередно всех функций массива М - имен функций: }

FOR I := 1 ТО 3 DO BEGIN VZP (VPF, I, M) ; WRITELN ('TFUN(VPF) (2,3) = ', TFUN ( VPF )(2,3));

END;

Writeln(#10#13, 'Возврат из функции FVZ  значения указателя - ',' адреса I-функции:');  

VPF := FVZ ( М, 2 ) ; { Вызов MINUS с помощью VPF: }

WRITELN (' TFUN(VPF)(6,4) = ', TFUN ( VPF )(6,4));

{ Вызов поочередно всех функций массива М - имен функций: }

FOR I := 1 ТО 3 DO BEGIN VPF := FVZ ( M, I ) ; WRITELN (' FUNT(VPF) (6,4) = ', TFUN ( VPF )(6,4));

END;

Writeln(#10#13, 'Возврат из функции FVZP значения указателя - ', 'I элемента массива указателей');  VPF := FVZP ( CMU, 2 );

{ Вызов MINUS с помощью VPF: }

WRITELN (' TFUN (VPF) (7, 4) = ', TFUN ( VPF )(7,4)); { Вызов поочередно всех функций с помощью CMU -

массива указателей на функции: }

FOR I := 1 ТО 3 DO BEGIN VPF : = FVZP ( CMU, I ); WRITELN (' FUNT(VPF) (7,4) = ', TFUN ( VPF )(7,4));

END;

END.

Массивы указателей на полпрограммы

Из подпрограмм с идентичными списками формальных параметров можно формировать массивы имен подпрограмм и массивы типовых и бестиповых указателей на подпрограммы.

В листинге 36 приведена программа, в которой формируются и используются массивы переменных и констант:

  1.  имен процедур;
  2.  указателей на процедуры, типовых и бестиповых.

В программе листинга 36 используются:

PROC - имя типа - процедуры без параметров;

PPROC - имя типа - указателя на процедуру без параметров;

MS - имя типа - массив имен процедур;

MU - имя типа - массив типовых указателей на процедуры;

МР - имя типа - массив бестиповых указателей;

М - имя константного массива типа MS - имен процедур;

CMU - имя константного массива типа MU - типовых указателей;

СМВР - имя константного массива типа МР - бестиповых указателей;

MV - имя массива типа MS - имен процедур;

MUK - имя массива типа MU - типовых указателей на процедуры;

МРР - имя массива типовых указателей на процедуры;

МБР - имя массива бестиповых указателей;

I - переменная для перебора номеров элементов массивов.

Программа показывает формы вызова процедур с помощью элементов массивов имен и указателей на процедуры, типовых и бестиповых.

Инициализация элементов массива имен процедур производится обычным способом:

MV[1] := SOZ; MV[2] := СНТ;

Аналогично для указателей на процедуры:

MUK[1] := @SOZ; MUK[2] := @СНТ; МРР[1] := @SOZ; МВР[2] := @СНТ;

Вызов процедур для выполнения с использованием массива имен процедур производится обычным способом, например: M[I] ; MV[I] ;.

При вызове процедур с помощью массивов указателей на процедуры обязательно явное преобразование к типу вызываемой процедуры.

Примеры вызова процедур с явным преобразованием указателей на процедуры к типу PROC:

PROC(CMU[I]); PROC(MUK[I]); PROC(МРР[I]);

PROC (MBP[I]);

Листинг 36. Вызова процедур с помощью элементов массивов имен процедур и массивов указателей на процедуры.

USES   CRT;

TYPE { Имена типов: }

PROC = PROCEDURE; { - процедуры без параметров }

PPROC = ^ PROG; { - указателя на процедуру   }

MS = ARRAY[1..4] OF PROC; {- массива имен процедур }

{ - массива указателей на процедуры:}

MU = ARRAY[1..4] OF PPROC;       {    - типовых    } МР = ARRAY [I .. 4] OF POINTER;  {    - бестиповых }

{ Переменные - массивы:      }
VAR MV : MS; { - имен процедур }

{ - указателей на процедуры: }

MUK : MU; {  - типовых    }

МРР : ARRAY [ 1..4 ] OF ^PROC;     {  - }

МБР : ARRAY [1 .. 4] OF POINTER;   {  - бестиповых}

I : INTEGER; {  - номер элемента массива }

{   - Процедуры     }

{$F+}

PROCEDURE SOZ; 'BEGIN WRITELN ('СОЗДАНИЕ'); END; PROCEDURE CHT; BEGIN WRITELN ('ЧТЕНИЕ'); END;

PROCEDURE KOR; BEGIN WRITELN ('КОРРЕКТИРОВКА'); END; PROCEDURE POISK; BEGIN WRITELN ('ПОИСК'); END;

{$F-}

{Массивы имен и указателей на процедуры - типизированные константы; могут быть объявлены только после текстов процедур этого массива:}

CONST М: MS = (SOZ,CHT,KOR,POISK );  {- массив имен   }

CMU:MU = (@SOZ,@CHT,@KOR,@POISK); {- мас.указ,типовых }

СМВР:МР = ( @SOZ, @CHT, @KOR, @POISK ); {- мас.ук. бестиповых}

{   Основная программа   }

BEGIN  CLRSCR;  { Вызовы процедур: }

WRITELN('Для константного массива инициализированных имен процедур:');

FOR I := 1 ТО 4 DO M[I] ;

WRITELN('Для константного массива инициализированных типовых указателей:')

FOR I := 1 ТО 4 DO PROC(CMU[I]);

WRITELN('Для константного массива инициализированных бестиповых', ' указателей:');  

FOR I := 1 ТО 4 DO PROC(СМВР[I]);

{ Инициализация массива имен процедур: }

WRITELN('Для массива переменных, инициализированных именами процедур:');

MV[1] := SOZ; MV[2] := CHT; MV[3] := KOR; MV[4] := POISK;

FOR I := 1 TO 4 DO MV[I];         { - вызов процедур } WRITELN ('Для массива типовых указателей на процедуры: 'PROC '); МРР[1] := @SOZ; МРР[2] := @СНТ; МРР[3] := @KOR; МРР[4] := @POISK;

FOR I := 1 ТО 4 DO PROC (MPP[I]); { - вызов процедур }

WRITELN('Для массива типовых указателей на процедуры: PPROC');

MUK[1] := @SOZ; MUK[2] := @CHT; MUK[3] := @KOR; MUK[4] := 0POISK;

FOR I := 1 TO 4 DO PROC (MUK[I]); { - вызов процедур }

WRITELN('Для массива бестиповых указателей на процедуры - POINTER:');

МВР[1] := @SOZ; МВР[2] := @СНТ; МВР[3] := @KOR; MBP[4] := @POISK;

FOR I := 1 ТО 4 DO PROC (МБР[I]); { - вызов процедур } END.


 

А также другие работы, которые могут Вас заинтересовать

27626. Объект преступления - общественная безопасность в сфере обращения указанных в ст.222 УК предметов (оружие, боеприпасы, взрывчатые вещ-ва, взрывчатые устройства) 81.5 KB
  Сбыте хранении перевозке либо ношении огнестрельного оружия боеприпасов взрывчатых веществ или взрывных устройств. Основные части оружия это ствол затвор барабан рамка и стальная коробка. Нёзаконность заключается в нарушении норм Закона об оружии хранение и ношение оружия без лицензии. Хранение нахождение оружия и предметов в помещениях тайниках а также в иных местах обеспечивающих их сохранность.
27628. Объект преступления - здоровье населения. Предмет преступления - наркотические средства, психотропные вещества или их аналоги 117.5 KB
  Предмет преступления наркотические средства психотропные вещества или их аналоги. Наркотические средства это вещества природного или синтетического происхождения которые способны оказывать специфическое воздействие на нервную систему человека в результате чего наступает полная зависимость от них а в дальнейшем разрушение и гибель организма. Психотропные вещества это природные или синтетические вещества способные оказывать стимулирующее и иное воздействие на психику и поведение человека. Перечень веществ относящихся к наркотическим...
27630. Необходимая оборона, условия её правомерности и значение в борьбе с преступностью 32.5 KB
  Превышение пределов необходимой обороны и его уголовноправовое значение. Необходимая оборона это правомерная защита лицом своих прав и интересов других лиц общества или государства от общественно опасного посягательства путем вынужденного причинения вреда нападающему если при этом не было допущено превышение пределов необходимой обороны. Уголовный закон устанавливает условия правомерности необходимой обороны которые делятся на условия относящиеся к посягательству и на условия относящиеся к защите. Нельзя ссылаться на состояние...
27631. Обоснованный риск, исполнение приказа или распоряжения, а также физическое и психическое принуждение, как обстоятельства, исключающие преступность деяния. Общие и частные признаки этих обстоятельств 41 KB
  Не является преступлением причинение вреда охраняемым уголовным законом интересам при обоснованном риске для достижения общественно полезной цели. Риск признается обоснованным при наличии совокупности нескольких условий: – общественно полезная цель не могла быть достигнута не связанными с риском действиями бездействием; – лицо допустившее риск предприняло достаточные меры для предотвращения вреда охраняемым уголовным законом интересам. Принятие достаточных мер для предотвращения вреда означает что совершаемые действия должны основываться...
27633. Использование должн. лицом своих служебных полномочий вопреки интересам службы 89.5 KB
  лицом своих служебных полномочий вопреки интересам службы если это деяние совершено из корыстной или иной личной заинтересованности и повлекло существенное нарушение прав и законных интересов граждан или организации либо охраняемых законом интересов общества или госва. лицом своих служебных полномочий вопреки интересам службы или иной личной заинтересованности. 286состоит в совершении действий явно выходящих за пределы его полномочий. полномочий может быть совершено только в форме активных действий злоупотребление ими может совершаться и...