Файл: А. Б. Шнейвайс основы программирования.pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 06.12.2023

Просмотров: 340

Скачиваний: 6

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

4. Дескриптор a используется для преобразования символьных дан- ных. В данном случае одна буква a означает преобразование кодов всех символов, образующих строковое значение из списка вывода,
в сами символы (т.е. всех символов строковой константы ’ n=’, за- ключенных между апострофами).
5. Дескриптор i2 (в write) используется для указания преобразования внутреннего двоичного представления целочисленного значения (в данном случае переменной n) в десятичное двузначное целое.
6. Дескрипторы l1,3x,l1 указывает оператору write вывести два бу- лева значения, разделённые тремя пробелами, и отводя под каждое только одно знакоместо.
7. Форматы 1x,5x,a,3a4 обеспечат вывод с седьмой позиции значения строковой константы ’ abc=’ и трёх элементов символьного масси- ва, под каждый из которых хотим отвести четыре знакоместа.
8. Дескриптор f5.2 при выводе вещественного значения переведёт в общепринятую запись числа, занимающую пять позиций с двумя десятичными цифрами после запятой.
9. Дескриптор e9.2 (при выводе) запишет вещественное значение в форме с плавающей запятой (девять позиций на всю запись, с дву- значной десятичной мантиссой и порядком числа).
10. Пример вывода через явное посредство оператора format с тем же результатом дан программой frm3:
program frm3; implicit none; integer n / 10 /
real x / 1.7 /, em /9e-28/, sunm / -1.991e+33 /
logical b(2) /.true., .false. /
character(1) abc(3) /’a’,’b’,’c’/; integer matr(2,3) / 1, 2, 3, 4, 5, 6 /
write(*,100) ’
n=’, n write(*,200) ’
b=’, b; write(*,300) ’
abc=’, abc write(*,400) ’
x=’, x; write(*,500) ’
em=’, em write(*,600) ’ sunm=’, sunm
! Целое число перед write(*,700) ’ matr=’, matr
! словом format -
100 format(1x,5x,a,i2)
! метка, ссылаясь на
200 format(1x,5x,a,l1,3x,l1); 300 format(1x,5x,a,3a4)
! которую, read или
400 format(1x,19x,a,f5.2);
500 format(1x,5x,a,e9.2) ! write "узнают" о
600 format(1x,5x,a,e10.3);
700 format(1x,5x,a,6i2)
! нужных правилах end
! форматирования
276

8.2
Способы явного задания формата
Явно указать формат ввода-вывода можно одним из двух способов:
• непосредственно в операторе ввода-вывода в виде константы или выражения символьного типа, что удобно при краткости их записи.
• в операторе format, указываемом оператору ввода-вывода посред- ством метки, что удобно, если запись формата громоздка, так как.
оператор format можно расположить в любом месте программы, не загромождая подробностями форматирования её проблемную часть.
Наиболее удобен оператор format, когда его используют несколько операторов ввода-вывода.
Спецификатор формата — выражение в скобках оператора format.
Спецификатор формата состоит из списка дескрипторов:
метка format( список_дескрипторов )
Дескриптор – указывает правило, по которому данное преобразует- ся при вводе-выводе, и записывается символами служебного алфавита оператора format. Имеется три вида дескрипторов.
1. Дескрипторы преобразования данных:
Имя дескриптора
Тип данного
Примечание
I, B, O, Z
целый можно
F,E, EN, ES, D
вещественный использовать
L
логический и заглавные,
A
символьный и строчные
G
любой буквы
2.
Управляющие дескрипторы: T, TL, TR, X, S, SP, SS, BN, BZ,P
3. Дескриптор в виде символьной строки удобен, когда нет необ- ходимости под выводимый текст выделять дополнительную пере- менную. Например,
program frm4; implicit none write(*,1001); 1001 format(’ Так можно вывыести двойную кавычку ".’)
write(*,1002); 1002 format(’ Так можно вывыести апостроф ’’
.’)
write(*,1003); 1003 format(" Так тоже можно вывыести апостроф ’
.")
write(*,1004); 1004 format(’ В старых версиях ФОРТРАНа нельзя было’/&
&" качестве апострофа использовать двойную кавычку")
end
277


8.2.1
Форматы данных целого типа
Основные дескрипторы
Iw и Iw.d
Дополнительные
Bw, Bw.d, Ow, Ow.d, Zw, Zw.d,
1. Здесь w — количество позиций, отводимое для размещения данного целого типа, т.е. число знакомест под данное, включая и знак числа.
2. Предполагается, что данное при чтении или записи должно быть выравнено по правой границе предоставляемого ему поля.
3. Если число цифр меньше w, то в левые позиции пишутся пробелы.
4. Если же запись числа требует больше позиций чем предоставлено шириной поля, то всё поле заполняется значком *.
5. Iw.d позволяет наряду с w задать и d — минимальное число цифр,
которые надо вывести, заполняя пустые старшие позиции поля дан- ного незначащими нулями, что удобно при необходимости. При вво- де Iw.d эквивалентено Iw и значение d игнорируется.
6. Дескрипторы B, O и Z задают форму представления данного в двоичной, восьмеричной и шестнадцатеричной системах счисления
(трактовка w и d — та же).
program frm5; implicit none; integer, parameter :: j=5, m=1024,n=-1024
write(*,’(" j=",i2," j=",i3," j=",i4)’) -j, -j, -j write(*,’(" m=",i3)’) m write(*,’(" m10=",i4," m2=",b11," m8=",O4," m16=",z4)’) m, m, m, m write(*,’(" n10=",i5," n2=",b32," n8=",O11," n16=",z8)’) n, n, n, n write(*,’(" n=",i4," n=",i5)’) n, n write(*,’(" m=",i5.2)’) m write(*,’(" n=",i7.6)’) n write(*,’(" n=",i10.6)’) n end j=-5 j= -5 j=
-5
m=***
m10=1024 m2=10000000000 m8=2000 m16= 400
n10=-1024 n2=11111111111111111111110000000000 n8=37777776000 n16=FFFFFC00
n=**** n=-1024
m= 1024
n=-001024
n=
-001024 278

8.2.2
Форматы данных вещественного типа
Дескриптор преобразования real-числа без порядка
Fw.d
Дескрипторы преобразования real-числа с порядком
Ew.d, Dw.d,
Ew.dEe, ENw.d, ESw.d
1. Здесь w — ширина поля; d — число цифр после десятичной точки.
2. Дескриптор F позволяет представить данное вещественного типа в обычном виде: целая часть числа, точка, дробная часть числа.
3. Дескрипторы E и D позволяют преобразовывать данные, в записи которых указан порядок числа. До ФОРТРАНа-90 E предназнача- лось для для преобразования данных типа real(4), а D — real(8).
Это их назначение сохраняется. Однако, современный ФОРТРАН
обслуживает данные типа real(8) и через дескриптор E, так что дескриптор D в значительной мере становится архаичным.
4. Внимание! Есть принципиальное различие между дескриптором D
и использованием литеры D при указании порядка числа в тексте программы. В случае дескриптора допускается замена литеры D на литеру E, но в случае записи числовой константы в исходном тексте подобная замена недопустима, т.к. литера E однозначно укажет на одинарную точность, а D — на удвоенную. Правда, в современном
ФОРТРАНе можно записать число удвоенной точности и с исполь- зованием литеры E, поместив после записи порядка символы _8,
указывающие количество байт, отводимых под константу.
5. Дескриптор Ew.dEx позволяет указать через константу x после второй буквы E количество позиций для записи порядка числа.
6. Дескриптор EN в отличие E при выводе приводит число к диапа- зону [1,1000) (кроме нуля), а десятичный порядок данного делает кратным 3 (ENgineering — инженерный формат).
7. Дескриптор ES в отличие E при выводе приводит число к диапазону
[1,10) (исключая нуль), и подстраивает соответственно десятичный порядок (Scientific — научный формат).
Ниже приведена программа frm6, демонстрирующая вышесказанное о дескрипторах вывода вещественных чисел:
279

program frm6; implicit none real(4), parameter :: a=-1.23456789, b=1.234567e+33
real(8), parameter :: c=-1.2345678901234567d-28
real(8) p , q character(66) :: text(16)=(/’ Нет места для знака числа’,’ Теперь есть’,&
&’ Младшая цифра в 12-ой позиции после знака =’,’ 7 позиций мало’,&
&’ Две цифры с порядком после точки.’,’ То же можно и так’,&
&’ 7 цифр с порядком после точки.’,’ Под порядок четыре цифры’,&
&’ Раньше лишь литера D задавала формат удвоенной точности’,&
&’ Теперь можно использовать и E’,’ Верны старшие 7-8 цифр’,’ Верны 16 цифр’,&
&’
EN-вывод в диапазоне [1,1000) и’,’
порядком кратным 3’,&
&’
E-вывод (сравнить с EN и последующим ES)’,’
ES-вывод в диапазоне [1,10)’/)
write(*,’(" a=",f4.3,12x,a)’) a,text(1) ! Нет места для знака числа !
write(*,’(" a=",f6.3,10x,a)’) a,text(2) ! Теперь есть write(*,’(" a=",f12.7,4x,a)’) a,text(3) ! Мл. цифра в 12-ой позиции после =
write(*,’(" b=",f7.3,9x, a)’) b,text(4) ! В 7 позиций мало для числа с порядком write(*,105) " b=",b, text(5)
! Две цифры с порядком после запятой write(*,106)
b, text(6)
! То же можно и так write(*,107)
b, text(7)
! 7 цифр с порядком после запятой write(*,108)
b, text(8)
! Под порядок четыре цифры write(*,109)
c, text(9)
! Раньше формат удвоенной точности указывался D
write(*,110)
c, text(10)
! В современном можно и E
p=1.234567890123456789e7
! E и D в константах - не дескрипторы q=1.234567890123456789d7
! а определяют тип константы:
write(*,111)
p, text(11)
! верны только старшие семь цифр write(*,112)
q, text(12)
! верны старшие 16
write(*,113)
p, text(13)
! EN-нормализация к диапазону [1,1000) и write(*,114)
c, text(14)
!
порядку кратному 3 (инженерная нотация)
write(*,115)
c, text(15)
! E-вывод (сравните с предыдущим и последующим)
write(*,116)
c, text(16)
! ES-нормализация к диапазону [1,10)
105 format(1x,a,e9.2,6x,a);
106 format(1x," b=",e9.2,6x,a);
107 format(1x," b=",e15.7,a);
108 format(1x," b=",e15.7e4,a)
109 format(1x," c=",d9.2,16x,a);
110 format(1x," c=",e25.16,a)
111 format(1x," p=",e25.16,a);
112 format(1x," q=",e25.16,a)
113 format(1x," q=",en12.2,12x,a); 114 format(1x," c=",en25.16,1x,a)
115 format(1x," c=",e25.16,a);
116 format(1x," c=",es25.16,a)
end
Заметим, что приведённый исходный текст frm6 набирался при ис- пользовании однобайтовой кодировки koi8r. В случае кодировки utf8
при пропуске иногда возникают проблемы (в особенности при использо- вании кириллицы). Именно, по умолчанию (в режиме свободного форма- та записи исходного текста) компилятор обычно отводит строку длиной
130 символов. Кодировка же кириллицы в utf8 — двухбайтовая, так что
(как только размер исходного текста в одной строке потребует более 130
символов) последует сообщение об ошибке. Исправить ситуацию можно
280
переустановив при запуске компилятора новый предел длины строки,
например, посредством опции -ffree-line-length-500 (или -ffree-line- length-0, или -ffree-line-length-none; см. Приложение VII).
Результаты работы frm6.
a=****
Нет места для знака числа a=-1.235
Теперь есть a=
-1.2345679
Младшая цифра в 12-ой позиции после знака =
b=*******
7 позиций мало b= 0.12E+34
Две цифры с порядком после точки.
b= 0.12E+34
То же можно и так b=
0.1234567E+34 7 цифр с порядком после точки.
b=0.1234567E+0034 Под порядок четыре цифры c=-0.12D-27
Раньше лишь литера D задавала формат удвоенной точности c=
-0.1234567890123457E-27 Теперь можно использовать и E
p=
0.1234567900000000E+08 Верны старшие 7-8 цифр q=
0.1234567890123457E+08 Верны 16 цифр q=
12.35E+06
EN-вывод в диапазоне [1,1000) и c=-123.4567890123456748E-30
порядком кратным 3
c=
-0.1234567890123457E-27
E-вывод (сравнить с EN и последующим ES)
c=
-1.2345678901234567E-28
ES-вывод в диапазоне [1,10)
281


8.2.3
Форматы ввода данных вещественного типа
Ввод осуществляется только из поля указанного дескриптором. Поэтому в остальной части строки можно поместить комментарий, напоминаю- щий о проблемном назначении вводимого параметра. Например, пусть главная программа должна вводить:
1. a и b — абсциссы концов отрезка, на котором ищется корень урав- нения f(x)=0 методом деления отрезка пополам;
2. epsx и epsy — абсолютные погрешности поиска корня по абсциссе и ординате (т.е. считаем, что корень найден, если длина уточняю- щего отрезка после очередного сужения оказалась меньше epsx и
|f (xискомое)| < epsy).
3. p и q — некоторые дополнительные параметры, от которых помимо аргумента x зависит левая часть уравнения f (x) = exp(−px
2
)−q∗x
Разместим вводимые величины во вводимом файле frm7.inp по одной в каждой строчке в первых 15 позициях так:
-1.300+00<--= a (левая граница промежутка с корнем)
файл input
2.3
<--= b (правая граница промежутка с корнем)
1.000-05
<--= a (левая граница промежутка с корнем)
0.00001
<--= b (правая граница промежутка с корнем)
314159265
<--= p (коэффициент при показателе экспоненты)
2.71828182+00<--= q (коэффициент перед линейным слагаемым)
Тогда ввод этих исходных данных можно осуществить программой program frm7; implicit none real(8) a, b, epsx, epsy, p, q read (*,’(e15.7)’) a, b, epsx, epsy, p, q write(*,1000)
a, b, epsx, epsy, p, q
!
! Вызов функции, реализующей алгоритм метода деления пополам
!
1000 format(1x,’
a=’,e25.16/1x,’
b=’,e25.16/1x,’ epsx=’,e25.16/&
&
1x,’ epsy=’, e25.16/1x,’
p=’,e25.16/1x,’
q=’,e25.16)
end
282

Замечания:
1. Перед записью числа могут находится пробелы (лишь бы они и чис- ло не выходили за пределы ширины поля ввода).
2. Если поле ввода содержит десятичную точку, то данное в пределах ширины поля можно сдвигать как угодно: значение d (число цифр после запятой в дескриптере) игнорируется.
3. При отсутствии десятичной точки d младших цифр числа тракту- ются как его дробная часть.
4. После записи мантиссы числа может присутствовать его десятич- ный порядок в виде целой констаны со знаком перед которым может быть литера E или D.
5. Записывать вводимые параметры столь разношёрстно, как это сде- лано в frm7.inp вряд ли практично. Обычно удобна однообразная форма записи. Здесь же приведены возможности форматного ввода.
6. Иногда спрашивают: “ Почему при указании формата ввода записан один дескриптор e15.7, а список ввода состоит из нескольких переменных?” Используемый способ ценен тем, что обеспечивает чтение очередного значения из первых 15 позиций оче- редной строки файла, позволяя в оставшуюся часть предыдущей по- местить поясняющий комментарий. Как только прочитывается оче- редное число и обнаруживается, что список форматов закончился,
то следующее данное читается по прежнему формату, но из новой строки. Это — частный случай проявления более общего ФОРТРАН- правила, называемого реверсией формата (см., например, [3]).
7. Для ввода всех данных из одной строки можно, например, вос- пользоваться дескриптором ’(6(e15.7,3x))’. Здесь шестёрка перед
(e15.7,3x) — повторитель формата.
8. Широко востребовано как размещение одного числа в одной строки,
так и нескольких чисел. Например, все данные по одной звезде из каталога звёзд обычно размещаются в одной строке файла с катало- гом, а при решении расчётных задач, требующих ввода небольшого числа параметров, каждый из них удобно размещать в отдельной строке с соответствующим пояснением.
283


8.2.4
Форматы ввода-вывода данных комплексного типа
Перевод комлексных данных из внутреннего машинного двоичного пред- ставления в обычное десятичное и обратно выполняется посредством двух вещественных дескрипторов. Первый задаёт преобразование для вещественной части, второй — для мнимой (при этом первый не обязан совпадать со вторым). Например,
program frm8; implicit none; complex(8) a, b, c, v real(8) vre, vim read (*,’(d10.3,d10.3)’) a, b; write(*,*) ’ a=’,a; write(*,*) ’ b=’,b c=a+b;
write(*,*) ’ c=’,c write(*,’(" a=",f5.2,"+",f5.2,"i")’) a write(*,’(" b=",f5.2,"+",f5.2,"i")’) b write(*,’(" c=",f5.2,"+",f5.2,"i")’) c read(*,’(f10.2,d10.3)’) vre, vim write(*,*) ’ vre=’,vre,’ vim=’,vim v=dcmplx(vre , vim); write(*,’("v=dcmplx(vre , vim)=",2d25.16)’) v v= cmplx(vre,vim,4); write(*,’("v= cmplx(vre,vim,4)=",2d25.16)’) v v= cmplx(vre,vim,8); write(*,’("v= cmplx(vre,vim,8)=",2d25.16)’) v v= cmplx(vre , vim); write(*,’("v= cmplx(vre , vim)=",2d25.16)’) v end
1.5 1.6
a
Файл frm8.inp
2.3 0.3
b
3.2 7.51
vre vim a= (
1.5000000000000000
,
1.6000000000000001
)
b= (
2.2999999999999998
, 0.29999999999999999
)
c= (
3.7999999999999998
,
1.9000000000000001
)
a= 1.50+ 1.60i b= 2.30+ 0.30i c= 3.80+ 1.90i vre=
3.2000000000000002
vim=
7.5099999999999998
v=dcmplx(vre , vim)=
0.3200000000000000D+01 0.7510000000000000D+01
v= cmplx(vre,vim,4)=
0.3200000047683716D+01 0.7510000228881836D+01
v= cmplx(vre,vim,8)=
0.3200000000000000D+01 0.7510000000000000D+01
v= cmplx(vre , vim)=
0.3200000047683716D+01 0.7510000228881836D+01
Внимание! Вызов cmplx с двумя аргументами типа real(8) (но без тре- тьего, параметра разновидности результата) полагает, что погрешности округления вещественной и мнимой частей результата соответствуют ти- пу complex(4), а не complex(8), т.е. в используемой версии компилято- ра механизм перегрузки функций для cmplx не работает, или, другими словами, имя cmplx здесь специфическое, а не родовое.
284

8.2.5
Форматы ввода-вывода данных логического типа
1. Для форматного ввода-вывода логических данных используется де- скриптор Lw (w — ширина поля).
2. При выводе в самую крайнюю правую позицию выводится T или F.
3. При вводе возможны необязательные пробелы и символы T или F.
4. Дескриптор L7 допускает ввод значений .true. и .false.
program frm9; implicit none; logical p, q, true; integer i write(*,*) ’ Ввод под управлением списка ввода вводим T и F:’;
read(*,*) p, q; write(*,*) ’ p=’,p, ’
q=’,q write(*,*) ’ Ввод по дескриптору L7 из первых 7 позиций двух строк:’
do i=1,3
read(*,’(l7)’) p, q; write(*,’(a,L7,a,L7)’) ’ p=’,p, ’
q=’,q enddo write(*,*) ’ Ввод по формату (L7,3x,L7) из первых 17 позиций одной строки:’
do i=1,3
read(*,’(l7,3x,l7)’) p, q; write(*,’(a,L7,a,L7)’) ’ p=’,p, ’
q=’,q enddo end t f
Файл frm9.inp c вводимыми данными.
.TRUE.
Программа frm9 вводит его через операцию перенаправления f
стандартного ввода < frm9.inp
.FALSE.
Помещение данного текста, начиная с 18 позиции этого файла t
не мешает работе, так ввод осуществляется исключительно t
по формату (L7,3x,L7). Однако, если в последней строке f
сместить букву T на одну позицию вправо или букву F
t f на одну позицию влево, или её же в 18-ю позицию, то t
f пропуск программы выдаст сообщение t
f
At line 13 of file frm9.f95 (unit = 5, file = ’stdin’)
Fortran runtime error: Bad value on logical read
Вывод программы frm9
Ввод под управлением списка ввода вводим T и F:
p= T
q= F
Ввод по дескриптору L7 из первых 7 позиций двух строк:
p=
T
q=
F
p=
F
q=
T
p=
T
q=
F
Ввод по формату (L7,3x,L7) из первых 17 позиций одной строки:
p=
T
q=
F
p=
T
q=
F
p=
T
q=
F
285