Fortran中的线阅读错误

时间:2016-09-08 15:51:30

标签: format fortran

我正在编写Fortran代码,以便阅读反应列表及其反应类型。该列表位于名为reactions.rx的文件中,如下所示:

H2O       O1D       OH        OH                2BODY                  .  
               .  
               .  (Same format continued)
               .  
CH3C2H    HV        C3H3      H                 PHOTO  
CH3C2H    HV        C3H2      H2                PHOTO  
CH3C2H    HV        CH3       C2H               PHOTO  
CH2CCH2   HV        C3H3      H                 PHOTO  
CH2CCH2   HV        C3H2      H2                PHOTO  
CH2CCH2   HV        C2H2      CH23              PHOTO  
C2H6      HV        CH23      CH23      H2      PHOTO  
C2H6      HV        CH4       CH21              PHOTO  
C2H6      HV        C2H2      H2        H2      PHOTO  
C2H6      HV        C2H4      H         H       PHOTO  
C2H6      HV        C2H4      H2                PHOTO  
C2H6      HV        CH3       CH3               PHOTO  
C2H       C2H2      HCAER     H                 2BODY  
C2H       CH2CCH2   HCAER2    H                 2BODY  

目标是编写代码,使其在最左边的列中找到第一次出现的指定物种,标签为PHOTO,然后继续读取文件,直到该行不再包含物种或不是PHOTO 。

到目前为止我的代码:

! reactions.rx is opened earlier as file 12
667   FORMAT(A10, A10, A10, A10, A8, A5)

      stat = 0
      ! Reads until a line is found in reactions.rx with reactant1 == species 
      ! and label beginning with "PHOT"
      do while((trim(reac1).ne.trim(species).OR.label(1:4).ne.'PHOT')
     &  .AND.stat == 0)
        READ(12,667,IOSTAT=stat) reac1,reac2,prod1,prod2,prod3,label
      end do

      if(stat.ne.0) then
        print*, " *** Species not in reactions.rx!!!! *** "
        STOP
      endif

     ! reac1...prod3,label hold the first line of matching info
     ! Does some work ...

     ! Continue reading the file until the line is no longer about a PHOT
     ! reaction beginning with species
     do while(trim(reac1).eq.trim(species).AND.
    &    label(1:4).eq.'PHOT')
       if(label(5:5).ne.'O') then
         ! Does some work ...    
       else
         ! Does some work ...
         ! The following print statements are for testing purposes
         print*, "AT SPECIES: ", species
         print*, "ON LINE: ", reac1,reac2,prod1,prod2,prod3,label
       endif
       stat = 0       
       READ(12, 667, IOSTAT=stat) reac1,reac2,prod1,prod2,prod3,
    &        label
       print*, "NEXT LINE: ",reac1,reac2,prod1,prod2,prod3,label,
    &        stat          
       if(stat.ne.0) then
         label = 'DONE ' !breaks while
       endif
     enddo
     close(12)

使用此代码我得到输出:(原谅可怜的格式化)

 AT SPECIES: H2O
 ON LINE: H2O       HV        H         OH                  PHOTO
 NEXT LINE: O3        HV        O2        O1D                 PHOTP                    0
 AT SPECIES: CO2
 ON LINE: CO2       HV        CO        O                   PHOTO
 NEXT LINE: CO2       HV        CO        O1D                 PHOTO                    0
 AT SPECIES: CO2
 ON LINE: CO2       HV        CO        O1D                 PHOTO
 NEXT LINE: CO        OH        CO2       H                   WEIRD                    0
 AT SPECIES: H2CO
 ON LINE: H2CO      HV        H2        CO                  PHOTO
 NEXT LINE: H2CO      HV        HCO       H                   PHOTO                    0
 AT SPECIES: H2CO
 ON LINE: H2CO      HV        HCO       H                   PHOTO
 NEXT LINE: HCO       HV        H         CO                  2BODY                    0
 AT SPECIES: CH4
 ON LINE: CH4       HV        CH21      H2                  PHOTO
 NEXT LINE: CH4       HV        CH3       H                   PHOTO                    0
 AT SPECIES: CH4
 ON LINE: CH4       HV        CH3       H                   PHOTO
 NEXT LINE: CH4       HV        CH23      H         H         PHOTO                    0
 AT SPECIES: CH4
 ON LINE: CH4       HV        CH23      H         H         PHOTO
 NEXT LINE: C         OH        CO        H                   2BODY                    0
 AT SPECIES: CH
 ON LINE: CH        HV        C         H                   PHOTO
 NEXT LINE: CH        S         CS        H                   2BODY                    0
 AT SPECIES: CH2CO
 ON LINE: CH2CO     HV        CH23      CO                  PHOTO
 NEXT LINE: CH23      CO        CH2CO                         WEIRD                    0
 AT SPECIES: C2H2
 ON LINE: C2H2      HV        C2H       H                   PHOTO
 NEXT LINE: C2H2      HV        C2        H2                  PHOTO                    0
 AT SPECIES: C2H2
 ON LINE: C2H2      HV        C2        H2                  PHOTO
 NEXT LINE: C2H2      OH        CO        CH3                 2BODY                    0
 AT SPECIES: C2H4
 ON LINE: C2H4      HV        C2H2      H2                  PHOTO
 NEXT LINE: C2H4      HV        C2H2      H         H         PHOTO                    0
 AT SPECIES: C2H4
 ON LINE: C2H4      HV        C2H2      H         H         PHOTO
 NEXT LINE: CH23      CH3       C2H4      H                   2BODY                    0
 AT SPECIES: CH3CHO
 ON LINE: CH3CHO    HV        CH3       HCO                 PHOTO
 NEXT LINE: CH3CHO    HV        CH4       CO                  PHOTO                    0
 AT SPECIES: CH3CHO
 ON LINE: CH3CHO    HV        CH4       CO                  PHOTO
 NEXT LINE: C2H5      CH3       C3H8                          WEIRD                    0
 AT SPECIES: C3H8
 ON LINE: C3H8      HV        C3H6      H2                  PHOTO
 NEXT LINE: C3H8      HV        C2H6      CH21                PHOTO                    0
 AT SPECIES: C3H8
 ON LINE: C3H8      HV        C2H6      CH21                PHOTO
 NEXT LINE: C3H8      HV        C2H4      CH4                 PHOTO                    0
 AT SPECIES: C3H8
 ON LINE: C3H8      HV        C2H4      CH4                 PHOTO
 NEXT LINE: C3H8      HV        C2H5      CH3                 PHOTO                    0
 AT SPECIES: C3H8
 ON LINE: C3H8      HV        C2H5      CH3                 PHOTO
 NEXT LINE: C2H       C3H8      C2H2      C3H7                2BODY                    0
 AT SPECIES: C3H6
 ON LINE: C3H6      HV        C2H2      CH3       H         PHOTO
 NEXT LINE: C3H6      HV        CH2CCH2   H2                  PHOTO                    0
 AT SPECIES: C3H6
 ON LINE: C3H6      HV        CH2CCH2   H2                  PHOTO
 NEXT LINE: C3H6      HV        C2H4      CH23                PHOTO                    0
 AT SPECIES: C3H6
 ON LINE: C3H6      HV        C2H4      CH23                PHOTO
 NEXT LINE: C3H6      HV        C2H       CH4       H         PHOTO                    0
 AT SPECIES: C3H6
 ON LINE: C3H6      HV        C2H       CH4       H         PHOTO
 NEXT LINE: C2H5CHO   HV        C2H5      HCO                 PHOTO                    0
 AT SPECIES: C2H5CHO
 ON LINE: C2H5CHO   HV        C2H5      HCO                 PHOTO
 NEXT LINE: H2O       O1D       OH        OH                  2BODY                    0
 AT SPECIES: C3H3
 ON LINE: C3H3      HV        C3H2      H                   PHOTO
 NEXT LINE: CH3C2H    HV        C3H3      H                   PHOTO                    0
 AT SPECIES: CH3C2H
 ON LINE: CH3C2H    HV        C3H3      H                   PHOTO
 NEXT LINE: H2O       O1D       OH        OH                  2BODY                    0
 AT SPECIES: CH2CCH2
 ON LINE: CH2CCH2   HV        C3H3      H                   PHOTO
 NEXT LINE: CH2CCH2   HV        C3H2      H2                  PHOTO                    0
 AT SPECIES: CH2CCH2
 ON LINE: CH2CCH2   HV        C3H2      H2                  PHOTO
 NEXT LINE: CH2CCH2   HV        C2H2      CH23                PHOTO                    0
 AT SPECIES: CH2CCH2
 ON LINE: CH2CCH2   HV        C2H2      CH23                PHOTO
 NEXT LINE: C2H6      HV        CH23      CH23      H2        PHOTO                    0
 AT SPECIES: C2H6
 ON LINE: C2H6      HV        CH23      CH23      H2        PHOTO
 NEXT LINE: H2O       O1D       OH        OH                  2BODY                    0

稍微澄清一下,AT SPECIES:告诉我与reac1匹配的物种。 ON LINE打印符合要求(种类和PHOT)的行信息。 NEXT LINE打印下一行读取的行。

我的虫首先出现在物种CH3C2H上。从输出中可以看出,CH3C2H的一条反应线被读取(从输出底部向上15行)。然而,NEXT LINE印刷为“H2O O1D OH OH 2BODY”。在react.rx(应该被读取)的下一行显然是“CH3C2H HV C3H2 H2 PHOTO”。这是我感兴趣的反应,但由于某种原因,行读取是第一行反应.rx。 C2H6也会出现同样的问题(最后在输出中)。对于这个物种,应该从reactions.rx中读取另外5行,但是在第一行NEXT LINE变为H2O后,再次读取...... 2BODY。 H2O行正确地结束了do循环,所以我的问题是我不明白为什么在这两种情况下会读取错误的行。

虽然在某些情况下我评论“!做了一些工作......”但代码更多,因为你可以看到我感兴趣的实际打印和读取语句之间没有其他代码。因此,我不相信它是变量/存储的问题,它似乎是我的循环或实际读取的某种错误。我确信正在阅读正确的文件(reactions.rx)。我甚至对它进行了更改并在代码中打印出整个内容以确保它是正在读取的文件。

我不能为我的生活弄清楚为什么会发生这种错误,特别是因为除了上面讨论的两个以外,代码完全符合其他所有物种的意图。我们非常感谢人们提供的任何帮助或建议。

我正在使用Windows 10机器上的gfortran 5.3.0进行编译。

1 个答案:

答案 0 :(得分:1)

您在问题的评论中问我“我的代码版本”。 我所做的是将你的代码变成一个子程序,然后用

调用
CALL READ_REACTIONS(species)

首先,这是您的代码,最低限度修改:

      SUBROUTINE READ_REACTIONS(species)
        implicit none
        character(len=10) :: species
        character(len=10) :: reac1, reac2, prod1, prod2
        character(len=8) :: prod3
        character(len=5) :: label
        integer stat

        PRINT *, "Searching for species " // species

        OPEN(12, file="reactions.rx", action="READ")
  667   FORMAT(A10, A10, A10, A10, A8, A5)

      stat = 0
      ! Reads until a line is found in reactions.rx with reactant1 == species
      ! and label beginning with "PHOT"
      do while((trim(reac1).ne.trim(species).OR.label(1:4).ne.'PHOT')
     &  .AND.stat == 0)
        READ(12,667,IOSTAT=stat) reac1,reac2,prod1,prod2,prod3,label
      end do

      if(stat.ne.0) then
        print*, " *** Species not in reactions.rx!!!! *** "
        GOTO 999 ! < You had a STOP here, but I'd rather make a clean
                 ! exit including the CLOSE
      endif

      ! reac1...prod3,label hold the first line of matching info
      ! Does some work ...

      ! Continue reading the file until the line is no longer about a PHOT
      ! reaction beginning with species
      do while(trim(reac1).eq.trim(species).AND.
     &    label(1:4).eq.'PHOT')
        if(label(5:5).ne.'O') then
          ! Does some work ...
        else
          ! Does some work ...
          ! The following print statements are for testing purposes
          print*, "AT SPECIES: ", species
          print*, "ON LINE: ", reac1,reac2,prod1,prod2,prod3,label
        endif
        stat = 0
        READ(12, 667, IOSTAT=stat) reac1,reac2,prod1,prod2,prod3,
     &        label
        print*, "NEXT LINE: ",reac1,reac2,prod1,prod2,prod3,label,
     &        stat
        if(stat.ne.0) then
          label = 'DONE ' !breaks while
        endif
      enddo
 999  CONTINUE   ! <-- added label for the clean exit if species not found.
      close(12)
      END SUBROUTINE READ_REACTIONS

正如您所看到的,我只添加了声明块和OPEN语句,并在关闭文件之前将STOP更改为GOTO

我没有完整的reactions.rx,但是根据您提供的代码段,它运行正常。

我还创建了自己的read_reactions版本,我认为这个版本更容易理解。我将整个事情包装在一个模块中,这样我就不需要声明一个显式接口了。在实际代码中,我实际上会做出更好的错误处理,但这篇文章已经太长了。

module mod_read_reactions

  implicit none
  character(len=*), parameter :: fmt = "(4(A10), A8, A5)"
  character(len=*), parameter :: file_name = 'reactions.rx'
contains
  subroutine read_reactions(species)
    implicit none
    character(len=10), intent(in) :: species
    integer :: iounit, ios
    character(len=200) :: iomsg
    character(len=10) :: reac1, reac2, prod1, prod2
    character(len=8) :: prod3
    character(len=5) :: label

    open( newunit=iounit, file=file_name, iostat=ios, &
          iomsg=iomsg, status="old", action="read" )
    if ( ios /= 0 ) stop "Error opening file " ! Suggest better error handling

    searchloop : do
      read(iounit, fmt, iostat=ios, iomsg=iomsg)  &
            reac1, reac2, prod1, prod2, prod3, label
      if (ios /= 0) then
        print *, "Species " // trim(species) // " not found."
        goto 999
      end if

      if (reac1 == species .and. label == "PHOTO") exit searchloop
    end do searchloop

    do while (ios == 0 .and. reac1 == species .and. label == 'PHOTO')
      ! When we come in here, we should already have the first match, so we can
      ! immediately act upon it (in this case just print it out)
      print *, reac1, reac2, prod1, prod2, prod3, label

      ! Now read the next line.
      read(iounit, fmt, iostat=ios, iomsg=iomsg)  &
            reac1, reac2, prod1, prod2, prod3, label
    end do

999 continue
    close(iounit)
  end subroutine read_reactions

end module mod_read_reactions

我应该补充一点,这段代码仍在重新打开并关闭每个新物种请求的文件,这不太聪明。