zoukankan      html  css  js  c++  java
  • fortran-目录:

    Fortran 语法备忘录 (中级1)——转载
    2010-03-10 19:12

    转载于http://zhousicheng.googlepages.com/a_014

    目录:目录:
    【主程序】【语句函数】【内在过程】【内部过程】【外部过程】

    【主程序】【语句函数】【内在过程】【内部过程】【外部过程】

    外部函数◆外部子程序◆EXTERNAL属性和哑过程◆INTENT属性◆OPTIONAL属性◆哑元改名◆关键字变元INTRINSIC属性◆类属过程◆过程接口 INTERFACE◆超载操作符◆自定义操作符◆超载赋值号
    【模块】【块数据】【指针】


    • 【主程序】
      !-----------------------------------------------------------------------
      [PROGRAM [程序名]]
      [说明部分]
      [可执行部分]
      [CONTAINS
      内部过程]
      END [PROGRAM [程序名]]
      !-----------------------------------------------------------------------

    • 【语句函数】 f(x)=x**2+1
    • 【内在过程】 max,abs,sin,char。。。。
    • 【内部过程】 Contains
      与宿主程序共享变量名, 外部过程FUNCTION, SUBROUTINE都可以有自己的内部过程。
      通常没有说明语句。
      没有哑元,无哑实结合。
      使用内部过程的规则:在宿主中不要定义子程序名和函数名的类型,也不能指定它们是有EXTERNAL属性。宿主中的变量名和数组名等在内部过程中有效,有相同的数值。但同一名若在内部过程中又进行了类型声明,则此名被视为其过程中的独立变量,无相同的数值。内部过程中也可引用另一内部过程。
      例:
      !-----------------------------------------------------------------------
      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
      !-----------------------------------------------------------------------

    • 【外部过程】
      过程=函数&子程序
      哑元调用方式:传址调用call by adress,即传递4字节的变量的内存地址。
      ◆外部函数
      调用:函数名(实元表) 函数名()
      如果没有结果名,则函数名就是结果名。
      !-----------------------------------------------------------------------
      [前缀] FUNCTION 函数名([哑元列表])[RESULT(结果名)]
      [说明部分]
      [可执行部分]
      [CONTAINS
      内部过程]
      END [FUNCTION 函数名]
      !-----------------------------------------------------------------------


      ◆外部子程序:
      调用:
      CALL 子程序名 [(哑元列表)]
      哑元可以是变量名、数组名、过程名、指针名等均可作为哑元。它们之间用逗号隔开。
      前缀是F90中新增的,它可以是:[类型说明] 或[关键词]。关键词:RECURSIVE(F90),PURE(F95),ELEMENTAL(F95)。RECURSIVE表示过程时可以直接或间接地调用自身,即递归调用,其过程是递归过程。
      !-----------------------------------------------------------------------
      [前缀] SUBROUTINE 子程序名[(哑元列表)]
      [说明部分]
      [可执行部分]
      [CONTAINS
      内部过程]
      END [SUBROUTINE [子程序名]]
      !-----------------------------------------------------------------------


      一个有用的例子:互换数字
      !-----------------------------------------------------------------------
      SUBROUTINE swap(p,q)
      INTEGER :: p,q,r
      r=p;p=q;q=r
      RETURN
      END
      !-----------------------------------------------------------------------


      ◆EXTERNAL属性和哑过程 (哑元为外部过程,即哑过程)
      指定EXTERNAL语句或属性说明实元实际上是外部过程
      类型定义语句: 类型,EXTERNAL :: 外部函数名[,外部函数名]…
      或EXTERNAL语句:EXTERNAL [外部函数名][,子程序名][,块数据名]…
      哑元也可以是一个过程,这时作为哑元的过程称为哑过程。(至少两层调用)
      例如:
      !-----------------------------------------------------------------------
      Programm main
      Real x,y
      External Plus !外部过程名作实元,必须用External说明,或者具有External属性
      x=1.0 ; y=2.0
      Print,* Calculate(x,y,Plus) !调用Calculate函数,实元为外部过程Plus
      End Program main
      Real Function Plus(a,b) !(第二层被调用的外部函数)
      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) !调用自定义的外部函数
      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 指明哑元仅用于向过程提供数据,过程的执行期间哑元不能被重定义或成为未定义的,相联合的实元可以是常数、变量、数组以及它们的算术表达式。
      OUT 指明哑元用于把过程中的数据传回调用过程的程序,与之相结合的实元只允许是变量,不得为常数。
      INOUT 指明哑元既可以用于向过程提供数据,也可用于返回数据,与之相结合的实元只允许是变量。


      ◆OPTIONAL属性可选变元,部分哑元作哑实结合
      内在函数PRESET用来反映它的自变量是否在程序执行部分中出现。PRESET(A)的值是一个逻辑值,以此来构造不同的算法。


      例如,要求编一子程序,既能求四边形同长(A+B+C+D)的值,也能求三角形周长(A+B+C)的值。此时D就是可选择变元,并规定当D不出现时,置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
      !-----------------------------------------------------------------------


      ◆哑元改名
      例如,对于上面求边长的子程序,如调用时欲把哑元名A,B,C,D改为物理意义明确的名称UPPER,DOWN,LEFT,RIGHT,只需在主调程序中写入接口块,在接口块的哑元表中用新的哑元名即可:
      !-----------------------------------------------------------------------
      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
      !-----------------------------------------------------------------------


      ◆关键字变元
      哑实结合:(哑元名=实元表达式)
      例如: CALL TEST(1,10,D=1000,C=100)
      同: CALL TEST(A=1,B=10,D=1000,C=100)
      F90也允许在调用语句中,前面部分实元不用关键字变元,只从某一个变元开始用关键字变元。
      主调程序中如采用关键字变元调用过程,就必须写出被调子程序的接口块。
      !-----------------------------------------------------------------------
      PROGRAM swap_pro !交换大小两个实数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语句或属性说明的实元是外部过程相对应,INTRINSIC语句或属性用来说明实元实际上是内在过程。其一般形式为:
      类型定义语句:类型,INTRINSIC :: 内在函数名[,内在函数名]…
      或INTRINSIC语句:INTRINSIC 内在过程名[,内在过程名]…
      内在过程名必须是内在过程的通用名或专用名。如果是专用名,则可以在其作用范围单元中作为一个过程的实元,但它必须出现在一个INTRINSIC语句中,或被该单元中的一个类型声明语句指明具有INTRINSIC属性。需要注意的是,一个内在过程名只能在INTRINSIC语句中出现一次,并且不能同时出现在INTRINSIC语句和EXTERNAL语句中。
      例:
      !-----------------------------------------------------------------------
      PROGRAM MAIN
      REAL F
      REAL,INTRINSIC :: ALOG !说明Alog是内部函数,可以作实元
      F=CALCULATE(0.0,1.0,ALOG) !使用内在函数ALOG作实元

      END PROGRAM
      !-----------------------------------------------------------------------
      注意这里必须用专用名ALOG,而不能用通用名LOG。


      ◆类属过程
      允许用不同类型的实元与同一个哑元结合,如内在基本函数ABS(X),结合的实元可以是整型、实型与复型。
      例如,要编写求两数之和的类属函数时,分别编写哑元是实型和整型的函数:
      !-----------------------------------------------------------------------
      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
      !现在把这两个函数过程综合成一个类属函数,类属函数名取为MY_SUM,在主调程序应写明如下接口:
      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
      一个内部过程总是由程序单元中的语句来调用的。一般来讲,编译程序知道内部过程的一切情况,如知道该过程是一个函数或子程序、过程名、哑元的名字、变量类型和属性、函数结果的特性等等。这个信息的集合被称为过程的接口(interface)。
      对于内部过程、内在过程和模块,过程接口对编译程序而言是己知的和显式给出的,故称显式接口。
      如在调用一个外部过程或一个哑过程时,编译系统通常不知道该过程的各种情况,这种接口是隐式的。
      用EXTERNAL语句来指明一个外部过程或哑过程,但此语句仅说明每一个外部名是一个外部过程名或哑过程名,并没有指明过程的接口,所以接口仍是隐式的。
      为了全面准确地通知编译系统,在主调程序中有时需要加入接口块,以说明主调程序与被调程序的接口。接口块是F90中引进的新颖程序块,它显式指明了过程接口的机制。通过接口块可用为一个外部过程或哑过程指明一个显式的接口。这比EXTERNAL语句提供了更多的信息,也提高了程序的可读性。
      过程接口确定过程被调用的形式,它由过程的特性、过程名、各哑元的名字和特性以及过程的类属标识符(可以省略)组成,一般它们都被写在一个过程的开头部分。此接口块被放在主调程序的说明部分中,通常还应写在类型说明语句之前,它的内容是被调用的过程中的说明部分,功能是通知编译系统,主调程序调用的过程中各种变元的类型、属性、性质等。
      用法:
      !-----------------------------------------------------------------------
      INTERFACE [类属说明]
      [接口体]…
      [模块过程语句]…
      END INTERFACE [类属说明]
      !-----------------------------------------------------------------------
      其中类属说明的形式为:
      类属名 -> 类属过程
      OPERATOR -> 超载操作符、自定义操作符
      ASSIGNMENT(=) -> 超载赋值号
      接口体的形式为:
      函数语句
      [说明部分]
      函数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
      !-----------------------------------------------------------------------
      凡遇下列情况之一时,主调程序必须有接口块:
      1、如果外部过程具有以下特征:
      过程的哑元有可选择属性。
      过程的哑元是假定形数组、指针变量、目标变量。
      函数过程的结果是数组或指针。
      对于字符型函数过程的结果、其长度不是常数,也非假定长度(*)。
      2、如果调用过程时出现:
      实元是关键字变元。
      用一个类属名调用。
      用超载赋值号(对于子程序)。
      用超载操作符(对于函数)。
      3、如果过程前缀关键词是ELEMENTAL


      ◆超载操作符
      超载操作符的形式仍是系统内部操作符,如+、-、*、/等,但通过编出恰当的过程,可以扩充这些操作符的功能。例如;‘+’本来用于对数值作算术操作,但经恰当的编程后‘+’也可用于字符型操作,这就像车辆超载一样,故称为超载操作符。定义超载操作符,需先编写一个实现此超载(扩充)功能的函数过程,再在主调程序中编写过程的接口,在接口语句后加上超载说明,其一般形式为:
      INTERFACE OPERATOR(被超载使用的操作符号)
      例如:要使‘+’超载能执行如下操作:把两个字符串的最后一个字母接起来。
      !-----------------------------------------------------------------------
      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
      !-----------------------------------------------------------------------
      接口的作用是向编译系统提示,遇到操作符‘+’时,如果操作数不是数值,就不是原来意义的加法,操作含义要到 FUNCTION ADD中找。当主调程序有了上述接口块后,在下面执行部分中执行字符串操作CH1+CH2时,+号作超载用。


      ◆自定义操作符 .klein. .gross. .plus.
      INTERFACE OPERATOR(.plus.) ! .plus. = +
      MODULE PROCEDURE add
      END INTERFACE


      ◆超载赋值号 INTERFACE ASSIGNMENT(=)
      例:编一程序把逻辑量超载赋值给整型变量。先编一个实现这一功能的子程序,
      !-----------------------------------------------------------------------
      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
      再在主程序内编写接口,
      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


    • 【模块】 复制所有语句,共享所有变量
      共享数据的2个方法:一个是哑实结合,一个就是数据共享
      共享方式有:使用COMMON语句和EQUIVALENCE语句(F77),使用模块(F90)。另外,使用INCLUDE复制。
      !-----------------------------------------------------------------------
      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
      !-----------------------------------------------------------------------
  • 相关阅读:
    poj 2763 Housewife Wind
    hdu 3966 Aragorn's Story
    poj 1655 Balancing Act 求树的重心
    有上下界的网络流问题
    URAL 1277 Cops and Thieves 最小割 无向图点带权点连通度
    ZOJ 2532 Internship 网络流求关键边
    ZOJ 2760 How Many Shortest Path 最大流+floyd求最短路
    SGU 438 The Glorious Karlutka River =) 拆点+动态流+最大流
    怎么样仿写已知网址的网页?
    5-10 公路村村通 (30分)
  • 原文地址:https://www.cnblogs.com/guosj/p/3755473.html
Copyright © 2011-2022 走看看