用指针创建链接列表时出现“ Fortran运行时错误:文件结尾”问题(在DO循环中读取)

时间:2019-04-16 08:52:55

标签: fortran gfortran

我正在从输入文件创建链接列表。链接列表中的每个节点都在输入的每个块中包含信息。 当我尝试从输入文件中获取值时,我将多行(每次4行)分配到一个1D数组“ tmp”中。我认为我在“ input:DO”循环中使用的DO循环是错误的。但是我不知道该怎么解决。

我使用gfortran进行编译,编译没有错误。 我已经尝试在“ input:DO”循环中进行WRITE测试。结果显示我可以成功打开输入文件。

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 个答案:

答案 0 :(得分: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,*)