Как кратко обсуждалось в комментариях, по умолчанию все операции ввода-вывода в Fortran основаны на записях. Это верно как для форматированных, так и для неформатированных файлов. Что происходит, файл рассматривается как набор записей - и вы можете думать о записи как о строке в файле. Теперь эти строки могут быть очень и очень длинными, особенно в неформатированных файлах, но методология ввода-вывода Fortran по-прежнему рассматривает их как набор строк.
Теперь важно то, что по умолчанию каждый раз, когда вы выполнить оператор ввода-вывода (чтение, запись, печать), последнее, что он делает, - это перейти от записи, к которой он относится, к следующей записи - оператор записи запишет маркер конца записи. Вот почему вы автоматически получаете новую строку после оператора записи, но это также означает, что для оператора чтения все оставшиеся в записи данные (в строке) будут пропущены. Это то, что происходит с вами. Первое чтение читает запись 1, и вы получаете 1.0, а затем переходит на запись 2. Затем ваша программа читает запись 2, и вы получаете 4.0, и она автоматически переходит на запись 3. Затем читается (9.0) и файл указатель перемещается на запись 4. Затем вы пытаетесь прочитать это, но записи 4 нет, поэтому вы получаете ошибку конца файла.
Структура записи немного странная, когда вы впервые сталкиваетесь с ней, но когда вы привыкнете к нему, это очень мощно и удобно - я покажу пример ниже, а другой может быть, что вы можете оставить комментарий в конце каждой строки, сообщая, что он делает, конец оператора read будет означает, что вы переходите к следующей записи, поэтому пропустите комментарий и вам не нужно предпринимать никаких специальных действий в своем коде, чтобы разобраться с таким случаем.
В любом случае, как решить ваше дело. Три возможных способа
- Чтение всей записи за раз - в комментарии предлагается подразумеваемый do l oop, но я думаю, что в этом случае секция массива намного проще и интуитивнее
- Вы можете просто прочитать весь массив в одном go. Это работает, потому что когда оператор чтения завершает запись и находит, что ему все еще «нужно» больше данных, он перенесет в следующую запись и продолжит чтение. Но обратите внимание, что идея с комментариями в конце строки здесь не сработает - вы можете понять почему?
- Не продвигающийся ввод / вывод. Я не рекомендую это вообще в этом случае, но для полноты это позволяет вам выполнять чтение или запись без перехода к следующей записи
Могут быть и другие, вы, вероятно, можете использовать так называемые Потоковый ввод-вывод, но лично я предпочитаю, когда это возможно, основывать записи, я считаю это более удобным и мощным. В любом случае, вот программа, иллюстрирующая 3 метода. Заметьте, что я также изменил ваш входной файл, заставить оригинал работать с неразвитым вводом-выводом - боль, но не другие 2 - еще одна причина не использовать его здесь.
ian@eris: ~ / работа / стек $ cat readit.f90
Program readit
Implicit None
Real, Dimension( 1:3, 1:3 ) :: a
Integer :: i, j
! one line per read
Write( *, * ) 'Line at a time'
Open( 10, file = 'in' )
Do i = 1, 3
Read ( 10, * ) a( i, : )
Write( *, * ) a( i, : )
End Do
Close( 10 )
! All in one go
Write( *, * ) 'All in one go'
Open( 10, file = 'in' )
Read ( 10, * ) a
Write( *, * ) a
Close( 10 )
! Non advancing I/O
Write( *, * ) 'Non-advancing'
Open( 10, file = 'in' )
Do i = 1, 3
Do j = 1, 3
! Non advancing I/O requires a 'proper' format
Read ( 10, '( f3.1, 1x )', Advance = 'No' ) a( i, j )
Write( *, '( f3.1, 1x )', Advance = 'No' ) a( i, j )
End Do
! Move to next records (lines)
Read ( 10, * )
Write( *, * )
End Do
Close( 10 )
End Program readit
ian@eris:~/work/stack$ gfortran-8 -Wall -Wextra -pedantic -std=f2008 -fcheck=all -O readit.f90
ian@eris:~/work/stack$ cat in
1.0 2.0 3.00
4.0 5.0 6.00
7.0 8.0 9.00
ian@eris:~/work/stack$ ./a.out
Line at a time
1.00000000 2.00000000 3.00000000
4.00000000 5.00000000 6.00000000
7.00000000 8.00000000 9.00000000
All in one go
1.00000000 2.00000000 3.00000000 4.00000000 5.00000000 6.00000000 7.00000000 8.00000000 9.00000000
Non-advancing
1.0 2.0 3.0
4.0 5.0 6.0
7.0 8.0 9.0