目录
Fortran中的 I/O 格式化用法
格式化:用来指定程序打印输出变量的具体形式,如位置、有效位数等。
READ(* , *)
和WRITE(* , *)
括号中第二个*
号均表示采用自由格式,此时输出中经常有多个额外的空格,且格式往往不统一。因此,可以采用格式化输出模式(采用格式描述符),来指定具体样式。
1.用法(READ
和WRITE
一致)
-
采用
FORMAT
语句,并且结合语句标号(行号)来使用,如:INTEGER:: a = 123 WRITE(*,100) a 100 FORMAT( ' ' , I5 ) ! 100是语句标号,将a变量用I5形式输出; ' '前面放置空格,实际上可以不要
- 1
- 2
- 3
-
直接在第二个
*
号中指定具体样式,如: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
)
-
具体使用格式为:
rIw
或rIw.m
,具体用法见上述。 -
须注意:
- 整数在输出域内为右对齐;
- 字符个数超出域宽,输出时会用
*
号填充; I0
是特殊描述符,可以输出任意整数,而不需担心域宽不足。
-
具体例子:
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
)
-
具体使用格式为:
rFw.d
,具体用法见上述。 -
须注意:
- 实数在输出域内为右对齐;
- 字符个数超出域宽,输出时会用
*
号填充; - 当字符小于域宽时,整数部分在左侧用
空格
填充,小数部分在右侧用0
填充。
-
具体例子:
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
)
-
具体使用格式为:
rEw.d
,具体用法见上述。 -
须注意:
- 不是标准的科学计数法,代表(0.1~1)×10n;
- 域宽需要满足一定的条件:
w≥d+7
,如精确至2位小数则有±0.ddE±aa
,共9位字符;精确至5位小数则有±0.dddddE±aa
,共12位字符。
特殊时候,数字前面的±
和0
在某种情况下可以省略(见下述具体例子),因此该条件不是硬性条件,但由于能够满足所有情况且可视化效果较好,建议使用该条件; - 同理,字符位数超出域宽时,会用
*
号填充。
-
具体例子:
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
)
-
具体使用格式为:
rESw.d
,具体用法见上述。 -
须注意:
- 标准的科学计数法,代表(1~10)×10n;
- 具体用法与
E
相同,域宽满足一定条件:w≥d+7
,该条件同样不是十分严格,但是均能避免不利情况,因此建议使用该条件; - 同理,字符位数超出域宽时,会用
*
号填充。
-
具体例子:
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
)
-
具体使用格式为:
rLw
,具体用法见上述。 -
须注意:
- 输出结果为
T
或F
; L0
会报错,因此总是可以输出结果。
- 输出结果为
-
具体例子:
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
)
-
具体使用格式为:
rA
或rAw
,具体用法见上述。 -
须注意:
- 输出结果为整个字符或切片后的字符;
A0
会报错,因此总是可以输出结果。
-
具体例子:
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) 水平定位(X
和T
)
-
具体使用格式为:
nX
和Tc
,具体用法见上述。 -
须注意:
nX
表示在变量间插入n
个空格;Tc
表示将输出位置移动到本行中的第c
个字节。
-
具体例子:
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) 垂直定位(/
)
-
换行符,使用:
- 可以或不使用逗号分隔换行符;
- 多个
/
表示多次换行。
-
具体例子:
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) 格式描述符组重复使用
-
可以用括号,括号前输入重复次数,甚至可以嵌套,如下式:
FORMAT( ' ' , I5 , 3(I5 , I6)) ! 3是重复次数 FORMAT( ' ' , I5 , I5 , I6 , I5 , I6 , I5 , I6 ) ! 与上式等效
- 1
- 2
-
如果用
*
号替代重复次数,则表示括号里的内容可以无限次重复使用,直至没有可输出的数据为止,如下所示:FORMAT( ' ' , I5 , *(I5 , I6)) ! *是代表无限重复
- 1
10) 注意事项
-
对于
WRITE
和FORMAT
语句,程序从变量列表和格式描述符列表的最左端开始,从左往右扫描并一 一对应,如果变量与格式描述符不是同样的类型和次序,则运行时会报错,如下例子;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
注意,同时需要考虑格式重复的次数。
-
如果变量的个数大于格式描述符的个数,则可以重复调用,如下例所示:
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
)
- 具体使用格式为:
rIw
,具体用法见上述。 - 整数数值可以放置在区域内的任何位置,并且可以被正确读取和解释,最好用逗号隔开不同变量。
2) 实数输入(F
、E
、ES
)
- 具体使用格式为:
rFw.d
,具体用法见上述。 - 输入值最好是使用带小数点的实数,输入不带小数点的数值可能会出现错误。
3) 实数输入(L
)
- 具体使用格式为:
rLw
,具体用法见上述。 - 输入数值为
.TRUE.
和.FALSE.
,或者以T
和F
开头的字符串。
4) 字符输入(A
)
- 具体使用格式为:
rA
或rAw
,具体用法见上述。 - 使用方法与
WRITE
的方法相同。
5) 水平定位(X
和T
)
X
作用是跳过输入数据中不想读取的区域;T
作用是跳到某一位置。
6) 垂直定位(/
)
- 可以理解成为,换行选取所有的变量参数。
7) 注意事项
-
常规用法是变量个数和格式描述符个数相同,扫描顺序、重复次数及括号的使用与
WRITE
相一致。 -
当变量与格式描述符的个数不相一致时:
-
如果
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
会重新读取新的输入缓冲区,而将上一次的输入缓冲区的数据丢弃。
-
如果
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