1

I'm working on a Fortran 90 assignment, and I'm having a lot of issues learning how to use subroutines and functions, and I'm hoping someone can help me. if it isn't obvious, I'm extremely new to FORTRAN and much more comfortable with language like C and Java.

Anyway, here's what I have to do: The user selects what they would like to do: add, subtract, multiply, or transpose two matrices. I'm using a select case for this, which works great. However, I obviously don't want to duplicate the same code to fill two matrices four different times, so I'm trying to make it a separate function. Ideally, I'd like to do something like this:

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

Is there any way to do something like this? And am i making myself clear, because sometimes I have trouble saying what I mean.

Or is this possible?

matrix1 = fillmatrix(rows1)cols1)


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

2 回答 2

2

如果你想使用 a 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数组传递给子例程并在那里分配它,但那是另一回事......

于 2013-10-09T21:13:19.423 回答
2

在 C 或 Java 中,只有函数,但 Fortran 既有函数又有子例程。subroutine在这种情况下,将其写为 a而不是a 可能更容易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.

于 2013-10-09T21:21:35.377 回答