在Fortran中读取具有已知行数但每行中未知条目数的数据文件

时间:2011-09-06 01:50:50

标签: fortran

如何读取包含已知行数的数据文件,但每行中的条目数未知,例如如果我的数据文件包含某些内容,如

  

1 3 4 5 6 -7 8 -9

     

1 3 5 6

     

4 5 6 7 8 3 5 6 7 8 4 5 7 8

即。三行,但每行的数据是未知的。有一次我需要一行数据。

5 个答案:

答案 0 :(得分:8)

一种方法:使用至少与最长预期行一样长的字符串将行读入字符串。然后你去解析字符串。例如,如果数字总是按空格分割,则使用它来计算子串边界。然后,您可以使用“内部读取”从每个子字符串中读取以获取数值。内部读取使用字符串而不是单元号并从字符串中获取数据 - 至少您不必重新创建字符到数值的转换,read语句将为您执行此操作。 Fortran提供的内部函数将使解析更容易。

答案 1 :(得分:2)

假设你可以用零填充数组(特别是指后面的重复问题here),这是我的想法:

逐行读取数据到一个字符串,然后附加一些零,最后从这个数组中读取每一行数据。这是一个例子:

program unknown_numbers

    implicit none
    integer, parameter :: nrow=3, ncol=14
    integer :: data(ncol, nrow)
    character(len=2*ncol) :: zeros ! will contain lots of zeros
    character(len=10*ncol) :: line ! temporary storage for each line of the file
    integer :: i, u

    ! Write " 0 0 0 0 0 0 0 0" into the string "zeros"
    write(zeros, '(*(I2))') [(0, i=1, ncol)]

    open(newunit=u, file='data.txt', status='old', action='read')

    do i = 1, nrow, 1
        ! Read the next line into a temporary string array
        read(u, '(A)') line
        ! Append a number of zeros to the temporary string
        line = trim(line) // zeros
        ! Read the row of data from the string.
        read(line, *) data(:, i)
    end do

    close(u)

    ! For testing purposes, print the data.
    print '(14(X, I3))', data

end program unknown_numbers

答案 2 :(得分:1)

integer,parameter :: reclen=99999        ! maximum record length
integer,parameter :: undef=-9999         ! undefined value
integer :: actual_reclen                 ! actual record length
integer,dimension(reclen) :: dummy=undef ! dummy array used for reading
integer,dimension(:),allocatable :: a    ! final array

open(unit=10,file='sample.txt',form='formatted',access='sequential')
read(unit=10,fmt=*,end=101)(dummy(i),i=1,reclen)
101 close(unit=10)

actual_reclen=COUNT(dummy/=undef)
allocate(a(actual_reclen))
a=dummy(1:actual_reclen)

end

答案 3 :(得分:1)

基于M.S. B.指出的实现。很晚了,但我想这可能对某人有用。

具有您希望已准备好阅读的类型的数组:

double precision, dimension(MAX_NUM_OF_COLS) :: test_array

从文件中读取一行:

READ(reading_unit,'(A)',iostat=io) line

循环并尝试从该行读取最大数量的数字:

do i=1,MAX_NUM_OF_COLS
  READ(line, *, iostat=io) test_array(1:i)
  if(io==0) exit
enddo

write(*,*) 'number of columns = ', (i-1)

如果需要,可以在文件的所有行上循环,并保留最大或最小列数。

最小示例:

integer, parameter :: MAX_NUM_OF_COLS=30
integer, parameter :: MAX_LINE_LENGTH=1000
character(len=MAX_LINE_LENGTH) line
integer i, io, reading_unit
double precision, dimension(MAX_NUM_OF_COLS) :: test_array

reading_unit=100
OPEN(reading_unit, file='the_file')

! Get first line of file.
DO
  READ(reading_unit,'(A)',iostat=io) line
  IF (io/=0) then
    write(*,*) "Error reading file."
    stop
  endif
  exit ! Eventually, do not exit and put the DO loop below here.
ENDDO
CLOSE(reading_unit)

do i=1,MAX_NUM_OF_COLS
  READ(line,*,iostat=io) test_array(1:i)
  if(io==-1) exit
enddo

write(*,*) 'number of columns = ', (i-1)

答案 4 :(得分:-3)

这是一个可以计算一行(或列数)但是一行的数字的程序。如果你有很多行,你应该稍微改一下。

program test12

implicit none

integer n,m,i

integer,allocatable::x(:)

 open(10,file='C:\Users\user\Desktop\file.txt')

allocate(x(n))

20 n=n+1

 deallocate(x) 



 allocate(x(n))

read(10,*,iostat=m)(x(i),i=1,n)

if (m==-1)then

goto 30

else


rewind 10

 goto 20

end if

 30 print*,n-1

 end