函数传递进/出程序Fortran 90

时间:2017-04-12 16:21:12

标签: fortran

我正在尝试将数组传递给函数,以便能够计算将替换该数组中原始值的新值。但是,我一直收到零返回,我不知道为什么。我的代码如下:

program HW10
    implicit none
    integer :: i
    integer, parameter :: &
    p=38      !lines to read
    real, parameter :: &
    g=9.81    !Value of gravity acceleration
    integer , dimension(p) :: direction, speed, rh, speedconv
    real, dimension (p) :: pressure, height, temp, dewpt, mixr
    real :: average, knots

    open(1,file='HW10input.txt', status='old', action='read')

    10 format (F6.1, T9, F6.1, T16, F5.1, T23, F5.1, T33, I2, T38, F4.2, T46, I3, T53, I3)

    do i=1,p
        read(1,10)pressure(i), height(i), temp(i), dewpt(i), rh(i), mixr(i), direction(i), speed(i)
    end do


    close (1)

    open(2, file='outputfilehw10.txt', status='new', action='write') 
    do i=1,p
    write (*, 20) pressure(i), height(i), temp(i), dewpt(i), rh(i), mixr(i), direction(i), speed(i)
    20 format (F6.1, T9, F6.1, T16, F5.1, T23, F5.1, T33, I2, T38, F4.2, T46, I3, T53, I3)
    end do
    write (*,*) 'Average= ', average(temp, p)
    do i=1,p
        write (*,*) 'Wind Speeds: ', knots(speed, p)
    end do
end program HW10

当我到达底部的“结”功能时出现问题。这就是函数的样子:

real function knots (x, n)
integer, intent(in) :: n
real, dimension(n), intent(inout) :: x
integer :: i

do i = 1, n
    x(i) = (x(i) * 0.514444 )
end do 
return x
end function knots

代码将在数据中读取正确,因为我有正确显示它的代码。但是,当我想在风速阵列中看到变化的数据时,所有数据点都是零。我是Fortran的新手,所以我不太清楚该怎么做。提前谢谢!

2 个答案:

答案 0 :(得分:3)

如果我尝试使用gfortran 4.8.3编译问题中给出的代码(将所有内容放在同一个文件中),我会收到以下两个错误:

第一个错误:

return x
      1
Error: Alternate RETURN statement at (1) is only allowed within a SUBROUTINE

第二个错误:

        write (*,*) 'Wind Speeds: ', knots(speed, p)
                                           1
Warning: Type mismatch in argument 'x' at (1); passed INTEGER(4) to REAL(4)

让我们来处理其中的第一个 - 与许多其他编程语言不同,它不用于设置返回值。

那么,为什么编译器只是抱怨你在一个函数而不是一个子例程中完成了这个,而不是编译器抱怨你在这里放了一个值?有一个称为备用返回的历史特征,有点像使用goto - 这些仅在子例程中允许。

所以让我们用return x替换return - 这可以避免编译错误,但是代码如何知道返回什么值?在fortran中定义函数时,您可以显式指定结果的名称,但如果不这样做,则它假定您的结果是与函数同名的变量,因此在您的情况下knots。因此,在您的代码中,要返回的变量称为knots,但它永远不会被设置为任何内容。通过“巧合”,看起来用于存储结果的内存位(从未显式设置为任何内容)要么被编译器初始化为零,要么只是访问未初始化的内存碰巧充满了零。

那么我们该如何解决这个问题呢?让我们明确定义结果

function knots (x, n) result(y)
  implicit none
  integer, intent(in) :: n
  real, dimension(n), intent(inout) :: x
  real, dimension(n) :: y
  integer :: i

  do i = 1, n
     y(i) = (x(i) * 0.514444 )
  end do
  return
end function knots

如果我们尝试编译,我们现在会收到一个新错误!

write (*,*) 'Wind Speeds: ', knots(speed, p)
                                    1
Error: The reference to function 'knots' at (1) either needs an explicit INTERFACE or the rank is incorrect

带参数/返回值的函数/子例程通常需要定义接口。有很多方法可以实现这一点,我将通过将函数放在一个模块中来实现:

module myknots
  implicit none
  public :: knots
contains
  function knots (x, n) result(y)
    implicit none
    integer, intent(in) :: n
    real, dimension(n), intent(inout) :: x
    real, dimension(n) :: y
    integer :: i

    do i = 1, n
       y(i) = (x(i) * 0.514444 )
    end do
    return
  end function knots
end module myknots

然后我们需要将use myknots, only: knots添加到主程序的顶部。现在这只剩下第二个错误了。

这告诉我们的是,您已将整数数组传递给期望实数值的函数。这是因为speed被声明为整数,但结中的x被声明为真实。为了解决这个问题,我们创建一个新的结函数,其中x被声明为整数。我还将使用显式接口来允许我们使用名称knots来引用任一版本的结。这样做myknots模块看起来像

module myknots
  implicit none
  private
  public :: knots

  interface knots
     module procedure knots_r
     module procedure knots_i
  end interface knots
contains
  function knots_r (x, n) result(y)
    implicit none
    integer, intent(in) :: n
    real, dimension(n), intent(inout) :: x
    real, dimension(n) :: y
    integer :: i

    do i = 1, n
       y(i) = (x(i) * 0.514444 )
    end do
    return
  end function knots_r

  function knots_i (x, n) result(y)
    implicit none
    integer, intent(in) :: n
    integer, dimension(n), intent(inout) :: x
    real, dimension(n) :: y
    integer :: i

    do i = 1, n
       y(i) = (x(i) * 0.514444 )
    end do
    return
  end function knots_i
end module myknots

主程序看起来像

Program HW10
  use myknots, only: knots
  implicit none
  integer :: i
  integer, parameter :: &
       p=38      !lines to read                                                                                                                                                                                    
  real, parameter :: &
       g=9.81    !Value of gravity acceleration                                                                                                                                                                    
  integer , dimension(p) :: direction, speed, rh, speedconv
  real, dimension (p) :: pressure, height, temp, dewpt, mixr
  real :: average

  open(1,file='HW10input.txt', status='old', action='read')

10 format (F6.1, T9, F6.1, T16, F5.1, T23, F5.1, T33, I2, T38, F4.2, T46, I3, T53, I3)

  do i=1,p
     read(1,10)pressure(i), height(i), temp(i), dewpt(i), rh(i), mixr(i), direction(i), speed(i)
  end do


  close (1)

  open(2, file='outputfilehw10.txt', status='new', action='write')
  do i=1,p
     write (*, 20) pressure(i), height(i), temp(i), dewpt(i), rh(i), mixr(i), direction(i), speed(i)
20   format (F6.1, T9, F6.1, T16, F5.1, T23, F5.1, T33, I2, T38, F4.2, T46, I3, T53, I3)
  end do
  write (*,*) 'Average= ', average(temp, p)
  do i=1,p
     write (*,*) 'Wind Speeds: ', knots(speed, p)
  end do
end program HW10

这解决了所有直接问题,但由于您尚未定义average函数,因此仍无法生成可执行文件。希望上面的步骤足以让你自己实现它。

答案 1 :(得分:2)

你有一个功能knots,它有一个真实的结果。看一下

write (*,*) 'Wind Speeds: ', knots(speed, p)

评估函数引用knots(speed, p)以返回该实际结果,然后打印该结果。

基于相同的误解,存在两个问题:在函数knots中,函数的结果具有名称knots。这与intent(inout)伪参数x不同。

问题1:您没有在函数中定义knots的值。

问题2:knots的值不是您想要的值。您需要speed的值(返回时)。

您可以将结果knots定义为输出数组,也可以使用子例程。我不会详细介绍这两种方法(因为那里有大量资源),但我会清楚地注意到:如果knots成为带有结果数组的函数,则需要{{3它被引用时可用。