Выделяемый массив '' в (1) должен иметь отложенную форму или предполагаемый ранг, а синтаксическая ошибка в операторе READ в (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

Первые 8 столбцов в моем файле ascii - это компоненты 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

1 ответ

Решение

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), это ясно, не так ли?"Возможно, но для того, чтобы предотвратить подводные камни, в Руководстве Фортрана говорится, что

... как только аргумент ключевого слова появляется в списке, все остальные аргументы также должны быть аргументами ключевого слова1

Интерфейс для read имеет unit как первый, а fmt как второй параметр. Таким образом, вы можете любой из них:

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

Но вы не можете использовать unit= без объявления fmt=

Если вы объявляете выделяемый массив, вам нужно указать ему количество измерений, которые вы хотите зарезервировать для размещения. Это не сделано с n, но с двоеточием ::

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

1 от Чепмена: Фортран 95/2003 Для ученых и инженеров

Другие вопросы по тегам