第 5章 过程与函数本章要点:
理解过程与函数的概念
掌握过程与函数的定义方法
掌握过程与函数中三种参数的传递的概念及特点
掌握过程与函数的调用方法
5.1 循序渐进学理论
5.1.1 过程与函数的概念
1.过程的概念
Delphi语言的过程有两种:标准过程与自定义过程。标准过程是系统内部定义好的过程 。 自定义过程是用户自己编写代码定义的过程,它又分为事件过程与通用过程两种。
2.函数的概念函数也是完成某一功能的程序段,与过程最重要的区别在于函数有返回值而过程没有。
Delphi的函数也有两类:标准函数和自定义函数。
5.1.2 过程的定义与调用
5.1.2 过程的定义与调用通用过程由用户自己创建并通过程序调用,创建通用过程也称过程声明或过程定义。
[格式 ],Procedure 过程名( [形参表 ]) //Procedure表示这是一个过程,有形参也可以没有局部声明 //声明常量,变量或另一个过程或函数等
begin
语句 ; //简单语句或复合语句都可以
end;
2.过程的调用创建的通用过程是为了调用的,通用过程只有通过调用才能被执行。若想要调用某个过程,该过程必须在调用语句之前定义。
[格式 1]:过程名(实参表) ;
[格式 2]:过程名 ; 或者:过程名 ( );
【 例 5-1】 定义一个过程,用来在一个 Memo组件中显示若干行欢迎词,欢迎词的显示次数是随机的,
但至少显示 3次,至多显示 7次。程序的设计界面如图
5-2所示,程序运行时,单击 【 显示欢迎词 】 按钮,
将在 Memo组件中显示出若干行欢迎词,如图 5-3所示。
图 5-2 程序设计界面 图 5-3 程序运行界面
5.1.3 函数的定义与调用
1.函数的定义函数也是完成一定功能的程序段,与过程的主要区别就是函数有返回值,其定义方式稍有不同,函数的定义格式如下。
[格式 ],Function 函数名(形参表),返回值类型 ;
局部声明
begin
语句 ;
end;
2.函数的调用函数也是通过调用来运行的,调用函数的一般格式如下 。
[格式 1]:变量名 =函数名 (实参列表 );
[格式 2]:表达式 运算符 函数名 (实参列表 );
注意,函数有一个返回值,函数调用就相当于一个同类型的值,可以和同类型的数据一样作为表达式或表达式的一部分参加运算 。
【 例 5-2】 定义一个函数,用来求任意非负整数各位数字之和。程序设计界面如图 5-4所示,程序运行时,在第一个编辑框中输入一个整数,然后按 【 计算 】
按钮,将把该整数的各位数字和求出来并显示在第二个编辑框中,如图 5-5所示。
要求把求整数的各位数字和编写成一个函数。
图 5-4 程序设计界面图 5-5 程序运行界面
5.1.4 参数的传递
1.常量参数和值参的传递在过程或函数的首部中,定义形参时,如果形参名前有保留字 Const,说明该参数是常量参数。在函数或过程中不允许给常量参数赋值。在定义形参时,
如果形参前没有任何保留字,则说明该参数为值参,
在函数或过程中可以给值参赋值,但在调用该函数或过程时不会改变与之对应的实参的值。值参的这种传递方式称为值传递,值传递是一种单向传递,即可把实参值传递给形参,但对形参的改变不会传给实参。
【 例 5-3】 编写一个求两个数的乘积的应用程序,程序设计界面如图 5-6所示。程序运行时,在“操作数 1”右边编辑框输入任意整数,在“操作数 2”右边编辑框也输入任意整数,单击按钮 【 运算 】 将把两个操作数的乘积运算出来并显示在最下面一个编辑框里,如图 5-7所示。要求把求两个数的乘运算编写成一个通用过程。
图 5-6 程序设计界面 图 5-7 程序运行界面
2.变量参数(变参)的传递在定义过程或函数时,形参表中
Var之后的参数即是变参。变参是按地址传递的,即在调用过程或函数时,实参的地址被传递给形参,故形参和实参实际上是同一个地址单元。
【 例 5-4】 重新做 【 例 5-3】,希望得到正确的答案。程序设计界面如图 5-6
所示,程序的运行界面如图 5-8所示。
图 5-8 程序运行界面
5.1.5 子程序的嵌套与递归
1.子程序的嵌套在 Delphi中把过程与函数统称为子程序,子程序既能嵌套定义也能嵌套调用。嵌套定义的含义是,在一个子程序中的定义中又包含了另一个子程序的定义。
嵌套调用是指在调用某个子程序时,该子程序又调用了其它的子程序。在嵌套定义时,被包含的子程序称为内层子程序,包含其它子程序的子程序称为外层子程序。紧邻的两层称为邻层,否则称为隔层。
关于子程序的嵌套定义和嵌套调用必须遵循如下规则:
( 1) 外层必须完全包含内层 。
( 2) 外层可以调用内层中的邻层子程序,但不能隔层调用 。
( 3) 内层可以调用外层中的邻层和隔层子程序 。
( 4) 同一层的子程序允许后定义的子程序调用先定义的子程序,反之,需要用 Forward( 超前引用 ) 在子程序的首部后面对后定义的子程序予以说明才能调用 。
【 例 5-5】 组合数的计算公式为。
请用子程序的嵌套来求组合数。程序设计界面如图 5-9所示,程序运行界面如图
5-10所示。
)!(!
!
zmz
mC z
m
图 5-9 程序设计界面 图 5-10 程序运行界面
2.子程序的递归子程序直接或间接调用自身称为子程序的递归调用。
【 例 5-6】 有 6个人坐在一块儿,问第 6个人多大年纪?他说他比第 5个人大 3岁;再问第 5个人多少岁,他说比第 4个人大 3岁;再问第 4个人多少岁,他说比第 3个人大 3岁;问第 3个人多少岁,他说比第 2个人大 3岁;问第 2个人多少岁,他说比第 1个人大 3岁;
最后问到第 1个人多少岁,他说 12岁。请问第 6个人多少岁?用子程序递归调用来实现。程序设计界面如图
5-11所示,程序运行界面如图 5-12所示。
图 5-11 程序设计界面图 5-12 程序运行界面从程序设计的角度来说,递归过程必须解决两个问题:一是递归计算的公式,二是递归结束的条件 。
本题可以写成:
递归计算公式,A(n)=A(n-1)+3 n>=1
递归结束条件,A(1)=1
凡是能够表示成上述式子的数学问题均可以用递归来实现,在递归函数中一般可采用双分支语句来实现:
if (递归结束条件 ) then
函数名,=递归终止值
else
函数名,=递归公式 ;
式子中的函数名也可以用 Result来代替 。
5.2 典型实例练能力
5.2.1 典型实例一:验证哥德巴赫猜想
【 实例题目 】
德国著名数学家哥德巴赫提出:任何一个大于等于 6的偶数都可以表示为两个素数之和 。 请编写程序验证这一猜想 。 程序的设计界面如图 5-13所示,程序运行时,在第一个编辑框里输入任意大于等于 6的偶数,单击
【 验证 】 按钮,则在另一编辑框里显示两个符合要求的素数 。 程序运行界面如图 5-14所示 。 要求判断某数是否为素数用一个函数来实现 。
图 5-13 程序设计界面图 5-14 程序运行界面
5.2.2 典型实例二:斐波那契( Fibonacci)数列
【 实例题目 】
斐波那契( Fibonacci)数列是一个典型的可用递归求解的问题。该数列来源于兔子的繁殖,大意是:
小兔子和大兔子没有繁殖能力,只有老兔子才有繁殖能力。假设第 1个月有一对小兔子,第 2个月长成大兔子,第 3个月长成老兔子,并生出一对小兔子;第 4个月,老兔子继续生出一对小兔子,同时原来的小兔子长成大兔子,这样在第 4个月就有一对老兔子,一对大兔子和一对小兔子共 3对兔子;依此类推,假设兔子永远不死,请编写程序求出任意一个月有多少对兔子。程序设计界面如图 5-15所示,程序运行时输入月数,然后单击 【 计算 】 按钮,将显示出该月的兔子对数,如图 5-16所示。
图 5-15 程序设计界面图 5-16 程序运行界面
5.3 上机练习重应用
5.3.1 上机练习一:分离字母和数字字符
【 练习 题目 】
编写一个程序,用来分离出字符串中的字母字符和数字字符。程序的设计界面如图 5-
17所示。程序运行时,在第一个编辑框中输入任意一串字符,然后单击 【 分离 】 按钮,
将把字母和数字分离开来并显示在对应的编辑框中,如图 5-18所示。
图 5-17 程序设计界面图 5-18 程序运行界面
5.3.2 上机练习二:校园歌手评分程序
【 练习 题目 】
请为某次校园歌手大赛编写一个评分程序,设共有裁判六人,评分满分为 10分,除去一个最高分,再除去一个最低分,剩余的评分的平均值即为选手得分 。
程序的设计界面如图 5-19所示,程序运行时,分别在
6个编辑框中输入 6个评委的评分,然后按 【 得分 】 按钮,将算出该选手的得分并在相应的编辑框中显示出来,如图 5-20所示 。 按 【 清除 】 按钮,将清除掉所有编辑框中的内容 。 要求:编写一个过程求选手得分,
得分通过参数返回给调用过程 。
图 5-19 程序设计界面 图 5-20 程序运行界面