第7章 过程与函数课件.ppt
《第7章 过程与函数课件.ppt》由会员分享,可在线阅读,更多相关《第7章 过程与函数课件.ppt(127页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、目录大纲第七章 过程与函数7.1 过程 7.1.1 事件过程的创建与调用 7.1.2 通用过程7.2 函数 7.2.1 函数的定义 7.2.2 函数的应用举例7.3 参数传递 7.3.1 变量参数 7.3.2 值参数和常量参数 7.3.3 默认参数7.4 子程序的嵌套与递归 7.4.1 子程序的嵌套 7.4.2 子程序的递归7.5 变量的作用域 7.5.1 公有变量和私有变量 7.5.2 全局变量和局部变量7.6 小结 过程(procedure)与函数(function)是实现面向对象编程思想的重要手段。在Delphi中将各个功能模块做成函数或者过程的形式,供程序不同位置的调用,被调用的函数和
2、过程也成为子程序。使用函数和过程不仅可以将一个大的、复杂的问题简单化,而且还可以使程序更加清晰、条理。 过程与函数的区别在于过程没有返回值,而函数有返回值。一般来说定义过程的目的是为了实现某个功能、执行某个操作,而定义函数的目的在于计算得到某个值。7.1 过程 在Delphi中过程分为系统标准过程和自定义过程。系统标准过程是系统内部定义的,无需定义即可直接调用,如第二章所讲的过程EncodeDate过程,用户无需定义它,即可直接调用实现将年、月、日合并成为日期类型的功能。自定义过程也分为两类,即事件过程和通用过程。 事件过程的执行有两种方式,一种是事件驱动,即一个事件发生了,系统自动执行相应的
3、事件过程,还有一种就是调用并执行事件过程。事件过程与对象有关,是Delphi应用程序中最重要的过程。 通用过程不依附于对象,通用过程一般用来执行某些操作,完成某个功能。有些功能代码在程序的多处出现,我们把它做成过程,在多处调用它,这样可以使得程序清晰、简洁,避免书写重复的代码,这就是我们设计通用过程的理由。为了加深对过程以及过程调用的理解,我们需要重新回顾一下事件过程的定义和调用。7.1.1 事件过程的创建与调用 在对象监视器中选择某个对象(或者在窗体中单击该对象),然后在对象监视器的“Event”页中选择相应的事件并双击右边的空白区域,Delphi将自动产生一个默认的事件过程。事件过程的名称
4、是对象名加上事件类型名,如Button1的OnClick事件对应的事件过程就是ButtonClick。 当一个事件发生后,Delphi会自动执行相应的事件过程。当然,一个事件过程也可以被多个事件甚至多个对象共享。方法是,首先为某个事件创建事件过程,然后在创建其它事件的事件过程时,从事件名称右边的下拉组合框中选择已经建立的事件过程名称即可。 共享事件的好处是,当共享事件过程的多个事件中任何一个事件发生时都会执行事件过程。有时候很多相似组件共享事件过程可以减少代码的编写。 【例7-1】在窗体上添加组件Image1Image9共9个Image组件,添加Shape组件若干,用于做Image组件的边框。
5、设计界面如图7-1所示。 本程序是两人对弈,双方在9格的棋盘上先后布棋,单击Image在Image上显示不同的图片(圆或者叉),哪方的三个图片先成一条直线,哪方获胜。 图 7-1 程序界面 步骤如下: (1)将Image1Image9的tag属性分别设置为19。 (2)定义全局变量: n:integer; flag:array1.9of integer; 说明: n用于控制步数,奇数和偶数步分别布“叉”棋和“圆”棋。 Flag数组用于判断某个位置的棋的性质: flagx= -1:表示x位置没有布棋; flagx=0:表示x位置布“圆”棋; flagx=1:表示x位置布“叉”棋。 (3)在TFo
6、rm1.FormCreate事件过程中将所有位置的棋子置为没有布棋(flagi:=-1,I从1到9),将n置初值为0,以后每布一颗棋子n就加1。代码如下: procedure TForm1.FormCreate(Sender: TObject); var i:integer; begin n:=0; /还没有布棋子 for i:=1 to 9 do flagi:=-1; /9个Image均没有布棋子 end; (4)在对象监视器中选定9个Image组件,在Event中选择OnClick事件并双击空白区域,编写如下代码: procedure TForm1.Image9Click(Sender:
7、TObject); begin if (flag(sender as timage).Tag=-1) then /如果该位置没有布棋子 begin n:=n+1; if n mod 2=0 then /偶数布“圆”棋子 begin (sender as timage).picture.loadfromfile(yuan.bmp); flag(sender as timage).Tag:=0; /布子后,做上标记 end else /奇数布“叉”棋子 begin (sender as timage).picture.loadfromfile(cha.bmp) ; flag(sender as t
8、image).Tag:=1; /布子后,做标记 end; end; /省略判断胜负的代码 end;(5)运行程序,界面如图7-2所示。 图 7-2 程序运行结果 说明: (1)本程序9个Image组件的OnClick事件都共用同一个事件过程,这样显然节省代码编写工作量。 (2)我们容易知道本程序中被单击的组件表示为(sender as timage),因此可以很方便地为它设置picture属性。 (3)全局变量n用于控制布棋的奇偶步数,根据n是否能被2整除可知目前应该布 “叉”棋还是布“圆”棋。 (4)tag的作用有两个。一是用于区分不同位置的Image组件,这样可以方便设置该位置的棋子属性(
9、是否有棋,有什么棋);二是用于判断胜负,例如:flag(sender as timage).Tag(tag为1、2、3的时候)的值都是0,显然说明“圆”棋获胜等等。请读者自己完成判断获胜的代码。 (5)上面是9个组件共用一个事件过程。当然,也可以只为Image9编写过程TForm1.Image9Click。而在Image1Image8的事件过程中调用TForm1.Image9Click事件过程。例如: procedure TForm1.Image1Click(Sender: TObject); / Image2 Image8类似 begin Form1.Image9Click(Sender)
10、end; 还可以写成: procedure TForm1.Image1Click(Sender: TObject); begin Form1.Image9Click(form1.Image1) end; 通过本例,读者应该对事件过程的创建与调用有一个较深的认识。7.1.2 通用过程 通用过程要遵循先定义后使用的原则,只用经过定义的过程才能够被程序调用,过程是没有返回值的,因此过程的调用就是一个独立执行的语句。 1通用过程的定义 通用过程的定义语法形式为: Procedure (); 局部声明; begin ; end; 的格式为: Const | Var :类型 说明: (1)保留字Proce
11、dure是定义通用过程的首部,过程名遵循标识符的命名规则。 (2)由若干个形式参数组成,形式参数的类型和个数都必须给定,同类型的形式参数之间用逗号隔开,不同类型的形式参数之间用分号隔开,如果没有形式参数,则括号可省略。例如: m,n:integer;var gys:integer (3)局部声明部分可以声明局部变量、常量、类型等等。 (4)程序体以begin开始,以end结束,end之后是分号。 2通用过程的调用 程序执行某个过程称之为调用,调用的格式为: 过程名(实参表); 说明: (1)实参表中的参数的个数和类型必须和形参一致,实参是按照在参数表中的先后顺序将参数值依次传递给形参的。 (2
12、)如果形参用前冠以var,则相应的实参必须是变量,否则只需要是同类型的表达式即可。 3通用过程举例 【例7-2】编写一个过程,输出m行“*”号,要求第一行输出1个“*”号,以后每行比上一行多出一个“*”,要求使用控制台应用程序。 设计步骤如下: (1)选择“File | New | Other”出现新建项目对话框,在新建项目对话框中选择“Console Applicaion”,出现代码编辑器。 (2)在代码编辑器中输入程序,如下: program Project1; $APPTYPE CONSOLE uses SysUtils; var n:integer; procedure prin(m:
13、integer); var i,j:integer; begin for i:=1 to m do begin for j:=1 to i do write(*); writeln; end; end; begin write(输入行数:); readln(n); prin(n); readln; end. (3)运行程序,输入行数6,结果如图7-3所示。 图 7-3 程序运行结果 说明: (1)本程序定义了变量n,在主程序和过程里面都是有效的,定义了i,j仅在过程中有效,是局部变量。 (2)形参m是整型,实参n也应该是整型。 【例7-3】编写通用过程,用于求两个数或者三个数的最大公约数。界面
14、如图7-4所示。 分析:由于求公约数在多处出现,因此最好把它定义为子程序,以便在多处调用,鉴于目前读者只学了过程,所以本例编写通用过程来解决问题。 图 7-4 求公约数界面图 步骤如下: (1)求两个数m和n的最大公约数有一种方法将做碾转相除法,即:求m和n的最大公约数就是求n和m mod n的最大公约数,这样一来问题就变成了求n和m mod n的最大公约数了。将n看成新的m,m mod n看成新的n继续使用碾转相除法直到n为0,此时的m就是所求的最大公约数。根据分析过程gys定义如下: procedure gys(m,n:integer;var result:integer); begin
15、repeat result:=m; m:=n; n:=result mod n; until n=0; result:=m; end; 说明:形式参数result必须定义为变量参数,以便将结果回传给实际参数,这点将在后面的章节中仔细讲解。 (2)编写Button1的OnClick事件过程如下: procedure TForm1.Button1Click(Sender: TObject); var result1:integer; begin gys(6,9,result1); panel2.Caption:=最大公约数为:+inttostr(result1); / Panel2是小面板 end
16、; (3)编写Button2的OnClick事件过程如下: procedure TForm1.Button2Click(Sender: TObject); var result1:integer; begin gys(12,16,result1); panel2.Caption:=最大公约数为:+inttostr(result1); end; (4)编写Button3的OnClick事件过程如下: procedure TForm1.Button3Click(Sender: TObject); var result1,result2:integer; begin gys(8,12,result1
17、); /带回的result1为8和12的最大公约数 gys(result1,18,result2); /求result1和18的最大公约数,结果由result2带回 panel2.Caption:=最大公约数为:+inttostr(result2); end;(5)运行程序,结果如图7-5所示。 图 7-5 求最大公约数 说明: 【例 7-2】的过程用于控制台应用程序,而【例7-3】的过程却用于 Windows 应用程序。另外【例 7-3】中的过程返回(或者带回)一个结果, 【例 7-2】却进行某种操作。因此活用 Delphi 过程将会为程序增色不少。 7.2 函数 和过程一样函数也是子程序的
18、一种形式,函数与过程的区别在于函数有返回值,过程没有返回值。Delphi中的函数同样分为标准函数和自定义函数,标准函数如sin,cos、exp、datetostr等,标准函数无需定义,直接调用即可。本节讲述自定义函数,自定义函数要先定义,后调用,调用的方法和标准函数一样。7.2.1 函数的定义 自定义函数要遵循先定义后使用的原则,只用经过定义的函数才能够被程序调用,函数定义的格式是: Function ():; 局部声明; begin ; end; 的格式为: Const | Var :类型 说明: (1)保留字Function是定义函数的首部,函数名遵循标识符的命名规则。 (2)由若干个形式
19、参数组成,形式参数的类型和个数都必须给定,同类型的形式参数之间用逗号隔开,不同类型的形式参数之间用分号隔开,如果没有形式参数,则括号可省略。例如: m,n:integer;var gys:integer (3)局部声明部分可以声明局部变量、常量、类型等等。 (4)程序体以begin开始,以end结束,end之后是分号 (5)是函数返回值的类型,函数是有返回值的。函数的返回值是通过函数名带回的,因此,在函数定义部分需要给函数名赋值,如果在函数体中不给函数名赋值,则函数的返回值就是默认值,数值型的默认值是0,布尔类型就是false,字符类型就是空字符等等。 【例7-4】编写一个自定义函数,用于求整
20、数n的阶乘。 function fac(n:integer):int64; /返回值定义为integer容易溢出 var m:int64;i:integer; begin m:=1; for i:=1 to n do m:=m*i; fac:=m; end;7.2.2 函数的应用举例 【例7-5】求100以内的素数之和。 分析:因为本程序需要多处求素数,因此可以考虑定义一个函数用于判断某个数是否为素数。这个函数是布尔类型,返回值为true表示这个数是素数,返回值为false表示这个数不是素数。 步骤如下: (1)设计界面如图7-6所示。 (2)设置函数如下: function prime(n:
21、integer):boolean; 图 7-6 程序界面 var i:integer; begin prime:=true; for i:=2 to trunc(sqrt(n) do if n mod i=0 then prime:=false; end; 说明:首先假设n是素数,令prime:=true,然后在2 之间寻找n的因子,如果找到n的因子则前面的假设是错误的,重新令prime:=false。如果找不到任何因子则n是素数,此时prime仍然保持为初始假设的true值。 (3)编写BitBtn1的事件过程,如下: procedure TForm1.BitBtn1Click(Sender
22、: TObject); var s,i:integer; begin s:=0; for i:=2 to 100 do if prime(i) then s:=s+i; panel2.Caption:=100以内素数之和为+inttostr(s); end;(4)程序运行,界面如图7-7所示。 图 7-7 程序运行结果 【例7-6】求两个数的最大公约数和最小公倍数。 分析:求两个数的最大公约数可以使用碾转相除法,而最小公倍数和最大公约数有这样的数学关系,即:m和n的最小公倍数乘以它们的最大公约数刚好等于m和n的乘积。因此,只要求出最大公约数,就可以求出最小公倍数。因为二者的特殊的数学关系,本例
23、将求最大公约数和最小公倍数定义为一个函数。 设计步骤如下: (1)设计界面如图7-8所示。设计界面如图7-8所示。 图 7-8 求公约数公倍数界面 (2)编写函数的代码如下: function divmul(m,n,flag:integer):integer; var t,a,b:integer; begin a:=m;b:=n; /在m和n值改变之前先将原值保留到a和b中以备以后使用 repeat t:=m; m:=n; n:=t mod n; until n=0; if flag=1 then divmul:=m /最大公约数 else divmul:=a*b div m; /最小公倍数
24、end; 说明: 由于求m和n的最小公倍数需要使用到最大公约数和m和n,所以先将m和n的值先保留到a和b中,以便在求最小公倍数的过程中使用。 本自定义函数的参数中巧妙地定义了一个flag,flag值为1就是求最大公约数的标志,flag值为其它值表示求最小公倍数。 (3)编写Button1的事件过程,如下: procedure TForm1.Button1Click(Sender: TObject); var m,n:integer; begin m:=strtoint(edit1.Text); n:=strtoint(edit2.Text); edit3.Text:=inttostr(divm
25、ul(m,n,1); /edit3中是最大公约数 edit4.Text:=inttostr(divmul(m,n,0); /edit4 中是最小公倍数 end;(4)运行程序,结果如图7-9所示。 图 7-9 程序运行结果 说明: (1)【例7-5】巧妙地将函数结果定义为布尔类型,然后在程序中根据prime(i)的值来决定是否加到s中。 (2)【例7-6】使用到参数flag,根据参数flag的值的不同,函数返回不同的值,这也是程序的巧妙之处。这两个例题各有千秋,读者应该举一反三,灵活运用。 (3)需要强调的是函数的使用必须遵循先定义后使用的原则,也就是说函数定义的代码必须写在调用程序之前。7.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 第7章 过程与函数课件 过程 函数 课件
限制150内