Возможности языка Fortran 95 - Fortran 95 language features

Это обзор Возможности языка Fortran 95. Включены дополнительные функции TR-15581: Расширенные возможности типов данных, которые реализованы повсеместно. Старые функции, которые были заменены новыми, не описываются - некоторые из этих исторических функций используются в современных программах, хотя большинство из них было сохранено в языке для поддержки Обратная совместимость. Текущий стандарт - Fortran 2018; многие из его новых функций все еще реализуются в компиляторах.[1] Дополнительные возможности Fortran 2003, Fortran 2008 и Fortran 2018 описаны Меткалфом, Ридом и Коэном.[2]

Элементы языка

Фортран - это без учета регистра. В этой статье принято соглашение о написании ключевых слов Fortran в верхнем регистре, а всех остальных имен в нижнем регистре; за исключением, для контраста, описаний входов / выходов (Передача данных и Операции с внешними файлами ).

Основы

Основным компонентом языка Фортран является его набор символов. Его членами являются

  • буквы A ... Z и a ... z (которые эквивалентны вне контекста символа)
  • цифры 0 ... 9
  • подчеркивание _
  • специальные символы =: + пробел - * / () [],. $ '! "% &; <>?

Токены которые имеют синтаксическое значение для компилятора, построены из этих компонентов. Всего существует шесть классов токенов:

Этикетка123
Постоянный123.456789_long
Ключевое словоРАЗМЕЩЕННЫЙ
Оператор.Добавить.
Имярешить_equation (до 31 символа, включая _)
Разделитель / ( ) (/ /) [ ] , = => : :: ; %

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

НАЗНАЧЕНИЕ string_concat(s1, s2)                             ! Это комментарий   ТИП (нить), НАМЕРЕНИЕ(В) :: s1, s2   ТИП (нить) string_concat   string_concat%string_data = s1%string_data(1:s1%длина) // &      s2%string_data(1:s2%длина)                          ! Это продолжение   string_concat%длина = s1%длина + s2%длинаКОНЕЦ ФУНКЦИИ string_concat

Обратите внимание на комментарии и знак продолжения. Может быть 39 строк продолжения и 132 символа в строке. Пробелы значительны. Если токен или символьная константа разделены на две строки:

               ...        начало&        &_имя               ...   'очень длинный &        &нить'

ведущий & на продолжении линии также требуется.

Автоматическое преобразование исходной формы для существующих программ может быть выполнено convert.f90.

Его варианты

  • значительная обработка бланков;
  • отступ;
  • CONTINUE заменяется на END DO;
  • имя добавлено в оператор END подпрограммы; и
  • Преобразование синтаксиса INTEGER * 2 и т. Д.

Внутренние типы данных

У Фортрана пять внутренние типы данных: ЦЕЛОЕ, НАСТОЯЩИЙ, СЛОЖНЫЙ, ЛОГИЧЕСКИЙ и ПЕРСОНАЖ. Каждый из этих типов может быть дополнительно охарактеризован своего рода. Kind, по сути, определяет внутреннее представление типа: для трех числовых типов он определяет точность и диапазон, а для двух других - особенности представления хранилища. Таким образом, это абстрактное понятие, моделирующее пределы представления типов данных; он выражается как член набора целых чисел (например, это может быть {1, 2, 4, 8} для целых чисел, обозначающих байты памяти), но эти значения не определены стандартом и не переносимы. Для каждого типа есть вид по умолчанию, который используется, если вид не указан явно. Для каждого внутреннего типа существует соответствующая форма буквальная константа. Числовые типы ЦЕЛОЕ и НАСТОЯЩИЙ может быть только подписано (нет понятия знака для типа СЛОЖНЫЙ).

Буквальные константы и виды

ЦЕЛОЕ

Целочисленные литеральные константы типа по умолчанию имеют вид

1   0   -999   32767   +10

Тип можно определить как именованную константу. Если желаемый диапазон составляет ± 10своего рода, переносимый синтаксис для определения подходящего типа, два_байта является

ЦЕЛОЕ, ПАРАМЕТР :: два_байта = SELECTED_INT_KIND(4)

что позволяет в дальнейшем определять константы вида

-1234_two_bytes   +1_two_bytes

Здесь, два_байта - параметр типа вида; он также может быть явным целочисленным литералом по умолчанию, например

-1234_2

но такое использование непереносимо.

Функция KIND предоставляет значение параметра типа kind:

СВОЕГО РОДА(1)            СВОЕГО РОДА(1_two_bytes)

и КЛАССИФИЦИРОВАТЬ функция предоставляет фактический десятичный диапазон (поэтому пользователь должен выполнить фактическое сопоставление с байтами):

КЛАССИФИЦИРОВАТЬ(1_two_bytes)

Также в ДАННЫЕ (инициализация) операторы могут использоваться двоичные (B), восьмеричные (O) и шестнадцатеричные (Z) константы (часто неофициально называемые «константами BOZ»):

B'01010101'   О'01234567'   Z'10fa'
НАСТОЯЩИЙ

Существует как минимум два реальных вида - стандартный и более точный (заменяет ДВОЙНАЯ ТОЧНОСТЬ). SELECTED_REAL_KIND функции возвращают номер типа для желаемого диапазона и точности; для не менее 9 десятичных цифр точности и диапазона 10−99 до 1099, его можно указать как:

ЦЕЛОЕ, ПАРАМЕТР :: длинный = SELECTED_REAL_KIND(9, 99)

и литералы, впоследствии указанные как

1,7_длинный

Также есть встроенные функции

СВОЕГО РОДА(1,7_длинный)   ТОЧНОСТЬ(1,7_длинный)   КЛАССИФИЦИРОВАТЬ(1,7_длинный)

которые, в свою очередь, дают значение типа kind, фактическую точность (здесь не менее 9) и фактический диапазон (здесь не менее 99).

СЛОЖНЫЙ

СЛОЖНЫЙ Тип данных состоит из двух целочисленных или вещественных компонентов:

(1, 3,7_длинный)
ЛОГИЧЕСКИЙ

Есть только два основных значения логических констант: .ИСТИННЫЙ. и .ЛОЖНЫЙ.. Здесь тоже могут быть разные виды. Логические элементы не имеют собственных функций запроса, но используют типы, указанные для ЦЕЛОЕs; вид по умолчанию ЛОГИЧЕСКИЙ совпадает с INTEGER.

.ЛОЖНЫЙ.   .истинный._one_byte

и СВОЕГО РОДА функция работает должным образом:

СВОЕГО РОДА(.ИСТИННЫЙ.)
ПЕРСОНАЖ

Формы буквальных констант для ПЕРСОНАЖ тип данных

'Строка'   "Другой"   'Цитата"'   '''''''

(последняя - пустая строка). Разрешены разные виды (например, чтобы различать ASCII и UNICODE строки), но не поддерживается компиляторами. Опять же, значение вида дается СВОЕГО РОДА функция:

СВОЕГО РОДА("ASCII")

Числовая модель и внутренние функции

Числовые типы основаны на числовых моделях со связанными функциями запроса (значения которых не зависят от значений их аргументов; аргументы используются только для обеспечения вида). Эти функции важны для портативного числового программного обеспечения:

ЦИФРЫ (X)Количество значащих цифр
ЭПСИЛОН (X)Практически ничтожно мало по сравнению с одним (настоящим)
ОГРОМНЫЙ (X)Наибольшее число
МАКСЭКСПОНЕНТ (X)Максимальный показатель модели (реальный)
МИНЭКСПОНЕНТ (X)Минимальная экспонента модели (действительная)
ТОЧНОСТЬ (X)Десятичная точность (действительная, комплексная)
РАДИКС (X)База модели
ДИАПАЗОН (X)Диапазон десятичной экспоненты
Крошечный (X)Наименьшее положительное число (реальное)

Скалярные переменные

Скалярный переменные соответствующие пяти внутренним типам определены следующим образом:

ЦЕЛОЕ(СВОЕГО РОДА=2) :: яНАСТОЯЩИЙ(СВОЕГО РОДА=длинный) :: аСЛОЖНЫЙ         :: ТекущийЛОГИЧЕСКИЙ         :: ПравдаПЕРСОНАЖ(LEN=20) :: словоПЕРСОНАЖ(LEN=2, СВОЕГО РОДА=Кандзи) :: kanji_word

где необязательный СВОЕГО РОДА параметр указывает тип не по умолчанию, а :: нотация отделяет тип и атрибуты от имени (имен) переменных и их необязательных начальных значений, позволяя вводить полную спецификацию и инициализацию переменной в одном операторе (в предыдущих стандартах атрибуты и инициализаторы должны были быть объявлены в нескольких операторах). Хотя это не требуется в приведенных выше примерах (поскольку здесь нет дополнительных атрибутов и инициализации), большинство программистов на языке Fortran-90 приобретают привычку использовать его везде.

LEN= спецификатор применим только к ПЕРСОНАЖs и указывает длину строки (заменяя более старые * len форма). Явный KIND = и LEN = спецификаторы не обязательны:

ПЕРСОНАЖ(2, Кандзи) :: kanji_word

работает так же хорошо.

Есть и другие интересные особенности персонажа. Как подстрока, как в

ПЕРСОНАЖ(80) :: линия   ... = линия(я:я)                     ! подстрока

раньше было возможно, так что теперь подстрока

'0123456789'(я:я)

Также разрешены строки нулевой длины:

линия(я:я-1)       ! строка нулевой длины

Наконец, есть набор встроенных символьных функций, например

АЧАРIACHAR (для набора ASCII)
ADJUSTLРЕГУЛИРОВКА
LEN_TRIMИНДЕКС (s1; s2; НАЗАД =. ИСТИНА.)
ПОВТОРЕНИЕСКАНИРОВАТЬ(для одного из набора)
ПОДРЕЗАТЬПРОВЕРЯТЬ(для всего комплекта)

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

Для производных типов данных сначала должна быть определена форма типа:

ТИП человек   ПЕРСОНАЖ(10) имя   НАСТОЯЩИЙ возрастКОНЕЦ ТИП человек

а затем могут быть определены переменные этого типа:

ТИП(человек) ты, мне

Чтобы выбрать компоненты производного типа, % квалификатор используется:

ты%возраст

Литеральные константы производных типов имеют вид Имя типа (1stComponentLiteral, 2ndComponentLiteral, ...):

ты = человек('Смит', 23.5)

который известен как конструктор конструкции. Определения могут относиться к ранее определенному типу:

ТИП точка   НАСТОЯЩИЙ Икс, уКОНЕЦ ТИП точкаТИП треугольник   ТИП(точка) а, б, cКОНЕЦ ТИП треугольник

и для переменной типа треугольник, как в

ТИП(треугольник) т

каждый компонент типа точка доступен как

т%а   т%б   т%c

которые, в свою очередь, имеют конечные компоненты типа real:

т%а%Икс   т%а%у   т%б%Икс   так далее.

(Обратите внимание, что % квалификатор был выбран, а не точка (.) из-за потенциальной двусмысленности с обозначениями операторов, например .ИЛИ ЖЕ.).

Неявная и явная типизация

Если не указано иное, все переменные, начинающиеся с букв I, J, K, L, M и N, используются по умолчанию. ЦЕЛОЕs, а все остальные по умолчанию НАСТОЯЩИЙ; другие типы данных должны быть явно объявлены. Это известно как неявная типизация и является наследием ранних дней FORTRAN. Эти значения по умолчанию могут быть отменены IMPLICIT TypeName (CharacterRange) утверждения, например:

СКРЫТЫЙ СЛОЖНЫЙ(Z)СКРЫТЫЙ ПЕРСОНАЖ(А-B)СКРЫТЫЙ НАСТОЯЩИЙ(C-ЧАС,N-Y)

Однако рекомендуется явно вводить все переменные, и это можно сделать принудительно, вставив оператор ПОДРАЗУМЕВАЕМЫЙ НЕТв начале каждого программного блока.

Массивы

Массивы считаются самостоятельными переменными. Каждый массив характеризуется своим тип, классифицировать, и форма (который определяет размеры каждого измерения). Границы каждого измерения по умолчанию равны 1 и размер, но можно явно указать произвольные границы. ИЗМЕРЕНИЕ ключевое слово является необязательным и считается атрибутом; если он опущен, форма массива должна быть указана после имени переменной массива. Например,

НАСТОЯЩИЙ:: а(10)ЦЕЛОЕ, ИЗМЕРЕНИЕ(0:100, -50:50) :: карта

объявляет два массива, ранг-1 и ранг-2, элементы которых находятся в порядок столбцов. Элементами являются, например,

а(1)  а(я*j)

и являются скалярами. Индексы могут быть любым скалярным целочисленным выражением.

Разделы являются частями переменных массива и сами являются массивами:

а(я:j)               ! ранг одинкарта(я:j, k:л:м)      ! второй ранга(карта(я, k:л))       ! векторный индекса(3:2)               ! нулевая длина

Целые массивы и секции массивов являются объектами с массивами. Доступны константы (конструкторы) с массивом значений, заключенные в (/ ... /):

(/ 1, 2, 3, 4 /)(/ ( (/ 1, 2, 3 /), я = 1, 4) /)(/ (я, я = 1, 9, 2) /)(/ (0, я = 1, 100) /)(/ (0.1*я, я = 1, 10) /)

используя нотацию неявного цикла DO. Fortran 2003 позволяет использовать скобки: [1, 2, 3, 4] и [([1,2,3], i = 1,4)]вместо первых двух приведенных выше примеров, и многие компиляторы сейчас это поддерживают. Производный тип данных, конечно, может содержать компоненты массива:

ТИП триплет   НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(3) :: вершинаКОНЕЦ ТИП триплетТИП(триплет), ИЗМЕРЕНИЕ(4) :: т

так что

  • т(2) скаляр (структура)
  • т(2)%вершина является компонентом массива скаляра

Инициализация данных

Переменным можно присвоить начальные значения, как указано в заявлении спецификации:

НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(3) :: а = (/ 0.1, 0.2, 0.3 /)

и начальное значение по умолчанию может быть присвоено компоненту производного типа данных:

ТИП триплет   НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(3) :: вершина = 0.0КОНЕЦ ТИП триплет

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

НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(3) :: точка = (/ 0.0, 1.0, -1.0 /)

Это объявление эквивалентно

НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(3), СПАСТИ :: точка = (/ 0.0, 1.0, -1.0 /)

для локальных переменных внутри подпрограммы или функции. Атрибут SAVE заставляет локальные переменные сохранять свое значение после вызова процедуры, а затем инициализировать переменную сохраненным значением после возврата к процедуре.

Атрибут PARAMETER

Именованную константу можно указать напрямую, добавив ПАРАМЕТР атрибут и постоянные значения в оператор типа:

НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(3), ПАРАМЕТР :: поле = (/ 0., 1., 2. /)ТИП(триплет), ПАРАМЕТР :: т = триплет( (/ 0., 0., 0. /) )

Заявление DATA

В ДАННЫЕ оператор может использоваться для скаляров, а также для массивов и переменных производного типа. Это также единственный способ инициализировать только части таких объектов, а также инициализировать двоичными, восьмеричными или шестнадцатеричными значениями:

ТИП(триплет) :: t1, t2ДАННЫЕ t1/триплет( (/ 0., 1., 2. /) )/, t2%вершина(1)/123./Массив данных(1:64) / 64*0/ДАННЫЕ я, j, k/ B'01010101', О'77', Z'ff'/

Выражения инициализации

Значения, используемые в ДАННЫЕ и ПАРАМЕТР операторы или с этими атрибутами являются постоянными выражениями, которые могут включать ссылки на: конструкторы массивов и структур, элементарные встроенные функции с целочисленными или символьными аргументами и результатами, а также шесть трансформационных функций REPEAT, SELECTED_INT_KIND, TRIM, SELECTED_REAL_KIND, RESHAPE и ПЕРЕДАЧА (видеть Внутренние процедуры ):

ЦЕЛОЕ, ПАРАМЕТР :: длинный = SELECTED_REAL_KIND(12),   &                      множество(3) = (/ 1, 2, 3 /)

Выражения спецификации

Можно указать детали переменных, используя любое непостоянное, скалярное, целочисленное выражение, которое также может включать ссылки на функции запроса:

ПОДРОБНЕЕ s(б, м, c)   ИСПОЛЬЗОВАТЬ мод                                 ! содержит   НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(:, :)             :: б   НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(UBOUND(б, 1) + 5) :: Икс   ЦЕЛОЕ                           :: м   ПЕРСОНАЖ(LEN=*)                  :: c   ПЕРСОНАЖ(LEN= м + LEN(c))        :: cc   НАСТОЯЩИЙ (SELECTED_REAL_KIND(2*ТОЧНОСТЬ(а))) :: z

Выражения и присвоения

Скалярный числовой

Доступны обычные арифметические операторы - +, -, *, /, ** (здесь в порядке возрастания приоритета).

При необходимости используются круглые скобки, чтобы указать порядок оценки:

а*б + c     ! * первыйа*(б + c)   ! + первый

Правила для скалярное числовое выражения и присваивания соответствуют типам, отличным от значений по умолчанию. Таким образом, числовые выражения и правила присваивания смешанного режима включают в себя параметры типов различных типов ожидаемым образом:

real2 = целое 0 + реальный1

обращает целое 0 к реальной стоимости того же вида, что и реальный1; результат того же типа и преобразуется в вид real2 для переуступки.

Эти функции доступны для контролируемых округление вещественных чисел в целые:

  • NINT: округлить до ближайшего целого числа, вернуть целочисленный результат
  • ANINT: округлить до ближайшего целого числа, вернуть реальный результат
  • INT: truncate (округлить до нуля), вернуть целочисленный результат
  • AINT: truncate (округлить до нуля), вернуть реальный результат
  • ПОТОЛОК: наименьшее целое значение не меньше аргумента (округлить) (Fortran-90)
  • ЭТАЖ: наибольшее целое значение не больше аргумента (округлить в меньшую сторону) (Fortran-90)

Скалярные реляционные операции

За скалярный реляционный операции числовых типов, есть набор встроенных операторов:

<<= == / =>> =. LT. .LE. .EQ. .NE. .GT. .GE.

(приведенные выше формы являются новыми для Fortran-90, а более старые эквивалентные формы приведены ниже). Примеры выражений:

а < б .И. я /= j      ! для числовых переменныхфлаг = а == б           ! для флагов логических переменных

Скалярные символы

В случае скалярные символы и учитывая ПЕРСОНАЖ(8) результат

это законно писать

результат(3:5) = результат(1:3)    ! допускается перекрытиерезультат(3:3) = результат(3:2)    ! нет присвоения нулевой строки

Объединение выполняется оператором «//».

результат = 'abcde'//'123'имя файла = результат//'.dat'

Типы производных данных

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

ТИП строка80   ЦЕЛОЕ длина   ПЕРСОНАЖ(80) ценитьКОНЕЦ ТИП строка80ПЕРСОНАЖ::    char1, char2, char3ТИП(строка80):: str1,  ул2,  ул3

мы можем написать

ул3  = str1//ул2       ! должен определить операциюул3  = str1.concat.ул2 ! должен определить операциюchar3 = char2//char3     ! только внутренний операторул3  = char1            ! должен определить назначение

Обратите внимание на "перегружен "использование внутреннего символа // и названный оператор, .concat. . Разница между этими двумя случаями состоит в том, что для внутреннего токена оператора применяются обычные правила приоритета, тогда как для именованных операторов приоритет является наивысшим для унарных операторов или самым низким для двоичных. В

vector3 = матрица    *    vector1  + vector2vector3 =(матрица .раз. vector1) + vector2

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

ИНТЕРФЕЙС ОПЕРАТОР(//) ! Перегружает // оператор при вызове процедуры string_concat  ПРОЦЕДУРА МОДУЛЯ string_concatКОНЕЦ ИНТЕРФЕЙСА

Функция конкатенации строк является более сложной версией того, что уже было показано в Основы. Обратите внимание, что для обработки состояния ошибки, которое возникает, когда две строки вместе превышают предварительно установленный предел в 80 символов, было бы безопаснее использовать подпрограмму для выполнения конкатенации (в этом случае перегрузка оператора не применима).

МОДУЛЬ string_type   ПОДРАЗУМЕВАЕМЫЙ НЕТ   ТИП строка80      ЦЕЛОЕ длина      ПЕРСОНАЖ(LEN=80)   :: string_data   КОНЕЦ ТИП строка80   ИНТЕРФЕЙС НАЗНАЧЕНИЕ(=)      ПРОЦЕДУРА МОДУЛЯ c_to_s_assign, s_to_c_assign   КОНЕЦ ИНТЕРФЕЙСА   ИНТЕРФЕЙС ОПЕРАТОР(//)      ПРОЦЕДУРА МОДУЛЯ string_concat   КОНЕЦ ИНТЕРФЕЙСАСОДЕРЖИТ   ПОДРОБНЕЕ c_to_s_assign(s, c)      ТИП (строка80), НАМЕРЕНИЕ(ИЗ)    :: s      ПЕРСОНАЖ(LEN=*), НАМЕРЕНИЕ(В)  :: c      s%string_data = c      s%длина = LEN(c)   КОНЕЦ ПОДПРОГРАММЫ c_to_s_assign   ПОДРОБНЕЕ s_to_c_assign(c, s)      ТИП (строка80), НАМЕРЕНИЕ(В)     :: s      ПЕРСОНАЖ(LEN=*), НАМЕРЕНИЕ(ИЗ) :: c      c = s%string_data(1:s%длина)   КОНЕЦ ПОДПРОГРАММЫ s_to_c_assign   ТИП(строка80) НАЗНАЧЕНИЕ string_concat(s1, s2)      ТИП(строка80), НАМЕРЕНИЕ(В) :: s1, s2      ТИП(строка80) :: s      ЦЕЛОЕ :: n1, n2      ПЕРСОНАЖ(160) :: ctot      n1 = LEN_TRIM(s1%string_data)      n2 = LEN_TRIM(s2%string_data)      ЕСЛИ (n1+n2 <= 80) тогдаs%string_data = s1%string_data(1:n1)//s2%string_data(1:n2)      ЕЩЕ  ! Это состояние ошибки, которое следует обработать - пока просто усеките         ctot = s1%string_data(1:n1)//s2%string_data(1:n2)         s%string_data = ctot(1:80)      КОНЕЦ ЕСЛИs%длина = LEN_TRIM(s%string_data)      string_concat = s   КОНЕЦ ФУНКЦИИ string_concatКОНЕЧНЫЙ МОДУЛЬ string_typeПРОГРАММА главный   ИСПОЛЬЗОВАТЬ string_type   ТИП(строка80) :: s1, s2, s3   ВЫЗОВ c_to_s_assign(s1,'Меня зовут')   ВЫЗОВ c_to_s_assign(s2,'Линус Торвальдс')   s3 = s1//s2   ЗАПИСЫВАТЬ(*,*) 'Результат: ',s3%string_data   ЗАПИСЫВАТЬ(*,*) 'Длина: ',s3%длинаКОНЕЦ ПРОГРАММЫ

Такие определенные операторы необходимы для выражений, которые разрешены также в конструкторах структур (см. Типы производных данных ):

str1 = нить(2, char1//char2)  ! конструктор конструкции

Массивы

В случае массивов, пока они имеют одну и ту же форму (согласованные), операции и присваивания расширяются очевидным образом на поэлементной основе. Например, учитывая декларации

НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(10, 20) :: а, б, cНАСТОЯЩИЙ, ИЗМЕРЕНИЕ(5)      :: v, шЛОГИЧЕСКИЙ флаг(10, 20)

это можно написать:

а = б                                       ! назначение всего массиваc = а/б                                     ! деление и присвоение всего массиваc = 0.                                      ! присвоение скалярного значения всему массивуш = v + 1.                                  ! дополнение всего массива к скалярному значениюш = 5/v + а(1:5, 5)                         ! деление массива и добавление к разделуфлаг = а==б                                 ! реляционный тест и назначение всего массиваc(1:8, 5:10) = а(2:9, 5:10) + б(1:8, 15:20) ! добавление и присвоение раздела массиваv(2:5) = v(1:4)                             ! присвоение перекрывающихся разделов

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

Некоторые реальные встроенные функции, которые полезны для числовых вычислений:

ПОТОЛОЧНЫЙ ПОЛ MODULO (также целое число)ПОКАЗАТЕЛЬНАЯ ДОЛЯБЛИЖАЙШЕЕ РАССТОЯНИЕSCALE SET_EXPONENT

Это значения массива для аргументов массива (элементарные), как и все FORTRAN 77 функции (кроме LEN):

INT НАСТОЯЩИЙ CMPLXAINT ANINT NINTЗНАК ABS MODРАЗМЕР МАКС МИНЖУРНАЛ SQRT EXPLOG10           SIN COSТАН АСИН АКОСЗАГАР ATAN2SINH COSH TANHAIMAG CONJGLGE LGT LLELLT ICHAR CHARИНДЕКС

(последние семь - для персонажей).

Управляющие заявления

Ветвление и условия

Простой ИДТИ К метка существует, но обычно его избегают - в большинстве случаев более конкретная конструкция ветвления реализует ту же логику с большей ясностью.

Простая условная проверка - это ЕСЛИ утверждение: ЕСЛИ (а > б) Икс = у

Полноценный ЕСЛИ конструкция иллюстрируется

ЕСЛИ (я < 0) ТОГДА   ЕСЛИ (j < 0) ТОГДАИкс = 0.   ЕЩЕz = 0.   КОНЕЦ ЕСЛИELSE IF (k < 0) ТОГДАz = 1.ЕЩЕИкс = 1.КОНЕЦ ЕСЛИ

CASE конструкция

В ДЕЛО конструкция является заменой вычисленного ИДТИ К, но он лучше структурирован и не требует использования меток операторов:

ВЫБЕРИТЕ СЛУЧАЙ (номер)       ! число целочисленного типаДЕЛО (:-1)                 ! все значения ниже 0   n_sign = -1ДЕЛО (0)                   ! только 0   n_sign = 0ДЕЛО (1:)                  ! все значения выше 0   n_sign = 1КОНЕЦ ВЫБОРА

Каждый ДЕЛО Список селекторов может содержать список и / или диапазон целых чисел, символов или логических констант, значения которых не могут перекрываться внутри или между селекторами:

ДЕЛО (1, 2, 7, 10:17, 23)

Доступны значения по умолчанию:

ДЕЛО ДЕФОЛТ

Есть только одна оценка и только одно совпадение.

ДЕЙСТВИТЕЛЬНО построить

Упрощенная, но достаточная форма ДЕЛАТЬ конструкция иллюстрируется

внешний: ДЕЛАТЬвнутренний:    ДЕЛАТЬ я = j, k, л      ! от j до k с шагом l (l необязательно)             :             ЕСЛИ (...) ЦИКЛ             :             ЕСЛИ (...) ВЫХОД внешний             :          КОНЕЦ ДЕЛАТЬ внутренний       КОНЕЦ ДЕЛАТЬ внешний

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

Многие, но не все, простые циклы могут быть заменены выражениями массивов и присваиваниями или новыми встроенными функциями. Например

малыш = 0.ДЕЛАТЬ я = м, п   малыш = малыш + а(я)КОНЕЦ ДЕЛАТЬ

становится просто малыш = СУММ( а(м:п) )

Программные единицы и процедуры

Определения

Чтобы обсудить эту тему, нам понадобятся некоторые определения. С логической точки зрения исполняемая программа состоит из одного основная программа и ноль или больше подпрограммы (или же процедуры) - они что-то делают. Подпрограммы либо функции или же подпрограммы, которые либо внешний внутренний или же модуль подпрограммы. (Внешние подпрограммы - это то, что мы знали из FORTRAN 77.)

Однако с организационной точки зрения полная программа состоит из программные единицы. Это либо основные программы, внешние подпрограммы или же модули и может быть скомпилирован отдельно.

Пример основной (и полной) программы:

ПРОГРАММА тест   РАСПЕЧАТАТЬ *, 'Привет, мир!'КОНЕЦ ПРОГРАММЫ тест

Примером основной программы и внешней подпрограммы, образующих исполняемую программу, является

ПРОГРАММА тест   ВЫЗОВ print_messageКОНЕЦ ПРОГРАММЫ тестПОДРОБНЕЕ print_message   РАСПЕЧАТАТЬ *, 'Привет, мир!'КОНЕЦ ПОДПРОГРАММЫ print_message

Форма функции

НАЗНАЧЕНИЕ имя(arg1, arg2) ! ноль или более аргументов   :                        имя = ...   :КОНЕЦ ФУНКЦИИ имя

Форма ссылки на функцию Икс = имя(а, б)

Внутренние процедуры

Внутренняя подпрограмма - это одна содержал в другом (максимум на одном уровне вложенности) и обеспечивает замену функции оператора:

ПОДРОБНЕЕ внешний   НАСТОЯЩИЙ Икс, у   :СОДЕРЖИТ   ПОДРОБНЕЕ внутренний      НАСТОЯЩИЙ у      у = Икс + 1.      :   КОНЕЦ ПОДПРОГРАММЫ внутренний     ! SUBROUTINE обязательныйКОНЕЦ ПОДПРОГРАММЫ внешний

Мы говорим что внешний это хозяин из внутренний, и это внутренний получает доступ к объектам в внешний к принимающая ассоциация (например, чтобы Икс), в то время как у это местный переменная для внутренний.

В объем названного объекта - это аналитическая единица, здесь внешний меньше внутренний, и внутренний.

Имена программных модулей и внешних процедур: Глобальный, а имена подразумеваемых переменных DO имеют область действия оператора, который их содержит.

Модули

Модули используются для упаковки

  • глобальные данные (заменяет COMMON и BLOCK DATA из Fortran 77);
  • определения типов (сами по себе единица области видимости);
  • подпрограммы (которые среди прочего заменяют использование ENTRY из Fortran 77);
  • интерфейсные блоки (другая единица определения объема, см. Блоки интерфейса );
  • группы имен (см. любой учебник).

Примером модуля, содержащего определение типа, интерфейсный блок и подпрограмму функции, является

МОДУЛЬ interval_arithmetic   ТИП интервал      НАСТОЯЩИЙ ниже, верхний   КОНЕЦ ТИП интервал   ИНТЕРФЕЙС ОПЕРАТОР(+)       ПРОЦЕДУРА МОДУЛЯ add_intervals   КОНЕЦ ИНТЕРФЕЙСА   :СОДЕРЖИТ   НАЗНАЧЕНИЕ add_intervals(а,б)      ТИП(интервал), НАМЕРЕНИЕ(В) :: а, б      ТИП(интервал) add_intervals      add_intervals%ниже = а%ниже + б%ниже      add_intervals%верхний = а%верхний + б%верхний   КОНЕЦ ФУНКЦИИ add_intervals             ! ФУНКЦИЯ обязательна   :КОНЕЧНЫЙ МОДУЛЬ interval_arithmetic

и простое заявление

     ИСПОЛЬЗОВАТЬ interval_arithmetic

обеспечивает использовать ассоциацию ко всем объектам модуля. Подпрограммы модуля, в свою очередь, могут содержать внутренние подпрограммы.

Контроль доступности

В ОБЩЕСТВЕННЫЙ и ЧАСТНЫЙ Атрибуты используются в спецификациях в модулях для ограничения объема сущностей. Форма атрибута

НАСТОЯЩИЙ, ОБЩЕСТВЕННЫЙ     :: Икс, у, z           ! дефолтЦЕЛОЕ, ЧАСТНЫЙ :: ты, v, ш

и форма выписки

ОБЩЕСТВЕННЫЙ  :: Икс, у, z, ОПЕРАТОР(.Добавить.)ЧАСТНЫЙ :: ты, v, ш, НАЗНАЧЕНИЕ(=), ОПЕРАТОР(*)

Форма оператора должна использоваться для ограничения доступа к операторам, а также может использоваться для изменения общего значения по умолчанию:

ЧАСТНЫЙ                        ! устанавливает по умолчанию для модуляОБЩЕСТВЕННЫЙ  :: только это

Для производных типов есть три возможности: тип и его компоненты - все PUBLIC, тип - PUBLIC и его компоненты PRIVATE (виден только тип, и его детали можно легко изменить), или все это PRIVATE (для внутреннего использования только в модуле):

МОДУЛЬ мой   ЧАСТНЫЙ   ТИП, ОБЩЕСТВЕННЫЙ :: список      НАСТОЯЩИЙ Икс, у      ТИП(список), УКАЗАТЕЛЬ :: следующий   КОНЕЦ ТИП список   ТИП(список) :: дерево   :КОНЕЧНЫЙ МОДУЛЬ мой

В ИСПОЛЬЗОВАТЬ цель оператора - получить доступ к сущностям в модуле. У него есть параметры для разрешения конфликтов имен, если импортированное имя совпадает с локальным:

ИСПОЛЬЗОВАТЬ мой, local_list => список

или ограничить используемые сущности определенным набором:

ИСПОЛЬЗОВАТЬ мой, ТОЛЬКО : список

Они могут быть объединены:

ИСПОЛЬЗОВАТЬ мой, ТОЛЬКО : local_list => список

Аргументы

Мы можем указать цель фиктивных аргументов:

ПОДРОБНЕЕ тасовать (ncards, открытки)  ЦЕЛОЕ, НАМЕРЕНИЕ(В)  :: ncards  ЦЕЛОЕ, НАМЕРЕНИЕ(ИЗ), ИЗМЕРЕНИЕ(ncards) :: открытки

Также возможен INOUT: здесь фактический аргумент должен быть переменной (в отличие от случая по умолчанию, когда он может быть константой).

Аргументы могут быть необязательными:

ПОДРОБНЕЕ mincon(п, ж, Икс, верхний, ниже, равенства, неравенство, выпуклый, xstart)   НАСТОЯЩИЙ, НЕОБЯЗАТЕЛЬНЫЙ, ИЗМЕРЕНИЕ :: верхний, ниже   :   ЕСЛИ (НАСТОЯЩЕЕ ВРЕМЯ(ниже)) ТОГДА   ! проверка на наличие действительного аргумента   :

позволяет нам звонить mincon к

ВЫЗОВ mincon (п, ж, Икс, верхний)

Аргументы могут быть ключевыми, а не позиционными (которые идут первыми):

ВЫЗОВ mincon(п, ж, Икс, равенства=0, xstart=x0)

Необязательные и ключевые аргументы обрабатываются явными интерфейсами, то есть с внутренними или модульными процедурами или с интерфейсными блоками.

Блоки интерфейса

Любая ссылка на внутреннюю подпрограмму или подпрограмму модуля осуществляется через интерфейс, который является «явным» (то есть компилятор может видеть все детали). Ссылка на внешнюю (или фиктивную) процедуру обычно является «неявной» (детали предполагаются компилятором). Однако и в этом случае мы можем предоставить явный интерфейс. Это копия заголовка, спецификаций и оператора END соответствующей процедуры, помещенная в модуль или вставленная напрямую:

НАСТОЯЩИЙ НАЗНАЧЕНИЕ минимум(а, б, func)  ! возвращает минимальное значение функции func (x)  ! в интервале (a, b)  НАСТОЯЩИЙ, НАМЕРЕНИЕ(в) :: а, б  ИНТЕРФЕЙСНАСТОЯЩИЙ НАЗНАЧЕНИЕ func(Икс)      НАСТОЯЩИЙ, НАМЕРЕНИЕ(В) :: Икс    КОНЕЦ ФУНКЦИИ func  КОНЕЦ ИНТЕРФЕЙСАНАСТОЯЩИЙ ж,Икс  :  ж = func(Икс)   ! вызов пользовательской функции.  :КОНЕЦ ФУНКЦИИ минимум

Явный интерфейс обязателен для

  • необязательные и ключевые аргументы;
  • POINTER и TARGET аргументы (см. Указатели );
  • УКАЗАТЕЛЬ результат функции;
  • аргументы массива нового стиля и функции массива (Обработка массивов ).

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

В общем, лучший способ обеспечить явный интерфейс процедуры - это либо поместить соответствующую процедуру в модуль, либо использовать ее в качестве внутренней процедуры.

Перегрузка и общие интерфейсы

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

ИНТЕРФЕЙС гамма                   ! родовое имя   НАЗНАЧЕНИЕ sgamma(Икс)              ! конкретное имя      НАСТОЯЩИЙ (SELECTED_REAL_KIND( 6)) sgamma, Икс   КОНЕЦ   НАЗНАЧЕНИЕ дгамма(Икс)              ! конкретное имя      НАСТОЯЩИЙ (SELECTED_REAL_KIND(12)) дгамма, Икс   КОНЕЦКОНЕЦ ИНТЕРФЕЙСА

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

ИНТЕРФЕЙС гаммаПРОЦЕДУРА МОДУЛЯ sgamma, дгаммаКОНЕЦ ИНТЕРФЕЙСА

Мы можем использовать существующие имена, например SIN, и компилятор выбирает правильную ассоциацию.

Мы уже видели использование интерфейсных блоков для определенных операторов и присваивания (см. Модули ).

Рекурсия

Косвенная рекурсия полезна для многомерного интегрирования. За

объем = интегрировать(фу, ybounds)

Мы могли бы иметь

РЕКУРСИВНАЯ ФУНКЦИЯ интегрировать(ж, границы)   ! Интегрируем f (x) от оценок (1) до оценок (2)   НАСТОЯЩИЙ интегрировать   ИНТЕРФЕЙС      НАЗНАЧЕНИЕ ж(Икс)         НАСТОЯЩИЙ ж, Икс      КОНЕЦ ФУНКЦИИ ж   КОНЕЦ ИНТЕРФЕЙСАНАСТОЯЩИЙ, ИЗМЕРЕНИЕ(2), НАМЕРЕНИЕ(В) :: границы   :КОНЕЦ ФУНКЦИИ интегрировать

и интегрировать f (x, y) над прямоугольником:

НАЗНАЧЕНИЕ фу(у)   ИСПОЛЬЗОВАТЬ func           ! модуль func содержит функцию f   НАСТОЯЩИЙ фу, у   Yval = у   фу = интегрировать(ж, xbounds)КОНЕЦ

Прямая рекурсия - это когда процедура вызывает сама себя, как в

РЕКУРСИВНАЯ ФУНКЦИЯ факториал(п) РЕЗУЛЬТАТ(res)   ЦЕЛОЕ res, п   ЕСЛИ(п.Эквалайзер.0) ТОГДАres = 1   ЕЩЕres = п*факториал(п-1)   КОНЕЦ ЕСЛИКОНЕЦ

Здесь отметим РЕЗУЛЬТАТ оговорка и испытание на прекращение.

Чистые процедуры

Это функция для параллельных вычислений.

В оператор FORALL и конструкция любые побочные эффекты в функции могут препятствовать оптимизации параллельного процессора - порядок выполнения назначений может повлиять на результаты. Чтобы контролировать эту ситуацию, мы добавляем ЧИСТЫЙ ключевое слово для ПОДРОБНЕЕ или же НАЗНАЧЕНИЕ заявление - утверждение, что процедура (выраженная просто):

  • не изменяет глобальную переменную,
  • не выполняет ввод / вывод,
  • не имеет сохраненных переменных (переменные с СПАСТИ атрибут, который сохраняет значения между вызовами), и
  • для функций не изменяет ни один из своих аргументов.

Компилятор может проверить, что это так, как в

ЧИСТАЯ ФУНКЦИЯ вычислить (Икс)

Все внутренние функции чистые.

Обработка массивов

Обработка массивов включена в Фортран по двум основным причинам:

  • удобство нотации, которое он обеспечивает, приближая код к основной математической форме;
  • за дополнительные возможности оптимизации он дает компиляторам (хотя есть много возможностей и для ухудшающей оптимизации!).

В то же время были добавлены основные расширения функциональности в этой области. Мы уже встречали целые массивы выше # Массивы 1 и тут # Массивы 2 - сейчас развиваем тему.

Массивы нулевого размера

Массив нулевого размера обрабатывается Фортраном как законный объект без специального программирования со стороны программиста. Таким образом, в

ДЕЛАТЬ я = 1,п   Икс(я) = б(я) / а(я, я)   б(я+1:п) = б(я+1:п) - а(я+1:п, я) * Икс(я)КОНЕЦ ДЕЛАТЬ

для последней итерации не требуется специального кода, где я = п. Отметим, что массив нулевого размера считается определяемым; однако массив формы (0,2) не соответствует массиву формы (0,3), тогда как Икс(1:0) = 3 является допустимым заявлением "ничего не делать".

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

Это расширение и замена массивов предполагаемого размера. Учитывая фактический аргумент, например:

НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(0:10, 0:20) :: а   :ВЫЗОВ суб(а)

соответствующая спецификация фиктивного аргумента определяет только тип и ранг массива, но не его форму. Эта информация должна быть доступна через явный интерфейс, часто с использованием интерфейсного блока (см. Блоки интерфейса ). Таким образом, мы пишем просто

ПОДРОБНЕЕ суб(да)   НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(:, :) :: да

и это как если бы да были рассчитаны (11,21). Однако мы можем указать любую нижнюю границу и соответственно сопоставить массив.

НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(0:, 0:) :: да

Передается форма, а не границы, где нижняя граница по умолчанию - 1, а верхняя граница по умолчанию - соответствующий экстент.

Автоматические массивы

Частичная замена тех целей, для которых ЭКВИВАЛЕНТНОСТЬ было помещено, предоставлено этим средством, полезно для локальных временных массивов, как в

ПОДРОБНЕЕ замена(а, б)   НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(:)       :: а, б   НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(РАЗМЕР(а)) :: работай   работай = а   а = б   б = работайКОНЕЦ ПОДПРОГРАММЫ замена

Фактическое хранилище обычно хранится в стеке.

ALLOCATABLE и ALLOCATE

Фортран обеспечивает динамическое выделение памяти; он полагается на механизм хранения в куче (и заменяет другое использование ЭКВИВАЛЕНТНОСТЬ). Примером создания рабочего массива для всей программы является

МОДУЛЬ work_array   ЦЕЛОЕ п   НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(:,:,:), РАЗМЕЩЕННЫЙ :: работайКОНЕЧНЫЙ МОДУЛЬПРОГРАММА главный   ИСПОЛЬЗОВАТЬ work_array   ЧИТАТЬ (Вход, *) п   РАСПРЕДЕЛЕНИЕ(работай(п, 2*п, 3*п), СТАТ=положение дел)   :   ОТКЛЮЧИТЬ (работай)

Рабочий массив можно распространять по всей программе через ИСПОЛЬЗОВАТЬ оператор в каждом программном блоке. Мы можем указать явную нижнюю границу и выделить несколько сущностей в одном операторе. Чтобы освободить мертвое хранилище, мы пишем, например,

ОТКЛЮЧИТЬ(а, б)

Освобождение массивов происходит автоматически, когда они выходят за пределы области видимости.

Элементарные операции, задания и процедуры

Мы уже встречались с назначениями и операциями целого массива:

НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(10) :: а, ба = 0.          ! скалярная трансляция; элементарное заданиеб = SQRT(а)     ! результат внутренней функции как объект массива

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

ПРОГРАММА тест   НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(3) :: а = (/ 1., 2., 3./),       &                         б = (/ 2., 2., 2. /),  р   р = ж(а, б)   РАСПЕЧАТАТЬ *, рСОДЕРЖИТ   НАЗНАЧЕНИЕ ж(c, d)   НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(:) :: c, d   НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(РАЗМЕР(c)) :: ж   ж = c*d        ! (или более полезная функция c и d)   КОНЕЦ ФУНКЦИИ жКОНЕЦ ПРОГРАММЫ тест

Элементарные процедуры задаются с помощью скалярных фиктивных аргументов, которые могут вызываться множеством фактических аргументов. В случае функции форма результата - это форма аргументов массива.

Большинство встроенных функций являются элементарными, и Fortran 95 расширяет эту функцию до не внутренних процедур, обеспечивая таким образом эффект записи в Fortran 90 22 различных версий для рангов 0-0, 0-1, 1-0, 1-1, 0- 2,2-0, 2-2, ... 7-7, а также является вспомогательным средством оптимизации на параллельных процессорах. Элементарная процедура должна быть чистой.

ЭЛЕМЕНТНАЯ ПОДПРОТИНКА замена(а, б)   НАСТОЯЩИЙ, НАМЕРЕНИЕ(INOUT)  :: а, б   НАСТОЯЩИЙ                 :: работай   работай = а   а = б   б = работайКОНЕЦ ПОДПРОГРАММЫ замена

Фиктивные аргументы нельзя использовать в выражениях спецификации (см. над ), за исключением аргументов некоторых встроенных функций (BIT_SIZE, СВОЕГО РОДА, LEN, и числовые запросы, (см. ниже ).

КУДА

Часто нам нужно замаскировать задание. Это можно сделать с помощью КУДА, либо как утверждение:

КУДА (а /= 0.0) а = 1.0/а  ! избегать деления на 0

(примечание: тест проводится поэлементно, а не для всего массива) или в виде конструкции:

КУДА (а /= 0.0)   а = 1.0/а   б = а             ! все массивы одинаковой формыКОНЕЦ ГДЕ

или же

КУДА (а /= 0.0)   а = 1.0/аВ другом месте   а = ОГРОМНЫЙ(а)КОНЕЦ ГДЕ

Дальше:

  • разрешается маскировать не только КУДА заявление КУДА построить, но и любой В другом месте заявление, которое он содержит;
  • а КУДА конструкция может содержать любое количество замаскированных В другом месте заявления, но не более одного В другом месте заявление без маски, и оно должно быть последним;
  • КУДА конструкции могут быть вложены друг в друга, просто ДЛЯ ВСЕХ конструкции;
  • а КУДА Оператор присваивания может быть определенным присваиванием при условии, что он является элементарным;
  • а КУДА конструкция может называться так же, как и другие конструкции.

Оператор FORALL и конструкция

Когда ДЕЛАТЬ конструкция выполняется, каждая последующая итерация выполняется по порядку и одна за другой, что препятствует оптимизации на параллельном процессоре.

ДЛЯ ВСЕХ(я = 1:п) а(я, я) = Икс(я)

где отдельные задания могут выполняться в любом порядке и даже одновременно. В ДЛЯ ВСЕХ можно рассматривать как присвоение массива, выраженное с помощью индексов.

ДЛЯ ВСЕХ(я=1:п, j=1:п, у(я,j)/=0.) Икс(j,я) = 1.0/у(я,j)

с условием маскировки.

В ДЛЯ ВСЕХ конструкция позволяет выполнять несколько операторов присваивания по порядку.

а(2:п-1,2:п-1) = а(2:п-1,1:п-2) + а(2:п-1,3:п) + а(1:п-2,2:п-1) + а(3:п,2:п-1)б(2:п-1,2:п-1) = а(2:п-1,2:п-1)

эквивалентно присвоению массива

ДЛЯ ВСЕХ(я = 2:п-1, j = 2:п-1)   а(я,j) = а(я,j-1) + а(я,j+1) + а(я-1,j) + а(я+1,j)   б(я,j) = а(я,j)КОНЕЦ НАЧАЛА

В ДЛЯ ВСЕХ версия более читабельна.

Назначение в ДЛЯ ВСЕХ похоже на присвоение массива: как если бы все выражения были вычислены в любом порядке, хранятся во временном хранилище, тогда все назначения выполняются в любом порядке. Первое утверждение должно быть полностью завершено, прежде чем можно будет начать второе.

А ДЛЯ ВСЕХ могут быть вложенными и включать КУДА.Процедуры, указанные в ДЛЯ ВСЕХ должен быть чистым.

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

Для простого случая, учитывая

НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(100, 100) :: а

мы можем ссылаться на один элемент как, например, а (1, 1). Для производного типа данных, например

ТИП fun_del   НАСТОЯЩИЙ ты   НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(3) :: дуКОНЕЦ ТИП fun_del

мы можем объявить массив этого типа:

ТИП(fun_del), ИЗМЕРЕНИЕ(10, 20) :: деготь

и ссылка вроде деготь(п, 2) это элемент (скаляр!) типа fun_del, но деготь(п, 2)%ду представляет собой массив типа real, а деготь(п, 2)%ду(2) является его элементом. Основное правило, которое следует помнить, заключается в том, что у элемента массива всегда есть нижний индекс или нижние индексы, квалифицирующие как минимум фамилию.

Подобъекты массива (разделы)

Общая форма индекса для секции массива:

      [ниже] : [верхний] [:шагать]

(где [] указывает на необязательный элемент), как в

НАСТОЯЩИЙ а(10, 10)а(я, 1:п)                ! часть одного рядаа(1:м, j)                ! часть одной колонкиа(я, : )                 ! весь ряда(я, 1:п:3)              ! каждый третий элемент строкиа(я, 10:1:-1)            ! ряд в обратном порядкеа( (/ 1, 7, 3, 2 /), 1)  ! векторный индекса(1, 2:11:2)             ! 11 является законным, поскольку не упоминаетсяа(:, 1:7)                ! раздел второго ранга

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

б( (/ 1, 7, 3, 7 /) ) = (/ 1, 2, 3, 4 /)

незаконно. Кроме того, секция с векторным нижним индексом не должна использоваться в качестве фактического аргумента для ИЗ или же INOUT фиктивный аргумент. Массивы массивов не допускаются:

деготь%ду             ! незаконный

Отметим, что на данное значение в массиве можно ссылаться как на элемент, так и как на раздел:

а(1, 1)            ! скаляр (нулевой ранг)а(1:1, 1)          ! секция массива (первый ранг)

в зависимости от обстоятельств или требований. Квалифицируя объекты производного типа, мы получаем элементы или разделы в зависимости от сформулированного ранее правила:

деготь%ты              ! секция массива (компонент структуры)деготь(1, 1)%ты        ! компонент элемента массива

Внутренние функции массивов

Умножение вектора и матрицы

     DOT_PRODUCT Точечное произведение двух массивов первого ранга MATMUL Матричное умножение

Уменьшение массива

     ВСЕ Истинно, если все значения истинны. ЛЮБОЕ Истинно, если любое значение истинно. Пример: IF (ANY (a> b)) THEN COUNT Количество истинных элементов в массиве MAXVAL Максимальное значение в массиве MINVAL Минимальное значение в массиве PRODUCT Продукт элементов массива SUM Сумма элементов массива

Запрос массива

     ALLOCATED Статус выделения массива LBOUND Нижние границы измерения массива SHAPE Форма массива (или скаляр) SIZE Общее количество элементов в массиве UBOUND Верхние границы измерения массива

Построение массива

     MERGE Объединить под маской PACK Упаковать массив в массив ранга 1 под маской SPREAD Реплицировать массив, добавив измерение UNPACK Распаковать массив ранга 1 в массив под маской

Изменение формы массива

     RESHAPE Изменить форму массива

Манипуляции с массивами

     CSHIFT Круговой сдвиг EOSHIFT Конечный сдвиг TRANSPOSE Транспонирование массива второго ранга

Расположение массива

     MAXLOC Расположение первого максимального значения в массиве MINLOC Расположение первого минимального значения в массиве

Указатели

Основы

Указатели - это переменные с УКАЗАТЕЛЬ атрибут; они не являются отдельным типом данных (и поэтому «арифметика с указателями» невозможна).

НАСТОЯЩИЙ, УКАЗАТЕЛЬ :: вар

Концептуально они представляют собой дескриптор, перечисляющий атрибуты объектов (целей), на которые может указывать указатель, и адрес цели, если таковой имеется. У них нет связанного хранилища, пока оно не будет выделено или иным образом не связано (путем назначения указателя, см. ниже ):

РАСПРЕДЕЛЕНИЕ (вар)

и они автоматически разыменовываются, поэтому специальный символ не требуется. В

вар = вар + 2.3

значение цели var используется и изменяется. Указатели не могут быть переданы через ввод-вывод. Заявление

ЗАПИСЫВАТЬ *, вар

записывает значение цели var, а не сам дескриптор указателя.

Указатель может указывать на другой указатель и, следовательно, на его цель, или на статический объект, имеющий ЦЕЛЬ атрибут:

НАСТОЯЩИЙ, УКАЗАТЕЛЬ :: объектНАСТОЯЩИЙ, ЦЕЛЬ  :: target_objвар => объект                  ! присвоение указателявар => target_obj

но они строго типизированы:

ЦЕЛОЕ, УКАЗАТЕЛЬ :: int_varвар => int_var                 ! незаконно - типы должны совпадать

и аналогично для массивов ранги, а также тип должны согласовываться.

Указатель может быть компонентом производного типа:

ТИП записи                       ! тип для разреженной матрицы   НАСТОЯЩИЙ ценитьЦЕЛОЕ индексТИП(Вход), УКАЗАТЕЛЬ :: следующий  ! обратите внимание на рекурсиюEND TYPE запись

и мы можем определить начало связанной цепочки таких записей:

ТИП(Вход), УКАЗАТЕЛЬ :: цепь

После соответствующих распределений и определений первые две записи могут быть адресованы как

цепь%ценить цепь%следующий%ценитьцепь%индекс цепь%следующий%индексцепь%следующий            цепь%следующий%следующий

но обычно мы определяем дополнительные указатели, чтобы указывать, например, на первую и текущую записи в списке.

Ассоциация

Статус ассоциации указателя - один из

  • undefined (начальное состояние);
  • связанный (после выделения или присвоения указателя);
  • диссоциирован:
    ОТКЛЮЧИТЬ (п, q)  ! для возврата храненияУДАЛИТЬ (п, q)     ! для установки в "ноль"

Следует проявлять осторожность, чтобы указатель не оставался «болтающимся» при использовании ОТКЛЮЧИТЬ на своей цели, не обнуляя любой другой указатель, ссылающийся на нее.

Внутренняя функция СВЯЗАННЫЕ может проверить статус ассоциации определенного указателя:

ЕСЛИ (СВЯЗАННЫЕ(указатель)) ТОГДА

или между определенным указателем и определенной целью (которая сама может быть указателем):

ЕСЛИ (СВЯЗАННЫЕ(указатель, цель)) ТОГДА

Альтернативный способ инициализировать указатель, также в операторе спецификации, - использовать НОЛЬ функция:

НАСТОЯЩИЙ, УКАЗАТЕЛЬ, ИЗМЕРЕНИЕ(:) :: вектор => НОЛЬ() ! время компиляциивектор => НОЛЬ()                                ! время выполнения

Указатели в выражениях и присвоениях

Для внутренних типов мы можем «перемещать» указатели по разным наборам целевых данных, используя один и тот же код без какого-либо перемещения данных. Учитывая матричную манипуляцию у = B C z, мы можем написать следующий код (хотя в этом случае того же результата можно было бы проще достичь другими способами):

НАСТОЯЩИЙ, ЦЕЛЬ  :: б(10,10), c(10,10), р(10), s(10), z(10)НАСТОЯЩИЙ, УКАЗАТЕЛЬ :: а(:,:), Икс(:), у(:)ЦЕЛОЕ мульт:ДЕЛАТЬ мульт = 1, 2   ЕСЛИ (мульт == 1) ТОГДАу => р              ! нет движения данных      а => c      Икс => z   ЕЩЕу => s              ! нет движения данных      а => б      Икс => р   КОНЕЦ ЕСЛИу = MATMUL(а, Икс)       ! общий расчетКОНЕЦ ДЕЛАТЬ

Для объектов производного типа мы должны различать указатель и обычное присваивание. В

ТИП(Вход), УКАЗАТЕЛЬ :: первый, Текущий:первый => Текущий

назначение заставляет сначала указывать на текущий, тогда как

первый =  Текущий

сначала перезаписывает ток, что эквивалентно

первый%ценить = Текущий%ценитьпервый%индекс = Текущий%индекспервый%следующий => Текущий%следующий

Аргументы указателя

Если фактический аргумент является указателем, то, если фиктивный аргумент также является указателем,

  • он должен иметь такой же ранг,
  • он получает свой статус ассоциации из фактического аргумента,
  • он возвращает свой окончательный статус ассоциации фактическому аргументу (примечание: цель может быть неопределенной!),
  • у него может не быть НАМЕРЕНИЕ атрибут (было бы неоднозначно),
  • для этого требуется блок интерфейса.

Если фиктивный аргумент не является указателем, он становится связанным с целью фактического аргумента:

   НАСТОЯЩИЙ, УКАЗАТЕЛЬ :: а (:,:)      :   РАСПРЕДЕЛЕНИЕ (а(80, 80))      :   ВЫЗОВ суб(а)      :ПОДРОБНЕЕ суб(c)   НАСТОЯЩИЙ c(:, :)

Функции указателя

Результаты функции также могут иметь УКАЗАТЕЛЬ атрибут; это полезно, если размер результата зависит от вычислений, выполняемых в функции, как в

ИСПОЛЬЗОВАТЬ data_handlerНАСТОЯЩИЙ Икс(100)НАСТОЯЩИЙ, УКАЗАТЕЛЬ :: у(:):у => компактный(Икс)

где модуль data_handler содержит

НАЗНАЧЕНИЕ компактный(Икс)   НАСТОЯЩИЙ, УКАЗАТЕЛЬ :: компактный(:)   НАСТОЯЩИЙ Икс(:)   ! Процедура удаления дубликатов из массива x   ЦЕЛОЕ п   :              ! Найдите количество различных значений, n   РАСПРЕДЕЛЕНИЕ(компактный(п))   :              ! Скопируйте отдельные значения в компактныйКОНЕЦ ФУНКЦИИ компактный

Результат можно использовать в выражении (но он должен быть связан с определенной целью).

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

Их не существует как таковых: дано

ТИП(Вход) :: ряды(п)

тогда

ряды%следующий              ! незаконный

был бы таким объектом, но с нерегулярной схемой хранения. По этой причине они не допускаются. Однако мы можем добиться того же эффекта, определив производный тип данных с указателем в качестве его единственного компонента:

ТИП ряд   НАСТОЯЩИЙ, УКАЗАТЕЛЬ :: р(:)КОНЕЦ ТИП

а затем определение массивов этого типа данных

ТИП(ряд) :: s(п), т(п)

где хранилище для строк может быть выделено, например,

ДЕЛАТЬ я = 1, п   РАСПРЕДЕЛЕНИЕ (т(я)%р(1:я)) ! Выделить строку i длины iКОНЕЦ ДЕЛАТЬ

Назначение массива s = ттогда эквивалентно присвоению указателя s(я)%р => т(я)%р для всех компонентов.

Указатели как динамические псевдонимы

Учитывая массив

НАСТОЯЩИЙ, ЦЕЛЬ :: стол(100,100)

который часто упоминается с помощью фиксированных индексов

стол(м:п, п:q)

эти ссылки могут быть заменены

НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(:, :), УКАЗАТЕЛЬ :: окно   :окно => стол(м:п, п:q)

Нижние индексы окна 1:п-м+1, 1:q-п+1. Аналогично для деготь%ты(как определено в уже ), мы можем использовать, скажем, тару => деготь%ты чтобы указать на все компоненты u в tar, и обозначить его индексом как тару(1, 2)

Индексы такие же, как у самого tar. (Это заменяет еще больше ЭКВИВАЛЕНТНОСТЬ.)

В ассоциации указателя

указатель => array_expression

нижние оценки для указатель определяются как если бы привязанный был применен к array_expression. Таким образом, когда указатель назначается всей переменной массива, он наследует нижние границы переменной, в противном случае нижние границы по умолчанию равны 1.

Фортран 2003 позволяет указать произвольные нижние границы ассоциации указателя, например

окно(р:,s:) => стол(м:п,п:q)

так что границы окно становиться г: г + н-м, с: с + д-п.Фортран 95 не имеет этой функции; однако его можно смоделировать с помощью следующего трюка (на основе правил ассоциации указателей для фиктивных аргументов предполагаемого массива форм):

НАЗНАЧЕНИЕ remap_bounds2(фунт1,фунт2,множество) РЕЗУЛЬТАТ(ptr)   ЦЕЛОЕ, НАМЕРЕНИЕ(В)                            :: фунт1,фунт2   НАСТОЯЩИЙ, ИЗМЕРЕНИЕ(фунт1:,фунт2:), НАМЕРЕНИЕ(В), ЦЕЛЬ :: множествоНАСТОЯЩИЙ, ИЗМЕРЕНИЕ(:,:), УКАЗАТЕЛЬ                  :: ptr   ptr => множествоКОНЕЦ ФУНКЦИИ  :окно => remap_bounds2(р,s,стол(м:п,п:q))

Исходный код расширенного примера использования указателей для поддержки структуры данных находится в pointer.f90.

Внутренние процедуры

Большинство внутренних функций уже упоминалось. Здесь мы имеем дело только с их общей классификацией и теми, которые до сих пор не приводились. Все внутренние процедуры можно использовать с ключевыми аргументами:

ВЫЗОВ ДАТА И ВРЕМЯ (ВРЕМЯ=т)

и у многих есть необязательные аргументы.

Внутренние процедуры сгруппированы в четыре категории:

  1. элементарный - работа со скалярами или массивами, например АБС (а);
  2. запрос - независимо от значения аргумента (который может быть неопределенным), например ТОЧНОСТЬ (а);
  3. трансформационный - аргумент массива с результатом массива другой формы, например ИЗМЕНИТЬ (a, b);
  4. подпрограммы, например SYSTEM_CLOCK.

Еще не введенные процедуры:

Битовый запрос

     BIT_SIZE Количество бит в модели

Битовые манипуляции

     BTEST Тестирование битов IAND Логический И IBCLR Очистить бит IBITS Извлечение битов IBSET Установить бит IEOR Исключительное ИЛИ IOR Включение ИЛИ ISHFT Логический сдвиг ISHFTC Круговой сдвиг НЕ Логическое дополнение

Передаточная функция, как в

ЦЕЛОЕ :: я = ПЕРЕДАЧА('abcd', 0)

(заменяет часть ЭКВИВАЛЕНТНОСТЬ)

Подпрограммы

     DATE_AND_TIME Получить дату и / или время MVBITS Копирует биты RANDOM_NUMBER Возвращает псевдослучайные числа RANDOM_SEED Доступ к начальному значению SYSTEM_CLOCK Доступ к системным часам CPU_TIME Возвращает время процессора в секундах

Передача данных

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

Форматированный ввод / вывод

Эти примеры иллюстрируют различные формы списков ввода-вывода с некоторыми простыми форматами (см. ниже ):

целое число             :: янастоящий, измерение(10) :: аперсонаж(len=20)   :: словоРаспечатать "(i10)",     яРаспечатать "(10f10.3)", аРаспечатать "(3f10.3)",  а(1),а(2),а(3)Распечатать "(а10)",     слово(5:14)Распечатать "(3f10.3)",  а(1)*а(2)+я, sqrt(а(3:4))

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

читать "(i10)", я

Если массив отображается как элемент, он обрабатывается так, как если бы элементы были указаны в порядке элементов массива.

Любые указатели в списке ввода-вывода должны быть связаны с целью, и передача происходит между файлом и целями.

Элемент производного типа обрабатывается так, как если бы компоненты были указаны в том же порядке, что и в объявлении типа, поэтому

читать "(8f10.5)", п, т  ! типы точка и треугольник

имеет тот же эффект, что и заявление

читать "(8f10.5)", п%Икс, п%у, т%а%Икс, т%а%у, т%б%Икс, &                           т%б%у, т%c%Икс, т%c%у

Объект в списке ввода-вывода не может быть производного типа, который имеет компонент-указатель на любом уровне выбора компонента.

Обратите внимание, что массив нулевого размера может присутствовать как элемент в списке ввода-вывода. Такой элемент не соответствует фактической передаче данных.

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

персонаж(len=*), параметр :: форма=«(f10.3)»:Распечатать форма, q

или как звездочка - это тип ввода-вывода, известный каксписок ориентированныйВвод / вывод (см. ниже ), формат которого определяется компьютерной системой:

Распечатать *, "Квадратный корень из q =", sqrt(q)

Операции ввода / вывода используются для передачи данных между хранилищем исполняемой программы и внешним носителем, указанным в номер единицы.Однако два оператора ввода / вывода, Распечатать и вариантчитать, не ссылайтесь ни на какой номер устройства: это называется вводом / выводом терминала. В противном случае форма выглядит так:

читать (единица измерения=4,     fmt=«(f10.3)») qчитать (единица измерения=монахиня, fmt=«(f10.3)») qчитать (единица измерения=4*я+j, fmt=«(f10.3)») а

куда unit = не является обязательным. Значение может быть любым неотрицательным целым числом, разрешенным системой для этой цели (но 0, 5 и 6 часто обозначают ошибку, клавиатуру и терминал, соответственно).

Звездочка - это вариант - опять же с клавиатуры:

читать (единица измерения=*, fmt=«(f10.3)») q

Чтение с указателем единицы измерения позволяет Обработка исключений:

читать (единица измерения=монахиня, fmt="(3f10.3)", iostat=iOS) а,б,cесли (iOS == 0) тогда! Успешное чтение - продолжить выполнение.   :еще! Состояние ошибки - примите соответствующие меры.   вызов ошибка (iOS)конец, если

Есть второй тип форматированного оператора вывода,записывать утверждение:

записывать (единица измерения=ноут, fmt="(10f10.3)", iostat=iOS) а

Внутренние файлы

Это позволяет программе выполнять преобразование формата между различными представлениями в области памяти, определенной в самой программе.

целое число, измерение(30)         :: ivalцелое число                        :: ключперсонаж(len=30)              :: буферперсонаж(len=6), измерение(3), параметр :: форма=(/ "(30i1)", "(15i2)","(10i3)" /)читать (единица измерения=*, fmt="(a30, i1)")      буфер, ключчитать (единица измерения=буфер, fmt=форма (ключ)) ival(1:30/ключ)

Если внутренний файл является скаляром, он имеет единственную запись, длина которой равна длине скаляра.

Если это массив, его элементы в порядке элементов массива рассматриваются как последовательные записи файла, и каждая имеет длину, равную длине элемента массива.

Пример использования записывать заявление

целое число           :: деньнастоящий              :: наличныеперсонаж(len=50) :: линия:! написать в строкузаписывать (единица измерения=линия, fmt="(a, i2, a, f8.2, a)") «Выручка за день», день, " находятся ", наличные, "доллары"

что может написать

 Сбор за 3-й день составляет 4329,15 долларов.

Список-управляемый ввод-вывод

Примером чтения без указанного формата для ввода является

целое число               :: янастоящий                  :: асложный, измерение(2) :: полелогичный               :: флагперсонаж(len=12)     :: заглавиеперсонаж(len=4)      :: слово:читать *, я, а, поле, флаг, заглавие, слово

Если это читает входную запись

10 6.4 (1.0,0.0) (2.0,0.0) т тест/

(в котором пробелы используются как разделители), то я, а, поле, флаг, и заглавие получит значения 10, 6.4, (1.0,0.0) и (2.0,0.0), .истинный.и тест соответственно, а слово остается неизменной.

Кавычки или апострофы необходимы в качестве разделителей для строки, содержащей пробел.

Не продвигающийся ввод / вывод

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

персонаж(len=3) :: ключцелое число      :: ты, s, iOS:читать(единица измерения=ты, fmt="(a3)", продвигать="нет", размер=s, iostat=iOS) ключесли (iOS == 0) тогда   :еще! ключ не в одной записи   ключ(s+1:) = ""   :конец, если

Непродвижущееся чтение может прочитать несколько первых символов записи, а обычное чтение - остаток.

Чтобы написать приглашение на экран терминала и читать со следующей позиции символа на экране без промежуточного перевода строки, мы можем написать

записывать (единица измерения=*, fmt="(а)", продвигать="нет") "введите следующее простое число:"читать  (единица измерения=*, fmt="(i10)") простое число

Непродолжительный ввод-вывод предназначен для внешних файлов и недоступен для ввода-вывода со списком.

Редактировать дескрипторы

Можно указать, что дескриптор редактирования будет повторяться указанное количество раз, используя счетчик повторов: 10f12.3

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

Распечатать "(2 (2i5,2f8.2))", я(1),я(2),а(1),а(2), я(3),я(4),а(3),а(4)

Все спецификации формата могут быть повторены:

Распечатать "(10i8)", (/ (я(j), j=1,200) /)

записывает 10 целых чисел, каждое из которых занимает 8 позиций символов, в каждой из 20 строк (повторение спецификации формата переходит к следующей строке).

Дескрипторы редактирования данных

  • Целое число: iW iW.M
  • Настоящий: fW.D esW.D esW.DeE
  • Комплекс: пары ж или же es редактировать дескрипторы
  • Логично: lW
  • Характер: a aW
  • Производные типы: редактируются соответствующей последовательностью дескрипторов редактирования, соответствующих внутренним типам конечных компонентов производного типа.
    тип, общественный :: нить   целое число   :: длина   персонаж(len=20) :: словотип конца нитьтип(нить) :: текстчитать(единица измерения=*, fmt="(i2, a)") текст

Дескрипторы редактирования управления

Условия установки дескрипторов редактирования управления:

  • В SS (подавление знака) дескриптор редактирования подавляет начальные знаки плюса. Чтобы включить печать знака плюса, нажмите зр (печать знака) используется дескриптор. В s дескриптор редактирования восстанавливает параметр для процессора.
  • Этот дескриптор остается в силе до конца спецификации формата, если не выполняется другой из них.

Управляйте дескрипторами редактирования для немедленной обработки:

  • Таблица: tN trN tlN
    читать (единица измерения=*, fmt="(t3, i4, tl4, i1, i2)") я,j,k
  • Новые рекорды: / N /
    читать "(i5, i3, /, i5, i3, i2)", я, j, k, л, м

    Обратите внимание, что

    Распечатать "(i5,4 /, i5)", я, j
    разделяет два значения тремя пустыми записями.
  • Редактирование двоеточия:  :завершает управление форматом, если в списке ввода-вывода нет других элементов.
    Распечатать "(i5,:, /, i5,:, /, i5)", (/(л(я), я=1,п)/)
    останавливает новые записи, если п равно 1 или 2.

Неформатированный ввод / вывод

Этот тип ввода-вывода следует использовать только в тех случаях, когда записи создаются программой на одном компьютере для последующего чтения на том же компьютере или другом компьютере с использованием тех же внутренних представлений чисел:

открыто(единица измерения=4, файл='тест', форма="неформатированный")читать(единица измерения=4) qзаписывать(единица измерения=ноут, iostat=iOS) а  ! нет fmt =

Файлы с прямым доступом

Эта форма ввода-вывода также известна как произвольный доступ или индексированный ввод-вывод. Здесь все записи имеют одинаковую длину, и каждая запись идентифицируется номером индекса. Можно писать, читать или перезаписывать любую указанную запись независимо от позиции.

целое число, параметр :: монахиня=2, длина=100настоящий, измерение(длина)            :: анастоящий, измерение(длина+1:2*длина) :: бцелое число                            :: я, rec_length:спрашивать (iolength=rec_length) аоткрыто (единица измерения=монахиня, доступ="непосредственный", recl=rec_length, положение дел="царапать", действие="читай пиши"):! Записать массив b в файл прямого доступа в записи 14записывать (единица измерения=монахиня, rec=14) б:!! Считайте массив обратно в массив aчитать (единица измерения=монахиня, rec=14) а:делать я = 1, длина/2   а(я) = яконец делать!! Заменить измененную записьзаписывать (единица измерения=монахиня, rec=14) а

Файл должен быть внешним файлом. Форматирование со списком и не продвигающийся ввод-вывод недоступны.

Операции с внешними файлами

Еще раз, это только обзор.

Операторы позиционирования файлов

  • В Backspace утверждение:
    Backspace (единица измерения=ты [,iostat=iOS])      ! где [] означает необязательный
  • В перемотка утверждение:
    перемотка (единица измерения=ты [,iostat=iOS])
  • В конец файла утверждение:
    конец файла (единица измерения=ты [,iostat=iOS])

В открыто утверждение

Этот оператор используется для подключения внешнего файла к модулю, создания файла, который предварительно подключен, или для создания файла и подключения его к модулю.

открыто (единица измерения=ты, положение дел=ул, действие=действовать [,олист])

куда олист - это список необязательных спецификаторов. Спецификаторы могут появляться в любом порядке.

открыто (единица измерения=2, iostat=iOS, файл="города", положение дел="новый", доступ="непосредственный",  &      действие="читай пиши", recl=100)

Другие спецификаторы форма и позиция.

В Закрыть утверждение

Используется для отключения файла от модуля.

Закрыть (единица измерения=ты [,iostat=iOS] [,положение дел=ул])

как в

Закрыть (единица измерения=2, iostat=iOS, положение дел="Удалить")

В спрашивать утверждение

В любой момент во время выполнения программы можно запросить статус и атрибуты файла с помощью этого оператора.

Используя вариант этого оператора, аналогичным образом можно определить статус единицы, например, существует ли номер единицы для этой системы.

Другой вариант позволяет запрашивать длину выходного списка, когда он используется для записи неформатированной записи.

Для запроса по подразделению

спрашивать (единица измерения=ты, Ilist)

или для запроса по файлу

спрашивать (файл=fln, Ilist)

или для запроса по списку ввода / вывода

спрашивать (iolength=длина) олист

В качестве примера

логичный            :: бывший, opперсонаж (len=11) :: нам, соотв, seq, отцелое число            :: irec, номерспрашивать (единица измерения=2, существовать=бывший, открыт=op, имя=нам, доступ=соотв, последовательный=seq, форма=FRM, &         recl=irec, следующийрек=номер)

дает

бывший      .истинный.op      .истинный.нам      городасоотв      НЕПОСРЕДСТВЕННЫЙseq      НЕТот      НЕФОРМАТИРОВАННЫЙirec     100номер       1

(при условии отсутствия промежуточных операций чтения или записи).

Другие спецификаторы iostat, открытый, число, имя, форматирование, позиция, действие, чтение, запись, чтение, запись.

Рекомендации

  1. ^ http://www.fortranplus.co.uk/fortran-information/
  2. ^ «Объяснение современного Фортрана: Мягкая обложка: Майкл Меткалф, Джон Рид, Малкольм Коэн - Oxford University Press». Ukcatalogue.oup.com (2019).