【问题标题】:Fortran Print Line Number While Reading Input FileFortran 在读取输入文件时打印行号
【发布时间】:2015-07-24 15:42:54
【问题描述】:

我收到来自输入文件的格式错误,我想确定输入文件中出现格式错误的位置。
我的问题是:有没有办法打印我的 fortran 代码中出现错误的输入文件的行号?

这是我得到的错误:

fmt: read unexpected character
apparent state: unit 4 named input_file
last format: (6(I3,X,F7.2,X,I2,X))
lately reading sequential formatted external IO

这意味着代码挂在我的输入文件中与上述格式不对应的某行。

这是我的代码中 Fortran 在输入文件中读取的部分:

      DO 20  K  = 1,NUMB
      READ(4,200)  (NSTN(J),TT(J),IKPS(J),J=1,6)
      DO 30 J   = 1,6
      L         = L+1
      ISTO(L,N) = NSTN(J)
      SECT(L,N) = TT(J)
      KWV(L,N)  = IKPS(J)
30    CONTINUE
20    CONTINUE
      KOBS(N)   = NSTM
10    CONTINUE
100   FORMAT(5(I2,X),F6.2,X,F5.2,X,F7.3,X,F6.3,X,F8.3,X,F6.3,
     &       X,F6.2,X,F5.2,X,I3,X,F4.1,X,F5.2,X,F7.3) 
200   FORMAT(6(I3,X,F7.2,X,I2,X))
      RETURN
      END

我想在上面的代码中添加一行来标识代码正在读取的当前行,这样当它挂断时,我就会知道哪一行包含错误。感谢您的帮助。

这是我尝试过的,但它给了我另一个错误:

c      READ(4,200)  (NSTN(J),TT(J),IKPS(J),J=1,6)
  READ(4,200)line
  READ(line,*,iostat=ios) (NSTN(J),TT(J),IKPS(J),J=1,6)
  IF(ios>0)THEN
  WRITE(*,*)'Error Reading Line',line
  STOP
  ENDIF
  INTEGER ios
  CHARACTER*(200)line

【问题讨论】:

  • 适应stackoverflow.com/a/24315813,作为一种方法。
  • 我在尝试调整该答案/建议时遇到了一些麻烦。您介意建议从其他帖子中调整该建议的最佳方法吗?谢谢。
  • 本质上:对于每个read 使用iostat=iostat 整数iostat 并找出iostat.ne.0 的时间。
  • 我在上面添加了编辑,但我仍然遇到错误。关于我在哪里搞砸“适应”的任何想法?谢谢。
  • 您需要将声明(放在底部)放在顶部。

标签: fortran


【解决方案1】:

使用类似的读取语句

      READ(4,200)  (NSTN(J),TT(J),IKPS(J),J=1,6)

输入错误会导致程序(错误)终止。无法控制此终止,尤其是无法进行进一步处理。

有两种方法可以避免这种终止,并且都涉及在 read 语句中使用附加说明符。一个是iostat=,另一个是err=。如果其中任何一个存在,则错误不会导致终止。

使用iostat(对于整数istat):

      READ(4,200,iostat=istat)  (NSTN(J),TT(J),IKPS(J),J=1,6)

然后在错误情况下,istat 将具有(取决于处理器的)正值。当(且仅当)没有错误时,它将为零。

使用err(对于某些标签,例如991):

      READ(4,200,err=991)  (NSTN(J),TT(J),IKPS(J),J=1,6)

把所有这些放在一起,让我们想象一个外部循环

      DO 100 LINE=1,91959
        READ(4,200,IOSTAT=ISTAT) (NSTN(J),TT(J),IKPS(J),J=1,6)
        IF (ISTAT.NE.0) THEN
          PRINT *, 'It went wrong on line', LINE
          STOP
        END IF
        ...
100   CONTINUE

      DO 100 LINE=1,91959
        READ(4,200,ERR=991) (NSTN(J),TT(J),IKPS(J),J=1,6)
        ...
 100  CONTINUE
      ...
 991  PRINT *, 'It went wrong on line', LINE
      STOP

[我无法让自己像 1980 年那样编写代码。]

【讨论】:

    【解决方案2】:

    添加一个显式循环来读取您的数据,例如:

          DO 20 J = 1,6
          write (*,*) 'Reading line = ', J
          READ(4,100)  NSTN(J),TT(J),IKPS(J)
    20    CONTINUE
    
    100   FORMAT(I3,X,F7.2,X,I2,X)
    

    这样,由于读取循环中的 write 语句,您将确切知道它停止的位置。请注意,我添加了两个新标签,20 用于控制新循环,100 用于新格式语句。相应地进行调整。

    ==============

          DO 20  K  = 1,NUMB
          WRITE (*,*) 'Reading line = ', K
          READ(4,200)  (NSTN(J),TT(J),IKPS(J),J=1,6)
          DO 30 J   = 1,6
          L         = L+1
          ISTO(L,N) = NSTN(J)
          SECT(L,N) = TT(J)
          KWV(L,N)  = IKPS(J)
    30    CONTINUE
    20    CONTINUE
          KOBS(N)   = NSTM
    200   FORMAT(6(I3,X,F7.2,X,I2,X))
          RETURN
          END
    

    【讨论】:

    • 把原来的注释掉。这段代码是您原始阅读的替代品。我的意思是一次读取 6 行的读取。
    • 在循环中进行读取与使用隐含执行进行读取不同。
    • @francescalus,我同意你的看法。这是对哪一行数据导致问题的建议。如果我做对了,这就是问题所在。
    • 但这只会测试每行对应前三个数据点的部分。也就是说,它从 6 条记录中读取 3 个数字,而不是从 1 条记录中读取 18 个。
    • 那是一个缺失的部分。您必须将调试写入语句添加到外部循环并保留您的原始代码。
    猜你喜欢
    • 2016-10-12
    • 1970-01-01
    • 1970-01-01
    • 2021-04-17
    • 2020-01-14
    • 2023-03-22
    • 2011-09-22
    相关资源
    最近更新 更多