Reading Fortran reading off line

Did you know that the following statement is guaranteed by one of the fortran standards 90/95/2003? "Suppose that the read statement for a character variable is given by an empty string (that is, it contains only spaces and new string characters). If the format specifier is an asterisk (*), it continues to read subsequent lines until it is empty If the specifier format is '(A)', an empty string is replaced instead of a character variable.

For example, check out the following minimum program and input file.

program code:

PROGRAM chk_read INTEGER, PARAMETER :: MAXLEN=30 CHARACTER(len=MAXLEN) :: str1, str2 str1='minomonta' read(*,*) str1 write(*,'(3A)') 'str1_start|', str1, '|str1_end' str2='minomonta' read(*,'(A)') str2 write(*,'(3A)') 'str2_start|', str2, '|str2_end' END PROGRAM chk_read 

input file:

 ----'input.dat' content is below this line---- yamanakako kawaguchiko ----'input.dat' content is above this line---- 

Note that there are four lines in 'input.dat', and the first and third lines are empty (contain only spaces and new string characters). If I run the program as

 $ ../chk_read < input.dat > output.dat 

I get the following output

 ----'output.dat' content is below this line---- str1_start|yamanakako |str1_end str2_start| |str2_end ----'output.dat' content is above this line---- 

The first read statement for the variable 'str1' seems to look at the first line of 'input.dat', find the empty line, go to the second line, find the value of the character 'yamanakako' and store it in 'str1'.

In contrast, the second read statement for the variable 'str2' seems to get the third line, which is empty, and store the empty line in 'str2' without going to the fourth line.

I tried compiling Intel Fortran (ifort 12.0.4) and GNU Fortran (gfortran 4.5.0) and got the same result.

A little bit about the background of the question: I am writing a routine to read a data file that uses an empty string as a separator of data blocks. I want to make sure that an empty line and only an empty line are thrown when reading data. I also need to make it standard and portable.

Thanks for your help.

+6
source share
2 answers

From the standard version of Fortran 2008:

List-oriented I / O allows you to edit data according to the type of list item instead of the format specification. It also allows data to be free, that is, separated by commas (or semicolons) or workpieces.

Then:

The characters in one or more list-oriented lists make up a sequence of values ​​and value separators. The end of a record has the same effect as an empty character if it is not inside a constant character. Any sequence of two or more consecutive blanks is considered as one space, if it is not in a symbolic constant.

This implicitly states that in a streaming reference, empty lines are treated as spaces until the next non-empty value.

When using the format descriptor fmt = '(A)' when reading empty lines are read to str. On the other hand, fmt = *, which implies free-form list I / O, skips blank lines until it finds a non-empty character string. To check this, do something like:

 PROGRAM chk_read INTEGER :: cnt INTEGER, PARAMETER :: MAXLEN=30 CHARACTER(len=MAXLEN) :: str cnt=1 do read(*,fmt='(A)',end=100)str write(*,'(I1,3A)')cnt,' str_start|', str, '|str_end' cnt=cnt+1 enddo 100 continue END PROGRAM chk_read $ cat input.dat yamanakako kawaguchiko 

Eof

Running the program gives this output:

 $ a.out < input.dat 1 str_start| |str_end 2 str_start| |str_end 3 str_start| |str_end 4 str_start|yamanakako |str_end 5 str_start| |str_end 6 str_start|kawaguchiko |str_end 

On the other hand, if you use the default input:

 read(*,fmt=*,end=100)str 

You will get this result:

 $ a.out < input.dat 1 str1_start|yamanakako |str1_end 2 str2_start|kawaguchiko |str2_end 
+3
source

This part of the F2008 standard project probably relates to your problem:

10.10.3 Entering a list with a list

7 When the next eff ective element is of type character, the input form consists of a possibly bounded sequence of zero or more rep-char s, the type of the form of the form of which is implied by the form e ff ective item. The sequence of characters can be continued from the end of one record to the beginning of the next record, but the end of the record should not occur between a double apostrophe in a sequence of characters with apostrophes, or between a double quote in a sequence of characters with quotation delimited characters. Ending a record does not cause the empty character or any other character to become part of the character sequence. The sequence of characters can be continued for as many records as necessary. Characters that are empty, commas, semicolons, and slashes can appear in the default character fields, ASCII, or ISO 10646.

+2
source

Source: https://habr.com/ru/post/902550/


All Articles