#fortran #gfortran
#fortran #gfortran
Вопрос:
Я создаю связанный список из входного файла. Каждый узел в связанном списке содержит информацию в каждом блоке ввода. Когда я пытаюсь получить значение из входного файла, я назначил несколько строк (по 4 строки каждый раз) в одномерный массив «tmp». Я думаю, что цикл выполнения, который я использовал в цикле «ввод: ВЫПОЛНЕНИЕ», неверен. Но я не знаю, как решить.
Я использую gfortran для компиляции, и при компиляции не возникает ошибок. Я попытался выполнить запись для тестирования в цикле «ввод: ВЫПОЛНЕНИЕ» для тестирования. Результат показывает, что я могу успешно открыть входной файл.
PROGRAM read
IMPLICIT NONE
INTEGER,PARAMETER :: nat=4
character(len=20) :: filename
!Derived types to store atom data
TYPE :: atom
CHARACTER(LEN=2) :: atom_name
REAL, DIMENSION(3) :: coord
END TYPE atom
!The array info stores info of all atom in one time step
type :: atom_seq
type(atom),dimension(nat):: info
type(atom_seq),pointer :: p
end type atom_seq
TYPE (atom_seq), POINTER :: head
TYPE (atom_seq), POINTER :: tail
type(atom), dimension(nat) :: temp
! Declare variable
INTEGER :: istat
INTEGER :: i=0, n=0
! Open input data file
WRITE(*,*) 'ENTER the file name with the data to be read: '
READ(*,'(A20)') filename
NULLIFY(head)
OPEN( UNIT=9, FILE=TRIM(filename), STATUS="OLD", ACTION="READ", IOSTAT=istat)
! Was the open successful
fileopen: IF (istat == 0) THEN
input: DO
!WRITE(*,*) "OPEN done " ! for testing
READ(9,*) ! <--when run, error is in this line
READ(9,*)
DO i = 1, nat
READ(9,*,IOSTAT=istat) temp(i)%atom_name, temp(i)%coord(1), temp(i)%coord(2), temp(i)%coord(3)
ENDDO
IF (istat /= 0) EXIT
n = n 1 ! Bump count
IF (.NOT. ASSOCIATED(head) ) THEN ! No values in list
ALLOCATE(head, STAT=istat) ! Allocate new value
tail => head ! Tail points to new value
NULLIFY(tail%p) ! Nullify p in new value
DO i = 1, nat ! Store number
tail%info(i)%atom_name = temp(i)%atom_name
tail%info(i)%coord(1) = temp(i)%coord(1)
tail%info(i)%coord(2) = temp(i)%coord(2)
tail%info(i)%coord(3) = temp(i)%coord(3)
ENDDO
ELSE ! Values already in list
ALLOCATE(tail%p, STAT=istat) ! Allocate new value
tail => tail%p
NULLIFY(tail%p)
DO i = 1, nat ! Store number
tail%info(i)%atom_name = temp(i)%atom_name
tail%info(i)%coord(1) = temp(i)%coord(1)
tail%info(i)%coord(2) = temp(i)%coord(2)
tail%info(i)%coord(3) = temp(i)%coord(3)
ENDDO
END IF
END DO input
ELSE fileopen
WRITE(*,1030) istat
1030 FORMAT ('File open failed --status = ', I6)
END IF fileopen
END PROGRAM read
Входной файл: inp
4
Particles:1_0
O 0.8050005000 0.7000000000 3.2350000000
H 1.4750005000 1.2800000000 2.8650000000
H 0.8550005000 -0.0900000000 2.7150000000
O 0.4050005000 0.7500000000 -4.1350000000
4
Particles:1_5
O 0.8799478358 0.6383317306 3.1569568025
H 1.4046592860 1.2232485826 2.4978364665
H 1.1472783731 -0.2687458123 3.0229092093
O 0.5392992531 0.6047144782 -4.0811918365
4
Particles:1_10
O -3.8021765454 3.1600783692 -4.5455655916
H -4.5320715486 3.0937504111 4.9514896261
H -3.5088238380 4.0613340230 -4.5394597924
O -3.3469012765 -0.7064128847 1.2465212113
и ошибка
hg@xi /home/hg/pole $ ./read
ENTER the file name with the data to be read:
inp
At line XXX of file read.f95 (unit = 9, file = 'inp')
Fortran runtime error: End of file
Error termination. Backtrace:
#0 0x7f1c1fdbb31a
#1 0x7f1c1fdbbec5
#2 0x7f1c1fdbc68d
#3 0x7f1c1ff32a33
#4 0x7f1c1ff364b7
#5 0x7f1c1ff365b8
#6 0x5566d3dc9daf
#7 0x5566d3dca9ed
#8 0x7f1c1f9d0b96
#9 0x5566d3dc9a79
#10 0xffffffffffffffff
Я надеюсь устранить проблему. Если моя идея неверна, пожалуйста, дайте несколько предложений по разработке лучшей структуры данных для сохранения данных во входных данных (входной файл может содержать тысячи блоков вместо 3. Он большой, и количество блоков неизвестно до запуска кода. )
Комментарии:
1. Я думаю, что вам также необходимо проверить состояние первого чтения во время цикла. (чтение (9,*)) В противном случае на 4-м цикле произойдет сбой.
2. Я снова протестировал, проблема может заключаться в следующем: он не может завершиться, когда достигнет конца файла, хотя я использовал
IF (istat /= 0) EXIT
в конце цикла выполнения. Я вставляю aWRITE()"XX"
в цикл. результат$ ./read ENTER the file name with the data to be read: inp OPEN done (XX 4 lines) OPEN done (XX 4 lines) OPEN done (XX 4 lines) OPEN done (XX 4 lines) OPEN done At line 35 of file read.f95 (unit = 9, file = 'inp') Fortran runtime error: End of file
3. Я попытался добавить
use iso_fortran_env
код и изменилIF (istat /= 0) EXIT
наif (stat == iostat_end) exit
, но проблема все та же.
Ответ №1:
Существует тест на IOSTAT
отсутствие с первым выполненным READ
в цикле. Когда результат не в порядке, цикл может быть завершен, например, изменить:
fileopen: IF (istat == 0) THEN
input: DO
!WRITE(*,*) "OPEN done " ! for testing
READ(9,*) ! <--when run, error is in this line
READ(9,*)
в
fileopen: IF (istat == 0) THEN
input: DO
!WRITE(*,*) "OPEN done " ! for testing
READ(9,*,IOSTAT=istat)
IF (istat /=0) EXIT
READ(9,*)
Комментарии:
1. Я тестирую
IOSTAT
с первымREAD
, тогда он работает!