Arrays 可分配数组'';at(1)必须具有延迟形状或假定秩,并且READ语句中的语法错误为at(1)错误

Arrays 可分配数组'';at(1)必须具有延迟形状或假定秩,并且READ语句中的语法错误为at(1)错误,arrays,fortran,readfile,gfortran,allocatable-array,Arrays,Fortran,Readfile,Gfortran,Allocatable Array,我试图读取ASCII文件,但在编译时出错,例如: Error: Syntax error in READ statement at (1) 及 我的代码: 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"

我试图读取ASCII文件,但在编译时出错,例如:

Error: Syntax error in READ statement at (1)

我的代码:

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
有两种方法可以调用这样的子例程:

  • 没有命名的伪参数:

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

    call mysub(1, 2, 3)   ! a->1, b->2, c->3
    call mysub(4711, 2)   ! a->4711, b->2, c unset
    
    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

    read
    的接口将
    单元
    作为第一个参数,将
    fmt
    作为第二个参数。因此,您可以选择其中一种:

    read(unit=11, fmt=*, iostat=ios) ...
    read(11, *, iostat=ios) ...
    
    但是如果不声明
    fmt=

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

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

    1摘自Chapman:Fortran 95/2003,适用于科学家和工程师

    读取语法错误源于使用命名伪参数(
    unit=11
    ),但随后不再继续使用命名伪参数

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

    subroutine mysub(a, b, c)
        implicit none
        integer, intent(in), optional :: a, b, c
    end subroutine mysub
    
    有两种方法可以调用这样的子例程:

  • 没有命名的伪参数:

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

    call mysub(1, 2, 3)   ! a->1, b->2, c->3
    call mysub(4711, 2)   ! a->4711, b->2, c unset
    
    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

    read
    的接口将
    单元
    作为第一个参数,将
    fmt
    作为第二个参数。因此,您可以选择其中一种:

    read(unit=11, fmt=*, iostat=ios) ...
    read(11, *, iostat=ios) ...
    
    但是如果不声明
    fmt=

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

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

    1摘自Chapman:Fortran 95/2003,适用于科学家和工程师

    感谢您的回答@chw21。事实证明,在声明可分配数组时,我需要以下行,因为它不喜欢3:
    real、allocatable、intent(out)::pos(:,:)、mass(:)、rho(:)、vel(:,:)
    。我已经实现了您的建议,但是它似乎也不喜欢
    字符(len)
    。我现在得到的唯一错误是
    read
    语句的语法错误。使用“(A)”参数似乎没有什么区别。我的read语句现在看起来是这样的:
    do read(unit=11,*,iostat=ios)pos,mass,rho,vel.
    read(unit=11,*)pos(:,i),mass(i),rho(i),vel(:,i)
    。如果我输入
    字符(len=1002)::pos,mass,rho,vel,它不喜欢它,因为我已经定义了这些变量,它也不喜欢我加入不同的变量。不确定这里有什么问题@chw21通常我在提交之前检查我的答案,这次我没有时间。很抱歉给你带来了困惑。正如所指出的(与我的想法相反),
    read
    不需要变量。这修复了语法错误,非常感谢您的帮助!关于数组本身,使用pos(3,n)会包含ascii文件中的前三列吗?或者最好为这个数组创建3个单独的变量,然后以某种方式将它们组合到pos(3,n)中?干杯@chw21,这取决于你想如何处理数据。谢谢你的回答@chw21。事实证明,在声明可分配数组时,我需要以下行,因为它不喜欢3:
    real、allocatable、intent(out)::pos(:,:)、mass(:)、rho(:)、vel(:,:)
    。我已经实现了您的建议,但是它似乎也不喜欢
    字符(len)
    。我现在得到的唯一错误是
    read
    语句的语法错误。使用“(A)”参数似乎没有什么区别。我的read语句现在看起来是这样的:
    do read(unit=11,*,iostat=ios)pos,mass,rho,vel.
    read(unit=11,*)pos(:,i),mass(i),rho(i),vel(:,i)
    。如果我输入
    字符(len=1002)::pos,mass,rho,