Фортран читает оператор, читающий за концом строки - PullRequest
6 голосов
/ 28 ноября 2011

Знаете ли вы, гарантируется ли следующее утверждение одним из стандартов Фортрана 90/95/2003? «Предположим, что оператору чтения для символьной переменной дана пустая строка (т. Е. Она содержит только пробелы и символы новой строки). Если спецификатор формата - звездочка (*), он продолжает читать последующие строки до тех пор, пока не будет пустым строка найдена. Если спецификатор формата '(A)', вместо символьной переменной подставляется пустая строка. "

Например, посмотрите на следующую минимальную программу и входной файл.

код программы:

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.dat' content is below this line----

yamanakako

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

Обратите внимание, что в файле input.dat четыре строки, а первая и третья строки не заполнены (содержат только пробелы и символы новой строки). Если я запускаю программу как

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

Я получаю следующий вывод

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

Первый оператор чтения для переменной 'str1', похоже, просматривает первую строку 'input.dat', находит пустую строку, переходит ко второй строке, находит значение символа 'yamanakako' и сохраняет его в 'str1'.

Напротив, второму оператору чтения для переменной 'str2', по-видимому, присваивается третья строка, которая является пустой, и сохраняется пустая строка в 'str2', не переходя к четвертой строке.

Я попытался скомпилировать программу с помощью Intel Fortran (ifort 12.0.4) и GNU Fortran (gfortran 4.5.0) и получил тот же результат.

Немного о том, как задать этот вопрос: я пишу подпрограмму для чтения файла данных, в котором в качестве разделителя блоков данных используется пустая строка. Я хочу убедиться, что пустая строка, и только пустая строка, выбрасывается при чтении данных. Мне также нужно сделать его стандартным и переносимым.

Спасибо за вашу помощь.

Ответы [ 2 ]

3 голосов
/ 28 ноября 2011

Из стандартного черновика Fortran 2008:

Ввод / вывод, направленный на список, позволяет редактировать данные в соответствии с типом элемента списка, а не спецификацией формата.Это также позволяет данным быть свободными, то есть разделяться запятыми (или точками с запятой) или пробелами.

Тогда:

Символы в одном или нескольких списках-направленные записи представляют собой последовательность значений и разделителей значений.Конец записи имеет тот же эффект, что и пустой символ, если только он не находится внутри символьной константы. Любая последовательность из двух или более последовательных пробелов обрабатывается как один пробел, если только он не находится внутри символьной константы.

Это неявно указывает, что в вводе, направленном на списки, пустые строкиобрабатываются как пробелы до следующего непустого значения.

При использовании дескриптора формата fmt = '(A)' при чтении пустые строки считываются в str.С другой стороны, fmt = *, что подразумевает направленный на список ввод-вывод в свободной форме, пропускает пустые строки, пока не найдет непустую строку символов.Чтобы проверить это, сделайте что-то вроде:

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

При запуске программы вы получите следующий вывод:

$ 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

С другой стороны, если вы используете ввод по умолчанию:

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

В результате вы получите:

$ a.out < input.dat 
1 str1_start|yamanakako                    |str1_end
2 str2_start|kawaguchiko                   |str2_end
2 голосов
/ 28 ноября 2011

Эта часть стандартного черновика F2008, вероятно, рассматривает вашу проблему:

10.10.3 Список-ориентированный ввод

7 Когда следующий эффективный элемент имеет тип символа, форма ввода состоит из возможно разделенной последовательности нуля или более rep-char s, чей тип параметра типа подразумевается типом эффективный элемент. Последовательности символов могут быть продолжены с конца одна запись к началу следующей записи, но конец записи не должно происходить между двойным апострофом в последовательность символов, разделенных апострофом, ни между двойными кавычками в последовательности символов, разделенных кавычками. Конец записи делает не заставлять пустой или любой другой символ стать частью последовательность символов Последовательность символов может быть продолжена на любом количестве записи по мере необходимости. Пустые символы, запятая, точка с запятой и косая черта может отображаться в последовательности символов по умолчанию, ASCII или ISO 10646.

...