2013-01-10 93 views
3

當前在我的程序中,我有幾個公用塊遍佈幾個子程序和函數。我有時會忘記在添加變量時,更改公共塊的所有實例。我想將這些通用塊組合成模塊,這樣我就可以在一個地方向模塊添加和刪除變量,而無需擔心在我的子程序中更新模塊的所有實例。從多個公共塊中創建多個模塊fortran 77

我是否需要在程序中包含'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

你只需要一個模塊的一個實例。您通過use聲明將其用於任何主程序或過程(子例程或函數)。如果你有一個子程序來設置值,那麼就像其他任何設置值一樣,它必須有一個use語句。如果正在設置初始值,您可以在聲明中這樣做。如果主程序使用該模塊,那麼它將始終處於範圍內,並且變量的值將在整個程序運行過程中保持不變。如果模塊僅被過程使用,那麼當調用鏈中沒有任何過程時,模塊原則上會超出範圍,並且編譯器被允許忘記模塊變量的值。 (任何Fortran編譯器實際上都這樣做是令人懷疑的。)通過聲明每個變量爲SAVE可以避免這種情況。如果用初始值聲明變量,則隱含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 
+1

自從2003年Fortran(或2008年?)以來,所有模塊變量都會自動保存。 – eriktous

+0

這非常有幫助。謝謝。希望在週末我可以成功地將模塊實現到我的程序中。 – kxk7607

+0

模塊的使用優於使用'include'嗎?我目前在我的MAIN結尾有很多'include'語句。我的理解是,包含的子程序可以彼此隱式訪問。這是一個正確的理解?我應該實現模塊嗎?我已經有了該程序,但如果使用模塊將使人們更容易編輯我的程序,那麼我將花時間實施它們。 – kxk7607

1

有幾個原因,爲什麼你的代碼不能編譯:

  1. 你有你的模塊定位你的主程序後,這意味着他們將不會有編譯時你use他們在那裏。將它們放在單獨的文件中並在主程序之前編譯它們,或將它們放在主程序之前。

  2. 您在主程序中重新聲明模塊中的變量,編譯器會將其解釋爲名稱衝突。具有public屬性(這是默認值)的所有模塊變量將在您的模塊use的範圍內可用;這被稱爲「使用關聯」。換句話說,use vals就足以使x,yint可用。

此外,模塊更像單一對象而不僅僅是數據容器。它們也可以包含在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 

上面,我已經使用了「新」 ::雙冒號操作符,它允許申報,一次初始化多個變量。由於模塊變量隱含地已經是save,這就好了。或者,如果這些模塊旨在分開,也可以在主程序(或任何子程序)中有contains部分,並將子例程放置在那裏。其優點是以這種方式聲明的過程總是具有明確的接口,這對編譯器的錯誤診斷有很大的好處,甚至在某些較新的情況下也是需要的。這是F90的主要改進之一,因爲F77只處理外部子程序和隱式接口。

+1

哦,darn,走開了一下,沒有看到MSB的答案。冗餘部門的道歉。 – sigma

-1

執行通用塊的最簡單方法是在每個公共塊中包含一個包含文件,並在包含文件中進行所有聲明。那樣的話,這個公共塊只能在一個地方聲明。不得不將代碼轉換爲使用模塊然後只是神奇地消失的問題。另外,如果你正在開始新的代碼,在公共塊變量的名稱前加上與指定的公共塊相同的名稱將使編碼變得容易很多。這最初是一種痛苦,並且多年來一直在進行編碼的首席代表將拒絕遵守。維護代碼的人會發現它很容易:沒有greps或groks。只要看一下這個名字,你就知道它來自哪個共同塊。

與模塊保持相同的約定也有幫助。如果所有例程名稱和變量名稱都以模塊名稱開頭,那麼只需查看名稱即可知道它來自哪個模塊。

+1

這是非常可憐的建議。在這個問題的背景下,它特別差,並且在這裏接受了答案,OP已經重寫模塊。正確使用它們是比普通塊更好的方法幷包含語句。將代碼轉換爲使用模塊不是問題,這是增強代碼的機會。 –