Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用fortran 77从多个公共块生成多个模块_Fortran_Gfortran_Fortran77_Fortran Common Block - Fatal编程技术网

用fortran 77从多个公共块生成多个模块

用fortran 77从多个公共块生成多个模块,fortran,gfortran,fortran77,fortran-common-block,Fortran,Gfortran,Fortran77,Fortran Common Block,目前在我的程序中,我有几个公共块分布在几个子程序和函数中。在向公共块添加变量时,有时会忘记更改它的所有实例。我想把这些公共块做成模块,这样我就可以在一个地方向模块添加和删除变量,而不用担心在子程序中更新模块的所有实例 我是否需要在初始化模块中变量的程序中包含“use”语句,还是在模块中包含该程序?我通常会使用公共块来实现这一点,但我正在尝试实现模块,因为我认为随着复杂性的增加,它们将帮助我的代码保持可读性 注意:模块中的一些变量值需要能够在从一个程序传递到另一个程序时进行更改 我试图编写一个简化

目前在我的程序中,我有几个公共块分布在几个子程序和函数中。在向公共块添加变量时,有时会忘记更改它的所有实例。我想把这些公共块做成模块,这样我就可以在一个地方向模块添加和删除变量,而不用担心在子程序中更新模块的所有实例

我是否需要在初始化模块中变量的程序中包含“use”语句,还是在模块中包含该程序?我通常会使用公共块来实现这一点,但我正在尝试实现模块,因为我认为随着复杂性的增加,它们将帮助我的代码保持可读性

注意:模块中的一些变量值需要能够在从一个程序传递到另一个程序时进行更改

我试图编写一个简化的测试程序来熟悉模块,但未能使其正常工作。我熟悉fortran 77,但以前从未使用过模块。我感谢任何帮助或建议

我正在使用gfortran 4.6.1

Main.f

program main
use Words
use Vals
double precision x,y,z
character*5 Greet
integer i

Greet = 'Hello'
x = 4.1
y = 5.2
z = 10.0
i = 3

call foo ()

end program main

subroutine foo ()
use Words
use Vals

print *, Greet

z = x + y
print *, z

print *, i

end subroutine

module Words
character*5 Greet
save
end module

module Vals
double precision x,y
integer int
save
end module

您只需要模块的一个实例。您可以通过
use
语句向任何使用它的主程序或过程(子程序或函数)公开它。如果您有一个设置值的子例程,那么与其他任何子例程一样,它必须有一个
use
语句。如果要设置初始值,可以在声明中进行设置。如果主程序使用该模块,则该模块将始终在作用域内,并且变量的值将在整个程序运行期间保持不变。如果模块仅由过程使用,原则上,当这些过程都不在调用链中,并且允许编译器忘记模块变量的值时,模块将超出范围。(任何Fortran编译器是否真的能做到这一点是值得怀疑的。)这可以通过使用
SAVE
声明每个变量来防止<如果使用初始值声明变量,则代码>保存是隐式的

通常,在使用模块之前必须先编译模块,以便编译器在遇到use语句时“知道”它们。这可以通过将它们放在文件的第一位或首先编译它们的文件来实现。以下是重新排序的示例:

module Words
character*5 Greet
save
end module

module Vals
double precision x,y
integer i
save
end module

module my_subs

contains

subroutine foo ()
use Words
use Vals
double precision :: z

print *, Greet

z = x + y
print *, z

print *, i

end subroutine

end module my_subs


program main
use Words
use Vals
use my_subs


Greet = 'Hello'
x = 4.1
y = 5.2

i = 3

call foo ()

end program main

代码无法编译的原因有两个:

  • 您将模块放在主程序之后,这意味着在您
    在那里使用它们时,它们不会被编译。或者将它们放在单独的文件中,并在主程序之前编译,或者将它们放在主程序之前

  • 在主程序中重新声明模块中的变量,编译器会将其解释为名称冲突。具有
    public
    属性(默认值)的所有模块变量将在
    使用该模块的范围内可用;这被称为“使用关联”。换句话说,
    使用VAL
    足以使
    x
    y
    int
    可用

  • 此外,模块更像是单例对象,而不仅仅是数据容器。它们还可以包含过程,在
    contains
    语句之后列出,这有助于将变量和相关过程分组在一起。例如,将两个模块与子例程
    foo
    一起分组为一个模块:

    module vals
      implicit none
    
      double precision :: x = 4.1, y = 5.2
      integer :: i = 3
      character(5) :: greet = 'Hello'
    
    contains
      subroutine foo()
        double precision :: z  ! New local variable
    
        print *, Greet
    
        z = x + y
        print *, z
    
        print *, i
      end subroutine
    end module
    
    上面,我使用了“new”
    双冒号操作符,它允许一次声明和初始化多个变量。因为模块变量已经隐式地保存了,所以这很好


    或者,如果这些模块是分开的,也可以在主程序(或任何子程序)中包含
    contains
    部分,并将子例程放在那里。其优点是,以这种方式声明的过程总是具有显式接口,这大大有利于编译器进行错误诊断,甚至在某些较新的情况下也是必需的。这是F90的主要改进之一,因为F77只处理外部子程序和隐式接口。

    执行公共块的最简单方法是每个公共块有一个包含文件,并在包含文件中进行所有声明。这样,公共块只在一个地方声明。必须将代码转换为使用模块的问题神奇地消失了

    此外,如果您正在启动新代码,则在公共块变量的名称前加上与命名公共块相同的名称,将使编码变得更加容易。最初这是一种痛苦,多年来一直在编码的首席女主角将拒绝遵从。维护代码的人会发现它很简单:没有greps或groks。只需查看名称,您就知道它来自哪个公共块


    对模块保持相同的约定也有帮助。如果所有例程名称和变量名称都以模块名称开头,那么只需查看名称,您就知道它来自哪个模块。

    自fortran 2003(或者是2008?)以来,所有模块变量都会自动保存。这非常有帮助。非常感谢。希望在周末我能成功地在我的程序中实现模块。使用模块是否比使用
    include
    更可取?我目前在我的主要报告末尾有许多“包含”语句。我的理解是,所包含的子例程彼此可以隐式访问。这是正确的理解吗?我应该实现模块吗?我的程序已经在运行了,但是如果使用模块可以使人们在将来编辑我的程序时更加容易,那么我将花时间来实现它们。如果您使用contain语句将子程序放在主程序之后,我建议将它们放在模块中。首先,主程序中contain语句后的子例程