Reputation: 2049
I have a file looking like this:
startSpecifier
( 251)-0.0110365 ( 168)-0.0110365 ( 1267) 0.0108601 ( 980) 0.0108601 (
( 251)-0.0110365 (
endSpecifier
I don't know how often the format repeats per line in the infile.
I need to get arrays looking like this (for the upper example):
a=[251, 268, 1267, 980, 251]
b=-0.0110365, -0.0110365, 0.0108601,...]
Any suggestions as to how to tackle the problem?
Upvotes: 1
Views: 523
Reputation: 3812
In my oppinion, you have basically two options:
You program a linked list in Fortran, read the file line by line, parse the lines and append the elements you extract into your linked lists. When the reading is finished, you convert your linked lists into arrays. We are doing that when reading in user data of unknown length in DFTB+, but that requires unfortunately quite a lot of programming.
Alternatively, you could use a script language to extract data from your input file and store in a more Fortran-friendly format. Below an example in Python, but you can use any other script language of your choice:
from __future__ import print_function
import sys
import re
PAT1 = re.compile(r"\(\s*(?P<int>\d+)\)")
PAT2 = re.compile(r"\)\s*(?P<float>-?\d+\.\d+)\s*\(")
txt = sys.stdin.read()
ints = PAT1.findall(txt)
floats = PAT2.findall(txt)
print(len(ints))
print(" ".join(ints))
print(" ".join(floats))
Store the script as convert.py and run it like:
python convert.py < mydata.dat > newdata.dat
where I assumed, that your data is stored in mydata.dat
. The new file newdata.dat
would then look like:
5
251 168 1267 980 251
-0.0110365 -0.0110365 0.0108601 0.0108601 -0.0110365
This you can easily parse with Fortran by reading the integer in the first line, allocate your integer and float array to the size given in it, and read in the two arrays with two read statements.
Upvotes: 1
Reputation: 60088
I would use
do line = 1,nlines !or just do and exit on end of file, it's up to you
lower = (line-1)*items_per_line + 1
upper = line*items_per_line
read (unit,fmt='(999(tr1,i5,tr1,f11))') (a(i),b(i),i=lower,upper)
end do
Add any other read(unit,*)
to skip lines where apropriate.
If the field widths are really fixed, as it seems from your example.
Upvotes: 0