[英]Write statement cannot produce new lines within user-defined formatted I/O procedures for derived type
I want to implement the user-defined I/O procedures for the derived types in my Fortran code. 我想在我的Fortran代码中为派生类型实现用户定义的I / O过程。 However, write
statements within those procedures cannot produce new lines between two sequential write
statements. 但是,这些过程中的write
语句不能在两个顺序write
语句之间产生新行。 The derived type and procedures are defined as below. 派生类型和过程定义如下。
The module: 模块:
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
We can see that the user-defined formatted write statement just call a regular subroutine named export_station
, by which I expect the same result in both ways. 我们可以看到用户定义的格式化的write语句只调用一个名为export_station
的常规子例程,我希望通过这两个方法得到相同的结果。
Here is my test program: 这是我的测试程序:
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
The output: 输出:
>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
The regular subroutine export_station
produces what I expect. 常规子例程export_station
产生了我所期望的。 New lines are produced between two write
statements, while write
statement of the derived type does not. 在两个write
语句之间生成新行,而派生类型的write
语句则不生成。
This was also asked on the Intel forum. 这也是在英特尔论坛上提出的。 I replied there."User-defined derived-type I/O is all non-advancing (and you can't change this). If you want newlines you have to write them explicitly (using a / format, for example.)" 我回答说。“用户定义的派生类型I / O都是非进展的(你不能改变它)。如果你想要新行,你必须明确地写它们(例如,使用/格式)。”
There are two classes of output statements here: a parent and a child. 这里有两类输出语句:父语句和子语句。 The parent output statement in the first case is the write (*,*) pt
. 第一种情况下的父输出语句是write (*,*) pt
。
When this first is the parent, then the call to export_station
through write_station
leads to the write statements there being child output statements. 当这首先是父母,然后调用export_station
通过write_station
导致写语句是有孩子的输出语句。 When export_station
is called directly by the user those write statements are themselves parent output statements. 当用户直接调用export_station
,这些write语句本身就是父输出语句。
One significant difference between a child data transfer statement and a parent data transfer statement is that a parent statement positions the file prior to and after data transfer. 子数据传输语句和父数据传输语句之间的一个显着区别是父语句在数据传输之前和之后定位文件。 That is, when the write (unit,*) "Z:"
completes the file is positioned after the record just written only when the transfer statement is a parent. 也就是说,当write (unit,*) "Z:"
完成时,文件位于刚刚写入的记录之后,当转移语句是父语句时。
Thus, you see the new lines: this is simply placing after the written record. 因此,您会看到新的行:这只是放在书面记录之后。
A child data transfer statement, not positioning the file on completion, does not effect a new line. 子数据传输语句(不是在完成时定位文件)不会影响新行。
I don't have access to a test machine at the moment, so this part is speculative. 我目前无法访问测试机器,所以这部分是推测性的。 You can explicitly write a new line character returned from new_line('')
as part of your output for the child transfer statement. 您可以显式写入从new_line('')
返回的new_line('')
作为子转移语句输出的一部分。 As advance='no'
will be ignored in a child statement you could use that for both cases, explicitly controlling where new lines are written, rather than relying on the split record approach as currently exists. 由于advance='no'
将在子语句中被忽略,您可以在两种情况下使用它,明确控制新行的写入位置,而不是依赖于当前存在的拆分记录方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.