Пример 3.81. Расстановка пробелов привыводе program FMT2
K=1; L=2; M=3; N=4 print ‘(4i1)’, K, L, M, N print ‘(4i2)’, K, L, M, N print 10, K, L, M, N
10 format(4(1x,i1)) end
Второй и третий PRINT дадут одинаковый результат «1^2^3^4». Во втором PRINT это происходит за счет избыточной ширины поля
исмещения выводимого результата к правой границе. Третий PRINT по метке «10» ссылается на оператор FORMAT. В спецификации, описанной оператором FORMAT, между целыми числами введен отступ в один пробел: «1X». В обоих случаях использован коэффициент повторения: «4I2» и «4(1X,I1)» вместо «I2, I2, I2, I2»,
иеще более длинной записи: «1X, I1, 1X, I1, 1X, I1, 1X, I1,».
Принципы формирования спецификаций формата с использова-
нием коэффициентов повторения, разделения пробелами и оператора FORMAT универсальны для всех дескрипторов (см. табл. 3.10). Далее приводятся некоторые особенности спецификаций формата для различных дескрипторов.
Пример 3.82. Вывод одного и того же числа в разных форматах
program FMT3 |
|
X=12345 |
|
print '(f6.0)', X |
! 12345. |
print '(g10.5)', X |
! 12345. |
print '(f7.1)', X |
! 12345.0 |
print '(e10.5)', X |
! .12345E+05 |
print '(e11.5)', X |
! 0.12345E+05 |
print '(e11.5e3)', X ! .12345E+005 |
|
print '(en10.3)', X |
! 12.345E+03 |
print '(es10.4)', X |
! 1.2345E+04 |
end |
|
При использовании дескриптора F одна позиция в поле вывода должна быть зарезервирована под десятичную точку, а применение дескриптора E помимо этого требует четыре позиции под экспоненциальную часть, если число позиций под степень десятичной экспоненты не задано явно (пример 3.82).
191
Целая часть числа при выводе под управлением дескриптора E равна нулю, что не всегда удобно. Сдвинуть десятичную точку на k порядков вправо, уменьшив настолько же показатель десятичной экспоненты, позволяет масштабный множитель kP (пример 3.83).
Пример 3.83. Использование масштабирующего множителя program FMT4
X=0.76543E+12; Y=0.34567E+21
print '(e11.5)', X |
! 0.76543E+12 |
print '(2p, e11.5)', X |
! 76.543E+10 |
print '(2p, 2(2x,e11.5)', X, Y ! 76.543E+10^^34.567E+19 end
Масштабный множитель является элементом списка спецификации формата и отделяется от последующих дескрипторов запятой. При этом он действует на все последующие дескрипторы E, F и G до появления в списке следующего масштабного множителя. Действие масштабного множителя не распространяется на дескрипторы EN и ES.
При выводе данных непосредственно в спецификацию формата может включаться текст в виде буквальных констант (пример 3.84) что в ряде случаев позволяет разгрузить оператор вывода данных, используя оператор FORMAT.
Пример 3.84. Дескрипторы текстовых строк в спецификации формата program FMT5
integer :: X=1, Y=2, Z=3
print '(1x, "X=", i1, 1x, "Y=", i1, 1x, "Z=", i1)', X, Y, Z print 10, X, Y, Z
print 20, X, Y, Z
10 format(1x, "X=", i1, 1x, "Y=", i1, 1x, "Z=", i1) 20 format(1x, "X=", i1/ 1x, "Y=", i1/ 1x, "Z=", i1) end
Появление в спецификации формата прямого слеша «/» (оператор FORMAT с меткой «20» в предыдущем примере) приводит к переводу строки, несколько слешей подряд инициируют соответствующее количество переводов строки.
Необходимо заметить, что после выполнения операторов вывода данных WRITE и PRINT сразу же происходит перевод строки. Для предотвращения этого в конце спецификации формата необхо-
192
димо поставить символ $ (знак денежной единицы), не отделяя его запятой от предыдущего списка спецификации формата. Это может потребоваться, если после вывода на экран требования ввода данных курсор оставался на месте (пример 3.85).
Пример 3.85. Исключение перевода строки program FMT6
print'("X="$)' read *, X
print'("X=", g12.7)', X end
Форматный ввод/вывод логических и текстовых данных полностью аналогичен вышеизложенным правилам и примерам, поэтому не должен вызывать затруднений.
3.6.3. Неявные циклы и ввод/вывод массивов
Неявные циклы аналогичны конструкции DO с фиксированным числом повторений (см. п. 3.5.3), но не являются самостоятельными конструкциями, поскольку могут быть использованы только в операторах ввода/вывода, как правило, для работы с массивами.
Для вывода двумерного массива на экран в виде матрицы можно использовать конструкцию DO с фиксированным числом повторений и ухищрение в спецификации формата вывода, когда все элементы строки с номером выводятся без перевода строки (запрет переводить строку контролирует символ «$» в конце спецификации формата). Перевод строки осуществляется за счет пустого оператора PRINT за пределами внутреннего цикла (пример 3.86).
При использовании для той же задачи вложенных неявных циклов программа становится более компактной. Неявный цикл представляет собой заключенную в круглые скобки конструкцию, в которой сначала записано выражение, зависящее от переменной цикла (в данном случае элемент массива), и через запятую записывается переменная цикла, диапазон пробегаемых ею значений и шаг (в точности, как в конструкции DO с фиксированным числом повторений).
193
Пример 3.86. Печать таблицы с помощью конструкции DO program ARRDO1
integer, parameter:: N = 3
integer, dimension(N, N) :: DIGITS = RESHAPE( (/1, 4, 7, 2, 5, 8, 3, 6, 9/), (/3,3/) ) do I = 1, N
do J = 1, N
print '(1x,i1 $)',DIGITS(I,J) end do
print*,'' end do end
Записанный неявный цикл может служить выражением, для последующего внешнего цикла, т. е. через запятую записывается переменная внешнего цикла со своими границами и шагом и все это заключается в круглые скобки (пример 3.87).
Пример 3.87. Печать таблицы с помощью неявного цикла для ввода/вывода массивов
program ARRDO2 integer, parameter:: N = 3
integer, dimension(N, N) :: DIGITS = RESHAPE( (/1, 4, 7, 2, 5, 8, 3, 6, 9/), (/3,3/) ) print'(3(1x,i1))', ((DIGITS (I, J), J = 1, N ), I = 1, N) ! Неявный цикл
end
Чтобы показать, что неявные циклы можно использовать не только для ввода/вывода массивов, но выражений (например, арифметических), можно напечатать все туже квадратную (3х3) таблицу чисел от единицы до девяти (пример 3.88).
Пример 3.88. Печать таблицы с помощью неявного цикла для ввода/вывода массивов и выражений
program TBLPRN integer, parameter:: N = 3
print'(3(1x,i1))', ((3*(I – 1)+J, J = 1, N ), I = 1, N) ! Неявный цикл end
Использование неявных циклов в конструкторах массивов показано в п. 3.3.6, но в этом случае в неявный цикл не могут быть включены даже простейшие выражения – только переменные.
194
3.6.4. Файловый ввод/вывод
Ранее рассматривалось взаимодействие со стандартными устройствами: клавиатурой и монитором. Также упоминалось, что доступные компьютеру устройства пронумерованы, и обращение к ним осуществляется через их номера. Так, номер стандартного устройства ввода – клавиатуры, обычно «5», а номер стандартного устройства вывода – экрана монитора, обычно «6». Но поскольку эти устройства используются по умолчанию, для них предусмотрено единое обозначение – символ «звездочка».
Если быть точнее, то внешние устройства и их номера в Фортране всегда относятся к файлам, т.е. программа считывает данные и записывает их в файлы, связанные с устройствами. Например, в UNIX стандартное устройство «5» ассоциируется с файлом потока стандартного ввода stdin, а стандартное устройство за номером «6» – с файлом потока стандартного ввода stdout. Не зарезервированные номера устройств (а это практически все множество буквальных целых констант) по умолчанию связаны с жестким диском компьютера, т.е. эти номера можно ассоциировать с файлами жесткого диска, обычно для этого хватает первых четырех номеров от
«1» до «4».
Пример 3.89. Открытие, запись, чтение и закрытиефайлов program FINOUT1
real :: X=1., Y=2., Z=3.
!Открытие пустого файла, запись данных и закрытие файла open(1, file= "info.txt")
write(1,*) X, Y, Z close(1)
!Открытие существующего файла, чтение данных и закрытие файла open(1, file='info.txt')
read(1,*) X, Y, Z close(1)
!Вывод на экран данных, считанных из файла print*, X, Y, Z
end
Ассоциирование файла с номером устройства – важный технологический момент, предшествующий чтению или записи данных. Сначала внешний файл связывается с номером устройства и от-
195