Fortran 格式化输入输出


Fortran中的 I/O 格式化用法

格式化:用来指定程序打印输出变量的具体形式,如位置、有效位数等。

READ(* , *)WRITE(* , *)括号中第二个*号均表示采用自由格式,此时输出中经常有多个额外的空格,且格式往往不统一。因此,可以采用格式化输出模式(采用格式描述符),来指定具体样式。


1.用法(READWRITE一致)

  1. 采用FORMAT语句,并且结合语句标号(行号)来使用,如:

    INTEGER:: a = 123
    WRITE(*,100) a
    100 FORMAT( '  ' , I5 )    ! 100是语句标号,将a变量用I5形式输出; '  '前面放置空格,实际上可以不要
    
          
          
    • 1
    • 2
    • 3
  2. 直接在第二个*号中指定具体样式,如:

    INTEGER:: a = 123
    WRITE(*,"(I5)") a     ! 单引号也可以,如 WRITE(*,'(I5)')
    
          
          
    • 1
    • 2

2.格式描述符

符号使用对象
I整数
F实数
E实数,指数表示法(非标准科学计数法)
ES实数,标准科学计数法
L逻辑数
X插入空格
T移动至同一数据行中某一字符位置
/换行
符号用途
c一行中的第c个字节位置
d用于实数,输入或输出的小数位数,不足则四舍五入
m至少输出的位数,若为2,则至少输出两位,即是变量的字符数小于2,也要输出两位
n插入空格的数目
r描述符的使用次数,如2I2,表示紧邻的两个变量用I2格式输出,而不需要重复写两次
w域宽,输入或输出占用的字符数,可以理解成是放字符的有效空间

3.WRITE使用对象

1) 整数输出(I
  1. 具体使用格式为:rIwrIw.m,具体用法见上述。

  2. 须注意:

    • 整数在输出域内为右对齐;
    • 字符个数超出域宽,输出时会用*号填充;
    • I0是特殊描述符,可以输出任意整数,而不需担心域宽不足。
  3. 具体例子:

    PROGRAM my_test
    IMPLICIT NONE
    INTEGER:: a = -123 , b  , c = 5 , d = 12345
    b = a+123
    

WRITE(,100) a , b , c , d
WRITE(
,101) a , b , c , d
WRITE(,200) a , b , c , d
WRITE(
,201) a , b , c , d
WRITE(,300) a , b , c , d
WRITE(
,400) a , b , c , d

100 FORMAT( ’ ’ , I5 , I5 , I6 , I10)
101 FORMAT( ’ ’ , 2I5 , I6 , I10) ! 用了rIw中的r
200 FORMAT( ’ ’ , 2I5.0 , I6 , I10.6) ! 用了rIw.m中的r和m,m是至少显示的位数,这里是0,则输出必须要≥0位,由于b的数值为0,因此没有显示值
201 FORMAT( ’ ’ , 2I5.2 , I6 , I10.6) ! 输出必须≥1位,b要显示出“00”
300 FORMAT( ’ ’ , 2I5 , I6 , I3) ! d的数值有5位,但域宽只有3位,装不下,因此输出“ * ”作为警告s
400 FORMAT( ’ ’ , 4I0) ! 特殊零长度描述符,使整数完整显示出来,此时的域宽w就是整数的长度,总是能够容纳进去

STOP
END PROGRAM my_test

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

相应结果为:

 -123    0     5     12345
 -123    0     5     12345
 -123          5    012345
 -123   00     5    012345
 -123    0     5***
-1230512345

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
2) 实数输出(F
  1. 具体使用格式为:rFw.d ,具体用法见上述。

  2. 须注意:

    • 实数在输出域内为右对齐;
    • 字符个数超出域宽,输出时会用*号填充;
    • 当字符小于域宽时,整数部分在左侧用空格填充,小数部分在右侧用0填充。
  3. 具体例子:

    PROGRAM my_test_F
    IMPLICIT NONE
    REAL:: a = -123. , b  , c = 5.2456
    b = a+123.
    

WRITE(,100) a , b , c
WRITE(
,200) a , b , c
WRITE(,300) a , b , c
WRITE(
,400) a , b , c

100 FORMAT( ’ ’ , F5.0 , F6.0 , F6.4) ! a、b变量,右对齐,左侧填空格;所有变量均使用了rFw.d中的d,即小数位数
200 FORMAT( ’ ’ , F5.0 , F6.0 , F6.3) ! c变量,由于只要求输出3位小数,因此四舍五入了
300 FORMAT( ’ ’ , F5.0 , 2F6.3) ! b变量,即使0没有小数,但也要补充完整;同时,使用了rFw.d中的r
400 FORMAT( ’ ’ , F5.0 , F6.3 , F3.2) ! c变量,由于需要输出2位小数,但域宽为3,而包含小数在内要4个字符宽(5.25),因此超出域宽,用*号填充

STOP
END PROGRAM my_test_F

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

相应结果为:

 -123.    0.5.2456
 -123.    0. 5.246
 -123. 0.000 5.246
 -123. 0.000***

 
 
  • 1
  • 2
  • 3
  • 4
3) 实数输出(E
  1. 具体使用格式为:rEw.d ,具体用法见上述。

  2. 须注意:

    • 不是标准的科学计数法,代表(0.1~1)×10n
    • 域宽需要满足一定的条件w≥d+7,如精确至2位小数则有±0.ddE±aa,共9位字符;精确至5位小数则有±0.dddddE±aa,共12位字符。
      特殊时候,数字前面的±0在某种情况下可以省略(见下述具体例子),因此该条件不是硬性条件,但由于能够满足所有情况且可视化效果较好,建议使用该条件
    • 同理,字符位数超出域宽时,会用*号填充。
  3. 具体例子:

    PROGRAM my_test_E
    IMPLICIT NONE
    REAL:: a = -123. , b  , c = 52456.
    b = a+123.
    

WRITE(,100) a , b , c
WRITE(
,200) a , b , c
WRITE(*,300) a , b , c

100 FORMAT( ’ ’ , 2E9.2 , E11.4) ! rEw.d,最好要满足 w≥d+7,a,b变量是2位小数,c变量是4位
200 FORMAT( ’ ’ , E8.2 , E8.2 , E13.6) ! a变量, w<d+7,但是不影响,因为正负符号或者整数位上的0可以省略
300 FORMAT( ’ ’ , E7.2 , E7.2 , E13.6) ! 域宽条件:负数可以为w≥d+6,正数可以为w≥d+5(针对整数位为0),否则会用 * 号填充

STOP
END PROGRAM my_test_E

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

相应结果为:


  -0.12E+03 0.00E+00 0.5246E+05
  -.12E+030.00E+00 0.524560E+05
  *******.00E+00 0.524560E+05

 
 
  • 1
  • 2
  • 3
  • 4
4) 实数输出(ES
  1. 具体使用格式为:rESw.d ,具体用法见上述。

  2. 须注意:

    • 标准的科学计数法,代表(1~10)×10n
    • 具体用法与E相同,域宽满足一定条件w≥d+7,该条件同样不是十分严格,但是均能避免不利情况,因此建议使用该条件
    • 同理,字符位数超出域宽时,会用*号填充。
  3. 具体例子:

    PROGRAM my_test_ES
    IMPLICIT NONE
    REAL:: a = -123. , b  , c = 52456.
    b = a+123.
    

WRITE(,100) a , b , c
WRITE(
,200) a , b , c
WRITE(*,300) a , b , c

100 FORMAT( ’ ’ , 2ES9.2 , ES11.4) ! rEw.d,最好要满足 w≥d+7,a,b变量是2位有效数字(小数),c变量是4位
200 FORMAT( ’ ’ , ES8.2 , ES8.2 , ES13.6) ! w<d+7,a变量,域宽已经受限,b变量不影响,因为开始的符号或者整数位上的0可以省略
300 FORMAT( ’ ’ , ES7.2 , ES7.2 , ES13.6) ! 如果负数必须为w≥d+7,正数可以为w≥d+6(对于整数位为0,则可以w≥d+5),否则会用 * 号填充

STOP
END PROGRAM my_test_ES

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

相应结果为:

 -1.23E+02 0.00E+00 5.2456E+04
 ********0.00E+00 5.245600E+04
 *******.00E+00 5.245600E+04	

 
 
  • 1
  • 2
  • 3
5) 逻辑输出(L
  1. 具体使用格式为:rLw ,具体用法见上述。

  2. 须注意:

    • 输出结果为TF
    • L0会报错,因此总是可以输出结果。
  3. 具体例子:

    PROGRAM my_test_L
    IMPLICIT NONE
    LOGICAL:: a =.TRUE. , b = .FALSE.
    

WRITE(,100) a , b
WRITE(
,200) a , b

100 FORMAT( ’ ’ , 2L5) ! 意义明确,不过过多解释
200 FORMAT( ’ ’ , 2L1)

STOP
END PROGRAM my_test_L

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

相应结果为:

    T    F
TF

 
 
  • 1
  • 2
6) 字符输出(A
  1. 具体使用格式为:rArAw,具体用法见上述。

  2. 须注意:

    • 输出结果为整个字符或切片后的字符;
    • A0会报错,因此总是可以输出结果。
  3. 具体例子:

    PROGRAM my_test_A
    IMPLICIT NONE
    CHARACTER(len=18):: a = "This is my_test_A."
    

WRITE(,100) a
WRITE(
,200) a
WRITE(*,300) a

100 FORMAT( ’ ’ , A) ! 输出定义的字符串
200 FORMAT( ’ ’ , A25) ! 设置域宽为25,域宽大于定义长度,右对齐,左侧填充空格
300 FORMAT( ’ ’ , A6) ! 设置域宽为6,域宽小于定义长度,只显示局部相当于切片

STOP
END PROGRAM my_test_A

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

相应结果为:

This is my_test_A.
       This is my_test_A.
This i	

 
 
  • 1
  • 2
  • 3
7) 水平定位(XT
  1. 具体使用格式为:nXTc,具体用法见上述。

  2. 须注意:

    • nX表示在变量间插入n个空格;
    • Tc表示将输出位置移动到本行中的第c个字节。
  3. 具体例子:

    PROGRAM my_test_X_T
    IMPLICIT NONE
    INTEGER::a = 123 , b = 55
    CHARACTER(len=5)::c = 'abcde'
    CHARACTER(len=3)::d = 'KJH'
    

WRITE(,100) a , b , c
WRITE(
,200) a

100 FORMAT( ’ ’ , T1 ,I3 , 1X , I2 , 1X , A5 , 1X , A3) ! 先跳到本行中第1个字符位置,然后逐一输出,每个变量用1个空格分隔
200 FORMAT( ’ ’ , T10 , I3) ! 先跳到本行中第10个字符位置,然后输出a变量

STOP
END PROGRAM my_test_X_T

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

相应结果为:

123 55 abcde
         123	

 
 
  • 1
  • 2
8) 垂直定位(/)
  1. 换行符,使用:

    • 可以或不使用逗号分隔换行符;
    • 多个/表示多次换行。
  2. 具体例子:

    PROGRAM my_test_1
    IMPLICIT NONE
    INTEGER::a = 123 , b = 55
    CHARACTER(len=5)::c = 'abcde'
    

WRITE(,100) a , b , c
WRITE(
,200) a , b , c
WRITE(*,300) a , b , c

100 FORMAT( ’ ’ ,T1 , I3 , / , I2 ,/ , A5 ) ! 使用换行符,可以采用逗号
200 FORMAT( ’ ’ ,T1 , I3 / I2 / A5 ) ! 换行符不采用逗号也可以
300 FORMAT( ’ ’ ,T1 , I3 , /// , I2 ,// , A5 ) ! 有几个换行符,表示可以换行几次

STOP
END PROGRAM my_test_1

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

相应结果为:

123     ! 第一次输出结果
55
abcde    
123     ! 第二次输出结果,与第一次结果一致
55
abcde
123     ! 第三次输出结果,多次换行

55

abcde

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
9) 格式描述符组重复使用
  1. 可以用括号,括号前输入重复次数,甚至可以嵌套,如下式:

    FORMAT( '  ' , I5 , 3(I5 , I6))  ! 3是重复次数
    FORMAT( '  ' , I5 , I5 , I6 , I5 , I6 , I5 , I6 )  ! 与上式等效
    
       
       
    • 1
    • 2
  2. 如果用*号替代重复次数,则表示括号里的内容可以无限次重复使用,直至没有可输出的数据为止,如下所示:

    FORMAT( '  ' , I5 , *(I5 , I6))  ! *是代表无限重复
    
       
       
    • 1
10) 注意事项
  1. 对于WRITEFORMAT语句,程序从变量列表格式描述符列表的最左端开始,从左往右扫描并一 一对应,如果变量与格式描述符不是同样的类型和次序,则运行时会报错,如下例子;

    INTEGER::a = 123 , b = 55
    CHARACTER(len=5)::c = 'abcde'
    WRITE(*,100) a , b , c 
    100 FORMAT( '  ' , I3 , I2 , I5 ) 	! I5是整数类型的,c变量是字符串,会报错
    
       
       
    • 1
    • 2
    • 3
    • 4

    注意,同时需要考虑格式重复的次数。

  2. 如果变量的个数大于格式描述符的个数,则可以重复调用,如下例所示:

    PROGRAM my_test_2
    IMPLICIT NONE
    INTEGER::a = 123 , b = 55 , c = 32
    

WRITE(*,100) a , b , c
100 FORMAT(I5)

STOP
END PROGRAM my_test_2

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

相应结果为:

  123
   55
   32

 
 
  • 1
  • 2
  • 3

4.READ使用对象

1) 整数输入(I
  1. 具体使用格式为:rIw ,具体用法见上述。
  2. 整数数值可以放置在区域内的任何位置,并且可以被正确读取和解释,最好用逗号隔开不同变量。
2) 实数输入(FEES
  1. 具体使用格式为:rFw.d ,具体用法见上述。
  2. 输入值最好是使用带小数点的实数,输入不带小数点的数值可能会出现错误。
3) 实数输入(L
  1. 具体使用格式为:rLw ,具体用法见上述。
  2. 输入数值为.TRUE..FALSE.,或者以TF开头的字符串。
4) 字符输入(A
  1. 具体使用格式为:rArAw,具体用法见上述。
  2. 使用方法与WRITE的方法相同。
5) 水平定位(XT
  1. X作用是跳过输入数据中不想读取的区域;
  2. T作用是跳到某一位置。
6) 垂直定位(/
  1. 可以理解成为,换行选取所有的变量参数。
7) 注意事项
  1. 常规用法是变量个数和格式描述符个数相同,扫描顺序、重复次数及括号的使用与WRITE相一致。

  2. 当变量与格式描述符的个数不相一致时:

    • 如果READ语句在格式结束前用完了所有的变量(变量小于格式),则格式的使用就停在最后读取的变量后面,下一个READ语句将从一个新的输入缓冲区开始,原来的输入缓冲区(即上一个READ语句输入的数值)的数据将被丢弃,例子:

      PROGRAM my_test_read
      IMPLICIT NONE
      INTEGER::i , j ,k , l , m
      

READ(,100) i , j
READ(
,100) k , l , m

100 FORMAT( 5I2 )

WRITE (*,100) i , j ,k , l , m

STOP
END PROGRAM my_test_read

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

键盘输入为:

1,2,3,4,5
6,7,8,9,10

 
 
  • 1
  • 2

相应的结果为:

 1 2 6 7 8	

 
 
  • 1

总结:变量用完了,格式描述符剩余,一个READ对应一个输入缓冲区,如果要再次建立输入缓冲区,则要再使用READ语句,新的READ会重新读取新的输入缓冲区,而将上一次的输入缓冲区的数据丢弃。

  1. 如果READ语句在使用完格式描述符后仍剩余变量(变量多于格式),则程序会自动丢弃当前的输入缓冲区,自动建立新的输入缓冲区(不需要READ语句),并在格式中最右边不带重复次数的开始括号处重新开始,如下例子1:

    PROGRAM my_test_read1
    IMPLICIT NONE
    INTEGER::i , j ,k , l , m
    

READ(*,100) i , j , k , l , m

100 FORMAT( T1, I2 , (T5 , 2I2) ) ! 第二次的输入缓冲区从右侧括号的T5开始
WRITE (*,100) i , j ,k , l , m

STOP
END PROGRAM my_test_read1

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

键盘输入为:

1,2,3,4,5
6,7,8,9,10

 
 
  • 1
  • 2

相应的结果为:

 1   3 4
     8 9

 
 
  • 1
  • 2

例子2:

PROGRAM my_test_read2
IMPLICIT NONE
INTEGER::i , j ,k , l , m

READ(,200) i , j , k , l , m
200 FORMAT( T1, I2 , T5 , 2I2 ) ! 里面没有括号,从左往右依次读取
WRITE (
,200) i , j ,k , l , m

STOP
END PROGRAM my_test_read2

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

键盘输入为:

1,2,3,4,5
6,7,8,9,10

 
 
  • 1
  • 2

相应的结果为:

 1   3 4
 6   8

 
 
  • 1
  • 2
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值