“(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