• 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
      !-----------------------------------------------------------------------
  • 相关阅读:
    JavaScript对象编程-第3章
    JavaScript对象编程-第3章
    JavaScript基础-第2章
    JavaScript基础-第2章
    JavaScript基础-第2章
    第十八节:详解Java抽象类和接口的区别
    第十八节:详解Java抽象类和接口的区别
    第十八节:详解Java抽象类和接口的区别
    JavaScript概述-第1章
    JavaScript概述-第1章
  • 原文地址:https://www.cnblogs.com/guosj/p/3755473.html
Copyright © 2020-2023  润新知