【Fortran】I/O(WRITE 和 READ)格式化输出、输入(初级)

目录

    • Fortran中的 I/O 格式化用法
      • 1.用法(`READ`和`WRITE`一致)
      • 2.格式描述符
      • 3.`WRITE`使用对象
        • 1) 整数输出(`I`)
        • 2) 实数输出(`F`)
        • 3) 实数输出(`E`)
        • 4) 实数输出(`ES`)
        • 5) 逻辑输出(`L`)
        • 6) 字符输出(`A`)
        • 7) 水平定位(`X`和`T`)
        • 8) 垂直定位(`/`)
        • 9) 格式描述符组重复使用
        • 10) 注意事项
      • 4.`READ`使用对象
        • 1) 整数输入(`I`)
        • 2) 实数输入(`F`、`E`、`ES`)
        • 3) 实数输入(`L`)
        • 4) 字符输入(`A`)
        • 5) 水平定位(`X`和`T`)
        • 6) 垂直定位(`/`)
        • 7) 注意事项


Fortran中的 I/O 格式化用法

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

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


1.用法(READWRITE一致)

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

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

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

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
    

    相应结果为:

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

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
    

    相应结果为:

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

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
    

    相应结果为:

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

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.23E+02 0.00E+00 5.2456E+04
     ********0.00E+00 5.245600E+04
     *******.00E+00 5.245600E+04	
    

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
    

    相应结果为:

        T    F
    TF
    

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	
    

    相应结果为:

    This is my_test_A.
           This is my_test_A.
    This i	
    

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	
    

    相应结果为:

    123 55 abcde
             123	
    

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	
    

    相应结果为:

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

9) 格式描述符组重复使用

  1. 可以用括号,括号前输入重复次数,甚至可以嵌套,如下式:

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

    FORMAT( '  ' , I5 , *(I5 , I6))  ! *是代表无限重复
    

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变量是字符串,会报错
    

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

  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
    

    相应结果为:

      123
       55
       32
    

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
      

      相应的结果为:

       1 2 6 7 8	
      

      总结:变量用完了,格式描述符剩余,一个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
      

      相应的结果为:

       1   3 4
           8 9
      

      例子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   3 4
       6   8
      

你可能感兴趣的:(fortran)