【问题标题】:Fortran Reading characters from file - no outputFortran 从文件中读取字符 - 无输出
【发布时间】:2017-07-13 23:27:11
【问题描述】:

所以我试图了解一些基本的 fortran IO 并遇到了麻烦。我写了以下

program RFF
implicit none
! Variables
integer :: ierr    
character (:), allocatable :: Filename     
character (:), allocatable :: read_in 

! Body of RFF
Filename = 'string_test.txt' 
open(10, file=Filename, status='old', action='read',iostat=ierr) !What is iostat? 

do while (ierr.eq.0) !What is this do loop doing exactly? 
    read(10,'(A)',iostat = ierr) read_in !What does '(A)' mean? I know it's a format descriptor, but nothing beyond that 
    print*, read_in !Nothing gets output to the terminal here        
enddo

write(*,*) 'Press Enter to Exit'
read(*,*) 

!Is deallocating dynamically allocatable strings something I should do? 
deallocate(Filename) 
end program RFF

我提供了一个非常简单的文本文件,其中包含“任意”一词,仅此而已。当我运行程序时,没有任何崩溃,但也没有任何输出到终端。有人可以帮助我了解发生了什么吗?注意我已经在我粘贴的代码的 cmets 中插入了许多其他问题。我也想帮助理解这些。

谢谢

【问题讨论】:

  • 你应该在循环之前初始化ierr=0。不,在程序结束时解除分配毫无意义。
  • 修改一下,你应该在打开之后额外检查ierr,或者最好不要在open中使用iostat。指定iostat 然后不对结果做任何事情通常是不好的做法。

标签: io fortran


【解决方案1】:

真正的问题是您必须先分配read_in,然后才能使用read 分配给它。另一件事:iostat 用于指示完成状态或可能的错误情况。其他详细信息请参见代码 cmets 和官方文档(例如,here)。

这是一个可行的解决方案:

program main
    implicit none

    character(len=20) :: read_in                     ! fixed-length string
    character(len=:), allocatable :: word, filename  ! allocatable strings
    integer :: iostat_1, iostat_2                    ! status indicators
    integer :: lun                                   ! file logical unit number

    filename = 'read_test.txt'                       ! allocate on assignment
    iostat_1 = 0                                     ! initialization
    iostat_2 = 0

    open(newunit=lun, file=filename, status='old', iostat=iostat_1)
    if (iostat_1 == 0) then                          ! no error occurred
        do while(iostat_2 == 0)                      ! continues until error/end of file
            read(lun, '(a)', iostat=iostat_2) read_in
            if (iostat_2 == 0) then
                word = trim(read_in)                 ! allocate on assignment to trimmed length.
            endif
        enddo
        if (allocated(word)) then
            print *, "read_in:", read_in
            print *, "len(read_in)", len(read_in)
            print *, "Word:", word
            print *, "len(word)=", len(word)
        else
            print *, "Word was not allocated!"
        endif
    endif
end program main

示例输出:

 read_in:arbitrary
 len(read_in)          20
 Word:arbitrary
 len(word)=           9

【讨论】:

  • 你为什么不指定 lun?您只需将其设置为任意数字,对吗?
  • @GeneralPancake 非常细心。 newunit 说明符(来自 2008 标准)打开未使用单元编号的文件,并返回所选编号。我已将该值分配给lun,以便稍后可以使用read 访问正确的单元号。
  • 所以写open命令的时候会自动分配lun?
  • 另外,我似乎无法对可分配数组执行读取操作。这意味着,基本上,我无法读入可分配的数组。这是为什么?这是个人的,但我不想阅读需要预先分配的内容。我的假设是,这是因为您尝试读取的未分配字符串的长度为零,因此 read 正在工作,它只是试图存储到一个带有零空格的数组中。反正有动态分配吗?例如。读取字符数或一次读取一个字符并追加等?
  • newunitlun 赋值,这是一个返回未使用单元号的函数。在大多数情况下,值是什么并不重要,只要您有对它的引用即可。
【解决方案2】:

您的一个代码中有两个问题,所以让我先解决它们:

  • iostat 是什么? -- iostat 是与 I/O 语句相关的错误代码。如果一切正常,它将被设置为0,如果不是,它将具有非零值。尝试打开文件时可能出错的示例:

    • 文件不存在
    • 目录不存在
    • 用户没有打开文件的权限
  • (A) 是什么? -- 这是格式字符串。 (A) 指的是任意长度的字符串。更多信息请见here

代码看起来应该可以工作,但结果却不是您所期望的。我想到了两种可能性:

  1. 您尝试读取的文件不存在,或者在您执行程序的目录中不存在,或者您没有读取它的权限。这导致ierr 被设置为非零错误代码(对应于“未找到文件”)。这会导致 do 循环甚至不会执行一次,因为 ierr 一开始就不是零。

    除了iostat,我建议使用更新的iomsg 语句。 iomsg 是一个字符串,对应于人类可读的错误解释。

    character(len=100) :: iomsg
    <snip>
    open(10, file=Filename, status='old', action='read',iostat=ierr, iomsg=iomsg)
    if (ierr /= 0) then
        print*, "Error opening file " // trim(Filename)
        print*, iomsg
        STOP 1
    end if
    
  2. 文件存在,但为空。这将导致不打印任何内容。只需检查以确保文件中没有任何更改。

提示,iostatiomsg 在所有文件 I/O 操作中都可用,readwrite 甚至 close 也是如此。使用它们不会有什么坏处。

【讨论】:

    猜你喜欢
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 2014-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多