读取未知形状的多维数组

PT2*_*009 5 arrays fortran dynamic-arrays fortran90

我想从文件中获取数据,该文件的数据内容可以具有可变大小。然而,结构非常简单。3 列和未定义的行数。我认为使用可分配的多维数组和显式 DO 循环可以解决我的问题。到目前为止,这是我的代码

program arraycall
    implicit none

    integer, dimension(:,:), allocatable :: array
    integer :: max_rows, max_cols, row, col

    allocate(array(row,col))

    open(10, file='boundary.txt', access='sequential', status='old', FORM='FORMATTED')

     DO row = 1, max_rows
       DO col = 1, max_cols
            READ (10,*) array (row, col)
       END DO
     END DO

     print *, array (row,col)

     deallocate(array)

 end program arraycall 
Run Code Online (Sandbox Code Playgroud)

现在我面临的问题是我不知道应该如何定义这些 max_rows 和 max_cols ,这与它的大小未知的事实产生共鸣。

示例文件可能看起来像

11 12 13

21 22 23

31 32 33

41 42 43
Run Code Online (Sandbox Code Playgroud)

所以我想出了一种动态(动态)估计文件记录长度的方法。更新一下,方便以后给其他人参考

!---------------------------------------------------------------------
! Estimate the number of records in the inputfile
!---------------------------------------------------------------------
    open(lin,file=inputfile,status='old',action='read',position='rewind')

    loop1: do
      read(lin,*,iostat=eastat) inputline
      if (eastat < 0) then
        write(*,*) trim(inputfile),": number of records = ", numvalues
        exit loop1
      else if (eastat > 0 ) then
        stop "IO-Error!"
      end if

      numvalues=numvalues+1
    end do loop1
!-----------------------------------------------------------------------
! Read the records from the inputfile
!-----------------------------------------------------------------------
    rewind(lin)
    allocate (lon(numvalues),lat(numvalues),value(numvalues))

    do i=1,numvalues
      read(lin,*) lon(i),lat(i),value(i)
    end do

    close(lin)
Run Code Online (Sandbox Code Playgroud)

Ale*_*ogt 1

您可以定义允许的最大行数并使用它iostat来检查文件末尾(或错误):

program arraycall 

  implicit none
  integer, dimension(:,:), allocatable :: array
  integer           :: row
  integer           :: stat ! Check return values
  ! Define max. values
  integer,parameter :: max_rows=1000
  integer,parameter :: max_cols=3    ! As stated in the question
  ! Total number of rows in the file
  integer           :: tot_rows

  allocate( array(max_cols,max_rows), stat=stat)
  ! Always a good idea to check the return value
  if ( stat /= 0 ) stop 'Cannot allocate memory!'

  open(10, file='boundary.txt', access='sequential', &
       status='old', FORM='FORMATTED')

  DO row = 1, max_rows
    ! You can directly read in arrays! 
    READ (10,*,iostat=stat) array(:,row)
    if ( stat > 0 ) then
      stop 'An error occured while reading the file'
    elseif ( stat < 0 ) then
      tot_rows = row-1
      print *, 'EOF reached. Found a total of ', tot_rows, 'rows.'
      exit
    endif
  END DO

  close(10)

  ! Do stuff, e.g. re-allocate the array
  print *,array(:,:tot_rows)

  deallocate(array)
end program arraycall 
Run Code Online (Sandbox Code Playgroud)

iostat > 0是一个错误,iostat < 0是文件结束符(或某些编译器的记录结束符)。