Название: Квантовая механика - Учеб. пособие. (Краснопевцев Е. А.)

Жанр: Информатика

Просмотров: 1190


2. теоретические сведения

 

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

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

Внутренняя процедура задается в головной программе, внешней или модульной процедуре после оператора CONTAINS. При этом головная программа или процедура называется носителями содержащихся в них внутренних процедур.

Имя внутренней процедуры локальное, т.е. к внутренней процедуре можно обратиться только внутри ее носителя. В свою очередь внутренняя процедура имеет доступ к объектам своего носителя (ассоциирование через носитель).

В отличие от внешних и модульных процедур внутренние процедуры не могут содержать других внутренних процедур.

Структура внутренней процедуры-подпрограммы:

      SUBROUTINE имя подпрограммы [([список формальных

                                параметров])]

           [операторы описания]

           [исполняемые операторы]

      END SUBROUTINE [имя подпрограммы]

Структура внутренней процедуры-функции:

      [type] FUNCTION имя функции ([список формальных

                                     параметров])  &

      [RESULT (имя результата)]

            [операторы описания]

            [исполняемые операторы]

      END FUNCTION [имя функции]

В отличие от внешних процедур внутренние процедуры (как и модульные), обязательно содержат в операторе END слово FUNCTION или SUBROUTINE. Внутренняя процедура компилируется со своей программой-носителем как единое целое, поэтому компилятор знает все о ней. То есть между внутренней процедурой и вызывающей программной единицей существует явный интерфейс, поэтому тип внутренней функции не должен объявляться в ее носителе.

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

Внешняя процедура может компилироваться отдельно от использующих ее программных единиц.

Структура внешней процедуры-подпрограммы:

       SUBROUTINE имя подпрограммы [([список формальных

                                 параметров])]

                   [операторы описания]

                   [исполняемые операторы]

                   [CONTAINS

                                внутренние процедуры]

       END[ SUBROUTINE [имя подпрограммы]]

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

Структура внешней процедуры-функции:

      [type] FUNCTION имя функции ([список формальных

                                     параметров])  &

               [RESULT (имя результата)]

                    [операторы описания]

                    [исполняемые операторы]

                    [CONTAINS

                         внутренние процедуры]

               END [FUNCTION [имя функции]]

Заголовок функции содержит оператор FUNCTION. Функция обязана содержать результирующую переменную, в которую помещается возвращаемый функцией результат. В качестве результирующей переменной может являться либо имя функции, следующее за оператором FUNCTION, либо имя результата, задаваемое в предложении RESULT. Имя результата не должно совпадать с именем функции. Предложение RESULT может отсутствовать.

Тип результирующей переменной определяет тип функции и может быть задан посредством указания type в заголовке функции. Type в заголовке может быть опущен, тогда тип результирующей переменной может быть задан явно в одном из операторов объявления функции, в операторе IMPLICIT или неявно.

Если результатом функции является переменная производного типа, массив или ссылка, то type опускается, и результирующая переменная объявляется в разделе объявлений функции.

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

Во внешней функции в операторе END оператор FUNCTION может отсутствовать (в отличие от внутренней процедуры).

Выполнение оператора END приводит к передаче управления в вызывающую программную единицу. Выход из процедур может осуществляться и с помощью оператора RETURN.

Вызов подпрограммы (внутренней и внешней) выполняется оператором:

CALL имя подпрограммы ([список фактических параметров])

Вызов функции (внутренней и внешней) выполняется из выражения, например:

Result = имя функции ([список фактических параметров])

1. Пример объявления и вызова внешней функции:

а)   logical function flag(a,n) result(vf)

 

 Объявлена логическая функция flag(a,n),

 a, n – формальные параметры.

 В качестве результирующей переменной используется   переменная vf, объявленная  в result

 
 ...

 

 vf =

 end

 

Логический тип функции flag также объявлен и в

головной программе fude

 

Вызов функции flag, a, n – фактические параметры

 

 
 

program fude                                  

logical flag, fl

 …

.fl=flag(a,n)

.…

end                                            

 

б) при отсутствии предложения result объявление функции будет:

       logical function flag(a,n)

           …

          flag =…      В качестве результирующей переменной

                              используется имя функции

       end                            

Вызов функции из program fude будет таким же, как и в а).

2. Пример объявления и вызова внешней подпрограммы:

program par

Вызов подпрограммы из головной  программы

 

вызов подпрограммы из головной  программы

 
integer a(10), b1(13), b2(8)

call fob ®

Объявление подпрограммы fob

 
     end program par

subroutine fob®

 

integer a, na, b, nb, c, nc

…                                                          

end

 

Объявление внутренних процедур будет отличаться от вышеприведенных объявлений внешних процедур тем, что они будут находиться внутри головной программы после оператора CONTAINS, и в операторе END внутренних процедур обязательно должен находится оператор FUNCTION, если это процедура-функция или оператор SUBROUTINE, если это процедура-подпрограмма. Вызовы внутренних процедур не отличаются от вызовов внешних процедур.

 

Обмен данными между процедурой и вызывающей

программной единицей

 

Обмен данными между процедурой и вызывающей программной единицей может быть выполнен через параметры процедуры (ассоциирование через параметры).

Параметры, используемые при вызове процедуры, называются фактическими. Параметры, используемые в процедуре, называются формальными (см. вышеприведенные структуры и примеры). Фактическими параметрами могут быть выражения, буквальные и именованные константы, простые переменные, массивы и их сечения, элементы массивов, записи, элементы записей, строки, подстроки, процедуры и встроенные функции. Формальными параметрами могут быть переменные, процедуры и звездочка (*). Формальные параметры могут отсутствовать, если передача данных выполняется посредством use – ассоциирования или ассоциирования через носитель (см. лабораторную работу № 10).

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

 

Таблица 7.1

Фактические и формальные параметры

Фактические параметы

Формальные параметры

Простая переменная

Простая переменная

Элемент записи

Переменная

Запись

Запись

Строка

Строка

Подстрока

Строка

Массив, сечение массива или элемент

массива

Массив или простая переменная

Процедура

Процедура

Выражение, константа

Переменная

 

Примечания.

1. Если формальный параметр является ссылкой, то и соответствующий параметр тоже должен быть ссылкой.

2. Если фактическим параметром является строка, то формальным параметром может быть строка, перенимающая длину.

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

 

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

– неявно, при этом способ использования формального параметра определяет ассоциированный с ним фактический параметр. Формальный параметр не должен переопределяться в процедуре, если ассоциированный с ним параметр выражение или константа;

– явно, с использованием атрибута или оператора INTENT, синтаксис которых:

 

INTENT (spec) [::] vname ! оператор INTENT

type-spec, INTENT (spec) [, attrs] :: vname ! атрибут INTENT;

 

spec – вид связи формального параметра, spec может принимать одно из трех значений:

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

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

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

– vname – разделенные запятыми имена формальных параметров;

– type-spec – спецификация любого типа данных;

– attrs – список иных атрибутов формальных параметров.

 

Пример 1. Сформировать вектор с1 из элементов вектора а, которых нет в векторе b1. Затем сформировать вектор с2 из элементов вектора а, которых нет в векторе b2. Формирование массивов выполнить в подпрограмме.

 

    Из головной программы part вызывается внешняя процедура-подпрограмма fobs.

    При первом вызове в подпрограмму посылаются фактические параметры: массив а и его размер na, массив b1 и его размер nb1; из подпрограммы возвращаются фактические параметры: массив с1 и его размер nc1.

 

    При втором вызове посылаются фактические параметры: массив а и его размер na, массив b2 и его размер nb2; из подпрограммы возвращаются фактические параметры: массив с2 и его размер nc2.

 
program part

integer, parameter:: na=10, &

             nb1=5, nb2=7

integer:: a(na) &

              = (/1,-1,2,-2,3,-3,4,-4,5,-5/)

integer:: b1(nb1)=(/1,-1,2,-2,3/)

integer:: b2(nb2)=(/1,-1,2,-2,3,-3,4/)

integer c1(na), c2(na), nc1, nc2

call fobs(a, na, b1, nb1, c1, nc1) 

call fobs(a, na, b2, nb2, c2, nc2)

print *, c1(:nc1)

print *,c2(:nc2)

end program

 

Подпись:    Объявлена внешняя процедура-подпрог-рамма fobs.
   Вид связи формальных параметров – неявный ( без атрибута INTENT). 
    Входные формальные параметры – массив а и его размер na, массив b и его размер nb. 
Выходные формальные параметры – массив с и его размер nc.
   В данном примере формальные парамет-ры строго соответствуют фактическим параметрам по типу, количеству, порядку следования. Формальным массивам а, b и с ставятся в соответствие фактические мас-сивы а, b1 и с1 (при первом вызове) и фактические массивы а, b2 и с2 (при втором вызове). Формальным переменным na, nb, nc ставятся в соответствие фактические переменные na, nb1, nc1 (при первом вызове) и фактические переменные na, nb2, nc2 (при втором вызове). 
subroutine fobs &

              (a, na, b, nb, c, nc)

integer na, nb ,a(na), b(nb)

integer c(na), nc

integer i, j, va

nc = 0

loop_a: do i = 1,na

  va = a(i)

  do j = 1,nb

    if(va) &

         = b(j)) cycle loop_a

  enddo

  nc = nc+1

  c(nc) = va

enddo loop_a

end

 

Пример 2. В предыдущем примере подпрограмму fobs оформить как внутреннюю.

program part

integer, parameter:: na = 10, nb1= 5, nb2 = 7

   В отличие от внешней, внутренняя процедура fobs:

– входит в состав головной программы после оператора CONTAINS;

– в операторе END процедуры fobs присутствует обязательно оператор SUBROUTINE;

– имя процедуры fobs теперь локально, ее данные доступны только головной программе part и другим внутренним процедурам part;

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

 
integer:: a(na)&

         =(/1,-1,2,-2,3,-3,4,-4,5,-5/)

integer:: b1(nb1)=(/1,-1,2,-2,3/)

integer:: b2(nb2) &

              = (/1,-1,2,-2,3,-3,4/)

integer c1(na), c2(na), nc1, nc2

call fobs(a, na, b1, nb1, c1, nc1) 

call fobs(a, na, b2, nb2, c2, nc2)

print *, c1(:nc1)

print *,c2(:nc2)

contains 

  subroutine fobs(a, na, b, nb, c, nc)

  integer na,nb,a(na),b(nb)

  integer c(na), nc

  integer i,j,va

  nc=0

  loop_a: do i=1,na

    va=a(i)

    do j=1,nb

      if(va==b(j)) cycle loop_a

    enddo

    nc=nc+1

    c(nc)=va

  enddo loop_a

  end     subroutine fobs

end program

 

Пример 3. В подпрограмме fobs объявить вид связи входных и выходных формальных параметров явно.

     subroutine fobs(a, na, b, nb, c, nc)

     integer, intent(in):: na,nb,a(na),b(nb) ! входные параметры

     integer, intent(out):: c(na), nc  !  выходные параметры

    integer i,j,va  !  локальные параметры, которые используются

                              только внутри процедуры fobs

Недопустимо использование атрибута INTENT для формальных параметров с атрибутом POINTER.

Если используется процедура-функция, то ее результирующая переменная подобна параметру с видом связи OUT.

 

Интерфейсы между процедурами и вызывающими

программными единицами

 

Интерфейс между процедурой и вызывающей программной единицей считается заданным, если вызывающей программной единице известны:

– имя процедуры;

– ее вид (подпрограмма или функция);

– свойства функции (если процедура-функция) (тип, результи-

   рующая переменная);

– имена, положение и свойства формальных параметров.

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

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

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

– интерфейс задается явно. Это делается при помощи интерфейсного блока, имеющего вид:

     Тело интерфейса содержит описание одного и более интерфейсов процедур. Как правило, интерфейс процедуры – это точная копия заголовка процедуры, объявлений ее формальных параметров, типа функции в случае процедуры-функции и оператора END процедуры.

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

 
 

 interface                     

  ...

 тело интерфейса

  ...

 end interface

 

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

    В теле интерфейса присутствует интерфейс одной процедуры fobs.

    Этот интерфейсный блок должен быть размещен среди операторов описания головной программы.

 
 

Interface                    

  subroutine fobs(a, na, b, nb, c, nc)

    integer  na, nb, a(na), b(nb)

    integer  c(na), nc

    end subroutine fobs

 end interface

 

В приведенном примере обязательной необходимости в явном интерфейсе нет.

Однако задание явного интерфейса необходимо, если:

1) процедура имеет необязательные формальные параметры. При некоторых вызовах процедуры часть фактических параметров может не использоваться. В этом случае соответствующие формальные параметры должны быть объявлены с атрибутом OPTIONAL или в операторе OPTIONAL

type-spec, OPTIONAL [,attrs]:: vname !  как атрибут

OPTIONAL [::] vname ! как оператор

(см. пример 5 пункта 3 данной лабораторной работы):

2) вызов процедуры осуществляется с ключевыми словами. Расположение фактических и соответствующих им формальных параметров может быть нарушено, если при вызове процедуры используются параметры с ключевыми словами. Ключевые слова – это имена формальных параметров, присвоенные им в интерфейсном блоке (см. пример 5 пункта 3 данной лабораторной работы);

3) результатом процедуры-функции является массив или ссылка (см. пример 2 и пример 3 пункта 3 данной лабораторной работы);

4) формальным параметром процедуры является перенимающий форму массив, ссылка или ее адресат (см. пример 4 пункта 3 данной лабораторной работы).

 

Массивы – формальные параметры процедур

 

В процедурах форма и размер массива-формального параметра могут определяться в момент вызова процедуры. Можно выделить 3 вида массивов-формальных параметров: заданной формы, перенимающие форму и перенимающие размер. Рассмотрим первых два.

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

Формы фактического и соответствующего ему формального параметра-массива могут отличаться.

 

Пример. Создать процедуру обмена содержимого двух массивов.

     Между вызывающей программой  и внешней процедурой swap устанавливается интерфейс во время вызова процедуры по фактическим массивам a, b и фактическим переменным  m, n.

 
integer, parameter::&

             m=3, n=4, k=m*n

real a(m, n)/k*1/, b(m, n)/k*2/

call swap(a, b, m, n )

write (*,'(3(/10x,4f5.2))') &

        ((a(i, j), i=1,3), j =1,4)

end

 

subroutine swap(a, b, m, n)

    а, b массивы заданной формы, нижняя граница их измерений равна 1, верхняя граница = m*n, где m, n – передаваемые в процедуру значения из вызывающей программы; формальные массивы  а, b и фактические массивы  а, b имеют разные формы;

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

 
integer m, n

real a(m*n), b(m*n)

real c(size(a))

c=a

a=b

b=c

end

           

Массивы, перенимающие форму. Такие массивы-формальные параметры перенимают форму у соответствующего фактического параметра. В результате ранг и форма фактического и формального параметров совпадают. При описании формы формального параметра каждая размерность имеет вид: [нижняя граница]: , где нижняя граница – это целое описательное выражение, которое может зависеть от данных в процедуре или других параметров. Если нижняя граница опущена, то она равна 1.

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

   Между вызывающей программой и внешними процедурами asub1, asub2 установлен явный интерфейс, поскольку  формальными параметрами этих процедур являются массивы а, b, перенимающие форму фактических параметров x и y соответственно.

 
Пример:

real x(0:3, 0:6), y(-3:0)

interface

  subroutine asub1(a, b)

    real a(:, :), b(:)

  end

  subroutine asub2(a, b)

    real a(:, :), b(:)

  end

end interface

call asub1(x, y)

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

 
call asub2(x, y)

end

 

subroutine asub1(a, b)

  real a(:, :), b(:)

  print *, lbound(a,1), ubound(a,1) ! будут напечатаны значения 1 4

  print *, lbound(a,2), ubound(a,2) ! будут напечатаны значения 1 7

  print *, lbound(b,1), ubound(b,1) !  будут напечатаны значения 1 4

   Функции lbound и ubound  возвращают значения нижней и верхней границы для каждого измерения массива.

 

 
end

 

subroutine asub2(a, b)

 real a(0:, 0:), b(-3:)

 print *, lbound(a,1), ubound(a,1)  ! будут напечатаны значения 0 3

 print *, lbound(a,2), ubound(a,2)  ! будут напечатаны значения 0 6

 print *, lbound(b,1), ubound(b,1) ! будут напечатаны значения -3 0

end

 

Примечание. Если оформить процедуры asub1, asub2 как внутренние, то явный интерфейс в вызывающей программе описывать не надо.

3. Примеры задач и примеры написания

для них программ на языке Фортран

 

Пример 1. Вывести первый отрицательный элемент каждого столбца матрицы.

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

integer, parameter:: m=4, n=5

integer j

real:: a(m,n)=1.0

a(1,1)=-1; a(2,2)=-2; a(3,3)=-3

do j=1,n

  call prifin(a(1,j), m, j)

enddo

end

     Между вызывающей программой и внешней процедурой prifin устанавливается интерфейс в момент вызова процедуры по фактическому элементу массива а(1,j) и фактическим переменным m, j.

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

     В процедуре prifin доступны все элементы столбца j, начиная с первого, и все последующие элементы матрицы а.

Вектор b содержит все элементы столбца j матрицы а.

 
 

 

subroutine prifin(b, m, j)

integer m, i, j

real b(m)

do i=1,m

  if(b(i)<0) then

    print *,'Col', j,'  Element', b(i)

  return

  endif

enddo

print *, ' col', j,'  no negativ'

end

 

Пример 2. Составить функцию, возвращающую массив из первых n положительных элементов передаваемого в нее массива. Сделать два варианта: оформить функцию как внутреннюю, затем как внешнюю.

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

а) функция-процедура задана как внутренняя

real, allocatable:: ap(:)

real:: a(10)=(/1,-1,2,-2,3,-3,4,-4,5,-5/)

real:: b(10)=(/2,-1,3,-2,4,-3,4,-4,5,-5/)

   б) при оформлении функции fap как внешней, нужно:

   1) в вызывающей программной единице явно задать интерфейс:

 interface

  function fap(a,n)

  integer n

  real fap(n)

  real, dimension(:):: a

  end function fap

end interface

   2) оператор contains убрать;

   3) оператор end поставить перед заголовком процедуры-функции fap.

 
integer n/3/

allocate(ap(n))

ap=fap(a,n)+fap(b,n)   !  3.0  5.0  7.0

print '(1x,10f5.1)', ap

contains

  function fap(a,n)

    integer:: n,k,i

            real:: fap(n)

            real, dimension(:):: a

            fap=0

            k=0

            do i=1, size(a)

              if(a(i)>0) then

                k=k+1

                fap(k)=a(i)

                if(k==n) exit

              endif

            enddo

            return

  end function fap

end

 

Пример 3. Получить массив а из неотрицательных чисел массива с. Использовать ссылку как результат процедуры-функции.

 

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

 

integer, pointer:: a(:)

integer:: c(10) = (/1,-2,2,-2,3,-2,4,-2,5,-2/)

interface

 

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

    К возвращаемому функцией массиву-ссылке emi прикреплен в головной программе массив-ссылка а.

 
  function emi(c)

  integer, pointer:: emi(:)

  integer c(:)

  end function emi

end interface

a=> emi(c)

print *,a  !  1   2   3   4   5

print *,2*emi(c)  !   2   4   6   8   10

end

function emi(c)

  integer, pointer:: emi(:)

  integer c(:),i,k,m

  k=count(c>=0)

  allocate(emi(k))

  m=1

    do i=1,size(c)

              if(c(i)<0) cycle

              emi(m)=c(i)

              m=m+1

            enddo

 end

 

Пример 4. Сформировать массив с из отрицательных элементов массива а и положительных элементов массива b. Массивы а и b одномерные. Использовать внешнюю процедуру-подпрограмму, массивы оформить как массивы-ссылки.

Замечание: ссылка может быть формальным параметром процедуры. В этом случае фактический параметр также должен быть ссылкой. Ранги фактического и формального параметров-ссылок должны совпадать. При вызове процедуры состояние привязки фактического параметра передается формальному и, наоборот, при завершении работы процедуры состояние привязки формального параметра передается фактическому.

integer, pointer:: a(:), b(:), c(:)

integer, target:: d(5) = (/-1,6,-5,3,8/)

     Так как формальный параметр является ссылкой, то интерфейсный блок для под-программы pab задан явно.

 

 

 

 
interface

  subroutine pab(a,b,c)

    integer, pointer:: a(:),b(:),c(:)

  end subroutine pab

end interface

    Фактическим массивам-ссыл-кам a, b, c поставлены в соответствие формальные массивы-ссылки a, b, c.

    Фактический массив-ссылка а привязан к массиву-адресату d

    Это состояние привязки передается формальному массиву-ссылке а.

   Формальный массив-ссылка b привязан  к определенному ранее формальному массиву-ссылке а. Это состояние привязки передается фактическому массиву-ссылке b.

 
a = > d

call pab(a,b,c)

print *,c   ! 6   3   8   -1   -5

end

 

 subroutine pab(a,b,c)

   integer, pointer:: a(:),b(:),c(:)

   integer m,n

   b = > a

   k = count(a < 0)+count(b > 0)

   allocate(c(k))

   m = 1

   do i = 1,size(a)

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

 
     if(a(i) > 0) then

             c(m) = a(i)

             m = m+1

             endif

   enddo

   n = m

   do i = 1,size(b)

     if(b(i) < 0) then

             c(n) = b(i)

             n = n+1

             endif

   enddo

 end

 

Пример 5. Создать функцию pre(array, me, sig), возвращающую:

– сумму me первых положительных элементов массива array, если sig > 0;

– сумму me первых отрицательных элементов массива array, если sig < 0;

– сумму me первых элементов массива array, если sig = 0 или отсутствует

program tes

  integer, parameter:: m = 3, n = 10

  integer:: a(n) = (/1,-1,2,-2,3,-3,4,-4,5,-5/)

  interface

    integer function npe(array, me ,sig)

              integer, intent(in):: array(:)

    Параметры функции me и sig имеют атрибут необязательных параметров при вызове функции. При вызове также используется ключевое слово sig. Поэтому к внешней функции npe интерфейс задан явно.

   Встроенная функция PRESENT(a) используется для того, чтобы определить, задан необязательный формальный параметр или нет (ее значение равно.TRUE., если задан, и .FALSE. – в противном случае).

 
  integer, intent(in), optional:: me, sig

    end function npe

  end interface

print *, npe(a,m,1)         !     6

print *, npe(a, sig=-1)   !  -15

print *, npe(a)                !     0

end program tes

integer function npe(array, me, sig)

 integer, intent(in):: array(:)

 integer, intent(in), optional:: me, sig

 integer mval, sval

 integer, allocatable:: temp(:)

 if(.not.present(sig)) then

   sval=0

  else

   sval=sig

 endif

 if(present(me)) then

   mval=me

 else

   mval=size(array)

 endif

 select case(sval)

   Встроенная функ-ция pack(array, array < 0) упаковывает массив array в одномерный массив temp под управлением массива mask (например, mask = = array < 0).

 
 case(1:)

   allocate(temp(min(mval,count(array>0))))

   temp=pack(array, array>o)

 case(:-1)

   allocate(temp(min(mval,count(array<0))))

   temp=pack(array, array<0)

 case(0)

   allocate(temp(mval))

   temp=array(1:mval)

 endselect

 npe=sum(temp)

 deallocate(temp)

 end function npe