3.4.3. Логические выражения
Логическими данными чаще всего являются логические отношения числовых или текстовых данных (п. 3.5.1), хотя могут иметь вид самостоятельных логических выражений. Каждая операция логического отношения имеет два равноценных обозначения, поддерживаемых стандартом Фортрана 90/95 (табл. 3.6). Для обозначений в первом столбце таблицы, унаследованных от ранних версий Фортрана (Фортран 77), обязательны обрамляющие точки, являющиеся частью мнемоники операции, т.е. запись с обрамляющими точками: «.EQ.» – правильно, а без них: «EQ» – неправильно. При записи таких операций отношения, как «= =», «/ =» и ниже, в том же столбце табл. 3.6 обрамляющие символы (точки или что-то еще) не требуются, но нужно следить, чтобы между символами не было пробелов. Если в тексте данного руководства такие пробелы присутствуют, то только для улучшения читаемости, поскольку не всякий читатель найдет на клавиатуре кнопку с длинным знаком равенства (по аналогии с клавишей Any Key).
Таблица 3.6. Логические отношения в Фортране
|
Обозначения |
Отношение |
||
.EQ. |
|
или |
= = |
РАВНО |
.NE. |
|
или |
/ = |
НЕ РАВНО |
.GT. |
|
или |
> |
БОЛЬШЕ |
.GE. |
|
или |
> = |
БОЛЬШЕ ИЛИ РАВНО |
.LT. |
|
или |
< |
МЕНЬШЕ |
.LE. |
|
или |
< = |
МЕНЬШЕ ИЛИ РАВНО |
Правила объявления и инициализация логических переменных и констант практически ничем не отличаются от объявления и инициализация числовых данных (см. п. 3.4.1) – в точности также используется атрибут PARAMETER для объявления именованных констант и оператор присваивания «=» для присваивания логических значений переменным и именованным константам (пример 3.55). Для объявления логических массивов в примере используется атрибут DIMENSION.
Для обеспечения возможности построения из операций отношения более сложных логических выражений в Фортране предусмот-
166
рены логические операции, представленные в табл. 3.7 в порядке убывания приоритета.
Пример 3.55. Особенности деления целых чисел program LOGFACT1
logical, parameter :: TRUFACT=.TRUE., FALFACT=.FALSE. logical, parameter , dimension(0:1):: FACTS=(/.FALSE., .TRUE. /) logical FACT1, FACT2
FACT1 = 0 .EQ. 0; FACT2 = – 1 /= 1 !Присваивание логических значений print*, TRUFACT, FALFACT ! Печать логических именованных констант print*, FACT1, FACT2
print*, FACTS end
Таблица 3.7. Логические операторы Фортрана
Обозначение |
Название оператора |
.NOT. |
ЛОГИЧЕСКОЕ ОТРИЦАНИЕ (НЕ) |
.AND. |
ЛОГИЧЕСКОЕ ПЕРЕСЕЧЕНИЕ (И) |
.OR. |
ЛОГИЧЕСКОЕ ОБЪЕДИНЕНИЕ (ИЛИ) |
.EQV. |
ЛОГИЧЕСКАЯ ЭКВИВАЛЕНТНОСТЬ |
.NEQV. |
ЛОГИЧЕСКАЯ НЕЭКВИВАЛЕНТНОСТЬ |
Если операндами логических отношений (см. табл. 3.6) могут быть только текстовые и числовые данные, то операндами логических операций могут быть только логические данные.
Логические отношения (см. табл. 3.6) имеют более высокий приоритет выполнения по сравнению с логическими операциями (см. табл. 3.7). Каждое логическое отношение (утверждение) является элементарным логическим выражением и может принимать значения: .TRUE. или .FALSE., все операции отношения имеют одинаковый приоритет выполнения по отношению друг к другу.
Из логических данных и элементарных логических выражений можно выстраивать достаточно сложные логические выражения. При записи логических выражений можно использовать круглые скобки. Заключенные в круглые скобки части логического выражения вычисляются в первую очередь.
Оба логических выражения (для переменной FACT1 и FACT2 в примере 3.56) содержат смешение стилей: для X > 0 используется знак «больше», а для Y.LT.2 используется мнемоника «меньше», что допустимо, но чего лучше избегать в силу возникающей пута-
167
ницы. В первом выражении проверяется истинность хотя бы одного из условий: принадлежности X интервалу от нуля до двух (включая два) или принадлежности Y тому же интервалу (включая нуль), а во втором выражении проверяется одновременная истинность тех же условий.
Поскольку логическое объединение «ИЛИ» (.OR.) имеет меньший приоритет, по сравнению с логическим пересечением «И» (.AND.), то в первом выражении скобки не требуются, а во втором выражении они необходимы для регулирования приоритета – иначе логические пересечения «И» (.AND.) будут выполняться последовательно, как имеющие равный приоритет.
Пример 3.56. Сложные логические выражения program LOGFACT2
logical FACT1, FACT2 real :: X= 1., Y =2.
FACT1=X > 0. .and. X <= 2. .or. Y .ge. 0. .and. Y .lt. 2. FACT2=(X > 0. .and. X <= 2.) .and. (Y .ge. 0. .and. Y .lt. 2.) print*, FACT1, FACT2
end
Практическое использование логических выражений рассматривается в связи с их использованием в логических операторах и кон-
струкциях IF (п. 3.6.1).
3.4.4. Работа с текстовыми строками
Как уже отмечалось (см. п. 3.3.4), тестовые данные (CHARACTER) имеют особенность описания, связанную с параметром разновидности типа: KIND, который применяется для указания кодовой таблицы символов: ASCII, UTF, Windows-1251 и т.д. При этом оптимальная кодовая таблица символов уже выбрана операционной системой, при инсталляции компилятора Фортрана и поэтому с кодовыми страницами символов нужно работать аккуратно. Если есть необходимость явного указания кодовой страницы, то KIND указывается через запятую, с длиной тестовой строки в символах LEN,
например: CHARACTER (KIND= KIND( UTF ), LEN=13).
LEN является параметром, отвечающим за длину текстовой строки, измеряемую количеством символов. С его помощью мож-
168
но, например, объявить именованную 13-ти символьную текстовую константу TEXT (произвольное имя) со значением «Hello, World!».
Сконстантой TEXT (пример 3.57) можно работать не только как
сцелостным объектом, но и выделять в нем подстроки, задавая их границы через номера начального и конечного символа. Например, нетрудно видеть, что подстрока «Hello» – это символы строки TEXT с первого по пятый, а подстрока «World!» – символы с восьмого по тринадцатый. Самое простое, что можно сделать со строкой и ее подстроками – это напечатать их (см. пример 3.57).
Пример 3.57. Текстовая константа и ее подстроки program TEXTLINE1
character(LEN=13), parameter :: TEXT=”Hello, World!” print*, TEXT; print*, TEXT(1:5); print*,TEXT(8:12) end
Если в программе используются текстовые константы, то их значения (как и любых других констант) не изменяются, соответственно, еще на стадии компиляции может быть автоматически посчитано количество символов в константе и произведена ее инициализация. Необязательно считать символы в константе – это сделает компилятор, если в качестве значения длины строки LEN указать: «*» (звездочку). При этом возможно сокращение записи – «звездочка» без LEN (пример 3.58).
Пример 3.58. Автоматическое определение длины текстовой константы program TEXTLINE2
character(LEN = *), parameter :: TEXT1=”Hello, World!” character(*), parameter :: TEXT2=”Global World! “ print*, TEXT1; print*, TEXT1(1:5); print*,TEXT1(8:12) print*, TEXT2; print*, TEXT1(1:6); print*,TEXT1(8:12) end
С текстовой переменной, как и с константой, можно работать как с целостным объектом (это происходит при инициализации), а можно работать с подстроками, задавая их границы (пример 3.59).
Пример 3.59. Текстовая переменная и ее подстрока (вариант 1) program TEXTLINE3
character(LEN=13) :: TEXT= “Hello, World!” TEXT(1:6) = “Global”
169
print*, TEXT end
Указание длины строки LEN для текстовых переменных обязательно.
Для тестовых данных определена единственная операция – конкатенация (пример 3.60), обозначаемая сдвоенными прямыми слешами: «//». Конкатенация позволяет последовательно объединить несколько текстовых строк в одну строку.
Пример 3.60. Текстовая переменная и ее подстрока (вариант 2) program TEXTLINE4
character(LEN=*), parameter :: TXT1=”Hello”, TXT2 = “Global”, TXT3=”World!” character(LEN=LEN(TXT1)+LEN(TXT2)+LEN(TXT3)+3) :: TEXT
TEXT= TXT1 // “,^” // TXT2 // “^” // TXT3 // “!”; print *, TEXT end
Помимо конкатенации в примере 3.60 использована строковая функция LEN, возвращающая в качестве результата длину строки, являющейся аргументом этой функции: LEN(TXT1) и т.д. Необходимо также вспомнить соглашения и рекомендации, по поводу обозначения пробелов (см. п. 3.1.1).
3.4.5. Операции с массивами
Любую операцию, определенную для скалярных встроенных объектов, можно применить к одному массиву, если речь идет об унарной операции, или двум массивам, когда дело касается бинарной операции. В последнем случае оба массива должны быть одинаковой формы (см. п. 3.3.6), т.е. одного ранга и с одинаковыми экстентами.
Пример 3.61. Объявление и инициализация массива констант с указанием верхней границы (вариант 1)
program OPERARR1
integer, parameter, dimension(5):: A = (/ 0, 1, 2, 3,4/), B = (/5, 6, 7, 8, 9/) integer, dimension(5):: C, D, E, F, G
C = A + B; D = A – B; E = A * B; F = A / B; G = A**B
print*, A; print*, B; print*, C; print*, D; print*, E; print*, F; print*, G end
170