1、单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,*,子程序,过程与函数,第1页,提出函数与过程理由,计算机程序设计和问题求解最基本思想是:将一个大复杂问题分解成更小、更简单和更轻易处理子问题。在,Pascal,语言提供了函数和过程,使得问题分解和处理愈加方便。,函数或过程:将对应于一个子问题求精语句写在一起,作为一个单独程序模块。,通常经过子程序定义抽象操作,实现程序模块化。,第2页,一、函数,1,。定义,函数说明普通形式:,FUNCTION ,(,):,;,;,BEGIN,END,;,注意,:,(,1,)函数名由正当标识符指出,;,参数表由形式参数名表
2、和说明参数类型标识符组成,;,函数类型即结果类型,由类型标识符指明。,(,2,)形式参数类似于数学函数中自变量,为函数子程序提供初始量。在一个形式参数表中,能够有多个参数。逗号用来分开同类型各个参数名,分号用来分开不一样类型参数。,比如:(,x,y:real;m,n:integer,),(,3,),说明部分对仅,在函数中使用量加以说明,,能够包含函数所需要常量、说明类型、变量说明,也能够包含其它函数或过程说明,普通称之为,局部变量,。函数也能够没有说明。,(,4,)函数体,:(,函数部分程序体,),其中最少要有一个给函数名赋值语句,并以分号结束函数体。,第3页,2.,函数调用,普通形式:,(,
3、解释:函数调用必须出现在表示式中。函数每次调用,是将,每个实在参数值赋给对应形式参数,然后由函数完成要求,处理,并回送处理结果。,注意:,实在参数与形式参数个数要相同,一一对应,类型上赋值相容。,实在参数能够是表示式。,若没有形式参数,则 略去实在参数和括号。,第4页,例,:,编写一个求,K,!函数,调用此函数计算:(,0nm=0)and(nm)and(mn2 then larger:=n1,else larger:=n2,;,end,;,larger,begin,largest:=larger(larger(f1,,,f2),,,f3),;,计算和返回,f1,,,f2,,,f3,最大值,
4、end,;,largest,largest,函数说明指明了,largest,函数和它子函数,larger,结果值类型都为整数。子函数,larger,结果值由赋值语句,larger:=n1,(或,larger:=n2,)确定;,largest,函数结果值由赋值语句,largest:=larger(larger(f1,,,f2),,,f3),确定。,第6页,例,:,求正整数,A,和,B,之间完全数,(AB).,分析:所谓完全数是指它小于该数本身因子之和等于它本身,如,6,1,2,3,,,6,即是一个完全数。所以我们可定义一个布尔型函数,perfect(x),若,x,是完全数,其值为,TURE,不然
5、为,FALSE,。整个程序算法以下:,1 for i:=A to B do,2 if perfect(i)then writeln(i);,var,i,a,b:integer;,begin,主程序开始,write(Input a,b:);,repeat,输入,0a0)and(b0)and(ab);,writeln(List of all perfect numbers:);,从,a,到,b,逐一判断,是完全数则打印出来,for i:=a to b do,if perfect(i)then writeln(i);,end.,function perfect(x:integer):boolean;
6、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,第7页,二、过程,1,。定义,过程说明普通形式:,PROCEDURE,(,);,;,BEGIN,END,;,注意:,(,1,)形式参数表有两种格式:,数值形参,和以,VAR,开头,变量形参,。,(,2,)过程体中没有也不能够有给过程名赋值语句,返回值由变量形参提供。,2.,过程调用普
7、通形式:,(,),解释:与数值形参对应实在参数能够是表示式,与变量形参对应实在参数必须是变量,而不能是普通表示式。,第8页,例:定义一个求三数中最大值过程,procedure largest(f1,f2,f3:integer,;,var ir:integer),;,计算和返回,f1,,,f2,,,f3,最大值,ir,var g:integer,;,procedure larger(n1,,,n2:integer,;,var r:integer),;,largest,子过程,计算和返回,n1,,,n2,最大值,r,begin,if n1n2 then r:=n1,else r:=n2,;,end
8、larger,begin,larger(f1,,,f2,,,g),;,求出,f1,,,f2,中最大值,g,larger(g,,,f3,,,ir),;,求出,g,,,f3,中最大值,Ir,,作为,f1,,,f2,,,f3,中最大值返回,end,;,largest,Largest,有四个类型为整型形式参数:,f1,,,f2,,,f3,和,Ir,,前三个参数,f1,,,f2,,,f3,为调用者向被调用者传入三个要求比较大小整数,这三个参数仅用作传入数据,不传出计算结果,所以称为值参;第四个参数,Ir,用来向调用者传送三数中最大值,这种用作传出计算结果参数称为变量参数,由,var,标志。,Lar
9、gest,使用子过程,larger,有三个类型为整型形式参数:,n1,,,n2,和,r,,前二个参数,n1,,,n2,为过程,Largest,向它传入二个要求比较大小整数,属于值参;第三个参数,r,用来向过程,Largest,传送,n1,和,n2,最大值,属于变量参数。,第9页,例:,输出以下一个图形,:*,分析:我们前面学习可用二重循环打印出上图形,现我们设置一个过程打印出,N,个连续,*,号。,program ex7_2;,var i:integer;,procedure draw_a_line(n:integer);,该过程打印出连续,n,个星号,并换行,var j:integer;,b
10、egin,for j:=1 to n do,write(*);,writeln;,end;,begin,for i:=1 to 6 do,draw_a_line(i);,调用过程,第,I,行打印,i,个连续星号,end.,第10页,例 说明一个求两个整数最大条约数和最小公倍数过程,Procedure mab(a,b:integer;,var maxab,minab:integer);,Var,f:boolean;,i:integer;,Begin,if ab then begin t:=a;a:=b;b:=t;end;,f:=true;i:=a;,while f and i0 do,begin
11、if (a mod i=0)and(b mod i=0)then,begin,maxab:=I;,minab:=a*b div I;,f:=false;,end;,i:=i-1;,end;,End;,第11页,过程与函数区分,第12页,实参加形参,子程序调用(过程调用或函数调用)执行次序分以下几步:,实参加形参结合执行子程序体返回调用处继续执行,子程序说明形式参数表对过程或函数内语句序列直接引用变量进行说明,详细指明这些参数类别、数据类型要求和参数个数。过程或函数被调用时必须为它每个形参提供一个实参,按参数位置次序一一对应,每个实参必须满足对应形参要求。,Pascal,子程序形参主要分类:,
12、1.,值参数 形式参数表中前面没有,var,,后有类型参数。它类似过程和函数局部变量,仅为过程和函数执行提供初值而不影响调用时实际参数值。在调用过程或应用函数时,值参数所对应实际参数必须是表示式,而且它值不能使文件类型或包含文件类型值。实参必须和形参赋值相容。,2.,变量参数 形式参数表中前面有,var,后由类型参数。假如需要子程序向调用程序返回值时,应采取变量参数。变量参数要求它实参是和它同一类型变量。因为在子程序执行时,碰到对对应形参引用式定值,就是对对应实参引用式定值,即对形参任何操作就是对实参本身操作。,第13页,例输出两个数中最大值过程,Var,x:y,:integer,proced
13、urelargest(a,b:integer);begin ifabthenwriteln(a)elsewriteln(b);end.,begin,Readln(x,y);,Lagest(x,y);,End.,实际引用时所用参数,x,y,,是主程序定义变量,过程中定义形式参数,a,b,,在实际引用过程时,将被实际参数代替,第14页,过程、函数数据传递,在程序调用子程序时,调用程序将数据传递给被调用过程或函数,而当子程序运行结束后,结果又能够经过函数名、变参。当然也能够用全局变量等形式实现数据传递。接下来我们,就来研究参数传递与局部变量、全局变量等问题。,第15页,数值形参 和 变量形参,Pro
14、cedure show(a:integer),值形参和对应实参必须一一对应,包含个数和类型。,对应实在参数可为表示式,与实在参数之间传递关系是传值,仅视作输入参数,它有入口值,而无出口值,故不能表示计算结果,值形参作为子程序局部量,当控制返回程序后,值形参存放单元释放。,实参和值形参之间数据传递是单向,只能由实参传送给形参,相当赋值运算。,Procedure show(var a:integer),对应实在参数必须为变量,与实在参数之间传递关系是传地址,既可视作输入参数,又可视作输出参数,它可有入口值,也可无入口值,但普通应有出口值,以表示调用过程返回结果,变量形参加对应实参类型必须完全相同。
15、对变量形参,运行时不另外开辟存放单元,而是与对应实参使用相同存放单元。也就是说,调用子程序时,是将实参地址传送给对应变量形参。当控制返回到调用程序后,变量形参存放单元不释放,但变量形参本身无定义,即不得再使用。,普通在函数中使用值形参,而在过程中才使用变量形参,但也有例外。,第16页,写出以下两个程序运行结果。,program ex1;,program ex2;,var a,b:integer;,var a,b:integer;,procedure swap(x,y:integer);,procedure swap(Var x,y:integer);,var t:integer;,var t
16、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;,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);,end.,end.,分析:这两个程序唯一区分是,ex1,中将,x,y,作为值形参,而,ex2,中将,x,y,作为变量形参,所以在,ex2,中对,x,y,修改实际上是对调用该过程时与它们对应变量,a,b,修改,故最终,
17、a,b,值为,2,,,1,。而,ex1,中调用,swap,过程时,只是将,a,b,值传递给,x,y,,之后在过程中操作与,a,b,无关。,ex1,运行结果为,:ex2,运行结果为,:,1 2,1 2,1 2,2 1,第17页,全局变量和局部变量,局部变量:,凡是在,子程序内部作用变量,,应该在本子程序内加以说明。这种在子程序内部说明变量称为,局部变量,。,形式参数,也只是在该子程序中有效,所以也属于局部变量。,一个变量作用域是指在程序中能对此变量进行存取程序范围。所以,,局部变量作用域就是其所在子程序,。实际上,局部变量只是当其所在子程序被调用时才含有确定存放单元,当控制从子程序返回到调用程
18、序后,局部变量存放单元就被释放,从而变得无定义。,全局变量:,是指在主程序说明部分中说明量。全局变量作用域分两种情况:,当全局变量和局部量不一样名时,其作用域是整个程序范围(自定义起直到主程序结束)。,当全局变量和局部量同名时,全局变量作用域不包含局部量作用域。,在子程序执行部分使用是与全局变量同名局部变量。,第18页,求程序输出结果,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;,writ
19、eln(*,x,*,,,y);,a;,writeln(*,x,*,y);,end.,分析:程序中,x,y,是全局变量,但在过程,a,中也有变量,x,,故全程变量,x,作用域为除过程,a,外任何地方。而,y,作用域包含了子程序,a,,即整个程序。,运行结果以下,:,*,1*2,#2#,#2#,*,1*2,第19页,求程序输出结果,program ex(input,output);var x,y,z:integer;procedure s(x:integer;var y:integer);var z:integer begin x:=5;y:=6;z:=7;end;begin x:=1;y:=2;
20、z:=3;s(x,y);writeln(x,y,z);end.,第20页,求程序输出结果,program range(input,output);var x,y:integer;procedure p1;var x,z:integer;begin x:=10;y:=y+1;z:=10;writeln(x,y,z);end;begin x:=1;y:=1;writeln(x,y);p1;writeln(x,y,z);end.,输出结果:,1 110 2 101 2(error),第21页,递归调用,直接递归,子程序内引用子程序本身。比如,按递归定义形式写出,fac(n),函数说明以下,:,fun
21、ction fac(n:integer):integer,;,begin,if n=0 then fac:=1,else fac:=n*fac(n-1),;,end,;,fac,第22页,例:,骨牌铺法,有,1*n,一个长方形,用一个,1*1,、,1*2,和,1*3,骨牌铺满方格。比如,n=3,时为,1*3,方格。此时用,1*1,、,1*2,和,1*3,骨牌铺满方格,共有四种铺法。图列出了四种铺法。输入,n(0,n,30),,输出铺法总数。,题解,var,n:integer,;,格子数,function f(i:integer):longint,;,输入格子数,计算和返回铺法总数,begin,
22、if i in1.2 ,递归边界,then f:=i,else if i=3,then f:=4,else f:=f(i-1)+f(i-2)+f(i-3),;,递归,end,;,f,begin,readln(n),;,输入格子数,writeln(f(n),;,计算和返回,1*n,长方形铺法总数,end.main,“铺砖问题”有推广价值。比如某人走,n,级楼梯,每步能够走,1,级、,2,级或,3,级,走完,n,级楼梯共有多少走法。这个问题数学意义和解法与“铺砖问题”相同。,第23页,函数递归调用,var n:integer;,function count(n:integer):integer;,
23、begin,if n=1 then count:=0,else,if n mod 2=0,then count:=count(n div 2)+2,else count:=count(n*3+1)+2;end;,begin,readln(n);,writeln(count(n);,end.,输入,:20,第24页,读程序写结果,var a,b,c,d:integer;,procedure p(a:integer;var b:integer);,var c:integer;,begin,a:=a+1;b:=b+1;c:=2;d:=d+1;,writeln(m,a,b,c,d);,if a3 then p(a,b);,writeln(n,a,b,c,d)end;,begin,a:=1;b:=1;c:=1;d:=1;,writeln(x,a,b,c,d);,p(a,b);,writeln(y,a,b,c,d);,end.,X1111,M2222,M3323,N3323,N2323,y1313,第25页,






