【问题标题】:How can I fill a matrix using a fortran subroutine (or function) and pass the matrix back to the main program?如何使用 fortran 子例程(或函数)填充矩阵并将矩阵传递回主程序?
【发布时间】:2013-10-09 20:29:56
【问题描述】:

我正在处理 Fortran 90 作业,在学习如何使用子例程和函数时遇到了很多问题,我希望有人能帮助我。如果不是很明显,我对 FORTRAN 非常陌生,并且对 C 和 Java 等语言更加熟悉。

无论如何,这就是我必须做的事情:用户选择他们想要做的事情:加、减、乘或转置两个矩阵。我为此使用了一个选择案例,效果很好。但是,我显然不想重复相同的代码以四次填充两个矩阵,因此我试图将其设为单独的函数。理想情况下,我想做这样的事情:

integer matrix1(11,11), matrix2(11,11)
integer rows1,cols1,rows2,cols2,i,j
case (1)  
    matrix1 = fillmatrix(rows1,cols1)
    matrix2 = fillmatrix(rows2,cols2)
.
.
.


function fillmatrix(rows,columns)
  integer input
  read *,rows,columns
  do i = 1, rows
    do j = 1, columns
       fillmatrix(i,j) = read *,input
    end do
  end do
end

有没有办法做这样的事情?我有没有说清楚,因为有时我很难说出我的意思。

或者这可能吗?

matrix1 = fillmatrix(rows1)cols1)


function fillmatrix(rows,columns)
   integer input,matrix(11,11)
       //fill matrix
   return matrix
end

【问题讨论】:

  • 您是否仅限于 FORTRAN 77,还是可以使用更新的标准?从 Fortran 90 开始,您可以使用返回数组的函数。
  • 嗯,作业文件没有说我们必须使用f77,所以我可能会使用f90,但是我根本没有用fortran 90做任何事情,所以我不知道是什么否则我需要改变
  • 哦,我刚刚注意到...select case IS Fortran 90 ;-) 见Wikipedia
  • 哇。我不知道 Fortran 90 是什么选择案例...显示了我的关注程度。如果我把他们弄得那么糊涂,我显然是在写草率的代码,哈哈。

标签: function matrix fortran subroutine


【解决方案1】:

在 C 或 Java 中,只有函数,但 Fortran 既有函数又有子例程。在这种情况下,将其写为subroutine 而不是function 可能更容易,所以你的调用看起来像

integer matrix1(11,11), matrix2(11,11)
integer rows1,cols1,rows2,cols2,i,j
...
case (1)  
    call fillmatrix(matrix1)
    call fillmatrix(matrix2)
...

子程序的样子

subroutine fillmatrix(m)
    implicit none
    integer, intent(out) :: m(:,:)

    integer :: i, j
    do j = 1,size(m,2)
        do i = 1,size(m,1)
            read *, m(i,j)
        end do
    end do
end subroutine fillmatrix

请注意,我没有直接指定数组边界——而是在子例程中找出它们。这意味着这个子例程需要一个显式接口 - 获得它的最简单方法是将它放在 contains 块或 module 中。

【讨论】:

  • “在 C 或 Java 中,你只有函数”——这是不正确的。 FORTRAN 函数返回一个值;子程序没有。所有基于 C 的语言,包括 Java,也都有。您始终可以从函数返回值。我想说一个返回 void 的函数相当于一个子例程。
  • @duffymo - 我同意你的观点,“返回 void 的函数相当于子例程”,只要它们具有相同的效果。但是,在 C/Java/等中。仍然只有一个“函数”语法,而 Fortran 对这两件事有完全不同的语法形式。
【解决方案2】:

如果你想使用function,你需要在调用它之前知道矩阵的大小。这是一个小例子:

module readMatrix
  implicit none
contains
  function fillmatrix(cols,rows)
    implicit none
    ! Argument/return value
    integer,intent(in)  :: rows,cols
    integer             :: fillmatrix(rows,cols)
    ! Loop counters
    integer             :: i,j

    do j = 1, rows
      do i = 1, cols
        write(*,*) 'Enter matrix element ',i,j
        read *,fillmatrix(i,j)
      enddo ! j
    enddo ! i
  end function
end module

program test
  use readMatrix
  implicit none
  integer,allocatable :: matrix(:,:)
  integer             :: row,col, stat

  write(*,*) 'Enter number of rows'
  read *,row
  write(*,*) 'Enter number of cols'
  read *,col
  allocate( matrix(col,row), stat=stat )
  if (stat/=0) stop 'Cannot allocate memory'

  matrix = fillmatrix(col,row)

  write(*,*) matrix
  deallocate(matrix)
end program

这类似,使用subroutine 和静态数组(如问题中所示):

module readMatrix
  implicit none
contains
  subroutine fillmatrix(cols,rows,matrix)
    implicit none
    ! Argument/return value
    integer,intent(out) :: rows,cols
    integer,intent(out) :: matrix(:,:)
    ! Loop counters
    integer             :: i,j

    write(*,*) 'Enter number of rows, up to a maximum of ',size(matrix,2)
    read *,rows
    write(*,*) 'Enter number of cols, up to a maximum of ',size(matrix,1)
    read *,cols

    if ( rows > size(matrix,2) .or. cols > size(matrix,1) ) &
      stop 'Invalid dimension specified'

    do j = 1, rows
      do i = 1, cols
        write(*,*) 'Enter matrix element ',i,j
        read *,matrix(i,j)
      enddo ! j
    enddo ! i
  end subroutine
end module

program test
  use readMatrix
  implicit none
  integer,parameter   :: maxCol=10,maxRow=10
  integer             :: matrix(maxCol,maxRow)
  integer             :: row,col

  call fillmatrix(col,row,matrix)

  write(*,*) matrix(1:col,1:row)

end program

您甚至可以将 allocatable 数组传递给子例程并在那里分配它,但那是另一回事...

【讨论】:

  • 有点小问题 - 请注意,您的第一句话在 Fortran 90 中并不完全正确 - 在调用函数之前,您不一定需要知道函数结果的长度,但它是混乱(您需要使用带有指针结果的函数)。为了使您最后一句中的“不同故事”适用,您正在谈论 Fortran 2003,然后编写和使用在函数开始执行之前返回结果未知的函数很容易 - 函数结果可以是可分配的,您可以使用 allocate -在参考点分配。
  • 是的,我知道...但我不想让海报超载。 (特别是因为最初的前提是 FORTRAN 77)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-11
  • 2013-12-07
  • 2016-10-28
  • 2015-08-12
  • 2019-04-08
相关资源
最近更新 更多