Границы размерностей массивов - формальных параметров могут определяться передаваемыми в процедуру
значениями других параметров. Так, в рассмотренной в разд. 6.3.1 задаче пользовательская функция md
имеет синтаксис
result = md(d,n)
где d - массив - формальный параметр заданной формы; an- целочисленный скаляр, используемый
для задания размера массива d.
функция вызывается 3 раза:
а = md(a, na); mb = md(b, nb); me = md(c, nc)
При каждом вызове фактическим параметром является массив той же формы, что
и массив - формальный параметр. Передаваемые размерности пассивов имеют разные значения.
Однако форма ассоциируемых при вызове процедуры массивов фактических и формальных
параметров может различаться, что позволяет в ряде случаев упростить написание программы.
Так это происходит при создании подпрограммы обмена содержимого двух многомерных массивов:
integer, parameter :: n = 5, m = 10, k = m*n
real a(m, n) /k*1.0/, b(m, n) /k*2.0/
call swap(a, b, m, n)
write(*, *) b
end
subroutine swap(a, b, m, n)
integer m, n
real a(m*n), b(m*n) ! а и b – массивы заданной формы)
real c(size(a)) ! с - автоматический массив
с = а
a= b
end subroutine swap
В общем случае для формального параметра - массива могут вычисляться как нижняя,
так и верхняя границы размерности. Общий вид размерности таких массивов:
[нижняя граница] : [верхняя граница]
Нижняя и верхняя границы - целочисленные описательные выражения. Вычисленные
границы массива фиксируются на время выполнения процедуры и не меняются при
изменении значения соответствующего описательного выражения.
При работе с такими массивами необходимо следить, чтобы размер массива - формального
параметра не превосходил размера ассоциированного с ним массива - фактического параметра.
Если фактическим параметром является многомерный массив и соответствующим ему формальным
параметром является массив заданной формы с тем же числом измерений, то для правильного
ассоциирования необходимо указать размерности массива - формального параметра такими же,
Как и у массива - фактического параметра. Исключение может составлять верхняя граница последней
размерности массива, которая может меньше соответствующей границы массива - фактического параметра.
Если в качестве фактического параметра задан элемент массива, т формальный параметр
ассоциируется с элементами массива-родителя начиная с данного элемента и далее по порядку.
Такие массивы - формальные параметры перенимают форму у соответствующего фактического
параметра. В результате ранг и форма фактического и формального параметров совпадают. При описании
формы формального параметра каждая размерность имеет вид: [нижняя граница] :
где нижняя граница - это целое описательное выражение, которое може! зависеть от данных в процедуре
или других параметров. Если нижняя граница опущена, то ее значение по умолчанию равно единице.
Например» ПРИ вызове
real х(0:3, 0:6, 0:8)
interface
subroutine asub(a)
real a(:, :, :)
end interface
call asub(x)
Соответствующий перенимающий форму массив объявляется так:
prnt *, lbound(a, 3), ubound(a, 3) ! 1 9
Так как нижняя граница в описании массива а отсутствует, то после вызова подпрограммы в ней будет
определен массив а(4, 7, 9). Если нужно сохранить соответствие границ, то массив а следует объявить так:
real a(0:, 0:, 0:)
В интерфейсном блоке по-прежнему массив а можно объявить:
real а(:, :, :)
Процедуры, содержащие в качестве формальных параметров перенимающие форму массивы,
должны обладать явно заданным интерфейсом.
Сортировка
Основное назначение сортировки - обеспечить быстрый поиск данных. Помимо этого, в отсортированном
файле или массиве гораздо быстрее выполнять многие вычисления.
Сортировка методом пузырька
Сортировка методом пузырька наиболее проста для реализации, но имеет по сравнению
с другими методами наименьшую вычислительную эффективность.
Не теряя общности, будем для простоты изложения в дальнейшем рассматривать задачу
сортировки массива х целых чисел, в котором первые я чисел должны быть
отсортированы так, чтобы хi <= Xj для 1 <=i <= j <= п.
Идея сортировки методом пузырька состоит в том, чтобы просмотреть массив последовательно
несколько раз. Один просмотр состоит из сравнения каждого элемента массива со следующим
за ним элементом (xi сравнивается с xj+1) и обмена этих двух элементов,
если они располагаются не в нужном порядке (если Xi >xi+1)
Рассмотрим массив х
25 37 12 33 48 57 92 86
В нем число 48 характеризуется тем, что, во-первых, все расположенные левее него числа меньше 48
и, во-вторых, числа, расположенные правее него больше 48. Назовем такое число разделителем массива
. Нетрудно понять, что теперь мы можем отдельно решать задачу сортировки для чисел до разделителя
и для чисел после него. Кроме того, сам разделитель находится в нужной позиции, то есть в
дальнейшей сортировке он уже не рассматривается.
Размещаемые массивы
рассмотренный массив marks является статическим - его размер не может быть изменен в процессе вычислений,
поэтому мы вынуждены задать 6го размер с некоторым запасом (чтобы иметь возможность использовать массив
для любой студенческой группы). Это приводит к тому, что программа, как правило, занимает больше памяти,
чем это требуется на самом деле. Подобного перерасхода памяти можно избежать, если применить динамический
массив и каждый раз выделять под него столько памяти, Сколько нужно. Работа с динамическим массивом происходит так:
выполняется объявление размещаемого массива. В отличие от статических размещаемые массивы объявляются с атрибутом ALLOCATABLE.
Кроме того, каждое измерение размещаемого массива задается в виде
двоеточия, например: integer, allocatable, dimension(:) :: marks
определяется размер массива;
· оператором ALLOCATE выделяется память под массив;
· после выполнения вычислений выделенная память освобождается. Это
· выполняется оператором DEALLOCATE;
· после этого массиву вновь может быть выделена свежая область памяти.
При размещении массива параметр STAT= позволяет узнать, удалось ли разместить массив.
Этот параметр может быть опущен, но тогда любая неудача при выделении памяти приведет к ошибке этапа исполнения и остановке
программы. Параметр указывается в операторе ALLOCATE последним. При удачном выделении памяти целочисленная статусная переменная
ierr возвращает нуль, в противном случае возвращается код ошибки размещения. Причиной ошибки может быть, например,
недостаток памяти или "попытка разместить ранее размещенный и не освобожденный оператором DEALLOCATE объект.
Аналогичную роль играет необязательный параметр STAT= и в операторе DEALLOCATE.
Сечение массива
В Фортране можно получить доступ не только к отдельному элементу массива, но и к некоторому подмножеству его элементов.
Такое подмножество элементов массива называется сечением массива. Сечение массива может быть получено в результате применения
индексного триплета или векторного индекса, которые при задании сечения подставляются вместо одного из индексов массива.
Индексный триплет имеет вид: [нижняя граница] : [верхняя граница] [.шаг]
Каждый из параметров триплета является целочисленным выражением. Шаг изменения индексов может быть и положительным и
отрицательным, но не может равняться нулю. Все параметры триплета являются необязательными.
Индексный триплет задает последовательность индексов, в которой первый элемент равен его нижней границе,
а каждый последующий больше (меньше) предыдущего на величину шага. В последовательности находятся все
задаваемые таким правилом значения индекса, лежащие между границами триплета. Если же нижняя граница больше
верхней и шаг положителен или нижняя граница меньше верхней и шаг отрицателен, то последовательность является пустой.
Пример. real a(1:10);,
а(3:7:2) = 3.0 ! Триплет задает сечение массива с элементами ! а(3), а(5), а(7), которые получат значение 3.0 а(7:3:-2) = 3.0 ! Элементы а(7), а(5), а(3) получат значение 3.0