Write语句无法在用户定义的格式I/O过程中生成新的行,以衍生类型



我想为我的fortran代码中的派生类型实现用户定义的i/o过程。但是,这些过程中的write语句无法在两个顺序write语句之间产生新的行。派生的类型和过程定义为以下。

模块:

module station_module
    implicit none
    character(8), parameter :: FmtFloat = '(5E15.7)'
    type :: station
        integer, private :: ns = 0
        real, public, allocatable :: xloc(:), yloc(:), zloc(:)
    contains
        procedure, public :: import_station
        procedure, public :: export_station
        procedure, private :: read_station
        generic, public :: read (formatted) => read_station
        procedure, private :: write_station
        generic, public :: write (formatted) => write_station
        final :: destruct_station
    end type station
    interface station
        module procedure new_station
    end interface station
contains
    function new_station(n) result(t)
        implicit none
        integer, intent(in) :: n
        type(station) :: t
        if (n > 0) then
            allocate (t%zloc(n))
            allocate (t%yloc(n))
            allocate (t%xloc(n))
            t%ns = n
        end if
    end function new_station
    subroutine read_station(dtv, unit, iotype, vlist, iostat, iomsg)
        implicit none
        class(station), intent(inout) :: dtv
        integer, intent(in) :: unit
        character(*), intent(in) :: iotype
        integer, intent(in) :: vlist(:)
        integer, intent(out) :: iostat
        character(*), intent(inout) :: iomsg
        call dtv%import_station(unit)
        iostat = 0
    end subroutine read_station
    subroutine import_station(this, unit)
        implicit none
        class(station), intent(inout) :: this
        integer, intent(in) :: unit
        character(256) :: header, footer
        integer ns
        read (unit, '(A)') header !> Header
        read (unit, *) ns
        if (ns > 0) then
            if (allocated(this%zloc)) then
                deallocate (this%zloc)
            end if
            allocate (this%zloc(ns))
            read (unit, *) this%zloc
            if (allocated(this%yloc)) then
                deallocate (this%yloc)
            end if
            allocate (this%yloc(ns))
            read (unit, *) this%yloc
            if (allocated(this%xloc)) then
                deallocate (this%xloc)
            end if
            allocate (this%xloc(ns))
            read (unit, *) this%xloc
            this%ns = ns
        end if
        read (unit, '(A)') footer !> Footer
    end subroutine import_station
    subroutine export_station(this, unit)
        implicit none
        class(station), intent(in) :: this
        integer, intent(in) :: unit
        write (unit, '(A)') ">STATION INFO"
        write (unit, '(I6)') this%ns
        write (unit, *) "Z:"
        write (unit, FmtFloat) this%zloc
        write (unit, *) "Y:"
        write (unit, FmtFloat) this%yloc
        write (unit, *) "X:"
        write (unit, FmtFloat) this%xloc
        write (unit, '(A)') ">END STATION"
    end subroutine export_station
    subroutine write_station(dtv, unit, iotype, vlist, iostat, iomsg)
        implicit none
        class(station), intent(in) :: dtv
        integer, intent(in) :: unit
        character(*), intent(in) :: iotype
        integer, intent(in) :: vlist(:)
        integer, intent(out) :: iostat
        character(*), intent(inout) :: iomsg
        call dtv%export_station(unit)
        iostat = 0
    end subroutine write_station
    subroutine destruct_station(this)
        implicit none
        type(station), intent(inout) :: this
        if (allocated(this%xloc)) then
            deallocate (this%xloc)
        end if
        if (allocated(this%yloc)) then
            deallocate (this%yloc)
        end if
        if (allocated(this%zloc)) then
            deallocate (this%zloc)
        end if
        this%ns = 0
    end subroutine destruct_station
end module station_module

我们可以看到用户定义的格式化写语句只需调用一个常规子例程,命名为export_station,我希望通过这两种方式会产生相同的结果。

这是我的测试程序:

program Test
    use station_module
    implicit none
    type(station) :: pt, pt1, pt2
    pt = station(4)
    write(*, *) pt
    call pt%export_station(6)
end program Test

输出:

 >STATION INFO     4Z:  0.0000000E+00  0.0000000E+00  0.0000000E+00  0.0000000E+00
 Y:  0.0000000E+00  0.0000000E+00  0.0000000E+00  0.0000000E+00X:  0.0000000E+00  0.0000000E+00  0.0000000E+00  0.0000000E+00>END STATION
>STATION INFO
     4
 Z:
  0.0000000E+00  0.0000000E+00  0.0000000E+00  0.0000000E+00
 Y:
  0.0000000E+00  0.0000000E+00  0.0000000E+00  0.0000000E+00
 X:
  0.0000000E+00  0.0000000E+00  0.0000000E+00  0.0000000E+00
>END STATION

常规子例程export_station产生我的期望。在两个write语句之间产生了新行,而write派生类型的语句则不会。

也在英特尔论坛上询问。我在那里回答。"用户定义的派生型i/o都是不易合的(您不能更改此)。如果您想要newlines,则必须明确地写下它们(例如,使用a/format,例如。)。

这里有两类的输出语句:父母和一个孩子。在第一种情况下,父级输出语句是write (*,*) pt

当第一个是父时,然后通过 write_station呼叫export_station会导致写入语句,那里有子输出语句。当用户直接调用export_station时,这些写语句本身就是父量输出语句。

儿童数据传输语句和父数据传输语句之间的一个重要差异是,父语句在数据传输之前和之后定位文件。也就是说,当write (unit,*) "Z:"完成文件时,只有在转移语句为父时才写入记录之后。

因此,您会看到新行:这只是在书面记录之后放置。

儿童数据传输语句,没有将文件定位在完成时,不会影响新的行。


我目前无法访问测试机,因此该部分是投机性的。您可以明确编写从new_line('')返回的新的行字符,作为子传输语句输出的一部分。由于advance='no'将在儿童语句中忽略您可以在两种情况下都可以使用它,因此可以明确控制编写新行的位置,而不是依靠当前存在的拆分记录方法。

相关内容

最新更新