4

現在、私のプログラムには、いくつかのサブプログラムと関数にまたがるいくつかの共通ブロックがあります。変数を追加するときに、共通ブロックのすべてのインスタンスを変更するのを忘れることがあります。これらの共通ブロックをモジュールにして、サブプログラム全体でモジュールのすべてのインスタンスを更新することを心配することなく、変数を 1 か所でモジュールに追加および削除できるようにしたいと考えています。

モジュール内の変数を初期化するプログラムに「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
4

3 に答える 3

5

モジュールのインスタンスは1つだけ必要です。useステートメントでそれを使用するすべてのメインプログラムまたはプロシージャ(サブルーチンまたは関数)にそれを知らせます。値を設定するサブルーチンがある場合は、他のサブルーチンと同様に、useステートメントが必要です。が初期値を設定している場合は、宣言で設定できます。モジュールがメインプログラムによって使用される場合、そのモジュールは常にスコープ内にあり、変数の値はプログラムの実行中ずっと保持されます。モジュールがプロシージャによってのみ使用される場合、原則として、これらのプロシージャのいずれもコールチェーンに含まれておらず、コンパイラがモジュール変数の値を忘れることができると、モジュールはスコープ外になります。(Fortranコンパイラが実際にこれを行うかどうかは疑わしいです。)これは、各変数を。で宣言することで防ぐことができますSAVESAVE初期値で変数を宣言する場合は暗黙的です。

通常、モジュールを使用する前に最初にモジュールをコンパイルして、コンパイラが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
于 2013-01-10T16:54:53.603 に答える
1

コードがコンパイルされない理由はいくつかあります。

  1. モジュールはメインプログラムの後に配置されています。つまり、モジュールがそこにあるときまでにコンパイルされていませんuse。これらを別々のファイルに入れてメインプログラムの前にコンパイルするか、メインプログラムの前に置いてください。

  2. メインプログラムでモジュールから変数を再宣言します。これは、コンパイラが名前の競合として解釈します。public属性(デフォルト)を持つすべてのモジュール変数は、モジュールを使用するスコープで使用可能になりuseます。これは「使用の関連付け」と呼ばれます。言い換えれば、use valsを作成するのに十分xyあり、int利用可能です。

さらに、モジュールは単なるデータコンテナではなく、シングルトンオブジェクトに似ています。また、ステートメントの後にリストされるプロシージャを含めることもできます。これはcontains、変数と関連するプロシージャをグループ化するのに役立ちます。例として、2つのモジュールを1つにグループ化し、サブルーチンを作成し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

::上記では、複数の変数を一度に宣言して初期化できる「新しい」二重コロン演算子を使用しました。モジュール変数はすでにsave暗黙的に'dされているので、これは問題ありません。

あるいは、これらのモジュールを分離することを目的としている場合はcontains、メインプログラム(または任意のサブプログラム)にセクションを作成し、そこにサブルーチンを配置することもできます。利点は、そのような方法で宣言されたプロシージャが常に明示的なインターフェイスを持っていることです。これは、コンパイラによるエラー診断に非常に役立ち、特定の新しい場合でも必要になります。F77は外部サブプログラムと暗黙のインターフェイスのみを処理するため、これはF90の主な改善点の1つです。

于 2013-01-10T17:24:51.620 に答える
-1

共通ブロックを実行する最も簡単な方法は、共通ブロックごとに 1 つのインクルード ファイルを作成し、そのインクルード ファイル内ですべての宣言を行うことです。このように、共通ブロックは 1 か所でのみ宣言されます。モジュールを使用するためにコードを変換しなければならないという問題は、魔法のように消えます。

また、新しいコードを開始する場合、共通ブロック変数の名前の前に名前付き共通ブロックと同じ名前を付けると、コーディングがはるかに簡単になります。それは最初は苦痛であり、何年もコーディングしてきたプリマドンナは準拠を拒否します. コードを保守する人は、非常に簡単であることに気付くでしょう。grep や grok は必要ありません。名前を見るだけで、それがどの共通ブロックに由来するかがわかります。

モジュールで同じ規則を維持することも役立ちます。すべてのルーチン名と変数名がモジュール名で始まる場合、名前を見るだけで、それがどのモジュールからのものかがわかります。

于 2013-03-17T09:15:34.780 に答える