(1) 处的可分配数组 '' 必须具有延迟形状或假定等级,以及 (1) 处 READ 语句中的语法错误错误

Allocatable array '' at (1) must have a deferred shape or assumed rank, and Syntax error in READ statement at (1) errors

我正在尝试读取 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

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。您可能会说,"What if I use mysub(a=1, 2, 3), that's clear, isn't it?" 可能是,但为了避免陷阱,Fortran 指南声明

... once a keyword argument appears in the list, all of the remaining arguments must also be keyword arguments1

read 的接口第一个参数是 unit,第二个参数是 fmt。所以你可以选择其中之一:

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

但是你不能在不声明 fmt=

的情况下使用 unit=

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

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

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