1 / 71

第 三 章

第 三 章. 模块化程序设计. 引出. 如果程序中有多个数,多处需要判断是否是素数,怎么办?反复书写那段重复的代码? 解决办法: 将判断素数的功能用一个独立的模块来实现,即自定义函数;在 main 函数中反复调用此功能模块就可以了。. for(i=2;i&lt;=x/2;i++) if(x%i==0) break; if(i&gt;=x/2) printf(&quot;yes<br>&quot;); else printf(&quot;no<br>&quot;);. void sushu(int x) {int i; for(i=2;i&lt;=x/2;i++)

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. 引出 • 如果程序中有多个数,多处需要判断是否是素数,怎么办?反复书写那段重复的代码? • 解决办法:将判断素数的功能用一个独立的模块来实现,即自定义函数;在main函数中反复调用此功能模块就可以了。 for(i=2;i<=x/2;i++) if(x%i==0) break; if(i>=x/2) printf("yes\n"); else printf("no\n");

  3. void sushu(int x) {int i; for(i=2;i<=x/2;i++) if(x%i==0) break; if(i>=x/2) printf("yes\n"); else printf("no\n"); } • 模块化的优点: • 实现了代码的复用; • 编程效率高;代码少; • 功能分解,易于实现; • 便于合作开发大型项目等。 main() { int a,b; printf("input a number:"); scanf("%d%d",&a,&b); sushu(a); sushu(b); }

  4. [教学要求] 1.掌握函数定义的一般形式。 2.掌握函数调用的两种方式。 3.理解函数形参与实参的对应关系、参数传递方法及函数返回值的概念。 4.掌握指针的含义。 5.掌握指针作为函数参数的数据传递特点。

  5. 3.2 函数的定义

  6. 函数定义的基本知识 • 函数的定义位置:应写在其它函数的外面,前后都可以,但不能写在内部。 • 函数的定义形式: • 第一行写函数名和括号 • 第二行开始是函数体,用大括号扩起来,如: 函数名称用户自定

  7. 函数定义的声明:函数被调用在前面,而函数定义书写在后面的,需要在使用该函数前进行声明。函数定义的声明:函数被调用在前面,而函数定义书写在后面的,需要在使用该函数前进行声明。 • 函数声明的形式:将函数定义的第一行信息重新写一遍,末尾加分号。 声明可以放在调用之前的任意位置处。 void sushu(int x) ; main() { …… sushu(a); …… } void sushu(int x) {…… }

  8. 函数声明的几种变通形式: main() { float add(float x,float y); float a,b,c; scanf("%f,%f",&a,&b); c=add(a,b); printf("sum is %f",c); } float add(float x, float y) { float z; z=x+y; return(z); } float add(float ,float ); float add(float a,float b);

  9. 函数定义的高级知识 • 函数的参数 • 函数的返回值

  10. 主调函数 自定义函数 参数 返回值 int sushu(int x)

  11. 有参函数 无参函数 函数的形式分类1 无论有参、无参,函数名后的括号不能省略。 函数的形式分类2 • 有返回值函数 • 无返回值函数

  12. 通常也无返回值,仅需书写: void 函数名(); 例如: void clrscr(); void draw() { …… } main() { draw(); draw(); } 如果有返回值,则写明返回值类型, 例如 char getchar(); ch=getchar(); 无参函数定义 特点:空括号

  13. 需写明参数的个数和类型: 类型函数名(类型 参数1,类型 参数2,…) 如:int sushu(int n); float fun(int m, int n); 【强调】:形参定义时需分别写明它们的类型,类型相同不能只写一个,例如下错误: float fun(int m, n); 有参函数定义 × 例如:求两个数的最大值的函数参数设计: max( ) float float x, float y

  14. 分析设计函数首部信息: 实验4-1-4: float fun(int n) 实验4-1-5: float fun(int m,int n) 实验4-1-7: void fun() 函数定义分析练习

  15. 有返回值函数,在函数体内用return语句返回处理的结果值。有返回值函数,在函数体内用return语句返回处理的结果值。 如:int sushu(int x) { int i; for(i=2;i<=x/2;i++) if(x%i==0) return 0; return 1; } return语句的两个功能:返回值、结束函数调用。 有返回值函数定义

  16. 如果函数不返回值,则名称前写void,如: void draw(int x,int y) 如果定义函数时名称前没写明类型,默认为int类型,如: draw(int x,int y) 【注意】:如果函数体内return语句返回值的类型与定义的函数名前类型不同,则以函数名前面的类型为准,系统会自动进行类型转换,可能会产生误差或错误。

  17. 例:编写一个函数,其功能是求m的n次方,即mn。例:编写一个函数,其功能是求m的n次方,即mn。 函数定义练习 ? • 分析:函数参数 • 函数返回值 2个,int类型参数 返回值为float或double类型 函数首部信息如下: double fun(int m,int n)

  18. double fun(int m,int n) { int i; double t=1; for(i=1;i<=n;i++) t=t*m; return t; } 形参在括号中定义后,直接在函数中使用,不能再次定义。 return (表达式); return 表达式; main() { int a,b; double c; printf("input two numbers:"); scanf("%d%d",&a,&b); c=fun(a,b); printf("%.0lf\n",c); }

  19. 函数调用

  20. 形参和实参 形参:定义时括号内的参数叫做形式参数,简称形参。 实参:调用是给予的实际数值叫做实际参数,简称实参。 形参和实参:个数相同、类型一致、一一对应。 例如求m的n次方的函数: float fun(int m,int n) 调用时如果求4的5次方,只能书写fun(4,5);不能写为fun(5,4);

  21. double fun(int m,int n) { int i; double t=1; for(i=1;i<=n;i++) t=t*m; return t; } 有返回值函数调用 实参可以是常量、变量、表达式等。如:fun(2,8) fun(3,1+5) main() { int a,b; double c; printf("input two numbers:"); scanf("%d%d",&a,&b); c=fun(a,b); printf("%.0lf\n",c); } 赋 值

  22. double fun(int m,int n) { int i; double t=1; for(i=1;i<=n;i++) t=t*m; return t; } 有返回值函数调用 main() { int a,b; printf("input two numbers:"); scanf("%d%d",&a,&b); printf("%.0lf\n", fun(a,b)); } 输 出

  23. double jiecheng(int n) { int i; double t=1; for(i=1;i<=n;i++) t=t*i; return t;} 有返回值函数调用 main() { int a,i; double b=0; scanf("%d",&a); for(i=1;i<=a;i++) b=b+jiecheng(i); printf("%.0lf\n",b); } 表达式运算

  24. 有返回值函数调用 b=jiecheng(a); b=b+jiecheng(i); printf("%.0lf\n", jiecheng(a)); • 总结: • 将函数调用看做一个可以利用的值。 • 函数调用一般不作为独立语句存在。 • jiecheng(a); ×

  25. 无返回值函数调用 编写一个函数,其功能画m行n列的矩形。 ? 2个,int类型参数 无返回值,为void • 分析:函数参数 • 函数返回值 函数首部信息如下: voiddraw(int m,int n)

  26. void draw(int m,int n) { int i,j; for(i=1;i<=m;i++) { for(j=1;i<=n;i++) printf(“*”); printf(“\n”); } } 总结: 函数调用作为独立语句存在。 void main( ) { int x,y; scanf(“%d%d”,&x,&y); draw(x,y); }

  27. 函数调用总结: • 两种形式: • 有返回值函数调用看做一个可以利用的值。 • 无返回值函数调用作为独立语句存在。

  28. 本次课内容小节 • 函数定义的基本形式 • 函数定义的参数表达 • 函数定义的返回值类型 • 函数调用的实参表达 • 函数调用的2种形式

  29. 编程练习 • 编写一个函数,判断一个给定的数是否是水仙花数。 • 编写一个函数,功能是输出如下三角形图案。

  30. 编写函数,求三角形面积。 函数参数:三角形的三条边 函数返回值:三角形面积。 函数编程练习 3-3

  31. 编写函数判断一个数是否是完数。 完数:一个数如果恰好等于它的因子之和,这个数就是完数,例如6的因子为1、2、3,而6=1+2+3,因此6是完数。 要求函数返回整型值。 编程练习(实验题目) 3-4

  32. 3.7 库函数的使用 参考书后附录,P303 注意包含相应的头文件。 注意理解参数的类型和含义。

  33. 3.8 局部变量与全局变量

  34. 例 不同函数中同名变量 局部变量---内部变量 在函数内定义的变量是局部变量, 其作用域:只在本函数内有效 声明: 不同函数中可定义的局部变量可同名,占不同内存单元 形参属于局部变量 在复合语句中也可以定义它的局部变量,其作用域是只在此复合语句中有效。 float f1(int a) { int b,c; ……. } char f2(int x,int y) { int i,j; …… } main() { int m,n; ……. {int i;…… } } main() { int a,b; a=3; b=4; printf("main:a=%d,b=%d\n",a,b); sub(); printf("main:a=%d,b=%d\n",a,b); } sub() { int a,b; a=6; b=7; printf("sub:a=%d,b=%d\n",a,b); } a,b,c有效 x,y,i,j有效 m,n有效 i有效

  35. 全局变量---外部变量 函数外部定义的变量称为全局变量 其作用域为定义位置后的任何函数 int a=13,b=-8; int max() { int z; z=a>b?a:b; return(z); } main() { printf(“a=%d,b=%d",a,b); printf("max=%d",max()); }

  36. 例 全局变量举例 int max(int x, int y) { int z; z=x>y?x:y; return(z); } main() { printf(“a=%d,b=%d",a,b); printf("max=%d",max(a,b)); } int a=13,b=-8; 因为全局变量的作用域为定义位置后的任何函数 编译出错

  37. 全局变量意味着多个函数可使用它,就是说各函数之间通过全局变量产生了相互的值的影响,因此降低了函数的独立性,使各函数间依赖型增强。 应尽量少使用全局变量

  38. int a=13,b=8; int sum() { int z; z=a+b; a++; b--; return(z); } main() { printf(“a=%d,b=%d",a,b); printf(“sum=%d",sum()); printf(“a=%d,b=%d",a,b); } 输出结果为: a=13,b=8; sum=21; a=14,b=7;

  39. 例 全局变量与局部变量同名举例 int a=3,b=5; max(int a, int b) { int c; c=a>b?a:b; return(c); } main() { int a=8; printf("max=%d",max(a,b)); }

  40. 例 全局变量副作用 int i; main() { void prt(); for(i=0;i<5;i++) prt(); } void prt() { for(i=0;i<5;i++) printf(“%c”,’*’); printf(“\n”); } 运行结果:*****

  41. 动态存储变量和静态存储变量 局部变量的存储类别:动态存储变量和静态存储变量。 auto动态存储变量是在程序运行时根据需要动态分配存储空间。函数被调用时,分配给内存单元,调用结束后就释放内存单元。 static静态存储变量局是指程序运行期间分配固定的存储空间。每次函数调用结束后不释放空间,只有在主程序运行结束才释放内存单元。 static静态变量在函数多次调用时,只赋一次初值,每次调用后保留当时的结果值。

  42. 变量的声明类型 局部变量的定义类型 auto自动类型 如:atuo int i,a,b; static静态类型 如:static int x,y; register寄存器类型 如:register int i; 补充:如无特殊声明,默认为auto类型 • 全局变量的定义类型 • static静态类型(默认是static类型) • extern 外部类型 如:extern int s; • 补充:如无特殊声明,默认为static类型

  43. a=0,b=-10,n=1 a=4,b=10,n=13 a=0,b=-10,n=13 a=6,b=10,n=25 int n=1; void func() { static int a=2; int b=5; a+=2; b+=5; n+=12; printf("a=%d,b=%d,n=%d\n",a,b,n); } main() { int a=0,b=-10; printf("a=%d,b=%d,n=%d\n",a,b,n); func(); printf("a=%d,b=%d,n=%d\n",a,b,n); func(); }

  44. 3.9 模块化程序设计 —指 针

  45. 普通函数参数值传递的特点 单向、值传递 函数return语句返回值的特点 只能返回一个值

  46. void swap(int x,int y) { int t; t=x; x=y; y=t; } main() { int a,b; printf("input a number:"); scanf("%d%d",&a,&b); swap(a,b); printf("After changer a=%d,b=%d\n",a,b); } 输入4,3 输出after change:a=4, b=3 本例说明:自定义函数中修改了形参变量的值,反过来不会影响主调函数中实参的值。

  47. 问题的引入 1、能不能在自定义函数中通过修改形参而改变主调函数中的变量值。 2、如果想同时返回多个处理值给主调函数怎么办? 例题1:编写函数分别返回双精度实数的整数部分和小数部分。 例题2:编写函数交换两个变量的值,并在主函数中输出结果。

  48. 解 决 方 案-使用指针类型的参数 void fun(int *x,int *y) { int t; t=*x; *x=*y; *y=t; } main() { int a,b; printf("input a, b:"); scanf("%lf%d",&a,&b); fun(&a,&b); printf("after call a=%d,b=%d\n",a,b); } 1、定义指针参数 2、间接访问 3、传递地址

  49. 解 决 方 案-使用指针类型的参数 1、定义指针参数 int fun(double a,double *b) { int x; x=(int)a; *b=a-x; return x; } main() { double x,y; int c; scanf("%lf",&a); c=fun(x,&y); printf(“zhengshu %d,xiaoshu %lf",c,y); } 2、间接访问 3、传递地址

  50. 通过演示的例题说明: 为什么有时需要在函数的参数中使用指针类型的参数? 1.可以同时将多个函数处理结果返回给主调函数。 2.可以间接访问主调函数的实参变量,即将函数内的值反向传递给实参变量。

More Related