Выделяемый массив '' в (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
Есть два способа вызвать такую подпрограмму:
Без названных фиктивных аргументов:
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)
, это ясно, не так ли?"Возможно, но для того, чтобы предотвратить подводные камни, в Руководстве Фортрана говорится, что
... как только аргумент ключевого слова появляется в списке, все остальные аргументы также должны быть аргументами ключевого слова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 Для ученых и инженеров