【问题标题】:Line Reading Bug in FortranFortran 中的行读取错误
【发布时间】:2016-09-08 15:51:29
【问题描述】:

我正在编写 Fortran 代码以读取反应列表及其反应类型。该列表位于名为response.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 打印符合要求(物种和照片)的生产线信息。 NEXT LINE 打印下一个读取的行。

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

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

我一辈子都想不通为什么会发生这个错误,尤其是因为代码完全按照除了上面讨论的两个物种之外的所有其他物种所做的事情。非常感谢人们提供的任何帮助或建议。

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

【问题讨论】:

  • 从输出中可以看出 不是。为什么不写出一个整齐的表格,就像你的输入文件一样;这将使我(甚至可能是你)更容易看到哪里出了问题以及如何出错。
  • 我猜...! Does some work 重新打开文件或重新定位单元12。在调试器中跟踪执行时会发生什么?
  • @HighPerformanceMark 你说得对,我可能需要一些时间来实际格式化输出。我在剩下的时间里还有其他义务,但我明天会尝试更新我的帖子。
  • @IanH 我已经多次查看了代码,但 12 没有重新打开或以不同的方式打开。你会推荐使用什么调试器?我目前在 Sublime 3 中进行编码并使用 cygwin 编译/运行。
  • 我拿走了你的代码并编译了它。尽管我注意到缩进中存在不一致,但它似乎工作正常。所以我同意@IanH 的观点,即问题可能出在! Does some work 区域的某个地方。

标签: format fortran


【解决方案1】:

您在 cmets 中向我询问了“我的代码版本”来回答您的问题。 我所做的是把你的代码变成一个子程序,然后我用

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,但是使用你提供的 sn-p,它可以正常工作。

我还创建了自己的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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-29
    • 1970-01-01
    • 1970-01-01
    • 2014-08-09
    • 2017-03-05
    • 2015-03-06
    相关资源
    最近更新 更多