笫11章指针 指针是现代程序设计语言中一个非常重要的概念,它使语言的功能大大加强。FORTRAN90以前的FORTRAN版本,没有指针这种数据类型,FORTRAN90对其作了重大改进,引入了指针的概念。但是值得注意的是,FORTRAN90的指针与C语言中的指针并不相同,因为它并不代表一个变量的地址,而是代表一个变量的别名,实质上它相当于C++里的引用,本章介绍指针的概念与应用。

Slides:



Advertisements
Similar presentations
完美殺人筆記簿 【爸!我受夠了!】 第七組組員: 林正敏 陳筱涵 李蓓宇 許純宜 羅玉芬 謝文軒.
Advertisements

当一切只剩断瓦颓垣的时候,我们只能把记忆 连根拔起。为了重建,必须先要毁灭。 落叶出版社 主编: curtian#
“ 上海市科研计划课题预算编制 ” 网上教程 上海市科委条财处. 经费预算表 表 1 劳务费预算明细表 表 2 购置设备预算明细表 表 3 试制设备预算明细表 表 4 材料费预算明细表 表 5 测试化验与加工费预算明细表 表 6 现有仪器设备使用费预算明细表 小于等于 20 万的项目,表 2 ~表.
用藥常識知多少? 五乙李麗娜 心寶的故事 心寶哪裡錯了? 說一說藥袋上有什麼資訊? 姓名 怎麼用(一天使用幾次? ) 藥的用途對症嗎? 藥品和外觀 副作用 注意事項 保存期限與方法 成藥有沒有衛生署許可證字號.
天水圍的體育設施.
社交礼仪.
学生入党材料写作规范.
損益表 原則: 收益與費用的計算,實際上是在實現或發生時所產生,與現金收付當時無關。
報告者:蕭曄鴻 班級:溫馨甲孝 指導教授:李開濟博士
單元名稱: 健康的兩性交往.
主題─ 悌 授課教師:謝宛琳.
《中国共产党发展党员工作细则》 学习提纲 中共进贤县委组织部 宋 剑
严格发展程序,提高工作能力 黄 玉 2010年9月.
发展党员的流程和要求 党委组织部 萧炽成.
莫让情感之船过早靠岸 兴庆回中 赵莉.
《老年人权益保障》 --以婚姻法.继承法为视角
姓名:劉芷瑄 班級:J201 座號:39號 ISBN:957-33-1963-2
行政公文写作 第七章 2004年8月 行政公文写作.
小微企业融资担保产品介绍 再担保业务二部 贾天
论文撰写的一般格式和要求 孟爱梅.
興華之寶.
第三章 幼儿园课程内容的编制与选择.
第三章  电话、电子通讯   本章重难点:     打电话的方法、         接听电话的方法。
电话联系.
迎宾员礼仪 包头机电工业职业学校管理系 白琳 1.
上課囉 職場甘苦談 小資男孩向錢衝 育碁數位科技 呂宗益/副理.
7步驟, 從窮忙族變新富族 修編配樂.
《社交礼仪分享》 阳晨牧业科技有限公司 市场中心 二O一二年四月十八日.
Chapter 4 流程控制.
会议文书.
如何写入团申请书.
财 务 会 计 第四篇:供应链会计实务 制作人:谌君、熊瑜.
第6章 PLC控制系统设计与应用 教学目的与要求:熟悉相关指令的综合应用,掌握PLC控制系统设计方法,掌握PLC程序编制方法,巩固所学内容。
XX信托 ·天鑫 9号集合资金信托计划 扬州广陵
第11周 工作计划.
Chapter 模組 台灣師範大學數學系 黃聰明.
第五章 数 组 Fortran 90数组的特点: *** 可以逐个元素对数组进行操作,也可以对数组整体、数组段直接进行操作;
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
Linked List Operations
陳維魁 博士 儒林圖書公司 第七章 參數的傳遞 陳維魁 博士 儒林圖書公司.
计算机操作系统 第二章 进程管理 高校教师、高级项目经理 任铄 QQ:
新觀念的 VB6 教本 第七章 讓程式轉彎的控制敘述.
数学3(必修)—— 算 法 ALGORITHM 苏州大学数学科学学院 徐稼红
Chapter 2 Basic Elements of Fortran
丙級電腦軟設-VB程式設計 資料來源:林文恭研究室 整理:張福生.
第4章 常量和变量 常量和变量都是程序中预留的用于保存数据的内存空间。常量的值在程序运行过程中始终不会发生变化。而变量的值在程序的运行过程中是可以变化的。在Fortran语言中,有五种基本的数据类型可供使用。他们分别是整型(INTEGER)、实型(REAL)、复型(COMPLEX)、字符型(CHARACTER)和逻辑型(LOGICAL)。按用途,又可以分数值型、字符型和逻辑型三种。相应的常量和变量也可以分为这三种。本章将按照用途介绍常量和变量的基本概念。
VB程序设计语言 主讲教师:王 杨.
VB程序设计语言 主讲教师:王 杨.
陳維魁 博士 儒林圖書公司 第五章 控制結構 陳維魁 博士 儒林圖書公司.
編譯程式設計 期末專題說明 V1.1 May 2004.
第九章 結 帳 9-1 了解結帳的意義及功能 9-2 了解虛帳戶結清之會計處理 9-3 了解實帳戶結轉的會計處理
Chapter 指標.
第3章 流程控制和逻辑运算.
陳維魁 博士 儒林圖書公司 第三章 變數與繫結 陳維魁 博士 儒林圖書公司.
特定消耗品說明 (指碳粉匣、墨水匣) 國立清華大學 保管組製作.
中国大连高级经理学院博士后入站申请汇报 汇报人:XXX.
第14章 基本数值算法举例 数值计算是Fortran语言的强项,也是Fortran语言发明者的初衷。本节主要介绍在计算机程序设计语言学习中经常遇到的一些基本数值算法。目的在于加深对Fortran语言的理解和分析,解决问题的一般思路,并希望通过这些例程介绍一些代码编写方面的技巧。
內部控制作業之訂定與執行 報告人:許嘉琳 日 期:
單元名稱:結構化程式設計 報告人 劉洲溶.
問題解決與流程圖 高慧君 台北市立南港高中 2006年12月22日.
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
Do While 迴圈 東海大學物理系‧資訊教育 施奇廷.
三 顺序结构程序设计 厦大附中信息技术.
臺中市龍山國小 校園常見瓢蟲辨識   瓢蟲屬於鞘翅目瓢蟲科。目前世界上約有5000多種瓢蟲,台灣地區約有80種以上,其中能捕食有害生物的瓢蟲約七十種之多。瓢蟲因為捕食有害生物為主食,所以又稱為『活農藥』。
程序调试与错误处理.
第三章 流程控制 程序的运行流程 选择结构语句 循环结构语句 主讲:李祥 时间:2015年10月.
Fortran 实用编程 系列视频教程 Fortran Coder 研讨团队
陳維魁 博士 儒林圖書公司 第六章 領域與範圍 陳維魁 博士 儒林圖書公司.
Fortran 实用编程 系列视频教程 Fortran Coder 研讨团队
Presentation transcript:

笫11章指针 指针是现代程序设计语言中一个非常重要的概念,它使语言的功能大大加强。FORTRAN90以前的FORTRAN版本,没有指针这种数据类型,FORTRAN90对其作了重大改进,引入了指针的概念。但是值得注意的是,FORTRAN90的指针与C语言中的指针并不相同,因为它并不代表一个变量的地址,而是代表一个变量的别名,实质上它相当于C++里的引用,本章介绍指针的概念与应用。

11.1 指针的定义与使用 在前面内容中,变量的使用,都是按变量的名字即标识符直接进行的,并且每个变量的名字都是唯一的,是否可以给同一个变量一个不同的名字?FORTRAN90中的指针,正是用来给变量起别名,并且通过后面的章节的学习,我们知道指针能给编程带来诸多的方便。

11.1.1 指针变量的定义格式 指针变量的定义格式为: 类型说明,POINTER:: 指针变量名1,指针变量名2,… 其中: (1)类型说明可以是任何数据类型,如INTEGER、REAL等,它表示该指针所指的目标变量类型。 (2)POINTER为指针定义的关键字,::为作用域符。 (3)指针变量名为标识符,只要符合标示符的命名规则即可。

定义举例 INTEGER,POINTER::A1,A2 此语句定义了两个指针变量A1和A2,它们都指向整型变量。 可以将类型说明与指针说明分开,即先说明变量的类型,然后指定变量为指针。例如 INTEGER A1,A2 POINTER A1,A2 此语句同样定义了整型两个指针变量A1和A2。

11.1.2、指针变量的使用 下面通过一个具体的实例来说明指针变量的使用: 例11.1指针变量示例1 PROGRAM POINTER1 INTEGER,POINTER::P INTEGER,TARGET:: X READ*,X P=>X PRINT*,"X=",X PRINT*,"P=",P END 输入3,程序的输出结果为: X=3

P=3 此例中,先定义了一个指针变量P,然后定义了一个整型变量X,再通过P=>X语句,使P指向X,这时两者实际上是同一个变量,就象一个人除了自己的名字外,还有外号一样。因此,无论输入的是什么整数,两者显示的结果一样。

下面再看一个例子 例11.2 PROGRAM POINTER3   INTEGER, POINTER::P1,P2,P3,P4 INTEGER,TARGET:: X1,X2 INTEGER X,S1,S2,S3,S4,S5 READ*,X1,X2 X=X1*X2 P1=>X1 P2=>X2 P3=>X1 P4=>P1 S1=P1*P2 S2=P3*P2 S3=P1*X2 S4=P3*X2 S5=P4*X2 PRINT*,"X=",X

PRINT*,"S1=",S1 PRINT*,"S2=",S2 PRINT*,"S3=",S3 PRINT*,"S4=",S4 PRINT*,"S5=",S5 END 输入:3 4后,输出结果为: X=12 S1=12 S2=12 S3=12 S4=12 S5=12

在该例中,定义了四个指针变量:P1,P2,P3,P4,通过P1=>X1,使P1指向X1,P2=>X2使P2指向X2,再通过P3=>X1和P4=>P1,使P3和P4都指向X1,因此,X、S1、S2、S3、S4、S5计算结果一样,实际上都是X1+X2。

(1) 指针变量赋值格式为: 指针变量=>目标变量或者另一指针变量。 (2) 多个指针变量可以指向同一目标变量,但是,一个指针变量只能指向一个目标变量,不能同时指向多个目标变量。 (3) 指针变量与目标变量的类型应当严格一致,不存在所谓的兼容情况,即,整型指针变量所指的只能是整型变量,而不能是实型变量等。 (4) 指针变量的本质是所指变量的别名,两者在编译时会当作同一变量,指针变量的引用实际上是对目标变量的引用。

(5) 在程序中,指针变量通常有以下三种状态: ① 未定义状态,在程序开始时,所有的指针都处于这种状态。 ② 空状态,此时指针还没有作为任何对象的别名。 在程序中,有时为了方便起见,可以让指针指向一个空对象。 INTEGER,POINTER::P=>NULL() 或者 INTEGER,POINTER::P NULLIFY(p) ③ 关联状态,此时,指针已经作为其他对象的别名。 值得注意的是只有在第三种状态时,指针才能参与运算,否则,或者编译出错,或者非法操作。

指针状态检测函数 Fortran提供ASSOCIATED 函数用来检查指针是否已经设置指向。 ASOCIATED(POINTER,[TARGET]) 返回值为逻辑量,如果只放入第一个指针参数,会检查这个指针是否已经赋好“方向”。如果放入两个变量,则会检查第一个指针变量时候指向第二个变量。

11.2 动态变量 前面已介绍过,变量的本质是一个内存单元,该单元一般是在变量定义时,就已经分配的,以后在程序运行期间不再改变,但是通过指针,可以先得到变量名,然后再利用ALLOCATE(P)函数可以动态分配其空间,其中P为指针变量。下面通过一个具体实例,来了解其使用方法。

例11.3 PROGRAM POINTER3 INTEGER,POINTER::P ALLOCATE(P) P=4   INTEGER,POINTER::P ALLOCATE(P) P=4 PRINT*,"P=",P END 输出结果为:P=4

在该例中,先定义了一个指针变量P,然后利用ALLOCATE(P)函数,为P分配空间,再给P赋值。 一般而言,ALLOCATE函数总是与DEALLOCATE函数配套使用,因为用动态分配函数为指针分配存储单元时,容易产生指针悬挂问题。所谓指针悬挂问题是指:当一个对象被释放,而释放时没有直接涉及作为其别名的指针时,就产生指针悬挂,这时,指针所占据的内存单元始终得不到释放,使用DEALLOCATE函数就可释放存储单元。 注意,对于普通变量,由于其内存空间自动回收,不存在上述问题。

例11.4,ALLOCATE和DEALLOCATE函数的用法,程序如下:  PROGRAM POINTER4  INTEGER,POINTER::P1,P2 INTEGER S ALLOCATE(P1,P2) READ*,P1,P2 S=P1+P2 DEALLOCATE(P1,P2) PRINT*,"S=",S END 输入5 6 输出S=11

该程序中,先定义了两个指针变量P1、P2,然后用ALLOCATE函数为其分配空间,再通过键盘输入其值,运算完毕,用DEALLOCATE函数,释放其空间。 必须注意的是:DELLOCATE函数所释放的空间,一定得是不再使用的动态空间,空间一旦被释放,就不得再使用,否则将产生非法操作,如上面程序中,如果将DEALLOCATE(P1,P2)语句提前,就会产生非法操作。 注意,即使用DEALLOCATE(P)函数,释放P所指的空间,也可能产生悬挂指针问题,下面我们看一个可能产生悬挂指针的例子。

REAL, POINTER :: P1, P2 ALLOCATE( P1 ) P1 = 13 P2 => P1 这时,P1,P2指向同一个存储单元,如果程序中在P1使用完后,用DEALLOCATE(P1)语句,这时,P2指针就被悬挂起来。 注意,ALLOCATE和DEALLOCATE还有可选用说明符STAT: ALLOCATE(P,STAT=IERR) DEALLOCATE(P,STAT=IERR) 其中IERR用于标识内存分配、解除是否成功,成功则IERR的值为0。

11.3 指针与数组 利用指针来指向一个数组,能动态地分配数组空间,给编程带来极大的方便,因为FORTRAN语言的特点是,如果要使用数组,则必须在可执行语句之前先定义它,而数组普通定义的方法是首先必须指定数组的维界,确定数组存储空间的大小,但在编写程序时,开始往往难以确定所用数组的大小,显然,所定义的数组空间的大小不能小于所需的空间,解决的办法是将数组定义得足够大,但这样浪费了内存空间,而通过动态定义,可以根据当时使用空间的大小来生成空间,使问题得到很好的解决。下面讨论指针与数组关系的建立、动态空间的生成等。

11.3.1 指针数组的定义 指针数组定义格式为: 类型说明,DIMENSION(: … :),POINTER::指针名 其中:类型说明可以为各种数据类型,如INTEGER、REAL等;DIMENSION(: … :)是数组的动态说明标识,即不指定数组下标界限,“:”个数=数组维数。POINTER为指针说明标识。例如 REAL, DIMENSION(:), POINTER :: X ALLOCATE(X(20)) 第一个语句声明了一个可以指向一维整型数组的指针X,第二个语句为该数组分配了20个单位的存储空间。

11.3.2 指针数组应用举例 下面看一个例子 例11.5 输入任意两个数,将它们及四则运算结果存储起来后,输出。 分析:此例中,可以利用指针,定义一个动态数组X,用来存放输入的数据和计算的结果,该数组的空间大小可以根据要存储的数据个数动态分配,程序如下:

REAL,DIMENSION(:),POINTER::X READ*,A,B C=A+B D=A-B E=A*B IF(B.NE.0)THEN F=A/B ELSE F=0 ENDIF

ALLOCATE(X(6)) X(1)=A X(2)=B X(3)=C X(4)=D X(5)=E X(6)=F WRITE(*,100)X 100 FORMAT(1X,3F8.2) DEALLOCATE(X) END

输入3 6,输出 3.00 6.00 9.00 -3.00 18.00 0.50

11.4 指针与函数

指针类似于可分配数组,允许动态访问和处理数据。指针在指向具体内存前没有初始化的地址空间,也不能被引用。当给它指定目标或分配内存后才和内存相联系。在程序执行过程中,指针的目标是可以改变的。

11.5 指针与链表 指针用途之一是使得数据在计算机中可以按链接方式存储,而链接存储中,最简单是链表。下面介绍关于链表的一些基本知识。 11.5 指针与链表 指针用途之一是使得数据在计算机中可以按链接方式存储,而链接存储中,最简单是链表。下面介绍关于链表的一些基本知识。 顺序存储和链接存储是数据的两种最基本的存储结构。在顺序存储中,每个存储结点只含有存储元素本身的信息,元素之间的逻辑关系是通过数组下标位置简单计算出来的。如在顺序表中,若一个元素存储在对应的数组中的下标位置为I,则它的前一个元素在对应的数组中的下标是I-1,它的后一个元素是数组中下标为I+1的元素。顺序存储最大的缺点是不利于数据的动态变化,如向顺序表中插入或删除一个元素时,需要大量移动数据,处理效率很低。在链式存储中,每一个结点除了存储自己的信息以外,还保留下一个值,用来访问下一个变量,这个值称为指针,下面介绍如何使用链表。

10.5.1 结点的定义 结点是存放数据的基本单位,最简单的结点是普通数组的元素,如若有以下定义:INTEGER A(10) 则象A(1) 、A(2)、 A(3)、 A(4) … 等,可以看作结点。 复杂的结点包含多种类型的数据,一般定义为一个结构体,下面定义一个链表结点的结构体:

TYPE NODE INTEGER VALUE TYPE (NODE), POINTER :: NEXT END TYPE NODE 该结点包含两项,一项是数据本身,即INTEGER VALUE,另外一项是一个指向下一个结点的指针NEXT,通过TYPE (NODE), POINTER :: NEXT语句定义,该结点可以用图10.3表示:

TYPE NODE INTEGER VALUE TYPE (NODE), POINTER :: NEXT END TYPE NODE 该结点包含两项,一项是数据本身,即INTEGER VALUE,另外一项是一个指向下一个结点的指针NEXT,通过TYPE (NODE), POINTER :: NEXT语句定义,该结点可以用图10.3表示:

VALUE NEXT   图11.3

下面再看一个结构体定义的例子。 TYPE STUDENTNODE CHARACTER (15)NAME INTEGER NUM LOGICAL SEX CHARACTER (30)ADDRESS TYPE (STUDENTNODE),POINTER::NEXT END TYPE

结点结构体表示如图11.4: 图10.4 结点示意图

11.4.2 链表的基本操作 链表的基本操作包括建表、插入、删除、查找、更新、遍历等,这里介绍建表、遍历、插入、删除等操作,其余操作将在下一节综合实例里介绍。 1. 链表的建立 例11.6 建立一个链表,并输出建表后的结果。 为了便于理解,假设链表结点仅包含一个数据项和一个指针项。 程序如下:

TYPE NODE INTEGER VALUE TYPE (NODE), POINTER :: NEXT END TYPE NODE !链表的建立,规定以0作为链表建立结束标志。 TYPE (NODE), POINTER :: CURRENT, L INTEGER NUM READ*,NUM NULLIFY( L ) ALLOCATE( CURRENT ) CURRENT % VALUE = NUM L => CURRENT DO WHILE (NUM /= 0)

READ*, NUM IF (NUM /= 0) THEN ALLOCATE( CURRENT ) CURRENT % VALUE = NUM CURRENT % NEXT => L L => CURRENT END IF END DO

!链表的输出过程。 CURRENT => L PRINT*, CURRENT % VALUE   !链表的输出过程。 CURRENT => L PRINT*, CURRENT % VALUE CURRENT => CURRENT % NEXT DO WHILE (ASSOCIATED(CURRENT)) PRINT *, CURRENT % VALUE NEXT NODE END DO END 输入:1 2 3 4 5 输出:5 4 3 2 1

必须注意的是:链表有一个表头和一个表尾,由于FORTRAN语言中指针实际上就是一个别名,不同于C语言中的指针(C中的指针代表内存地址),因此没有明确的空指针的概念,链表的访问方式只能从最后一个结点开始,到第一个结点,通过检查链表是否再被连接作为结束标识,例11.6所建链表过程如图11.5所识。

例11.7 建立有关链表的的模板函数,其中包含链表的删除、插入、输出等函数,程序如下: !模板函数的说明 MODULE MODLINK   IMPLICIT NONE !结点定义 PRIVATE NODE TYPE NODE INTEGER VALUE TYPE (NODE), POINTER :: NEXT END TYPE NODE

!定义链表头指针 TYPE LIST PRIVATE TYPE (NODE), POINTER :: END END TYPE LIST !模板函数所包含的内容 CONTAINS   !删除函数DISPOSE( L ),用于清空链表。 SUBROUTINE DISPOSE( L ) TYPE (NODE), POINTER :: CURRENT TYPE (LIST) L

CURRENT => L % END DO WHILE (ASSOCIATED(L % END)) L % END => CURRENT % NEXT PRINT*, CURRENT % VALUE, ' IS ABOUT TO GO' DEALLOCATE( CURRENT ) END DO END SUBROUTINE DISPOSE

!插入函数INSERT,通过插入结点建立链表 SUBROUTINE INSERT( L, NUM ) TYPE (NODE), POINTER :: CURRENT TYPE (LIST) L INTEGER NUM ALLOCATE( CURRENT ) CURRENT % VALUE = NUM CURRENT % NEXT => L % END L % END => CURRENT END SUBROUTINE INSERT

!遍历函数PRINTLIST,用来访问链表各结点,并输出结点的值 SUBROUTINE PRINTLIST( L )   !遍历函数PRINTLIST,用来访问链表各结点,并输出结点的值 SUBROUTINE PRINTLIST( L ) TYPE (NODE), POINTER :: CURRENT TYPE (LIST) L PRINT*, 'FROM THE END:' CURRENT => L % END ! ALIAS OF LAST NODE DO WHILE (ASSOCIATED(CURRENT)) PRINT *, CURRENT % VALUE CURRENT => CURRENT % NEXT END DO

END SUBROUTINE PRINTLIST   !初始化链表,使表头指针空 SUBROUTINE SETUP( L ) TYPE (LIST) L NULLIFY( L % END ) END SUBROUTINE SETUP END MODULE MODLINK

!主函数部分,根据要求调用前面的函数。 PROGRAM TESTLIST USE MODLINK ! LINKED LIST IMPLEMENTATION IMPLICIT NONE TYPE (LIST) L INTEGER :: NUM = 1   CALL SETUP( L ) DO WHILE (NUM /= 0) READ*, NUM IF (NUM /= 0) THEN CALL INSERT( L, NUM ) END IF END DO CALL PRINTLIST( L ) CALL DISPOSE( L ) END PROGRAM TESTLIST

输入1 2 3 4 5 0 输出5 4 3 2 1 5将被删除 4将被删除 3将被删除 2将被删除 1将被删除。

11.5 综合实例 用链表完成学生情况的管理,已知学生包含姓名,学号,和一门成绩等,其中学号作为关键字。完成链表的建立,和按关键字的排序,插入,查找,删除等操作。 1 定义结点 定义带指针的存放学生记录的结点如下: TYPE NODE CHARACTER(15)NAME INTEGER MARK REAL GRADE TYPE (NODE), POINTER :: NEXT END TYPE NODE

2 定义链表的头指针: TYPE LIST PRIVATE TYPE (NODE), POINTER :: END END TYPE LIST 必须注意,放在模板函数中的链表必须为PRIVATE类型。 3 链表头指针的初始化 SUBROUTINE SETUP( L ) TYPE (LIST) L NULLIFY( L % END ) ! LIST IS EMPTY AT FIRST END SUBROUTINE SETUP 初始化就是将头指针清空,其主要目的是为了在链表的逆序访问中知道链表结点是否访问完毕。

4 链表建立 建立方式用后插方式,即不断在表头结点后面加入新结点。 SUBROUTINE INSERT( L, NAME1,MARK1,GRADE1) TYPE (NODE), POINTER :: CURRENT TYPE (LIST) L CHARACTER(15)NAME1 INTEGER MARK1 REAL GRADE1 ALLOCATE(CURRENT) !为CURRENT指针分配空间和数据,生成结点。 CURRENT%NAME=NAME1 CURRENT%MARK=MARK1 CURRENT%GRADE=GRADE1 CURRENT%NEXT =>L%END !将CURRENT指针生成的结点连接到链表上。 L%END => CURRENT !链表末尾指针后移,为连接新结点做准备。 END SUBROUTINE INSERT

5 链表删除 删除过程为:先定义指针保留待删指针及相关的数据,然后删除待删指针,再输出删除的数据并移动指针保留指针,为删除下一结点作准备。 SUBROUTINE DISPOSE( L ) TYPE (NODE), POINTER :: CURRENT TYPE (LIST) L CURRENT => L % END !从最后一个结点开始删除,用 CURRENT保留待删指针即L链表的END指针。 DO WHILE (ASSOCIATED(L % END)) !注意循环进行条件是链表继续相连,通过ASSOCIATED函数来判断。 L % END => CURRENT % NEXT ! END指针前移。 PRINT*, CURRENT % NAME ! 输出相关的数据。 PRINT*, CURRENT % MARK PRINT*, CURRENT % GRADE DEALLOCATE( CURRENT ) ! 删除CURRENT指针,即删除结点。 CURRENT => L % END !CURRENT 指针保留下一个待删结点的指针。 END DO END SUBROUTINE DISPOSE

6 数据记录的查找 查找是以一个关键字为基础进行的,这里用MARK作关键字进行查找,程序如下 SUBROUTINE FIND(L,KEY) TYPE (NODE), POINTER :: CURRENT TYPE (LIST)L INTEGER KEY PRINT*, "请输入待查找的关键字KEY" READ*,KEY CURRENT => L % END ! 从最后一个结点开始。

DO WHILE (ASSOCIATED(CURRENT%NEXT)) !注意循环只能进行到链表头的前一个结点,否则将产生非法操作。 IF(CURRENT%MARK.EQ.KEY)THEN ! 一旦找到记录,则将结果输出,并退出循环。 PRINT*,’与’,KEY,’相对应的记录如下:’ PRINT *,CURRENT %NAME,CURRENT %MARK,CURRENT %GRADE GOTO 100 ELSE CURRENT => CURRENT % NEXT ! 查找下一个记录。 ENDIF END DO PRINT*,'没有该记录' !循环结束还没有找到该记录的话,说明该记录不存在。 100 CONTINUE END SUBROUTINE FIND

7 数据更新 数据更新是根据给定的关键字查找到相应的记录后,再将相关项更新。 SUBROUTINE UPDATA(L,KEY) TYPE (NODE), POINTER :: CURRENT TYPE (LIST)L CHARACTER(15)NEWNAME INTEGER KEY,NEWGRADE PRINT*, "请输入待更新项的关键字KEY" READ*,KEY PRINT*, "请输入待更新的其它项" READ*,NEWNAME,NEWGRADE CURRENT => L % END ! 从链表末尾开始

DO WHILE (ASSOCIATED(CURRENT%NEXT)) IF(CURRENT%MARK.EQ.KEY)THEN CURRENT %NAME=NEWNAME CURRENT %GRADE=NEWGRADE GOTO 100 ELSE CURRENT => CURRENT % NEXT !查找下一个结点。 ENDIF END DO PRINT*,'该项不存在,无法更新' 100 CONTINUE END SUBROUTINE UPDATA

8 链表输出 程序如下: SUBROUTINE PRINTLIST( L ) TYPE (NODE), POINTER :: CURRENT TYPE (LIST)L PRINT*, 'FROM THE END:' CURRENT => L % END DO WHILE (ASSOCIATED(CURRENT)) PRINT *,CURRENT %NAME,CURRENT %MARK,CURRENT %GRADE CURRENT => CURRENT % NEXT END DO