我不是Fortran 90的新手,但我很好奇是否存在我问题的简单解决方案。我有一个看起来像这样的文件:
.git/info/exclude
其中1
2
3
...
n
可以是任何整数,我想将文件中的每个数字读成整数数组n
。换句话说,A
。在运行代码之前,我不知道n有多大。我的解决方案是打开文件,从中读取所有内容,找到n,然后A=(1,2,3,...,n)
,然后重新读取文件:
allocate A(n)
但是,为了优雅,可以避免这种双重阅读吗?
答案 0 :(得分:2)
以下是一个非常简单的链表示例:
module list_mod
implicit none
type list_int
integer :: val = 0
integer :: length = 0
type(list_int), pointer :: next => NULL()
type(list_int), pointer :: tail => NULL()
end type
contains
subroutine append( list, val )
type(list_int), intent(inout) :: list
integer :: val
if ( associated(list%next) ) then
allocate( list%tail%next )
list%tail => list%tail%next
else
allocate( list%next )
list%tail => list%next
endif
list%tail%val = val
list%length = list%length + 1
end subroutine
end module
您可以使用它来按条目读入文件条目。列表的长度随着每个项目的增加而增加。此信息用于分配一个数组,然后以文件为单位。
program test
use list_mod
implicit none
type(list_int) :: ilist
type(list_int), pointer :: cur
integer,allocatable :: array(:)
integer :: i, io
open( unit=20, file="test.txt", status='old' )
do
read(unit=20,fmt=*,iostat=io) i
if (io/=0) exit
call append(ilist, i)
enddo
allocate( array( ilist%length ) )
cur => ilist%next
i = 1
do while (associated(cur))
array( i ) = cur%val
i = i + 1
cur => cur%next
enddo
print *,array
end program
答案 1 :(得分:1)
我已经通过@VladimirF(在评论中)翻译了这个建议,如下所示。虽然vector_t的定义相当冗长(在自动扩展大小时可能与vector有些类似),但调用程序变得有点短。
module vector_mod
implicit none
type vector_t
integer, allocatable :: elem(:) !! elements
integer :: n !! current vector size (<= size(elem))
contains
procedure :: push
procedure :: resize
procedure :: fit
end type
contains
subroutine push ( v, x )
class(vector_t) :: v
integer :: x
if ( allocated( v% elem ) ) then
if ( v% n == size( v% elem ) ) call v% resize( v% n * 2 )
v% n = v% n + 1
v% elem( v% n ) = x
else
allocate( v% elem( 1 ) )
v% n = 1
v% elem( 1 ) = x
endif
end subroutine
subroutine resize ( v, n )
class(vector_t) :: v
integer :: n
integer, allocatable :: buf(:)
integer :: m
allocate( buf( n ), source=0 )
m = min( n, size(v% elem) )
buf( 1:m ) = v% elem( 1:m )
deallocate( v% elem )
call move_alloc ( buf, v% elem )
end subroutine
subroutine fit ( v )
class(vector_t) :: v
call v% resize( v% n )
end subroutine
end
program main
use vector_mod, only: vector_t
implicit none
type(vector_t) :: v
integer x, ios
open( 10, file="test.dat", status="old" )
do
read( 10, *, iostat=ios ) x
if ( ios /= 0 ) exit
call v% push( x )
enddo
close( 10 )
call v% fit()
print *, v% elem(:)
end
但恕我直言,我想问题中给出的解决方案(即打开文件,从中读取所有内容,找到n,然后分配A(n)然后重新读取文件)将是最简单的... < / p>