Процедуры-подпрограммы
Процедура-подпрограмма отличается от процедуры-функции тем, что она не имеет возвращаемого значения. Результаты ее работы передаются вызываемой программе через формальные параметры, либо через глобальные переменные.
Структура подпрограммы имеет вид:
subroutine Имя подпрограммы (список формальных параметров)
[Операторы описания]
[Исполняемые операторы]
[contains
внутренние процедуры]
end [subroutine[имя подпрограммы]]
В списке формальных параметров подпрограммы перечислены входные и выходные параметры. Используя входные параметры, процедура вычисляет значения выходных параметров и возвращает управление в вызывающую программную единицу.
Оператор subroutineназывается заголовком подпрограммы. Тип подпрограммы не существует, так как у нее нет возвращаемого значения. В заголовке указывается уникальное имя подпрограммы, составленное по правилам Фортрана, и список формальных параметров в круглых скобках.
Так же, как и в функции, среди операторов описания должны присутствовать описания формальных параметров подпрограммы и внутренних (локальных) переменных и массивов.
Если в операторе end указано имя подпрограммы, оно должно совпадать с именем в заголовке подпрограммы.
Обращение к подпрограмме осуществляется оператором call, имеющим вид:
call имя подпрограммы [(список фактических параметров)]
Пример подпрограммы
Написать подпрограмму, меняющую местами первую и последнюю строки вещественной матрицы.
subroutine Transform(Matrix, cRows, cCols) ! заголовок
! операторы описания:
implicit none! оператор должен быть в каждой программной единице
! формальные параметры
integer,intent(in)::cRows, cCols! протяженности по измерениям
! матрица
real, dimension(1:cRows, 1:cCols),intent(in)::Matrix
! локальный временный массив для одной строки:
real, dimension(1:cCols):: Temp
! исполняемые операторы:
cRows = size(Matrix,1) ! количество строк матрицы
Temp = Matrix(1, :) ! первая строка матрицы
Matrix(1, :) = Matrix(cRows, :) ! последняя строка на место первой
Matrix(cRows, :) = Temp ! первая строка на место последней
end subroutine Transform
В главной программе:
integer, parameter:: cR = 6, cCol = 8
real, dimension(1:cR, 1:cCol) :: Array
. . .
call Transform(Array, cR, cCol)
В подпрограмме используется временный локальный массив Temp, длина которого равна длине строки матрицы (cCols). Память для этого массива выделяется динамически при выполнении подпрограммы, операторы allocatable и allocate не требуются.
Параметры процедур
Рассмотрим подробнее способ передачи данных между вызывающей программной единицей и процедурой через параметры. В этом случае в заголовке процедуры указывается список формальных параметров. Формальными параметрами могут быть переменные и массивы, а также имена функций.
В операторах вызова процедуры указывается список фактических параметров. В отличие от формальных параметров, фактическими параметрами могут быть:
- переменные;
- массивы;
- имена функций;
- элементы массивов;
- секции массивов;
- константы – только входные параметры;
- выражения – только входные параметры.
Каждый параметр процедуры имеет следующие основные характеристики:
- тип;
- ранг – размерность или количество измерений; ранг переменной равен 0;
- назначение параметра – входной, выходной или универсальный (изменяемый).
Назначение формального параметра определяет атрибут intent.
Пример.
subroutine Transform(N, Pin, Result) ! заголовок
! операторы описания:
implicit none! оператор должен быть в каждой программной единице
integer, intent(in):: N ! входной параметр
real, intent(out) :: Pin ! выходной параметр
! Result – изменяемый параметр – одномерный массив:
real, dimension(:), intent(inout) :: Result
Атрибут intent(in) в описании параметра определяет параметр как входной: такой параметр не должен изменяться во время работы подпрограммы.
Атрибут intent(out) определяет параметр как выходной, то есть параметр должен быть переопределен в процедуре, поэтому при входе в подпрограмму он переходит в состояние неопределенности. Соответствующий фактический параметр не может быть константой или выражением.
Универсальные параметры описываются с атрибутом intent(inout). Предполагается, что значение универсального параметра может быть переопределено, поэтому соответствующий фактический параметр не может быть константой или выражением.
Для корректной связи вызывающей и вызываемой программных единиц фактические параметры должны согласовываться с формальными параметрами по количеству, и попарно в порядке следования – по типу, рангу, назначению.
Совпадение имен формального и фактического параметров не требуется.
Пример соответствия фактических и формальных параметров:
В функции вычислить среднее арифметическое значение N последних элементов одномерного вещественного массива. В главной программе применить функцию к строкам матрицы из 10 строк и 7 столбцов, считая количество элементов для усреднения N = 5. Результаты записать в одномерный массив.
real function Average(Array, Len, N)
! заголовок функции; возвращаемое значение вещественного типа
! операторы описания:
implicit none! оператор должен быть в каждой программной единице
! формальные параметры
integer, intent(in) :: Len ! длина одномерного массива
integer, intent(in) :: N ! кол-во последних элементов
integer :: i ! локальная переменная
real :: summa ! локальная переменная
real, dimension(1:Len), intent(in) :: Array ! массив
! исполняемые операторы:
summa = 0
do i = Len-N+1, Len
summa = summa + Array(i)
Enddo
Average = summa/N ! возвращаемое значение
end function Average
В главной программе:
program Main
! операторы описания:
Implicit none
real, dimension(1:10, 1:7) :: Array ! исходная матрица
real, dimension(1:10) :: Result ! результирующий массив
! локальные переменные
integer :: N=5 ! количество элементов для усреднения
integer :: i
real Average
! исполняемые операторы:
do i = 1, 10 ! цикл по строкам матрицы
Result(i) = Average(Array(i, :), 7, N)
Enddo
end program Main
Здесь в качестве фактического параметра функции – одномерного массива – используется секция двумерного массива (строка с номером i)
Дата добавления: 2017-09-19; просмотров: 299;