返回介绍

4.3.2 派生类型

发布于 2025-03-08 16:28:33 字数 4810 浏览 0 评论 0 收藏 0

为了便于组织数据,F90 允许定义和使用派生数据类型。任何复杂的数据结构,经分析后都可分解为较简单的成员,可用自定义的派生类型反映它。派生数据类型有一个类型名称,它不能和任何内部数据类型或已定义的派生数据类型重名。定义一种派生数据类型后就可以用它来定义变量、命名常量或其它派生类型了。

a) 派生类型定义

定义派生类型时必须使用 TYPE 块。TYPE 块应写在程序的说明部分中,通常写在说明的前部,其一般形式是:

TYPE[,访问属性说明::] 派生类型名

成员 1 类型说明

……

成员 n 类型说明

END TYPE [派生类型名]

其中,TYPE 是关键字,表示派生类型定义开始。访问属性说明关键字是 PUBLIC 或 PRIVATE,默认值是 PUBLIC,即访问方式是共用的。PRIVATE 表示该类型是专用的,这个关键字只有当 TYPE 块写在模块说明部分中时,才允许使用。如果不是在模块内定义的派生类型,不可使用 PRTVATE。派生类型名是任意取的,一旦定义完成,该类型名就成为一个新的类型,就像整型、实型、逻辑型等一样,按一种类型使用。例如可以把各种变量、各种数组说明为这种新的类型,而后按新类型特有法则操作。通常,类型的取名与物理对象的名称一致。例如上述学生结构定义成派生类型可以取派生类型名是 STUDENT。

TYPE 语句下面是结构中各成员的类型说明语句,被说明的类型一般就是 FORTRAN 内部类型(整型、实型等),也允许用一个层次较低的派生类型作为某成员的类型。派生类型的说明语句的一般形式是:TYPE(派生类型名)::变量名。TYPE 块中只有类型说明语句,不允许有可执行的动作语句。派生类型中字符型成员不可取*为长度,必须是确定长度。系统不一定会按定义时的顺序储存各个成员,除非在定义中包含有 SEQUENCE 语句。

例如:对上面的学生记录作派生定义,由于学生结构中有两个成员 CLASS 与 SCORES 本身又是次一层的结构,因此要先对 CLASS 与 SCORES 这两个结构作出派生类型定义。CLASS 下有两个成员:DEPARTMENT(字符型)、MAJOR(字符型)。SCORES 下有三个成员:MATH(整型)、PHYSICS(整型)、ENGLISH(整型)。整个学生结构定义派生类型名为 STUDENT_TYPE。

TYPE CLASS_TYPE

CHARACTER(LEN=50) :: DEPARTMENT, MAJOR

END TYPE CLASS_TYPE

TYPE SCORES_TYPE

INTEGER(1) :: MATH, PHYSICS, ENGLISH

END TYPE SCORES_TYPE

TYPE STUDENT_TYPE

SEQUENCE

INTEGER(4) :: NUMBER

TYPE(CLASS_TYPE) :: CLASS

CHARACTER(LEN=10) :: NAME, ADDRESS

TYPE(SCORES_TYPE) :: SCORES

END TYPE STUDENT_TYPE

TYPE(STUDENT_TYPE),DIMENSION(40):: STUDENT

注意在上面三个定义派生类型 TYPE 语句中,派生类型名取成‘名_TYPE’形式,这是为了加强可读性。特别是当它的成员名与类型名一致时,可以这样区分。当给定属性 DIMENSION(40) 后,STUDENT 即为有 40 个学生的派生型数组,每个学生按顺序有学号、班级(系、专业)、姓名、地址、成绩(数学、物理、英语) 等成员。

b) 缺省初始化

F95 中,允许定义派生数据类型成员时给予初始值,这时就有了缺省初始化,但没有必要为每一个成员指定初始值。它的显式初始化会覆盖缺省初始化。例如:

TYPE REPORT

CHARACTER (LEN=20) REPORT_NAME

INTEGER DAY

CHARACTER (LEN=3) MONTH

INTEGER :: YEAR = 1999 ! 年份这个成员有缺省初始值

END TYPE REPORT

而下面语句中,显式的初始化覆盖了 NOV_REPORT 中的 YEAR 成员。

TYPE(REPORT),PARAMETER :: NOV_REPORT=REPORT("Sales",15,"NOV",2001)

又如,下面用 DATA 语句进行显式初始化:

TYPE EMPLOYEE

INTEGER ID

CHARACTER(LEN=40) NAME

END TYPE EMPLOYEE

TYPE(EMPLOYEE) MAN_NAME,CON_NAME

DATA MAN_NAME/EMPLOYEE(417,'Henry Adams')/

DATA CON_NAME%ID,CON_NAME%NAME /891,"David James"/

c) 结构构造函数

F90 有一种与结构有关的函数,称为结构构造函数,它用来给某结构类型中一个具体的变量赋值。定义了一个派生类型,实际上也同时建立了一个结构构造函数,这个函数名就是派生类型名,函数的自变量就是派生类型内各成员。只要派生类型一建立,就可直接调用这个结构构造函数。如果把实在的各成员值作为实元,与结构构造函数中自变量作哑实结合,其函数值就是被定义成派生类型的一个变量的值,可以直接赋给派生类型中的某一变量名。例如,对下面的派生类型:

TYPE FRIEND_TYPE

CHARACTER(LEN=20) :: NAME

INTEGER :: AGE

END TYPE FRIEND_TYPE

系统中就自动生成一个函数名叫 FRIEND_TYPE 的结构函数,该函数有两个哑元自变量:NAME、AGE。其完整的函数形式为:FRIEND_TYPE(NAME,AGE)。假设变量名 MY_FRIEND 被说明为 FRIEND_TYPE 类型,即程序中有说明语句:

TYPE(FRIEND_TYPE) :: MY_FRIEND, MY_BOY_FRIEND, MY_GIRL_FRIEND

于是可把‘Kong Ming’作为 NAME 的实元,25 作为 AGE 的实元,在程序执行部分中调用结构构造函数,并把函数值赋给变量 WHO,赋值语句为:MY_FRIEND=FRIEND_TYPE(‘Kong Ming’,25)。此时具有 FRIEND_TYPE 类型的变量 MY_FRIEND 就有了 NAME 成员值和 AGE 成员值。

调用结构构造函数作哑实结合时,只要保持类型、个数、位置一致,可以有多种形式的实元与哑元结合。譬如实元可以又是另一低层次结构的结构构造函数,或另一个结构的成员等。如回到前面较复杂的学生结构例中,设已定义派生类型 STUDENT_TYPE,并说明了变量名 ZHANG_FEI 是 STUDENT_TYPE 类型的,而后我们在执行部分中对 ZHANG_FEI 的成员 CLASS 通过如下赋值语句赋值:

ZHANG_FEI%CLASS=CLASS_TYPE(‘22th Department’,‘Applied Physics’)

这里引用 CLASS_TYPE 的结构构造函数,说明变量 ZHANG_FEI 的班级是 22 系应用物理专业,也即 ZHANG_FEI%CLASS 已经有定义。因此接着可以把 ZHANG_FEI%CLASS 作为结构构造函数 STUDENT_TYPE 的实元,把整个函数值赋给变量 ZHANG_FEI:

ZHANG_FEI=STUDENT_TYPE(0022123,ZHANG_FEI%CLASS,&

‘ZHANG_FEI’,‘He Fei’,SCORES_TYPE(82,73,90))

使用结构构造函数可以非常方便地给具有这种结构的变量赋值,如果若干变量形成一个数组,就可打印出一份详细的档案,并可按照需要排序及检索。

d) 应用

例:利用成员特征作排序检索。如果上面 40 个学生姓名和成绩已经读入,要查找名叫张飞的成绩并打印输出,并列出数学成绩在 85 分以上的名单。将前面的派生类型定义简化后为:

PROGRAM STUDENT_IO

TYPE SCORES_TYPE

INTEGER(1) :: MATH, PHYSICS, ENGLISH

END TYPE SCORES_TYPE

TYPE STUDENT_TYPE

CHARACTER(LEN=10) :: NAME

TYPE(SCORES_TYPE) :: SCORES

END TYPE STUDENT_TYPE

TYPE(STUDENT_TYPE),DIMENSION(40):: STUDENT

READ‘(A,3I3)’, STUDENT

DO I=1,40

IF(STUDENT(I)%NAME=‘Zhang Fei’) PRINT *,STUDENT(I)%SCORES

END DO

DO I=1,40

IF(STUDENT(I)%SCORES%MATH>=85) PRINT *,STUDENT(I)%NAME

END DO

END PROGRAM STUDENT_IO

例:建立一个计算机帐户的数据库,根据用户号码查找其帐上余额并显示。 [e_432_01.f90]

例:建立一个学生的数据库,包含有学生姓名和考分的记录。从键盘上输入这些记录,并将它们放入一直接存取的文件中,要求可以显示、增加和修改记录。 [e_432_02.f90]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文