drjrm3
drjrm3

Reputation: 4718

Parsing strings in Fortran

I am reading from a file in Fortran which has an undetermined number of floating point values on each line (for now, there are about 17 values on a line). I would like to read the 'n'th value on each line to a given floating point variable. How should i go about doing this?

In C the way I wrote it was to read the entire line onto the string and then do something like the following:

for(int il = 0; il < l; il++)
{
    for(int im = -il; im <= il; im++)
        pch = strtok(NULL, "\t ");
}
for(int im = -l; im <= m; im++)
    pch = strtok(NULL, "\t ");
dval = atof(pch);

Here I am continually reading a value and throwing it away (thus shortening the string) until I am ready to accept the value I am trying to read.

Is there any way I can do this in Fortran? Is there a better way to do this in Fortran? The problem with my Fortran code seems to be that read(tline, '(f10.15)') tline1 does not shorten tline (tline is my string holding the entire line and tline1 what i am trying to parse it into), thus I cannot use the same method as I did in my C routine.

Any help?

Upvotes: 3

Views: 7663

Answers (3)

Alberto
Alberto

Reputation: 1

Alternatively, the string can be generated directly as an output by means of the WRITE statement to strip whatever character is unwelcome:

character(len=12), dimension(  12) :: file_name        ! filename
character(len=24), dimension(  12) :: files            ! directory path + filename
character(len= 8), dimension(  14) :: short            ! stores filename without path & file extension

...

do i=1,m
   files(i)= './debug/emi/'//file_name(i)
   write(short(i),"(a8)")    file_name(i)
end do
call show(io_unit, files, short)
!.. Generates the output
    file #: 1  ./debug/emi/cicle_a2.dat  cicle_a2
    file #: 2  ./debug/emi/cicle_a5.dat  cicle_a5

Upvotes: 0

eriktous
eriktous

Reputation: 6659

If you know exactly at what position the value you want starts, you can use the T edit descriptor to initiate the next read from that position.
Let's say, for instance, that the width of each field is 10 characters and you want to read the fifth value. The read statement will then look something like the following.

read(file_unit, '(t41, f10.5)') value1

P.s.: You can dynamically create a format string at runtime, with the correct number after the t, by using a character variable as format and use an internal file write to put in this number.
Let's say you want the value that starts at position n. It will then look something like this (I alternated between single and double quotes to try to make it more clear where each string starts and stops):

write(my_format, '(a, i0, a)') "(t", n, ', f10.5)'
read(file_unit, my_format) value1

Upvotes: 0

tpg2114
tpg2114

Reputation: 15110

The issue is that Fortran is a record-based I/O system while C is stream-based.

If you have access to a Fortran 2003 compliant compiler (modern versions of gfortran should work), you can use the stream ACCESS specifier to do what you want.

An example can be found here.

Of course, if you were really inclined, you could just use your C function directly from Fortran. Interfacing the two languages is generally simple, typically only requiring a wrapper with a lowercase name and an appended underscore (depending on compiler and platform of course). Passing arrays or strings back and forth is not so trivial typically; but for this example that wouldn't be needed.

Once the data is in a character array, you can read it into another variable as you are doing with the ADVANCE=no signature, ie.

do i = 1, numberIWant
   read(tline, '(F10.15)', ADVANCE="no") tline1
end do

where tline should contain your number at the end of the loop.

Because of the record-based I/O, a READ statement will typically throw out what is after the end of the record. But the ADVANCE=no tells it not to.

Upvotes: 2

Related Questions