Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
современный фортран , Бортеньев.pdf
Скачиваний:
242
Добавлен:
26.03.2015
Размер:
2.34 Mб
Скачать

О. В. Бартеньев. Современный ФОРТРАН

или

write(*, fmt = '(1x, f8.3, i10)') a, k

в виде имени именованного списка В/В:

integer :: k = 100, iarray(3) = (/ 41, 42, 43 /) real :: r4*4 = 24.0, r8*8 = 28.0

namelist /mesh/ k, r4, r8, iarray write(*, mesh)

или

write(*, nml = mesh)

в виде звездочки, указывающей на использование управляемого неименованным списком В/В:

write(*, *) a, k write(*, fmt = *) a, k

9.5. Списки ввода/вывода

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

9.5.1. Элементы списков ввода/вывода

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

Пример:

type point

 

real x, y

 

character(8) st

 

end type point

 

type(point) p(20), pxy

 

open(1, file = 'a.txt')

 

read(1, '(2f8.2)') pxy.x, pxy.y

! Возможные списки ввода

read(1, '(f8.2 / f8.2 / a)') p(1).x, p(1).y, p(1).st

read(1, 20) pxy

! В списке ввода 3 элемента

read(1, 20) (p(k), k = 1, 20)

! В списке ввода 60 элементов

20 format(2f8.2, a)

 

Присутствующий в списке В/В скалярный объект встроенного типа (кроме комплексного) создает один элемент В/В. Массив встроенного типа (кроме комплексного) добавляет в список В/В все свои элементы. Порядок

296

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

следования элементов массива в списке В/В совпадает с порядком их расположения в памяти ЭВМ. Так, эквивалентны списки:

real a(2, 3) / 1.1, 2.2, 3.3, 4.4, 5.5, 6.6 /

write(*, *) a ! В списке вывода 6 элементов write(*, *) a(1, 1), a(2, 1), a(1, 2), a(2, 2), a(1, 3), a(2, 3)

Скаляр комплексного типа создает два элемента В/В. В случае комплексного массива из n элементов в список В/В добавляется 2*n элементов. Компоненты скаляра производного типа располагаются в списке В/В в том же порядке, в котором они располагаются и в операторе объявления этого типа.

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

integer(2) k, m, a(20), b(10) complex(4) z

character(30) art(15)

character(30) :: fmt = '(4i4 / 10i3 / 2f8.2 / (a30))' open(1, file = 'a.txt')

read(1, fmt) k, m, a(2), a(4), b, z, art

Список ввода содержит 31 элемент: 25 из них дают массивы b и art, 2 - комплексная переменная z и по одному переменные k, m, a(2), a(4). Следовательно, не менее 31 значения должно присутствовать и в файле, из которого выполняется ввод данных. Число строк в файле не может быть менее 18, поскольку в спецификации формата fmt присутствует преобразование слеша (/), которое обеспечивает перемещение файлового указателя на начало новой записи. Положение и состав полей файла может

быть, например таким (символ

использован для обозначения пробела):

111

222

333

444

 

 

 

 

 

11

12

13

14

15

16

17

18

19

20

1111.11

2222.22

 

 

 

 

 

строка

 

1

 

 

 

 

 

 

 

...

 

 

 

 

 

 

 

 

 

 

строка

 

15

 

 

 

 

 

 

При составлении списка В/В следует учитывать ограничения:

в списке В/В не может появляться перенимающий размер массив, но могут появляться его подобъекты (элементы и сечения);

присутствующий в списке В/В размещаемый массив должен быть к моменту выполнения В/В размещен;

все ссылки списка В/В к моменту выполнения В/В должны быть прикреплены к адресатам. Передача данных выполняется между файлом и адресатом;

297

О. В. Бартеньев. Современный ФОРТРАН

каждый конечный компонент присутствующего в списке В/В объекта производного типа не должен иметь атрибут PRIVATE;

в списке В/В не могут присутствовать объекты производного типа, у которых среди компонентов какого-либо уровня есть ссылки.

Список В/В может быть пустым. Тогда при выводе создается запись нулевой длины. При вводе выполняется переход к следующей записи. Если же при пустом списке вывода используется формат, состоящий только из строки, то будет выведена запись, содержащая эту строку, например:

write(*, '(1x, "I am a test string")')

9.5.2. Циклические списки ввода/вывода

Список В/В может также содержать и циклический список, имеющий вид: (список объектов цикла, dovar = start, stop [, inc])

где каждый объект цикла - это переменная (в случае ввода), или выражение (в случае вывода), или новый циклический список; dovar - переменная цикла - целая скалярная переменная; start, stop, inc - целые скалярные выражения. Циклический список оператора В/В работает так же, как и DOцикл с параметром или неявный цикл оператора DATA и конструктора массива. Другое название циклического списка оператора В/В - неявный цикл оператора В/В.

Пример. Вывод горизонтальной линии.

print '(1x, 80a1)', ('_', k = 1, 80) ! В списке вывода 80 элементов

9.5.3. Пример организации вывода

Задача: выполнить табуляцию функции двух переменных: z = |x - y| ey/3/(1/3 + cos(x/y))

при изменении x от 1 до 5 с шагом 0.5, а y - от 1.1 до 1.5 с шагом 0.05. Оформим результат в виде таблицы, содержащей заголовок, значения x

по вертикали и значения y по горизонтали. В ячейках таблицы выведем соответствующие аргументам x и y значения z (рис. 9.1).

Зависимость z = ABS(x - y) * EXP(y/3)/(1/3 + cos(x/y))

x \ y

1.10

1.15

1.20

...

1.50

 

 

 

 

 

 

1.00

z1,1

z1,2

z1,3

...

z1,9

1.50

z2,1

z2,2

z2,3

...

z2,9

...

 

 

 

 

 

 

 

 

 

 

 

5.00

z11,1

z11,2

z11,3

...

z11,9

Рис. 9.1. Проект таблицы вывода (выходная форма)

298

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

Ясно, что для организации такой таблицы потребуется выполнить некоторые преобразования: смещение позиции вывода, форматирование вывода значений x, y и z, вывод символьных данных.

Для вывода нам дополнительно надо знать:

допустимое число выводимых на одной строке символов (в случае консоль-проекта это число равно 80);

диапазон изменения значений функции z;

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

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

Рассмотрим подробно механизм формирования формата вывода одной строки таблицы. Положим, что максимальное и минимальное значения z могут быть размещены на поле длиной в 7 символов, причем два правых символа поля будут расположены после десятичной точки. Такое поле задается преобразованием F7.2. Расстояние между полями вывода z положим равным единице. Тогда при выводе одного поля следует использовать формат 1X, F7.2. Всего в одной строке таблицы будет размещено 9 полей со значениями z. Для их вывода необходим формат 9(1X, F7.2). Теперь предусмотрим при выводе строки значений z отступ от левой границы экрана в 1 символ и последующий вывод значения x в поле длиной в 5 символов, содержащее два десятичных знака. Получаем формат вывода строки таблицы: (2X, F5.2, 9(1X, F7.2)).

program zxy

real :: x, y, xa = 1.0, xb = 5.0, ya = 1.1, yb = 1.51

real :: z(10)

! Массив значений z для строки таблицы

real :: dx = 0.5, dy = 0.05

! Шаг изменения x и y

character(80) :: title = 'Зависимость z = ABS(x - y) * EXP(y/3)/(1/3 + cos(x/y))'

integer(1) k, tab

 

tab = (80 - len_trim(title)) / 2

 

write(*, '(<tab>x, a)') title

! Вывод заголовка по центру экрана

write(*, 1) ('_', k = 1, 80)

! Вывод горизонтальной линии

write(*, '(2x, a, 9f8.2)') 'x \ y', (y, y = ya, yb, dy)

write(*, 1) ('_', k = 1, 80)

! Вновь выводим горизонтальную линию

x = xa

 

do while(x <= xb)

 

k = 0

 

y = ya

! Формирование массива значений z

do while(y <= yb)

k = k + 1

z(k) = abs(x - y) * exp(y / 3.0) / (1.0/3.0 + cos(x / y)) y = y + dy

299