gpt4 book ai didi

class - 使用定义的输入过程从 Fortran 中的二进制文件中读取错误值

转载 作者:行者123 更新时间:2023-12-02 01:00:37 25 4
gpt4 key购买 nike

我正在尝试编写一个简单的代码,它获取一些具有相同父抽象类的对象,将它们存储到一个二进制文件中并读回它们。

我的代码是这样的:

module m
implicit none

type :: container
class(a), allocatable :: item
end type container

type, abstract :: a
character(20), public :: obj_type
integer, public :: num
contains
procedure :: write_impl => write_a
procedure :: read_impl => read_a

generic :: write(unformatted) => write_impl
generic :: read(unformatted) => read_impl
end type a

type, extends(a) :: b
integer, public :: num2
contains
procedure :: write_impl => write_b
procedure :: read_impl => read_b
end type b

type, extends(a) :: c
end type c

contains

subroutine write_a(this, unit, iostat, iomsg)
class(a), intent(in) :: this
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg

write(unit, iostat=iostat, iomsg=iomsg) this%num
end subroutine write_a

subroutine read_a(this, unit, iostat, iomsg)
class(a), intent(inout) :: this
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg

read(unit, iostat=iostat, iomsg=iomsg) this%num
end subroutine read_a

subroutine write_b(this, unit, iostat, iomsg)
class(b), intent(in) :: this
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg

write(unit, iostat=iostat, iomsg=iomsg) this%num, this%num2
end subroutine write_b

subroutine read_b(this, unit, iostat, iomsg)
class(b), intent(inout) :: this
integer, intent(in) :: unit
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg

read(unit, iostat=iostat, iomsg=iomsg) this%num, this%num2
end subroutine read_b
end module m

program mwe
use m

implicit none

class(a), allocatable :: o1, o2, o3, o4
class(container), allocatable :: arr(:)
integer :: i, arr_size, tmp
character(20) :: str_tmp

o1 = b('b', 1, 2)
o2 = c('c', 3)

allocate(arr(2))
arr(1)%item = o1
arr(2)%item = o2

select type(t => o1)
type is(b)
write(*,*) t%num, t%num2
end select

select type(t => arr(1)%item)
type is(b)
write(*,*) t%num, t%num2
end select

write(*,*) 'Write into binary'
! WRITE size
open(123, file='test5.dat', form='unformatted')
write(123) SIZE(arr)

do i=1,2
write(123) arr(i)%item%obj_type
if(arr(i)%item%obj_type .eq. 'b') then
select type(t => arr(i)%item)
type is(b)
write(123) t
end select
else if(arr(i)%item%obj_type .eq. 'c') then
select type(t => arr(i)%item)
type is(c)
write(123) t
end select
end if
end do
close(123)

write(*,*) 'Read from binary'
open(123, file='test5.dat', form='unformatted')
read(123) arr_size
write(*,*) 'array size: ', arr_size

do i=1,2
read(123) str_tmp
write(*,*) str_tmp
if(allocated(o3)) deallocate(o3)
if(str_tmp .eq. 'b') then
allocate(b :: o3)
select type(t => o3)
type is(b)
read(123) t
write(*,*) t%num, t%num2 ! BAD OUTPUT
end select
else if(str_tmp .eq. 'c') then
allocate(c :: o3)
select type(t => o3)
type is(c)
read(123) t
write(*,*) t%num
end select
end if

end do

end program mwe

问题是,读取 o1 - 它是 b 类型,即这个对象有两个组件 - numnum2。我存储它,我自然希望读取值与写入值相同。

但我遇到了与 Variables being deleted in Fortran Arrays? 中描述的相同的奇怪行为.在那个问题中,它是由初始化数组时错误的赋值语法引起的,但在这种情况下,我完全不知道为什么我的输出看起来像这样:

           1           2
1 2
Write into binary
Read from binary
array size: 2
b
1 0
c
3

b 下的值显然应该是 1 和 2,而不是 1 和 0。我做错了什么?

最佳答案

这里的问题是在

select type(t => arr(i)%item)
type is(b)
write(123) t
end select

ifort 实际上并没有选择过程 write_b 来处理定义的输出。在处理定义的输入时,它也没有选择过程 read_b

而是选择过程 write_aread_a

这是编译器的问题,应该报告给英特尔。一个相当繁琐的解决方法是在这些过程中选择类型

关于class - 使用定义的输入过程从 Fortran 中的二进制文件中读取错误值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50774846/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com