Справочное руководство по языку Fortran 95

перевод Балуева А. Н.

Оглавление

Глава 1. Элементы Fortran

Данные

В начало страницы

Fortran предлагает программисту различные способы хранения данных и ссылок на них. Можно ссылаться на данные буквально, как в вещественных числах 4.73 и 6.23E5, в целых -3000 и 65536, или в CHARACTER литерале "Continue (y/n)?". Или вы можете хранить и ссылаться на разные переменные данные, используя имена, такие как x или y, DISTANCE_FROM_ORIGIN или USER_NAME. Постоянные, такие как pi или скорость света, могут задаваться именами и постоянными значениями. Можно хранить данные в фиксированного размера области в памяти или отводить для них память, когда программа в этом нуждается. Наконец, Fortran предлагает различные средства создания, хранения и ссылки на структурированные данные с помощью массивов, указателей и производных типов.

Встроенные типы данных

Пять встроенных типов данных есть INTEGER, REAL, COMPLEX, LOGICAL и CHARACTER. Тип DOUBLE PRECISION доступный в Fortran 77 также поддерживается, но рассматривается как подмножество или разновидность данных типа REAL.

Разновидность

В Fortran встроенный тип данных имеет одну или более разновидностей. В LF95 для типов CHARACTER, INTEGER, REAL и LOGICAL параметр разновидности ( число, используемое при ссылке на разновидность) соответствует количеству байтов, используемых для представления разновидности. Для данных типа COMPLEX значение параметра есть количество байтов для представления вещественной или мнимой части. Имеются две встроенные справочные функции, SELECTED_INT_KIND и SELECTED_REAL_KIND. Каждая выдает значение параметра разновидности на основании требуемых диапазона и точности объекта данных в форме, переносимой на другие Fortran 90 или 95 системы. Разновидности, доступные в LF95, перечислены в следующей таблице:

Таблица 1: Встроенные типы данных
Тип Параметр
разновидности
Диапазон и точность
INTEGER 1 Диап.: -128    127
INTEGER 2 Диап.: -32.768   32.767
INTEGER 4* Диап.: -2.147.483.648   2.147.483.647
INTEGER 8 Диап.: -9.223.372.036.854.775.808
9.223.372.036.854.775.807
REAL 4* Диап.: 1.18 * 10-38   3.40 * 1038
Точность: 7-8 дес. цифр>
REAL 8 Диап.: 2.23 * 10-308  1.79 * 10308
Точность: 15-16 дес. цифр
REAL 16 Диап.: 10-4931  104932
Точность: прибл.33 дес. цифры
COMPLEX 4* Диап.: 1.18 * 10-38    3.40 * 1038
Точность: 7-8 дес. цифр
COMPLEX 8 Диап.: 2.23 * 10-308    1.79 * 10308
Точность: 15-16 дес. цифр
COMPLEX 16 Диап.: 10-4931    104932
Точность прибл. 33 дес. цифры
LOGICAL 1 Значения: .TRUE. и .FALSE.
LOGICAL 4* Значения: .TRUE. и .FALSE.
CHARACTER 1* ASCII character set

"*" отмечает значения по умолчанию
Длина

Количество символов в объекте типа CHARACTER указывается его параметром длины типа. Например, CHARACTER литерал "Half Marathon" имеет длину тринадцать.

Данные типа Literal

Данные этого типа, называемые также literal, literal constant или непосредственная константа, характеризуются как указано далее для всех типов данных Fortran. Синтаксис литеральных констант определяет их встроенный тип.

Литералы INTEGER

Целый литерал состоит из одного или более символов с необязательным начальным знаком
(+ или -) и необязательными подчеркиванием и параметром разновидности в конце. Если подчеркивание и параметр разновидности отсутствуют, литерал INTEGER имеет разновидность по умолчанию. Примеры литералов INTEGER:
  34
  -256
  345_4
  +78_mykind
  34 and -256 имеют тип INTEGER по умолчанию.
  345_4 есть INTEGER разновидности 4 (умолчание для INTEGER в LF95).
В последнем примере mykind должен быть объявлен предварительно как скалярная именованная константа типа INTEGER со значением параметра разновидности INTEGER (1, 2, или 4 в LF95).

Двоичные, восьмеричные или шестнадцатеричные константы могут появиться в операторе DATA. Такие константы могут образовываться заключением последовательности двоичных, восьмеричных или шестнадцатеричных цифр в апострофы или кавычки с буквами B, O или Z впереди для соответственно двоичного, восьмеричного или шестнадцатеричного представления.
    B'10101'    Z"1AC3"
Литералы REAL

Литерал типа REAL состоит из одной или более цифр и десятичной точки (точка может появиться перед, после или между цифрами), содержит впереди необязательный знак
(+ или -) и в конце может иметь букву экспоненты и порядок, а затем знак подчеркивания и параметр разновидности. Если присутствует буква экспоненты, десятичная точка необязательна. Экспонента обозначается буквой E при простой точности, D при двойной, Q при четверной. Если подчеркивание и параметр разновидности отсутствуют, литерал REAL имеет точность по умолчанию. Примеры литералов:
    -3.45    .0001    34.E-4    1.4_8
Первые три примера имеют тип REAL по умолчанию. Последний пример есть REAL разновидности 8.

Литералы COMPLEX

Литерал COMPLEX формируется заключением в скобки пары разделенных запятой литералов типа REAL или INTEGER. Первый из REAL или INTEGER литералов представляет вещественную часть комплексного числа; второй представляет мнимую часть. Параметр разновидности константы COMPLEX есть 16, если либо вещественная, либо комплексная часть или обе имеют четверную точность REAL, или 8, если вещественная или мнимая часть или обе есть REAL двойной точности. В противном случае параметр разновидности есть 4 (точность по умолчанию для COMPLEX). Примеры правильных литералов COMPLEX:
    (3.4,-5.45)    (-1,-3)    (3.4,-5)     (-3.d13,6._8)
Первые три примера имеют точность по умолчанию -- четыре байта для каждой части. В четвертом используются 8 байтов.

Литералы типа LOGICAL

Логический литерал есть либо .TRUE. либо .FALSE. с необязательным параметром разновидности в конце. Если необязательные подчеркивание и параметр разновидности отсутствуют, литерал имеет разновидность по умолчанию. Примеры правильных литералов типа LOGICAL есть:
    .false.    .true.    .true._mykind
В последнем примере константа mykind должна быть предварительно определена как скалярная именованная константа INTEGER со значением параметра разновидности LOGICAL (1 или 4 в LF95). Два первых примера имеют тип LOGICAL по умолчанию.

Литералы CHARACTER

Такой литерал состоит из цепочки символов, заключенных в соответствующие кавычки или апострофы, перед ним могут располагаться параметр разновидности и знак подчеркивания.
Если внутри цепочки CHARACTER, заключенной в кавычки, встречается кавычка, ее нужно удвоить. Такая удвоенная кавычка считается за один знак. Подобно этому, если внутри цепочки CHARACTER в апострофах встречается апостроф, его нужно удвоить. Удвоенный апостроф также считается за один знак.
Вот примеры правильных литералов CHARACTER:
  "Hello world"
  'don''t give up the ship!'
  ASCII_'foobeedoodah'
  ""
  ''
ASCII должна быть предварительна объявлен как именованная скалярная константа типа INTEGER со значением 1, чтобы использоваться для указания разновидности. Два последних примера удвоенных кавычек и апострофов есть литералы CHARACTER длины 0.

Именованные данные

Именованные объекты данных, такие как переменные, именованные константы или результаты функций имеют свойства встроенных или определенных пользователем типов данных, или неявно (по первой букве имени), или по типу оператора объявления. Дополнительная информация о именованных объектах данных, называемая атрибутами объектов данных, может также быть указана или в операторах объявления типа или в отдельных операторах специально для атрибутов.
Если объект данных имеет имя, он становится доступным как единое целое, с помощью ссылки на это имя. Для некоторых объектов данных, таких как цепочка символов, массивы и производные типы, возможен прямой доступ к частям объектов. Кроме того, для ссылки на объекты данных или их части могут устанавливаться псевдонимы (aliases), называемые указателями (pointers).

Неявное задание типов

При отсутствии операторов объявления типов, тип объекта данных с именем определяется по первой букве его имени. Буквы от I до N означают тип INTEGER, а остальные буквы --- тип REAL. Эти неявные правила могут изменяться или отменяться пользователем с помощью оператора IMPLICIT. Оператор IMPLICIT NONE можно использовать для отмены всех неявных назначений типа в пределах программной единицы (scoping unit).

Операторы объявления типа

Операторы объявления типа указывают типы, параметры типов и атрибуты именованных объектов данных или функций. Оператор объявления типа можно использовать для каждого встроенного типа INTEGER, REAL (и DOUBLE PRECISION), COMPLEX, LOGICAL или CHARACTER, а также для производных типов (см. "Производные типы" на стр. 16).

Атрибуты

Кроме типов и параметров типа, объекты данных или функции могут иметь один или более следующих атрибутов, которые могут быть указаны в операторах объявления типов или в отдельных операторах специально для атрибутов:

  • DIMENSION - объект данных есть массив (см. "Оператор DIMENSION" на стр.104).
  • PARAMETER - объект данных есть именованная константа (см. "Оператор PARAMETER" на стр. 186).
  • POINTER - объект данных, используемый как псевдоним для других объектов данных того же типа, разновидности и ранга (см. "Оператор POINTER" на стр. 188).
  • TARGET - объект данных, на который надо ссылаться по псевдониму с атрибутом POINTER (см. "Оператор TARGET" на стр. 223).
  • EXTERNAL - имя служит именем внешней процедуры (см. "Оператор EXTERNAL" на стр. 124).
  • ALLOCATABLE - объект данных есть массив не фиксированного размера, память для размещения которого должна отводиться по указанию в процессе выполнения программы (см. "Оператор ALLOCATABLE" на стр. 63).
  • INTENT - фиктивное значение аргумента, не будет изменяться в процедуре (INTENT (IN) ), не будет снабжено начальным значением при вызове подпрограммы (INTENT (OUT) ), или и начальное значение будет обеспечено и новое значение может иметь место (INTENT (IN OUT) ) (см."INTENT Statement" на стр. 151).
  • PUBLIC - именованный объект данных или процедура в программной единице MODULE, доступная из программной единицы, использующей этот модуль (см. "Оператор PUBLIC" на стр. 195).
  • PRIVATE - именованный объект данных или процедура в программной единице MODULE, доступная только в этом модуле (см. "Оператор PRIVATE" на стр. 193).
  • INTRINSIC - имя, служащее названием встроенной функции (см. "Оператор INTRINSIC" на стр. 154).
  • OPTIONAL - фиктивный аргумент, которому в вызове содержащей его процедуры может не соответствовать никакой фактический аргумент (см. "Оператор OPTIONAL" на стр. 184).
  • SAVE - объект данных, который сохраняет свое значение, ассоциативный статус association status, и статус расположения в памяти после операторов RETURN или END (см. "Оператор SAVE" на стр. 207).
  • SEQUENCE - порядок определения компонент в определении производного типа, последовательность расположения в памяти объектов этого тип (см. "Оператор SEQUENCE" на стр. 211).
  • DLLEXPORT (только Windows) - имя внешней процедуры, модуля, или имя общего (common) блока, который должен быть DLL (см. "Оператор DLL_EXPORT" на стр. 105).
  • DLLIMPORT (только Windows) - имя внешней процедуры, имя модуля, служащего внешней процедурой, имя модуля или общего блока для использования DLL (см. "Оператор DLL_IMPORT" на стр. 106).

Подцепочки

Цепочка символов есть последовательность символов в объекте данных типа CHARACTER. Символы цепочки нумеруются слева направо, начиная с 1. Сплошная часть цепочки символов, называемая подцепочкой (substring), может выделяться согласно следующему синтаксису:
  string ( [lower-bound] : [upper-bound] )
Здесь:
string есть имя цепочки или литерала CHARACTER.
[lower-bound] есть номер в цепочке самого левого символа подцепочки.
[upper-bound] есть номер в цепочке последнего символа подцепочки.
При отсутствии они получают значения соответственно 1 и длины цепочки.
Подцепочка имеет длину 0, если lower-bound больше чем upper-bound.
lower-bound не может быть меньше 1.
Например, если abc_string есть имя цепочки "abcdefg", то
  abc_string(2:4) есть "bcd"
  abc_string(2:) есть "bcdefg"
  abc_string(:5) есть "abcde"
  abc_string(:) есть "abcdefg"
  abc_string(3:3) есть "c"
  "abcdef"(2:4) есть "bcd"
  "abcdef"(3:2) есть цепочка нулевой длины

Массивы

Массив есть множество данных, которые все имеют одинаковый тип и параметры типа и представляет вектор или прямоугольную матрицу двух и более измерений. Объект данных, не являющийся массивом, есть скаляр. Массивы объявляются операторами DIMENSION или операторами объявления типа. Массив имеет ранг, равный количеству измерений массива; скаляр имеет ранг ноль. Форма массива определяется его протяженностью по каждому измерению. Размер массива определяется количеством его элементов. В следующем примере:
  integer, dimension (3,2) :: i
  i имеет ранг 2, форму (3,2) и размер 6.

Ссылки на массив

На массив в целом ссылаются по имени массива. На индивидуальные элементы или секции массива ссылаются с помощью индексов массива.
   Синтаксис: array [(subscript-list)]
Здесь:
  array есть имя массива.
  subscript-list есть разделенный запятыми список из
  element-subscript
  или subscript-triplet
  или vector-subscript.
  element-subscript есть скалярное выражение типа INTEGER.
  subscript-triplet есть [element-subscript] : [element-subscript] [ : stride]
  stride есть скалярное выражение типа INTEGER.
  vector-subscript есть INTEGER array expression ранга 1.
Индексы в subscript-list относятся каждый к измерению массива.
Самый левый индекс относится к первому измерению массива.

Элементы массива

Если каждый индекс в списке индексов массива есть элементарный индекс, то такая ссылка на массив означает его отдельный элемент. В противном случае это есть ссылка на секцию массива (см. "Секции массива " на стр. 11).

Порядок элементов в массиве

Элементы массива образуют последовательность, называемую порядком элементов массива. Позиция элемента массива в этой последовательности определяется так:
  (1 + (s1 - j1)) + ((s2 - j2) x d1) + ... + ((sn - jn) x dn-1 x dn-2... x d1)
Здесь:
  si есть индекс в измерении i.
  ji есть нижняя граница i-го измерения.
  di есть размер i-го измерения.
  n есть ранг массива.
Другой путь описания порядка элементов массива состоит в том, что индекс самого левого измерения меняется наиболее часто при движении от первого элемента к последнему в порядке элементов массива. Например, в следующем коде:
  integer, dimension(2,3) :: a
порядок элементов есть a(1,1), a(2,1), a(1,2), a(2,2), a(1,3), a(2,3).
Порядок элементов используется при производстве ввода/вывода массивов.

Секции массивов

Можно ссылаться на некоторую часть массива как на массив. Такие порции называются секциями массивов. Секция массива имеет список индексов, который содержит по крайней мере один индекс, который есть или индекс-триплет или вектор-индекс (см. ниже примеры в "Индексы-триплеты" и "Вектор-индексы"). Заметим, что секция массива только из одного элемента не есть скаляр.

Индексы-триплеты

Три компоненты индекса-триплета есть соответственно нижняя граница секции массива, верхняя граница и шаг (приращение между последовательными индексами в секции). Любые из них или все три могут отсутствовать. Если опущена нижняя граница, на ее месте предполагается объявленная нижняя граница измерения. Если опущена верхняя граница, предполагается верхняя граница измерения. Если опущен шаг. предполагается шаг 1. Правильные примеры секций массивов с триплетами:

    a(2:8:2)    ! a(2), a(4), a(6), a(8)
    b(1,3:1:-1)    ! b(1,3), b(1,2), b(1,1)
    c(:,:,:)    ! c
Вектор-индексы

Вектор-индексы (вектор есть одномерный массив) могут использоваться для ссылки на секцию всего массива. Рассмотрим следующий пример:
  integer :: vector(3) = (/3,8,12/)
  real :: whole(3,15)
  ...
  print*, whole(3,vector)
Здесь массив vector использован как индекс массива whole в операторе PRINT, который печатает значения элементов (3,3), (3,8) и (3,12).

Массивы и подцепочки

Секция массива CHARACTER или элемент массива может иметь спецификацию подцепочки вслед за списком индексов. Если весь массив или его секция имеет спецификатор подцепочки, то это ссылка на секцию массива. Например:
  character (len=10), dimension (10,10) :: my_string
  my_string(3:8,:) (2:4) = 'abc'
присваивает 'abc' секции массива, состоящей из символов по порядку 2,3,4 в рядах от 3 до 8 в массиве my_string типа CHARACTER.

Динамические массивы

Массив может иметь фиксированный размер во время компиляции или может предполагать определение размеров и формы во время исполнения несколькими способами:

  • размещаемые (allocatable) массивы и массивы указателей могут получать память когда нужно с помощью операторов ALLOCATE и освобождать ее с помощью операторов DEALLOCATE. Массив указателей предполагает форму его назначения, когда используется оператор присваивания указателям (см. "Размещаемые массивы" на стр. 13 и "Массивы указателей" на стр. 13). Размещаемые массивы и массивы указателей вместе называются массивы с отложенной формой.
  • Фиктивный массив может получать размер и форму на основании размера и формы соответствующего фактического аргумента (см. "Массивы предполагаемой формы" на стр. 14).
  • Фиктивный массив может иметь необъявленный размер (см. "Массивы предполагаемого размера" на стр. 14).
  • Массив может иметь переменные измерения на основе значений фиктивных аргументов (см. "Настраиваемые и автоматические массивы" на стр. 15).

Размещаемые массивы

Атрибут ALLOCATABLE может быть придан массиву в операторе объявления типа или в операторе ALLOCATABLE. Размещаемый массив должен быть объявлен со спецификатором отложенной формы, `:', для каждого измерения. Например:
  integer, allocatable :: a(:), b(:,:,:)
объявляет два размещаемых массива, один с рангом один и другой ранга три. Границы, а тем самым и форма размещаемого массива определяются, когда ему отводится память по оператору ALLOCATE. Продолжая предыдущий пример,   allocate (a(3), b(1,3,-3:3))
отводит память для массива ранга 1 размера 3 и массива ранга 3 и размера 21 с нижней границей -3 по третьему измерению. Память, занятая размещаемым массивом, возвращается в систему по оператору DEALLOCATE.

Массивы указателей

Атрибут POINTER может придаваться массиву оператором объявления типа или в операторе POINTER. Массив указателей, подобно размещаемому массиву, объявляется с спецификатором отложенной формы, `:', для каждого измерения. Например:
  integer, pointer, dimension(:,:) :: c
объявляет массив указателей ранга два. Массив указателей помещается в память тем же путем, как и размещаемый массив. Дополнительно, форма массива указателей может быть установлена, когда указатель ассоциируется с назначением в операторе присваивания указателю. Тогда форма устанавливается по форме назначения.
  integer, target, dimension(2,4) :: d
  integer, pointer, dimension(:,:) :: c
   c => d
В этом примере массив c становится ассоциированным с массивом d и принимает форму массива d.

Массивы предполагаемой формы

Массив предполагаемой формы есть фиктивный массив, принимающий форму соответствующего фиктивного аргумента. Нижняя граница массива с предполагаемой формой может быть объявлена и может отличаться от соответствующей границы фактического аргумента-массива. Спецификация предполагаемой формы есть
  [lower-bound] :
для каждого измерения массива предполагаемой формы. Например:
  ...
  integer :: a(3,4)
  ...
  call zee(a)
  ...
  subroutine zee(x)
  implicit none
  integer, dimension(-1:,:) :: x
  ...
Здесь фиктивный массив x предполагает форму фактического аргумента a с новой нижней границей для измерения один. Интерфейс для массива предполагаемой формы может быть явным (см. "Явные интерфейсы" на стр. 50).

Массивы предполагаемого размера

Массив предполагаемого размера есть фиктивный массив, размер которого не известен. Все границы, кроме верхней границы последнего измерения, указаны в объявлении фиктивного массива. В объявлении верхняя граница последнего измерения обозначается звездочкой. Оба массива имеют тот же самый начальный элемент массива и ассоциированы по памяти. Нельзя ссылаться на массив с предполагаемым размером в контексте, где форма массива должна быть известна, таком как ссылка на весь массив или во многих встроенных функциях преобразования массива. Результат функции не может быть массивом предполагаемого размера.
  ...
  integer a
  dimension a(4)
  ...
  call zee(a)
  ...
  subroutine zee(x)
  integer, dimension(-1:*) :: x
  ...
В этом примере размер фиктивного массива x не известен.

Настраиваемые и автоматические массивы

Можно устанавливать форму массива на основании значений фиктивных аргументов. Если такой массив есть фиктивный массив, он называется настраиваемым (adjustable) массивом. Если массив не есть фиктивный массив, он называется автоматическим массивом. Рассмотрим следующий пример:
  integer function bar(i, k)
  integer :: i,j,k
  dimension i(k,3), j(k)
  ...
Здесь формы массивов i и j зависят от значения фиктивного аргумента k. i есть настраиваемый массив, а j есть автоматический массив.

Конструкторы массивов

Конструктор массива есть массив без имени.
Синтаксис: ( / constructor-values / )
Здесь constructor-values есть разделенный запятыми список expr или ac-implied-do ,
где expr есть выражение.
  ac-implied-do есть ( constructor-values, ac-implied-do-control ),
  ac-implied-do-control есть do-variable = do-expr, do-expr [, do-expr],
  do-variable есть скалярная переменная типа INTEGER.
  do-expr есть скалярное выражение типа INTEGER.
Конструктор массива есть массив ранга один. Если элемент конструктора есть сам массив, то значения его элементов, расположенных в порядке элементов массива, представляют соответствующую последовательность элементов конструктора массива. Если какое-то значение конструктора есть implied-do, оно расширяется в последовательность значений под управлением индекса цикла как в конструкте DO (см. "Конструкт DO" на стр. 106).
  integer, dimension(3) :: a, b=(/1,2,3/), c=(/(i, i=4,6)/)
  a = b + c + (/7,8,9/) ! a присваивается (/12,15,18/)
Конструктор массива может быть изменен с помощью встроенной функции RESHAPE и может быть затем использован для инициализации или представления массивов с рангом больше чем один. Например:
  real,dimension(2,2) :: a = reshape((/1,2,3,4/),(/2,2/))
присваивает (/1,2,3,4/) массиву a в порядке элементов массива после изменения для соответствия с формой массива a.

Производные типы

Производные типы есть определяемые пользователем типы данных на основе встроенных типов INTEGER, REAL, COMPLEX, LOGICAL и CHARACTER. В то время как массив есть множество данных одного типа, производный тип может представлять комбинацию встроенных типов и других производных типов. Объект данных производного типа называется структурой.

Определение производного типа

Производный тип должен быть определен до объявления объектов этого типа.
В определении производного типа указывается имя нового типа и имена типов его компонент.
Синтаксис:
  derived-type-statement
  [private-sequence-statement]
  type-definition-statement
  [type-definition-statement]
  ...
  END TYPE [type-name]
Здесь derived-type-statement есть оператор производного типа.
private-sequence-statement есть оператор PRIVATE или оператор SEQUENCE.
type-definition-statement есть оператор INTEGER, REAL, COMPLEX, DOUBLE PRECISION, LOGICAL, CHARACTER или TYPE.
Оператор определения типа в составе определения производного типа может иметь только атрибуты POINTER и DIMENSION. Он не может быть функцией. Ему может быть придано инициализирующее значение по умолчанию, и в этом случае компоненты получают атрибут SAVE. Компонента-массив может быть массивом отложенной формы, если присутствует атрибут POINTER, в остальных случаях он должен иметь явную форму.

type coordinates
          real :: latitude, longitude
end type coordinates
type place
          character(len=20) :: name
          type(coordinates) :: location
end type place
type link
          integer :: j
          type (link), pointer :: next
end type link
В предыдущем примере тип coordinates есть производный тип с двумя компонентами типа REAL: latitude and longitude. Тип place имеет две компоненты: name типа CHARACTER длины двадцать и структуру типа coordinates с именем location. Тип link имеет две компоненты: INTEGER с именем j и структуру типа link, с именем next, которая есть указатель на тот же самый производный тип. Компонента структуры может иметь тот же самый тип, что и сам производный тип только если он имеет атрибут POINTER. Таким способом могут формироваться связные списки, деревья и графы.
Есть два пути использования производных типов в более чем одной программной единице. Предпочтительный путь состоит в определении производного типа в модуле (см."Программные единицы модули" на стр.55) и использовать этот модуль там, где нужен производный тип. Другой метод, без модулей, состоит в употреблении оператора SEQUENCE в определении производного типа и в определении производного типа точно тем же способом в каждой программной единице, где этот тип используется. Это можно сделать с помощью файла include. Компоненты производного типа могут быть сделаны недоступными другим программным единицам использованием оператора PRIVATE перед всеми компонентами операторов определений.

Объявление переменных производного типа

Переменные производного типа объявляются оператором TYPE. Вот примеры объявления переменных для каждого из определенных выше производных типов:
  type(coordinates) :: my_coordinates
  type(place) :: my_town
  type(place), dimension(10) :: cities
  type(link) :: head

Ссылки на компоненты

На компоненты структуры ссылаются с помощью оператора `%'.
Например, на latitude в структуре my_coordinates нужно ссылаться как my_coordinates%latitude.
На latitude в типе coordinates в структуре my_town ссылаются так: my_town%coordinates%latitude.
Если переменная есть массив структур, как в случае объявленного выше cities, на секции массива ссылаются как cities(:,:)%name, что означает ссылку на компоненту name для всех элементов массива cities, или как
  cities(1,1:2)%coordinates%latitude
что означает ссылку на элемент latitude типа coordinates для элементов (1,1) и (1,2) массива cities. Заметим, что в первом примере синтаксис
  cities%name
эквивалентен и представляет секцию массива.

Конструкторы структур

Конструктором структуры называется структура без имени.
Синтаксис:
  type-name ( expr-list )
где
  type-name есть имя производного типа,
  expr-list есть список выражений.
Каждое выражение в expr-list должно быть согласовано по количеству и порядку с соответствующими компонентами производного типа. Там где необходимо, производятся конверсии встроенных типов. Например, для компонент не-указателей форма выражений должна соответствовать форме компонент.

type mytype              ! определение производного типа
integer :: i,j
character(len=40) :: string
end type mytype

type (mytype) :: a       ! объявление производного типа
a = mytype (4, 5.0*2.3, 'abcdefg')
В этом примере второе выражение в конструкторе структуры приводится к типу по умолчанию INTEGER при присваивании.

Указатели

В Fortran указатель есть псевдоним. Переменная, псевдонимом которой он служит, есть его назначение. Указательные переменные должны иметь атрибут POINTER; переменные назначения должны иметь атрибут или TARGET или POINTER.

Ассоциирование Pointer с Target

Указатель может ассоциироваться только с переменной, которая имеет атрибут TARGET или POINTER. Такая ассоциация может быть осуществлена одним из двух путей:

  • явно оператором присваивания указателю.
  • неявно с помощью оператора ALLOCATE.
Если ассоциация между указателем и назначением установлена, всякая ссылка на указатель применяется к назначению.
Объявление указателей и назначений

Переменная может быть объявлена имеющей атрибут POINTER или TARGET в операторе объявлении типа, или в операторе POINTER или TARGET. Когда массив объявляется как указатель, нужно объявлять массив с отложенной формой.
Пример:

integer, pointer :: a, b(:,:)
integer, target :: c

a => c                      ! оператор присваивания указателю
                            ! a есть псевдоним для c
allocate (b(3,2))           ! оператор allocate
                            ! безымянное назначение для  b
                            ! создается в форме (3,2)
В этом примере явная ассоциация создается между a и c через оператор присваивания указателю. Заметим, что a была ранее объявлена указателем, c была ранее объявлена назначением, и а и c согласованы в типе, разновидности и ранге. В операторе ALLOCATE целевой массив размещается и b становится указателем на него. Массив b был объявлен с отложенной формой, так что массив назначения мог быть размещен с любой формой ранга два.

Выражения

В начало страницы

Выражение состоит из операндов, операторов и скобок. Вычисление выражения производит значение с типом, параметрами типа (разновидность и в случае CHARACTER длина) и формой. Вот несколько примеров правильных выражений Fortran:

5
n
(n+1)*y
"to be" // ' or not to be' // text(1:23)
(-b + (b**2-4*a*c)**.5) / (2*a)
b%a - a(1:1000:10)
sin(a) .le. .5
l .my_binary_operator. r + .my_unary_operator. m

В последнем примере используются определяемые пользователем операции (см. "Определяемые операции" на стр. 51).
Все операнды-массивы в выражении должны иметь одинаковую форму. Скаляр может преобразовываться в любую форму. Выражения с значениями-массивами вычисляются поэлементно для соответствующих элементов каждого массива и скаляр в таком выражении рассматривается как массив, все элементы которого имеют значение скаляра. Например, выражение
  a(2:4) + b(1:3) + 5   будет превращено в
  a(2) + b(1) + 5
  a(3) + b(2) + 5
  a(4) + b(3) + 5

Выражения вычисляются в соответствии с правилами приоритета операторов, описанными ниже. Если имеются кратные соседние операции одного приоритета, то вычитания и деления выполняются слева направо, возведения в степень производятся справа налево, а остальные операции могут производиться любым путем в зависимости от оптимизирующих действий компилятора. Скобки могут использоваться для установления нужного порядка действий.

Спецификационным выражением называется скалярное выражение типа INTEGER, значение которого можно вычислить при входе в программную единицу во время ее выполнения. Инициализируемым выражением называется выражение, значение которого можно вычислить во время компиляции.

Встроенные операции

Перечислим встроенные операции в порядке уменьшения их приоритета:

Table 2: Встроенные операции

Оператор Действие Операнды
** возведение в степень два числа
* и / умножение и деление два числа
+ и - одноместные плюс и минус одно число
+ и - бинарные сложение и вычитание два числа
// конкатенация два CHARACTER
.EQ. и == равно два числа или два CHARACTER
.NE. и /= не равно
.LT. и < меньше чем два числа (не COMPLEX) или два CHARACTER
.LE. и <= меньше или равно
.GT. и > больше чем
.GE. and >= больше чем или равно
.NOT. логическое отрицание один LOGICAL
.AND. логическая конъюнкция два LOGICAL
.OR. логическая дизъюнкция два LOGICAL
.EQV. логическая эквивалентностьtwo LOGICAL
.NEQV. и не-эквивалентность

Замечание: все операции в этой части таблицы имеют одинаковый приоритет
Если некая операция произведена над операндами одного типа, результат будет иметь тот же тип и больший из двух параметр разновидности.
Если операция произведена над численными операндами разных типов, результат будет иметь высший из типов операндов, причем COMPLEX выше чем REAL, а REAL выше чем INTEGER.
Если операция произведена над численными или LOGICAL операндами одинакового типа, но разных разновидностей, результат будет иметь разновидность операнда, имеющего большую точность.
Результат конкатенации имеет длину, равную сумме длин операндов.
Деление типа INTEGER Результат операции деления INTEGER операндов есть целое, ближайшее к точному отношению операндов в промежутке между нулем и этим отношением. Например, 7/5 вычисляется как 1, а -7/5 --- как -1.

Ввод/вывод

В начало страницы

В Fortran ввод и вывод производятся на логических устройствах. Устройством может быть:

  • неотрицательное INTEGER, связанное с физическим устройством, таким как консоль или принтер. Устройство может быть связано с файлом или устройством в операторе OPEN, исключая случай предварительно связанных файлов.
  • звездочка, `*', указывающая устройство стандартного ввода и стандартного вывода, обычно это предварительно подключенные клавиатура или monitor.
  • переменная типа CHARACTER соответствующая имени внутреннего файла.
Операторы Fortran'а могут подключать (OPEN) или отключать (CLOSE) файлы и устройства из ассортимента ввода/вывода; передавать данные (PRINT, READ, WRITE); устанавливать позицию в файле (REWIND, BACKSPACE, ENDFILE); запрашивать файл или устройство об их связях (INQUIRE).
Предварительно подключенные устройства ввода/вывода
Устройства ввода/вывода 5, 6 и * автоматически подключаются при использовании. Устройство 5 связано со стандартным устройством ввода, обычно клавиатурой, а устройство 6 связано со стандартным выводом, обычно монитором. Устройство * постоянно связано со стандартным вводом и стандартным выводом.
Устройства вывода
Файлы
Fortran рассматривает все физические устройства, такие как файлы на дисках, консоль, принтеры и внутренние файлы как файлы. Файл есть последовательность из нуля или более записей. Формат данных (форматированные или нет), тип доступа (прямой или последовательный) и длина записи определяют структуру файла.
Позиция в файле
Некоторые операторы ввода/вывода влияют на позицию в пределах внешнего файла. До выполнения оператора передачи данных указанный файл устанавливается на позицию начала записи, указанной спецификатором записи REC= в операторе передачи данных. По умолчанию последовательный файл устанавливается на позицию после последней записанной или прочтенной записи. Но если указан не продвигающий (non-advancing) ввод/вывод с помощью спецификации ADVANCE= , то можно читать или писать определенные записи и читать записи переменной длины с уведомлением об их длине. Оператор ENDFILE записывает признак конца фала после последней прочтенной или записанной записи и устанавливает файл на позицию после конечной записи. Оператор REWIND устанавливает файл в начальную позицию. Оператор BACKSPACE сдвигает позицию файла на одну запись назад. Если обнаружена ошибка, позиция файла не определена. Если ошибок нет и прочтена или записана конечная запись файла, файл устанавливается на позицию после последней записи. В этом случае он должен быть переустановлен перед продолжением чтения или записи операторами REWIND или BACKSPACE. При не продвигающем вводе\выводе некоторой записи, если не было ошибок и не достигнут конец файла, но появился сигнал конца записи, файл устанавливается на позицию после только что прочтенной записи. Если сигнала конца не было, позиция файла не меняется.
Типы файлов
Тип файла, намеченного для доступа, указывается в операторе OPEN с помощью спецификаторов FORM= и ACCESS= (см."Оператор OPEN" на стр. 181).
Форматированный последовательный
  • записи переменной длины заканчиваются концом строки
  • хранятся как данные типа CHARACTER
  • может использоваться на устройствах или в дисковых файлах
  • записи могут обрабатываться подряд
  • файлы могут легко печататься и выдаваться на дисплей
  • обычно самый медленный
Форматированный прямой
  • записи фиксированной длины, нулевая запись служит заголовком
  • хранятся как данные типа CHARACTER
  • только дисковые файлы
  • записи доступны в любом порядке
  • не являются легко обрабатываемыми при компиляции не с LF95
  • та же скорость как в форматированных последовательных дисковых файлах
Неформатированные последовательные
  • записи переменной длины разделены маркерами
  • хранятся как двоичные данные
  • только дисковые файлы
  • записи должны обрабатываться подряд
  • быстрее чем форматированные файлы
  • не являются легко читаемыми не в LF95
Неформатированные прямые
  • записи фиксированной длины, нулевая запись служит заголовком
  • хранятся как двоичные данные
  • только дисковые файлы
  • записи доступны в любом порядке
  • самые быстрые
  • не являются легко читаемыми не в LF95
Двоичные (или прозрачные)
  • хранятся как двоичные данные без межзаписных маркеров или заголовка
  • длина записи один байт, но ограничения на конец записи отсутствуют
  • записи могут обрабатываться в любом порядке
  • могут располагаться как дисковые файлы или на других физических устройствах
  • хороши для файлов, используемых вне LF95
  • быстрые и компактные
См. "Форматы файлов" в Руководстве пользователя для подробностей.
Внутренние файлы
Всякий внутренний файл есть всегда форматированный последовательный файл и состоит из единственной переменной типа CHARACTER. Если эта переменная имеет значением массив, каждый элемент массива рассматривается как запись в файле. Это свойство допускает конверсию от внутреннего представления (двоичного бесформатного) к внешнему (ASCII, форматированному) без передачи данных на внешнее устройство.
Управление кареткой
Первый символ форматированной записи, посылаемой на терминальное устройство, такое как консоль или принтер, используется для управления кареткой и не печатается. Остальные символы печатаются в строке, начинающейся с левой крайней позиции. Символы управления кареткой интерпретируются следующим образом:
Таблица 3: Управление кареткой

СимволВертикальное перемещение перед печатью
0 Две строки
1 К первой строке следующей страницы
+ Ничего
Пробел или любой из остальных символов Одна строка


<<< Оглавление Страницы:  3   4 >>>