通过 gfortran 使用 write 语句输出格式化
Output formatting with the write statement via gfortran
我习惯了支持使用 <n>
扩展的 Intel fortran 编译器,例如
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 不支持 <n>
扩展,如何解决这些问题?
近乎欺骗Variable format statement when porting from Intel to GNU gfortran
对于像 (i,i=...)
这样的 1-dim 情况:
如果你有(或得到)支持F08的gfortran版本,浏览https://gcc.gnu.org/onlinedocs/似乎是4.6.4左右,用*
作为计数喜欢 (1x,*i16)
否则,使用旧的-the-hillsF77 技巧:由于格式重复或项目'beyond' 数据列表被忽略,只需使用至少与数据一样大的重复计数(但不超过 HUGE(0)),这里 (1x,10i16)
实际上就足够了,但像 (1x,999i16)
这样的东西使它更加明显
或者如果您喜欢额外的工作,可以像下面的 2-dim 案例一样即时进行
对于像 (i,(bb(i,j),j=...),i=...)
这样目前使用格式循环插入记录中断的 2-dim 案例:
- 通过将记录分成单独的 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
我习惯了支持使用 <n>
扩展的 Intel fortran 编译器,例如
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 不支持 <n>
扩展,如何解决这些问题?
近乎欺骗Variable format statement when porting from Intel to GNU gfortran
对于像 (i,i=...)
这样的 1-dim 情况:
如果你有(或得到)支持F08的gfortran版本,浏览https://gcc.gnu.org/onlinedocs/似乎是4.6.4左右,用
*
作为计数喜欢(1x,*i16)
否则,使用旧的-
the-hillsF77 技巧:由于格式重复或项目'beyond' 数据列表被忽略,只需使用至少与数据一样大的重复计数(但不超过 HUGE(0)),这里(1x,10i16)
实际上就足够了,但像(1x,999i16)
这样的东西使它更加明显或者如果您喜欢额外的工作,可以像下面的 2-dim 案例一样即时进行
对于像 (i,(bb(i,j),j=...),i=...)
这样目前使用格式循环插入记录中断的 2-dim 案例:
- 通过将记录分成单独的 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