Отправляет email-рассылки с помощью сервиса Sendsay

Всё о работе в Интернет

  Все выпуски  

Занятие 44. Процедурный тип. Его применение для построения подпрограмм вычисления сумм и произведений членов числовых последовательностей.


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

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

ПРОЦЕДУРНЫЙ ТИП

1. Описание и свойства процедурного типа.

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

Существует два процедурных типа: тип-процедура и тип-функция. Наиболее популярным из них является тип-функция. Займёмся его рассмотрением.

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

Для описания процедурного типа-функции используется заголовок функции, в котором опускается её имя, например:

Type

   TFunc = Function ( x: Real ): Real;

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

Механизм использования процедурных типов продемонстрирован на примере следующей программы:

   Program Procedure_Type;
      Type
         TFunc = Function (x: Real): Real;
      Function f1 (x: Real): Real; Far;
      Begin
         f1 := x 
* x
      End;
      Function f2 (x: Real): Real; Far;
      Begin
         f2 := -x 
* x
      End;
      Procedure PrintFunc ( x: Real; Func: TFunc );
      Begin
         WriteLn( x:0:3, ' ', Func(x):0:3 )
      End;
      Var x: Real;
   Begin
      Write( 'Введите аргумент: x = ' ); ReadLn(x);
      PrintFunc(x, f1);
      PrintFunc(x, f2);
      ReadLn
   End.

Используемая в программе процедура PrintFunc предназначена для печати значения аргумента и соответствующего значения некоторой функции. И аргумент x: Real, и функция Func: TFunc указаны в качестве формальных параметров этой процедуры. При этом функция Func, значение которой должно быть напечатано, имеет процедурный тип-функцию TFunc. Этот процедурный тип, в соответствии с его описанием в разделе нестандартных типов Type, указывает, что он распространяется на все функции типа Real, и имеющие один аргумент также типа Real.

Кроме этого, в программе представлены описания двух функций f1 (x: Real): Real и f2 (x: Real): Real, тип которых полностью соответствует типу TFunc. Поэтому они могут использовать в качестве фактических параметров обращения к процедуре PrintFunc.

В исполняемой части программы сначала с клавиатуры вводится значение аргумента, а затем дважды выполняется обращение к процедуре PrintFunc. При этом сначала печатается значение функции f1, а затем – значение функции f2.

Для установления правильных связей функций f1 и f2 с процедурой PrintFunc они должны компилироваться с расчётом на дальнюю модель памяти. Вкратце напомним, что это такое.

Установка дальней модели памяти для тех процедур и функций, которым она требуется, осуществляется с помощью стандартной директивы Far. Эти директивы должны указываться непосредственно после заголовков процедур и функций. Дальняя модель памяти может быть установлена также для всей программы в целом. Для этого перед началом программы должна указываться директива компиляции {$F+}. В этом случае указание директив Far не требуется.

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

2. Циклические подпрограммы с использованием процедурного типа.

В материалах занятия 42 мы рассмотрели алгоритмы вычисления сумм и произведений членов последовательностей простого типа. При этом в качестве недостатка этих алгоритмов было отмечено то, что они могут работать только с общими членами, обозначенными f(i). Теперь мы имеем возможность на основе использования процедурного типа избавиться от этого недостатка.

Решим те же задачи повторно.

Задача C.1.1. “Сумма членов последовательности простого типа”. Бесконечная числовая последовательность простого типа задана формулой общего члена i = f ( i ), = 1, 2, 3, ... . Построить подпрограмму вычисления суммы первых N членов этой последовательности (>= 0).

Function Sum_Simple_Sequence ( N: LongInt; f: TFunction ): Real;
   Var i: LongInt; S: Real;
Begin
   S := 0;
   For i:=1 To N Do S := S + f(i);
   Sum_Simple_Sequence := S
End;

Задача C.1.2. “Произведение членов последовательности простого типа”. Бесконечная числовая последовательность простого типа задана формулой общего члена i = f ( i ), = 1, 2, 3, ... . Построить подпрограмму вычисления произведения первых N членов этой последовательности (>= 0).

Function Product_Simple_Sequence ( N: LongInt; f: TFunction ): Real;
   Var i: LongInt; P: Real;
Begin
   P := 1;
   For i:=1 To N Do P := P * f(i);
   Product_Simple_Sequence := P
End;

В обеих подпрограммах с целью вычисления значения члена последовательности по его порядковому номеру используется обращение к некоторой функции f(i), указанной в качестве их формального параметра. Эта функция имеет нестандартный процедурный тип TFunction, который предварительно должен быть определён в разделе типов следующим образом:   Type TFunction = Function(i: LongInt): Real. Это значит, что подпрограммы C.1.1 и C.1.2 способны работать с любыми функциями типа Real, имеющими единственный аргумент типа LongInt. Например, формула общего члена числовой последовательности простого типа Ai = 1 / ( 2 + sin(i) ), i = 1, 2, 3, …  полностью соответствует этим требованиям, поэтому её можно будет использовать как фактический параметр обращения к подпрограммам, если представить её, например, в следующем виде:

Function f ( i: LongInt ): Real;
Begin
   f := 1 / ( 2 + Sin(i) )
End;

Для установления правильных связей функций-фактических параметров с вызывающими подпрограммами все они должны компилироваться с расчётом на дальнюю модель памяти. Как уже указывалось, установка дальней модели памяти для тех подпрограмм, которым она требуется, осуществляется с помощью стандартной директивы Far. Эта директива должна указываться непосредственно после заголовков подпрограмм, например, Function f ( i: LongInt ): Real; Far. Дальняя модель памяти может быть установлена также для всей программы в целом посредством указания директивы компиляции {$F+} перед её началом. В этом случае указание директив Far не требуется. 

Уважаемые подписчики! При необходимости задать вопрос, проконсультироваться, уточнить или обсудить что-либо обращайтесь через Гостевую книгу моего персонального сайта http://a-morgun.narod.ru. При этом настоятельно рекомендую пользоваться браузером Internet Explorer.

С уважением, Александр.


В избранное