【问题标题】:Fortran: reading file with unknown number of linesFortran:读取行数未知的文件
【发布时间】:2021-09-14 19:56:28
【问题描述】:

我正在尝试打开行数未知的 ASCII 文件(但每行中的条目数固定 - 请参阅下面的示例文件)。它转到文件末尾,但之后失败。

选项 1:使用 iostat 语句:使用“Use, intrinsic :: iso_fortran_env, Only : iostat_end”或简单地将 io 视为整数时,我得到相同的错误。

选项 2:使用“end= ..”选项。这是我之前使用的(F77)。

这两种方法原则上都应该有效,但两者都没有。任何解决此问题的帮助将不胜感激。

谢谢, 皮纳基。

计划

!=======================================!
program read
!=======================================!
!  Use, intrinsic :: iso_fortran_env, Only : iostat_end
  implicit none

  integer :: i,io,n     

  n=0
  open(10,file='a.dat',status='old',action='read')

!=================================!
! option 1
!=================================!  
  do 
     read(10,*,iostat=io)
     write(*,*)io
!     if (io.eq.iostat_end) exit
     if (io.ne.0) exit
     n=n+1
     write(*,*)'n=',n
  enddo
!=================================!

!=================================!
! option 2
!=================================!
  do 10 i=1,1000000
     read(10,*,end=10)
     n=n+1
     write(*,*)n
10   continue
!================================!

  close(10)
  write(*,*)'n=',n
  
end program read
!======================!

使用“gfortran --std=f2003 -o read.out read.f90”编译

错误信息:

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

dyld: lazy symbol binding failed: Symbol not found: ___emutls_get_address
  Referenced from: /usr/local/opt/gcc/lib/gcc/11/libgfortran.5.dylib
  Expected in: /usr/lib/libSystem.B.dylib

dyld: Symbol not found: ___emutls_get_address
  Referenced from: /usr/local/opt/gcc/lib/gcc/11/libgfortran.5.dylib
  Expected in: /usr/lib/libSystem.B.dylib

程序收到信号SIGABRT:进程中止信号。

此错误的回溯: #0 0x105364f8e #1 0x10536419d #2 0x7fff6eed05fc zsh: 中止 ./read.out

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

我正在阅读的文件:

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

 1    -1.1559859375    2.0399371094    0.1686166667    0.8242152778
  2    -1.1618015625    2.1375250000    0.1765231481    0.8105046296
  3    -1.1696710937    2.2325417969    0.1860513889    0.7936782407
  1    -1.1730312500    2.3271382813    0.1975254630    0.7718773148
  2    -1.1767945313    2.3942726563    0.2113162500    0.7446933333
  3    -1.1694437500    2.4738000000    0.2281966667    0.7099266667
  1    -1.1566140625    2.5312164063    0.2494466667    0.6636841667
  2    -1.1293765625    2.5746707031    0.2747766667    0.6066154167
  3    -1.0836390625    2.5938144531    0.3026616667    0.5403733333
  1    -1.0380632812    2.5721433594    0.3302462121    0.4727159091

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

【问题讨论】:

标签: fortran


【解决方案1】:

我测试了您的代码,第一个选项有效。如果您从do 10 i=1,1000000 中删除标签10 并在10 continue 之前添加end do,您的第二个选项也将起作用。您还必须在第二个选项的 do 循环之前添加 rewind(10)close(10); open(10,file='a.dat',status='old',action='read')。但更有趣的是,在 Fortran 2008 中使用检查文件结尾错误代码出现的 is_iostat_end() 内部函数很容易解决这个问题。这是一个现代的实现,

program read
    implicit none
    integer :: i, n, iostat, fileUnit
    n = 0
    open(newunit = fileUnit, file = 'a.dat', status = 'old', action = 'read')
    do
         read(fileUnit,*,iostat = iostat)
         if (is_iostat_end(iostat)) exit
         write(*,*) iostat
         n = n + 1
         write(*,*)'n = ', n
    end do
    close(fileUnit)
end program read

使用以下命令编译并运行它,

gfortran --std=f2008 -o read.out read.f90
./read.out

尽管问题很小,但您通过提供完整代码、数据文件、编译代码的方法以及遇到的错误提出了一个非常好的问题。它值得一票。

【讨论】:

  • 好吧,如果您尝试编写原始代码,则在第一个选项的代码执行后,第二个选项将永远无法工作。在这里,never work 意味着给出想要的结果。在执行选项 2 循环之前,需要设置 n = 0 rewind(10)
  • 设置n = 0 没有任何作用。我之前尝试过close(10); open(...),但rewind(10) 更好。但即使这样也不够。问题在于错误的退出行10 continue。我已经为答案添加了一个解决方案。感谢您提供更多深入研究的动力。
  • @roygvib 感谢您的仔细观察。在这种特殊情况下,它是无关紧要的,因为它在主代码中并且只执行一次。但我理解你的担忧,并且在写这篇文章时实际上考虑了这个常见的误解。固定。
  • @king,在原始代码中的选项 2 之前设置 n = 0 将确保在单元已倒带的情况下正确计算文件中的行数。很好地抓住了end=1010 continue 行的分支。我在大部分代码中使用选项 2 惯用语,但我的 end=10 通常会分支到 do-loop 之外的 `10 rewind(unit=10)` 以进一步处理文件内容。
  • @King:感谢您的详细回答。我真的很感激。当我尝试选项 1 或 2 时,我应该在代码中注释掉选项 2,而不是同时尝试两者。不幸的是,我仍然遇到同样的错误 - 所以我猜这是 roygvib 建议的 gcc 安装问题。我现在就试试。
猜你喜欢
  • 2017-10-30
  • 2011-11-10
  • 2016-06-22
  • 1970-01-01
  • 1970-01-01
  • 2015-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多