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

问题描述 投票:0回答:1

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

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

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个。它很大,并且在运行代码之前块数是未知的。)

fortran gfortran
1个回答
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,*)
© www.soinside.com 2019 - 2024. All rights reserved.