《pascal过程与函数教程618.pdf》由会员分享,可在线阅读,更多相关《pascal过程与函数教程618.pdf(15页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、Pascal 教程 第 1 页 共 15 页 第十二课 过程与函数 前面我们曾经学习了程序设计中的三种基本控制结构(顺序、分支、循环)。用它们可以组成任何程序。但在应用中,还经常用到子程序结构。通常,在程序设计中,我们会发现一些程序段在程序的不同地方反复出现,此时可以将这些程序段作为相对独立的整体,用一个标识符给它起一个名字,凡是程序中出现该程序段的地方,只要简单地写上其标识符即可。这样的程序段,我们称之为子程序。子程序的使用不仅缩短了程序,节省了内存空间及减少了程序的编译时间,而且有利于结构化程序设计。因为一个复杂的问题总可将其分解成若干个子问题来解决,如果子问题依然很复杂,还可以将它继续分
2、解,直到每个子问题都是一个具有独立任务的模块。这样编制的程序结构清晰,逻辑关系明确,无论是编写、阅读、调试还是修改,都会带来极大的好处。在一个程序中可以只有主程序而没有子程序(本章以前都是如此),但不能没有主程序,也就是说不能单独执行子程序。pascal 中子程序有两种形式:函数和过程。一、函数 在此之前,我们曾经介绍并使用了 pascal 提供的各种标准函数,如 ABS,SUCC 等等,这些函数为我们编写程序提供了很大的方便。但这些函数只是常用的基本函数,编程时经常需要自定义一些函数。(一)函数的说明 在 pascal 中,函数也遵循先说明后使用的规则,在程序中,函数的说明放在调用该函数的程
3、序(主程序或其它子程序)的说明部分。函数的结构主程序的结构很相似。函数定义的一般格式:function ():;函数首部 说明:函数由首部与函数体两部分组成。函数首部以关键字 function 开头。函数名是用户自定义的标识符。函数的类型也就是函数值的类型,所求得的函数值通过函数名传回调用它的程序。可见,函数的作用一般是为了求得一个值。形式参数简称形参,形参即函数的自变量。自变量的初值来源于函数调用。在函数中,形参一般格式如下:变量名表 1:类型标识符 1;变量名表 2:类型标识符 2;;变量名表 n:类型标识符 n 可见形参表相当于变量说明,对函数自变量进行说明,但应特别注意:此处只能使用类
4、型标识符,而不能直接使用类型。当缺省形参表(当然要同时省去一对括号)时,称为无参函数。函数体与程序体基本相似,由说明部分和执行部分组成。函数体中的说明部分用来对本函数使用的标号、常量、类型、变量、子程序加以说明,这些量只在本函数内有效。函数体的执行部分由 begin 开头,end 结束,中间有若干用分号隔开的语句,只是 end 后应跟分号,不能像程序那样用句号.。在函数体的执行部分,至少应该给函数名赋一次值,以使在函数执行结束后把函数值带回调用程序。(二)函数的调用 Pascal 教程 第 2 页 共 15 页 我们可以在任何与函数值类型兼容的表达式中调用函数,或者说,函数调用只能出现在允许表
5、达式出现的地方,或作为表达式的一个因子。函数调用方式与标准函数的调用方式相同。函数调用的一般格式:函数名 或 函数名(实在参数表)说明:实在参数简称实参。实参的个数必须与函数说明中形参的个数一致,实参的类型与形参的类型应当一一对应。调用函数时,一般的,实参必须有确定的值。函数调用的步骤为:计算实参的值,赋给对应的形参;(三)函数的应用举例 例 1 求正整数 A 和 B 之间的完全数(AB).分析:所谓完全数是指它的小于该数本身的因子之和等于它本身,如 6123,6 即是一个完全数。因此我们可定义一个布尔型函数 perfect(x),若 x 是完全数,其值为 TURE,否则为 FALSE。整个程
6、序算法如下:1 for i:=A to B do 2 if perfect(i)then writeln(i);源程序如下:program ex7_1;var i,a,b:integer;function perfect(x:integer):boolean;var k,sum:integer;begin 累加 x 所有小于本身的因数 sum:=1;for k:=2 to x div 2 do if x mod k=0 then sum:=sum+k;判断 x 是否是完全数 perfect:=x=sum;将结果赋值给函数名 end;end of perfect begin主程序开始 write
7、(Input a,b:);repeat 输入 0a0)and(b0)and(ab);writeln(List of all perfect numbers:);从 a 到 b 逐个判断,是完全数则打印出来 for i:=a to b do Pascal 教程 第 3 页 共 15 页 if perfect(i)then writeln(i);end.自定义函数只是主程序的说明部分,若主程序中没有调用函数,则系统不会执行函数子程序。当主程序调用一次函数时,则将实在参数的值传给函数的形式参数,控制转向函数子程序去执行,子程序执行完毕后自动返回调用处。补充:若一个自然数,它所有的真因子(即除了自身以
8、外的约数)的和恰好等于它本身,这种数叫做完全数。完全数,又称完美数或完备数,是一些特殊的自然数:它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。例如:第一个完全数是 6,它有约数 1、2、3、6,除去它本身 6 外,其余 3 个数相加,1236。第二个完全数是 28,它有约数 1、2、4、7、14、28,除去它本身 28 外,其余 5 个数相加,124+7+1428。后面的数是 496、8128。例如,6=1+23 28=124714 496=1+2+4+816+31+62124+248 8128=124+81632+64127+254508+10162032+406
9、4 对于“4”这个数,它的真因子有 1、2,其和是 3。由于 4 本身比其真因子之和要大,这样的数叫做亏数。对于“12”这个数,它的真因子有 1、2、3、4、6,其和是 16。由于 12 本身比其真因子之和要小,这样的数就叫做盈数。那么有没有既不盈余,又不亏欠的数呢?即等于它自己的所有真因子之和的数,这样的数就叫做完全数。编辑本段【性质】完全数有许多有趣的性质:它们都能写成连续自然数之和。如:6=1+2+3;28=1+2+3+4+5+6+7;496=1+2+3+30+31;它们的全部因数的倒数之和都是 2,因此每个完全数都是调和数。如:1/1+1/2+1/3+1/6=2;1/1+1/2+1/4
10、+1/7+1/14+1/28=2;3.除了 6 之外,都有这样的一个性质:如 28,2+8=10,1+01;496,4+9+619,1+910,1+01 函数的调用。Pascal 教程 第 4 页 共 15 页 二、过程 在 pascal中,自定义过程与自定义函数一样,都需要先定义后调用。函数一般用于求值,而过程一般实现某些操作。(一)过程的说明 过程说明的一般格式为:procedure ();过程首部 说明:过程首部以关键字procedure开头。过程名是用户自定义的标识符,只用来标识一个过程,不能代表任何数据,因此不能说明 过程的类型。形参表缺省(当然要同时省去一对括号)时,称为无参过程。
11、形参表的一般格式形式如下:var 变量名表:类型;var 变量名表:类型。其中带 var的称为变量形参,不带 var的称为值形参。在函数中,形参一般都是值形参,很少用变量形参(但可以使用)。例如,下列形参表中:(x,y:real;n:integer;var w:real;var k:integer;b:real)x、y、n、b 为值形参,而 w、k 为变量形参。调用过程时,通过值形参给过程提供原始数据,通过变量形参将值带回调用程序。因此,可以说,值形参是过程的输入参数,变量形参是过程的输出参数。有关变参,这在后面内容具体叙述。过程体与程序、函数体类似。与函数体不同的是:函数体的执行部分至少有一
12、个语句给函数名赋值,而过程体的执行部分不能给过程名赋值,因为过程名不能代表任何数据。过程体的说明部分可以定义只在本过程有效的标号、常量、类型、变量、子程序等。(二)过程的调用 过程调用是通过一条独立的过程调用语句来实现的,它与函数调用完全不同。过程调用与调与标准过程(如 write,read等)的方式相同。调用的一般格式为:Pascal 教程 第 5 页 共 15 页 过程名 或 过程名(实在参数表)说明:实参的个数、类型必须与形参一一对应。对应于值形参的实参可以是表达式,对应于变量形参的实参只能是变量。过程调用的步骤为:计算实参的值;将值或变量的 地址 传送给对应的形参;执行过程体;返回调用
13、处。过程与函数有下列主要区别:过程的首部与函数的首部不同;函数通常是为了求一个函数值,而过程可以得到若干个运算结果,也可用来完成一系列的数据处理,或用来完成与计算无关的各种操作;调用方式不同。函数的调用出现在表达式中,而过程调用是一个独立的语句。(三)过程的应用举例 例 2 输出以下一个图形:*分析:我们前面学习可用的二重循环打印出上图形,现我们设置一个过程打印出 N 个连续的*号。源程序如下:program ex7_2;var i:integer;procedure draw_a_line(n:integer);该过程打印出连续 n 个星号,并换行 Pascal 教程 第 6 页 共 15
14、页 var j:integer;begin for j:=1 to n do write(*);writeln;end;begin for i:=1 to 6 do draw_a_line(i);调用过程,第 I 行打印 i 个连续星号 end.三、过程、函数的数据传递 在程序调用子程序时,调用程序将数据传递给被调用的过程或函数,而当子程序运行结束后,结果又可以通过函数名、变参。当然也可以用全局变量等形式实现数据的传递。这一节我们,就来研究参数传递与局部变量、全局变量等问题。(一)数值参数和变量参数 前面已经讲过,pascal子程序中形式参数有数值形参(简称值参)和变量形参(变参)两种。事实上
15、,还有函数形参和过程形参两种,只是应用并不太多,我们不作深入地研究。1、值形参 值参的一般格式如7.1.1所示。应该强调的是:形参表中只能使用类型标识符,而不能使用类型。值形参和对应的实参必须一一对应,包括个数和类型。实参和值形参之间数据传递是单向的,只能由实参传送给形参,相当赋值运算。Pascal 教程 第 7 页 共 15 页 一个特殊情况是,当值形参是实型变量名时,对应的实参可以是整型表达式。值形参作为子程序的局部量,当控制返回程序后,值形参的存储单元释放。2、变量形参 变量形参的一般格式如7.2.1所示,必须在形参前加关键字 var。应该注意的是:与变量形参对应的实参只能是变量名,而不
16、能是表达式。与变量形参对应的实参可以根据需要决定是否事先有值。变量形参与对应的实参的类型必须完全相同。对变量形参,运行时不另外开辟存储单元,而是与对应的实参使用相同的存储单元。也就是说,调用子程序时,是将实参的地址传送给对应的变量形参。当控制返回到调用程序后,变量形参的存储单元不释放,但变量形参本身无定义,即不得再使用。选用形式参时,到底是使用值形参还是变量形参,应慎重考虑。值形参需要另开辟存储空间,而变量形参会带来一些副作用。一般在函数中使用值形参,而在过程中才使用变量形参,但也有例外。例 3 写出下列两个程序的运行结果。program ex1;program ex2;var a,b:int
17、eger;var a,b:integer;procedure swap(x,y:integer);procedure swap(Var x,y:integer);var t:integer;var t:integer;begin begin t:=x;x:=y;y:=t;t:=x;x:=y;y:=t;end;end;begin begin a:=1;b:=2;a:=1;b:=2;Pascal 教程 第 8 页 共 15 页 writeln(a:3,b:3);writeln(a:3,b:3);swap(a,b);swap(a,b);writeln(a:3,b:3);writeln(a:3,b:3
18、);end.end.分析:这两个程序唯一的区别是 ex1中将 x,y作为值形参,而 ex2中将 x,y作为变量形参,因此在 ex2中对 x,y的修改实际上是对调用该过程时与它们对应的变量 a,b的修改,故最后,a,b的值为 2,1。而 ex1中调用 swap过程时,只是将 a,b的值传递给 x,y,之后在过程中的操作与 a,b无关。答:ex1的运行结果为:ex2的运行结果为:1 2 1 2 1 2 2 1 (二)全程变量、局部变量及它们的作用域 在主程序的说明部分和子程序的说明部分均可以说明变量,但它们的作用范围是特定的。1、局部量及其作用域 在介绍过程和函数的说明时,我们曾指出,凡是在子程序
19、内部作用的变量,应该在本子程序内加以说明。这种在子程序内部说明的变量称为局部变量。形式参数也只是在该子程序中有效,因此也属于局部变量。一个变量的作用域是指在程序中能对此变量进行存取的程序范围。因此,局部变量的作用域就是其所在的子程序。实际上,局部变量只是当其所在的子程序被调用时才具有确定的存储单元,当控制从子程序返回到调用程序后,局部变量的存储单元就被释放,从而变得无定义。事实上,在子程序内定义的标号、符号常量、类型、子程序也与局部变量具有相同的作用域。2、全程量及其作用域 全程量是指在主程序的说明部分中说明的量。全程量的作用域分两种情况:当全程量和局部量不同名时,其作用域是整个程序范围(自定
20、义起直到主程序结束)。Pascal 教程 第 9 页 共 15 页 当全程量和局部量同名时,全程量的作用域不包含局部量的作用域。例 4 写出下列程序的运行结果:program ex7_4;var x,y:integer;procedure a;var x:integer;begin x:=2;writeln(#,x,#);writeln(#,y,#);end;of a beginmain program x:=1;y:=2;writeln(*,x,*,y);a;writeln(*,x,*,y);end.分析:程序中 x,y是全局变量,但在过程 a 中也有变量 x,故全程变量 x 的作用域为除过
21、程 a 外的任何地方。而 y 的作用域包含了子程序 a,即整个程序。答:运行结果如下:*1*2#2#2#Pascal 教程 第 10 页 共 15 页 *1*2 评注:变量作用域内对变量的操作都是对同一存储单元中的量进行的。四、过程和函数的嵌套 Pascal语言中,使用过程和函数,能使程序设计简短,便于阅读,节省存贮单元和编译时间。程序往往设计成分层结构,由一个主程序和若干个过程及函数组成。在过程或函数中,还可以说明另一些过程或函数,即过程或函数可以分层嵌套。在同一层中亦可说明几个并列的过程或函数。例如:上例过程的分层嵌套关系如下:0 层主程序 sample内并列两个 1 层过程 P1a和 P
22、1b。过程 P1a又嵌套两个 2 层过程 p2a和 p2b,2 层的第二过程 p2b又嵌套过程 p3,p3 就是第 3 层。其中 p1b,p2a和 p3 不再嵌套别的过程,称为基本过程。这种分层结构的程序设计,特别要注意局部变量的使用范围和过程调用的要求。在主程序 sample中定义的变量,可以在所有的过程中使用,主程序可调用 p1a和 p1b两个过程。过程p1a中定义的变量,只能在 p2a,p2b 和 p3 中使用。它能调用 p2a,p2b两个过程,而不能调用 p3 和 p1b。在Pascal 教程 第 11 页 共 15 页 过程 p1b中定义的变量,只能在 p1b中使用,它只能调用过程
23、p1a。过程 p2a不能调用任何过程。过程 p2b可以调用并列过程 p2a和 p3,而过程 p3 可以调用 p2a过程。过程调用是有条件的,过程定义在先,调用在后。同一层过程,后说明的过程可以调用先说明的过程。如果要调用在它后面定义的过程(或函数),可使用FORWARD这个扩充标识符。要注意的是 过程(或函数)首部中形式参数表写一次即可,不必重复。如:procedure extend(var a,b:integer);forward;表示过程 extend。因此,过程 extend 的说明部分只须如下书写:procedure extend;begin :end;五、子程序(模块化)结构的程序设
24、计 例 5 对 6 到 60 的偶数验证哥德巴赫猜想:不小于 6 的偶数可分解成两个素数之和。分析:用布尔型函数 prime(x)判断 x 是否是素数,若是,函数值为真,否则,函数值为假。算法如下所示。1 t:=6 2 while t60 do 3 t1 1;4 repeat 5 t1 1+2;/*找下一个素数 a*/6 until prime(t1)and prime(t-t1);/*直到 a,b都是素数*/7 writeln(i,=,t1,+,t-t1);Pascal 教程 第 12 页 共 15 页 8 tt+2;9 endwhile 源程序如下:program ex9_7;var t,
25、t1:integer;function prime(x:integer):boolean;var i:integer;begin if x=1 then prime:=false else if x=2 then prime:=true else begin prime:=true;i:=2;while(i=round(sqrt(x)and(x mod i0)do i:=i+1;if i=round(sqrt(x)then prime:=false;end;end;of prime begin t:=6;while t=60 do Pascal 教程 第 13 页 共 15 页 begin t
26、1:=1;repeat t1:=t1+2;until prime(t1)and prime(t-t1);writeln(t,=,t1,+,t-t1);t:=t+2;end;end.例 6 编写一个给一个分数约分的程序。源程序如下:program ex7_6;变量参数 var a,b:integer;procedure common(var x,y:integer);var i,j,k:integer;begin 求 x,y 的最大公约数 i:=x;j:=y;repeat k:=i mod j;i:=j;j:=k;until k=0;对 x,y 进行约分 x:=x div i;y:=y div
27、i;Pascal 教程 第 14 页 共 15 页 end;begin write(Input a,b=);readln(a,b);common(a,b);writeln(a,b:5);end.如输入:Input a,b=12 8 则输出:3 2 练习 1 输入 5 个正整数求它们的最大公约数。(提示:可用一个数组将个数存放起来,然后求第一个数和第二个数的公约数,再求第三个数与前两个数公约数的公约数,这样求得前三个整数最大公约数如此类推可求出个整数的最大公约数)2 给一维数组输入任意6 个整数,假设为:7 4 8 9 1 5 请建立一个具有以下内容的方阵:7 4 8 9 1 5 4 8 9 1 5 7 8 9 1 5 7 4 9 1 5 7 4 8 1 5 7 4 8 9 5 7 4 8 9 1 (请用子程序编写)。Pascal 教程 第 15 页 共 15 页 3 求两个正整数的最小公倍数。4 输入一个任意位的正整数,将其反向输出。5 有五位同学,其各科成绩如下:学号 数学 语文 英语 总分 名次 1 108 97 90 2 98 88 100 3 100 43 89 4 84 63 50 5 97 87 100 ()编写一个过程 enter,输入每个学生成绩并计算各人的总分。()编写过程 minci,用以排出每个人的名次。()按学号顺序输出。
限制150内