fortran输入输出语句的格式说明可以是字符表达式。只要该表达式在语句执行时产生一个语法完整的格式字符串,例如(A,F0.3),运行库会按其中的编辑描述符处理数据。
因此可以把字段宽度、小数位数或重复次数等运行时参数写入字符变量,再将该变量用作格式。动态格式改变的是数据的外部表示,不会改变变量本身的值、类型或存储精度。
适用场景
动态格式适合输出布局由运行时配置决定的场景,例如用户选择计算报告保留几位小数、不同数据集需要不同列宽,或表格列数在运行时才确定。布局始终固定时应直接使用内联格式或FORMAT语句,以免增加构造和校验字符串的复杂度。
语法结构
character(len=...) :: runtimeFormat
write (runtimeFormat, buildFormat) runtimeParameters
write (unit, runtimeFormat) outputList
- 第一条write是内部文件输出:它把数据写入字符变量,而不是终端或磁盘文件。
- 字符变量最终必须包含外层括号以及合法的编辑描述符;格式不完整或不合法通常会导致运行时输入输出错误。
- 字符变量要有足够长度。使用时可通过trim查看实际生成的格式。
本文代码
! 根据运行时输入构造格式,控制测量结果的小数位数。
program dynamicFormatDemo
implicit none
integer :: decimalPlaces, readStatus
real :: voltage
character(len=32) :: valueFormat
voltage = 12.34567
decimalPlaces = -1
print "(A)", "请输入电压的小数位数(0到6):"
read (*, *, iostat=readStatus) decimalPlaces
if (readStatus /= 0 .or. decimalPlaces < 0 .or. decimalPlaces > 6) then
error stop "小数位数必须是0到6之间的整数"
end if
write (valueFormat, "('(A,F0.',I0,',1X,A)')") decimalPlaces
print "(A,A)", "生成的格式:", trim(valueFormat)
write (*, valueFormat) "电压:", voltage, "V"
end program dynamicFormatDemo
编译运行
(base) hong@hongdeMacBook-Pro 042.dynamicFormat % gfortran -Wall -Wextra -std=f2018 exampleDynamicFormat.f90
(base) hong@hongdeMacBook-Pro 042.dynamicFormat % printf '2\n' | ./a.out
请输入电压的小数位数(0到6):
生成的格式:(A,F0.2,1X,A)
电压:12.35 V
(base) hong@hongdeMacBook-Pro 042.dynamicFormat % printf '5\n' | ./a.out
请输入电压的小数位数(0到6):
生成的格式:(A,F0.5,1X,A)
电压:12.34567 V
现象分析
第一次运行输入2,内部write把整数2嵌入固定片段,生成(A,F0.2,1X,A),电压因而显示为12.35V。
第二次输入5,程序生成(A,F0.5,1X,A),同一个变量显示为12.34567V。说明小数位数是由运行时输入控制而不在代码的输出语句中写死。
两次运行中的voltage都没有被修改;两位小数结果只是格式化时的舍入显示。即先把输入限制在0到6之间,避免构造出不符合本例要求的格式,也防止结果超出预留的显示范围。
核心知识点
- 格式说明可以来自字符变量或其他字符表达式,其内容可在运行时生成。
- 内部write是构造动态格式的一种实用方法,它把运行时参数转换并写入字符变量。
- 动态格式必须包含合法、完整的格式规范,程序还应限制参与构造的参数并预留足够的字符长度。
- 格式控制输出形式,不改变原变量的数值和存储精度。