современный фортран , Бортеньев. О. В. Бартеньев Современный Фортран
Скачать 2.24 Mb.
|
* и латинских букв c или C, размещенных в первую позицию строки, либо после восклицательного 417 О. В. Бартеньев. Современный ФОРТРАН знака, размещаемого в любой (с 1-й по 72-ю) позиции строки. Строка с восклицательным знаком в колонке 6 интерпретируется как строка продолжения. Комментарии не оказывают никакого влияния на работу программы. Первая, или единственная, строка оператора Фортрана называется начальной строкой. Начальная строка имеет либо пробел, либо 0 в 6-й колонке; в колонках 1-5 указываются метка оператора либо пробелы. Метка оператора - целая константа без знака в диапазоне от 1 до 99999. Метки используются для ссылки на оператор. Ссылка на оператор выполняется в операторах перехода (GOTO), в операторах В/В для ссылки на оператор FORMAT, в операторах цикла и в других случаях. Пример: real x / -1.32 /, y / 6.487 / write(*, 1) x, y ! Ссылка на оператор format 1 format(2x, 'x = ', f6.2, 2x, 'y = ', f6.3) if(exp(x/3.) .gt. cmax) go to 89 ! Ссылка на оператор return 89 return Строка продолжения содержит пробелы в колонках 1-5 и символ (отличный от нуля или пробела) в колонке 6. Строка продолжения увеличивает число доступных для записи оператора позиций. Число строк продолжения ограничено доступной памятью ЭВМ. Директивы управляют работой компилятора. Директива начинается с символа $, или префикса !MS$ в FPS, или префикса !DEC$ в CVF. В любом случае в фиксированной форме директива должна начинаться в первой колонке строки, например: $NOFREEFORM !DEC$NOFREEFORM !MS$NOFREEFORM Отладочные строки. Включение режима проверки осуществляется директивой $DEBUG. Выключение - директивой $NODEBUG. В одной строке исходного текста могут располагаться строки двух типов: • начальная строка и комментарий (после символа !); • строка продолжения и комментарий (после символа !). Пример двух вариантов одной и той же программы, содержащей начальные строки, комментарии и в варианте 2 строку продолжения. C Вариант 1 C234567 - нумерация позиций PROGRAM p1 ! Комментарий implicit none ! Должны быть объявлены типы всех объектов данных 418 Приложение 2. Нерекомендуемые, устаревшие и исключенные свойства real d /4./, s /2.3/ ! Объявляем переменные write(*, *) s / sqrt(d) ! SQRT(x) - встроенная функция end ! вычисления квадратного корня из x * Вариант 2 *234567 - Комментарий c Это тоже комментарий data d /4./, s /2.3/ ! Инициализация переменных write(*, *) ! Начальная строка * s/sqrt(d) ! Строка продолжения end Пояснение. Отказаться от раздела объявлений во втором варианте позволяют существующие умолчания о типах данных. П.-2.1.2. Оператор EQUIVALENCE Оператор указывает, что две или более переменные занимают одну и ту же область памяти. EQUIVALENCE(nlist) [,(nlist)] ... nlist - список двух или более переменных (простых или составных), разделенных запятыми. Список не может включать формальные параметры, динамические массивы и ссылки. Размерности массивов списка должны быть целыми константами. Заданное без размерностей имя массива адресует первый элемент массива. Переменные, адресующие одну и ту же область памяти, называются ассоциированными по памяти. При этом не выполняется никакого автоматического преобразования типов данных. Ассоциированные символьные элементы могут перекрываться, что иллюстрируется следующим примером: character a*4, b*4, c*3(2) equivalence(a, c(1)), (b, c(2)) Графически перекрытие отображено на рис. П.-2.1. 1 2 3 4 5 6 7 ------------ a ------------- ------------- b ------------- ------- c(1) ------- ------- c(2) ------- Рис. П.-2.1. Перекрытие ассоциированных символьных элементов Правила ассоциирования элементов: • переменная не может занимать более одной области памяти. Так, следующие операторы вызовут ошибку, поскольку пытаются адресовать переменную r двум различным областям памяти, в одной из которых размещен элемент s(1), а в другой - s(2): 419 О. В. Бартеньев. Современный ФОРТРАН real r, s(10) equivalence(r, s(1)) equivalence(r, s(2)) ! Ошибка • соответствующие элементы массивов должны ассоциироваться последовательно. Так, следующие операторы вызовут ошибку: real r(10), s(10) equivalence(r(1), s(1)) equivalence(r(5), s(7)) ! Допустимо: equivalence(r(5), s(5)) Компилятор всегда выравнивает несимвольные элементы по четному байту. Символьные и несимвольные элементы могут быть ассоциированы, если несимвольный элемент начинается на четном байте. При необходимости компилятор разместит символьный элемент так, чтобы несимвольный начинался на четном байте. Однако это не всегда возможно. В следующем примере невозможно разместить символьный массив так, чтобы оба несимвольных элемента начинались на четном байте памяти. character*1 char1(10) real a, b equivalence(a, char1(1)) equivalence(b, char1(2)) Элемент списка nlist нельзя инициализировать в операторах объявления типа. Пример ошибки: integer i /1/, j ! Ошибка equivalence(i, j) Оператор EQUIVALENCE не может разделять память между двумя common-областями или между элементами одного и того же общего блока. Оператор EQUIVALENCE может расширить common-область в результате добавления переменных, продолжающих common-область. Нельзя расширять common-область, добавляя элементы перед этой областью. Так, следующие операторы вызовут ошибку: common /b1/ r(10) real s(20) equivalence(r(1), s(7)) ! Правильно: equivalence(r(1), s(1)) Ошибка возникает из-за того, что перед общей областью должны быть размещены элементы s(1), ..., s(6). Если использована директива $STRICT или опция компилятора /4Ys, то при работе с оператором EQUIVALENCE следует придерживаться следующих правил: • если ассоциируемый объект имеет стандартный целый, логический, вещественный, вещественный двойной точности тип или относится к упорядоченному производному типу с числовыми и логическими компонентами, то все объекты в операторе EQUIVALENCE должны иметь один из таких типов; 420 Приложение 2. Нерекомендуемые, устаревшие и исключенные свойства • если ассоциируемый объект имеет символьный тип или относится к упорядоченному производному типу с символьными компонентами, то все объекты в операторе EQUIVALENCE должны иметь один из таких типов, хотя могут быть и разной длины; • если ассоциируемый объект имеет упорядоченный производный тип, который не является чисто числовым или символьным, то все объекты в операторе EQUIVALENCE должны относиться к тому же производному типу; • если ассоциируемый объект имеет встроенный, но нестандартный тип, например INTEGER(1), то все объекты в операторе EQUIVALENCE должны иметь тот же тип и параметр разновидности типа. Оператор EQUIVALENCE предназначен для экономии оперативной памяти. Так, можно использовать одну и ту же память под символьный и вещественный массивы, уменьшая издержки памяти в два раза. Недостатки оператора очевидны: если переменные a и b занимают одну и ту же память, то изменение значения одной из переменных приведет к изменению значения и другой. Поэтому каждый раз, применяя переменную a, необходимо следить, чтобы ее значение не было случайным образом изменено в результате изменения значения переменной b. В больших программах это может оказаться весьма затруднительным. Другие применения оператора - создание псевдонимов и отображение одного типа данных в другой, что можно было бы использовать при хранении и выборке данных. Теперь все эти задачи можно решить более надежными и удобными средствами. В зависимости от ситуации вместо оператора EQUIVALENCE можно использовать автоматические массивы, размещаемые массивы и ссылки для повторного использования памяти; ссылки как псевдонимы и функцию TRANSFER (разд. 6.5) для отображения одного типа данных в другой. П.-2.1.3. Оператор ENTRY Рассмотренный в разд. 8.12 оператор ENTRY дополнительного входа в процедуру не может быть рекомендован для применения, как оператор, серьезно ухудшающий структуру программы. П.-2.1.4. Вычисляемый GOTO Оператор имеет вид: GOTO(labels) [,] n labels - список одной или более разделенных запятыми меток исполняемых операторов того же блока видимости. Одна и та же метка может появляться в списке более одного раза. n - целочисленное выражение. 421 О. В. Бартеньев. Современный ФОРТРАН Оператор передает управление n-й метке списка labels. Допустимый диапазон значений n: 1 ≤ n ≤ m, где m - число меток в списке labels. Если n выходит за границы допустимого диапазона, то вычисляемый GOTO работает так же, как и пустой оператор CONTINUE. Переход внутрь DO-, IF-, SELECT CASE- или WHERE-конструкций запрещен. Пример: next = 1 goto (10, 20) next ! Передача управления на оператор 10 continue 10 continue 20 continue Оператор заменяется конструкциями IF и SELECT CASE. П.-2.1.5. Положение оператора DATA Оператор DATA задания начальных значений переменных (разд. 3.7) можно располагать среди исполняемых операторов программы. Но этой возможностью пользоваться не рекомендуется. Следует располагать операторы DATA в разделе описаний перед первым исполняемым оператором. П.-2.2. Устаревшие свойства Фортрана, определенные стандартом 1990 г. П.-2.2.1. Арифметический IF Оператор имеет вид: IF(expr) m1, m2, m3 expr - целочисленное или вещественное выражение. m1, m2, m3 - метки исполняемых операторов того же блока видимости. Значения меток могут совпадать. Оператор обеспечивает переход по метке m1, если expr < 0, по метке m2, если expr = 0, и по метке m3, если expr > 0. Пример. Вычислить число отрицательных, нулевых и положительных элементов целочисленного массива. integer a(10) /-2, 0, 3, -2, 3, 3, 3, 0, 4, 0/ integer k1, k2, k3 k1 = 0; k2 = 0; k3 = 0 do i = 1, 10 if(a(i)) 10, 11, 12 10 k1 = k1 + 1; cycle 11 k2 = k2 + 1; cycle 12 k3 = k3 + 1 end do 422 Приложение 2. Нерекомендуемые, устаревшие и исключенные свойства print *, k1, k2, k3 ! 2 3 5 end Оператор заменяется конструкциями IF и SELECT CASE. П.-2.2.2. Оператор ASSIGN присваивания меток Оператор присваивания меток имеет вид: ASSIGNметкаTOимя переменной метка - целое число из диапазона 1-99999. В результате выполнения оператора ASSIGN переменной, которая должна быть целого типа, будет присвоено значение метки. Пример: integer label, k y = (2.5 * sin(5.2))**3 ... ! k получает некоторое значение if(k .eq. 1) assign 89 to label write(*, label) y ! Ссылка на оператор format 89 format(2x, 'y = ', f10.3) assign 17 to label if(y .gt. 0) go to label ! Переход к метке 17 17 stop Переменная, получившая в результате выполнения оператора ASSIGN значение метки, не может использоваться как переменная, имеющая численное значение, в выражениях Фортрана. Переменная, получившая значение помимо оператора ASSIGN, например в результате присваивания, не может использоваться в операторе перехода. Также в операторе GOTO не может быть использована и именованная константа. Оператор используется для выбора подходящего оператора FORMAT и в назначаемом операторе GOTO. В первом случае заменой оператору AS- SIGN является задание формата при помощи символьных выражений (разд. 9.2). Назначаемый GOTO всегда может быть успешно заменен конструкциями IF или SELECT CASE. П.-2.2.3. Назначаемый GOTO Оператор имеет вид: GOTOvar [[,] (labels)] var - переменная целого типа, значением которой является метка исполняемого оператора. Значение переменной var должно быть определено оператором ASSIGN в том же блоке видимости. 423 О. В. Бартеньев. Современный ФОРТРАН labels - список одной или более разделенных запятыми меток исполняемых операторов того же блока видимости. Одна и та же метка может появляться в списке более одного раза. Оператор передает управление оператору, метка которого совпадает со значением var. Запрещается переход внутрь DO-, IF-, SELECT CASE- и WHERE-конструкций. Пример: integer vi, cle ... ! cle получает некоторое значение if(cle .eq. 1) then ! Назначим vi нужное значение метки assign 200 to vi else if(cle .eq. 2) then assign 400 to vi else assign 100 to vi end if goto vi (100, 200, 400) 100 continue goto 500 200 continue goto 500 400 continue 500 continue end П.-2.2.4. Варианты DO-цикла Параметр DO-цикла и циклического списка, а также выражения, задающие пределы и шаг изменения параметра, могут быть вещественного типа (REAL(4) или REAL(8)). Например: do x = 0.4, 20.4, 0.4 end do Для приведенного цикла естественно ожидать, что число итераций ni, которое вычисляется по формуле ni = MAX(INT((stop - start + inc)/inc), 0), будет равно 51. На самом деле в результате ошибок округления промежуточным результатом при расчете ni может явиться число 50.999999..., а не 51.000000... Тогда после применения функции int значение ni будет равно 50. Поскольку такое может случиться, то применение вещественного параметра в DO-цикле и циклическом списке нежелательно. 424 Приложение 2. Нерекомендуемые, устаревшие и исключенные свойства DO-цикл с вещественным параметром заменяется DO- или DO WHILE- циклом. Не может быть рекомендовано и завершение вложенного DO-цикла одним общим помеченным оператором, например: s = 0.0 do 1 i = 1, n1 do 1 j = 1, n2 do 1 k = 1, n3 s = s + a(i, j, k) 1 continue Такая форма может послужить источником разнообразных ошибок. П.-2.2.5. Переход на END IF Переход на END IF может быть выполнен не только из конструкции, которую он завершает, но и извне. Этого следует избегать и пользоваться переходом на следующий за END IF оператор. П.-2.2.6. Альтернативный возврат Использование альтернативного возврата из подпрограммы (разд. 8.19) ухудшает структуру программы. Вместо него можно при выходе из подпрограммы вернуть код ее завершения, а последующее ветвление выполнить, например, конструкцией SELECT CASE. П.-2.2.7. Дескриптор формата H Дескриптор рассмотрен в разд. 9.7. Вместо него лучше использовать преобразование апострофа или кавычек. Так, вместо write(*, '(2x, 31HВведите границы отрезка [a, b]:)') лучше записать: write(*, '(2x, a)') 'Введите границы отрезка [a, b]: ' или write(*, "(2x, 'Введите границы отрезка [a, b]: ')") В отличие от первого оператора два последних не требуют подсчета числа передаваемых символов. П.-2.3. Устаревшие свойства Фортрана, определенные стандартом 1995 г. Приводимые ниже устаревшие свойства языка будут удалены из Фортрана в последующих версиях и, следовательно, их применение нежелательно. В приводимом перечне тремя звездочками (***) отмечены свойства, которые классифицируются как устаревшие, начиная с версии 425 О. В. Бартеньев. Современный ФОРТРАН Фортран 95. Прочие свойства отнесены к устаревшим еще стандартом Фортран 90. В списке 9 устаревших свойств: • арифметический оператор IF; • завершение нескольких DO-циклов одним оператором и завершение DO-цикла оператором, отличным от CONTINUE или END DO; • альтернативный возврат из процедуры; • вычисляемый оператор GOTO (***); • операторная функция (***); • размещение оператора DATA среди исполняемых операторов (***); • символьные функции предполагаемой - CHARACTER(len = *) - длины (***); • фиксированная форма исходного кода (***); • форма CHARACTER* для объявления символьных типов данных (***). Предполагается изъять из Фортрана первые 6 свойств уже в следующем стандарте. П.-2.4. Исключенные свойства Фортрана Стандарт 1995 г. исключил из Фортрана: 1) DO-цикл с вещественным и двойной точности параметром, например запрещен цикл: real(4) :: x, xs = 1.0, xf = 3.0, dx = 0.1 do x = xs, xf, df print *, x * sin(x) end do 2) переход на END IF из внешнего блока; 3) оператор PAUSE; 4) оператор ASSIGN присваивания меток и назначаемый GO TO; ясно, что нельзя использовать в качестве метки целочисленную переменную, получившую значение в результате выполнения оператора ASSIGN; 5) символьные константы с указателем длины, называемые также холлеритовскими константами. 426 Приложение 3. Дополнительные процедуры CVF и FPS, помимо предусмотренных стандартом Фортрана встроенных процедур, содержат большое число дополнительных процедур, которые в документации распределены по разделам: Раздел Модуль Запуск программ DFLIB (MSFLIB) Управление программой " Работа с системой, дисками и директориями " Управление файлами " Случайные числа " Процедуры даты и времени " Процедуры клавиатуры и звука " Обработка ошибок " Аргументы в командной строке " Сортировка и поиск в массиве " Процедуры управления операциями с плавающей точкой " Процедуры QuickWin " Графические процедуры " Создание диалогов DIALOGM Работа с национальным языком DFNLS (MSFNLS) Обеспечение совместимости с другими платформами PORTLIB Перечислим и опишем назначение дополнительных процедур (кроме процедур QuickWin и графических процедур), интерфейс к которым находится в модуле MSFLIB. Для вызова таких процедур необходимо к вызывающей программной единице подключить этот модуль, применив оператор USE MSFLIB. Графические процедуры подробно рассмотрены в гл. 12. Там же рассмотрена часть процедур QuickWin. |