1 / 57

过程与函数

过程与函数. 过程和函数. 顺序结构. 程 序 的基本结构. 程序设计的基本思想:. 自顶向下、逐步求精. 选择结构. 循环结构. 程序的模块化. 过程和函数. 说明: 程序中可以只有主程序而没有子程序,但不能没有主程序,也就是说不能单独执行子程序。. 结构化程序设计思想:. 方法 1 、模块化: (1) 把一个较大的程序划分为若干子程序,每一个子程序独立成为一个模块; (2) 每一个模块又可继续划分为更小的子模块; (3) 程序具有一种层次结构。   注:运用这种编程方法,考虑问题必须先进行整体分析,避免边写边想。. 结构化程序设计思想:.

keegan
Download Presentation

过程与函数

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 过程与函数

  2. 过程和函数 顺序结构 程 序 的基本结构 程序设计的基本思想: 自顶向下、逐步求精 选择结构 循环结构 程序的模块化 过程和函数 说明:程序中可以只有主程序而没有子程序,但不能没有主程序,也就是说不能单独执行子程序。

  3. 结构化程序设计思想: 方法1、模块化:(1)把一个较大的程序划分为若干子程序,每一个子程序独立成为一个模块;(2)每一个模块又可继续划分为更小的子模块;(3)程序具有一种层次结构。  注:运用这种编程方法,考虑问题必须先进行整体分析,避免边写边想。

  4. 结构化程序设计思想: 方法2、自顶向下:(1)先设计第一层(即:顶层),然后步步深入,逐层细分,逐步求精,直到整个问题可用程序设计语言明确地描述出来为止。(2)步骤:首先对问题进行仔细分析,确定其输入、输出数据,写出程序运行的主要过程和任务;然后从大的功能方面把一个问题的解决过程分成几个问题,每个子问题形成一个模块。 (3)特点:先整体后局部,先抽象后具体。

  5. 结构化程序设计思想: 方法3、自底向上:(1)先设计底层,最后设计顶层;(2)优点:由表及里、由浅入深地解决问题; (3)不足:在逐步细化的过程中可能发现原来的分解细化不够完善;(4)注意:该方法主要用于修改、优化或扩充一个程序。

  6. 标准函数有: abs(x)/ sqrt(x)/ round(x)… X:=abs(-10); Y:=sqrt(81); Z:=round(35.9); 标准函数的调用

  7. 例1-1:编程求12+22+...+1002的和 例2_1:编程求1!+2!+3!+...+10!的和。 PROGRAM sum(input,output); VAR i:integer; s:longint; BEGIN s:=0; for i:=1 to 100 do s:=s+sqr(i) ; fac(i) writeln('s=',s); END.

  8. 一、函数的定义及调用 函数首部 Function 函数名(形参表):函数类型; 局部变量说明; begin 语句1; …; 函数名:=表达式; end; 函数的类型 函数体 将函数值传递给函数名 注意:自定义函数先定义后使用。 函数值通过函数名传送回调用程序。 在表达式中调用:函数名(实参) 如:x= Abs(n) abs为函数名,n为实参,函数类型为integer or real

  9. 例2-2 编写一个求n!的函数fac. 形式参数 函数首部 function fac(n:integer):longint; var k:integer; t:longint; begin t:=1; for k:=2 to n do t:=t*k; fac:=t; end; {endfac} 函数的结果类型 局部变量说明 函数说明 函数执行部分 将函数值传递到函数名中

  10. 注意: 1、使用函数前应先说明。 2、函数首部以保留字function开头,函数名由用户自定义的一个标识符,用来存放最终函数值。 3、形参就是函数的自变量,其初值来源于主程序的调用,只有在程序的执行过程中调用了函数,形参才能得到具体的值并参与运算,得到函数值。注意:形参表类似于变量说明,但只能使用类型标识符,且不能直接使用类型。形参可缺省。 4、函数的类型也就是函数值的类型,函数值将通过函数名传送回调用程序。 5、函数体内所用的类型、常量、变量等只在本函数内有效,退出函数体后,分配的存储单元被释放。这些量与函数体外的同名变量无关。 6、在函数体中至少有一条将函数值传给函数名的赋值语句。

  11. 例7-1 编写一个求n!的函数fac. 若求3!+5!+7!的值,如何修改程序? Program ex1-2a(input,output); var s:longint; 形式参数 函数首部 function fac(n:integer):longint; var k:integer; t:longint; begin t:=1; for k:=2 to n do t:=t*k; fac:=t; end; {endfac} 局部变量说明 函数说明 函数执行部分 将函数值传递到函数名中 begin S:=fac(3)+fac(5)+fac(7); Writeln(‘s=‘,s) End. 主程序 函数调用出现在表达式中

  12. 调用函数时注意: 1、自定义函数中的形参,不是实际存在的变量,故又称为虚拟变量,它们并不占用内存单元,只是在调用函数时,才临时开辟相应的内存单元,存放实在参数的值,如fac(3)中的3。它是在调用函数时的所用的自变量。形参实质上是实参的一个“替身”。在调用函数时,实参将值赋给形参,因此实参的个数、类型应与形参一一对应,并且要有确定的值。 2、函数调用步骤是:首先在调用程序中计算实参的值,传送给对应的形参,接着执行函数体,最后将函数值返回给调用程序。 3、函数的定义是静态的,若定义后未被调用,则该函数永远不会被执行。

  13. b2 b1 b6 用海伦公式求三角形的面积:s= p(p-a)(p-b)(p-c) b3 b5 b7 b4 例2-3 计算如图所示的多边形面积。 分析: a,b,c为三角形的边长,p为半周长,即p=(a+b+c)/2 Program ex1-2(input,output); var b1,b2,b3,b4,b5,b6,b7,s:real; 函数首部 function area(a,b,c:real):real; var p:real; begin p:=(a+b+c)/2; area:=sqrt(p*(p-a)*(p-b)*(p-c)); end; 函数area结果类型为实型 三个形式参数 给函数名area赋值 Begin readln(b1,b2,b3,b4,b5,b6,b7); s:=area(b1,b5,b6)+area(b2,b6,b7)+area(b3,b4,b7); writeln(‘s=’,s:10:3); End. 调用函数

  14. 例2-4 自定义一个专门求两自然数的最大公约数的函数GCD; function GCD(x,y: integer): integer; Var n:integer; begin While x mod y <>0 do begin n:=x; x:=y; y:=n mod y end; GCD:=y end;

  15. 思考: 1、若求3个数的最大公约数,能否定义函数?求4个数最大公约数的函数能否定义?求N个数呢? 2、函数中能否调用已定义函数?自己能否调用自己?

  16. 练习:设计一个函数digit(N,K),它能将自然数N的从右边开始的第K位上的数字取出来。例如:digit(13579,3)=5,digit(2468,6)=0,调用此函数,求出10次输入后,得到的第K位上的数字之和。练习:设计一个函数digit(N,K),它能将自然数N的从右边开始的第K位上的数字取出来。例如:digit(13579,3)=5,digit(2468,6)=0,调用此函数,求出10次输入后,得到的第K位上的数字之和。 拓展:1、从左边开始的第K位上的数字如何取出? 2、从中间的第K位开始取M个数字如何取出?

  17. 在屏幕上输出如图所示的图形。 * *** ***** * *** ***** ******* ********* *********** * *** ***** ******* ********* *********** ************ ************** * * * * * * Program exam; var I,j:integer; begin for i:=1 to 3 do begin write(‘ ‘:(40-i)); for j:=1 to 2*i-1 do write('*'); writeln; End.

  18. 2、过程定义及调用 read/readln/write/writeln 标准过程有: 标准过程调用: Read(a,b,c); 自定义过程的格式: Procedure 过程名(形参表); 局部变量说明; begin 语句1; 语句2; … end; 过程首部 过程体

  19. 在屏幕上输出如图所示的图形。 * *** ***** * *** ***** ******* ********* *********** * *** ***** ******* ********* *********** ************ ************** *************** * * * * * * procedure draw (n:integer); var I,j:integer; begin for i:=1 to n do begin write(‘ ‘:(40-i)); for j:=1 to 2*i-1 do write('*'); writeln; end; Begin {main} Draw(4);draw(6);draw(9); for k:=1 to 5 do writeln(‘*’:39); End.

  20. 将例2-2中n!用过程fa来定义。 思考:n!的结果存放在哪里? Procedure fa(n:integer); var k:integer; begin t:=1; for k:=2 to n do t:=t*k; end; t 在主程序中说明,为全程量。 n!的结果是如何回传给主程序的? 是通过t带回主程序的。 注意: 1、过程体内所用的类型、常量、变量只在本过程内有效,退出过程体后,该单元被释放。 2、不能给过程名赋值,过程名不能代表任何数据。

  21. 练习:2-3-b 定义一个求三角形面积的过程area。 Procedure area(a,b,c:real; var m:real); var p:real; begin p:=(a+b+c)/2; m:=sqrt(p*(p-a)*(p-b)*(p-c)); end; a、b、c、m四个参数,a、b、c为值参,参数m前面有var,是变参。该过程被调用后,由变参m将结果传回调用程序。

  22. b2 b1 b6 b3 b5 b7 b4 过程调用: 过程名:实在参数表; 例:用过程编写程序求如图所示的五边形面积。 Program lx1-1(input,output); var b1,b2,b3,b4,b5,b6,b7,s,sum,real; Procedure area(a,b,c:real; var s:real); var p:real; begin p:=(a+b+c)/2; s:=sqrt(p*(p-a)*(p-b)*(p-c)); end; begin readln(b1,b2,b3,b4,b5,b6,b7); area(b1,b5,b6,s); 三角形的面积通过变参s传回主程序。 sum:=0; area(b2,b6,b7,s); sum:=sum+s; sum:=sum+s; area(b3,b4,b7,s); sum:=sum+s; writeln(‘sum=‘,sum:10:3); end.

  23. 过程 函数 过程和函数的主要区别: 完成一系列的数据处理,或与计算无关的各种操作 操作 往往求一个函数值 函数有类型,最终要将函数值传送给函数名。 无 结果类型 由独立的过程调用语句来完成 函数调用出现在表达式中 调用方式 返回值的方法 通过变参将运算的结果传给调用程序 函数值是通过函数名传回调用程序

  24. 3、变量及其作用域 例1-5 a读程序写结果。 m为全程变量。 Program ex1-5(input,output); var m:integer; procedure test1; begin m:=100; end; begin m:=5; writeln(‘m=‘,m); test1; writeln(‘m=‘,m); end. 全程量的作用域有两种情况: 1、在全程变量和局部变量不同名时,其作用域是整个程序。 2、在全程变量和局部变量同名时,全程变量的作用域不包含同名局部变量的作用域。 m=5 结果为: m=100

  25. 例1-5b 读程序写结果。 Program ex1-5b(input,output); var m:integer; procedure test2; var m:integer; begin m:=100; end; begin m:=5; writeln(‘m=‘,m); test2; writeln(‘m=‘,m); end. M是局部量,结果被屏蔽,它不影响到全程量m的值。 m=5 结果为: m=5

  26. 全局变量:在主程序中被说明 作用域:整个程序; 局部变量:在子程序中被说明 作用域:主程序及其下级的程序。 全程量的作用域分两种情况:  ①当全程量和局部量不同名时,其作用域是整个程序。 ②当全程量和局部量同名时,全程量的作用域不包含局部量的作用域。 当局部变量所在子程序被调用时,局部变量才被分配有效的存储单元;当返回调用程序时,局部变量所占的存储单元就被释放。

  27. 练一练: Program ex1-2(input,output); var x,y:integer; procedure change; var x:integer; begin x:=2; y:=2; writeln(x,y); end; begin x:=1; y:=1; writeln(x,y); change; writeln(x,y); end. 结果为: • 1 • 2 • 1 2

  28. 4、参数的传递 Function fac(x,y:integer):real; 值形参 形参 变形参 procdure fac(var x,y:integer); 参数 实参 a:=fac(5,6); 值参类似于局部变量,仅为过程和函数的执行提供初值而不影响调用时实际参数的值。 对变参操作实际上就是对实参本身的操作。

  29. Program ex1-6-1(input,output); var a:integer; procedure sum(b:integer); begin b:=b+10; writeln(‘b=‘,b); end; begin a:=10; sum(a); writeln(‘a=‘,a); end. Program ex1-6-2(input,output); var a:integer; procedure sum(var b:integer); begin b:=b+10; writeln(‘b=‘,b); end; begin a:=10; sum(a); writeln(‘a=‘,a); end. 值参 变参 运行结果为: b=20 a=10 运行结果为: b=20 a=20

  30. Program lx1-2-1(input,output); var x,n:integer; procedure chan(x:integer; var y:integer); begin x:=x+5; y:=y+5; writeln(‘x=’,x, ‘y=’,y); end; begin x:=10; n:=10; writeln(‘x=’,x, ‘n=’,n); chan(x,n); writeln(‘x=’,x, ‘n=’,n); end. 练一练 结果为: X=10 n=10 X=15 y=15 X=10 y=15

  31. 读下列程序体会子程序的功能: Program lx_2_2a(input,output); var x,y:integer; procedure swap1; var t:integer; begin t:=x; x:=y; y:=t; end; begin x:=10; y:=20; writeln(‘x= ’,x, ‘y=’: 6,y); swap; writeln(‘x=’,x,’y=’:6:y) End. Program lx_2_2b(input,output); var x,y:integer; procedure swap1(var x,y:integer); var t:integer; begin t:=x; x:=y; y:=t; end; begin x:=10; y:=20; writeln(‘x= ’,x, ‘y=’: 6,y); swap; writeln(‘x=’,x,’y=’:6:y) End.

  32. 值参 实参 过程 变参 过程 实参 值参与变参的区别: 1、传值:为值参分配存储单元,过程体内对值参的操作不影响实参的值。一旦过程体执行结束后,系统将收回值参所占用的存储单元,值参的值也就不再存在。 2、变参是传地址:变参所占用的存储单元中存放的是实参的地址,因此对变参的操作就是对实参的操作。一旦过程体执行完毕,系统将收回变参所占用的存储单元,但运算结果已保留在对应的实参中。 形参种类不同决定了实参的单、双向传递。值参实现单向传递,仅将过程外部的值传递给过程,故称为输入参数,它所对应的实在参数可以是常量、变量或表达式;变参实现的是双向传递,除了将过程外部的值传递给过程外,更重要的是它能将过程中变化的形参值带出来,故又称为输出参数,其对应的实参必须是变量。

  33. 练习: 指出程序中的全程变量、局部变量、值参、变参,并写出程序运行后的输出结果。 Program lx(input,output); var a,b,c:integer; Procedure suan(var x:integer;y:integer); var m,n:integer; begin m:=x*y;x:=x+1; y:=y+10;n:=x+y; writeln(‘x=‘,x, ‘ y= ’:4,y,’m=’:4,m‘ n=’:4,n) end; begin a:=3;b:=3; suan(a,b); suan(a,b); suan(a,b) end. 全程变量 a,b,c 局部变量 m,n 值参:y 变参:x 结果: x=4 y=13 m=9 n=17 x=5 y=13 m=12 n=18 x=6 y=13 m=15 n=19

  34. [例2-5]如果一个自然数除了1和本身,还有别的数能够整除它,这样的自然数就是合数。例如15,除了1和15,还有3和5能够整除,所以15是合数。14,15,16是三个连续的合数,试求连续十个最小的合数。[例2-5]如果一个自然数除了1和本身,还有别的数能够整除它,这样的自然数就是合数。例如15,除了1和15,还有3和5能够整除,所以15是合数。14,15,16是三个连续的合数,试求连续十个最小的合数。 分析:①从最小的素数开始,先确定第一个素数A; ②再确定与A相邻的后面那个素数B;(作为第二个素数); ③检查A,B的跨度是度否在10 以上,如果跨度小于10,就把B 作为新的第一个素数A,重复作步骤②; ④如果A、B跨度大于或等于10,就打印A、B之间的连续10个自然数,即输出 A+1, A+2, A+3 …, A+10。

  35. Program exam44; var a,b,s,n: integer; yes: boolean; procedure sub(x: integer;var yy: boolean); {求x是否为素数 } var k,m: integer; { 用yy逻辑值转出 } begin k:=trunc(sqrt(x)); for m:=3 to k do if odd(m) then if x mod m=0 then yy:=false; end;

  36. begin {主程序 } b:=3; repeat a:=b;{a 为第一个素数 } repeat yes:=true; inc(b,2); {b是a后面待求的素数} sub(b,yes);{调用SUB过程来确认b是否为素数 } if yes then s:=b-a;{如果b是素数,则求出跨度s } until yes; until s > = 10; for n:=a+1 to a+10 do write(n:6); writeln; readln end.

  37. n! 例1-7 求组合数C +C 的和。 3 6 5 9 m n C = m!(n-m)! 6、子程序的嵌套 1、嵌套 一个函数或过程可能要求调用另一个函数或过程,这种调用称为函数或过程的嵌套。 n!=n*(n-1)*…*2*1 用fac函数实现。 组合用cnm函数实现。被调用的函数写在调用它的函数前面。 Program ex1-7(input,output); var s:real; function fac(k:integer):real; var I,fa:integer; begin fa:=1; for I:=2 to k do fa:=fa*I; fac:=fa end; 求组合函数 Function cnm(n,m:integer):real; begin cnm:=fac(n)/(fac(m)*fac(n-m)); end; Begin s:=cnm(6,3)+cnm(9,5); writeln(‘s=‘,s:6:0); End. 调用fac函数 求n!函数 调用cnm函数 主程序

  38. 程序的执行过程: 1 开始 3调用fac(6) 函数fac 函数cnm 主程序 2调用cnm(6,3) 4返回 5调用fac(3) 6返回 7用fac(6-3) 9返回 8返回 继续执行主程序

  39. Function fac(k:integer):real; var I,fa:integer; begin fa:=1; for I:=2 to k do fa:=fa*I; fac:=fa end; Function cnm(n,m:integer):real; begin cnm:=fac(n)/(fac(m)*fac(n-m)); end; Function cnm(n,m:integer):real; function fac(k:integer):real; var I,fa:integer; begin fa:=1; for I:=2 to k do fa:=fa*I; fac:=fa end; begin cnm:=fac(n)/(fac(m)*fac(n-m)); end;

  40. 过程a的说明 . . . 调用b . . . 过程b的说明 . . . 调用a . . . 提前引用子程序: 在程序中并列的过程或函数需要相互调用。 Procedure b(c,y;var y:real); forward; Procedure a(p:real; var q:real); begin … b(p,q); … end; Procedure b; begin … a(x,y); … end; 说明: 把需要提前引用的过程或函数的首部放置在前面,并加上保留字forward;

  41. 例1_7b(提前引用子程序示例) Function cnm(n,m:integer):real; begin cnm:=fac(n)/(fac(m)*fac(n-m)); end; 求组合数C +C 的和。 3 6 5 9 function fac(k:integer):real; var I,fa:integer; begin fa:=1; for I:=2 to k do fa:=fa*I; fac:=fa end; function fac(k:integer):real; forward; function cnm(n,m:integer):real; begin cnm:=fac(n)/(fac(m)*fac(n-m)); end; function fac(k:integer):real; var I,fa:integer; begin fa:=1; for I:=2 to k do fa:=fa*I; fac:=fa end;

  42. 综合应用: 例2-9 对6-1000内的偶数验证哥德巴赫猜想:任何一个大于6的偶数总可以分解为两个素数之和。 分析:哥德巴赫猜想是一个古老而著名的数学难题,它的理论证明十分复杂。在这里我们用计算机对有限范围内的数加以验证,即任意输入一个大于6的偶数,若能拆分成两个素数,则认为该猜想成立。 解题的关键是判素数。假设定义函数pan(x),用来判断x是否为素数。若x为素数,则函数pan值为1,若不是素数则pan值为0。

  43. Program ex1_9(input,output); var n,m:integer; Function pan(x:integer):integer; var f,k:integer; begin f:=1; for k:=2 to trunc(sqrt(x)) do if x mod k=0 then f:=0; pan:=f end; begin repeat write(‘n=‘); readln(n); until(n>6) and (n<1000) and (n mod 2=0); for m:=2 to n div 2 do if pan(m)+pan(n-m)=2 then writeln(n,’=‘,m,’+’,n-m); end.

  44. 结构化程序设计思想: 方法1、模块化:(1)把一个较大的程序划分为若干子程序,每一个子程序独立成为一个模块;(2)每一个模块又可继续划分为更小的子模块;(3)程序具有一种层次结构。  注:运用这种编程方法,考虑问题必须先进行整体分析,避免边写边想。

  45. 结构化程序设计思想: 方法2、自顶向下:(1)先设计第一层(即:顶层),然后步步深入,逐层细分,逐步求精,直到整个问题可用程序设计语言明确地描述出来为止。(2)步骤:首先对问题进行仔细分析,确定其输入、输出数据,写出程序运行的主要过程和任务;然后从大的功能方面把一个问题的解决过程分成几个问题,每个子问题形成一个模块。 (3)特点:先整体后局部,先抽象后具体。

  46. [例2-12]将合数483的各位数字相加(4+8+3)=15,如果将483分解成质因数相乘: 483=3*7*23,把这些质因数各位数字相加(3+7+2+3),其和也为15。即某合数的各位数字之和等于它所有质因数的各数字之和。求500以内具有上述特点的所有合数。 分析: 要建立以下几个过程: (1)过程1:要分离X上的各个数字并求和 (2)过程2:分解因子并求所有因子数字和 (3)过程3:判断是否为素数

  47. program exam45; var n,t1,t2,tatol: integer; yes: boolean; procedure sub1(x:integer; var t:integer); {过程:分离x的各位数字} begin {并求各位数字之和} repeat t:=t+x mod 10; x:=x div 10; until x=0 end;

  48. procedure sub2(x: integer; var t: integer); {过程:分解质因数 } var xx,tt:integer; begin xx:=2; while x>1 do if x mod xx=0 then begin tt:=0; sub1(xx,tt); t:=t+tt; x:=x div xx end else inc(xx) end;

  49. procedure sub3(x: integer;var yy: boolean); {过程:判断x是否为素数 } var k,m: integer; begin k:=trunc(sqrt(x)); for m:=2 to k do if x mod m=0 then yy:=false; end;

  50. begin {主程序} for n:=1 to 500 do begin t1:=0;t2:=0; yes:=true; sub3(n,yes); {调用过程求素数 } if not yes then {如果非素数就… } begin sub1(n,t1); {调用过程求n的各位数字之和 } sub2(n,t2);{调用过程求n的各质因数的数字之和 } if t1=t2 then write(n:6); {打印合格的合数 } end end; readln end.

More Related