【问题标题】:Output formatting with the write statement via gfortran [duplicate]通过 gfortran 使用 write 语句输出格式[重复]
【发布时间】:2021-01-23 02:46:50
【问题描述】:

我用过 Intel fortran 编译器,它支持使用 <n> 扩展,比如

write(*, '(<n>(2I4))') (i, 2*i, i=1,n)

为了说明,我给出一个s1_fprint.f90子程序如下

subroutine fprint(name,bb)

IMPLICIT NONE
character(len=*), intent(in) :: name
real, intent(in) :: bb(:,:)
integer :: column=10
integer i,j,k,m,n

n = size(bb,1)
m = size(bb,2)

write(*,'(1a)')name
do k=0,m/column-1
    write(*, '(1x,<column>i16)')(i,i=k*column+1,(k+1)*column)
    write(*,'(1i10,<column>f)')(i,(bb(i,j),j=k*column+1,(k+1)*column),i=1,n)
    write(*,'(/)')
end do
if(mod(m,column)/=0)then
    write(*, '(1x,<m-m/column*column>i16)')(i,i=m/column*column+1,m)
    write(*,'(1i10,<m-m/column*column>f)')(i,(bb(i,j),j=m/column*column+1,m),i=1,n)
    write(*,'(/)')
endif

end subroutine fprint

现在,我将 Intel fortran 编译器更改为 gfortran,然后进行测试 (t1_useSur.f90) gfortran 中的上述子程序如下:

program main

implicit none
real :: A(2,3) = reshape([1.2, 2.3, 3.4, 4.5, 5.6, 6.7], [2,3])

call fprint('A',A)

end program main

这应该向我们展示类似的东西

A
            1              2              3
    1      1.2000000      3.4000001      5.5999999
    2      2.3000000      4.5000000      6.6999998

但是,当我在 gfortran 编译器中运行时

gfortran t1_useSur.f90 s1_fprint.f90 -o out
./out

有很多错误

.\s1_fprint.f90:14.17:

    write(*, '(1x,<column>i16)')(i,i=k*column+1,(k+1)*column)
                1
Error: Unexpected element '<' in format string at (1)
.\s1_fprint.f90:15.19:

    write(*,'(1i10,<column>f)')(i,(bb(i,j),j=k*column+1,(k+1)*column),i=1,n)
                1
Error: Unexpected element '<' in format string at (1)
.\s1_fprint.f90:19.17:

    write(*, '(1x,<m-m/column*column>i16)')(i,i=m/column*column+1,m)
                1
Error: Unexpected element '<' in format string at (1)
.\s1_fprint.f90:20.19:

    write(*,'(1i10,<m-m/column*column>f)')(i,(bb(i,j),j=m/column*column+1,m),i=
                1
Error: Unexpected element '<' in format string at (1)

由于gfortran不支持&lt;n&gt;扩展,如何解决这些问题?

【问题讨论】:

  • 关于您之前的补充问题,m/column-1 将小于零,不会通过循环。你只需要m-1
  • 我会试试的。谢谢你的帮助@francescalus

标签: fortran gfortran intel-fortran


【解决方案1】:

接近欺骗Variable format statement when porting from Intel to GNU gfortran

对于像(i,i=...) 这样的一维案例:

  • 如果您拥有(或获得)支持 F08 的 gfortran 版本,浏览 https://gcc.gnu.org/onlinedocs/ 似乎是 4.6.4 左右,请使用 * 作为计数,如 (1x,*i16)

  • 否则,请使用旧的the-hillsF77 技巧:由于格式重复或“超出”数据列表的项目将被忽略,因此只需使用至少与这里的数据将永远是(但不超过 HUGE(0))(1x,10i16) 实际上就足够了,但像 (1x,999i16) 这样的东西让它更明显

  • 或者,如果您喜欢额外的工作,可以像下面的 2-dim 外壳那样即时完成

对于像(i,(bb(i,j),j=...),i=...) 这样的二维情况,目前使用格式循环来插入记录中断:

  • 通过将记录分成单独的 WRITE 来减少 1-dim:
    do i=...
        write(*,'(1i10,*f)') i,(bb(i,j),j=...)
    end do !i
  • 即时生成正确的计数:
    character(len=20) fmt
    ...
    write(fmt,'(a,i0,a)') '(1i10,', numcols_expression, 'f)'
    write(*, trim(fmt)) (i,(bb(i,j),j=...),i=...)
    ... or ...
    write(fmt,'(i0)') numcols_expression
    write(*, '(1i10,'//trim(fmt)//'f)') (i,bb(i,j),j=...),i=...)

PS:你实际上并不需要1i10,只需要i10,但为了保持一致,我把它留了下来。另外,我可能会这样做,而不是完整块的循环,然后是部分块的 if,它们必须保持同步:

    do k=1,m,column
      l=min(k+column-1,m)
      ... print chunk for i=k,l (numcols is l-k+1) ...
    end do !k

【讨论】:

  • 谢谢!我按照您的提示测试代码,请参阅上面我重新编辑的内容。它仍然存在一些问题。顺便说一句,PC 上的gfortran --version 命令给出了GNU Fortran (x86_64-posix-seh, Built by MinGW-W64 project) 4.9.3 Copyright (C) 2015 Free Software Foundation, Inc. @dave_thompson_085
  • 请不要编辑您的问题来提出新问题 - 只需提出适当的新问题。它让其他人更容易搜索
  • 知道了,很抱歉。谢谢你提醒我这个@Ian Bush@Ian Bush
猜你喜欢
  • 2014-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多