1

我正在尝试读取 ASCII 文件并在编译时遇到错误,例如:

Error: Syntax error in READ statement at (1)

Error: Allocatable array 'pos' at (1) must have a deferred shape or assumed rank

我的代码:

subroutine read_file(pos,mass,rho,vel,n)
integer :: i, n
real, allocatable, intent(out) :: pos(3,n), mass(n), rho(n), vel(3,n)

open(unit=11,file="star.ascii",status="old",action="read") 

n = 0

do
  read(unit=11,*)
  n = n+1
enddo

allocate(pos(3,n), mass(n), rho(n), vel(3,n))

do i = 1,n
  read(unit=11,*) pos(:,i), mass(i), rho(i), vel(:,i)
enddo
close(unit=11)

end subroutine read_file

我的 ascii 文件中的前 8 列是位置、质量、密度的 x、y、z 分量,以及我正在读入数组的速度的 x、y、z 分量,其中 (1,n), (2, n), (3,n) 分别是 x、y 和 z 分量,n 应该是粒子数。

我做错了什么,如何编译这段代码?

更新:第一个错误已解决,但 READ 语句仍然出现相同的语法错误。

subroutine read_file(pos,mass,rho,vel,n) 
integer :: i, n, ios
real, allocatable, intent(out) :: pos(:,:),mass(:),rho(:),vel(:,:)

open(unit=11,file="star.ascii",status="old",action="read")

n = 0
do
  read(unit=11,*,iostat=ios) pos,mass,rho,vel 
  if (ios /= 0) exit
  n = n+1
enddo

allocate(pos(3,n), mass(n), rho(n), vel(3,n))  
rewind(11)

do i = 1,n
  read(unit=11,*)pos(:,i),mass(i),rho(i),vel(:,i) 
enddo
close(unit=11)

end subroutine read_file
4

1 回答 1

0

read语法错误来自您使用命名虚拟参数 ( unit=11) 但您没有继续使用命名虚拟参数这一事实。

假设您有一个带有此接口的子例程:

subroutine mysub(a, b, c)
    implicit none
    integer, intent(in), optional :: a, b, c
end subroutine mysub

有两种方法可以调用这样的子程序:

  1. 没有命名的虚拟参数:

    call mysub(1, 2, 3)   ! a->1, b->2, c->3
    call mysub(4711, 2)   ! a->4711, b->2, c unset
    
  2. 使用所谓的关键字参数:

    call mysub(a=4, c=2)  ! b unset
    call mysub(b=14)      ! a and c unset
    

在情况 1. 编译器根据参数在接口中定义的顺序解释输入。在案例 2. 它通过关键字参数设置它们。在某种程度上,您可以混合一下:

call mysub(1, c=5)   ! b unset

但是,这很重要,在第一个关键字参数之后,您不能返回:

call mysub(b=4, 2)   ! DOES NOT WORK

在这种情况下,编译器不知道 a 或 c 是否应该为 2。你可能会说,“如果我使用mysub(a=1, 2, 3),那很清楚,不是吗?” 可能是这样,但为了避免这些陷阱,Fortran 指南指出

...一旦关键字参数出现在列表中,所有剩余的参数也必须是关键字参数1

接口readunit第一个fmt参数是 ,第二个参数是 。因此,您可以选择以下任何一种:

read(unit=11, fmt=*, iostat=ios) ...
read(11, *, iostat=ios) ...

但是你不能在unit=没有声明的情况下使用fmt=

如果您声明一个可分配数组,您需要告诉它您要为分配保留的维数。这不是用冒号完成的n,而是用冒号完成的:

real, allocatable :: pos(:, :), mass(:), rho(:), vel(:, :)

1来自 Chapman:Fortran 95/2003 供科学家和工程师使用

于 2017-08-01T03:38:18.350 回答