从txt中读取科学格式的数字



我想从一个txt文件中读取和存储科学格式的数字,该文件是格式化的,数字由制表符分隔。

这是我目前为止写的:

IMPLICIT NONE
REAL,ALLOCATABLE,DIMENSION(2)    :: data(:,:)       
INTEGER              :: row,column
INTEGER              :: j,i
CHARACTER(len=30)        :: filename
CHARACTER(len=30)        :: format
filename='data.txt'
open(86,file=filename,err=10)
write(*,*)'open data file'   
read(86, *) row
read(86, *) column
allocate(data(row,column))
format='(ES14.7)'   
do i=1,row
  read(86,format) data(i,:)
enddo
close(86)

txt文件是这样的:

200
35
2.9900E-35  2.8000E-35  2.6300E-35  2.4600E-35  2.3100E-35  2.1600E-35  ...

问题是它没有读取和存储从txt到data变量的正确值。是格式造成的问题吗?

我还想知道在这种情况下如何计算列的数量。(我可以通过在for循环中使用read(86,*)来计算行数。)

是的,您的格式不适合您显示的数据。更好的应该是这样的read(99,'(6(E11.4,X))') myData(i,:)

然而,我不确定你是否真的需要在阅读中使用格式。

下面的例子非常接近你要做的,它可以工作,无论有没有格式。

program readdata
  implicit none
  real, allocatable :: myData(:,:)
  real              :: myLine
  integer           :: i, j, myRow, myColumn
  character(len=30) :: myFileName
  character(len=30) :: myFormat
  myFileName='data.dat'
  open(99, file=myFileName)
  write(*,*)'open data file'
  read(99, *) myRow
  read(99, *) myColumn
  allocate(myData(myRow,myColumn))
  do i=1,myRow
    read(99,*) myData(i,:)
    !read(99,'(6(E11.4,X))') myData(i,:)
    print*, myData(i,:)
  enddo
  close(99)
end program readdata

为了测试,我假设文件中总是有行和列,如您所给的,所以我的测试数据如下:

2
6
2.9900E-35  2.8000E-35  2.6300E-35  2.4600E-35  2.3100E-35  2.1600E-35
2.9900E-35  2.8000E-35  2.6300E-35  2.4600E-35  2.3100E-35  2.1600E-35

如果您真的对使用格式读取文件感兴趣,并且如果列数不是恒定的,则可能需要根据变量设置格式,请参阅此处的相关讨论。

虽然没有直接命令来计算一行中的项数,但我们可以使用scan命令来计算句点或(E| E| D| D)的数量。例如,

program main
    implicit none
    character(100) str
    integer n  
    read( *, "(a)" ) str
    call countreal( str, n )
    print *, "number of items = ", n
contains
subroutine countreal( str, num )
    implicit none
    character(*), intent(in)  :: str
    integer,      intent(out) :: num
    integer pos, offset
    num = 0
    pos = 0
    do
        offset = scan( str( pos + 1 : ), "." )        !! (1) search for periods
        !! offset = scan( str( pos + 1 : ), "EeDd" )  !! (2) search for (E|e|D|d)
        if ( offset > 0 ) then
            pos = pos + offset
            num = num + 1
            print *, "pos=", pos, "num=", num   !! just for check
        else
            return
        endif
    enddo
endsubroutine
end

请注意,模式(1)只在所有项都有句号时起作用,而模式(2)只在所有项都有指数时起作用:

# When compiled with (1)
$ echo "2.9900  2.8000E-35  2.6300D-35  2.46  2.31" | ./a.out
 pos=           2 num=           1
 pos=          10 num=           2
 pos=          22 num=           3
 pos=          34 num=           4
 pos=          40 num=           5
 number of items =            5
# When compiled with (2)
$ echo "2.9900E-35  2.8000D-35  2.6300e-35  2.4600d-35" | ./a.out
 pos=           7 num=           1
 pos=          19 num=           2
 pos=          31 num=           3
 pos=          43 num=           4
 number of items =            4

对于更一般的用途,编写一个自定义的"split()"函数可能更方便,该函数用空格分隔项(或使用支持split函数的外部库)。

相关内容

  • 没有找到相关文章

最新更新