Пример 3.44. Объявление и инициализация двумерного массива с явным указанием диапазона индексов по каждому измерению
program ARRINIT7
integer, dimension(1:3, 1:3) :: MATRIX data MATRIX /1, 4, 7, 2, 5, 8, 3, 6, 9/ I=1; print*, (MATRIX(I, J), J = 1, 3) I=2; print*, (MATRIX(I, J), J = 1, 3) I=3; print*, (MATRIX(I, J), J = 1, 3) end
При необходимости можно было бы определить матрицу MATRIX как DIMENSION(–1:1, 0:2) с диапазоном индекса строк от минус единицы до плюс единицы (с учетом нуля размерность будет равна трем) и диапазоном столбцов от нуля до двух.
В примерах 3.41 – 3.44 показана инициализация массивов при помощи конструктора инициализации, пригодного только для одномерных массивов. Для того чтобы воспользоваться таким конструктором для инициализации двумерных (и более) массивов, используется функция RESHAPE (пример 3.45).
Пример 3.45. Объявление и инициализация двумерного массива с применением конструктора инициализации и функции преобразования формы program ARRINIT8
integer, dimension(3, 3) :: MATRIX=RESHAPE( (/1, 4, 7, 2, 5, 8, 3, 6, 9/), (/3,3/) ) I=1; print*, (MATRIX(I, J), J = 1, 3)
I=2; print*, (MATRIX(I, J), J = 1, 3) I=3; print*, (MATRIX(I, J), J = 1, 3) end
В простейшем случае эта функция содержит два аргумента (в круглых скобках, через запятую): сам конструктор одномерного массива констант и константу, определяющую форму конечного массива – верхние границы индексов, которые указываются для атрибута DIMENSION, но в упаковке лексем «(/» и «/)».
Возможно объявление и инициализация массивов в стиле Фортран 77 (с сохранением свободного формата записи) с операторами
PARAMETER и DIMENSION (пример 3.46). Это можно проиллю-
стрировать на примере рассмотренных выше массивов: массиваконстанты DIGITS и массива-переменной MATRIX.
156
Пример 3.46. Объявление и инициализация массивов в стиле Фортран 77 при помощи операторов PARAMETER и DIMENSION
program ARRINIT9
integer DIGITS ! MATRIX – объект целого типа по умолчанию dimension DIGITS(10), MATRIX(3,3)
parameter (DIGITS=(/0, 1, 2, 3, 4, 5, 6, 7, 8, 9/) ) data MATRIX /1, 4, 7, 2, 5, 8, 3, 6, 9/
print*, DIGITS
I=1; print*, (MATRIX(I, J), J = 1, 3) I=2; print*, (MATRIX(I, J), J = 1, 3) I=3; print*, (MATRIX(I, J), J = 1, 3) end
В заключение рассмотрим работу с динамическими или, как они называются в Фортране, выделяемыми массивами (пример 3.47). Для объявления выделяемого массива помимо уже известного атрибута DIMENSION требуется еще атрибут – ALLOCATABLE. Ранг массива описывается в атрибуте DIMENSION как шаблон, т.е. на месте диапазонов границ по каждому измерению просто ставится двоеточие (границы при этом не указываются).
Пример 3.47. Объявление и инициализация динамического массива program ARRINIT10
real, dimension(:,:), allocatable :: MATRIX
N=2 |
! В качестве теста берется матрица 2х2 |
ALLOCATE( MATRIX(1:N, 1:N) ) ! Можно оставить только верхние границы |
|
read *, MATRIX |
!Чтение массива. Ввести четыре числа через пробел |
I=1; print*, (MATRIX(I, J), J = 1, 2) I=2; print*, (MATRIX(I, J), J = 1, 2) DEALLOCATE( MATRIX)
end
Память для такого массива выделяется после успешного выполнения оператора ALLOCATE (до этого момента границы массива по каждому измерению остаются неопределенными). В ALLOCATE границы (в данном случае массива MATRIX) описываются в круглых скобках после имен массивов, так же как для атрибута DIMENSION при работе со статическими массивами.
Если выделяемый массив MATRIX больше не нужен, то можно освободить от него память при помощи оператора DEALLOCATE.
157
3.3.7. Производные типы данных
Для обеспечения возможности работы со сложными структурами данных в Фортране 90/95 предусмотрена возможность создания новых (производных) типов данных, на основе встроенных типов. В качестве иллюстрации (пример 3.48) рассмотрим создание производного типа POINT, моделирующего точку на координатной плоскости с вещественными (стандартной разновидности) координатами (X, Y). Скалярный объект производного типа называется структурой, содержащей несколько элементов, которые являются данными встроенных типов и объявляются точно так же, как переменные встроенных типов, но при этом заключены в операторные скобки (TYPE … END TYPE). Для обращения к элементу структуры сначала указывается имя объекта, а затем через разделитель «%» (символ процента ) имя элемента структуры: C%X, C%Y и т.д.
Пример 3.48. Объявление производного типа «Точка на плоскости» program POINTYPE
type POINT real X, Y
end type POINT
type(POINT) , parameter :: A = POINT(1., 2.), B = POINT(3., 4.) type(POINT) C, D
C%X =5.; C%Y =6.; D%X =7.; D%Y =8. print *, A; print *, B; print *, C; print *, D end
Скалярные объекты производного типа, так же как объекты встроенных типов, подразделяются на переменные (как C и D в примере 3.48) и константы A и B (там же).
Как и для встроенных типов, существует понятие буквальных констант, например: POINT(1., 2.) и B = POINT(3., 4.). Буквальная константа встроенного типа определяется как список (через запятую) констант, являющихся значениями элементов структуры объекта – этот список записывается в круглых скобках после имени производного типа.
Пример 3.49. Объявление производного типа «Вектор» program VECTYPE
! Объявление производных типов
158
type POINT real X, Y
end type POINT type VECTOR
type (POINT) P1, P2 end type VECTOR
! Объявление и инициализация переменных производных типов type (POINT), parameter :: A = POINT(1., 2.), B = POINT(3., 4.) type (VECTOR) :: AB =VECTOR(A, B), &
CD = VECTOR( POINT(3., 4.), POINT(2., 1.)) type (VECTOR) EF
EF%P1%X =5.; EF%P1%Y =6.; EF%P2%X =7.; EF%P2%Y =8.; print *, AB; print *, CD
end
Производный тип может быть определен как через встроенные типы, так и через ранее определенные производные типы. В качестве примера можно, используя точки на координатной плоскости (тип POINT), определить тип VECTOR как пару точек P1 и P2 на координатной плоскости (пример 3.49).
В приведенном примере заданы три объекта типа VECTOR – векторы AB, CD и EF. Первый из них (вектор AB) инициализирован двумя предварительно определенными именованными константами A и B типа POINT, второй (вектор CD) – двумя буквальными константами того же типа. Третий (вектор EF) инициализирован по компонентам: поскольку вектор EF, как и любой объект типа VECTOR, имеет элементы структуры P1 и P2, каждый из которых – компоненты X и Y, то необходимо инициализировать ком-
поненты EF%P1%X, EF%P1%Y и т.д.
Стоит отметить, что, используя атрибут PARAMETER (см. п. 3.3.6), можно объявлять массивы производных типов. Массивы также могут являться элементами структуры объектов производного типа, при этом единичный объект (производного типа), в состав которого входит массив, считается скалярным объектом.
159
3.4. ВЫРАЖЕНИЯ И ПРЕОБРАЗОВАНИЕ ТИПОВ
3.4.1. Скалярное присваивание
Если с точки зрения элементарной математики запись X=X+1, констатирующая равенство левой и правой части, не имеет смысла ввиду отсутствия значения X, удовлетворяющего такому уравнению, то для программирования такая запись имеет важный практический смысл. Символ «=» (знак равенства в математике) используется в таких языках, как Фортран, Си и ряде других, для того, чтобы записать значение выражения X+1 (вычисленного для текущего значения переменной) в ячейку памяти X. Тем самым текущее значение переменной X заменяется новым, равным величине текущего значения X, увеличенного на единицу или, как говорят, переменной X, посредством оператора присваивания «=», присваивается новое значение, равное X+1.
Действие оператора присваивания наглядно иллюстрируется примером 3.50. После инициализации вещественной переменной X нулем ее значение три раза подряд инкрементируется (увеличивается на единицу), т.е. берется текущее значение X, к нему добавляется единица и получившееся значение записывается в переменную X посредством оператора присваивания. С помощью этого оператора можно присваивать значения переменным и именованным константам всех встроенных типов Фортрана.
Пример 3.50. Иллюстрация работы оператора присваивания program ASSIGN
real :: X=0; print*, X X=X+1; print*, X X=X+1; print*, X X=X+1; print*, X end
Рассмотрим общую форму скалярного числового присваивания, она имеет вид: ПЕР = ВЫР, и подразумевает, что переменной ПЕР присваивается значение, полученное в результате вычисления выражения ВЫР (под выражением может подразумевается не только какая-либо вычислительная формула но и переменная, а также именованная или буквальная константа).
160