1、第九章 格式化输入/输出及文件操作,采用程序解决各类问题,需要有文件的输入和输出。格式化的文件输入输出操作可以有效的帮助我们理解问题。本章中,将着重探讨格式化输入/输出,包括各种格式编辑符、输入/输出语句以及文件操作,主要包括以下内容: 1 PRINT 语句 2 格式编辑符 3 READ 语句 4 WRITE 语句 5 内部文件 6 外部文件 7 不换行的读写,实例,输出 Fibonacci 数列:从第三项开始,每一项为前两项之和。例 9-1 输出Fibonacci 数列 PROGRAM RabbitBreeding IMPLICIT NONE INTEGER Month REAL Fn,Fn
2、_1,Fn_2 !Format 规定 10 FORMAT( Month,T12,Population,T27,Ratio/5(-),T12,10(-),T27,5(-) ) 20 FORMAT( I13,T12,F7.1,T27,F6.4) Fn_1=1 Fn_2=1 PRINT 10 !输出表头 DO Month =3,12 Fn = Fn_1+Fn_2 PRINT 20,Month,Fn,Fn/Fn_1 !输出表中记录 Fn_2 = Fn_1 Fn_1 = Fn END DO END PROGRAM,第一节 PRINT 语句,程序运行结果: Month Population Ratio -
3、 - - 3 2.0 2.0000 4 3.0 1.5000 5 5.0 1.6667 6 8.0 1.6000 7 13.0 1.6250 8 21.0 1.6154 9 34.0 1.6190 10 55.0 1.6176 11 89.0 1.6182 12 144.0 1.6180程序中对PRINT语句说明如下:,程序中,用 PRINT n 代替 PRINT*,n 为语句(199999)的行标号,FORMAT语句则规定了输出的格式。第一个 FORMAT 语句用于输出表头。 T12 将制表位移到第12 列,后面的输出项从第12列开始;撇号(/)终止当前行,开始新的一行;5(-)表示将-重复
4、输出5次。第二个 FORMAT 语句用于输出表中记录,即是输出变量列表。 I 为整数编辑符,I3 指整数输出宽度占 3列;F为实数编辑符,F7.1、F6.4指实数输出宽度分别占7列和6列,小数点后分别有1位和4位。PRINT 语句通常用于屏幕输出,其一般形式为: PRINT fmt ,list 其中List 为输出列表,其中的项可以是常量、表达式、变量或隐式 DO 循环列表(形如:variable = expr1,expr2 ,expr3)。,Fmt 可以是下列三种格式之一:(1) FORMAT 格式,通过语句标号引用 FORMAT 格式规定。例如: PRINT 10,X 10 FORMAT(
5、The answer is:,F6.2)10 为语句标号,X 为实型变量,FORMAT 为格式语句。(2)自由格式,以星号表示自由格式。例如: PRINT*,The answer is:,X(3)字符串规定格式,字符串即为格式规定。例如: PRINT ”(The answer is:,F6.2)”,X,编辑符决定了计算机内部表示的数据如何转换为输出设备及文件中可读的字符串,或输入设备或文件中的字符串如何转换为计算机内部表示的数据,共有三类编辑符:数据编辑符、字符串编辑符和控制编辑符。例如9-1中的 F7.1 为格式编辑描述符,规定了输出/输入的外观。一. 数据编辑符 在以下描述中,字母 w 、
6、m 、d 和 e 代表正整型常量,b 代表空格。假如规定的宽度不够,输出项以星号(*)填充。数据编辑符分为整数、实数、复数、逻辑数和字符 5 种编辑符。(一) 整数 整数使用 I 编辑符,其一般形式为 Iw,当中的 w 规定了输出宽度,包括前导的负号所占据的一列。 另一种形式为Iw.m,保证有m 位数字(不包括负号)被输出,若不够 m 位,前面填0。例如:在I6.3 编辑符下,-99被输出为 bb-099。 二进制、八进制和十六进制整数,分别使用 Bw、Ow 和 Zw 编辑符。例如: READ (B4),I 在 Bw、Ow 和Zw 编辑符下,同样可以规定最小的位数 m。,第二节 格式编辑符,(
7、二)实数实数编辑符包括F、E、G、EN 和 ES。1. F 编辑符 F 编辑符的形式为 Fw.d,w 为总的输出宽度(包括负号和小数点列),d 为小数点后的位数。例如:在 F8.2 编辑符下,-12.345 输出为 bb-12.35,小数点后的第二位四舍五入。 输入时,若字符串包含小数点,d 被忽略。例如: F8.2 编辑符,1.2345仍被读为1.2345;在 F9.1 编辑符下,12.345E-2 被读为 0.12345。 输入时,若字符串不包含小数点,最右边的 d 位为小数部分。例如:在 F7.2 编辑符下,-12345 被读为 -123.45。2. E 编辑符 E 编辑符包括 Ew.d
8、 和 Ew.dEe,两种形式输入规则与 F 编辑符相同。 输出时,Ew.d 中的 w 规定了输出项的宽度,包括可能的前导负号列、小数点和4列指数部分;d 仍为小数部分的位数;基数的绝对值小于1。例如:在 E10.4 编辑符下,1.234E+23 输出为0.1234E+24。 Ew.dEe 中的e 限定了指数部分的位数,不足部分填充0。例如:在 E11.4E3 编辑符下,1.234E+23 输出为0.1234E+024。,3. G 编辑符 G 编辑符包括 Gw.d 和 Gw.dEe,是 F 和 E 编辑符的一般形式。在事先无法确定变量大小时,G 编辑符十分方便,将依据变量值的大小,相应地采取 F
9、 编辑符或 E 编辑符。4. EN 编辑符 EN(Engineering) 编辑符限定指数为3的倍数,基数大于或等于 1 且 小于1000,其他的规则与 E 编辑符相同。例如:在 EN 10.2 编辑符下,2.17E-2 输出为21.70E-03。5. ES 编辑符 ES (Scientific,科学计数法)编辑符限定基数大于或等于1且小于10。例如:在 ES 10.2编辑符下,0.217输出为 2.17E-01。(三) 复数 复数由实部和虚部构成,因此其编辑符由一对实数编辑符(F、E、EN或ES)组成,实部和虚部可以使用不同的实数编辑符,它们之间由字符串、控制编辑符分隔。(四) 逻辑数 L为
10、逻辑数编辑符,一般形式为 Lw。输出时,T 或 F 出现在第 w 列,即右对齐;输入时,可以输入大写或小写的T或F,也可以输入.TRUE.或.FALSE.,此时 w 被忽略。,(五) 字符字符编辑符包括 A 和 Aw。 在 A 编辑符下,若实际字符个数小于声明时字符个数,取实际字符个数,右边填充空格;若实际字符个数大于声明时的字符个数,则从左到右取声明时的字符个数。例如: CHARACTER*7 : C1 =SMITH,C2 = JOHN SMITH 输出分别为 SMITHbb 和 JOHN SM。 在 Aw 编辑符下,输出时,左边的 w 个字符被输出,不足时左边填充空格。例如: CHARAC
11、TER*5 : C = ABCDE 在A3 编辑符下,输出为 ABC;在 A6 编辑符下,输出为 bABCDE。 输入与输出的不同: Aw 编辑符输入规则有点特殊,例如 len 代表声明字符变量的长度,如果 w len,在 w 个字符中(包括右边的空格)最右边的 len 位字符被读入。例如:输入ABCDEF,在 A6 编辑符下,C 的值为BCDEF。 值得注意的是:整数、实数、复数和逻辑数据的输出,均为右对齐。,二. 字符串编辑符可以将字符串常量嵌入 FORMAT 语句中输出。例如: PRINT 10 10 FORMAT(Fortran 90 is the language for me) 关
12、于H 编辑符:输出字符串时,将 nH 描述符置于字符串首部。例如: PRINT 10 10 FORMAT( 24HWe must count carefully!) 24代表输出字符串的字符个数(包括空格在内)。 使用 H 编辑符时,字符个数 n 的规定必须准确;否则,会出现程序编译错误。,三. 控制编辑符 控制编辑符可以准确定位输出列,开始新的一行,在输入时跳过若干列等。(一)内嵌空格输入及正号输出 在 BN (blanks null,空白)和 BZ(blanks zero,0) 编辑符下,输入列表中的内嵌空格要么作为0,要么作为空白,例如: INTEGER I1,I2 READ (BN,I
13、3,BZ,I3),I1,I2 若输入字符串 1b31b3,I1和I2 的值分别为 13 和 103。 有三种编辑符控制正数的正号输出:SP 输出正号,SS 正号被压缩掉,S恢复缺省设置。例如: INTEGER : I=99 PRINT (SP,I3,SS,I3,S,13),I,I,I I 被输出3次,其结果为+99b99b99。,(二) 比例因子 比例因子 kP 可以应用到E、F、EN、ES 和 G 编辑符下实数的输入,k为整数比例因子,将把除指数部分外的实数缩小10k。例如:在 (2P,F3.0)格式下,1.0 被读为0.01。 比例因子kP 也对E、F和G 编辑符下实数的输出产生影响,在
14、F 编辑符下,kP将实数扩大10k 输出;在E 编辑符下,kP 将指数缩小 k 倍、基数扩大10k 输出。(三) 制表位 制表位编辑符 T 包括 Tn、TRn 和TLn。Tn 在例 9-1中以出现过,将制表位移到第 n 列;TRn(或 nX)将制表位从当前位置向右移动 n 列;TLn 将制表位从当前位置向左移动 n 列。(R:RIGHT;L:LEFT。) 输入时,制表位可以用来跳过若干列或重读数据。例如:在 (I1,2X,I3)格式下,输入字符串 1234 被读为整数 1 和 4。 输入时,制表位可以用来替换输出的数据。例如:在(I3, TL2, I3)格式下, 整数 911 和 999 输出
15、为 9999。,(四) 另起一行 撇号(/)编辑符在例 9-1 中也出现过,其作用是开始新的输出行。撇号可以连续出现,也可用重复数来标识。例如:格式规定中的/或3/。(五) 冒号编辑符冒号(:)编辑符的出现,必须有对应的输出项,否则格式控制失效。例如: INTEGER : X(3)=(/10,20,30/),N = 2,I PRINT 10,(X(I),I = 1,N) 10 FORMAT(X1=,I2 : X2=,I2 :X3=,I2)根据 N =1,2,3,分别产生如下的输出: X1=10 X1=10 X2=20 X1=10 X2=20 X3=30若第一个 I2 编辑符后没有冒号,当 N
16、=1 时,将输出: X1=10 X2=(六) 编辑符重复数据编辑符可以出现重复,一个重复次数可以应用到括号包围的一组编辑符,也可以被嵌套使用,例如: 3(2F6.2,2(I2,3I3)假设格式规定的项数小于 I/O项数,就开始一个新行,相同的格式规定又施加到其余的I/O项上,这一点必须在书写输入、输出格式时加以 注意。,READ语句类似于 PRINT 语句,其基本形式为: READ fmt ,list其中,fmt 为语句标号、星号或字符串;list 为输入列表。为了防止从输入设备读入数据的过程中出现错误,引发程序意外地被终止,Fortran 90 提供了更为一般的 READ 语句: READ(
17、UNIT=u,FMT=fmt,IOSTAT=ios,ERR=errorlabel,END=endlabel)list其中:(1)单元号 u 和格式规定 fmt 是必须项,其他为可选项。(2)单元指I/O设备,如打印机、终端、磁盘驱动器等,通过编译器与程序相连接。输出时的终端指键盘,被称为标准I/O设备或单元。I/O 设备通常有一个与之关联的单元号,其范围为 199。(3)上述 READ 语句中的单元规定可以有三种形式:正是表达式、星号(指标准输入设备)和用于内部文件的字符变量。(4)如果可选项中的 IOSTAT 被规定,ios 须是整形变量。READ 语句执行后,依据到达行末、文件尾的不同情况
18、,ios 获得不同的负值;当错误发生时,ios 为正值或0。提供 IOSTAT参数,可以阻止由于异常使程序意外终止。,第三节 READ 语句,WRITE 语句的一般形式为: WRITE(UNIT=u,FMT=fmt,IOSTAT=ios,ERR=errorlabel)list其中各参数的规定和 READ 语句的相同。 需要注意的是:输出设备可以在程序执行期间指定。当开发需要输出大量数据到打印机上时,为了在正式打印前浏览、检查输出的数据,可以选择输出到打印机和终端 (屏幕)两种方式,程序代码如下: CHARACTER OutputDevice*3 PRINT*, Where do you wan
19、t the output(“prn”or”con”)? READ*, OutPutDevice OPEN(1,FILE = OutputDevice) WRITE(1,*)Output on designated device prn 和 con 分别代表PC打印机和终端,注意OPEN与CLOSE的对应。,第四节 WRITE 语句,在 READ 和 WRITE 语句中,I/O 设备可以是内部文件(字符变量),可以从内部文件读取数据,也可以向内部文件写数据,内部文件用于字符串和数字之间的转换。下列代码段从内部文件读取数据,将字符串转换成数字: INTEGER NYEAR CHARACTER (3
20、0) STRING STRING = “1984” READ(STRING,10) NYEAR 10 FORMAT(I4)下列代码段向内部文件写数据,将数字转换为字符串: CHARACTER(50) CAPTION INTEGER : YEAR=1984 WRITE(CAPTION,10) YEAR 10 FORMAT(Sales figures for the financial year :,I4),第五节 内部文件,* 外部文件可以将数据永久地保留在磁盘上,以方便对数据的更新、检查和分析;* 外部文件分为顺序访问文件(文本文件)和直接访问文件(随机文件),直接访问文件要求文件中所有的行(
21、记录)是等长的,顺序访问文件则无此要求。* 文件中的行可以是有格式的,也可以是无格式的。1. 顺序访问文件顺序访问文件只能从头开始读取数据,假如要读取的数据在文件末,也需要先读过前面不需要的行,读取顺序访问文件要比读取直接访问文件来的慢。不能直接替换或删除顺序访问文件中的部分数据,但顺序访问文件是 ASCII 文本文件,可以使用各种字处理软件进行查看。,第六节 外部文件,实例9-2,更新一个顺序访问文件:先从文件中读取每一行,将要保留的行写到临时文件(SCRATCH)中,删除原文件中的所有数据,再将临时文件中的数据拷贝回原文件。例 9-2 顺序访问文件的操作 PROGRAM ExternalF
22、ile IMPLICIT NONE CHARACTER(80)Name, FileName, Ans INTEGER:IO = 0 WRITE(*,(A),ADVANCE = NO)”Name of file to be updated: ” READ*, FileName OPEN(1,FILE = FileName) OPEN(2,STATUS = SCRATCH) DO WHILE (IO = 0) !没有到达文件尾 READ(1,*,IOSTAT = IO) Name !读文件 IF (IO = 0)THEN PRINT(A), Name WRITE(*, (A), ADVANCE =
23、 NO) “Keep(Y/N)?” READ*,Ans IF(Ans/=Y .AND. Ans/=y)WRITE(2, (A) Name,END IF END DO REWIND(2) ! 定位SCRATCH文件头 CLOSE(1,STATUS = DELETE) ! 关闭文件的同时删除所有数据 OPEN(1,FILE = FileName) ! 打开删除数据后的空文件 IO = 0 DO WHILE (IO = 0) READ(2,*,IOSTAT = IO) Name IF(IO = 0) WRITE(1,(A) Name !更新 END DO CLOSE(1) CLOSE(2) ! 临时
24、文件被关闭,删除,消失 END PROGRAM打开文件,建立文件与程序之间的连接,OPEN 语句的一般形式为: OPEN( UNIT=u,speclist)u 为单元号,假如不使用有名参数(UNIT=),单元号须出现在开头;speclist 为格式规定列表,其中的项大多是可选的:(1)FILE 参数指文件名,假如 FILE 被省略,则必须提供 STATUS 参数,且其值为 SCRATCH。,(2)STATUS 参数若规定为 SCRATCH,一个临时文件被创建,当文件关闭或程序结束时,临时文件随即消失;若规定为 NEW,不能有同文件存在;若规定为 OLD,同名文件必须存在;若规定为 REPLAC
25、E,文件不存在时创建新文件,文件存在时其内容将被替换。(3)ACCESS 参数规定了文件读取模式,顺序文件缺省为 SEQUENTIAL(4)FORM 参数规定了是否按格式读取,顺序文件缺省为 FORMATTED(5)POSITION 参数代表文件指针位置,若规定为 APPEND,新的数据将被追加到文件尾。(6)CLOSE 语句和 OPEN 语句配套使用,使文件与程序断开连接,一般形式为: CLOSE(UNIT=u,STATUS = st)其中u 代表要关闭文件的单元号。STATUS 可选参数可以规定为 KEEP 或 DELETE,缺省为 KEEP,关闭后文件数据被保留;若规定为 DELETE,
26、关闭时文件中的数据被删除;若文件为临时文件,则 STATUS 只能是 DELETE(缺省)。当程序正常结束时,不管是否执行了 CLOSE 语句,所有打开的文件都自动被关闭。,(7)在读写文件时,文件指针在不断移动。REWIND 语句将文件指针定位到文件的开头,使用形式为: REWIND u(8)BACKSPACE 语句将文件指针定位到当前行的开头,使用形式为: BACKSPACE u(9)顺序文件末尾有一个结束标记。计算机系统大多自动追加标记,也允许用户显式追加结束标记,形式为: ENDFILE u(10)前面提到:在 OPEN 语句中的 specilist中,可选参数 FORM 的缺省值为
27、formatted,即顺序文件默认是有格式的。但顺序文件也可以是无格式的,无格式可以有效地节省存储空间。 例 9-3 无格式顺序访问文件操作 PROGRAM Unformat IMPLICIT NONE INTEGER I INTEGER, DIMENSION(10) : A = (/(I, I = 1,10)/), B OPEN(1, FILE = TEST, FORM = UNFORMATTED) WRITE(1) A !无格式写入 REWIND(1) !读前,文件指针重定位到文件头 READ(1) B !无格式读入 PRINT*, B CLOSE(1) END PROGRAM,2. 直接
28、访问文件说明:在直接(或随机)访问文件中,可以方便的读取、改写或追加一个数据行。直接访问文件缺省是无格式的(二进制),但要求每行记录长度是等长的。在 OPEN 语句中,RECL 参数规定记录长度;在读取过程中,可由 INQUIRE 语句查询记录长度。实例:例 9-4 直接访问文件操作,从键盘读取名字写到随机文件中,再从文件中读取 PROGRAM DirectAccess IMPLICIT NONE CHARACTER(20) NAME INTEGER I, LEN INQUIRE (IOLENGTH = LEN) NAME !确定记录长度 OPEN(1, FILE = LIST, STATUS
29、 = REPLACE,& ACCESS = DIRECT, RECL = LEN),DO I = 1, 3 READ*,NAME WRITE(1, REC = I) NAME !往文件写数据 END DO NAME = JOKER WRITE (1,REC = 4) NAME !追加行 DO I =1,4 READ(1, REC =1) NAME !从文件读数据 PRINT*, NAME END DO CLOSE(1) END PROGRAM 在直接访问文件的 READ 和 WRITE 语句中,必须给出行号或记录号(REC)。,Fortran 90提供non-advancing I/O,实现不
30、换行读写,写语句形式为: WRITE (*,(A),ADVANCE=NO) Enter a number:光标停在字符串Enter a number之后,保持在行内,而不是下行的开头。实例:例9-5,利用不换行的读语句统计文本文件字符个数。 PROGRAM NON_ADVANCE IMPLICIT NONE CHARACTER ch*1,name*20 INTEGER : IO =0, Num = 0 WRITE(*, (A),ADVANCE =NO)Input file name:!不换行写 READ*, name OPEN(1,FILE = name) DO WHILE(IO/= -1)
31、READ(1,(A1),IOSTAT = IO, ADVANCE =NO)ch !不换行读,从键盘 IF(IO = 0) Num = Num + 1 END DO PRINT*,Num CLOSE(1) END PROGRAM,第七节 不换行的读写,小 结(1) 格式可以是带语句标号的 FORMAT 语句、星号(*)表示的自由格式(表控格式)和字符串规定格式。(2) PRINT 语句只能将数据输出到屏幕,WRITE 语句可以将输出定向到屏幕、打印机或文件,READ 语句可以从键盘、文件中读入数据。代表屏幕、文件的I/O设备单元,可以是单元号、星号(指标准I/O 设备)和字符变量(内部文件)。(
32、3) 格式可以由编辑描述符控制,编辑描述符包括数据编辑符、字符串编辑符和控制编辑符。(4) OPEN 语句通过单元号建立程序与文件之间的连接,CLOSE 语句则断开连接(关闭)。(5) 内部文件主要用于字符串与数字之间的转换。,(6) 外部文件分为顺序访问文件和直接访问文件(随机文件),每种文件又分为有格式文件的和无格式文件。(7) 顺序文件的数据缺省是有格式的,每行不要求是等长的,对顺序文件的读写须从头依次进行,可以追加新行,但不能改写现有的行。利用各种文字处理软件可以对顺序文件进行查看。(8) 随机文件的数据缺省是无格式的(二进制),每行必须是等长的,对随机文件的读写按行号(记录号)进行,可以追加新行,也可改写现有的行。随机文件的操作比顺序文件更有效率。(9) 利用 FORTRAN 90提供的 non-advancing I/O,可以进行不换行的读写。,