How do I extract a floating number in the middle of an alphanumeric chain?

123 views Asked by At

I am coding in Fortran 95.

I must extract the two floating values from this line in an ascii file:

circle(4097.0438,4111.337)

Of course the READ statement is

read(unit=11, fmt="(tr7,f9.4,tr1,f8.3)") x, y

The problem is that I must do that for hundreds of ascii files, but there are variations in the number of digits. For instance:

circle(201.043,7250.1234) # which would require fmt="(tr7,f7.3,tr1,f9.4)"

circle(0.004038,9999.12) # which would require fmt="(tr7,f8.6,tr1,f7.2)"

circle(0.004038,22.1234) # etc

Therefore I cannot use a single format. I don't know how to read those x, y coordinates using free format because I must skip the first 7 spaces anyway.

2

There are 2 answers

3
roygvib On BEST ANSWER

Reading in the data into a string buffer and removing unnecessary parts probably work.

program main
    character(100) :: buf
    real :: x, y

    read( *, "(a)" ) buf
    buf = buf( 8 : len(trim(buf))-1 ) !! remove "circle(" and ")"
    read( buf, * ) x, y               !! read two reals (commas/spaces are regarded as separators)
    print *, x, y
end

Another way is to use index() to find "(" and ") [please see ref also]. In this case the data may contain any string before "(" or after ")". Similar methods can be used to extract necessary parts in more complicated cases.

integer :: n1, n2
n1 = index( buf, "(" )
n2 = index( buf, ")" )
read( buf( n1+1 : n2-1 ), * ) x, y
4
francescalus On

To supplement roygvib's answer I'll add a "cute" something. This takes the suggested approach of using list-directed input from an internal file.

program main
  character(100) :: buf
  complex :: temp
  real :: x, y

  read( *, "(a)" ) buf
  read(buf(7:), *, decimal='point') temp ! read a complex
  x = temp%RE                            ! assign x as real part of that
  y = temp%IM                            ! assign y as imaginary part

  print *, x, y
end

[Instead of temp%RE, temp%IM, possibly REAL(temp), AIMAG(temp).]

This works because we know that for a complex number with list-directed input (Fortran 2008, 10.10.3)

the input form consists of a left parenthesis followed by an ordered pair of numeric input fields separated by a comma (if the decimal edit mode is POINT) or semicolon (if the decimal edit mode is COMMA), and followed by a right parenthesis.

I made the decimal='point' explicit in the code above. I also didn't remove the prefix from the buffer character variable itself.

Yes, this offers very little except less worry about removing the parantheses.