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

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

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

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

Добавлен: 06.12.2023

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

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

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

8.2.6
Формат ввода-вывода данных символьного типа
1. Для форматного ввода-вывода символьных данных используем де- скриптор A или Aw (w — ширина поля).
2. A определяет w по фактической длине элемента ввода-вывода.
3. Aw определяет ширину поля ввода-вывода лишь w символами.
4. Если w > длины данного, то считываются все символы из правых позиций; а при выводе место слева дополняется пробелами.
5. Если w < длины символьного данного, то при вводе считывается w левых символов (оставшееся поле данного заполняется пробелами),
а при выводе выводится лишь w левых символов.
program frm10; implicit none; character(11)
b read(*,’(a)’) b
; write(*,*) ’ввод по формату a: b=’,b,b read(*,’(a15)’) b; write(*,*) ’ввод по формату a15: b=’,b,b read(*,’(a11)’) b; write(*,*) ’ввод по формату a11: b=’,b,b read(*,’(a6)’)
b; write(*,*) ’ввод по формату a6: b=’,b,b write(*,*) ’ASCII-code пробела в b(7:7)=’,iachar(b(7:7))
write(*,’("вывод по формату a: b=",a,a)’) b, b write(*,*) ’ASCII-code пробела в b(11:11)=’,iachar(b(11:11))
write(*,’("вывод по формату a15: b=",a15,a15)’) b, b write(*,*) ’ASCII-code символа b(1:1)=’,iachar(b(1:1)),’ Это буква ’,b(1:1)
write(*,’("вывод по формату a11: b=",a11,a11)’) b, b write(*,’("вывод по формату a6: b=", a6, a6)’) b, b write(*,’("вывод по формату a4: b=", a4, a4)’) b, b end astronomy
Файл frm10.inp.
astronomy
Текст "Файл frm10.inp" можно помещать в первую строку, т.к.
astronomy формат A действует лишь на все элемены переменной b, а их astronomy только 11.
ввод по формату a: b=astronomy astronomy
|
Вывод программы frm10:
ввод по формату a15: b=onomy onomy
|
ввод по формату a11: b=astronomy astronomy
|
ввод по формату a6: b=astron astron
|
ASCII-code пробела в b(7:7)=
32
|
вывод по формату a: b=astron astron
|
ASCII-code пробела в b(11:11)=
32
|
вывод по формату a15: b=
astron astron
<--= Здесь b(1:1)=’a’.
ASCII-code символа b(1:1)=
97
Это буква a |
Пробелы добавлены вывод по формату a11: b=astron astron
|
не в b,
вывод по формату a6: b=astronastron
|
а в поле вывода.
вывод по формату a4: b=astrastr
286

8.2.7
G — дескриптор для данных любого встроенного типа
Дескриптор Gw.d[Ex] работает с данными любого встроенного типа:
program frm20; implicit none;
integer :: k=375
complex :: z=(1.2,3.4);
real(4) :: a=-1.234567, p=1.991e33
real(8) :: b=1.2345678901234567_8; real(8) :: c=1.2345678901234567
logical :: t=.true.
character(45) :: s=’Это длинная строка выводится по формату g25.0’
read(*,*); ! пропуск строки с номерами позиций write(*,’(" Вывод по ")’); write(*,’("
g5.0 integer k= ",g5.0)’ ) k write(*,’("
g13.7 real(4)
a= ",g12.7)’) a write(*,’("
g13.7 real(4)
a= ",g13.7)’) a write(*,’("
g15.7 real(4)
p= ",g15.7)’) p write(*,’("
g25.16 real(8)
b=",d25.16)’) b write(*,’("
g25.16 real(8)
c=",d25.16)’) c write(*,’("
g15.7 complex z=", g15.7)’) z write(*,’("
g1.0 logical t=",g1.0,"
.not.t=",g1.0)’) t, .not. t write(*,’(g45.0)’) s;
write(*,’(" Ввод по ")’)
read(*,100) k; write(*,’(5x," g5.0 : данное в первых 5 позициях k=",g5.0)’) k read(*,100) k; write(*,’(11x,": данное в первых 5 позициях k=",g5.0)’) k read(*,100) k; write(*,’(11x,": данное в первых 5 позициях k=",g5.0)’) k read(*,100) k; write(*,’(11x,": мл. цифра
ВНЕ поля ввода k=",g5.0)’) k read(*,100) k; write(*,’(11x,": две цифры
ВНЕ поля ввода k=",g5.0)’) k read(*,100) k; write(*,’(11x,": три цифры
ВНЕ поля ввода k=",g5.0)’) k read(*,101) a; write(*,’(5x," g9.6 : по g9.6 1.3
можно ввести,"$)’)
write(*,’(" НО НЕ ВЫВЕСТИ a=",g9.6)’) a read(*,101) a; write(*,’(11x,":",32x," и по g10.6
a=",g10.6)’) a read(*,101) a write(*,’(11x,":",4x," 1.3
можно ВЫВЕСТИ,
начиная с g11.6
a=",g11.6)’) a read(*,101) a; write(*,’(5x," g9.6 :-1.234e+33 можно ВЫВЕСТИ, "$)’)
write(*,’(" начиная с g12.6
a=",g12.6)’) a write(*,’(5x," g9.6 :-1.234e+33",18x," ВЫВОД по g13.6
a=",g13.6)’) a read(*,101) b write(*,’(5x," g9.6 : 1.234+33
ВЫВОД по g25.16
real(8)
b=",g25.16)’) b read(*,101) c write(*,’(5x," g9.6 : 1.234+33
ВЫВОД по g25.16
real(8)
c=",g25.16)’) c read(*,101) z write(*,’(5x," g9.6 : ВЫВОД по g15.7 complex z=",g15.7,g15.7)’) z read(*,100) t write(*,’(5x," g9.6 :logical t=",g1.0,"
.not.t=",g1.0)’) t, .not. t read(*,102) s; write(*,’(5x," g45.0: Так оно выведется по g45.0",&
& /11x,": s=",g45.0)’) s; write(*,’(5x,"
: Так по g50.0 s=",g50.0)’) s write(*,’(5x,"
: Так по g25.0 s=",g25.0)’) s
100 format(g5.0)
101 format(g9.6)
102 format(g45.0)
end
287


1234567890<--=номера позиций
!
Содержимое файла frm20.inp
376
:
376 в позициях 123
! Программа осуществляет ввод
376
:
376 в позициях 234
! через операцию перенаправления
376
:
376 в позициях 345
! стандартного ввода.
376
:
376 в позициях 456 376
:
376 в позициях 567 376 :
376 в позициях 678 1.3
:
Наличие точки в пределах поля ввода позволяет программе
1.3
:
выяснить значение данного независимо от дескриптора формата
1.3
:
(лишь бы ширина его поля была достаточна)
-1.234+33:
1.234+33 :
1.234e+33:
3.7
:
Re(z)
5.2
:
Im(z)
t
Это строковое данное введено по формату g45.0.
Вывод по
!
Результат работы g5.0 integer k=
375
!
программы frm20
g13.7 real(4)
a= ********
!
g13.7 real(4)
a= -1.234567
g15.7 real(4)
p=
0.1991000E+34
g25.16 real(8)
b=
0.1234567890123457D+01
g25.16 real(8)
c=
0.1234567880630493D+01
g15.7 complex z=
1.200000
g15.7 complex z=
3.400000
g1.0 logical t=T
.not.t=F
Это длинная строка выводится по формату g25.0
Ввод по g5.0 : данное в первых 5 позициях k=
376
: данное в первых 5 позициях k=
376
: данное в первых 5 позициях k=
376
: мл. цифра
ВНЕ поля ввода k=
37
: две цифры
ВНЕ поля ввода k=
3
: три цифры
ВНЕ поля ввода k=
0
g9.6 : по g9.6 1.3
можно ввести, НО НЕ ВЫВЕСТИ a=*****
:
и по g10.6
a=******
:
1.3
можно ВЫВЕСТИ,
начиная с g11.6
a=1.30000
g9.6 :-1.234e+33 можно ВЫВЕСТИ,
начиная с g12.6
a=-.123400E+34
g9.6 :-1.234e+33
ВЫВОД по g13.6
a=-0.123400E+34
g9.6 : 1.234+33
ВЫВОД по g25.16
real(8)
b=
0.1234000000000000E+34
g9.6 : 1.234+33
ВЫВОД по g25.16
real(8)
c=
0.1234000000000000E+34
g9.6 : ВЫВОД по g15.7 complex z=
3.700000 5.200000
g9.6 :logical t=T
.not.t=F
g45.0: Так оно выведется по g45.0
: s=Это строковое данное введено по формату g45.0
: Так по g50.0 s=
Это строковое данное введено по формату g45.0
: Так по g25.0 s=Это строковое данное введ
288

8.2.8
Формат ввода-вывода данных производного типа
Для форматного ввода-вывода производного типа можно использовать подходящую последовательность дескрипторов, каждый из которых на- целен на обработку соответствующего поля производного типа.
Пусть, например, программа использует производный тип star, поля- ми которого служат номер звезды (поле num), её имя (поле nam, прямое восхождение (поле ra) и склонение (поле dec):
program frm11
implicit none type star integer num character (len=20) nam real ra, dec end type star type (star) a read (*,’(i5,a20,f6.2,f6.2)’) a%num, a%nam, a%ra, a%dec write(*,1000) a%num, a%nam, a%ra, a%dec
1000 format(i5,a20,e15.7,e15.7)
end
333
name_mystar 3.141 0.75
Файл frm11.inp.
Вывод программы frm11 333
name_mystar
0.3141000E+01 0.7500000E+00
Вообще говоря, придумывание производных типов требует глубокого понимания сути задачи: грамотно придуманный производный тип сильно упрощает написание, отладку и эксплуатацию программы. Поэтому, как правило, не стоит в теле основной программы работать непосредственно с конкретными полями структуры.
Выгоднее создать и вызывать соответствующие процедуры, на вход к которым подаётся просто имя структурной переменной или ссылка на неё, поручая этим процедурам обработку соответствующих задаче полей.
В частности, это относится и к процедурам ввода и вывода.
Использование отдельных полей производного типа в главной про- грамме объективно можно оправдать лишь отладочным характером ра- боты с ней или же какой-то сиюминутной выгодой, которая в конечном итоге должна быть спрятана в соответствующей процедуре или модуле.
289


8.3
Управляющие дескрипторы
Дескриптор
Назначение (кратко)
BN, BZ
Интерперетация пробелов
S, SP, SS
Управление выводом знака
T, TL, TR, X
Управление табуляцией
/ (косая черта)
Завершение передачи данных в текущую запись
: ( двоеточие )
Прерывание управления форматом вывода
P
Масштабный множитель
8.3.1
BN и BZ — управление интерпретацией пробелов
BN (blank null) и BZ (blank zero) указывают, что пробелы поля ввода
(кроме начального)
1. BN — игнорируются.
2. BZ — интерперетируются как нули.
3. При вводе BN и BZ влияют только лишь на дескрипторы числовых данных.
4. При выводе BN и BZ игнорируются.
5. BN и BZ действуют до конца списка дескрипторов формата или пока не встретится другой дескриптор BN или BZ
program frm13
integer k, l, m, n read (*, 100) k,l,m,n; 100 format(
i5,i5,i5,i5); write(*,1100) k,l,m,n read (*, 101) k,l,m,n; 101 format(bz,i5,i5,i5,i5); write(*,1100) k,l,m,n read (*, 102) k,l,m,n; 102 format(bn,i5,i5,i5,i5); write(*,1100) k,l,m,n read (*, 103) k,l,m,n;
103 format(bn,i5,bz,i5,i5,i5); write(*,1100) k,l,m,n
1100 format(4i5)
end
12 13 14 15
Файл ввода frm12.inp
12 13 14 15 12 13 14 15 12 13 14 15
Вывод программы frm12 12 13 14 15 12000 130 1400 15 12 13 14 15 12 130 1400 15 290

8.3.2
S, SP, SS —управление выводом знака
1. При вводе S, SP, SS игнорируются.
2. При выводе S, SP, SS влияют только на дескрипторы числовых данных.
3. S, SP, SS действуют до конца списка дескрипторов формата или пока не встретится снова S, SP или SS.
4. SP указывает, что знак “+” следует выводить всюду, где возможно.
5. SS указывает, что знак “+” следует везде опускать.
6. S установка принятого в реализации режима вывода знака “+”.
7. Отрицательные числа всегда выводятся со знаком.
Например,
program frm13
implicit none integer, parameter :: k=5, m=-7
real, parameter :: a=3.14, b=-7.28
write(*,’(" k=",i3," m=",i3," a=",f7.3," b=",e15.7 )’) k,m,a,b write(*,’(sp," k=",i3," m=",i3," a=",f7.3," b=",e15.7 )’) k,m,a,b write(*,’(ss," k=",i3," m=",i3," a=",f7.3," b=",e15.7 )’) k,m,a,b write(*,’(sp," k=",i3," m=",i3," a=",f7.3," b=",e15.7 )’) k,m,a,b write(*,’(s," k=",i3," m=",i3," a=",f7.3," b=",e15.7 )’) k,m,a,b end
Вывод программы frm13
k=
5 m= -7 a=
3.140 b= -0.7280000E+01
k= +5 m= -7 a= +3.140 b= -0.7280000E+01
k=
5 m= -7 a=
3.140 b= -0.7280000E+01
k= +5 m= -7 a= +3.140 b= -0.7280000E+01
k=
5 m= -7 a=
3.140 b= -0.7280000E+01 291

8.3.3
Tn, TRn, TLn и nX —управление табуляцией
Табуляция — задание позиции в записи
Целая константа без знака n в
1. Tn задаёт номер позиции, с которой надо начать передачу данных.
2. TLn задаёт на сколько позиций влево следует сместить текущую позицию во внешней записи.
3. Позиция левой границы записи полагается равной единице.
4. TRn задаёт на сколько позиций вправо следует сместить текущую позицию во внешней записи.
5. nX обычно используется для вставки пробелов в выводимую запись или указания количества позиций, которые надо пропустить до на- чала данного для очередного числового дескриптора. Эквивалентно
TRn.
6. Ценность дескрипторов управления табуляцией в том, что они поз- воляют после ввода отдельных частей записи осуществить повтор- ную их обработку причём возможно с другим дескриптором.
Например,
program frm14
implicit none integer k,m,n character(4) sk, sm, sn real(4)
rk, rm, rn, rr read(*,100) k,m,n, sk,sm,sn, rk,rm,rn, rr write(*,’("
k=",i3,"
m=",i3,"
n=",i3)’) k,m,n write(*,’(" sk=",a4," sm=",a4," sn=",a4)’) sk(1:4), sm(2:4), sn(3:4)
write(*,’(" rk=",e15.7,"
rm=",e15.7,"
rn="e15.7)’) rk, rm, rn write(*,’(" rr=",e10.3)’) rr
100 format(3(i4,6x),T7,3(a4,6x),T1,3E10.1,TL7,f3.1)
end
123.4e+05 678.9e-08 987.5e+11
Файл ввода frm14.inp
Вывод программы frm14
k=123
m=678
n=987
sk=e+05 sm= -08 sn=
11
rk=
0.1234000E+08
rm=
0.6789000E-05
rn=
0.9875000E+14
rr= 0.750E+01 292


8.3.4
Дескриптор “дробная черта”
Дескриптор “/” означает конец передачи в текущую запись или из неё.
Варианты использования:
1. При выводе в файл последовательного доступа (пока мы только с такими файлами и имели дело) создаётся новая пустая запись,
которая становится текущей, и пишущий элемент устанавливается на её начало (по сути дела это — просто перевод строки).
2. При вводе из файла последовательного доступа остаток теку- щей записи пропускается и читающий элемент устанавливается на начало следующей записи, которая становится текущей.
3. При работе с файлом прямого доступа (познакомимся позже) но- мер записи увеличивается на единицу и читающий (или пишущий)
элемент устанавливается в начало записи с полученным номером.
4. Дескриптор “/” можно повторить несколько раз ////, что приведёт к появлению в файле вывода последовательного доступа четы- рёх пустых строк. Того же можно достичь, используя повторитель
4/, правда, такое сочетание придётся выделять запятыми.
program frm15
implicit none integer a(15), i open (5,file=’frm15.inp’)
read (5,101) a write(*,101) a
101 format( 4i3 / 5i3 / 2i3/4i3)
end
1 2
3 4
5 6
7 8
9 10 11 12 13 14 15
! Содержимое файла ввода
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 1
2 3
4
! Результат работы программы frm15:
21 22 23 24 25 41 42 61 62 63 64
Обратить внимание, что корректный ввод и вывод возможен лишь в случае, когда сумма повторителей перед дескритпором формата равна заявленному числу элементов массива (ведь по имени массива формаль- но выводится заявленное число его элементов).
293

8.3.5
Дескриптор “ $”
Дескриптор “$” — признак продолжения текущей записи. Позволяет:
1. после вывода приглашения ко вводу набрать данное в строке при- глашения.
2. добавить в хвост строки вывода предыдущего данного очередное если по каким-то причинам для этого неудобно использовать один оператор общего вывода.
program frm16; implicit none real p, q write(*,100); read(*,*) p; write(*,’(" p=",e15.7)’) p write(*,101); read(*,*) q; write(*,’(" q=",e15.7)’) q write(*,’(" p=",f7.3,$)’) p write(*,’(" q=",f7.3)’) q
100 format(’input parameter:’); 101 format(’input parameter:’,$)
end
3.2 7.5
input parameter:
!
Результат работы программы frm16:
p=
0.3200000E+01
input parameter:q=
0.7500000E+01
p=
3.200 q=
7.500
В некоторых реализация ФОРТРАНа-95 наряду с $ c той же целью может использоваться дескриптор обратный слеш.
8.3.6
Дескриптор “:”
Дескриптор “:” — при исчерпании списка вывода прерывает управление форматом
Дескриптор “:” игнорируется в случае ввода или при наличии в списке вывода элементов.
program frm17; implicit none; real ::
p=3.2, q=7.5
write(*,100) p, q write(*,100) p
100 format(1x,’ p=’, f10.3,: 2x,’ q=’,e10.3)
end
Вывод программы frm17
p=
3.200
q= 0.750E+01
p=
3.200 294


8.3.7
Дескриптор kP (масштабный множитель)
Буква k в синтаксической конструкции kP — константа, обозначающая показатель степени десятки, а P — символическое имя конструкции, ука- зывающее её назначение (power — показатель степени).
Дескриптор kP устанавливает значение масштабного множителя 10
k
,
(часто само k называют масштабным множителем) используя который вместо истинного значения некоторой величины (обозначим её, напри- мер, A) можно вывести или ввести значение A · 10
−k
, что иногда удобно.
Например, вывести значения 9.283 · 10
−28
и 1.991 · 10
+28
в форме
F (с фиксированной запятой) можно, но вряд ли это выгодно. Более практичны в данном случае формы E (или D) или даже ES.
Однако, если на выводе потребуется обширная таблица подобных ве- личин, то запись порядка каждого её числа в виде E-28 или E+33 зай- мёт почти столько же места сколько значащие цифры, что неудобно.
Для повышения наглядности числа можно домножить на некоторый масштабный множитель (например, на 10 28
или 10
−28
— увеличить или уменьшить масштаб чисел) и вывести их по дескриптору F c небольшим количеством значащих цифр Цена за полученную наглядность — заме- чание к таблице о том, что порядок приведённых значений отличается от истинного на величину порядка масштабного множителя.
Полезно знать, что сочетание управляющего дескриптора kP (мас- штабного множителя) с дескрипторами F и E приводит к принципиаль- но разным результатам. Однако, прежде чем сформулировать оконча- тельные рекомендации, полезно пропустить программу frm18. Её тело состоит из вызова трёх процедур: tstPout1, tstPout2 и tstPinp, ко- торые дают возможность посмотреть на результаты работы сочетания дескрипторов kP, F и E на примерах:
1. вывода чисел 0.9234 · 10
−27
и 0.1991 · 10 29
(процедура tstPout1).
2. вывода числа 1.234 (процедура tstPout2).
3. ВВОДА числа 5.678 (процедура tstPinp).
4. С целью удобства сопоставления исходных текстов подпрограмм и соответствующих результатов последние помещены непосредствен- но под исходным текстом
295
program frm18
implicit none call tstPout1
call tstPout2
call tstPinp end subroutine tstPout1; implicit none; real(8) :: a=9.234d-28, s=1.991d+28
write(*,’(78("=")/T33,a/)’) ’ Работа tstPout1:’
write(*,’(" a=",f33.30$)’) a;
write(*,’(5x,"Вывод по F33.30")’);
write(*,’(" s=",f33.0$)’) s;
write(*,’(5x,"Вывод по F33.0"/)’);
write(*,’("Вывод
E11.4",9x,"D11.4",10x,"EN15.7",13x,"ES15.7")’)
write(*,’("
a:",2x,E11.4,3x,d11.4,3x, en15.7,3x,es15.7)’) a,a,a,a write(*,’("
s:",2x,E11.4,3x,d11.4,3x, en15.7,3x,es15.7/)’) s,s,s,s write(*,’("Вывод по
28P,F11.4
a:", 28P,F11.4)’) a write(*,’("Вывод по
-28P,F11.4
s:",-28P,F11.4)’) s write(*,’(28x,"a",12x,"s")’);
write(*,’("Вывод по
-1P,e15.7",-1P,e15.7,e15.7)’) a,s write(*,’("Вывод по
-2P,e15.7",-2P,e15.7,e15.7)’) a,s write(*,’("Вывод по
-3P,e15.7",-3p,e15.7,e15.7)’) a,s write(*,’("Вывод по
-4P,e15.7",-4p,e15.7,e15.7/)’) a,s write(*,’("Вывод по
1P,e15.7", 1P,e15.7,e15.7)’) a,s write(*,’("Вывод по
2P,e15.7", 2P,e15.7,e15.7)’) a,s write(*,’("Вывод по
3P,e15.7", 3p,e15.7,e15.7)’) a,s write(*,’("Вывод по
4P,e15.7", 4p,e15.7,e15.7)’) a,s end;
====================================================================
Работа tstPout1:
a= 0.000000000000000000000000000923
Вывод по F33.30
s=
19909999999999998662017000000.
Вывод по F33.0
Вывод
E11.4
D11.4
EN15.7
ES15.7
a:
0.9234E-27 0.9234D-27 923.4000000E-30 9.2340000E-28
s:
0.1991E+29 0.1991D+29 19.9100000E+27 1.9910000E+28
Вывод по
28P,F11.4
a:
9.2340
Вывод по
-28P,F11.4
s:
1.9910
a s
Вывод по
-1P,e15.7 0.0923400E-26 0.0199100E+30
Вывод по
-2P,e15.7 0.0092340E-25 0.0019910E+31
Вывод по
-3P,e15.7 0.0009234E-24 0.0001991E+32
Вывод по
-4P,e15.7 0.0000923E-23 0.0000199E+33
Вывод по
1P,e15.7 9.2340000E-28 1.9910000E+28
Вывод по
2P,e15.7 92.340000E-29 19.910000E+27
Вывод по
3P,e15.7 923.40000E-30 199.10000E+26
Вывод по
4P,e15.7 9234.0000E-31 1991.0000E+25 296