Из Википедии, бесплатной энциклопедии
Перейти к навигации Перейти к поиску

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

Элементы языка [ править ]

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

Основы [ править ]

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

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

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

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

ФУНКЦИЯ string_concat ( s1 ,  s2 )  ! Это комментарий  TYPE  ( строка ),  INTENT ( IN )  ::  s1 ,  s2  TYPE  ( строка )  string_concat  string_concat % string_data  =  s1 % string_data ( 1 : s1 % length )  //  &  s2 % string_data ( 1 : s2 % length ) ! Это продолжение  string_concat % length  =  s1 % length  +  s2 % length END FUNCTION string_concat

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

 ...  start_of &  & _ name  ...  'очень длинная &  & строка'

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

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

Его варианты

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

Внутренние типы данных [ править ]

Fortran имеет пять встроенных типов данных : INTEGER, REAL, COMPLEX, LOGICALи CHARACTER. Каждый из этих типов можно дополнительно охарактеризовать по виду . Kind, по сути, определяет внутреннее представление типа: для трех числовых типов он определяет точность и диапазон, а для двух других - особенности представления хранилища. Таким образом, это абстрактное понятие, моделирующее пределы представления типов данных; он выражается как член набора целых чисел (например, это может быть {1, 2, 4, 8} для целых чисел, обозначающих байты памяти), но эти значения не указаны в Стандарте и не переносимы. Для каждого типа есть вид по умолчанию, который используется, если явно не указан тип. Для каждого внутреннего типа существует соответствующая форма литеральной константы . Числовые типы INTEGERи REALмогут быть только подписаны (нет понятия знака для типа COMPLEX).

Литеральные константы и виды [ править ]

INTEGER [ править ]

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

1  0  - 999  32767  + 10

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

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

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

- 1234_two_bytes  + 1_two_bytes

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

- 1234_2

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

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

ВИД ( 1 )  ВИД ( 1_two_bytes )

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

ДИАПАЗОН ( 1_два_байта )

Кроме того, в DATAоператорах (инициализации) могут использоваться двоичные (B), восьмеричные (O) и шестнадцатеричные (Z) константы (часто неофициально называемые «константами BOZ»):

B '01010101'  O '01234567'  Z '10fa'
НАСТОЯЩИЙ [ править ]

Есть как минимум два реальных вида - по умолчанию и один с большей точностью (это заменяет DOUBLE PRECISION). SELECTED_REAL_KINDfunctions возвращает номер вида для желаемого диапазона и точности; для не менее 9 десятичных цифр точности и диапазона от 10 -99 до 10 99 его можно указать как:

ЦЕЛОЕ ,  ПАРАМЕТР  ::  long  =  SELECTED_REAL_KIND ( 9 ,  99 )

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

1,7_длинный

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

ВИД ( 1.7_long )  ТОЧНОСТЬ ( 1.7_long )  RANGE ( 1.7_long )

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

КОМПЛЕКС [ править ]

COMPLEX Тип данных состоит из двух целочисленных или вещественных компонентов:

( 1 ,  3,7_длинный )
ЛОГИЧЕСКИЙ [ править ]

Есть только два основных значения логических констант: .TRUE.и .FALSE.. Здесь тоже могут быть разные виды. Логические элементы не имеют своих собственных функций запроса, но используют типы, указанные для INTEGERs; вид по умолчанию такой LOGICALже, как у INTEGER.

. ЛОЖЬ .  . правда . _ one_byte

и KINDфункция работает так, как ожидалось:

ВИД (. ИСТИНА .)
ПЕРСОНАЖ [ править ]

Формы буквальных констант для CHARACTERтипа данных:

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

(последняя - пустая строка). Разрешены разные типы (например, для различения строк ASCII и UNICODE ), но компиляторы не поддерживают их. Опять же, значение вида задается KINDфункцией:

ВИД ( 'ASCII' )

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

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

Скалярные переменные [ править ]

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

INTEGER ( KIND = 2 )  ::  i REAL ( KIND = long )  ::  a COMPLEX  ::  current LOGICAL  ::  Pravda CHARACTER ( LEN = 20 )  ::  word CHARACTER ( LEN = 2 ,  KIND = Kanji )  ::  kanji_word

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

LEN=спецификатор применим только к CHARACTERs и указывает длину строки (заменяя старую *lenформу). Явные KIND=и LEN=спецификаторы не являются обязательными:

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

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

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

ХАРАКТЕР ( 80 )  ::  строка  ...  =  строка ( i : i )  ! подстрока

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

'0123456789' ( i : i )

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

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

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

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

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

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

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

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

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

вы % возраста

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

you  =  person ( 'Смит' ,  2 3,5 )

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

TYPE точка  REAL x ,  y END TYPE точка TYPE треугольник  TYPE ( точка )  a ,  b ,  c END TYPE треугольник

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

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

pointдоступ к каждому компоненту типа осуществляется как

т % а  т % б  т % в

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

t % a % x  t % a % y  t % b % x и  т . д.

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

Неявная и явная типизация [ править ]

Если не указано иное, все переменные, начинающиеся с букв I, J, K, L, M и N, являются значениями по умолчанию INTEGER, а все остальные - значениями по умолчанию REAL; другие типы данных должны быть явно объявлены. Это называется неявной типизацией и является наследием первых дней FORTRAN. Эти значения по умолчанию могут быть отменены такими IMPLICIT TypeName (CharacterRange)операторами, как:

НЕЯВНЫЙ КОМПЛЕКС ( Z ) НЕЯВНЫЕ СИМВОЛЫ ( - Б ) НЕЯВНЫЕ РЕАЛЬНАЯ ( С - Н , Н - Y )

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

Массивы [ править ]

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

REAL ::  a ( 10 ) INTEGER ,  DIMENSION ( 0 : 100 ,  - 50 : 50 )  ::  map

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

а ( 1 )  а ( я * j )

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

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

а ( я : j )  ! карта первого ранга ( i : j ,  k : l : m )  ! ранг два a ( map ( i ,  k : l ))  ! векторный индекс a ( 3 : 2 )  ! нулевая длина

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

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

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

TYPE триплет  REAL ,  DIMENSION ( 3 )  ::  вершина END TYPE триплет TYPE ( триплет ),  DIMENSION ( 4 )  ::  t

чтобы

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

Инициализация данных [ править ]

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

НАСТОЯЩИЙ ,  РАЗМЕР ( 3 )  ::  a  =  ( /  0,1 ,  0,2 ,  0,3  / )

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

TYPE триплет  REAL ,  DIMENSION ( 3 )  ::  vertex  =  0.0 END TYPE триплет

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

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

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

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

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

Атрибут PARAMETER [ править ]

Именованную константу можно указать напрямую, добавив PARAMETERатрибут и значения константы в оператор типа:

REAL ,  DIMENSION ( 3 ),  PARAMETER  ::  field  =  ( /  0. ,  1. ,  2.  / ) TYPE ( триплет ),  PARAMETER  ::  t  =  triplet (  ( /  0. ,  0. ,  0.  / )  )

Заявление DATA [ править ]

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

ТИП ( триплет )  ::  t1 ,  t2 ДАННЫЕ t1 / триплет (  ( /  0. ,  1. ,  2.  / )  ) / ,  t2 % vertex ( 1 ) / 12 3. / Массив ДАННЫХ ( 1 : 64 )  /  64 * 0 / ДАННЫЕ i ,  j ,  k /  B '01010101' ,  O'77' ,  Z 'ff' /

Выражения инициализации [ править ]

Значения , используемые в DATAи PARAMETERзаявлении, или с этими атрибутами, являются постоянными выражениями , которые могут включать в себя ссылку на: массив и структуры конструкторы, элементные встроенные функции с целыми или символьными аргументами и результатами, а также шесть трансформационных функциями REPEAT, SELECTED_INT_KIND, TRIM, SELECTED_REAL_KIND, RESHAPEи TRANSFER(см характеристических процедур ):

ЦЕЛОЕ ,  ПАРАМЕТР  ::  long  =  SELECTED_REAL_KIND ( 12 ),  &  array ( 3 )  =  ( /  1 ,  2 ,  3  / )

Выражения спецификации [ править ]

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

SUBROUTINE s ( b ,  m ,  c )  ИСПОЛЬЗУЙТЕ мод  ! содержит  REAL ,  DIMENSION (:,  :)  ::  b  REAL ,  DIMENSION ( UBOUND ( b ,  1 )  +  5 )  ::  x  INTEGER  ::  m  CHARACTER ( LEN = * )  ::  c  CHARACTER ( LEN =  m  +  LEN ( в )) ::  cc  REAL  ( SELECTED_REAL_KIND ( 2 * ТОЧНОСТЬ ( a )))  ::  z

Выражения и присвоения [ править ]

Скалярное числовое [ править ]

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

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

а * б  +  в  ! * сначала a * ( b  +  c )  ! + первый

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

real2  =  integer0  +  real1

преобразуется integer0в реальное значение того же типа, что и real1; результат того же типа и преобразуется в тип real2для назначения.

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

  • NINT: округлить до ближайшего целого числа, вернуть целочисленный результат
  • ANINT: округлить до ближайшего целого числа, вернуть реальный результат
  • INT: truncate (округлить до нуля), вернуть целочисленный результат
  • AINT: truncate (округлить до нуля), вернуть реальный результат
  • CEILING: наименьшее целое значение не меньше аргумента (округлить) (Fortran-90)
  • FLOOR: наибольшее целое значение не больше аргумента (округлить в меньшую сторону) (Fortran-90)

Скалярные реляционные операции [ править ]

Для скалярных реляционных операций числовых типов существует набор встроенных операторов:

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

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

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

Скалярные символы [ править ]

В случае скалярных символов и заданныхCHARACTER(8) result

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

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

Конкатенация выполняется оператором '//'.

result  =  'abcde' // '123' filename  =  result // '.dat'

Типы производных данных [ править ]

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

TYPE string80  INTEGER length  CHARACTER ( 80 )  value END TYPE string80 CHARACTER ::  char1 ,  char2 ,  char3 TYPE ( string80 ) ::  str1 ,  str2 ,  str3

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

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

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

вектор3  =  матрица  *  вектор1  +  вектор2 вектор3  = ( матрица  . раз .  вектор1 )  +  вектор2

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

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

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

МОДУЛЬ string_type  НЕЯВНЫЕ НЕТ  ТИП string80  ЦЕЛОЕ Длина  СИМВОЛОВ ( LEN = 80 )  ::  string_data  КОНЕЦ ТИП string80  ИНТЕРФЕЙС ПЕРЕУСТУПКА ( = )  ПРОЦЕДУРА МОДУЛЬ c_to_s_assign ,  s_to_c_assign  КОНЕЦ ИНТЕРФЕЙС  ИНТЕРФЕЙС ОПЕРАТОРА ( // )  МОДУЛЬ ПРОЦЕДУРА string_concat  КОНЕЦ ИНТЕРФЕЙС СОДЕРЖИТ  SUBROUTINE c_to_s_assign ( ы ,  гр ) TYPE  ( string80 ),  INTENT ( OUT )  ::  s  CHARACTER ( LEN = * ),  INTENT ( IN )  ::  c  s % string_data  =  c  s % length  =  LEN ( c )  END SUBROUTINE c_to_s_assign  SUBROUTINE s_to_c_assign ( c ,  s )  TYPE  ( строка80 ),  НАМЕРЕНИЕ ( В )  :: s  СИМВОЛ ( LEN = * ),  INTENT ( OUT )  ::  c  c  =  s % string_data ( 1 : s % length )  END SUBROUTINE s_to_c_assign  TYPE ( string80 )  FUNCTION string_concat ( s1 ,  s2 )  TYPE ( string80 ),  INTENT ( IN )  ::  s1 ,  s2  ТИП ( строка80)  ::  s  INTEGER  ::  n1 ,  n2  CHARACTER ( 160 )  ::  ctot  n1  =  LEN_TRIM ( s1 % string_data )  n2  =  LEN_TRIM ( s2 % string_data )  IF  ( 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 )  END IF s % length = LEN_TRIM ( s % string_data ) строка_concat     =  s  КОНЕЦ ФУНКЦИИ string_concat КОНЕЦ МОДУЛЯ string_typeПРОГРАММА основное  ИСПОЛЬЗОВАНИЕ string_type  TYPE ( string80 )  ::  s1 ,  s2 ,  s3  CALL c_to_s_assign ( s1 , 'My name is' )  CALL c_to_s_assign ( s2 , 'Linus Torvalds' )  s3  =  s1 // s2  WRITE ( * , * )  'Результат : ' , s3 % string_data  WRITE ( * , * )  ' Длина: ', s3 % длина КОНЕЦ ПРОГРАММЫ

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

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

Массивы [ править ]

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

REAL ,  DIMENSION ( 10 ,  20 )  ::  a ,  b ,  c REAL ,  DIMENSION ( 5 )  ::  v ,  w LOGICAL flag ( 10 ,  20 )

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

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

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

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

ПОТОЛОЧНЫЙ ПОЛ МОДУЛЬ  ( также  целое число ) ЭКСПОНЕНТНАЯ ДОЛЯ БЛИЖАЙШЕГО RRSPACING ПРОСТРАНСТВЕННЫЙ МАСШТАБ SET_EXPONENT

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

INT REAL CMPLX AINT ANINT NINT ABS MOD SIGN DIM MAX MINSQRT EXP LOG LOG10  SIN COS TAN ASIN ACOS ATAN ATAN2 SINH COSH TANHAIMAG CONJGLGE LGT LLE LLT ICHAR ИНДЕКС СИМВОЛОВ

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

Операторы управления [ править ]

Ветвление и условия [ править ]

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

Простой условный тест - это IFутверждение:IF (a > b) x = y

Полноценная IFконструкция иллюстрируется

ЕСЛИ  ( i  <  0 )  ТО  ЕСЛИ  ( j  <  0 )  ТО x = 0. ИНАЧЕ z = 0. END IF ELSE IF ( k < 0 ) THEN z = 1. ИНАЧЕ x = 1. END IF                  

CASE конструкция [ править ]

CASEКонструкция является заменой вычисленного GOTO, но лучше структурирована и не требует использования отчетности меток:

ВЫБЕРИТЕ СЛУЧАЙ  ( число )  ! число типа integer CASE  (: - 1 )  ! все значения ниже 0  n_sign  =  - 1 CASE  ( 0 )  ! только 0  n_sign  =  0 CASE  ( 1 :)  ! все значения выше 0  n_sign  =  1 END SELECT

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

CASE  ( 1 ,  2 ,  7 ,  10 : 17 ,  23 )

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

СЛУЧАЙ ПО УМОЛЧАНИЮ

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

СОЗДАТЬ [ править ]

Упрощенная, но достаточная форма DOконструкции иллюстрируется

внешний :  DO внутренний :  DO i  =  j ,  k ,  l  ! от j до k с шагом l (l необязательно)  :  IF  (...)  CYCLE  :  IF  (...)  EXIT external  :  END DO inner  END DO external

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

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

tot  =  0. DO i  =  m ,  n  tot  =  tot  +  a ( i ) КОНЕЦ DO

становится просто tot = SUM( a(m:n) )

Программные единицы и процедуры [ править ]

Определения [ править ]

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

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

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

ПРОГРАММА тестовая  ПЕЧАТЬ  * ,  'Hello world!' END PROGRAM тест

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

ПРОГРАММА test  CALL print_message END PROGRAM test SUBROUTINE print_message  PRINT  * ,  'Hello world!' КОНЕЦ ПОДПРОГРАММЫ print_message

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

Имя ФУНКЦИИ ( arg1 ,  arg2 )  ! ноль или более аргументов  :  name  =  ...  : END FUNCTION name

Форма ссылки на функцию x = name(a, b)

Внутренние процедуры [ править ]

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

SUBROUTINE внешний  РЕАЛ х ,  у  : СОДЕРЖИТ  SUBROUTINE внутренняя  РЕАЛ у  у  =  х  +  1  :  END SUBROUTINE внутренний  ! ПОДПРОГРАММА обязательная КОНЕЦ ПОДПРОГРАММА внешняя

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

Область действия именованной сущности - это единица области видимости , здесь outerменьше inner, и inner.

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

Модули [ править ]

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

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

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

МОДУЛЬ interval_arithmetic  ТИП интервал  РЕАЛЬНОГО нижний ,  верхний  торцевым интервал  ИНТЕРФЕЙСА ОПЕРАТОРА ( + )  МОДУЛЬ ПРОЦЕДУРА add_intervals  END ИНТЕРФЕЙС  : СОДЕРЖИТ  FUNCTION add_intervals ( , б ) ТИП ( интервал ), НАМЕРЕНИЕ ( IN ) :: , б TYPE ( интервал ) add_intervals add_intervals %        lower  =  a % lower  +  b % lower  add_intervals % upper  =  a % upper  +  b % upper  КОНЕЦ ФУНКЦИЯ add_intervals  ! ОБЯЗАТЕЛЬНАЯ ФУНКЦИЯ  : КОНЕЦ МОДУЛЯ interval_arithmetic

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

 ИСПОЛЬЗОВАТЬ интервальную_арифметику

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

Управление доступностью [ править ]

PUBLICИ PRIVATEатрибуты используются в спецификациях модулей для ограничения объема объектов. Форма атрибута

НАСТОЯЩИЙ ,  ОБЩЕСТВЕННЫЙ  ::  x ,  y ,  z  ! по умолчанию INTEGER ,  PRIVATE  ::  u ,  v ,  w

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

PUBLIC  ::  x ,  y ,  z ,  ОПЕРАТОР (. Доп .) ЧАСТНЫЙ  ::  u ,  v ,  w ,  НАЗНАЧЕНИЕ ( = ),  ОПЕРАТОР ( * )

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

ЧАСТНЫЙ  ! устанавливает значение по умолчанию для модуля PUBLIC  ::  only_this

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

MODULE mine  ЧАСТНЫЙ  ТИП ,  PUBLIC  ::  list  REAL x ,  y  TYPE ( список ),  POINTER  ::  next  END TYPE list  TYPE ( list )  ::  tree  : END MODULE mine

Цель USEоператора - получить доступ к сущностям в модуле. У него есть опции для разрешения конфликтов имен, если импортированное имя совпадает с локальным:

ИСПОЛЬЗУЙТЕ мой ,  local_list  =>  список

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

ИСПОЛЬЗОВАНИЕ шахты ,  ТОЛЬКО  :  список

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

ИСПОЛЬЗОВАНИЕ шахты ,  ТОЛЬКО  :  local_list  =>  список

Аргументы [ править ]

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

SUBROUTINE shuffle  ( ncards ,  cards )  INTEGER ,  INTENT ( IN )  ::  ncards  INTEGER ,  INTENT ( OUT ),  DIMENSION ( ncards )  ::  cards

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

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

SUBROUTINE mincon ( п ,  е ,  х ,  верхний ,  опустить ,  равенства ,  неравенства ,  выпуклые ,  XStart )  РЕАЛ ,  ДОПОЛНИТЕЛЬНО ,  DIMENSION  ::  Верхняя ,  опустить  :  IF  ( НАСТОЯЩЕЕ ( опустить ))  ТОГДА  ! проверка на наличие действительного аргумента  :

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

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

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

ВЫЗОВ mincon ( п ,  е ,  х ,  равенство = 0 ,  XStart = х0 )

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

Блоки интерфейса [ править ]

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

РЕАЛЬНАЯ ФУНКЦИЯ минимум ( a ,  b ,  func )  ! возвращает минимальное значение функции func (x)  ! в интервале (a, b)  REAL ,  INTENT ( in )  ::  a ,  b  INTERFACE REAL FUNCTION func ( x ) REAL , INTENT ( IN ) :: x END FUNCTION func END INTERFACE REAL f , x : f = func (            х )  ! вызов пользовательской функции.  : END FUNCTION минимум

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

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

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

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

Перегрузка и общие интерфейсы [ править ]

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

ИНТЕРФЕЙС гамма  ! общее имя  FUNCTION sgamma ( X )  ! конкретное имя  REAL  ( SELECTED_REAL_KIND (  6 ))  sgamma ,  x  END  FUNCTION dgamma ( X )  ! конкретное имя  REAL  ( SELECTED_REAL_KIND ( 12 ))  dgamma ,  x  END END INTERFACE

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

ИНТЕРФЕЙС gamma МОДУЛЬ ПРОЦЕДУРА sgamma , dgamma КОНЕЦ ИНТЕРФЕЙСА  

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

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

Рекурсия [ править ]

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

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

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

РЕКУРСИВНАЯ ФУНКЦИЯ интегрировать ( f ,  границы )  ! Интегрируйте f (x) от границ (1) до границ (2)  REAL интегрировать   ФУНКЦИЮ ИНТЕРФЕЙСА f ( x ) REAL f , x END FUNCTION f END INTERFACE REAL , DIMENSION ( 2 ), INTENT ( IN ) :: bounds : END FUNCTION интегрировать          

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

ФУНКЦИЯ fy ( y )  USE func  ! модуль func содержит функцию f  REAL fy ,  y  yval  =  y  fy  =  интегрировать ( f ,  xbounds ) END

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

РЕКУРСИВНАЯ ФУНКЦИЯ factorial ( n )  RESULT ( res )  INTEGER res ,  n  IF ( n . EQ . 0 )  THEN res = 1 ELSE res = n * factorial ( n - 1 ) END IF END        

Здесь мы отмечаем RESULTусловие и тест на завершение.

Чистые процедуры [ править ]

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

В операторе и конструкции FORALL любые побочные эффекты в функции могут препятствовать оптимизации параллельного процессора - порядок выполнения присваиваний может повлиять на результаты. Чтобы контролировать эту ситуацию, мы добавляем PUREключевое слово в оператор SUBROUTINEor FUNCTION- утверждение, что процедура (выраженная просто):

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

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

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

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

Обработка массивов [ править ]

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

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

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

Массивы нулевого размера [ править ]

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

DO i  =  1 , n  x ( i )  =  b ( i )  /  a ( i ,  i )  b ( i + 1 : n )  =  b ( i + 1 : n )  -  a ( i + 1 : n ,  i )  *  x ( i ) КОНЕЦ ДЕЛАТЬ

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

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

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

REAL ,  DIMENSION ( 0 : 10 ,  0 : 20 )  ::  a  : CALL sub ( a )

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

SUBROUTINE sub ( da )  REAL ,  DIMENSION (:,  :)  ::  da

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

РЕАЛЬНОЕ ,  РАЗМЕР ( 0 :,  0 :)  ::  da

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

Автоматические массивы [ править ]

Частичная замена использований, которые EQUIVALENCE были применены, обеспечивается этим средством, полезным для локальных временных массивов, как в

ПОДПРОГРАММА swap ( a ,  b )  REAL ,  DIMENSION (:)  ::  a ,  b  REAL ,  DIMENSION ( SIZE ( a ))  ::  work  work  =  a  a  =  b  b  =  work END SUBROUTINE swap

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

ALLOCATABLE и ALLOCATE [ править ]

Fortran обеспечивает динамическое выделение памяти; он полагается на механизм хранения в куче (и заменяет другое использование EQUIVALENCE). Примером создания рабочего массива для всей программы является

МОДУЛЬ work_array  INTEGER n  REAL ,  DIMENSION (:,:, :),  ALLOCATABLE  ::  work END MODULE PROGRAM main  USE work_array  READ  ( input ,  * )  n  ALLOCATE ( work ( n ,  2 * n ,  3 * n ),  STAT = status )  :  DEALLOCATE  ( работа )

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

ОТКЛЮЧИТЬ ( a ,  b )

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

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

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

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

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

ПРОГРАММА test  REAL ,  DIMENSION ( 3 )  ::  a  =  ( /  1. ,  2. ,  3. / ),  &  b  =  ( /  2. ,  2. ,  2.  / ),  r  r  =  f ( a ,  b )  ПЕЧАТЬ  * ,  r СОДЕРЖИТ  ФУНКЦИЮ f ( c ,  d )  REAL ,  РАЗМЕР(:)  ::  с ,  d  РЕАЛ ,  DIMENSION ( РАЗМЕР ( с ))  ::  е  е  =  с * d  ! (или другая полезная функция c и d)  КОНЕЦ ФУНКЦИИ f КОНЕЦ ПРОГРАММЫ тест

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

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

ELEMENTAL SUBROUTINE swap ( a ,  b )  REAL ,  INTENT ( INOUT )  ::  a ,  b  REAL  ::  work  work  =  a  a  =  b  b  =  работа END SUBROUTINE swap

Аргументы холостые не могут быть использованы в спецификации выражений (см выше ) , за исключением в качестве аргументов некоторых внутренних функций ( BIT_SIZE, KIND, LEN, и числовая запрос из них (см ниже ).

ГДЕ [ редактировать ]

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

ГДЕ  ( а  / =  0,0 )  а  =  1,0 / а  ! избегать деления на 0

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

ГДЕ  ( a  / =  0,0 )  a  =  1,0 / a  b  =  a  ! все массивы одинаковой формы КОНЕЦ ГДЕ

или же

ГДЕ  ( a  / =  0,0 )  a  =  1,0 / a В другом месте  a  =  ОГРОМНЫЙ ( a ) КОНЕЦ ГДЕ

Способствовать:

  • разрешено маскировать не только WHEREоператор WHEREконструкции, но также любой ELSEWHEREоператор, который он содержит;
  • WHEREконструкция может содержать любое количество замаскированных ELSEWHEREзаявлений , но не более одного ELSEWHEREзаявления без маски, и это должно быть окончательным;
  • WHERE конструкции могут быть вложены друг в друга, просто FORALLконструкции;
  • оператору WHEREприсваивания разрешено быть определенным присваиванием, при условии, что оно является элементарным;
  • WHEREконструкция может быть названа таким же образом , как и другие конструкции.

Оператор FORALL и конструкция [ править ]

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

FORALL ( i  =  1 : n )  a ( i ,  i )  =  x ( i )

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

FORALL ( i = 1 : n ,  j = 1 : n ,  y ( i , j ) / = 0. )  x ( j , i )  =  1.0 / y ( i , j )

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

FORALLКонструкция позволяет несколько операторов присваивания , которые будут выполняться в порядке.

a ( 2 : n - 1 , 2 : n - 1 )  =  a ( 2 : n - 1 , 1 : n - 2 )  +  a ( 2 : n - 1 , 3 : n )  +  a ( 1 : n - 2 , 2 : n - 1 )  +  a ( 3: n , 2 : n - 1 ) b ( 2 : n - 1 , 2 : n - 1 )  =  a ( 2 : n - 1 , 2 : n - 1 )

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

FORALL ( i  =  2 : n - 1 ,  j  =  2 : n - 1 )  a ( i , j )  =  a ( i , j - 1 )  +  a ( i , j + 1 )  +  a ( i - 1 , j )  +  ( я + 1 , J ) б ( i , j )  =  a ( i , j ) КОНЕЦ НАВСЕГДА

FORALLВерсия более читаемым.

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

A FORALLможет быть вложенным и может включать в себя WHERE. Процедуры, указанные в a, FORALLдолжны быть чистыми.

Элементы массива [ править ]

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

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

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

TYPE fun_del  REAL u  REAL ,  DIMENSION ( 3 )  ::  du END TYPE fun_del

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

ТИП ( fun_del ),  РАЗМЕР ( 10 ,  20 )  ::  tar

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

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

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

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

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

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

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

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

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

tar % du  ! незаконный

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

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

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

tar % u  ! раздел массива (компонент структуры) tar ( 1 ,  1 )% u  ! компонент элемента массива

Внутренние функции массивов [ править ]

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

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

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

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

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

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

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

 MERGE Слияние под маской PACK Упакуйте массив в массив первого ранга под маской SPREAD Репликация массива путем добавления измерения РАСПАКОВАТЬ Распаковать массив первого ранга в массив под маской

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

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

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

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

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

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

Указатели [ править ]

Основы [ править ]

Указатели - это переменные с POINTERатрибутом; они не являются отдельным типом данных (и поэтому «арифметика указателей» невозможна).

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

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

ALLOCATE  ( var )

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

var  =  var  +  2.3

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

ЗАПИСАТЬ  * ,  var

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

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

REAL ,  POINTER  ::  object REAL ,  TARGET  ::  target_obj var  =>  объект  ! присвоение указателя var  =>  target_obj

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

INTEGER ,  POINTER  ::  int_var вар  =>  int_var  ! незаконно - типы должны совпадать

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

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

ТИП записи  ! тип для разреженной матрицы  REAL значение INTEGER index TYPE ( entry ), POINTER :: next ! обратите внимание на запись END TYPE рекурсии      

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

ТИП ( запись ),  УКАЗАТЕЛЬ  ::  цепочка

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

Цепь % значение цепь % в следующем % Значении цепи % Индекс цепи % в следующем % Индексе цепи % в следующей  цепи % в следующем % в следующем

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

Ассоциация [ править ]

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

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

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

Внутренняя функция ASSOCIATEDможет проверить статус ассоциации определенного указателя:

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

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

ЕСЛИ  ( АССОЦИАЦИЯ ( указатель ;  цель ))  ТО

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

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

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

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

REAL ,  TARGET  ::  b ( 10 , 10 ),  c ( 10 , 10 ),  r ( 10 ),  s ( 10 ),  z ( 10 ) REAL ,  POINTER  ::  a (:, :),  x (:),  y (:) INTEGER mult : DO mult  =  1 ,  2  IF  ( mult  ==  1 )  ТОГДА y =>   г  ! нет перемещения данных  a  =>  c  x  =>  z  ELSE y => s ! нет перемещения данных a => b x => r END IF y = MATMUL ( a , x ) ! общий расчет END DO                

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

ТИП ( запись ),  УКАЗАТЕЛЬ  ::  первый ,  текущий : первый  =>  текущий

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

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

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

первый % значение  =  текущее % значение первый % индекс  =  текущий % индекс первый % следующий  =>  текущий % следующий

Аргументы указателя [ править ]

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

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

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

 REAL ,  POINTER  ::  a  (:, :)  :  ALLOCATE  ( a ( 80 ,  80 ))  :  CALL sub ( a )  : SUBROUTINE sub ( c )  REAL c (:,  :)

Функции указателя [ править ]

Результаты функции также могут иметь POINTERатрибут; это полезно, если размер результата зависит от вычислений, выполняемых в функции, как в

ИСПОЛЬЗУЙТЕ обработчик_данных REAL x ( 100 ) REAL ,  POINTER  ::  y (:) : y  =>  compact ( x )

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

ФУНКЦИЯ compact ( x )  REAL ,  POINTER  ::  compact (:)  REAL x (:)  ! Процедура удаления дубликатов из массива х  INTEGER н  :  ! Найти число различных значений п  ALLOCATE ( компактный ( п ))  :  ! Скопируйте отдельные значения в компактный END FUNCTION compact

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

Массивы указателей [ править ]

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

ТИП ( запись )  ::  строки ( n )

тогда

row % next  ! незаконный

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

TYPE row  REAL ,  POINTER  ::  r (:) END TYPE

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

ТИП ( строка )  ::  s ( n ),  t ( n )

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

DO i  =  1 ,  n  ALLOCATE  ( t ( i )% r ( 1 : i ))  ! Выделить строку i длины i END DO

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

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

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

REAL ,  TARGET  ::  таблица ( 100 , 100 )

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

таблица ( m : n ,  p : q )

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

РЕАЛЬНОЕ ,  РАЗМЕР (:,  :),  УКАЗАТЕЛЬ  ::  окно  : окно  =>  таблица ( m : n ,  p : q )

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

Индексы такие же, как у самого tar. (Это заменяет еще больше EQUIVALENCE.)

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

указатель  =>  выражение_массив

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

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

окно ( r :, s :)  =>  таблица ( m : n , p : q )

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

ФУНКЦИЯ remap_bounds2 ( lb1 , lb2 , array )  RESULT ( ptr )  INTEGER ,  INTENT ( IN )  ::  lb1 , lb2  REAL ,  DIMENSION ( lb1 :, lb2 :),  INTENT ( IN ),  TARGET  ::  array REAL , DIMENSION (:, :), УКАЗАТЕЛЬ :: ptr ptr => ФУНКЦИЯ КОНЕЦ массива : окно          =>  remap_bounds2 ( r , s , таблица ( m : n , p : q ))

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

Внутренние процедуры [ править ]

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

ВЫЗОВ DATE_AND_TIME  ( ВРЕМЯ = т )

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

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

  1. элементарный - работа со скалярами или массивами, например ABS(a);
  2. запрос - независимо от значения аргумента (который может быть не определен), например PRECISION(a);
  3. трансформационный - аргумент массива с результатом массива другой формы, например RESHAPE(a, b);
  4. подпрограммы, например SYSTEM_CLOCK.

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

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

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

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

 BTEST Bit тестирование 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 ), a ( 2 ), a ( 3 ) печать «(a10)» , слово ( 5 : 14 ) печать «(3f10.3)» ,            а ( 1 ) * а ( 2 ) + я ,  sqrt ( а ( 3 : 4 ))

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

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

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

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

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

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

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

прочтите  "(8f10.5)" ,  p % x ,  p % y ,  t % a % x ,  t % a % y ,  t % b % x ,  &  t % b % y ,  t % c % x ,  t % c % y

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

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

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

символ ( len = * ),  параметр  ::  form = "(f10.3)" : печатная форма ,  q

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

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

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

чтение  ( unit = 4 ,  fmt = "(f10.3)" )  q чтение  ( unit = nunit ,  fmt = "(f10.3)" )  q чтение  ( unit = 4 * i + j ,  fmt = "(f10. 3) " )  а

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

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

read  ( unit = * ,  fmt = "(f10.3)" )  q

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

read  ( unit = nunit ,  fmt = "(3f10.3)" ,  iostat = ios )  a , b , c if  ( ios  ==  0 )  то ! Успешное чтение - продолжить выполнение.  : else ! Состояние ошибки - примите соответствующие меры.  ошибка вызова ( ios ) закончится, если 

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

write  ( unit = nout ,  fmt = "(10f10.3)" ,  iostat = ios )  a

Внутренние файлы [ править ]

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

целое число ,  размер ( 30 )  ::  ival integer  ::  ключевой символ ( len = 30 )  ::  буферный символ ( len = 6 ),  размер ( 3 ),  параметр  ::  form = ( /  "(30i1)" ,  "(15i2) ) " , " (10i3) "  / ) чтение  ( unit = * ,  fmt = " (a30, i1) " )  буфер,  Ключ для чтения  ( единица = буфер ,  FMT = форма  ( ключ ))  Ival ( 1 : 30 / ключ )

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

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

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

целое  ::  дня реального  ::  денежный символ ( LEN = 50 )  ::  строка : ! впишите в строку write  ( unit = line ,  fmt = "(a, i2, a, f8.2, a)" )  "Выручка за день" ,  день ,  "are" ,  наличные ,  "доллары"

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

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

Ввод-вывод, управляемый списком [ править ]

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

целое число  ::  я реальная  ::  комплекс , размерность ( 2 ) :: Поле логического :: флаг символов ( LEN = 12 ) :: Название символа ( Len = 4 ) :: слово : чтение * , я , , поле , флаг , название , слово                

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

10  6.4  ( 1.0 , 0.0 )  ( 2.0 , 0.0 )  t  испытание /

(в котором заготовки используются в качестве разделителей), а затем i, a, field, flag, и titleбудет приобретать значения 10, 6.4, (1.0,0.0) и (2.0,0.0), .true.и , testсоответственно, в то время как wordостается неизменным.

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

Не продвигающийся ввод-вывод [ править ]

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

character ( len = 3 )  ::  key integer  ::  u ,  s ,  ios : read ( unit = u ,  fmt = "(a3)" ,  advance = "no" ,  size = s ,  iostat = ios )  key if  ( ios  ==  0 )  тогда  : else ! ключ не находится в одном  ключе записи ( s + 1:)  =  ""  : конец, если

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

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

write  ( unit = * ,  fmt = "(a)" ,  advance = "no" )  "введите следующее простое число:" read  ( unit = * ,  fmt = "(i10)" )  prime_number

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

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

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

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

напечатайте  «(2 (2i5,2f8.2))» ,  i ( 1 ), i ( 2 ), a ( 1 ), a ( 2 ),  i ( 3 ), i ( 4 ), a ( 3 ), a ( 4 )

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

напечатать  "(10i8)" ,  ( /  ( i ( j ),  j = 1 , 200 )  / )

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

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

  • Целое число: iW iW.M
  • Настоящий: fW.D esW.D esW.DeE
  • Сложный: пары fили esредактировать дескрипторы
  • Логично: lW
  • Персонаж: a aW
  • Производные типы: редактируются соответствующей последовательностью дескрипторов редактирования, соответствующих внутренним типам конечных компонентов производного типа.
    type ,  public  ::  string  integer  ::  length  character ( len = 20 )  ::  word end type string type ( string )  ::  text read ( unit = * ,  fmt = "(i2, a)" )  текст

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

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

  • ss(Знак подавить) Дескриптор подавляет ведущий плюс признаки. Для включения печати знака плюс spиспользуется дескриптор (печать знака). sДескриптор восстанавливает возможность процессора.
  • Этот дескриптор остается в силе до конца спецификации формата, если не соблюдается другой из них.

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

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

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

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

Неформатированный ввод-вывод [ править ]

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

open ( unit = 4 ,  file = 'test' ,  form = 'unformatted' ) чтение ( unit = 4 )  q write ( unit = nout ,  iostat = ios )  a  ! нет fmt =

Файлы прямого доступа [ править ]

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

целое число ,  параметр  ::  NUnit = 2 ,  длина = 100 реальных ,  размер ( длина )  ::  реальная , размер ( длина + 1 : 2 * длина ) :: б целое :: я , rec_length : справки ( iolength = rec_length ) open ( unit = nunit , доступ          = "Прямой" ,  Recl = rec_length ,  статус = "Царапина" ,  действие = "чтение и запись" ) : ! Запись массив б в файл прямого доступа в рекордных 14 записей  ( блок = NUnit ,  прн = 14 )  б : ! ! Прочитать массив обратно в массив a read  ( unit = nunit ,  rec = 14 )  a : do i  =  1 ,  length/ 2  a ( i )  =  i end do ! ! Заменить измененную запись записи  ( unit = nunit ,  rec = 14 )  a

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

Операции с внешними файлами [ править ]

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

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

  • backspaceЗаявление:
    backspace  ( unit = u  [, iostat = ios ])  ! где [] означает необязательный
  • rewindЗаявление:
    перемотка назад  ( unit = u  [, iostat = ios ])
  • endfileЗаявление:
    endfile  ( unit = u  [, iostat = ios ])

openЗаявление [ править ]

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

open  ( unit = u ,  status = st ,  action = act  [, olist ])

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

open  ( unit = 2 ,  iostat = ios ,  file = "cities" ,  status = "new" ,  access = "direct" ,  &  action = "readwrite" ,  recl = 100 )

Остальные спецификаторы - formи position.

closeЗаявление [ править ]

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

закрыть  ( unit = u  [, iostat = ios ]  [, status = st ])

как в

закрыть  ( unit = 2 ,  iostat = ios ,  status = "delete" )

inquireЗаявление [ править ]

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

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

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

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

узнать  ( unit = u ,  ilist )

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

справки  ( файл = FLN ,  IList )

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

узнать  ( iolength = длина )  olist

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

логический  ::  ех ,  оп характер  ( LEN = 11 )  ::  NAM ,  согл ,  Seq ,  FRM целого  ::  IREC ,  NR INQUIRE  ( единица = 2 ,  существует = ех ,  открыто = оп ,  имя = NAM ,  доступ = согл ,  последовательного = seq ,  form = frm ,  & recl = irec ,  nextrec = nr )

дает

напр  . правда . op  . правда . Nam  города согл  DIRECT SEQ  NO FRM  UNFORMATTED IREC  100 NR  1

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

Остальные спецификаторы есть iostat, opened, number, named, formatted, position, action, read, write, readwrite.

Ссылки [ править ]

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