1 / 45

本章主要内容

本章主要内容. 第六章 函 数. 函数的定义 函数的调用 函数的嵌套调用 递归函数 数组与函数 全局变量和局部变量. C 程序的结构由若干个 C 函数组成。 C 函数是 C 程序的组成部分,是由完成一特定任务的说明语句和执行语句组成的基本功能单元。 C 函数的功能相当于其它程序设计语言中的一个程序模块,或一个子程序。. 6.1 认识C函数. 学生成绩管理系统. 成绩录入. 成绩管理. 打印输出. 成绩更新. 成绩查询. 插入. 更新. 删除. 按学号查询. 按课程查询. 模块化程序示意图 :. 图 6-1 学生成绩管理系统.

jemma
Télécharger la présentation

本章主要内容

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. C程序的结构由若干个C函数组成。 C函数是C程序的组成部分,是由完成一特定任务的说明语句和执行语句组成的基本功能单元。 C函数的功能相当于其它程序设计语言中的一个程序模块,或一个子程序。 6.1认识C函数

  3. 学生成绩管理系统 成绩录入 成绩管理 打印输出 成绩更新 成绩查询 插入 更新 删除 按学号查询 按课程查询 模块化程序示意图: 图6-1 学生成绩管理系统

  4. 函数调用程序实例 调用函数 main( ) { printstar(); print_message( ); printstar( ); } printstar( ) { printf(“**************\n”);} print_message( ) { printf(“how do you do!\n”);} 用户自定义函数

  5. 函数的分类(1) • 从使用角度分: 标准库函数:以程序库的形式直接提供给用户使用。 stdio.h……gets()、printf() math.h ……sin()、sqrt() 用户自定义函数:由用户自己建立定义。

  6. 函数的分类(2) • 从函数形式分: • 无参函数:调用函数时主函数不将数据传送给被调函数。用于完成特定功能的操作。 如:c=getchar( )…… • 有参函数:调用函数时在主调函数和被调函数之间有参数传递。 如:putchar(c)、puts(str)、……

  7. 函数说明 • 一个C程序是由一个或多个源文件组成,每个源文件由若干函数组成。 • C程序的执行从main函数开始,也从main函数终止。 • 源程序中所有的函数在结构上都是平行的,互相独立的。 • main函数可以调用其他函数,其他函数之间可以互相调用。

  8. 函数的定义(一) • 无参函数的特点:只完成某些动作,不进行参数传递。 • 无参函数的定义形式: 类型标识符 函数名( ) { 说明部分; 语句部分 }

  9. 例:无参函数使用示例。 main( ) { printstar( ); printword( ); printstar( ); } printstar( ) /*定义无参函数printstar()*/ { printf("******************\n");} printword( ) /*定义无参函数printword()*/ { printf("This is an example\n");}

  10. 有参函数定义形式(一): 类型标识符 函数名(形式参数列表) 形式参数说明; { 说明部分; 语句部分; } int max(x,y) int x,y; { int z; z=(x>y)?x:y; return(z); } 函数的定义(二)

  11. int max( int x,int y) { int z; z=(x>y)?x:y; return(z); } 有参函数定义形式(二): 类型标识符 函数名(类型名 参数1,…,类型名 参数n) { 说明部分; 语句部分; } 函数的定义(二)

  12. 有参函数定义说明: • “类型标识符”指的是函数计算结果的数据类型,即函数类型。 • “函数名”必须是合法的标识符,命名时尽可能使之“见名知意”。 • 参数的类型定义部分可在{ }外,也可在{ }内。 • 只在函数内部使用的变量,因为不参与主调函数与被调函数之间的参数传递,必须放在{ }内部的说明部分位置。

  13. 例:求两数的最大值。注意函数的定义形式。 main( ) { int a,b,c; scanf("%d%d",&a,&b); c=max(a,b); printf("max=%d\n",c); } int max(x,y) int x,y; { int z; z=(x>y)?x:y; return(z); }

  14. 函数参数 几个相关术语: • 函数调用:一个函数调用另一个函数。 • 主调函数、被调函数 • 有参函数:主调函数和被调函数之间有数据传递关系,被调函数即有参函数。 • 无参函数:主调函数和被调函数之间无数据传递关系,被调函数即无参函数。

  15. 关于实参和形参 main( ) {int a,b,c; scanf("%d%d",&a,&b); c=max(a,b); printf("max=%d\n",c); } int max(int x,int y) { int z; z=(x>y)?x:y;return(z);} 实际参数 形式参数

  16. 函数的返回值 • 函数的返回值是通过return语句传递的。 • return语句的一般形式: return 表达式; return (表达式);

  17. main() { int a,b,c; scanf(“%d%d”,&a,&b); c=max(a,b); printf(“max=%d\n”,c); } int max(x,y) int x,y; { int z; z=(x>y)?x:y; return(z); } return语句执行图示: 主调函数 被调函数

  18. 函数返回值的注意事项 • 返回值类型要与函数类型一致,且以函数类型为准。 • 函数类型缺省时,系统自动按整型处理。 • 例如: int max(int x,int y ) { return x*y;}

  19. 补充说明 • 一个函数中可以有若干个return语句,流程执行到哪里,就从哪里返回主调函数。 • 若函数体内没有return语句,则执行函数到末尾,然后返回主调函数。 • 当不需要返回值的时候,可以用void定义函数为空类型,表示无返回值。

  20. 6.2 编写和调用自定义函数 • 函数调用的一般格式: 函数名(实参表); • 举例(设已建立max函数,为求最大值): …… main( ) { int x,y,z; scanf(“%d,%d”,&x,&y); z=max(x,y); …… }

  21. 函数调用中参数传递的两种方法 • 传值调用:函数调用中,采用赋值方式将实参的值传给形参。即单向调用。 • 传址调用:函数调用中,把实参的地址传给形参。在被调用函数中通过形参中的地址来访问调用函数中的实参。双向调用。

  22. 函数调用的三种方式 按照函数在程序中出现的位置来分; • 作为表达式出现在任何允许表达式出现的地方,参与运算。 如:a=sqrt(b); • 作为一条独立的语句完成特定的操作。 如:gets(string1); • 作为函数的参数被其他函数调用。 如:printf(“%s\n”,strcpy(str1,”Red rose”));

  23. 调用函数与被调函数的相对位置关系 • 如使用库函数,一般应在文件开头用: #include <……> …… • 函数调用遵循“先定义后调用”的原则。一般被调函数放在调用函数之前定义。 • 若被调函数在调用函数之后定义,就必须在调用函数中对被调函数加以如下说明: 类型名 被调函数名( );

  24. 例:被调函数在调用函数之后出现: main( ) { float sum( ); /*对被调函数的说明*/ float a,b,c; scanf("%f%f",&a,&b); c=sum(a,b); printf("sum=%f\n",c); } float sum(x,y) /*对函数sum进行定义*/ float x,y; { float z; z=x+y; return z; }

  25. 数组与函数 函数间传递数组数据的两种方法: • 值传递:将数组中的每个元素都作为一个参数来传递。 • 地址传递:通过地址传送方式将数组的首地址(如数组名)作为参数进行传递 。

  26. 数组元素作函数实参 • 数组元素(同简单变量)作函数实参,单向值传递,即“传值调用”方式。 • 【例6.17】用程序求出a数组中所有素数的和及平均值,函数isprime用来判断自变量是否素数。

  27. int isprime(int x) /*该函数判断是否素数*/ { int i; for (i=2;i<=x/2;i++) if (x%i==0) return (0); return (1); } main( ) { int i,a[10],sum=0,n=0; float aver; printf("Enter 10 numbers:\n"); for(i=0;i<10;i++)

  28. scanf("%d",&a[i]); printf("\n"); for(i=0;i<10;i++) if(isprime(a[i])==1) /*若a[i]素数*/ { printf("%d ",a[i]); sum+=a[i]; /*求素数和*/ n++; /*统计素数个数*/ } aver=sum/n; /*求素数平均值*/ printf("\nsum=%d,aver=%f\n",sum,aver); }

  29. 数组名作函数实参 • 形参和实参都采用数组名,传递是实参数组的起始地址,是地址传递方式。 • 【例6.18】求某学生10门课程成绩的平均分,课程成绩用数组存放。

  30. 例: float average(b) float b[10]; { int i; float aver,sum=0; for (i=0;i<10;i++) sum+=b[i]; aver=sum/10; return(aver); } 数组名作形参

  31. main( ) { float a[10],ave; int i; printf("Input 10 scores:\n"); for (i=0;i<10;i++) scanf("%f",&a[i]); printf("\n"); ave=average(a); printf("average score is %5.2f",ave); } 数组名作实参,传递的是实参数组的起始地址

  32. 使用数组名作函数实参说明 • 数组名表示数组元素存放的起始地址,可认为是地址常量。 • 数组名作实参,传递是数组地址,而非数组元素。 • 字符串常量作实参,传递的字符串常量的首地址而非字符内容。 • 用数组名作函数参数,必须在主调函数和被调函数中分别定义数组,并保证类型一致。

  33. 6.3函数的嵌套调用 • C语言程序由函数构成。 • 函数与函数之间是平行的,独立的。 • 不允许在一个函数内部嵌套定义另一个函数;但允许在调用一个函数的过程中,又调用另一个函数。

  34. 函数a 函数b main函数 调用函数b 调用函数a 结束 函数的嵌套调用

  35. 6.4 编写递归函数 • 递归调用: 在调用一个函数的过程中又出现直接或间接的调用该函数本身,称为函数的递归调用。 注意: 递归结构构成了另外一种形如循环的结构。

  36. 递归函数设计举例:求n! • 算法描述: n!=1 × 2 × 3 × …… × (n-1)×n • 求积公式: 1 n=0 n ×(n-1)! n>0 f(n) =

  37. 5!的运算过程: ? 5! 120 5×4! 5×24 4×3! 4×6 3×2! 3×2 2×1 2×1! 1×0! 1×1 1

  38. 求n!递归源程序如下: long facto(n) int n; { long int z; if (n==0) z=1; else z=n*facto(n-1); return z; } main( ) { int x; long facto( ); printf("Input a number:\n"); scanf("%d",&x); printf("The result is %ld",facto(x)); }

  39. 6.4 局部变量和全局变量 基本概念: • 变量的生命期 变量占用存储空间的时限 • 变量的作用域 在变量占用存储空间的时间内是否能够被引用,即变量作用的有效范围是全局的还是局部的。

  40. 局部变量 • 局部变量 在一个函数内部定义的变量(内部变量),它只在此函数范围内有效,在此函数以外不能被使用。 • 局部变量的作用域所在函数内部

  41. 局部变量举例 a 、b、c有效范围 float f1(a) int a; { int b,c; …… } char f2(int x, int y) { int a,b; …… } main() { int m,n; …… } x、y、a 、b有效范围 m、n有效范围

  42. 局部变量使用说明: • 主函数main中定义的变量只在main函数中有效。 • 不同函数中可以使用同名变量,它们互不干扰。 • 形参也是局部变量。 • 在一个函数内部,可以在复合语句中定义变量,这些变量只在该复合语句中有效。这种复合语句称为“分程序”和“程序块”。

  43. 全局变量 • 在函数之外定义的变量是外部变量,外部变量是全局变量。全局变量可以为本文件中所有函数共用。 • 全局变量的有效范围为从定义变量的位置开始直到本源文件结束。 • 设置全局变量的作用是增加函数间数据联系的渠道。

  44. 全局变量举例 int i,j; /*全局变量*/ float f1(a) int a; { int b,c; …… } float p,q; /*全局变量*/ char f2(int x, int y) { int a,b; …… } main() { int m,n; …… } 全局 变量 i、j 的作用 范围 p、q 的作用 范围

  45. 全局变量的使用说明 在程序设计中,应尽量避免使用全局变量。 • 全局变量在程序的全部执行过程中都占用存储单元,而不是仅在需要时才开辟单元。 • 如果在同一个源文件中,外部变量与局部变量同名,则在局部变量的作用域范围内外部变量不起作用。 • 使函数的可靠性和通用性降低。 • 使用全局变量过多,会降低程序的清晰性。

More Related