I'm writing a preprocessor and postprocessor for Fortran input and output using FORMAT-like statements (there are reasons not to use a FORTRAN library). I want to treat the new line ("/") character correctly. I don't have a Fortran compiler immediately to hand. Is there a simple algorithm for working out how many newlines are written or consumed (This post just gives reading examples)
[Please assume a FORTRAN77-like mentality in the FORTRAN code and correct any FORTRAN syntax on my part]
UPDATE: no comments yet so I am reduced to finding a compiler and running it myself. I'll post the answers if I'm not beaten to it. No-one commented I had the format syntax wrong. I've changed it but there may still be errors
Assume datafile 1
a
b
c
d
etc...
(a) does the READ command always consume a newline? does
READ(1, '(A)') A
READ(1, '(A)') B
give A='a' and B='b'
(b) what does
READ(1,'(A,/)') A
READ(1,'(A)') B
give for B? (I would assume 'c')
(c) what does
READ(1, '(/)')
READ(1, '(A)') A
give for A (is it 'b' or 'c')
(d) what does
READ(1,'(A,/,A)') A, B
READ(1,'(A)') C
give for A and B and C(can I assume 'a' and 'b' and 'c')
(e) what does
READ(1,'(A,/,/,A)') A开发者_开发技巧, B
READ(1,'(A)') C
give for A and B and C(can I assume 'a' and 'c' and 'd')?
Are there any cases in which the '/' is redundant?
To be precise the slash edit descriptor, represented by the character /
, is actually the end of record specifier. I'm now going to quote from the draft Fortran 2008 standard, I don't think the programming language's behaviour has changed in this respect since FORTRAN77, but I'm not certain. I'm quoting from the standard because (a) if you are writing a pre- and post-processor I guess you will want it to adhere to the standard rather than to some ambiguous explanation of it which is all I could provide, and (b) there are so many variations in Fortran I/O statements that I am really familiar with only a few of them (and this isn't one of them).
10.8.2 Slash editing
1 The slash edit descriptor indicates the end of data transfer to or from the current record.
2 On input from a file connected for sequential or stream access, the remaining portion of the current record is skipped and the file is positioned at the beginning of the next record. This record becomes the current record. On output to a file connected for sequential or stream access, a new empty record is created following the current record; this new record then becomes the last and current record of the file and the file is positioned at the beginning of this new record.
3 For a file connected for direct access, the record number is increased by one and the file is positioned at the beginning of the record that has that record number, if there is such a record, and this record becomes the current record.
(NOTE 10.25 A record that contains no characters may be written on output. If the file is an internal file or a file connected for direct access, the record is filled with blank characters. An entire record may be skipped on input.)
4 The repeat specification is optional in the slash edit descriptor. If it is not specified, the default value is one.
So, the slash can be used to read to the end of a partially-read record and to skip a record entirely (mutatis mutandis for writing).
If I compile your program (Intel Fortran 11.1 on Mac OS X) I get the following output:
a
b
====== example b
a
c
====== example c
c
====== example d
a
b
c
====== example e
a
c
d
====== example f
a
b
which suggests that, based on my interpretation of the standard, gfortran exhibits non-standard behaviour. However, I suspect that if you are more specific in your I/O operations, you might perhaps want to specify record lengths in your READ and WRITEs, you may be able to achieve what you want.
As there have been no comments so far, I'm adding my own answer. (If anyone adds light to this I'll give them votes).
Program:
program TEST
character (len=80) :: a,b,c
write(6,'(a)') '====== example a'
open(1,file='test1.dat',form='formatted',status='old',action='read')
READ(1, '(A)') a
READ(1, '(A)') b
write(6,'(a)') a
write(6,'(a)') b
close(1)
write(6,'(a)') '====== example b'
open(1,file='test1.dat',form='formatted',status='old',action='read')
READ(1, '(A,/)') a
READ(1, '(A)') b
write(6,'(a)') a
write(6,'(a)') b
close(1)
write(6,'(a)') '====== example c'
open(1,file='test1.dat',form='formatted',status='old',action='read')
READ(1, '(/)')
READ(1, '(A)') A
write(6,'(a)') a
close(1)
write(6,'(a)') '====== example d'
open(1,file='test1.dat',form='formatted',status='old',action='read')
READ(1, '(A,/,A)') a,b
READ(1, '(A)') c
write(6,'(a)') a
write(6,'(a)') b
write(6,'(a)') c
close(1)
write(6,'(a)') '====== example e'
open(1,file='test1.dat',form='formatted',status='old',action='read')
READ(1,'(A,/,/,A)') a, b
READ(1,'(A)') c
write(6,'(a)') a
write(6,'(a)') b
write(6,'(a)') c
close(1)
write(6,'(a)') '====== example f'
open(1,file='test1.dat',form='formatted',status='old',action='read')
READ(1, '(A1)') a
READ(1, '(A1)') b
write(6,'(a)') a
write(6,'(a)') b
close(1)
end
compiled under gfortran gives:
gfortran -O2 -c test.f90
gfortran -o test.x *.o
C:\test>test.x
====== example a
a
b
====== example b
a
c
====== example c
c
====== example d
a
b
c
====== example e
a
c
d
====== example f
a
b
QUESTION: why are there additional new lines between all the outputs? Is there a newline in the strings that have been read in?
Those new lines are really 79 printed spaces. Use the LEN_TRIM() function to your write statements like this: write(6,'(a)') a(1:LEN_TRIM(a)) or change the length of your character field to (1)
精彩评论