“(23A, 1X, F4.1, 2X, 1A)”格式的输出不正确
Incorrect output with '(23A, 1X, F4.1, 2X, 1A)' format
我正在编写自 1989 年以来的第一个 FORTRAN 程序(使用 FORTRAN77),这是我对现代 FORTRAN 的介绍。我在格式化写入语句时遇到问题。具体来说,在读取一个 REAL 值和一个 CHARACTER 之后,我然后使用格式化的 WRITE 语句来允许用户查看输入。我可以使用未格式化的 WRITE 语句,一切都很好,但是,如果我使用简单的格式化语句,生成的输出是垃圾。以下是我的MWE:
! MWE program testing formatted write of a real number
!
! bash cmd line gfortran-9 -o MWE_formated_write MWE_formated_write.f95
! build environment:
! Kubuntu 21.04 / kernel 5.11.0-34-generic
! GNU Fortran (Ubuntu 9.3.0-23ubuntu2) 9.3.0
! laptop w/ 4x Intel i5-5200U @ 2.2 GHz w/ 8 GiB ram
!
program MWE_formated_write
!
implicit none
real :: temp_input ! input temperature
character(len=1) :: temp_input_units ! input temperature unit, [F]/[C]/[R]/[K]
!
! Get input temperature and temperature units
!
write(*,*) "Enter the temperature and units F/C/R/K: "
read(*,*) temp_input, temp_input_units
!
! verify the input temperature and temperature units
!
write(*, *) " You entered (raw):", temp_input, temp_input_units
write(*, '(23A, 1X, F4.1, 2X, 1A)') "You entered (formated):", temp_input, temp_input_units
!
stop
end program MWE_formated_write
和输出捕获:
joseph@bohr:~/Projects$ gfortran-9 -o MWE_formated_write MWE_formated_write.f95
joseph@bohr:~/Projects$ ./MWE_formated_write
Enter the temperature and units F/C/R/K:
95 F
You entered (raw): 95.0000000 F
You entered (formated):�BF
我希望第二行输出“您输入(格式化):95.1 F”。
您的代码中存在一个简单的错误,格式字段显示为 23A
。这意味着有 23 个字符对象要在 stdout 上打印,而实际上只有 1 个。我想你的意思是宽度为 23 的单个字符对象。但对于长度为 23 的输出字符串,即使是 23 也可能太小了23。也许像 30 这样的数字会更合适。然后是实数的宽度问题,要求只有 4,这在大多数情况下太窄了。一般来说,指定宽度至少比指定的精度(这里是 1)多 7 个字符是好的。以下解决了这两个问题。但更好的是使用现代 Fortran 通用描述符 g0
,它会自动处理所有类型的对象。 g0
编辑描述符的完整描述相当冗长,但它有效地消除了用户指定记录宽度和类型的负担,并将其留给编译器。 g0.d
规范意味着如果编译器遇到 real
数字,则应将输出记录的精度设置为小数点后 d
位,否则忽略一个字符或整数输出。
格式中的 ' '
强制编译器用一个白色 space 分隔每个输出记录。将其更改为 ','
,它将成为一组以逗号分隔的值 (CSV)。
格式中的 :
有一个有趣的故事,它是 Fortran 2008 标准中的拼写错误,但现在可以跳过最后一个分隔符的添加,在本例中是一个白色space " "
.
program MWE_formated_write
use iso_fortran_env, only: RK => real64
implicit none
real(RK) :: temp_input ! input temperature
character(len=1) :: temp_input_units ! input temperature unit, [F]/[C]/[R]/[K]
! Get input temperature and temperature units
write(*,"(*(g0.10,:,' '))") "Enter the temperature and units F/C/R/K: "
read(*,*) temp_input, temp_input_units
write(*,*) temp_input, temp_input_units
! verify the input temperature and temperature units
write(*,"(*(g0,:,' '))") " You entered (raw):", temp_input, temp_input_units
write(*, '(A30, 1X, F10.1, 2X, 1A)') "You entered (formated):", temp_input, temp_input_units
end program MWE_formated_write
这是使用 Intel ifort 的程序输出:
Enter the temperature and units F/C/R/K: 123 C
123.000000000000 C
You entered (raw): 123.0000000000000 C
You entered (formated): 123.0 C
我正在编写自 1989 年以来的第一个 FORTRAN 程序(使用 FORTRAN77),这是我对现代 FORTRAN 的介绍。我在格式化写入语句时遇到问题。具体来说,在读取一个 REAL 值和一个 CHARACTER 之后,我然后使用格式化的 WRITE 语句来允许用户查看输入。我可以使用未格式化的 WRITE 语句,一切都很好,但是,如果我使用简单的格式化语句,生成的输出是垃圾。以下是我的MWE:
! MWE program testing formatted write of a real number
!
! bash cmd line gfortran-9 -o MWE_formated_write MWE_formated_write.f95
! build environment:
! Kubuntu 21.04 / kernel 5.11.0-34-generic
! GNU Fortran (Ubuntu 9.3.0-23ubuntu2) 9.3.0
! laptop w/ 4x Intel i5-5200U @ 2.2 GHz w/ 8 GiB ram
!
program MWE_formated_write
!
implicit none
real :: temp_input ! input temperature
character(len=1) :: temp_input_units ! input temperature unit, [F]/[C]/[R]/[K]
!
! Get input temperature and temperature units
!
write(*,*) "Enter the temperature and units F/C/R/K: "
read(*,*) temp_input, temp_input_units
!
! verify the input temperature and temperature units
!
write(*, *) " You entered (raw):", temp_input, temp_input_units
write(*, '(23A, 1X, F4.1, 2X, 1A)') "You entered (formated):", temp_input, temp_input_units
!
stop
end program MWE_formated_write
和输出捕获:
joseph@bohr:~/Projects$ gfortran-9 -o MWE_formated_write MWE_formated_write.f95
joseph@bohr:~/Projects$ ./MWE_formated_write
Enter the temperature and units F/C/R/K:
95 F
You entered (raw): 95.0000000 F
You entered (formated):�BF
我希望第二行输出“您输入(格式化):95.1 F”。
您的代码中存在一个简单的错误,格式字段显示为 23A
。这意味着有 23 个字符对象要在 stdout 上打印,而实际上只有 1 个。我想你的意思是宽度为 23 的单个字符对象。但对于长度为 23 的输出字符串,即使是 23 也可能太小了23。也许像 30 这样的数字会更合适。然后是实数的宽度问题,要求只有 4,这在大多数情况下太窄了。一般来说,指定宽度至少比指定的精度(这里是 1)多 7 个字符是好的。以下解决了这两个问题。但更好的是使用现代 Fortran 通用描述符 g0
,它会自动处理所有类型的对象。 g0
编辑描述符的完整描述相当冗长,但它有效地消除了用户指定记录宽度和类型的负担,并将其留给编译器。 g0.d
规范意味着如果编译器遇到 real
数字,则应将输出记录的精度设置为小数点后 d
位,否则忽略一个字符或整数输出。
格式中的 ' '
强制编译器用一个白色 space 分隔每个输出记录。将其更改为 ','
,它将成为一组以逗号分隔的值 (CSV)。
格式中的 :
有一个有趣的故事,它是 Fortran 2008 标准中的拼写错误,但现在可以跳过最后一个分隔符的添加,在本例中是一个白色space " "
.
program MWE_formated_write
use iso_fortran_env, only: RK => real64
implicit none
real(RK) :: temp_input ! input temperature
character(len=1) :: temp_input_units ! input temperature unit, [F]/[C]/[R]/[K]
! Get input temperature and temperature units
write(*,"(*(g0.10,:,' '))") "Enter the temperature and units F/C/R/K: "
read(*,*) temp_input, temp_input_units
write(*,*) temp_input, temp_input_units
! verify the input temperature and temperature units
write(*,"(*(g0,:,' '))") " You entered (raw):", temp_input, temp_input_units
write(*, '(A30, 1X, F10.1, 2X, 1A)') "You entered (formated):", temp_input, temp_input_units
end program MWE_formated_write
这是使用 Intel ifort 的程序输出:
Enter the temperature and units F/C/R/K: 123 C
123.000000000000 C
You entered (raw): 123.0000000000000 C
You entered (formated): 123.0 C