Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Fortran字符格式字符串作为子例程参数_Fortran_Gfortran - Fatal编程技术网

Fortran字符格式字符串作为子例程参数

Fortran字符格式字符串作为子例程参数,fortran,gfortran,Fortran,Gfortran,我正在努力阅读文本字符串。我正在使用gfortran 4.9.2 下面我编写了一个小的子程序,我想在其中提交write格式作为参数 理想情况下,我希望能够与您联系 call printarray(mat1, "F8.3") 例如,以该格式打印矩阵mat1。列数应在子例程内自动确定 subroutine printarray(x, udf_temp) implicit none real, dimension(:,:), intent(in) :: x ! array to

我正在努力阅读文本字符串。我正在使用gfortran 4.9.2

下面我编写了一个小的子程序,我想在其中提交write格式作为参数

理想情况下,我希望能够与您联系

call printarray(mat1, "F8.3")
例如,以该格式打印矩阵mat1。列数应在子例程内自动确定

subroutine printarray(x, udf_temp)
implicit none
real, dimension(:,:), intent(in) :: x           ! array to be printed     
integer, dimension(2)            :: dims        ! array for shape of x
integer                          :: i, j
character(len=10)                :: udf_temp    ! user defined format, eg "F8.3, ...
character(len = :), allocatable  :: udf         ! trimmed udf_temp
character(len = 10)              :: udf2
character(len = 10)              :: txt1, txt2
integer                          :: ncols       ! no. of columns of array
integer                          :: udf_temp_length

udf_temp_length = len_trim(udf_temp)
allocate(character(len=udf_temp_length) :: udf)

dims = shape(x)
ncols = dims(2)
write (txt1, '(I5)') ncols
udf2 = trim(txt1)//adjustl(udf)
txt2 = "("//trim(udf2)//")"

do i = 1, dims(1)
   write (*, txt2) (x(i, j), j = 1, dims(2))        ! this is line 38
end do

end suroutine printarray
当我设置len=10时:

character(len=10) :: udf_temp
我发现编译错误:

call printarray(mat1, "F8.3")
                      1
Warning: Character length of actual argument shorter than of dummy argument 'udf_temp' (4/10) at (1)
当我设置
len=*

character(len=*) :: udf_temp
它可编译,但在运行时:

At line 38 of file where2.f95 (unit = 6, file = 'stdout')
Fortran runtime error: Unexpected element '(    8
我做错了什么? 有没有更简洁的方法可以做到这一点?

除了实际的错误(不使用输入参数),整个过程可以做得更简单:

  subroutine printarray(m,f)
  implicit none
  character(len=*)f
  real m(:,:)
  character*10 n
  write(n,'(i0)')size(m(1,:))
  write(*,'('//n//f//')')transpose(m)
  end subroutine
  end
注意:不需要循环构造,因为fortran将在达到格式指定的数据长度时自动写入整个数组、换行

或者,您可以使用循环构造,然后可以在格式中使用“*”重复计数,从而避免内部写入来构造格式字符串

  subroutine printarray(m,f)
  implicit none
  character(len=*)f
  real m(:,:)
  integer :: i
  do i=1,size(m(:,1))
     write(*,'(*('//f//'))')m(i,:)
  enddo
  end subroutine
  end
除了实际的错误(不使用输入参数),整个过程可以做得更简单:

  subroutine printarray(m,f)
  implicit none
  character(len=*)f
  real m(:,:)
  character*10 n
  write(n,'(i0)')size(m(1,:))
  write(*,'('//n//f//')')transpose(m)
  end subroutine
  end
注意:不需要循环构造,因为fortran将在达到格式指定的数据长度时自动写入整个数组、换行

或者,您可以使用循环构造,然后可以在格式中使用“*”重复计数,从而避免内部写入来构造格式字符串

  subroutine printarray(m,f)
  implicit none
  character(len=*)f
  real m(:,:)
  integer :: i
  do i=1,size(m(:,1))
     write(*,'(*('//f//'))')m(i,:)
  enddo
  end subroutine
  end

下面是我将尝试解决的问题的摘要:您希望有一个子例程,它将以指定的格式打印指定的二维数组,这样每一行都打印在一行上。例如,假设我们有真实的数组:

real, dimension(2,8) :: x
x = reshape([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16], shape=[2,8], order=[2,1])

! Then the array is:
!    1.000   2.000   3.000   4.000   5.000   6.000   7.000   8.000
!    9.000  10.000  11.000  12.000  13.000  14.000  15.000  16.000
我们希望使用格式
“F8.3”
,它打印字段宽度为8和3位小数的浮点值(real)

现在,在子例程中创建格式时,您犯了几个错误。首先,尝试使用
udf
创建
udf2
字符串。这是一个问题,因为尽管您已经分配了
udf
,但没有分配任何内容(在@francescalus的评论中指出)。因此,您会看到报告的错误消息:
Fortran运行时错误:意外元素'(8

在下面,我做了几个简化的更改,并演示了几个(稍微)不同的技术。如图所示,我建议使用
*
来表示可以无限次地应用该格式,直到访问了输出列表的所有元素。当然,明确说明应用该格式的次数(即,
“(8F8.3)”
,而不是
”(*(F8.3))“
)很好,但后者的工作量稍微少一些

program main
    implicit none

    real, dimension(2,8) :: x
    character(len=:), allocatable :: udf_in

    x = reshape([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16], shape=[2,8], order=[2,1])
    udf_in = "F8.3"
    call printarray(x, udf_in)

contains
    subroutine printarray(x, udf_in)
        implicit none
        real, dimension(:,:), intent(in) :: x
        character(len=*), intent(in)     :: udf_in

        integer                        :: ncols         ! size(x,dim=2)
        character(len=10)              :: ncols_str     ! ncols, stringified
        integer, dimension(2)          :: dims          ! shape of x
        character(len=:), allocatable  :: udf0, udf1    ! format codes
        integer                        :: i, j          ! index counters

        dims = shape(x)                                 ! or just use: ncols = size(x, dim=2)
        ncols = dims(2)

        write (ncols_str, '(i0)') ncols                 ! use 'i0' for min. size

        udf0 = "(" // ncols_str // udf_in // ")"        ! create string: "(8F8.3)"
        udf1 = "(*(" // udf_in // "))"                  ! create string: "(*(F8.3))"

        print *, "Version 1:"
        do i = 1, dims(1)
            write (*, udf0) (x(i, j), j = 1,ncols)      ! implied do-loop over j.
        end do

        print *, "Version 2:"
        do i = 1, dims(1)
            ! udf1: "(*(F8.3))"
            write (*, udf1) (x(i, j), j = 1,ncols)      ! implied do-loop over j
        end do

        print *, "Version 3:"
        do i = 1, size(x,dim=1)                         ! no need to create nrows/ncols vars.
            write(*, udf1) x(i,:)                       ! let the compiler handle the extents.
        enddo

    end subroutine printarray
end program main


观察:最终do循环(“版本3”)非常简单。它不需要显式的NCOL计数,因为
*
会自动处理它。由于它的简单性,实际上根本不需要子例程。

下面是我将尝试解决的问题的摘要:您想要一个子例程,它将使用sp打印指定的二维数组指定的格式,每行打印在一行上。例如,假设我们有真实数组:

real, dimension(2,8) :: x
x = reshape([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16], shape=[2,8], order=[2,1])

! Then the array is:
!    1.000   2.000   3.000   4.000   5.000   6.000   7.000   8.000
!    9.000  10.000  11.000  12.000  13.000  14.000  15.000  16.000
我们希望使用格式
“F8.3”
,它打印字段宽度为8和3位小数的浮点值(real)

现在,您在子例程中创建格式时犯了几个错误。首先,您尝试使用
udf
创建
udf2
字符串。这是一个问题,因为尽管您分配了
udf
的大小,但没有为其分配任何内容(在@francescalus的评论中指出)。因此,您会看到报告的错误消息:
Fortran运行时错误:意外元素’(8

在下面,我做了几个简化的更改,并演示了几个(稍微)不同的技术。如图所示,我建议使用
*
来表示可以无限次地应用该格式,直到访问了输出列表的所有元素。当然,明确说明应用该格式的次数(即,
“(8F8.3)”
,而不是
”(*(F8.3))“
)很好,但后者的工作量稍微少一些

program main
    implicit none

    real, dimension(2,8) :: x
    character(len=:), allocatable :: udf_in

    x = reshape([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16], shape=[2,8], order=[2,1])
    udf_in = "F8.3"
    call printarray(x, udf_in)

contains
    subroutine printarray(x, udf_in)
        implicit none
        real, dimension(:,:), intent(in) :: x
        character(len=*), intent(in)     :: udf_in

        integer                        :: ncols         ! size(x,dim=2)
        character(len=10)              :: ncols_str     ! ncols, stringified
        integer, dimension(2)          :: dims          ! shape of x
        character(len=:), allocatable  :: udf0, udf1    ! format codes
        integer                        :: i, j          ! index counters

        dims = shape(x)                                 ! or just use: ncols = size(x, dim=2)
        ncols = dims(2)

        write (ncols_str, '(i0)') ncols                 ! use 'i0' for min. size

        udf0 = "(" // ncols_str // udf_in // ")"        ! create string: "(8F8.3)"
        udf1 = "(*(" // udf_in // "))"                  ! create string: "(*(F8.3))"

        print *, "Version 1:"
        do i = 1, dims(1)
            write (*, udf0) (x(i, j), j = 1,ncols)      ! implied do-loop over j.
        end do

        print *, "Version 2:"
        do i = 1, dims(1)
            ! udf1: "(*(F8.3))"
            write (*, udf1) (x(i, j), j = 1,ncols)      ! implied do-loop over j
        end do

        print *, "Version 3:"
        do i = 1, size(x,dim=1)                         ! no need to create nrows/ncols vars.
            write(*, udf1) x(i,:)                       ! let the compiler handle the extents.
        enddo

    end subroutine printarray
end program main


观察:最终的do循环(“版本3”)非常简单。它不需要显式的NCOL计数,因为
*
自动处理它。由于它的简单性,实际上根本不需要子程序。

在文件where2.f95(unit=6,file='stdout'的第38行len=10时调试输出)Fortran运行时错误:意外元素'(8[次1(进程19607)以代码02退出]调试输出,当len=*位于文件where2.f95(unit=6,file='stdout')的第38行时。Fortran运行时错误:意外元素'(8[次1(进程19634)以代码02退出)不要把你想让人们理解的内容放进评论中,格式还不够好。你实际上没有使用
udf\u temp
anywhere-voting的值作为一个简单的打字错误来结束。如果你能解释一些真正的误解,我可能会收回投票。此外,在引用它之前,你没有定义
udf
(在
udf2=trim(txt1)//adjustl(udf)
)中,
“8”
如何显示在错误消息中令人费解。我认为所显示的代码并不是实际给出错误的代码。当len=10出现在文件where2.f95(unit=6,file='stdout')的第38行时调试输出Fortran运行时错误:意外的元素(8[substander 1(process 19607)当len=*位于文件where2.f95(unit=6,file='stdout')的第38行时,以代码02退出]调试输出Fortran运行时错误:意外元素'(8[次1(进程19634)以代码02退出)未放入注释ma