如何从一行中具有不同列的文件中读取数据

How to read data from a file with different column in a line

我想从一个文件中读取数据,其中每一行都有不同数量的数据,例如

a b c d
e f 
h g k

我需要这样的格式 format(T8,<num>(I7)) 其中 <num> 是在 运行 时间内确定的动态格式说明符,它指定了输入文件一行中的列数。 这是我要修改的代码。该代码在 Intel fortran 中有效,但在 gfortran 中出现错误。

 do i=1,N
    read(20,'(I7)') CV(i,1)

    backspace(20)
    15 format(T8,CV(i,1)(I7))
    read(20,15) CV(i,2:CV(i,1)+1)
 end do

错误信息是

         15 format(T8,CV(i,1)(I7))
                      1
Error: Unexpected element ‘C’ in format string at (1)

您不需要可变格式来执行此操作。

处理输入列表时,处理输入项所需的任何值都在开始处理该项时确定。在这种情况下,可以使用一行的第一项来确定要读取的数组元素:

read(20, '(*(I7))') CV(i,1), CV(i,2:CV(i,1)+1) 

格式的重复说明符("number of items to read"方面),在这种情况下,尝试使用CV(i,1)的意思是什么,不需要匹配项目的数量:它只需要更大(在本例中 * 表示 "unlimited")。当列表中的所有项目都已读取时,处理停止。

这可以通过内部写入构造格式来完成,如下所示:

character(Len=30) :: form
do i=1,N
    read(20,'(I7)') CV(i,1)
    write( form, '(a,i0,a)' )  '(', CV(i,1), 'i7)'
    backspace(20)
    read(20,form) CV(i,2:CV(i,1)+1)
end do

为了避免 BACKSPACE,这真的很耗时,我通常更喜欢将输入读入字符行,然后我可以快速分析它。在您的特定情况下,由于输入数据的数量始终作为数据项 1 给出,@francescalus 给出的答案非常好。如果线条变化更大,您可以扩展以下代码(目前只是您的示例)

program read_data
! 
integer, parameter :: MAX_DATA=10
integer, parameter :: MAX_ROWS=4
integer :: ios
integer :: i
character(len=18+7*MAX_DATA) :: line
integer, dimension(MAX_ROWS, MAX_DATA) :: cv
!
cv(:,:) = 0
open(unit=20, file='data.txt')
main_loop: do i=1, 4
  read(20, '(a)', iostat=ios) line
  if(is_iostat_end(ios)) exit main_loop
  read(line(1:len_trim(line)),'(*(i2))', iostat=ios) cv(i,1), cv(i,2:cv(i,1)+1)
  if(.not.(ios==0 .or. is_iostat_end(ios))) exit main_loop
  write(*,*) i,cv(i,1), cv(i,1:6)
enddo main_loop
!
end program read_data