I have an input file that I cannot alter the format. One of the lines in particular can contain either 6 or 7 reals and I don't have any way of knowing ahead of time.
After some reading, my understanding of the list-formatted read statement is that if I attempt to read 7 reals on a line containing 6, it will attempt to read from the next line. The author of the code says that when it was written, it would read the 6 reals and then default the 7th to 0. I am assuming he relied on some compiler specific behavior, because I cannot find a mention of this behavior anywhere.
I am using gfortran as my compiler, is there a way to specify this behavior? Or is there a good way to count a number of inputs on a line and rewind to then chose to read the correct number?
here is a little trick to accomplish that
character*100 line
real array(7)
read(unit,'(a)')line !read whole line as string'
line=trim(line)//' 0' !add a zero to the string
read(line,*)array !list read
If the input line only had 6 values, the zero is now the seventh. If there were seven to begin with it will do nothing.
I try to avoid using format specifiers on input as much as possible.
Maybe you should use the IOSTAT
statement for detecting the wrong format when you attempt to read 7 values when there are only 6. And you should use the ADVANCE
statement to be able to retry to read the same line.
READ(LU,'7(F10.3)', IOSTAT=iError, ADVANCE='NO') MyArray(1:7)
IF(iError > 0) THEN
! Error when trying to read 7 values => try to read 6 !
READ(LU, '6(F10.3)') MyArray(1:6)
ELSEIF(iError == 0) THEN
READ(LU, *) ! For skipping the line read with success with 7 values
ENDIF
IOSTAT takes a negative value for example when you reach the end of the file, positive for problem of reading (typically formatting error) and 0 when the read succeed. See this link for a complete definition of gfortran error code: http://www.hep.manchester.ac.uk/u/samt/misc/gfortran_errors.html
Another way to do it could be to read the line as a string and manipulating the string in order to get the vector values :
CHARACTER(LEN=1000) :: sLine
...
READ(LU, '(A)') sLine
READ(sLine,'7(F10.3)', IOSTAT=iError) MyArray(1:7)
IF(iError > 0) THEN
! Error when trying to read 7 values => try to read 6 !
READ(sLine, '6(F10.3)') MyArray(1:6)
ENDIF
If the values are written in fixed format, you can determine the lenght of the vector by testing the lenght of the line:
CHARACTER(LEN=1000) :: sLine
INTEGER :: nbValues
CHARACTER(LEN=2) :: sNbValues
...
READ(LU, '(A)') sLine
nbValues = LEN_TRIM(sLine) / 10 ! If format is like '(F10.x)'
WRITE(sNbValues, '(I2)') nbValues
READ(sLine, '('//TRIM(sNbValues)//'(F10.3))') MyArray(1:nbValues)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.