Аверянов Введение в оператсионные системы и основы программирования 2015
.pdf3.7. ПРОГРАММНЫЕ КОМПОНЕНТЫ И ЭЛЕМЕНТЫ ООП
3.7.1.Структура программных компонентов
Впростейшем случае программа на Фортране может состоять из одной главной программы, находящейся в файле с соответствующим расширением (для компилятора Gfortran это .f95). При этом она может состоять даже из одного единственного оператора END. Операторы PROGRAMM … END являются операторными скобками, ограничивающими последовательность операторов главной программы, при этом оператор PROGRAMM – не обязательный (хотя настоятельно рекомендуемый, особенно для программ, предъявляемым сторонним заказчикам, к которым стоит отнести и преподавателя на зачете).
Сучетом синтаксиса Фортрана 90/95, структуру главной программы упрощенно можно представить в виде:
PROGRAM имя программы операторы описания исполняемые операторы
CONTAINS
внутренние подпрограммы END имя программы
К операторам описания относятся объявления скалярных переменных и констант, а также объявление массивов и описание производных типов (п. 3.3). В исполняемые входят операторы ввода/вывода данных, управляющие операторы, присваивания и выражения всех встроенных и производных типов, а также использования программных компонентов.
Оператор CONTAINS используется только при наличии внутренних подпрограмм (п. 3.7.3), а имя главной программы после оператора END так же необязательно, как и оператор PROGRAM.
Программные компоненты подразделяются на подпрограммы-
процедуры (SUBROUTINE), подпрограммы-функции (FUNCTION)
и модули (MODULE). Каждый модуль (MODULE) должен размещаться в отдельном файле, а расположение и группировка по фай-
201
лам внешних подпрограмм, как процедур (SUBROUTINE), так и функций (FUNCTION), не являющихся компонентами модулей, не регламентирована, т.е. полностью на усмотрении программиста: в одном файле с главной программой или в отдельных файлах При этом исходные файлы, содержащие внешние подпрограммы и модули, должны иметь расширение .f95 (для Gfortran).
Все программные компоненты Фортрана, т.е. подпрограммыпроцедуры, подпрограммы-функции и модули, имеют одинаковую структуру (табл. 3.11).
Таблица 3.11. Структура программных компонентов
Оператор PROGRAM, SUBROUTINE, FUNCTION или MODULE
Операторы USE (4. 3.7.4)
|
Оператор IMPLICIT NONE |
Операторы IMPLICIT |
||
|
|
|||
|
|
Операторы |
описания: |
|
Операторы FORMAT |
Операторы PARAMETER |
объявления |
переменных |
|
и DATA |
и констант, массивов, |
|||
|
описание |
|
производных |
|
|
|
|
||
|
|
типов, |
интерфейсных |
|
|
|
блоков модулей |
||
|
Исполняемыеоператоры |
|
|
|
Оператор CONTAINS |
|
|
|
|
Внутренние или модульные (для MODULE) подпрограммы |
|
|
||
Оператор END |
|
|
|
|
3.7.2. Внешние подпрограммы
Внешние подпрограммы служат для выполнения определенной задачи в рамках основной программы, а также используются во избежание повторения одинаковых блоков операторов. В Фортране существует два вида внешних подпрограмм – подпрограммы-
процедуры и подпрограммы-функции. Оба вида подпрограмм име-
ют практически одинаковую структуру:
SUBROUTINE имя процедуры (список формальных параметров) описание формальных параметров описание внутренних параметров исполняемые операторы
202
CONTAINS
внутренние подпрограммы END имя процедуры
или
тип функции FUNCTION имя функции (список формальных параметров)
описание формальных параметров описание внутренних параметров исполняемые операторы
CONTAINS
внутренние функции END подпрограммы-процедуры
Подпрограмма-процедура ограничена операторными скобками (SUBROUTINE … END), а подпрограмма-функция операторными скобками (FUNCTION … END).
После имени подпрограммы в круглых скобках указывается список формальных параметров, которые передаются в подпрограмму при ее вызове. Формальные параметры, переданные в под- программу-процедуру, изменяются алгоритмом процедуры и возвращаются в программную компоненту, из которой была вызвана подпрограмма.
Подпрограмма-процедура может вернуть в вызывающую программу только список формальных параметров, для ее вызова используется оператор CALL (пример 3.94).
Пример 3.94. Подпрограмма-процедура, складывающая два числа program SUBPRG1
real :: X=1., Y=2., Z call SUMAB(X, Y, Z) print *, Z
end
subroutine SUMAB(A,B,C) real :: A, B, C
C = A + B return end
203
Подпрограмма-функция может использоваться в вызывающей программе аналогично переменной соответствующего типа (пример 3.95), в том числе в выражениях и присваиваниях, для этого функция должна быть объявлена внешней с помощью оператора EXTERNAL. Точно также используется внутри подпрограммыфункции ее имя – переменной соответствующего типа, но перед завершением работы подпрограммы-функции эта переменная должна получить значение, которое вернется в вызывающую программу. При этом подпрограмма-функция, как и подпрограммапроцедура, может изменять значения элементов списка формальных параметров (но этого делать не рекомендуется).
Пример 3.95. Подпрограмма-функция, складывающая два числа program SUBPRG2
external SUM
real :: X=1., Y=2., Z Z = SUM(X, Y) print *, Z
end
real function SUM(A,B) real :: A, B
SUM = A + B return
end
Возврат управления в вызывающую процедуру осуществляется оператором RETURN, а если в силу каких-то причин необходимо прекратить работу программы в целом, то можно воспользоваться оператором STOP.
Если в подпрограмме (процедуре или функции) предполагается обработка массива, то ранги (размерности) массивов в вызывающей и вызываемой программной компоненте должны совпадать, а экстенты (количество элементов по каждому измерению) должны передаваться через список формальных параметров (пример 3.96).
Пример 3.96. Передача массивав подпрограмму program SUBPRG3
integer, parameter :: M=1, N=2 integer , dimension(M,N) :: A, B, C data A /1, 2/ B /3, 4/
call SUMARR(A, B, C, M, N)
204
print *, C end
subroutine SUMARR(X,Y, Z, K, L) integer , dimension(K, L) :: X,Y, Z Z = X+Y
return end
Формальные параметры подпрограммы должны быть объявлены в разделе описания, или к ним будут применены правила по умолчанию для имен переменных. При вызове подпрограммы в список формальных параметров предаются соответствующие фактические параметры. Списки формальных и фактических должны иметь строгое поэлементное соответствие в отношении данных. Скаляру должен соответствовать скаляр того же типа, массиву – массив, а функции – функция.
Одноименные переменные в списках формальных и фактических параметров программ и подпрограмм ни как не связаны друг с другом, поскольку являются внутренними переменными своих программ и подпрограмм (пример 3.97).
Пример 3.97. Независимость имен (A иB) в программных компонентах program SUBPRG4
external SUM real :: A=1., B=2.
print *, SUM (A, B) end
real function SUM(A, B) real :: A, B
SUM = A + B return
end
3.7.3. Внутренние подпрограммы
Внутренние подпрограммы (процедуры и функции) по структуре и способу применения ничем не отличаются от внешних подпрограмм (см. п. 3.7.2). Однако это не отдельная программная компонента, а составная часть главной программы или внешней подпрограммы. Хотя внутренние подпрограммы не могут иметь собственных внутренних подпрограмм, они имеют доступ ко всем объ-
205
ектам своего носителя, в том числе могут вызывать его другие внутренние подпрограммы (пример 3.98).
Внутренние подпрограммы располагаются внутри своих носителей (в главной программе или во внешних подпрограммах) последовательно одна за другой.
Последовательность внутренних подпрограмм находится в блоке операторов сразу после оператора CONTAINS и заканчивается оператором END программной компоненты-носителя.
Пример 3.98. Пример внутренней подпрограммы program SUBPRG5
real :: A=1., B=2., C print *, SUM(A, B) contains
real function SUM(A, B) real :: A, B
SUM = A + B return
end end
3.7.4.Модули как библиотеки производных типов
ВФортране 90/95 модули используются для хранения глобальных данных и как контейнер производных типов. В данном учебном пособии рассматривается именно последнее назначение модулей. В контексте использования модуля как контейнера производных типов его структура имеет общий вид:
MODULE имя модуля описание производных типов
описание интерфейсов внутренние подпрограммы модуля
CONTAINS
внутренние подпрограммы модуля END имя модуля
В качестве примера рассмотрим создание производного типа VECTOR, обеспечивающего работу с векторами, лежащими на плоскости (x, y), и начало каждого вектора совпадает с началом координат (0, 0). Каждый такой вектор может быть описан конечной
206
точкой с координатами (X, Y). В соответствии с правилами векторной алгебры и аналитической геометрии могут быть описаны такие операции над векторами, как умножение вектора на число, сумма (разность) и т.д. В качестве примера реализуем операцию сложения данных типа VECTOR так, чтобы для трех векторов этого типа A, B и C с точки зрения Фортрана была правомерна операция сложения «C=A+B». Это означает, что нужно создать задаваемую ска-
лярную операцию сложения с обозначением «+» для производного типа данных VECTOR.
Дело в том, что для производных типов данных не существует заведомо определенных операций – доступны операции только с элементами структуры, поскольку они являются данными встроенных типов, и для них определены соответствующие покомпонентные операции, что-то вроде:
C%X = A%X + B%X
C%Y = A%Y + B%Y
Модуль с реализацией типа VECTOR и векторной арифметики
(см. пример 3.19) так и называется: VECTOR_ARITHMETIC.
Описание производных типов следует в модулях сразу после заголовка. Тип VECTOR объявлен в соответствии с правилами объявления производных типов (см. п. 3.3.7) и имеет в своей структуре два вещественных компонента – X и Y, или в геометрической интерпретации координаты конца вектора.
Для создания операции сложения для элементов типа VECTOR нужно сделать две вещи – написать функцию, которая будет заниматься покомпонентным сложением, и связать ее с интерфейсом виде знака «плюс» (если не нравится «плюс», можно использовать обозначение любой встроенной операции Фортрана или последовательность букв, не длиннее 31, ограниченную точками, предположительно .PLUS.).
Тип функции сложения (ADD_VECTORS – название произвольное) и возвращаемое ею значение должно быть таким же, как у слагаемых A и B, т.е. VECTOR.
Поскольку операция сложения – бинарная, то входными параметрами функции с атрибутом INTENT(IN) объявлены два входных параметра: A и B.
207
При описании унарной операции потребуется только один входной параметр.
Функция ADD_VECTORS реализует операцию сложения на компонентном уровне: ADD_VECTORS%X = A%X +B%X и т.д.,
поскольку компоненты типа VECTOR являются вещественными и для них определена операция сложения вещественных чисел, а ин-
терфейсный блок (INTERFACE ... END INTERFACE) связывает функцию ADD_VECTORS, являющуюся внутренней модульной процедурой, с оператором «плюс».
Любой модуль должен располагаться в отдельном файле, название которого должно совпадать с названием модуля, а расширение зависит от компилятора – для компилятора Gfortran созданный модуль VECTOR_ARITHMETIC должен быть помещен в отдельный файл c именем vector_arithmetic и расширением .f95. Ограничений на имена программ и программных компонентов, использующих модули, не существует.
Пример 3.99. Использование модуля в программе program VECTOR_TEST
use VECTOR_ARITHMETIC
type (VECTOR) :: A = VECTOR(1., 2.), B = VECTOR(3., 4.), C C = A + B
print*, A; print*, B; print*, C end
Чтобы использовать модуль в других программе и программных компонентах, необходимо объявить об его использовании при помощи оператора USE (пример 3.99). Подключив таким образом модуль VECTOR_ARITHMETIC, можно объявлять переменные типа VECTOR, не описывая структуру типа, и применять к переменным операции, определенные в модуле.
Два файла – с модулем и тестирующей программой, необходимо правильно скомпилировать для получения запускаемой программы, для этого необходимо внимательно изучить специально посвященный этому п. 3.2.4.
В качестве упражнения и тренировки работы с модулями полезно дополнить созданный модуль VECTOR_ARITHMETIC другими такими стандартными векторными операциями, как скалярное и векторное произведение и т.д.
208
3.7.5. Встроенные функции Фортрана
|
|
НЕКОТОРЫЕ СПРАВОЧНЫЕФУНКЦИИ |
|
|
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Функция |
|
Тип |
|
|
|
Тип аргумента |
|
|
Действие |
|
||||
|
|
функции |
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
Возвращает |
ми- |
||||
|
|
|
|
|
|
Количество |
|
||||||||
|
selected_int_kind(R) |
Стандартный |
|
|
|
нимально |
|
воз- |
|||||||
|
|
|
знаков |
integer |
|
можное значение |
|||||||||
|
integer |
|
|
|
|||||||||||
|
|
|
|
|
числа |
|
|
|
KIND |
для |
R |
– |
|||
|
|
|
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|
значного целого |
|
|||
|
|
|
|
|
|
|
|
|
|
|
Возвращает |
ми- |
|||
|
|
|
Стандартный |
|
|
Количество зна- |
|
нимально |
|
воз- |
|||||
|
selected_real_kind(R, P) |
|
|
|
можное значение |
||||||||||
|
integer |
|
|
ков и |
степень |
|
KIND |
для |
R |
– |
|||||
|
|
|
|
|
real числа |
|
|||||||||
|
|
|
|
|
|
|
значного |
real |
в |
||||||
|
|
|
|
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
степени P |
|
|
|
|
|
kind(X) |
|
Стандартный |
|
|
Любой |
|
|
|
значение |
|
KIND |
|||
|
|
integer |
|
|
встроенный тип |
|
аргумента X |
|
|||||||
|
|
|
|
|
|
|
|||||||||
|
|
|
Совпадает |
с |
|
Числовой |
тип |
|
Модуль |
макси- |
|||||
|
|
|
|
|
мального |
значе- |
|||||||||
|
huge(X) |
|
типом |
|
|
любой |
|
|
|
ния |
для |
|
чисел |
||
|
|
|
аргумента |
|
|
разновидности |
|
данной |
разно- |
||||||
|
|
|
|
|
|
|
|
|
|
|
видности типа |
|
|||
|
|
|
Совпадает |
с |
|
Числовой |
тип |
|
Модуль |
мини- |
|||||
|
|
|
|
|
мального |
значе- |
|||||||||
|
tiny(X) |
|
типом |
|
|
любой |
|
|
|
ния |
для |
|
чисел |
||
|
|
|
аргумента |
|
|
разновидности |
|
данной |
разно- |
||||||
|
|
|
|
|
|
|
|
|
|
|
видности типа |
|
|||
|
|
НЕКОТОРЫЕ ФУНКЦИИ ПРЕОБРАЗОВАНИЯ |
|
|
|
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Функция |
|
Тип |
|
|
|
Тип аргумента |
|
|
Действие |
|
||||
|
|
функции |
|
|
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
integer для це- |
|
|
|
Числовой тип |
|
Возвращает |
|
|
||||
|
abs(X) |
|
лого аргумента |
|
|
|
|
|
|||||||
|
|
и real для ос- |
|
|
|
любой |
|
|
|
модуль |
|
|
|
||
|
|
|
|
|
|
разновидности |
|
аргумента |
|
|
|
||||
|
|
|
тальных |
|
|
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
real с парамет- |
|
|
|
|
|
|
|
Возвращает |
|
|
||
|
aimag(Z) |
|
ром разновид- |
|
|
comlex |
|
|
|
мнимую часть |
|
||||
|
|
ности типа как |
|
|
|
|
комплексной |
|
|||||||
|
|
|
уаргумента |
|
|
|
|
|
|
|
величины |
|
|
|
|
|
|
|
Совпадает с |
|
|
|
real любой |
|
Отбрасывает |
|
|||||
|
|
|
|
|
|
|
дробную часть |
|
|||||||
|
aint(X [, KIND]) |
|
типом |
|
|
|
поддерживаемой |
|
|
||||||
|
|
|
|
|
|
числа, не изме- |
|
||||||||
|
|
|
аргумента |
|
|
|
разновидности |
|
няя тип |
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||
|
|
|
209 |
|
|
|
|
|
|
|
|
|
|
|
МАТЕМАТИЧЕСКИЕ ФУНКЦИИ
|
Функция |
|
Тип |
|
|
Тип аргумента |
|
|
Действие |
|
|
|
функции |
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Совпадает с |
|
|
real любой |
|
Возвращает бли- |
||
|
anint(X [, KIND]) |
типом |
|
|
поддерживаемой |
|
жайшее целое, как |
|||
|
|
|
аргумента |
|
|
разновидности |
|
real |
||
|
|
|
|
|
|
real любой |
|
Возвращает бли- |
||
|
ceiling(X) |
integer |
|
|
поддерживаемой |
жайшее целое |
||||
|
|
|
|
|
|
разновидности |
справа от X |
|||
|
|
|
|
|
|
real любой |
|
Преобразует пару |
||
|
cmplx(X[, Y]) |
complex |
|
|
поддерживаемой |
|
чисел real (или |
|||
|
|
|
|
|
|
разновидности |
|
одно) в comlex |
||
|
|
|
|
|
|
real любой |
|
Возвращает бли- |
||
|
floor(X) |
integer |
|
|
поддерживаемой |
жайшее целое |
||||
|
|
|
|
|
|
разновидности |
слева от X |
|||
|
|
|
|
|
|
real любой |
|
Преобразует к |
||
|
int(X[, KIND]] |
integer |
|
|
поддерживаемой |
|
целомутипураз- |
|||
|
|
|
|
|
|
разновидности |
|
новидности KIND |
||
|
|
|
|
|
|
real любой |
|
Возвращает |
||
|
nint(X) |
integer |
|
|
поддерживаемой |
|
||||
|
|
|
|
|
|
разновидности |
|
ближайшее целое |
||
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
real иinteger |
|
Преобразует к |
||
|
|
|
|
|
|
|
вещественному |
|||
|
real(X[, KIND]] |
real |
|
|
любой разно- |
|
типузаданной |
|||
|
|
|
|
|
|
видности |
разновидности |
|||
|
|
|
|
|
|
|
|
KIND |
||
|
|
|
Совпадает с |
|
|
real любой |
|
Возвращает зна- |
||
|
|
|
|
|
|
чение функции |
||||
|
acos(X) |
типом |
|
|
поддерживаемой |
|
||||
|
|
|
аргумента |
|
|
разновидности |
|
арккосинуса: |X| ≤ |
||
|
|
|
|
|
1 |
|
||||
|
|
|
|
|
|
|
|
|
||
|
|
|
Совпадает с |
|
|
real любой |
|
Возвращает зна- |
||
|
asin(X) |
типом |
|
|
поддерживаемой |
|
чение функции |
|||
|
|
|
аргумента |
|
|
разновидности |
|
арксинуса: |X| ≤ 1 |
||
|
|
|
Совпадает с |
|
|
real любой |
|
Возвращает зна- |
||
|
|
|
|
|
|
чение функции |
||||
|
atan(X) |
типом |
|
|
поддерживаемой |
|
||||
|
|
|
аргумента |
|
|
разновидности |
|
арктангенса: |X| ≤ |
||
|
|
|
|
|
1 |
|
||||
|
|
|
|
|
|
|
|
|
||
|
|
|
Совпадает с |
|
|
real любой |
|
Главное значение |
||
|
atan2(X,Y) |
типом |
|
|
поддерживаемой |
|
аргумента ком- |
|||
|
|
|
аргумента |
|
|
разновидности |
|
плексного числа |
||
|
|
|
Совпадает с |
|
|
real и complex |
|
Значение |
||
|
cos(X) |
типом |
|
|
любой разно- |
|
||||
|
|
|
|
функции косинуса |
||||||
|
|
|
аргумента |
|
|
видности |
|
|||
|
|
|
|
|
|
|
|
|||
|
|
|
|
210 |
|
|
|
|
|