将数据从文件导入到数组

时间:2010-04-24 11:15:59

标签: fortran

我在文件中有2维表,如下所示:

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

我希望它以二维数组导入。我写了这段代码:

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

但是它会导入一维数组中的所有内容。

编辑:

我已更新代码:

    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 个答案:

答案 0 :(得分:2)

嗯,你已经将SMALL定义为一维数组,而Fortran只是试图提供帮助。你应该像这样定义SMALL;

integer, dimension(2,5) :: small

执行read语句时发生的情况是系统在SMALL已满或遇到文件末尾之前用完了编辑描述符(您指定了5个整数)。如果我没记错,Fortran将重新使用编辑描述符,直到SMALL已满或遇到文件结尾。但是根据Fortran标准,这种行为多年来已经发生了变化,并且各种编译器已经在这部分语言中实现了各种非标准功能,因此您可能需要检查编译器的文档或进行更多实验以确切地找出会发生什么。

我认为你的代码也有点奇怪,因为你从SMALL读了3次。为什么?

编辑:好的,我们到了那里。您刚刚发现Fortran以列主顺序存储数组。我相信大多数其他编程语言都以行主顺序存储它们。换句话说,数组的第一个元素是small(1,1),第二个元素(在内存中)是small(2,1),第三个元素是small(1,2),依此类推。我认为你的读(和写)语句不是标准的,而是广泛实现的(这在Fortran编译器中并不罕见)。我可能错了,可能是标准的。无论哪种方式,read语句都被解释为以列为主要顺序读取small的元素。读取的第一个数字放在small(1,1)中,第二个放在small(2,1)中,第三个放在small(1,2)中,依此类推。

您的write声明使用相同的功能;你可能已经为自己发现了这个,如果你已经用循环中的元素写出了也打印了索引。

读取数组并控制元素放入数组的顺序Fortran方法是在read语句中包含一个 implied-do 循环,如下所示:

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

您也可以在write语句中使用此方法。

您还应该仔细研究编译器文档,并确定如何为所有非标准功能启用警告。

答案 1 :(得分:1)

添加高性能马克所写的......

如果要使用逗号分隔数字,则应使用列表定向的IO而不是格式化的IO。 (有时这称为无格式IO,但非标准术语很容易与二进制IO混淆)。这更容易使用,因为您不必在列中精确排列数字,并可以用空格或逗号分隔它们。读取只是“读(10,*)变量”

但坚持使用格式化IO,这里有一些示例代码:

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所需的对齐方式。

使用我的示例程序,有一个用于irow的外部do循环和一个“隐含的do循环”作为read语句的一部分。你也可以消除外部的do循环,并在read语句中使用两个隐含的do循环,正如High Performance Mark所示。在这种情况下,如果保留格式规范(5I4),它将被重用以读取第二行 - 这称为格式恢复。 (在更复杂的格式上,需要阅读规则以了解格式的哪一部分在格式恢复中被重用。)这是标准的,至少从FORTRAN 77和FORTRAN IV开始。 (当然,我的例子的声明和风格是Fortran 90)。

我使用了“ubound”,因此您既不需要携带存储数组维度的变量,也不必使用特定的数值。如果您以后决定更改数组的维度,后面的方法可能会导致问题 - 然后您必须搜索所有特定值(此处为2和5)并更改它们。

在公开声明后无需倒退。