Reputation:
I am new to FORTRAN, and must write a FORTRAN 77 program to read the following format from a file redirection or standard input:
[CHARACTER] [REAL] [REAL] [REAL] ... (can have any number of these)
D [INTEGER] (only one of these)
[REAL] [REAL] [REAL] ... (can have any number of these)
example input could be:
T 1.0 2.0 3.0
S 1.0 2.0 4.0
Y 3.0 4.0 5.0
D 2
3.0 5.0 6.0
4.5 4.6 5.6
My native language is C++, so I'm new to this whole idea of a read statement going to the next line automatically.
So far, I have the following code:
c234567
character*1 D
character*1 LETTER
real X, Y, Z
integer lines
real point1, point2, point3
85 format (3F10.6)
100 format (A1, 5X, F10.6, 5X, F10.6, 4X, F10.6)
990 format (A, I10)
MAX = 6
LETTER = 'Z'
D = 'D'
read *, LETTER, X, Y, Z
10 if(LETTER .ne. D) then
write (6, 100) LETTER, X, Y, Z
read *, LETTER, X, Y, Z
goto 10
else
goto 20
endif
C =====================================================
20 lines = aint(X)
write (*,990) 'LINES: ', lines
write (6, 85) X, Y, Z
read *, Z
write (6, 85) X, Y, Z
end
As you can see, I get the first portion of the input fine, but after that it kind of all goes to mush because of the read statement: read*, Z going to the next line. In my specific input file provided above, I get the 2 after the D, and the next two values (3.0, 5.0) but I skip the 6.0
Any help would be great. Thanks.
Upvotes: 2
Views: 3700
Reputation: 101251
I haven't even looked at you code but I would suggest a strategy like this
(1) read the initial character of the line
if not "D" then
read reals
store the line
loop to (1)
else
read one integer
store the line
break
endif
read lines of reals until end-of-file
My fortran is very rusty, but I believe that there are constructs that will help you with this. Certainly the END
modifier to READ
is going to be helpful with the last bit.
After a little experimenting, I find that gfortran
seems to support the old trailing $
for non-advancing input convention and advance='no'
. However, g77
does not. I can't speak to any other compiler--as far as I know this was never standardized until fortran 90 where advance='no'
was introduced.
Demo code that works in gfortran
, but not in g77
program temp
c234567
character a
integer i
real x, y, z, w(50)
c This or with (*,'(A1 $)')
read (*,'(A1)',advance='no') a
if (a .eq. 'D') then
read (*,*) i
write (*,*) a, i
endif
end
This should be enough to make the incremental strategy work if you compiler supports non-advancing input somehow.
The alternative is to read the letter plus the rest of the line into a large character buffer, then parse the buffer separately along the lines of
character a, buf(1024)
read (*,'(a1, a1024)') a, buf
if (a .eq. d) then
read (buf,*) i
endif
Upvotes: 0
Reputation: 1664
If you know that your lines will never exceed a maximum length, I suggest to read the whole line and then to parse the line according to your rules.
An example using a maximum line length of 1024 characters:
CHARACTER*1024 line
CHARACTER letter
100 FORMAT (A)
READ(*,100) line
READ(line, *) letter
IF (letter .eq. 'T') THEN
...
END IF
Maybe this technique works for you.
Upvotes: 3