Импорт данных из файла в массив - PullRequest
1 голос
/ 24 апреля 2010

У меня есть двухмерная таблица в файле, которая выглядит следующим образом:

11, 12, 13, 14, 15
21, 22, 23, 24, 25

Я хочу, чтобы он был импортирован в 2-мерном массиве. Я написал этот код:

      INTEGER :: SMALL(10)      
      DO I = 1, 3
        READ(UNIT=10, FMT='(5I4)')    SMALL
        WRITE(UNIT=*, FMT='(6X,5I4)') SMALL
      ENDDO

Но он импортирует все в одномерный массив.

EDIT:

Я обновил код:

    program filet

    integer :: reason
    integer, dimension(2,5) :: small

    open(10, file='boundary.inp', access='sequential', status='old', FORM='FORMATTED')
    rewind(10)
      DO
        READ(UNIT=10, FMT='(5I4)', iostat=reason)    SMALL
        if (reason /= 0) exit
        WRITE(UNIT=*, FMT='(6X,5I4)') SMALL
      ENDDO
      write (*,*) small(2,1)
    end program

Вот вывод:

        11  12  13  14  15
        21  22  23  24  25
          12

Ответы [ 2 ]

2 голосов
/ 24 апреля 2010

Ну, вы определили SMALL как одномерный массив, и Фортран просто пытается помочь. Возможно, вы должны были определить SMALL как это;

integer, dimension(2,5) :: small

То, что произошло, когда был выполнен оператор read, заключался в том, что система исчерпала дескриптор редактирования (вы указали 5 целых чисел) до того, как либо SMALL был заполнен, либо обнаружен конец файла. Если я правильно помню, Fortran будет повторно использовать дескриптор редактирования до тех пор, пока либо SMALL не заполнится, либо будет достигнут конец файла. Но это поведение менялось с годами, в соответствии со стандартами Fortran, и различные компиляторы реализовали различные нестандартные функции в этой части языка, поэтому вам может потребоваться проверить документацию вашего компилятора или провести еще несколько экспериментов, чтобы точно определить, что происходит.

Я думаю, что ваш код также немного своеобразен тем, что вы читаете из SMALL 3 раза. Почему?

РЕДАКТИРОВАТЬ: ОК, мы там. Вы только что обнаружили, что Fortran хранит массивы в порядке столбцов. Я считаю, что большинство других языков программирования хранят их в порядке следования строк. Другими словами, первый элемент вашего массива - small(1,1), второй (в памяти) - small(2,1), третий - small(1,2) и т. Д. Я думаю, что ваши операторы чтения (и записи) не являются стандартными, но широко применяются (что не является чем-то необычным в компиляторах Фортрана). Я могу ошибаться, это может быть стандартным. В любом случае, оператор read интерпретируется для чтения элементов small в мажорном столбце. Первое прочитанное число вводится в small(1,1), второе в small(2,1), третье в small(1,2) и т. Д.

Ваш оператор write использует ту же функцию; Вы могли бы открыть это для себя, если бы вы записали элементы в циклы с напечатанными индексами.

Идиоматический способ чтения массива на Фортране и управления порядком, в котором элементы помещаются в массив, заключается в том, чтобы включить в оператор чтения цикл implied-do , например:

READ(UNIT=10, FMT='(5I4)', iostat=reason)  ((SMALL(row,col), col = 1,numCol), row=1,numRow)

Вы также можете использовать этот подход в write выражениях.

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

1 голос
/ 24 апреля 2010

Добавление к написанному High Performance Mark ...

Если вы хотите использовать запятые для разделения чисел, то вам следует использовать IO, ориентированный на список, а не отформатированный IO. (Иногда это называется IO без формата, но этот нестандартный термин легко спутать с бинарным IO). Это проще в использовании, так как вам не нужно располагать числа точно в столбцах и разделять их пробелами или запятыми. Чтение - это просто «чтение (10, *) переменных»

Но придерживаясь форматированного ввода-вывода, вот пример кода:

program demo1

implicit none

integer, dimension (2,5) :: small

integer :: irow, jcol

open ( unit=10, file='boundary.txt', access='sequential', form='formatted' )

do irow=1, ubound (small, 1)
   read (10, '(5I4)')  (small (irow, jcol), jcol=1, ubound (small, 2))
end do

write (*, '( / "small (1,2) =", I2, " and small (2,1)=", I2 )' )  small (1,2), small (2,1)

end program demo1

При использовании чтения в формате I4 данные должны быть в столбцах:

12341234123412341234
  11  12  13  14  15
  21  22  23  24  25

Файл данных не должен содержать первую строку «1234 ...» - то есть в примере, чтобы сделать выравнивание, требуемое для формата 5I4, ясным.

В моем примере программы есть внешний цикл do для irow и «подразумеваемый цикл do» как часть оператора read. Вы также можете исключить внешний цикл do и использовать два подразумеваемых цикла do в операторе read, как показала метка высокой производительности. В этом случае, если вы сохранили спецификацию формата (5I4), он будет повторно использован для чтения второй строки - это называется реверсией формата. (В более сложном формате необходимо прочитать правила, чтобы понять, какая часть формата используется повторно при реверсии формата.) Это стандарт, и так было, по крайней мере, с FORTRAN 77 и, вероятно, с FORTRAN IV. (Конечно, декларации и стиль моего примера - Fortran 90).

Я использовал «ubound», чтобы вам не приходилось переносить переменные, хранящие размеры массива, и не использовать конкретные числовые значения. Более поздний метод может вызвать проблемы, если позднее вы решите изменить размерность массива - тогда вам придется искать все конкретные значения (здесь 2 и 5) и изменять их.

Нет необходимости в перемотке после открытого заявления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...