【发布时间】:2011-11-10 23:15:09
【问题描述】:
如何读取包含已知行数但每行中的条目数未知的数据文件,例如如果我的数据文件包含类似
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
即三行,但每行中的数据是未知的。有一次我需要来自一行的数据。
【问题讨论】:
标签: 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
即三行,但每行中的数据是未知的。有一次我需要来自一行的数据。
【问题讨论】:
标签: fortran
基于 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)
【讨论】:
假设您可以用零填充数组(具体参考后面的重复问题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
【讨论】:
这是一个程序,可以计算一行(或列数)中的数字,但只计算一行。如果你有很多行,你应该稍微改变一下。
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
【讨论】:
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
【讨论】:
一种方法:将行读入字符串,使用至少与最长预期行一样长的字符串。然后你开始解析字符串。例如,如果数字总是用空格分隔,则使用它来确定子字符串的边界。然后您可以使用“内部读取”从每个子字符串中读取以获取数值。内部读取使用字符串而不是单位编号并从字符串中获取数据——至少您不必重新创建字符到数值的转换,读取语句会为您完成。 Fortran 提供的内在函数将使解析更容易。
【讨论】: