如何在Fortran中将文本文件读入数组

时间:2015-05-27 18:30:49

标签: arrays fortran

有没有办法压缩这段代码?

.
.
real*4 a4,e4,inc4,capom4,omega4,capm4
integer*2 id2
real*8 array(1e7,8)
.
.
row=0
do n=1,nleft+nbod2-1
 row=row+1
 read(iu) id2,a4,e4,inc4,capom4,omega4,capm4    
 array(row,1)=id2
 array(row,2)=a4
 array(row,3)=e4
 array(row,4)=inc4
 array(row,5)=capom4
 array(row,6)=omega4
 array(row,7)=capm4
end do
.
.

我尝试了五种不同的方式,从隐含的DO循环开始,所有结果都是" forrtl:严重(67):输入语句需要太多数据......"。

3 个答案:

答案 0 :(得分:2)

你无法凝聚的原因

 read(iu) id2,a4,e4,inc4,capom4,omega4,capm4    
 array(row,1)=id2
 array(row,2)=a4
 array(row,3)=e4
 array(row,4)=inc4
 array(row,5)=capom4
 array(row,6)=omega4
 array(row,7)=capm4

read(iu) (array(row,i), i=1:7)

是因为这会导致数据文件与读取参数不匹配。在下面评论中提供的来源中,您将这些变量声明为:

real*4 ttmp,a4,e4,inc4,capom4,omega4,capm4
integer*2 nleft,nbod2,id2
real*8 array(1e7,8)

这意味着您的read调用read(iu) id2,a4,e4,inc4,capom4,omega4,capm4正在请求26个字节(1 * 2个字节+ 6 * 4个字节),这对应于注释中提供的无格式文件中的记录大小。

将读取更改为:

read(iu) (array(row,i), i=1:7)

它本身完全有效,它不再匹配二进制文件,读取失败。此读取请求56个字节(7 * 8个字节)并产生您正在报告的致命运行时错误(您从26字节记录请求56个字节)。读取中使用的临时变量是必需的,这样您就可以读取2字节整数和4字节浮点数,然后将它们分配给8字节实数变量。读取无法直接完成此操作,因为文件中的基础二进制数据不是8字节实数。

那你能做什么?

在您下面发布的代码中,您的阅读略有不同

  read(iu) id2,a4,e4,inc4,capom4,omega4,capm4

  array(row,1)=id2
  array(row,2)=ttmp
  array(row,3)=a4
  array(row,4)=e4
  array(row,5)=inc4
  array(row,6)=capom4
  array(row,7)=omega4
  array(row,8)=capm4

你可以取消6个命名的临时变量,而是使用6个实数的数组。 e.g。

real*4 :: readtemp(6)
.
.
do n=1,nleft+nbod2-1
  read(iu) id2,readtemp 
  array(n,1)=id2
  array(n,2)=ttmp
  array(n,3:8)= readtemp
end do

这可以让您摆脱6个单独的实数换取一个数组,并将6个赋值浓缩为1个赋值。读取/分配组合并不像其他答案那样完全崩溃,但这确实避免了需要定义类型来完成它。

答案 1 :(得分:0)

你还没有真正向我们展示提供非常好的建议。将其留在一边,这可能有用:

替换块

row=0
do n=1,nleft+nbod2-1
 row=row+1
 read(iu) id2,a4,e4,inc4,capom4,omega4,capm4    
 array(row,1)=id2
 array(row,2)=a4
 array(row,3)=e4
 array(row,4)=inc4
 array(row,5)=capom4
 array(row,6)=omega4
 array(row,7)=capm4
end do

do n=1,nleft+nbod2-1
 read(iu) array(n,1:7)    
end do

在任何进一步的问题中,请准确发布您遇到问题的代码,以及编译器或运行时报告的错误。

答案 2 :(得分:0)

由于OP的代码涉及包含> y@.Data [[1]] [1] 1 2 3 4 [[2]] [1] 5 6 7 8 的混合数据类型,因此integer*2的直接使用似乎无效。所以我又做了两次试验来浓缩代码。第一个是

read(iu) array( n, 1:7 )

保存了一些代码行,但仍然有点冗长。所以第二次试验是

read(iu) id2, a4, e4, inc4, capom4, omega4, capm4
array( n, : ) = [ real*8 :: id2, a4, e4, inc4, capom4, omega4, capm4 ]

并将未格式化的文件读为

type dat_t
    sequence
    integer*2 :: id2
    real*4    :: a4, e4, inc4, capom4, omega4, capm4
endtype

type(dat_t) :: dat( 10000 )   !! or allocate() if necessary

获得的数据可以照常使用,例如do n = 1, nleft + nbod2 - 1 read(iu) dat( n ) enddo 。这里放置关键字dat( n )% a4以确保内存中变量的连续排列非常重要。否则会出现与OP案例相同的错误......

我用下面的代码(使用gfortran4.8和ifort14.0)测试了这个

sequence