truyền mảng được cấp phát từ chương trình con sang chương trình chính trong fortran; sử dụng hoặc mô-đun? giao diện?

Aug 16 2020

Tôi muốn cấp phát một mảng trong chương trình con, sau đó sử dụng mảng này trong chương trình chính và chuyển nó cho một số chương trình con khác. Trong quá khứ (F77?), Việc vượt qua có thể được thực hiện trong một khối chung, nhưng ngày nay thủ tục được ưa chuộng dường như là sử dụng một mô-đun. Khi tôi thử điều này, như trong ví dụ mã, trình biên dịch cho tôi biết

Rank mismatch in argument ‘f’ at (1) (scalar and rank-1)

Rõ ràng, chương trình chính nghĩ rằng 'f' là một đại lượng vô hướng: nhưng, tôi đọc đoạn mã này có nghĩa là tôi đã khai báo nó là một mảng một chiều, cả bên trong chương trình con và chương trình chính. Tôi đang thiếu gì?

Tôi đã thử các biến thể, chẳng hạn như khai báo các biến như một phần của mô-đun, nhưng tôi không thể nghĩ ra cách nào để làm cho quá trình biên dịch không có lỗi (và một số tạo ra nhiều lỗi khác ;-(). Mọi thông tin chi tiết đều được đánh giá cao nhất.

          module subs
        contains
        subroutine makef(f)
        end subroutine makef
      end module subs
c-----------------------------------------------------------------------
      program work

      use subs
      implicit none
        real, allocatable :: f(:)

      call makef(f)

      write (*,*) f
      stop
      end
c---------------------------------------------------------------------
      subroutine makef(f)
      implicit none

      real, allocatable, intent(out) :: f(:)
      integer :: i
      integer :: is

      is=10
      allocate(f(-is:is))

      do i=-is,is
        f(i)=i
      end do
      return
      end subroutine makef

Trả lời

2 francescalus Aug 16 2020 at 17:19

Các mô-đun trong Fortran không giống như các tệp tiêu đề trong các ngôn ngữ khác mà chỉ cung cấp thông tin về những thứ được xác định ở nơi khác. Có khái niệm về "định nghĩa trì hoãn" (mô-đun con) nhưng trong trường hợp này mô-đun nên nói mọi thứ về chương trình con, chứ không chỉ cố gắng chỉ ra sự tồn tại của nó.

Trong ví dụ của câu hỏi, chúng ta có: chương trình chính; một mô-đun subsvới thủ tục mô-đun makef; một chương trình con bên ngoài makef.

Chương trình chính sử dụng mô-đun subsvà thủ tục của nó makef, vì vậy tham chiếu trong chương trình chính makeflà quy trình mô-đun đó không phải là chương trình con bên ngoài makef.

Chương trình con mô-đun makefcó đối số fkhông có câu lệnh khai báo, làm cho nó trở thành một hàm vô hướng / hàm ngoài được khai báo ngầm. Đây là thông báo của trình biên dịch. Sử dụng implicit nonetrong các mô-đun, cũng giống như trong chương trình chính và chương trình con bên ngoài ở đây.

Toàn bộ định nghĩa của chương trình con nên được đặt trong mô-đun:

module subs
  implicit none
contains
  subroutine makef(f)
    real, allocatable, intent(out) :: f(:)
    integer :: i
    integer :: is

    is=10
    allocate(f(-is:is))

    do i=-is,is
      f(i)=i
    end do
  end subroutine makef
end module subs

Ngoài ra, nếu người ta muốn đề cập đến việc triển khai sau này của một thủ tục bên ngoài, một khối giao diện có thể có tính năng trong mô-đun mà không cần khai báo chính chương trình con. Trong trường hợp này, vẫn cần chỉ định giao diện hoàn chỉnh:

module subs
  implicit none

! An interface block to give an explicit interface to the external subroutine makef
  interface
     subroutine makef(f)
       implicit none
       real, allocatable, intent(out) :: f(:)
     end subroutine makef
  end interface
end module subs

Trong trường hợp này, không thích khối giao diện.

VladimirF Aug 16 2020 at 13:07

Bạn chỉ đặt bản sao của dòng đầu tiên và dòng cuối cùng vào mô-đun. Điều đó không thể hoạt động. Bạn phải chuyển toàn bộ chương trình con vào mô-đun.