轉(zhuǎn)自:http://zhousicheng.googlepages.com/a_014目錄:
【主程序】【語句函數(shù)】【內(nèi)在過程】【內(nèi)部過程】【外部過程】
◆外部函數(shù)◆外部子程序◆EXTERNAL屬性和啞過程◆INTENT屬性◆OPTIONAL屬性◆啞元改名◆關(guān)鍵字變元INTRINSIC屬性◆類屬過程◆過程接口 INTERFACE◆超載操作符◆自定義操作符◆超載賦值號
【模塊】【塊數(shù)據(jù)】【指針】
【主程序】
!-----------------------------------------------------------------------
[PROGRAM [程序名]]
[說明部分]
[可執(zhí)行部分]
[CONTAINS
內(nèi)部過程]
END [PROGRAM [程序名]]
!-----------------------------------------------------------------------
【語句函數(shù)】 f(x)=x**2+1
【內(nèi)在過程】 max,abs,sin,char。。。。
【內(nèi)部過程】 Contains
與宿主程序共享變量名, 外部過程FUNCTION, SUBROUTINE都可以有自己的內(nèi)部過程。
通常沒有說明語句。
沒有啞元,無啞實結(jié)合。
使用內(nèi)部過程的規(guī)則:在宿主中不要定義子程序名和函數(shù)名的類型,也不能指定它們是有EXTERNAL屬性。宿主中的變量名和數(shù)組名等在內(nèi)部過程中有效,有相同的數(shù)值。但同一名若在內(nèi)部過程中又進行了類型聲明,則此名被視為其過程中的獨立變量,無相同的數(shù)值。內(nèi)部過程中也可引用另一內(nèi)部過程。
例:
!-----------------------------------------------------------------------
program internal
real a,b,c
call find
print *,c
contains
subroutine find
read *, a,b
c=sqrt(a**2+b**2)
end subroutine find
end
!-----------------------------------------------------------------------
【外部過程】
過程=函數(shù)&子程序
啞元調(diào)用方式:傳址調(diào)用call by adress,即傳遞4字節(jié)的變量的內(nèi)存地址。
◆外部函數(shù)
調(diào)用:函數(shù)名(實元表) 函數(shù)名()
如果沒有結(jié)果名,則函數(shù)名就是結(jié)果名。
!-----------------------------------------------------------------------
[前綴] FUNCTION 函數(shù)名([啞元列表])[RESULT(結(jié)果名)]
[說明部分]
[可執(zhí)行部分]
[CONTAINS
內(nèi)部過程]
END [FUNCTION 函數(shù)名]
!-----------------------------------------------------------------------
◆外部子程序:
調(diào)用:
CALL 子程序名 [(啞元列表)]
啞元可以是變量名、數(shù)組名、過程名、指針名等均可作為啞元。它們之間用逗號隔開。
前綴是F90中新增的,它可以是:[類型說明] 或[關(guān)鍵詞]。關(guān)鍵詞:RECURSIVE(F90),PURE(F95),ELEMENTAL(F95)。RECURSIVE表示過程時可以直接或間接地調(diào)用自身,即遞歸調(diào)用,其過程是遞歸過程。
!-----------------------------------------------------------------------
[前綴] SUBROUTINE 子程序名[(啞元列表)]
[說明部分]
[可執(zhí)行部分]
[CONTAINS
內(nèi)部過程]
END [SUBROUTINE [子程序名]]
!-----------------------------------------------------------------------
一個有用的例子:互換數(shù)字
!-----------------------------------------------------------------------
SUBROUTINE swap(p,q)
INTEGER :: p,q,r
r=p;p=q;q=r
RETURN
END
!-----------------------------------------------------------------------
◆EXTERNAL屬性和啞過程 (啞元為外部過程,即啞過程)
指定EXTERNAL語句或?qū)傩哉f明實元實際上是外部過程
類型定義語句: 類型,EXTERNAL :: 外部函數(shù)名[,外部函數(shù)名]…
或EXTERNAL語句:EXTERNAL [外部函數(shù)名][,子程序名][,塊數(shù)據(jù)名]…
啞元也可以是一個過程,這時作為啞元的過程稱為啞過程。(至少兩層調(diào)用)
例如:
!-----------------------------------------------------------------------
Programm main
Real x,y
External Plus !外部過程名作實元,必須用External說明,或者具有External屬性
x=1.0 ; y=2.0
Print,* Calculate(x,y,Plus) !調(diào)用Calculate函數(shù),實元為外部過程Plus
End Program main
Real Function Plus(a,b) !(第二層被調(diào)用的外部函數(shù))
Real, Intent(In) :: a,b
Plus=a+b
End Function Plus
Real Function Calculate (x,y,func)
Real, Intent(In) :: x,y
Real, External func !類型定義語句, 說明啞元時一個外部過程, 也可以直接用External說明
Calculate=func(x,y) !調(diào)用自定義的外部函數(shù)
End Function Calculate
!-----------------------------------------------------------------------
或者將 Real, External func 改為接口程序:
Interface
Real Function Plus(a,b) !Plus被接口塊說明為一個啞元,即一個啞過程
Real, Intent(In) :: a,b
End Function Plus
End Interface
◆INTENT屬性 (過程的啞元說明)
在類型定義語句中: 類型,INTENT(意圖說明符) :: 啞元名表
或用INTENT語句 : INTENT(意圖說明符) :: 啞元名表
意圖說明符為以下字符串:
IN 指明啞元僅用于向過程提供數(shù)據(jù),過程的執(zhí)行期間啞元不能被重定義或成為未定義的,相聯(lián)合的實元可以是常數(shù)、變量、數(shù)組以及它們的算術(shù)表達式。
OUT 指明啞元用于把過程中的數(shù)據(jù)傳回調(diào)用過程的程序,與之相結(jié)合的實元只允許是變量,不得為常數(shù)。
INOUT 指明啞元既可以用于向過程提供數(shù)據(jù),也可用于返回數(shù)據(jù),與之相結(jié)合的實元只允許是變量。
◆OPTIONAL屬性可選變元,部分啞元作啞實結(jié)合
內(nèi)在函數(shù)PRESET用來反映它的自變量是否在程序執(zhí)行部分中出現(xiàn)。PRESET(A)的值是一個邏輯值,以此來構(gòu)造不同的算法。
例如,要求編一子程序,既能求四邊形同長(A+B+C+D)的值,也能求三角形周長(A+B+C)的值。此時D就是可選擇變元,并規(guī)定當D不出現(xiàn)時,置D值為零。子程序如下:
!-----------------------------------------------------------------------
SUBROUTINE SUM(S,A,B,C,D)
IMPLICIT NONE
REAL,INTENT(IN) :: A,B,C
REAL,INTENT(IN),OPTIONAL :: D
REAL,INTENT(OUT) :: S
REAL :: TEMP
IF(PRESET(D)) THEN
TEMP=D
ELSE
TEMP=0.
END IF
S=A+B+C+TEMP
END SUBROUTINE SUM
!-----------------------------------------------------------------------
◆啞元改名
例如,對于上面求邊長的子程序,如調(diào)用時欲把啞元名A,B,C,D改為物理意義明確的名稱UPPER,DOWN,LEFT,RIGHT,只需在主調(diào)程序中寫入接口塊,在接口塊的啞元表中用新的啞元名即可:
!-----------------------------------------------------------------------
PROGRAM SUMMATION
INTERFACE
SUBROUTINE SUM(S,UPPER,DOWN,LEFT,RIGHT)
IMPLICIT NONE
REAL,INTENT(IN) :: UPPER,DOWN,LEFT
REAL,INTENT(IN),OPTIONAL :: RIGHT
REAL,INTENT(OUT) :: S
REAL :: TEMP
END SUBROUTINE SUM
END INTERFACE
READ *, UPPER,DOWN,LEFT,RIGHT
CALL SUBROUTINE SUM(S,UPPER,DOWN,LEFT,RIGHT)
……
END PROGRAM SUMMATION
!-----------------------------------------------------------------------
◆關(guān)鍵字變元
啞實結(jié)合:(啞元名=實元表達式)
例如: CALL TEST(1,10,D=1000,C=100)
同: CALL TEST(A=1,B=10,D=1000,C=100)
F90也允許在調(diào)用語句中,前面部分實元不用關(guān)鍵字變元,只從某一個變元開始用關(guān)鍵字變元。
主調(diào)程序中如采用關(guān)鍵字變元調(diào)用過程,就必須寫出被調(diào)子程序的接口塊。
!-----------------------------------------------------------------------
PROGRAM swap_pro !交換大小兩個實數(shù)swap(a,b)
INTERFACE
SUBROUTINE swap(klein,gross)
IMPLICIT NONE
REAL,INTENT(out) :: klein,gross
END SUBROUTINE swap
END INTERFACE
READ *, klein,gross
CALL SUBROUTINE swap(klein,gross)
……
END PROGRAM swap_pro
!-----------------------------------------------------------------------
◆INTRINSIC屬性
與EXTERNAL語句或?qū)傩哉f明的實元是外部過程相對應(yīng),INTRINSIC語句或?qū)傩杂脕碚f明實元實際上是內(nèi)在過程。其一般形式為:
類型定義語句:類型,INTRINSIC :: 內(nèi)在函數(shù)名[,內(nèi)在函數(shù)名]…
或INTRINSIC語句:INTRINSIC 內(nèi)在過程名[,內(nèi)在過程名]…
內(nèi)在過程名必須是內(nèi)在過程的通用名或?qū)S妹H绻菍S妹?,則可以在其作用范圍單元中作為一個過程的實元,但它必須出現(xiàn)在一個INTRINSIC語句中,或被該單元中的一個類型聲明語句指明具有INTRINSIC屬性。需要注意的是,一個內(nèi)在過程名只能在INTRINSIC語句中出現(xiàn)一次,并且不能同時出現(xiàn)在INTRINSIC語句和EXTERNAL語句中。
例:
!-----------------------------------------------------------------------
PROGRAM MAIN
REAL F
REAL,INTRINSIC :: ALOG !說明Alog是內(nèi)部函數(shù),可以作實元
F=CALCULATE(0.0,1.0,ALOG) !使用內(nèi)在函數(shù)ALOG作實元
…
END PROGRAM
!-----------------------------------------------------------------------
注意這里必須用專用名ALOG,而不能用通用名LOG。
◆類屬過程
允許用不同類型的實元與同一個啞元結(jié)合,如內(nèi)在基本函數(shù)ABS(X),結(jié)合的實元可以是整型、實型與復(fù)型。
例如,要編寫求兩數(shù)之和的類屬函數(shù)時,分別編寫啞元是實型和整型的函數(shù):
!-----------------------------------------------------------------------
FUNCTION SUM_REAL(A,B) RESULT(SUM_REAL_RESULT)
REAL :: A,B,SUM_REAL_RESULT
SUM_REAL_RESULT=A+B
END FUNCTION SUM_REAL
FUNCTION SUM_INTEGER(A,B) RESULT(SUM_INTEGER_RESULT)
INTEGER :: A,B,SUM_INTEGER_RESULT
SUM_INTEGER_RESULT=A+B
END FUNCTION SUM_INTEGER
!現(xiàn)在把這兩個函數(shù)過程綜合成一個類屬函數(shù),類屬函數(shù)名取為MY_SUM,在主調(diào)程序應(yīng)寫明如下接口:
PROGRAM SUMMATION
INTERFACE MY_SUM
FUNCTION SUM_REAL(A,B) RESULT(SUM_REAL_RESULT)
REAL :: A,B,SUM_REAL_RESULT
END FUNCTION SUM_REAL
FUNCTION SUM_INTEGER(A,B) RESULT(SUM_INTEGER_RESULT)
INTEGER :: A,B,SUM_INTEGER_RESULT
END FUNCTION SUM_INTEGER
END INTERFACE
IMPLICIT NONE
REAL :: X,Y
INTEGER :: I,J
READ *, X,Y,I,J
PRINT *, MY_SUM(X,Y),MY_SUM(I,J)
END PROGRAM SUMMATION
!-----------------------------------------------------------------------
◆過程接口 INTERFACE
一個內(nèi)部過程總是由程序單元中的語句來調(diào)用的。一般來講,編譯程序知道內(nèi)部過程的一切情況,如知道該過程是一個函數(shù)或子程序、過程名、啞元的名字、變量類型和屬性、函數(shù)結(jié)果的特性等等。這個信息的集合被稱為過程的接口(interface)。
對于內(nèi)部過程、內(nèi)在過程和模塊,過程接口對編譯程序而言是己知的和顯式給出的,故稱顯式接口。
如在調(diào)用一個外部過程或一個啞過程時,編譯系統(tǒng)通常不知道該過程的各種情況,這種接口是隱式的。
用EXTERNAL語句來指明一個外部過程或啞過程,但此語句僅說明每一個外部名是一個外部過程名或啞過程名,并沒有指明過程的接口,所以接口仍是隱式的。
為了全面準確地通知編譯系統(tǒng),在主調(diào)程序中有時需要加入接口塊,以說明主調(diào)程序與被調(diào)程序的接口。接口塊是F90中引進的新穎程序塊,它顯式指明了過程接口的機制。通過接口塊可用為一個外部過程或啞過程指明一個顯式的接口。這比EXTERNAL語句提供了更多的信息,也提高了程序的可讀性。
過程接口確定過程被調(diào)用的形式,它由過程的特性、過程名、各啞元的名字和特性以及過程的類屬標識符(可以省略)組成,一般它們都被寫在一個過程的開頭部分。此接口塊被放在主調(diào)程序的說明部分中,通常還應(yīng)寫在類型說明語句之前,它的內(nèi)容是被調(diào)用的過程中的說明部分,功能是通知編譯系統(tǒng),主調(diào)程序調(diào)用的過程中各種變元的類型、屬性、性質(zhì)等。
用法:
!-----------------------------------------------------------------------
INTERFACE [類屬說明]
[接口體]…
[模塊過程語句]…
END INTERFACE [類屬說明]
!-----------------------------------------------------------------------
其中類屬說明的形式為:
類屬名 -> 類屬過程
OPERATOR -> 超載操作符、自定義操作符
ASSIGNMENT(=) -> 超載賦值號
接口體的形式為:
函數(shù)語句
[說明部分]
函數(shù)END語句
子程序語句
[說明部分]
子程序END語句
模塊過程語句的形式為:MODULE PROCEDURE 過程名表。
例:
!-----------------------------------------------------------------------
interface
subroutine swap(x,y)
real x,y
end subroutine
end interface
real a,b
read *,a,b
call swap(a,b)
end
subroutine swap(x,y)
real x,y
z=x;x=y;y=z
end subroutine
!-----------------------------------------------------------------------
凡遇下列情況之一時,主調(diào)程序必須有接口塊:
1、如果外部過程具有以下特征:
過程的啞元有可選擇屬性。
過程的啞元是假定形數(shù)組、指針變量、目標變量。
函數(shù)過程的結(jié)果是數(shù)組或指針。
對于字符型函數(shù)過程的結(jié)果、其長度不是常數(shù),也非假定長度(*)。
2、如果調(diào)用過程時出現(xiàn):
實元是關(guān)鍵字變元。
用一個類屬名調(diào)用。
用超載賦值號(對于子程序)。
用超載操作符(對于函數(shù))。
3、如果過程前綴關(guān)鍵詞是ELEMENTAL
◆超載操作符
超載操作符的形式仍是系統(tǒng)內(nèi)部操作符,如+、-、*、/等,但通過編出恰當?shù)倪^程,可以擴充這些操作符的功能。例如;‘+’本來用于對數(shù)值作算術(shù)操作,但經(jīng)恰當?shù)木幊毯?#8216;+’也可用于字符型操作,這就像車輛超載一樣,故稱為超載操作符。定義超載操作符,需先編寫一個實現(xiàn)此超載(擴充)功能的函數(shù)過程,再在主調(diào)程序中編寫過程的接口,在接口語句后加上超載說明,其一般形式為:
INTERFACE OPERATOR(被超載使用的操作符號)
例如:要使‘+’超載能執(zhí)行如下操作:把兩個字符串的最后一個字母接起來。
!-----------------------------------------------------------------------
PROGRAM ADD_CHARACTER
IMPLICIT NONE
CHARACTER(LEN=10) :: A,B
INTEGER :: I,J
INTERFACE OPERATOR(+)
FUNCTION ADD(A,B) RESULT(ADD_RESULT)
IMPLICIT NONE
CHARACTER(LEN=*),INTENT(IN) :: A,B
CHARACTER(LEN=2) :: ADD_RESULT
END FUNCTION ADD
END INTERFACE
READ *, A,B
PRINT *, A+B,2+3
END PROGRAM ADD_CHARACTER
FUNCTION ADD(A,B) RESULT(ADD_RESULT)
IMPLICIT NONE
CHARACTER(LEN=*),INTENT(IN) :: A,B
CHARACTER(LEN=2) :: ADD_RESULT
ADD_RESULT=A(LEN_TRIM(A):LEN_TRIM(A))//B(LEN_TRIM(B):LEN_TRIM(B))
END FUNCTION ADD
!-----------------------------------------------------------------------
接口的作用是向編譯系統(tǒng)提示,遇到操作符‘+’時,如果操作數(shù)不是數(shù)值,就不是原來意義的加法,操作含義要到 FUNCTION ADD中找。當主調(diào)程序有了上述接口塊后,在下面執(zhí)行部分中執(zhí)行字符串操作CH1+CH2時,+號作超載用。
◆自定義操作符 .klein. .gross. .plus.
INTERFACE OPERATOR(.plus.) ! .plus. = +
MODULE PROCEDURE add
END INTERFACE
◆超載賦值號 INTERFACE ASSIGNMENT(=)
例:編一程序把邏輯量超載賦值給整型變量。先編一個實現(xiàn)這一功能的子程序,
!-----------------------------------------------------------------------
SUBROUTINE LOG_INT(I,L)
IMPLICIT NONE
LOGICAL, INTENT(IN) :: L
INTEGER, INTENT(OUT):: I
IF(L) I=1 !I=.True. 得到1
IF(.NOT.L) I=0 !I=.Falsh. 得到0
END SUBROUTINE LOG_INT
再在主程序內(nèi)編寫接口,
INTERFACE ASSIGNMENT(=)
SUBROUTINE LOG_INT(I,L)
IMPLICIT NONE
LOGICAL, INTENT(IN) :: L
INTEGER, INTENT(OUT):: I
END SUBROUTINE LOG_INT
END INTERFACE
!-----------------------------------------------------------------------
I=1 得到1
I=.True. 得到1
I=.Falsh. 得到0
【模塊】 復(fù)制所有語句,共享所有變量
共享數(shù)據(jù)的2個方法:一個是啞實結(jié)合,一個就是數(shù)據(jù)共享
共享方式有:使用COMMON語句和EQUIVALENCE語句(F77),使用模塊(F90)。另外,使用INCLUDE復(fù)制。
!-----------------------------------------------------------------------
COMMON [/[公共塊名1]/]變量名表1[[,]/[公共塊名2]/變量名表2]...
EQUIVALENCE (變量名表1),(變量名表2),… !僅限于同一程序單元
INCLUDE '文件名[/[NO]LIST]'
!-----------------------------------------------------------------------
例如:下面的COMMON語句段
COMMON/happy/we,you,they
COMMON/ /our,your,their
COMMON/happy/i,he,she
COMMON/angry/dog,cat,mouse
COMMON my,his,her
等價于語句段,
COMMON/happy/we,you,they,i,he,she
COMMON/angry/dog,cat,mouse
COMMON/ /our,your,their,my,his,her
!-----------------------------------------------------------------------
◆模塊用途:
包含通常使用的過程
聲明全局變量和派生類型
聲明外部過程的接口塊
初始化全局數(shù)據(jù)和全局可分配數(shù)組
封裝數(shù)據(jù)和處理數(shù)據(jù)的過程
存儲在公共塊COMMON中的變量可以被摘錄和保存到模塊之中。
如果一個程序單元中,只使用模塊中的部分變量或需要重新命名部分變量,可以指定這些變量具有ONLY屬性。
模塊用法:
!-----------------------------------------------------------------------
MODULE 模塊名
類型說明部分
[CONTAINS
內(nèi)部過程
…
[內(nèi)部過程]]
END MODULE [模塊名]
!-----------------------------------------------------------------------
例如:
MODULE MY_MODULE
REAL, PARAMETER :: Pi=3.141592654
CONTAINS
SUBROUTINE SWAP(X,Y)
REAL :: TEMP,X,Y
TEMP=X
X=Y
Y=TEMP
END SUBROUTINE SWAP
END MODULE MY_MODULE
該模塊內(nèi)有一內(nèi)部過程SWAP,引用這個模塊的外部過程都將包含有此內(nèi)部過程。
◆使用模塊:
USE 模塊名1, 模塊名2, … 模塊名n
它包括兩方面:模塊定義時規(guī)定只有哪些內(nèi)容允許共享、引用模塊時只要求共享哪些內(nèi)容。
1) 模塊的PRIVATE屬性:
當定義派生類型的TYPE塊寫在模塊中時,可以限制該派生類型定義的使用范圍,以及類型定義內(nèi)各成員的使用范圍。譬如規(guī)定模塊內(nèi)的該派生類型或派生類型內(nèi)的成員只供本模塊內(nèi)引用,不許模塊外程序單元引用。其形式是:
!-----------------------------------------------------------------------
TYPE,PRIVATE :: 派生類型名
成員1類型說明
……
成員n類型說明
END TYPE [派生類型名]
!-----------------------------------------------------------------------
使用PRIVATE專用特性后,可以禁止一切外部過程(包括主程序)訪問派生類型的內(nèi)部成員,而只是把派生定義類型作為一個整體黑箱使用。以后如果派生類型內(nèi)部成員要改動,只需改寫派生類型部分,引用模塊的各程序單元可不必改動。
2) 模塊內(nèi)的變量改名:
如果需要對多個模塊進行訪問,而在不同的模塊中可能用到了相同的名字,因此允許USE語句對被訪問的實體重新命名,以解決局部實體和模塊中訪問實體之間的名字沖突問題。要重新命名時,USE語句具有下列形式:
!-----------------------------------------------------------------------
USE 模塊名 [,改名列表]
!-----------------------------------------------------------------------
其中,改名列表的形式為:局部名1=>塊中名1, 局部名2=>塊中名2, …。其中,局部名是使用USE語句的程序單元中用的名字,塊中名是待改的模塊內(nèi)部使用的變量名。
如模塊中定義的變量名是A、B,程序單元中同名變量A、B與之共享,但若要在程序單元中把變量名改為C、D,則只需在單元內(nèi)把引用語句寫成:
USE模塊名, C=>A, D=>B
即可,而無需修改模塊。
3) ONLY選項:
可以規(guī)定只取模塊中一部分變量與本程序單元中實體共享,即只需要使用模塊中的部分實體,其它實體沒有共享關(guān)系。這時可在USE語句中使用ONLY選項。這時USE語句具有下列形式:
!-----------------------------------------------------------------------
USE模塊名, ONLY : [,僅用名列表]
!-----------------------------------------------------------------------
其中,僅用名列表的形式為:[局部名1=>]塊中名1, [局部名2=>]塊中名2, …。
模塊應(yīng)用:
1) 全局數(shù)據(jù)
如果數(shù)據(jù)是在整個可執(zhí)行程序中都要用到的全局數(shù)據(jù),可以把它們放在一個模塊中統(tǒng)一說明,在需要這些數(shù)據(jù)的程序單元內(nèi)使用USE語句導(dǎo)出它們即可。例如:
!-----------------------------------------------------------------------
MODULE DATA_MODULE
SAVE
REAL :: A(10), B, C(50,10)
INTEGER,PARAMETER :: I=10
COMPLEX D(I,I)
END MODULE DATA_MODULE
!-----------------------------------------------------------------------
如果要在程序單元中訪問模塊中定義的全部數(shù)據(jù)對象,可使用語句:
USE DATA_MODULE
如果只需訪問其中的A和D,則可使用語句:
USE DATA_MODULE, ONLY : A,D
如果要避免名字沖突而改名的話,則可使用語句:
USE DATA_MODULE, ONLY : A_MODULE=>A, D_MODULE=>D
2) 過程共享
利用模塊,還可以把整個可執(zhí)行程序中都要用到的全局過程封裝在一起,即把這些過程放在一個模塊中統(tǒng)一說明,而在需要這些過程的程序單元內(nèi)使用USE語句導(dǎo)出它們即可,這就是模塊過程。使用的方式是,首先在模塊中把待用的全局過程定義為模塊的內(nèi)部過程,即寫在CONTAINS語句之后,在調(diào)用過程單元中寫上USE語句以調(diào)用此模塊,再寫上接口塊,接口塊的實體是模塊過程語句:
USE MODULE PROCEDURE 模塊過程名表
例:
!-----------------------------------------------------------------------
PROGRAM CHANGE_KIND
USE Module1
INTERFACE DEFAULT
MODULE PROCEDURE Sub1, Sub2
END INTERFACE
integer(2) in
integer indef
indef = DEFAULT(in)
END PROGRAM
MODULE Module1
CONTAINS
FUNCTION Sub1(y)
REAL(8) y
sub1 = REAL(y)
END FUNCTION
FUNCTION Sub2(z)
INTEGER(2) z
sub2 = INT(z)
END FUNCTION
END MODULE
!-----------------------------------------------------------------------
3) 公用派生類型
模塊還可用來封裝一些派生類型,供其它程序單元公用。例如:
!-----------------------------------------------------------------------
MODULE SPARSE_MATRIX
TYPE NONEZERO
REAL A
INTEGER I,J
END TYPE
END MODULE SPARE_MATRIX
!-----------------------------------------------------------------------
定義了一個由實數(shù)和兩個整數(shù)構(gòu)成的數(shù)據(jù)類型,用以表示稀疏矩陣的非零元素。其中的實數(shù)表示元素的值,兩個整數(shù)表示該元素的下標。于是,派生類型NONZERO就可被其他單元通過USE語句來共用。
4) 全局可分配數(shù)組
在許多程序中需要一些全局公用的可分配數(shù)組,它們的大小在程序執(zhí)行前是不知道的,這時也可用模塊來實現(xiàn)。例如:
!-----------------------------------------------------------------------
PROGRAM MAIN
…
CAIL CONFIGURE_ARRAYS !分配數(shù)組
CALL COMPUTE !用分配好的數(shù)組進行計算
…
END PROGRAM MAIN
MODULE WORK_ARRAYS
INTEGER N
REAL,ALLOATABLE,SAVE :: A(:),B(:,:),C(:,:,:)
END MODULE WORK_ARRAYS
SUBROUTINE CONFIGURE_ARRAYS
USE WORK_ARRAYS
READ *,N
ALLOCATE(A(N),B(N,N),C(N,N,2*N))
END SUBROUTINE CONFIGURE_ARRAYS
SUBROUTINE COMPUTE
USE WORK_ARRAYS
…
END SUBROUTINE COMPUTE
!-----------------------------------------------------------------------
5) 抽象數(shù)據(jù)類型和超載運算
可以用模塊來自定義抽象數(shù)據(jù)類型,為此只需在模塊中先定義派生類型,再隨后定義可在這種類型值上進行的運算即可。例如:
!-----------------------------------------------------------------------
MODULE INTERVAL_ARITHMETIC
TYPE INTERVAL
REAL LOWER,UPPER
END TYPE INTERVAL
INTERFACE OPERATOR(+)
MODULE PROCEDURE COMB_INTERVALS
END INTERFACE
INTERFACE OPERATOR(*)
MODULE PROCEDURE INTERSECTION_INTERVALS
END INTERFACE
CONTAINS
FUNCTION COMB_INTERVALS(A,B)
TYPE(INTERVAL) COMB_INTERVALS,A,B
COMB_INTERVALS%LOWER=MIN(A&LOWER,B%LOWER)
COMB_INTERVALS%UPPER=MAX(A&UPPER,B%UPPER)
END FUNCTION
FUNCTION INTERSECTION_INTERVALS(A,B)
TYPE(INTERVAL) INTERSECTION_INTERVALS,A,B
INTERSECTION_INTERVALS%LOWER=MAX(A&LOWER,B%LOWER)
INTERSECTION_INTERVALS%UPPER=MIN(A&UPPER,B%UPPER)
END FUNCTION
END MODULE INTERVAL_ARITHMETIC
!-----------------------------------------------------------------------
模塊中定義了派生類型INTERVAL,它表示一個實數(shù)區(qū)間,通過接口塊說明定義的運算符‘+’和‘*’號,它們分別是求兩個區(qū)間的并計和交集。
【塊數(shù)據(jù)】--> 模塊
!-----------------------------------------------------------------------
BLOCK DATA[塊數(shù)據(jù)名]
[說明部分]
COMMON
DATA
END [BLOCK DATA[塊數(shù)據(jù)名]]
!-----------------------------------------------------------------------
【指針】
◆用法1:指向變量
Integer, Target :: a
Integer, Pointer :: p
p=>a
p=3 !改變指針指向的變量
!-----------------------------------------------------------------------
用法2:指向一塊內(nèi)存
Allocate (p) !給指針p分配一塊內(nèi)存空間
Deallocate (p) !重新指定p之前最好將其釋放
!-----------------------------------------------------------------------
◆查詢:
Associated (pointer,[target])
檢查針是否指向一個target,返回邏輯變量。
判斷:
確保開始指針沒有指向的函數(shù)null(),指向一塊不能用的內(nèi)存地址
Integer, Pointer :: p=>null() !F95用法
或者用Nullify命令,設(shè)置指針為不能使用的內(nèi)存地址
Nullify (pointer1, [pointer2,...]) !F90用法
32位機,一個pointer記錄一個地址,占4字節(jié)
◆數(shù)組操作:
用法1:
Integer, Target :: a(5)=(/1,2,3,4,5/)
Integer, Pointer :: p(:) !聲明p為一個一維指針數(shù)組,大小未定
p=>a
p=>a(1:5:2) !p=>部分數(shù)組
p=>a(5:1:-1)
!-----------------------------------------------------------------------
用法2
Integer, Pointer :: p(:)
Allocate (p(3)) !分配指針p內(nèi)存空間,3個整數(shù)
p=(/1,2,3,4,5/)
!-----------------------------------------------------------------------
◆指針作為啞元需要添加接口程序:
求一維數(shù)組的最小值,函數(shù)名和變量均為指針
!-----------------------------------------------------------------------
Implicit none
Integer, target :: a(5)
Integer, Pointer :: p(:)
Interface
Function getbig(p)
Integer, Pointer :: p(:)
Integer, pointer :: getbig
End Function
End Interface
a=(/1,2,3,4,5/)
p=>a
write (*,*) getbig(p)
stop
End
Function getbig(p)
Implicit none
Integer, Pointer :: p(:)
Integer, Pointer :: getbig
Integer n,temp,i
n=size(p,1)
temp=0
do i=1,n
if (temp<p(i)) then
temp=p(i)
getbig=>p(i)
endif
end do
End Function
!-----------------------------------------------------------------------
用Module來封裝函數(shù),相當于寫好了Interface:
!-----------------------------------------------------------------------
Module func
contains
Function getbig(p)
Implicit none
Integer, Pointer :: p(:)
Integer, Pointer :: getbig
Integer n,temp,i
n=size(p,1)
temp=0
do i=1,n
if (temp<p(i)) then
temp=p(i)
getbig=>p(i)
endif
end do
End Function
end module
use func
Implicit none
Integer, target :: a(5)
Integer, Pointer :: p(:)
a=(/1,2,3,4,5/)
p=>a
write (*,*) getbig(p)
stop
End
!-----------------------------------------------------------------------
指針的應(yīng)用:
◆指向多維數(shù)組:
integer, target :: matrix(100:100)
integer, pointer :: p(:,:)
p=>matrix(10:20,10:20)
!-----------------------------------------------------------------------
指向Type類型:
type person
character*20 name
integer number
real old
end type
type(person) :: me,he,temp
type(person),pointer :: pme,phe,ptemp
pme=>me
phe=>he
ptemp=>pme
!-----------------------------------------------------------------------
◆指向Next
module k_module
type :: knoten
integer :: i
type (knoten), pointer :: next
end type knoten
type(knoten) punkt
end k_module
!-----------------------------------------------------------------------
第一行定義一個擴展類型knoten
第二行定義一個編號i,例如 punkt%i
第三行定義一個指針next,類型為knoten,例如:punkt%next指向一個地址。
指針punkt%next還沒有指向的時候,是沒有定義的,也就是說punkt%next%i不存在。
指針punkt%next只能指向一個knoten類型的地址,即變量punkt%next%i與punkt%next%next
例如:
!-----------------------------------------------------------------------
call k_module
implict none
type(knoten), target :: k(3)
tyep(knoten), pointer :: p
integer :: i
p=>k(1) !定義一個計數(shù)指針
k(1)%i=1
k(1)%next=>k(2) !定義k(1)%next指向k(2)
k(2)%i=2
k(1)%next=>k(2)
k(3)%i=3
nullify(k(3)%next) !定義k(3)的指針變量不再有指向!
!連續(xù)輸出的方法:
i=1
do while (.true.)
write (*,*) p%i
if (.not. associated (p%next)) exit
p=>p%next
end do
stop
end
!-----------------------------------------------------------------------
循環(huán)運行過程:
p=>k(1) 輸出p%i 即k(1)%i=1
p%next=k(2)
p%next%next=k(3)
p%next%next%i=k(3)%i=3
i=1, p=>k(1)%next 即k(2) 輸出p%i 即k(2)%i=1
i=2, p=>k(2)%next 即k(3) 輸出p%i 即k(3)%i=1
i=3, exit
數(shù)據(jù)結(jié)構(gòu)為
k(1)=knoten(1,K(2))
k(2)=knoten(1,K(3))
k(3)=knoten(1,null())