
- •Управление векторами и матрицами
- •Компиляция и выполнение Компиляция
- •Связывание (редактирование связей )
- •Выполнение
- •Примеры
- •Соглашения о записи кода
- •Арифметические выражения
- •Операции отношения
- •Логические выражения
- •Сравнение символов
- •Переносимость результата
- •Спецификация массивов
- •Сечения массива Индивидуальные элементы
- •Сечения
- •Векторные указатели
- •Память для массива Физическая память:
- •Присваивание массива Присваивание всего массива
- •Присваивание секции (вырезки) массива
- •Повторная нумерация
- •Основные встроенные процедуры
- •Массивы нулевого размера
- •Массивы и производные типы
- •Инициализация массивов Конструкторы
- •Оператор data
- •Встроенные функции для массива
- •Пример упрощения
- •Пример исследования (запроса)
- •Пример конструирования
- •Пример локализации
- •Я Операторы управления
- •Вложения
- •Порядок операторов
- •Синтаксис программы Main
- •Формат представления программы
- •Программные единицы
- •Уровни доступа
- •Дополнения
- •Спецификация входных-выходных параметров
- •Использование модуля
- •Родовые подпрограммы
- •Интерактивный ввод-вывод
- •Простой Input и Output
- •Форматирование по умолчанию
- •Форматированный ввод-вывод I/o
- •Дескрипторы редактора
- •Вещественные - форма с фиксированной точкой
- •Вещественные - экспотенциальная форма
- •Символьные
- •Логические
- •Заполнение пробелами (пропуск символьных позиций)
- •Специальные символы
- •Списки ввода-вывода
- •Производные типы данных
- •Неявный цикл do
- •Ввод-вывод без продвижения
- •Файловый ввод-вывод
- •Номера устройств
- •Операторы read и write
- •Оператор write
- •Оператор open
- •Оператор close
- •Оператор inquirе
- •Динамический массив
- •Распределяемые массивы
- •Спецификация
- •Выделение и возвращение памяти
- •Статус распределяемых массивов
- •Потоки памяти (куча)
- •Что есть указатели?
- •Указатели и адресаты
- •Спецификации указателя Общая форма для операторов определения указателя и адресата такая:
- •Присваивание указателя
- •Разыменование (Dereferencing)
- •Статус (состояние) связи указателя
- •Динамическая память
- •Общие ошибки
- •Указатели в производных типах данных
- •Связанные списки
- •Параметры - указатели
- •Функции для указателей
Использование модуля
Ниже пример очень простой главной программы для тестирования интервальной арифметики . Он из файла interval.f90 или intv.f90.
USE INTERVAL_ARITHMETICS
IMPLICIT NONE
TYPE (INTERVAL) :: A, B, C, D, E, F
A%LOWER = 6.9
A%UPPER = 7.1
B%LOWER = 10.9
B%UPPER = 11.1
WRITE (*,*) A, B
C = A + B
D = A - B
E = A * B
F = A / B
WRITE (*,*) C, D
WRITE (*,*) E, F
END
Запуская эту программу на компьютере Sun с компилятором NAG получили следующий результат на выводе:
% f90 interval_arithmetics.f90 interval.f90
interval_arithmetics.f90:
interval.f90:
% a.out
6.9000001 7.0999999 10.8999996 11.1000004
17.7999992 18.2000008 -4.2000003 -3.7999997
75.2099991 78.8100052 0.6216216 0.6513762
% exit
Мы компилировали программу компилятором f90, и счетная программа была автоматически названа a.out. Прямо с выше приведенным (первый модуль) компиляция работала с SunSoft и компилятором Digital compilers!
Я
PRIVATE и PUBLIC
В модуле некоторые понятия могут быть определены как PRIVATE, которое означает, что программная единица закрывает использования этого понятия извне. В противовес этому может быть использовано явное описание PUBLIC, обычно PUBLIC имеет место по умолчанию. Следующие операторы
PRIVATE
PUBLIC :: VAR1
Объявляют все переменные локальными, но VAR1 глобальный. Заметим, что оба понятия (PUBLIC и PRIVATE) могут быть даны как оператор, например
INTEGER :: IVAR
PRIVATE :: IVAR
Или как атрибут
INTEGER, PRIVATE :: IVAR
Я
Процедуры
Описание всех сторон понятия "процедура" включает следующие разделы
Фактические и формальные параметры |
Переменные в процедуре |
Параметры процедур |
Внутренние процедуры |
SAVE |
Объекты допустимого образа |
Внешние процедуры |
Локальные объекты |
Вид параметра (атрибут INTENT) |
Подпрограммы и функции |
Соответствие параметров |
Ключевые параметры |
Subroutine |
Правила области действия |
Необязательные параметры |
Function |
Связь с хозяином (Host) - глобальные данные |
Процедуры в качестве параметров |
|
Блок взаимодействия |
Рекурсия |
Процедуры это самостоятельные программные единицы, каждая со своим именем, которое служит для обращения к этим единицам. Структура текста процедуры такова
procedure name [(argument list)]
[specification statements]
[executable statements]
...
[CONTAINS
internal procedures]
END procedure [name]
Где вместо procedure может быть одно из слов SUBROUTINE или FUNCTION.
Имеется некоторое различие типов процедур:
•Internal - внутри другой программной единицы
•External - внешняя (возможно на языках, отличных от Fortran 90)
•Module - размещаемая внутри модуля.
Чтобы использовать процедуры (независимо от типа) требуется оператор вызова. Подпрограммы вызываются оператором CALL, а функции вызываются по имени:
CALL name [( список параметров )]
result = name ( [список параметров] )
В обоих случаях управление передается процедуре из вызывающего оператора и возвращается в тот же оператор по выходе из процедуры. Список параметров пуст или несколько переменных или выражений, значения которых используются процедурой. Заметим, что функция должна включать скобки, заключающие список параметров, даже если список пуст.
Из процедур могут быть созданы их множества. Существуют
•встроенные (их в Fortran 90 имеется 113),
•библиотеки, напрмер, NAg fl90 Numerical Library has 300+, BLAS, IMSL, LaPACK, Uniras
•модули, много свободно распространяемых, см. WWW.
Библиотечные процедуры обычно работают быстрее, даже быстрее чем встроенные!
Я
Фактические и формальные параметры
Процедуры могут быть использованы для хорошо определенных задач, использующих доступные им данные. Наиболее общим способом сделать данные доступными процедуре является передача данных в списке параметров при вызове процедуры.
Список параметров это просто несколько переменных или выражений (или имен процедур). Параметр(ы) в вызывающем операторе называются фактическими параметрами; параметры в соответствующем операторе процедуры называются формальными. Фактические и формальные параметры соотносятся с их позицией в списке параметров - первый фактический параметр соотносится с первым формальным параметром, второй фактический параметр соотносится со вторым формальным параметром и т.д. Тип данных, ранг и др. у фактических и формальных параметров должно соответствовать точно.
Когда процедура вызвана, исходные данные копируются из фактических параметров в формальные, и копируются обратно из формальных параметров в фактические при возврате. При изменении значения формального параметра процедура может изменить значение фактического параметра.
•Пример подпрограммы, которая измененяет значения одного или более своих параметров:
REAL, DIMENSION(10) :: a, c
. . .
CALL swap( a,c )
SUBROUTINE swap( a,b )
REAL, DIMENSION(10) :: a, b, temp
temp = a
a = b
b = temp
END SUBROUTINE swap
Подпрограмма swap обменивает содержимое двух массивов типа real. (то есть значения одного массива становятся значениями другого массива)
•Пример функции для генерации одного результата, использующего ее параметры (аргументы):
REAL :: y,x,c
. . .
y = line( 3.4,x,c )
FUNCTION line( m,x,const )
REAL :: line
REAL :: m, x, const
line = m*x + const
END FUNCTION line
Функция line вычисляет значение y путем приравнивания напрямую значения функции line. Имя функции line выступает явно как переменная, и оно должно быть определено с тем же типом, что и y и использует память для значения результата функции.
Заметим, что в обоих примерах имена формальных параметров могут быть одинаковыми с фактическими параметрами или отличными от имен фактических параметров.
Другие правила и особенности оформления формальных и фактических параметров будут рассмотрены ниже в разделе "Параметры процедур".
Я
Внутренние процедуры
Программные единицы (главная программа, внешние процедуры и модули) могут содержать в себе внутренние процедуры. Внутренние процедуры собираются вместе в конце программного модуля после оператора CONTAINS. Программная единица "хозяйничает" (распоряжается) в любых процедурах, которые содержатся в ней. Внутренние процедуры не могут содержать внутри себя других внутренних процедур и не могут включать оператор CONTAINS.
Внутренние процедуры могут быть только вызванными своим хозяином и другими процедурами, внутренними для того же самого хозяина, не смотря на то, что внутренние процедуры могут вызывать другие процедуры (внешние или модуль). Например:
PROGRAM outer
REAL :: a, b, c
. . .
CALL inner( a )
. . .
CONTAINS
SUBROUTINE inner( a ) ! доступна только для outer
REAL :: a ! передается как параметр
REAL :: b=1.0 ! переопределяется
c = a + b ! c соотносится с хозяйской переменной
END SUBROUTINE inner
END PROGRAM outer
Программа outer содержит внутреннюю подпрограмму inner. Заметим, что переменные определены у единицы-хозяина и снова переопределены во внутренней подпрограмме. В примере, не смотря на то, что a, b и c определены в outer:
•Значение a передается как параметр, переопределяемая переменная (формальный параметр), также называемой a. Передаваемое значение то же самое, что и программе outer, переменные a в outer и inner это различные объекты
•Подобно a, переменная b переопределена в подпрограмме и также другой объект чем объект b в хозяйской программе. Значение переменной b не передается параметром и не соотносится с хозяином
•c есть единственный объект, общий для outer и inner, соотносится с хозяином.
В связи с правилами переопределения переменных во избежание ошибок полезно определять все переменные, используемые в процедуре.
Я
Внешние процедуры
Внешние процедуры содержатся в собственных программных единицах (подпрограммах или функциях), которые могут содержать (то есть иметь во владении) внутренние процедуры. Например:
PROGRAM first
REAL :: x
x = second()
. . .
END PROGRAM first
FUNCTION second() ! внешняя
REAL :: second
. . . ! не соотносится с хозяином
END FUNCTION second
Внешние процедуры не имеют хозяина и поэтому не могут разделять данные через соотнесение с хозяином. Передача данных с помощью параметров есть наиболее общий способ разделения данных с внешними процедурами. Внешние процедуры можно вызывать из всех других типов процедур.
Я
Подпрограммы и функции
Подпрограммы (Subroutine)
Рассмотрим следующий пример
PROGRAM Thingy
IMPLICIT NONE
. . . . .
CALL OutputFigures(Numbers)
. . . . ..
CONTAINS
SUBROUTINE OutputFigures(Numbers)
REAL, DIMENSION(:), INTENT(IN) :: Numbers
PRINT*, "Здесь фигуры ", Numbers
END SUBROUTINE OutputFigures
END PROGRAM Thingy
Подпрограмма просто печатает свой аргумент. Внутренние процедуры могут "видеть" все переменные , объявленные в главной программе (и оператор IMPLICIT NONE ). Если внутренняя процедура объявляет переменную, которая имеет то же имя, что и переменная из главной программы, то это объявление определяет новую переменную внутри процедуры.
Используя процедуру можно легко заменить формат вывода. Чтобы затем формат действовал для всех выводов, необходимо сделать замену в строке внутри процедуры.
Внутренние процедуры располагаются между операторами CONTAINS и END PROGRAM и имеют следующий синтаксис
SUBROUTINE < имя подпрограммы >[ (< формальные аргументы >) ]
< объявление формальных аргументов >
< объявление локальных объектов >
...
< выполняемые операторы >
END [ SUBROUTINE [< имя подпрограммы > ] ]
(Заметим, что не все HPF-компиляторы реализуют внутренние подпрограммы.)
Подпрограмма SUBROUTINE может включать вызов других подпрограмм из той же главной программы, из присоединенных модулей или внешних файлов. Заметим, что как главная программа, так и подпрограмма SUBROUTINE должны заканчиваться оператором END. Полезно в конце подпрограммы SUBROUTINE указывать ее имя.
Я
Функции
Рассмотрим пример,
PROGRAM Thingy
IMPLICIT NONE
.....
PRINT*, F(a,b)
.....
CONTAINS
REAL FUNCTION F(x,y)
REAL, INTENT(IN) :: x,y
F = SQRT(x*x + y*y)
END FUNCTION F
END PROGRAM Thingy
Функции размещены между операторами CONTAINS и END PROGRAM . Они имеют синтаксис:
[< префикс >] FUNCTION < имя функции>( [< форм.арг >])
< объявление форм.арг >
< объявление локальных объектов >
...
< вычисляемые операторы, присваивание результата >
END [ FUNCTION [ < имя функции > ] ]
Допускается объявлять тип функции внутри функции вместо заголовка.
Я
Переменные в процедуре
Любые переменные, объявленные в процедуре ( любого типа), вызываются как локальные этой процедуре - они не могут быть использованы вне процедуры, в которой они определены (объявлены). Формальные параметры-переменные всегда локальны в процедуре .
Переменные, объявленные внутри процедуры, обычно существуют только во время выполнения процедуры:
• Какая бы процедурa ни была вызвана, переменные, объявленные в процедуре , "созданы" и для них выделено требуемое место в памяти
• Какая бы процедурa ни существовала, по умолчанию по ее завершении переменные, объявленные в процедуре, "уничтожаются" и любая память, которую процедура имела, будет возвращена снова.
Это "создание" и "уничтожение" переменных процедур означает, что по умолчанию, переменные, объявленные внутри процедуры ,не сохраняют , не помнят значений от одного вызова к другому. Это умолчание может быть преодолено, чтобы позволить локальным переменным помнить их значения от вызова до вызова.
Я
SAVE
Атрибут SAVE заставляет программу помнить значения переменных процедур от одного вызова до следующего вызова. Любые переменные, которым даны начальные значения при их объявлении, имеют атрибут SAVE по умолчанию. Например:
FUNCTION func1( a_new )
REAL :: func1
REAL :: a_new
REAL, SAVE :: a_old ! сохраняемая
INTEGER :: counter=0 ! сохраняемая
...
a_old = a_new
counter = counter+1
END FUNCTION func1
Когда функция вызвана в первый раз, a_old имеет неопределенное значение пока счетчик counter установлен в 0. Эти переменные модифицированы функцией и сохраняемы, так что в любых последовательных вызовах a_old имеет значение предыдущего аргумента и counter это счетчик числа вызовов func1.
Я
Локальные объекты
В процедуре
SUBROUTINE Madras(i,j)
INTEGER, INTENT(IN) :: i, j
REAL :: a
REAL, DIMENSION(i,j):: x
a, и x известны как локальные объекты. Они :
•создаются каждый раз, когда процедура вызывается,
•исчезают, когда процедура завершается,
•не сохраняются их значения между вызовами,
•не используется для них память между вызовами.
x будет вероятно иметь различный размер и образ в каждом вызове.
Место обычно выделяется из программного стека.
Я
Соответствие параметров
Вызов процедуры может быть таким:
CALL OutputFigures(NumberSet)
А ее объявление,
SUBROUTINE OutputFigures(Numbers)
Здесь NumberSet фактический параметр и он соответствует формальному параметру Numbers.
В вызове OutputFigures имя Numbers есть иначе называемый NumberSet. Аналогично рассмотрим
PRINT*, F(a,b)
и
REAL FUNCTION F(x,y)
Фактические параметры a и b соответствуют формальным параметрам x и y.
Значение формального параметра заменяется значением фактического.
Подробнее см. раздел "Параметры процедур".
Я
Правила области действия
Fortran 90 не является традиционным языком с блочной структурой:
•область действия объекта есть программная единица, где он видим и доступен
•внутренние процедуры могут наследовать существующие в главной единице (совокупности).
•объекты, объявленные в модулях, могут быть видимы в ассоциации-пользователе (через оператор USE ) -- используется для глобальных данных;
Я
Связь с хозяином (Host) - глобальные данные
Рассмотрим,
PROGRAM CalculatePay
IMPLICIT NONE
REAL :: Pay, Tax, Delta
INTEGER :: NumberCalcsDone = 0
Pay = ...; Tax = ... ; Delta = ...
CALL PrintPay(Pay,Tax)
Tax = NewTax(Tax,Delta)
....
CONTAINS
SUBROUTINE PrintPay(Pay,Tax)
REAL, INTENT(IN) :: Pay, Tax
REAL :: TaxPaid
TaxPaid = Pay * Tax
PRINT*, TaxPaid
NumberCalcsDone = NumberCalcsDone + 1
END SUBROUTINE PrintPay
REAL FUNCTION NewTax(Tax,Delta)
REAL, INTENT(IN) :: Tax, Delta
NewTax = Tax + Delta*Tax
NumberCalcsDone = NumberCalcsDone + 1
END FUNCTION NewTax
END PROGRAM CalculatePay
Здесь NumberCalcsDone глобальная переменная. Она доступна во всех процедурах главной ассоциации.
Рассмотрим еще один пример
PROGRAM Proggie
IMPLICIT NONE
REAL :: A, B, C
CALL sub(A)
CONTAINS
SUBROUTINE Sub(D)
REAL :: D ! D формальный (соответствующий для фактического параметра A)
REAL :: C ! локальное C (отлично от С из Proggie)
C = A**3 ! A не может быть заменено
D = D**3 + C ! D может быть заменено B = C ! B из Proggie получает новое значение
END SUBROUTINE Sub
END PROGRAM Proggie
В процедуре Sub при выполнении с одной стороны A как параметр будет подставлен вместо D, с другой стороны в операторе
C = A**3
используется значение А из процедуры Proggie, независимо от того, какой фактический параметр использован при вызове Sub.
Есть и другой аспект: А как глобальная величина из процедуры Proggie не может менять значения, но как фактический параметр, соответствующий D, будет перевычислено оператором
D = D**3 + C.
C в Sub отдельное от C в Proggie, замена его значения в Sub не приведет к замене значения C в Proggie.
Я
Блок взаимодействия (Interface Blocks)
Интерфейс происходит всегда, когда одна программная единица вызывает другую. Чтобы работать правильно , программа должна обеспечивать , чтобы фактические параметры в вызове процедуры согласовывались с формальными параметрами этой процедуры. Такой интерфейс проверяется компилятором во время компиляции программы и может быть:
•явным - как в вызове внутренних процедур и процедур модуля, где компилятор может видеть подробности вызова параметров процедуры
•неявным - как в вызове внешних процедур. Здесь компилятор допускает, что детали вызова процедуры и параметры увязаны.
Как бы ни было интерфейс возможно сделать явным. Это может быть сделано с помощью интерфейсного блока:
INTERFACE
Операторы интерфейса
END INTERFACE
Интерфейсный блок для процедуры включается в начало вызывающей программной единицы. Операторы интерфейса содержат копию оператора SUBROUTINE (или FUNCTION), все операторы объхявлений для формальных аргумнетов и оператор END SUBROUTINE (или FUNCTION) . Например:
PROGRAM count
INTERFACE
SUBROUTINE ties(score, nties)
REAL :: score(50)
INTEGER :: nties
END SUBROUTINE ties
END INTERFACE
REAL, DIMENSION(50):: data
...
CALL ties(data, n)
...
END PROGRAM count
SUBROUTINE ties(score, nties)
REAL :: score(50)
INTEGER :: nties
...
END SUBROUTINE ties
Интерфейсный блок в программе count обеспечивает явный интерфейс с подпрограммой ties. Если бы программа count могла бы вызвать другую внешнюю процедуру, ее операторы интерфейса могли бы быть заменены в том же интерфейсном блоке.
Я
Параметры процедур
Объекты допустимого образа
Одно из мощнейших как в использовании процедур так и представлении задачи сделать так, чтобы однажды написанная и протестированная процедура могла быть использованной и повторно использованой как только потребуется. (даже в другой программе).
Поскольку часто имеет место случай, когда программа может хотеть рассматривать массивы или символьные строки различного размера в одной и той же процедуре, Fortran 90 позволяет формальным параметры иметь размер переменных. Такие объекты могут вызывать объекты допустимого образа. Например:
SUBROUTINE sub2(data1, data3, str)
REAL, DIMENSION(:) :: data1
INTEGER, DIMENSION(:,:,:) :: data3
CHARACTER(len=*) :: str
...
Формальные параметры data1 и data3 это массивы, которые могут быть объявлены с рангом, но без размера - задан двоеточием ':' , использованным внутри спецификации размера по каждому измерению. Подобным образом, str имеет не явное задание длины и заимствует длину строки фактического параметра. Когда вызывается подпрограмма sub2, все три формальных параметра принимают размер им соответствующих фактических параметров; все три формальных параметра объекты допустимого образа.
Я
Вид параметра (атрибут INTENT)
Хорошим стилем программирования считается использование
указания компилятору, будет параметр входным или выходным с помощью атрибута INTENT
•только входным (вызываемым) -- INTENT(IN), означает, что формальный параметр ожидает значение при вызове процедуры, но не изменяется процедурой;
•выходным (присваиваемым после использования) -- INTENT(OUT), означает, что формальный параметр не имеет значения при вызове процедуры, но значение будет дано прежде, чем процедура будет завершена;
•и входным и выходным -- INTENT(INOUT) означает, что формальный параметр имеет начальное значение при вызове процедуры, и значение будет изменено процедурой.
SUBROUTINE example(arg1,arg2,arg3)
REAL, INTENT(IN) :: arg1
INTEGER, INTENT(OUT) :: arg2
CHARACTER, INTENT(INOUT) :: arg3
REAL :: r
r = arg1*ICHAR(arg3)
arg2 = ANINT(r)
arg3 = CHAR(MOD(127,arg2))
END SUBROUTINE example
Другой пример:
SUBROUTINE invert(a, inverse, count)
REAL, INTENT(IN) :: a
REAL, INTENT(OUT) :: inverse
INTEGER, INTENT(INOUT) :: count
inverse = 1/a
count = count+1
END SUBROUTINE invert
Подпрограмма invert имеет три формальных параметра: а используется в процедуре, но не меняется в ней, имеет атрибут INTENT(IN); inverse вычисляется в процедуре, имеет атрибут INTENT(OUT), и count (счетчик вызовов) увеличивается процедурой и требует атрибута INTENT (INOUT).
Использование атрибута INTENT рекомендуется, чтобы:
•позволить хорошему компилятору проверить ошибки кодирования,
•выполнить эффективно компиляцию и оптимизацию.
Ключевые параметры
Вместо связывания фактических параметров с формальными только с помощью позиции возможно их связать с помощью имени. Это поможет избежать неприятностей при вызове процедуры часто используется и вызывается несколько встроенных процедур Fortran 90. Например:
SUBROUTINE sub2(a, b, stat)
INTEGER, INTENT(IN) :: a, b
INTEGER, INTENT(INOUT):: stat
...
END SUBROUTINE sub2
Может быть вызвана операторами:
INTEGER :: x=0
...
CALL sub2( a=1, b=2, stat=x )
CALL sub2( 1, stat=x, b=2)
CALL sub2( 1, 2, stat=x )
Имена формальных параметров служат ключевыми словами в операторе вызова. Использование ключевых слов не освобождает от следования порядку параметров, заданных без ключевых слов:
CALL sub2( 1, b=2, 0 ) ! неверно
CALL sub2( 1, stat=x, 2) ! неверно
Когда используются ключевые слова параметров интерфейс между вызывающей программной единицей и процедурой должен быть явным. Заметим также, что параметры с атрибутом INOUT должны быть ассоциированы с переменной и поэтому значение - stat=0 будет неправильным.
Я
Необязательные параметры
Иногда не все параметры требуются при каждом использовании процедуры. Потому некоторые аргументы могут быть специфицированы как необязательные с помощью атрибута OPTIONAL:
SUBROUTINE sub1(a, b, c, d)
INTEGER, INTENT(INOUT):: a, b
REAL, INTENT(IN), OPTIONAL :: c, d
...
END SUBROUTINE sub1
Здесь a и b требуются всегда, когда вызывается процедура sub1. Параметры c и d не обязательны и sub1 можно вызывать так:
CALL sub1( a, b )
CALL sub1( a, b, c, d )
CALL sub1( a, b, c )
Заметим, что порядок, в котором появляются аргументы, важен (без использования ключевых слов), так что не возможно вызвать call sub1 с параметром d, но без параметра c.
CALL sub1( a, b, d ) ! неверно
Необязательные параметры должны располагаться после всех параметров, связанных с позициями в операторе вызова и требуется явный интерфейс.
Возможно проверять, какой или никакой необязательный параметр представлен, когда вызвана процедура с помощью логической встроенной функции PRESENT. Например:
REAL :: inverse_c
IF( PRESENT(c) ) THEN
inverse_c = 0.0
ELSE
inverse_c = 1/c
ENDIF
Если необязательный параметр имеется, то PRESENT возвращает значение .TRUE. . В вышеприведенном примере это использовано для ошибки времени выполнения (деление на 0 будет причиной краха программы 'crash').
Я
Процедуры в качестве параметров
Возможно использовать как фактический параметр в вызове другой процедуры. Часто получается в результате вызова функции, которая использована как фактический параметр другой процедуры. Например:
PROGRAM test
INTERFACE
REAL FUNCTION func( x )
REAL, INTENT(IN) ::x
END FUNCTION func
END INTERFACE
...
CALL sub1( a, b, func(2) )
...
END PROGRAM test
REAL FUNCTION func( x ) ! внешняя
REAL, INTENT(IN) :: x
func = 1/x
END FUNCTION func
Когда вызов sub1 сделан с тремя параметрами a, b и результат функции func(2) - в этом случае возвращаемое значение 1/2. Процедура, которая использована как параметр будет всегда выполняться прежде, чем процедура, в которой оператор вызова появиться. Использование процедуры в качестве параметра требует явного интерфейса.
Заметим, что оператор спецификации для функции func идентифицирует результат типа REAL. Это альтернатива объявлению имени функции как переменной:
REAL FUNCTION func( x )
REAL, INTENT(IN) :: x
func = 1/x
END FUNCTION func
и
FUNCTION func( x )
REAL :: func
REAL, INTENT(IN) :: x
func = 1/x
END FUNCTION func
эквивалентны.
Я
Рекурсия
Fortran 90 допускает рекурсивные подпрограммы (подпрограммы , которые вызывают сами себя). В целях оптимизации рекурсивная подпрограмма должна быть специфицирована ключевым словом RECURSIVE .
Объявление рекурсивной функции имеет отличие в синтаксисе. Должно быть использовано ключевое слово RESULT , специфицирующее имя переменной, хранящей значение результата функции (Ключевое слово RESULT необходимо, чтобы использовать имя функции для возвращения результата. Массив значений рекурсивной функции допустим и в то же время ссылка на рекурсивную функцию будет неразличима от ссылки на массив. Имя функции неявно имеет тот же атрибут , что и имя результата.)
Очевидно, что что рекурсия должна быть объявлена в заголовке:
INTEGER RECURSIVE FUNCTION fact(N) RESULT(N_Fact)
или
RECURSIVE INTEGER FUNCTION fact(N) RESULT(N_Fact)
(Целыми INTEGER будут и fact и N_Fact.)
или,
RECURSIVE FUNCTION fact(N) RESULT(N_Fact)
INTEGER N_Fact
В последнем случае INTEGER N_Fact дает тип величине fact; фактически специфицирует тип fact.
Рекурсия может одного из двух типов:
•Непрямая рекурсия - A вызывает B вызывает A...
•Прямая рекурсия - A вызывает A вызывает A...
обе требуют атрибута RECURSIVE для процедуры A.
Рекурсивные процедуры требуют осторожного управления. Важно обеспечить ограничения самовызова процедуры. Например, рекурсивная процедура factorial, приведенная выше, использует конструкцию IF , чтобы вызвать себя снова или возвратить зафиксированный результат. Потому здесь есть ограничение на количество вызовов процедуры.
Пример рекурсивной функции
RECURSIVE FUNCTION fact( n ) RESULT(N_Fact)
INTEGER, INTENT(IN) :: n
INTEGER :: N_Fact
IF( n==1 ) THEN
N_Fact = 1
ELSE
N_Fact = n*fact( n-1 )
END IF
END FUNCTION fact
Подпрограммы объявляются с помощью заголовка RECURSIVE SUBROUTINE.
Пример рекурсивной подпрограммы
RECURSIVE SUBROUTINE Factorial(N, Result)
INTEGER, INTENT(IN) :: N
INTEGER, INTENT(INOUT) :: Result
IF (N > 0) THEN
CALL Factorial(N-1,Result)
Result = Result * N
ELSE
Result = 1
END IF
END SUBROUTINE Factorial