第七章 输入输出和文件
输入输出编辑
7.1.1 输入输出语句
a) 相关语句
输入输出语句决定了作用在数据上的I/O操作。
数据传输语句有:READ,ACCEPT,WRITE,PRINT和REWRITE。文件连接、查询和定位语句有:BACKSPACE,CLOSE,DELETE,ENDFILE,INQUIRE,OPEN,REWIND和UNLOCK。下表给出了它们的简要描述。另外,内在函数EOF可以用来判断在文件当前位置之后是否还有剩余数据。
语句 | 功能 |
ACCEPT | 输入数据,和格式化顺序READ语句类似 |
BACKSPACE | 定位到文件上一个记录开始处 |
CLOSE | 断开和一个单元(文件和设备)的连接 |
DELETE | 从相关文件中删去一条记录 |
ENDFILE | 写一个文件结束记录 |
INQUIRE | 返回一个单元或外部文件的属性 |
OPEN | 使一个单元号和一个文件或设备相连接 |
向星号单元(屏幕)输出数据 | |
READ | 从一个文件向I/O列表中的项目输入数据 |
REWIND | 重新定位于文件的开头 |
REWRITE | 覆盖当前记录 |
UNLOCK | 释放先前被READ语句锁定的相关或顺序文件中的一个记录 |
WRITE | 从一个I/O列表中的项目向文件输出数据 |
一个记录是一个数字或字符的序列。有三种记录形式,即格式化记录、非格式化记录和文件结束记录。一条格式化记录的数据需要进行内部和外部形式间的转化,格式化I/O语句有确切的格式说明符或名称列表,只有格式化I/O语句才能读写格式化记录。非格式化记录保持其内部形式,而内部形式依赖于处理器。只有非格式化I/O语句才能读写非格式化记录。文件结束记录是文件的最后一个记录,可以在顺序文件中用ENDFILE语句写出一个文件结束记录。
b) WRITE语句
用于输出的WRITE语句的一般形式为:
WRITE({[UNIT=]单元|*}[,{[FMT=]格式说明符|[NML=]名称列表组名|*}][,REC=记录号][,IOSTAT=状态变量名][,ERR=错误标号]) [I/O列表]
上面一般形式中的各项不是同时具有的,根据文件的属性(外部文件(顺序文件(格式化、格式化直接列表、格式化名称列表、非格式化)和直接文件(格式化、非格式化))和内部文件)不同而择其项。如果省略UNIT=,则第一个参数必须是“单元”。如果省略了FMT=或NML=,则格式说明符或名称列表组名必须是第二个参数(格式化文件)。其后的几项参数次序可以任意。
单元:外部文件时是一个指定设备号的整型表达式,内部文件时是一个字符串、变量、数组、数组元素或非字符数组。
格式说明符:对于格式写操作是必需的,非格式写操作时不能有。
名称列表组名:如果它被说明,则I/O列表必须省略。
错误标号:在同一个程序单位中的一个可执行语句的标号。如果指定了它,I/O错误将把控制传递给此标号处的语句,省略时取决于状态变量名的存在与否。
状态变量名:一个整型变量、数组元素。当无错误时,它返回值为0,有错误时则返回错误信息号。
记录号:一个整数表达式指定要被写的记录序号,仅用于直接文件。文件中的第一条记录的记录号为1,缺省值为文件中的当前位置。
c) PRINT和TYPE语句
PRINT语句向屏幕输出,TYPE语句是PRINT语句的别名,其规则是:PRINT {*|格式}[,I/O列表]和PRINT 名称列表。
例:下面的语句是等价的:
PRINT '(A11)', 'Abbottsford'
WRITE (*, '(A11)') 'Abbottsford'
TYPE '(A11)', 'Abbottsford'
例:一个输出的趣例。[e_711_01.f90]
d) READ语句
用于输入的READ语句的一般形式为:
READ({[UNIT=]单元|*}[,{[FMT=]格式说明符|[NML=]名称列表组名|*}] [,REC=记录号][,IOSTAT=状态变量名][,ERR=错误标号][,END=文件结束标号][,EOR=记录结束标号]) [I/O列表]
文件结束标号:读到文件结束记录时把控制传递给标号处的语句。
记录结束标号:读完一个记录时把控制传递给标号处的语句。
7.1.2 I/O列表
a) NAMELIST语句
名称列表NAMELIST语句将一组变量用一个名字相关联。这个组名可以在输入和输出中被引用。其一般形式为:NAMELIST/名称列表组名/变量列表[[,]/组名/变量列表]...。
例:integer int1
logical log1
real r1
character(20) char20
namelist/mylist/int1,log1,r1,char20
例:NAMELIST/INPUT/NAME,GRADE,DATE/OUTPUT/TOTAL,NAME
此例的INPUT组中包括NAME,GRADE,DATE三个变量。OUTPUT组中包括TOTAL,NAME两个变量。
b) I/O列表实体
I/O列表提供将要传输的数据的信息。数据传输语句(READ,WRITE和PRINT)需要如何传递数据和传递什么数据的信息。其中传递什么数据由I/O列表(iolist)中列出的将要读写的项确定。指定I/O列表可以有以下方法:
无实体。I/O列表可以是空列表。结果记录要么是零长度,要么是只包含填充字符。如果使用只有字符串而没有加列表的格式,结果记录将包含这个字符串。
例:WRITE(1,FMT=’(2I8)’)
WRITE(1,”(’string’)”)
变量名、数组元素名、派生类型名、派生类型元素名或子字符串名。[e_711_02.f90]
指定数组名或数组片段。没有下标的数组指的是按列存储的所有数组元素。[e_711_03.f90]
表达式。WRITE和PRINT语句中的输出列表可以包含表达式。表达式的类型可以是数值、逻辑型、字符型或派生类型。
例:PRINT *,’(I5)’,2*3
隐DO列表。它和一般的DO循环类似,起始、终值和增量值决定了循环次数。
例:WRITE(*,*) (my_data(i),I=2,30,3)
除此之外,指定名称列表后可以对其中的所有变量用一个I/O语句进行读写。
7.1.3 非格式输入输出编辑
I/O编辑告知系统如何在内存中的变量和外部设备及外部文件之间传递数据。有三种方法,即格式化I/O,直接列表I/O,名称列表I/O。当用户使用格式I/O时,必须指定数据在外部设备上如何出现的显示格式或FORMAT语句。后两种方法中的格式不是由程序员指定的,而是按系统默认的格式进行输入输出。
a) 直接列表I/O
使用直接列表I/O可以从一个I/O列表中读写数据而不需要格式或FORMAT语句,它可以用于读写外部或内部文件。输入输出由I/O列表中的数据项的数目和类型决定,格式指定符是星号(*)。例如下例中READ语句需要两个2字节整数,两个8字节实数和七个字符。
INTEGER(2) INT1,INT2
REAL(8) REAL1,REAL2
CHARACTER CHAR(7)
READ(10,*) INT1,INT2,REAL1,REAL2,CHAR(7)
1) 直接列表输入:必须提供包含要读变量名称的I/O列表。直接列表输入数据记录是一系列由逗号或空格分开的值。在直接列表数据记录中的每个数据项必须要么是某个值要么是Null(空)值。只有字符串常量可以包含嵌入的空格,两个数字之间的空格被解释为分隔符。与分隔符(逗号,斜杠或其它空格)相邻的空格被忽略。例如5, 6 /7等价于5,6/7。重复输入的值可以通过给该值乘上要重复的次数来实现。例如:对于程序 REAL R(10); READ(5,*) R 如果输入10*3.14,则数组R的十个元素都被置为3.14。空值对其映射的变量没有影响,有值的变量仍保留其值,没有值的变量仍保持为空。指定空值的方法是,用无间值的连续分隔符,如3.14,,,14记录中3.14后面两个值为空。还可以用星号格式说明一组Null,如10* 等价于10个空值。斜杠(/)将结束输入流,输入列表中的其它项就像其值为空一样不会产生任何影响。例如:
INTEGER I1,I2,I3
I1=1
I2=2
READ(*,*) I1,I2,I3
如果用户输入:8, , / 9则I1被赋成8,I2的输入为空,所以它的值仍为2,然后因为有斜杠所以输入记录被中止,I3的值仍为空(0)。
2) 直接列表输出:程序员写出I/O列表,Fortran系统提供输出格式。如果需要,系统会创建新的记录。为了在打印记录时提供走纸控制,每个输出记录自动以空格作为开头。每种内部数据类型有其默认的输出格式。
b) 名称列表I/O
名称列表I/O是功能强大的读入数据或向文件(终端)写入数据的方法。通过在名称列表组中确定一个或多个变量,可以用一个单独的输入输出语句读写它们所有的值。
1) 名称列表输出:名称列表中变量的值通过WRITE语句写入一个文件或屏幕,其格式指定符是名称列表名。注意,这里不需要I/O列表也不允许出现I/O列表。名称列表输出的一般格式为:WRITE(*,[NML=]namelist)。名称列表输出文件中第一个输出记录是连字符(&),紧接着是大写的名称列表组名称。然后是一个等号和变量当前的取值。名称列表输出由斜杠结束。变量的输出格式与直接列表I/O中的相同。下面的例子先声明一些变量,然后放入名称列表中并初始化,最后用名称列表I/O写入屏幕和文件:[e_711_04.f90]
2) 名称列表输入:一条名称列表READ语句的操作几乎是一个WRITE操作的逆操作。READ语句先从当前位置开始扫描文件(终端或者在磁盘上),直到找到一个紧接着名称列表组名称的开始符号(连字符&或美元符$)。在组名称后面必须至少有一个空格或回车来把名称和后面的赋值对区分开,语句找到组名称后会继续扫描寻找给组中的变量赋值的赋值语句。以斜杠、连字符或美元符号为结束符号。END可以在结束符号&或$后出现,但不能出现在斜杠之后。[e_711_05.f90]
赋值规则:一个赋值对由一个变量名、数组元素或子字符串和后面的等号以及一个或多个值和值分隔符组成。等号前后可以有任意个或没有空格。值分隔符可以是逗号或tab。如果逗号前面没有值则认为是空值,相应的变量或数组元素原来的值不变。字符串必须用撇号或引号隔开。变量出现的顺序是任意的。同一个变量可以在多个赋值对中出现,变量最终值由最后一个赋值决定。名称列表中的所有变量不一定都要赋值,其中没有出现的或与空值联系的变量保持它们原来的值。在输入文件中的变量名如果不在名称列表组中会产生运行错误。数组赋值是按行顺序进行的,所赋的值不能多于数组中元素的个数,重复赋值时可以在要赋的值前加上重复系数和星号。如7*5把5赋给数组或变量列表的下七个元素。如果星号后没有值,则认为是空值,相应的元素原来的值不变。
例:matrix=10,50*25,50*,-101
matrix(42)=63
第一条语句给元素0赋成10,元素1至元素50赋成25,元素51至元素100为空,元素10l赋成-101。第二条语句把元素42的值该为63。
7.1.4 格式化输出编辑
a) 格式化I/O和ASSIGN语句
格式信息包含在格式列表中,并由PRINT,WRITE和READ语句使用。这些语句可以包含格式列表本身,或包含有格式列表的FORMAT语句标号,或包含一个变量以设置编辑列表或语句标号。
格式列表是一系列格式描述符,之间用逗号隔开。这些格式描述符描述了将要传输的数据,例如要被读写的数字,数据类型和长度。下面是FORMAT和WRITE语句中的格式列表的例子:
例:100 FORMAT(’A=’,I5, ’B=’,F7.2)
例:WRITE(*,’(F8.5,2I3,A20) ’) REAL1,INT1,INT2,”format list example”
FORMAT语句可以出现在程序的任何地方(但必须在PROGRAM语句之后和END语句之前,如果在子程序中用FORMAT语句,则应在子程序定义语句之后)。系统按WRITE语句中指定的语句标号找到相应的FORMAT语句,并按所规定的格式对输出数据进行编辑。
格式列表(包括外部的括号)是字符常量,在READ或WRITE语句中出现时应被单引号或双引号包括。当格式列表在FORMAT语句中出现时整个格式列表并不用引号。编辑列表也可以包含另一个格式列表,在格式列表最外层括号中最多允许8层嵌套的括号。格式列表由可重复和不可重复的编辑描述符组成。可重复编辑描述符描述了数据项,如2I3指定编辑描述符I3重复两次,这样可以写两个3位的整数。不可重复编辑描述符可以改变数据格式,如SP使正数输出时带有加号。
指定包含格式列表的格式方法是:
FORMAT语句标号:如果指定I/O中的FORMAT语句标号,在FORMAT语句中的格式列表规定了数据的格式。
例: WRITE(*,9000) int1,real1(3),char1
9000 FORMAT(I5,3F4.5,A16)
整型变量名:可以使用ASSIGN语句把FORMAT语句的标号和一个整型变量相联系,随后使用这个变量来引用FORMAT语句。ASSIGN语句的形式为:ASSIGN 语句标号 TO 整型变量
例: ASSIGN 9000 TO MYFMT
WRITE(*,MYFMT) iolist
9000 FORMAT(I5,3F4.5,A16)
字符表达式或变量:可以把格式表达式写成字符表达式并在READ,WRITE或PRINT语句中使用,也可把格式列表赋给变量名。
例:WRITE(*,’(I5,3F4.5,A16) ’) iolist
例:CHARACTER(80) MYLIST
MYLIST=’(I5,3F4.5,A16) ’
WRITE(*,MYLIST) iolist
数组或数组元素:如果把格式列表写成字符表达式并将其赋值给一个数组,可以使用数组作为格式指定符。如果把格式列表写成字符表达式并将其赋值给一个数组元素,可以使用数组元素作为格式指定符。
例:CHARACTER(6) array(3)
DATA array/’(I5’, ’,3F4.5’, ’,A16) ’/
WRITE(*,array) iolist
例:CHARACTER(80) array(5)
array(2)= ’(I5,3F4.5,A16) ’
WRITE(*,array(2)) iolist
b) 输出规则
1) 如果输出字符的数目超过了指定的区域宽度或指数宽度,则整个区域将被写为星号(*)。如果实数小数点后包含的数字位数比区域允许的多,结果会四舍五入。
2) 输出时数字是右对齐的,如果输出数字少于规定宽度前面会补上空格。
3) 规定复数的格式时需要两个连续的F,G和D编辑描述符,而且两个编辑符可以不同,第一个指定实部,第二个指定虚部。
4) 在可重复编辑描述符之间可以出现不可重复编辑描述符。
c) 可重复编辑描述符
可重复编辑符告知Fortran输入输出系统如何解释FORMAT语句中的数据项。它可以根据I/O列表中数据项的需要重复任意次。重复方式是指定一个非零的无符号整数常量或一个被尖括号括起来的整型表达式。例如<J+K>I5就说明I5格式的数据项应该重复J+K次。
重复编辑描述符有:
1) 整数编辑(I)
2) 二进制(B)、八进制(O)和十六进制(Z)编辑
3) 没有指数的实型编辑(F)
4) 有指数的实型编辑(E)
5) 双精度实型编辑(D)
6) 工程计数法编辑(EN)
7) 科学计数法编辑(ES)
8) 逻辑编辑(L)
9) 字符编辑(A)
10)普通编辑(G)
其中I(整数)、B(二进制)、O(八进制)、F(单精度实型)、E(有指数的实型)、EN(工程计数法实型)、ES(科学计数法实型)、G(普通)和D(双精度实型)编辑描述符用于数字数据的输入输出。
d) I编辑符
I编辑符用于整型数据的输入输出,其一般形式为:Iw[.m]。一个数据所占的宽度称为“字段宽度”,w用来指定字段宽度,负数的符号也包含在字段宽度内。如I3表示相应的整数的输出占3列位置。FORMAT语句中各编辑符与WRITE语句中的各输出项按排列的顺序一一对应。数字在指定的区域内向右端靠齐,如果数字位数比Iw的w小则左边补以空格。如果应输出的列数超过了规定的字段宽度,则不输出有效数据,而在该字段宽度范围内充满星号。m表示需要输出的最少数字位数,不足添0,如果应输出的数字超过m,则按实际应输出的值数输出(但不能超过w)。
在任何需要整型常量作为编辑符的地方都可以在FORMAT语句中指定数值表达式。如果表达式不是整型的,则它将在使用之前被转化为整型。
e) F编辑符
F编辑符用于实数的小数形式输出,其一般形式为:Fw.d。其中w的含义仍为“字段宽度”,包含一位小数点和一位负号(如为负时),d的含义是输出数据的小数位数。用F编辑符输出时,由于难以事先确切估计出数据值的大小,输出大的数时容易产生“宽度不够”的错误,输出小的数时会出现丢掉有用数字的情况,这是用F编辑符所应注意的一个问题。
f) 可变格式的输出
可变格式即用用尖括号括起来的数值表达式。
例: WRITE(6,20) INT1
20 FORMAT(I<MAX(20,5)>)
例: WRITE(6,FMT=30) REAL1(10),REAL3
30 FORMAT(<J+K>X,<2*M>F8.3)
例:用于可变格式输出时的一例。[e_711_06.f90]
g) E编辑符
E编辑符用来输出指数形式的实数,其一般形式为:Ew.d。其中w仍为字段宽度,d为以指数形式出现的数据的数字部分的小数位数。例如,若A=-746.578,则WRITE(*,’(E15.6,E12.4,E9.3,E8.3)’) A,A,A,A语句的输出结果为: -0.746578E+03 -0.7466E+03-.747E+03********
小数部分d位,再加上一个小数点、小数点前的0、一位负号、指数部分4位,需要w≥d+7。用E编辑符可以避免“大数印错,小数印丢”的情况,可见用x编辑符输出实数的优点是它能容纳任意大小的数据,不必事先估计数值的大小,但输出的是指数形式,看起来不大直观。
小数点前的0与Fortran编译器有关,有的系统不提供0。
h) G编辑符
G编辑符综合了F编辑符和E编辑符各自的长处。它可以根据输出的实数大小决定用F型格式输出或E型格式输出。当输出大数值或小数值时自动按E格式,当输出的数不大不小时用F格式。其一般格式为:Gw.d。绝对值小于0.1或大于10d的数用E格式,否则用F格式,有效位数为d位。如A=758321.6,用G14.7,由于d=7,系统采用F格式输出: 758321.6 。而当A=75.83216E+06时,用E格式输出: O.7583216E+08。
注意用F格式输出时,不是按Fw.d格式输出,d规定的不是小数位数而是打印出来的全部数字的位数,小数位数根据数值大小和d的大小而定,这样做的目的是使数的整数部分能全部保留,而适当截去小数部分,以保证输出数值的正确性。
i) D编辑符
D编辑符用于双精度数据的输出。其一般形式为:Dw.d。使用方法与E编辑符相仿,只是把字母“E”换成“D”。F编辑符也可用于双精度数据的输出,和用于实型数据输出相似。
j) L编辑符
L编辑符用于逻辑型数据的输出。其一般形式为:Lw。对值为“真”的,在输出时打印一个字母T,“假”则以一个字母F表示。w>1时左边补空格。逻辑常量(.TRUE.或.FALSE.)可以直接输出。
k) A编辑符
A编辑符用于字符型数据的输出。其一般形式为:A[w]。w为字段宽度。如果待输出的字符串的长度大于w,则左边补空格,否则只输出最左边的w个字符。用A时按字符串定义的长度输出。
l) B、O、Z编辑符
二进制(B)、八进制(O)和十六进制(Z)是F90新增的编辑描述符,用于整数、实数和逻辑量的输出。其一般形式为:Bw[.m],Ow[.m],Zw[.m]。w为字段宽度。m表示需要输出的最少数字位数,缺省值为1。如果输出少于指定的宽度,则左边补空格。但对于二进制数,如果以0填补可读性会更好一些,例如O0010101显示了l0101所有的8位。可以使用类似B8.8,B16.16,B32.32等的格式强迫开始以O填补。
编辑描述符不包含小数点或负号。相应进制的数据只能由允许的数字组成:B描述符允许0和1,O描述符允许0-7,Z描述符允许0-9和A-F。它们都可用于整型、字符型、实型或逻辑型。因为没有负号,所以B,O和Z的负值应根据所使用编码转换来表示。对二进制、八进制和十六进制的译码,尤其是负数的译码是和CPU有关的。使用B,O和Z编辑描述符和以B,O和Z存储数据的程序可能不能直接在计算机之间移植。
使用B,O和Z编辑可以在二进制、八进制和十六进制形式的外部数据和内部数值表示之间互相转换。内部数据的每个字节对应8位二进制字符,3个八进制字符和2个十六进制字符。例如,十进制255的输出就是二进制字符11111111、八进制字符377和十六进制字符FF。类似地,一个数据存储中的INTEGER(4)输出时是32个二进制字符、12个八进制字符或8个十六进制字符。w被忽略时,缺省区域宽度为8*n个二进制字符,3*n个八进制字符或2*n个十六进制字符。n是I/O列表中的数据项的字节长度。例如,一个为INTEGER(2)的值是由4个十六进制字符表示的。[e_711_07.f90]
m) EN、ES编辑符
工程计数法(EN)和科学计数法(ES)也是F90新增的编辑描述符。EN的一般形式为:ENw.d[Ee]。EN和E编辑描述符基本类似,区别在于EN输出数据的非指数部分的绝对值强制在1到1000的范围内,且指数可以被3整除。包括指数的区域的宽度是w个字符,小数点后d个字符,指数宽度e是可选的。ES的一般形式为:ESw.d[Ee]。它和E编辑描述符也基本类似,区别在于ES输出数据的非指数部分的绝对值强制在l到10的范围内,而非E的0到1的范围。[e_711_08.f90]
n) 不可重复编辑描述符
不可重复编辑描述符可以改变解释重复编辑符的方式,还可以改变完成输入输出的方式。
形式 | 名称 | 用途 | 可否用于输入 | 可否用于输出 |
’ ’或” ” | 撇号编辑 | 传递string到输出单元 | 否 | 是 |
nH | Hollerith编辑 | 传递下n个字符到输出单元 | 否 | 是 |
Q | 字符计数编辑 | 返回记录中剩余字符的数目 | 是 | 否 |
T,TL,TR | 位置编辑(Tab) | 指定记录的位置 | 是 | 是 |
nX | 位置编辑 | 指定记录的位置 | 是 | 是 |
SP,SS,S | 可选加号的编辑 | 控制加号的输出 | 否 | 是 |
/ | 斜杠编辑 | 指向下一个记录或写记录结束符 | 是 | 是 |
\ | 反斜杠编辑 | 延续相同的记录 | 否 | 是 |
$ | 美元符号编辑 | 延续相同的记录 | 否 | 是 |
: | 格式控制结束 | 如果I/O列表中没有其它记录则结束语句 | 否 | 是 |
kP | 指数比例编辑 | 设置后面的F和E编辑符的指数比例 | 是 | 是 |
BN,BZ | 空格解释 | 指定对数值空格的解释 | 是 | 否 |
用来分隔列表项的逗号在下列不可重复编辑符前面或后面时可以忽略:
1) 在P编辑符和紧接着的F、E、EN、ES、D或G编辑符之间,例如:I3,2PF8.6,4F4.3。
2) 在撇号、双引号、反斜杠、美元符号或冒号编辑符前后,例如:A14,A35,I5$。
3) 当可选的重复系数没有出现时,在斜杠编辑符之前;所有情况时在斜杠之后。
4) 在nH或X编辑符之后,例如:2I3,8HF5.3,A12。
o) 撇号编辑符
撇号编辑符(单撇号’或双撇号”)用来插入所需的字符串,如WRITE(*,’(1X,’I=’,I3,’J=’,I4)’) I,J。如果需要输出的字符包括单撇号,则用两个连续的单撇号代表一个被输出的撇号(撇号编辑符为单撇号时)或用双撇号的编辑符,如WRITE(*,’(’I’ ’m a boy’)’)或WRITE(*,’(”I ’m a boy”)’)。
p) H编辑符
H编辑符它用来输出字符常量,其一般形式为:nH字符串。n为字符串中字符个数。它的作用与撇号编辑符相似。例如,上面用撇号编辑符的例子也可用H编辑符:WRITE(*,’(9HI ’m a boy)’)。用H编辑符必须准确地数出字符串中字符(包括符号,. ’)的个数,数错了就会造成错误。因此不建议使用H编辑符,而应该用A编辑符和撇号编辑符来输出字符串。F77之所以保留H编辑符主要是为了与F66兼容,但在F95中已被废除。
q) X编辑符
X编辑符用来在输出时产生空格。没有空格的输出时数据是连成一片的,难以区分开,为此需要插入空格。它的一般形式为:nX,n为插入的空格数,如WRITE(*,’(1X,’I=’,I3,5X,’J=’,I4)’) I,J在数据I和字符串’J=’之间插入5个空格。注意第一项中的1X,在行式打印机上可作为纵向走纸控制符,但在输出到文件和屏幕时,按Visual Fortran的默认编译它仅仅为空一格。
r) 纵向控制符
在把格式记录中的信息传送到打印设备上(打印机或终端)时,格式说明中的第一个字符不被印出,这个字符作为纵向间隔控制标志,称为纵向控制符。它们的功能在下表中列出。
格式说明的首字符 | 纵向间隔控制功能 | 常用形式 |
(空格) | 移到下一行开头 | 1X, ’ ’,1H |
0(数字0) | 移到下面第二行开头 | ’0’,1H0 |
1(数字1) | 移到下一页第一行开头 | ’1’,1H1 |
+(加号) | 移到当前行开头 | ’+’,1H+ |
其它字符 | 移到下一行开头 | (非标准规定) |
要使这些功能在Visual Fortran上实现,必须按以下步骤修改默认值:对于输出到终端的情形,在菜单选项中Project -> Setting -> Fortran -> Compatibility选取Enable VMS Compatibility项。对于输出到文件的情形,在打开文件的OPEN语句中加上说明项CARRIAGECONTROL='FORTRAN'。这时每行记录的第一个字符被当作控制符,可能产生输出的数字或字符被吃掉的情形。另外重叠印刷功能仅对于行式打印机有效,对于终端和文件的输出其效果是覆盖。
s) 斜杠编辑符
斜杠(/)编辑符的作用是结束记录在本行的输出并从下一行开始输出下一个记录。如果有两个连续的斜杠,相当于增加一个空行输出。如果在编辑符的最后出现斜杠,也是再输出一个空行。用n个连续的斜杠,可以达到输出n-1个空行的效果。如WRITE(*,’(I3,I4/I1,I2//3F8.2/)’) I,J,M,N,X,Y,Z 的输出第一行为I,J的值,第二行为M,N的值,第三行为空行,第四行是X,Y,Z的值,第五行为空行。
t) 反斜杠编辑符和美元编辑符
反斜杠(\)编辑符和美元($)编辑符的作用相同,都是在输出一个记录行后取消回车符。常用于输出字符串与输入数据显示于屏幕同一行的情形。
例:Write(*,’(”Please Enter Your Age =”,$)’)
Read(*,*) My_age
当屏幕上输出字符串Please Enter Your Age =后没有换行,My_age的数值可紧接在=号后输入。
u) T,TL,TR编辑符
位置编辑符(T,TL,TR)在用于输出时,指出将要输出到记录上的下一个字符的位置。它们的一般形式为:Tn,TLn,TRn。n是非零正整数。
T指明记录相对于左Tab端的位置,记录上的下一个字符输出第n个字符的位置上。对于行式打印输出,因为记录的第一个字符作为纵向控制符不被打印,所以Tn是定位在打印记录的第n-1个字符的位置上。在这个位置之前若没有字符输出,则填满空格。
TL用于输出时,指明把记录上的下一个字符输出到从当前位置向左移n个字符的位置上。如果左移已到记录的第一列,则不再向左移,即向左移至多回退到第一列。TR用于输出时,指明把记录上的下一个字符传输到从当前位置向右移n个字符的位置上。如WRITE(*,’(TR10,F6.2,TL16,F6.2)’) 4.25, -21.46语句的输出结果是-21.46 4.25。
v) 冒号编辑符
当I/O列表中没有更多的数据顶时,冒号(:)编辑符使格式控制结束。此编辑将常常用于FORMAT语句中没有要输出的数据项时的输出结束。
w) P编辑符
P编辑符设置比例因子以改变小数点位置,它用于实数变量编辑描述符如F、E和G编辑符。其作用范围延续到下一个比例因子的设置处。它的一般形式是:kP。k是一有符号整数以指定小数点向左或向右移几位,k取值范围在-128至127之间。在每一个输入输出语句开始时,这个比例因子被初始化为O。输出时,正k向右移,负k向左移(输入时相反)。比例因子对下面格式编辑符的影响:在用F编辑符输出时,这个要输出的值在显示以前将乘以10k。在用E编辑符输出时,这个要输出的值的实数部分在显示以前将乘以10k,其指数部分减k。
例:Format Value Output
1PE12.3 -270.139 -2.701E+02
1P,E12.2 -270.139 -2.70E+02
-1PE12.2 -270.139 -0.03E+04
例:dimension a(6)
a=25.;write(*, "(' ',f8.2,2pf8.2,f8.2)") a
其输出是: 25.00 2500.00 2500.00
2500.00 2500.00 2500.00
x) SP,SS,S编辑符
SP,SS和S编辑符在数字输出字段中控制着任选加号(+)的打印。SP在其后所有正数值域的位置输出加号,SS为不输出加号,S重新储存SS使其后不输出加号。
y) 输出格式指定和I/O列表
在输出语句执行时,I/O列表中的每一项都和一个可重复编辑符联系(I/O列表中的复型数据需要两个编辑符),非重复编辑符不和I/O列表中的数据项联系。如果I/O列表包含一个或多个数据项,则在格式指定时至少有一个可重复编辑符。空的编辑指定()只能用在I/O列表没有数据项的情况。一条编辑指定为空的FORMAT()格式WRITE语句输出的是回车换行。
在格式输入输出过程中,格式控制器从左向右扫描格式数据项。下面列出了格式控制器可能碰到的具体情况及相应的解释:
1) 如果I/O列表中出现了可重复编辑符和相应的数据项,该数据项和编辑符是互相联系的,该数据项的输出会在编辑符的格式控制下执行。如果没有相应的数据项格式控制器将中止输出,即多余的编辑符无效。
2) 如果I/O列表中项数多于格式说明中的可重复编辑符个数,即WRITE语句中的输出项表列中还有末输出的元素,而格式说明中的编辑符已用完,则重新使用该格式说明,但从下一行开始产生一个新记录。
3) 如果在格式说明中包含有重复使用的编辑符组,则当格式说明用完后再重新使用时,只有最右面的一个编辑符组(包括其重复系数)和它右面的编辑符被重复使用。
4) 遇格式说明的右括号(即最后面一个括号)或斜杠“/”时,结束本记录的输出,但不意味停止全部输出。只要I/O列表中还有未输出的量,将重复使用格式说明或按斜杠右面的格式说明组织输出。右括号与斜杠的不同是:当扫描到右括号而列表中已无数据项时,输出即告结束。而斜杠只表示结束本行输出,即使此时已无输出变量要输出,输出并未停止,它会重新开始一个新记录,直到遇到右括号或非重复编辑符为止。
5) 如果出现冒号编辑符(中止格式控制)且I/O列表中没有其它项,则格式控制器将中止输入输出。
7.1.5 格式化输入编辑
a) 输入规则
1) 输入时,全部是空格的区域始终解释为O。拖后空格和分散空格的解释由BN和BZ两个编辑描述符和OPEN语句中BLANK=选项来控制。正号(+)可选的,但对指数例外。
2) F、E、EN、ES、G和D编辑下的输入中,输入区域的显式小数点将覆盖编辑描述符中对小数点位置的指定。例如,READ(*,’(F4.2)’) x当输入123.4时,x=123.4而非按格式指定的23.40。
3) 当用I、B、O、Z、F、E、EN、ES、G、D或L编辑描述符时,输入区域可以包含逗号,表示结束该区域。下一个区域开始于逗号后的第一个字符。丢掉的字符没有意义。但在使用如T、TL、TR或nX等显式编辑描述符时不能使用这个性质,因为这样将会改变数据中的字符位置。
b) 整数输入
整数输入用I编辑符。Iw中的w规定输入数据所占的列数。在规定的字段宽度内,空格按零处理(BZ),除非用BN另行解释。因此必须使输入的数据在规定的字段宽度内向右端对齐。符号也包括在字段宽度内。
c) 实数、复数和双精度数的输入
实数用F编辑符输入:当输入数据不带小数点,由系统按指定格式自动加上小数点。输入数据可以自带小数点,如果Fw.d指定的小数点位置与输入数据的小数点位置不一致,按“输入数据自带小数点优先”原则。
输入实数时可以任选F、E、EN、ES、G编辑符,输入数据的形式可以是小数形式或指数形式。如果用指数形式输入数据而其数字部分不带小数点,则按照Fw.d(或Ew.d)中d的值对其加上小数点。
复数输入时,按两个实数输入,双精度数用D编辑符输入。
d) 逻辑型和字符型数据的输入
逻辑型数据用L编辑符输入。输入的数据可以是.TRUE.(真)或.FALSE.(假),也可以是以T或F字母开头的任何字符串。
字符型数据的输入用A编辑符。不指定字段宽度w则自动按字符变量的定义的长度截取所需字符。
e) BN、BZ编辑符
BN,BZ编辑符在数字输入字段中控制着空格的解释。BN编辑符忽略数字输入字段中内嵌和后续空格,使格式控制器仅使用字段上的所有非空格字符,并使它们向右对齐。例如,对于READ(*,’(BN,I6)’) n,输入以下3个值后按回车键:
123
123
123 456
READ语句将这三个输入值都理解为123。因为只有前6个字符才作为n的数值,且123前后的空格都被忽略了。
BZ编辑符使结尾空格符和分散空格符为零,而开头空格符仍为零。例如,对于READ(*,’(I6)’) n,当输入123后按回车键,则n值为123000。
f) Q编辑符和可变格式输入
Q编辑描述符返回当前输入记录中剩余的字符数。对应的I/O列表中的数据项必须是整型或逻辑型的。
例:READ(4,’(E15.7,I4,Q,(80A1))’)XRAY,KK,NCHRS,(ICHR(I),I=1,NCHRS)
输入语句首先读出前面XAY和KK的变量值。记录中后面剩余的字符数赋值给NCHRS,然后字符数组ICHAR读入的字符数即为准确的待读字符数。通过将Q作为格式说明的第一项,可以确定待输入记录的长度。
注意由Q返回的长度是记录左边的字符串的长度,不是实数,或整数或其他数据类型的长度。一旦由Q读出长度,此值可以立即使用,或者用于可变格式表达式中。下面是可变格式输入的例子:
例:INTEGER width, value
width=2
READ (*,10) width, value
10 FORMAT(I1, I <width>)
PRINT *, value
END
当输入3123时,打印输出值是123而非12。
g) 输入格式指定和I/O列表
一条编辑指定为空的FORMAT()格式READ语句将跳过相邻的下一个记录,除非输入输出设置成ADVANCE=’NO’,这时文件位置将保持不变。记录中的字符如果少于编辑符指定的长度,在右侧会填以空格,除非在OPEN语中指定PAD=’NO’。用户输入的空格的解释取决于空格编辑描符(BN或BZ)的作用或OPEN语句中的BLANK=选项。BN和BZ的优先级比BLANK=选项要高。