问题
I would like to read and store scientific formatted numbers from a txt file, which is formatted and the numbers are separated by tabulator.
This is what I have so far:
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)
This is how the txt file looks like:
200
35
2.9900E-35 2.8000E-35 2.6300E-35 2.4600E-35 2.3100E-35 2.1600E-35 ...
The problem is that it doesn't read and store the correct values from the txt to the data variable. Is it the format causing the problem?
I would also like to know how to count the number of columns in this case. (I can count the rows by using read(86,*) in a for loop.)
回答1:
Yes, your format is not good for the data you show. Better one should be like that read(99,'(6(E11.4,X))') myData(i,:)
.
However, I am not sure if you really need to use format at your reading at all.
Following example pretty close to what you are trying to do, and it is working bot with and without format.
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
To test, I assumed that you have rows and columns always in the file, as you give, so my test data was following.
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
If you are really interested to read your files with a format and if the number of columns are not constant you may need a format depending on a variable, please see related discussions here.
回答2:
Though there are no direct command to count the number of items in a line, we can count the number of periods or (E|e|D|d) by using the scan command. For example,
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
Please note that pattern (1) works only when all items have periods, while pattern (2) works only when all items have exponents:
# 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
For more general purposes, it may be more convenient to write a custom "split()" function that separate items with white spaces (or use an external library that supports a split function).
来源:https://stackoverflow.com/questions/40058712/read-scientific-formatted-numbers-from-txt