1 / 47

第七章 函 数

第七章 函 数. 7 -1 函数的定义与调用 7-2 外部函数和内部函数 7-3 内部变量和外部变量 7-4 变量的存储类型 7-5 函数的数据传递 7-6 数组作为函数参数 7-7 递归函数. 7. 1 函数的定义与调用. 一个源程序文件由一个或多个函数组成。 一个 C 程序由一个或多个源程序文件组成; C 程序执行从 main() 开始,在 main() 中结束; 所有 C 函数都是平行(独立)的,不能嵌套定义; 函数分类: 从用户角度: 标准函数和用户自定义函数; 从函数形式: 无参函数和有参函数;.

eyad
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. 第七章 函 数 7-1 函数的定义与调用7-2 外部函数和内部函数7-3 内部变量和外部变量7-4 变量的存储类型7-5 函数的数据传递7-6 数组作为函数参数7-7 递归函数

  2. 7. 1 函数的定义与调用 • 一个源程序文件由一个或多个函数组成。 • 一个C程序由一个或多个源程序文件组成; • C程序执行从main()开始,在main()中结束; • 所有C函数都是平行(独立)的,不能嵌套定义; • 函数分类: • 从用户角度: 标准函数和用户自定义函数; • 从函数形式: 无参函数和有参函数;

  3. 7.1.1 函数定义 函数定义的一般形式: 函数类型 函数名(类型 形式参数1,类型 形式参数2,…) {//函数体 函数内部变量说明 函数执行语句 }

  4. 无无参函数 类型标识符函数名( ) {说明部分 语句 } • 空空函数 类型标识符函数名( ) { }

  5. 例:设计函数,求1+……+n的和 Int sum(int n) { int i,s=0; for (i=1;i<=n;i++) s=s+i; return s; }

  6. 一、类型标识符——函数的返回值类型 • 函数返回值指通过函数调用得到的一个确定的值; • 函数返回值通过return语句得到。形式为: return(表达式); 一个函数可以几个return语句。 • 函数返回值的类型为定义函数时说明的类型; • C规定:定义函数时不说明类型,默认为整型; • 函数值类型与return中表达式类型不一致时,以函数值类型为准; • 函数若无return语句,不是不带回值,而是带回不确定的值;可用“void”定义“无类型”,保证不使函数带回任何值。

  7. #include <stdio.h> int abs(int x) { return x>0?x:-x; } main() { int n; scanf("%d",&n); printf("%d\n",abs(n)); }

  8. #include <stdio.h> void abs(int x) { int y=(x>0?x:-x); printf("%d\n",y); } main() { int n; scanf("%d",&n); abs(n); }

  9. 以下函数的返回值: #include <stdio.h> max(float x,float y) { return x>y? x: y ; } main() { printf("%d\n",max(2,3.5)); } 程序运行结果: 3

  10. 二、函数参数 • 形式参数: 定义函数时,函数名后面括号中变量名; • 实际参数: 调用函数时,函数名后面括号中变量名;

  11. 三、函数的调用 • 一般形式: 函数名(实际参数表) • 说明: • 实参间用逗号隔开; • 实参与形参必须一一对应; • 函数调用方式 • 函数语句:printf(“%d,%d”,a,b); • 函数表达式:c=2*max(a,b) • 函数参数: m=max(max(a,b),c);

  12. 函数参数之间的数据传递 1.调用函数时: • 给形参分配存储单元; • 将实参的值传递给形参; • 执行函数体; • 返回函数值,释放形参占用存储单元。 2.说明: • 形参只有在函数调用时才分配存储单元,调用结束释放; • 实参可以是常量、变量、表达式; • 实参与形参类型应一致; • C规定,实参与形参间为“值传递”,即单向传递。

  13. “值传递”举例 a 5 b 8 x 5 y 8 swap(int x,int y) {int t; t=x;x=y;y=t; printf(“x=%d,y=%d\n”,x,y); } main() {int a,b; a=5;b=8; swap(a,b); printf(“a=%d,b=%d”,a,b); } 调用前 调用开始时 调用结束后

  14. #include <stdio.h> long fun(int x) { int i; long f=1; for (i=2;i<=x;i++) f=f*i; return f;} void main() { int m,n; long c; do { printf("m,n:"); scanf("%d%d",&m,&n); } while (m<=n); c=fun(m)/(fun(n)*fun(m-n)); printf("c=%ld\n",c); }

  15. 编写函数,验证陈景润研究的哥德巴赫猜想:任意大偶数为两个素数之和并输出这两个素数(所谓大偶数是指6开始的偶数)。编写函数,验证陈景润研究的哥德巴赫猜想:任意大偶数为两个素数之和并输出这两个素数(所谓大偶数是指6开始的偶数)。 • 要求: • prime(int x)实现判断一个数x是否为素数, 返回值为0 或1 ,0 表示不是素数,1 表示是素数 • main()实现输入一个大偶数,并输出该大偶数对应的两个素数。

  16. include <stdio.h> #include <math.h> int prime(int x); /*函数声明*/ void main() { int n,i; for (n=1000;n<=10000;n+=2) { for (i=1;i<=n/2;i++) if (prime(i)==1 && prime(n-i)==1) { printf("%d=%d+%d\n",n,i,n-i); break; } } } int prime(int x) { int i; for (i=2;i<(int)sqrt(x);i++) if (x%i==0) return 0; return 1;}

  17. 被调函数需具备的条件 • 被调函数函数必须存在(自定义或库函数); • 若被调函数是库函数,须在文件头加 #include “~”; • 若被调函数为自定义函数, 且与主调函数在同一文件中,一般应在主调函数中对被调函数作声明, 形式为: 类型名被调函数名( 类型1 参数1, 类型2 参数2, …) 或 类型名被调函数名( 类型1, 类型2, …) 函数原型

  18. C规定,以下几种情况可不作被调函数声明: • 被调函数的定义出现在主调函数之前; • 已经在所有函数定义之前作了函数声明;

  19. 练习 • 求三个数的最小公倍数。 • 求x的y次方

  20. 函数的嵌套调用 void main() {printf(“sum=%d\n”,total(5)); } int fac(int n) {int i,s=1; for(i=1;i<=n;i++) s=s*i; return(s); } int total(int n) {int i,s=0; for(i=1;i<=n;i++) s=s+fac(n); return(s); } • 所谓嵌套调用,就是在调用一个函数的过程中,又调用另一个函数。即: 函数A中调用函数B,函数B中又调用函数C。例如:

  21. 练习: 若有以下程序 int f(int x, int y) { return (y-x)*x ; } void main() { int a=3, b=4, c=5, d; d=f( f(3, 4), f(3, 5) ) ; printf(“%:d); } 执行后输出结果是 ______ 有以下程序 char fun (char x, char y) { if (x<y) return x; return y; } void main() { int a='9', b='8', c='7'; printf(“%c” fun(fun(a, b), fun(b, c)); } 程序的执行结果是 ---------

  22. 有以下程序 void f(int x, int y) { int t; if (x<y) { t=x; x=y; y=t; } } void main() { int a=4, b=3, c=5; f(a, b); f(a, c); f(b, c); printf(“%d,%d,%d”,a,b,c } 运行结果是______________

  23. 以下程序的功能是调用函数fun计算: m=1-2+3-4…+9-10,并输出结果,请填空 。 int fun( int n ) { int m=0, f=1, i; for (i=1; i<=n; i++) { m+=i*f; f= _________ ;} return m;} main() { printf(“%d”,_________); }

  24. 请在以下程序第一行的下划线处填写适当内容,使程序能正确运行。 _________(double, double) ; void main() { double x, y; scanf(“%ld%ld”, x, y) ; printf(“%____”,max(x, y)); } double max(double a, double b) { return (a>b?a:b) ; }

  25. 以下sum函数的功能是计算下列级数之和。 S=1 + x + x2/2! + x3/3! + … xn/n! 请给函数中的各变量正确赋初值。 double sum(doudle x, int n) { int i; double a, b, s; ________________ for (i=1; i<=n; i++) { a=a*x; b=b*i; s=s+a/b; } return s; }

  26. 7.2 外部函数和内部函数 1. 外部函数 在源文件中定义的函数,可以被同一源程序的其他源文件调用,则称为外部函数。 extern 数据类型 函数名(形参定义表) { } //extern 可以省略 2. 内部函数 在源文件中定义的函数,只能在该文件内使用,则称为内部函数。 static 数据类型 函数名(形参定义表) { }

  27. 7.3 内部变量和外部变量 • 内部变量(局部变量) 在一个函数内部定义的变量。只在本函数内部有效。 • 说明: • 主函数main中定义的变量也只在main中有效; • 不同函数中定义的变量名可以同名,互不干扰; • 形式参数也是局部变量; • 可在一组复合语句中定义变量,该变量只在本复合语句中有效(分程序);

  28. #include <stdio.h> void main() { int n=2; { int n=10; printf("n=%d\n",n); } printf("n=%d\n",n); }

  29. 外部变量(全局变量) 在函数外部定义的变量。有效范围为从定义位置开始到 本源文件结束。 • 外部变量的作用:增加函数间联系的渠道。 • 外部变量的局限: • 占用存储单元; • 降低函数的通用性; • 降低函数的清晰性。 • 当外部变量与局部变量同名时: 在函数内部只有局部变量起作用。

  30. #include <stdio.h> void fun(); int n=2; /*外部变量定义*/ main() { int n=10; fun(); printf("n=%d\n",n); } void fun() { printf("n=%d\n",n); }

  31. #include <stdio.h> void fun(); main() { extern int n; /*外部变量声明*/ fun(); printf("n=%d\n",n); } int n; /*外部变量定义*/ void fun() { n=10; }

  32. 7.4 变量存储类别 • 变量分类: • 从变量作用域分:全局变量和局部变量; • 从变量生存期分:静态存储变量和动态存储变量; • 变量存储方式: • 静态存储方式:指在程序运行期间分配固定存储空间的方式; • 动态存储方式:指在程序运行期间根据需要进行动态分配存储空间的方式;

  33. Auto变量 • 格式: auto 类型 变量名; • 该变量在动态存储区动态的分配空间; • 局部变量和函数形式参数都属auto变量; • “auto”可以省略。如在函数内部定义的: auto int a,b; 等价于: int a,b; 这样变量的值在函数调用结束后自动释放。 • 如果希望变量的值在函数调用结束后仍保留,可通过指定该局部 变量为“局部静态变量”实现。

  34. Static局部静态变量 • 格式:static 类型 变量名; • 说明: • 局部静态变量在静态存储区内分配存储单元,在整个程序运行期间都不释放; • 局部静态变量赋初值在编译时只进行一次(例8-17); • 静态变量不赋初值自动赋0; • 局部静态变量在调用函数结束后仍然存在,但其他函数不能引用它(P175例8-18); • 静态存储缺点: • 占用存储空间; • 降低程序可读性。

  35. 7.6数组作为函数参数 A[i] 5 B[I] 8 x y • 数组元素作函数实参; 同变量实参,为单向“值传递” 例:

  36. 例7.19 统计成绩数组中不及格人数 #include <stdio.h> #define N 10 int fun(int x); void main() { int a[]={90,65,48,82,52,67,45,92,58,87},i,num=0; for (i=0;i<N;i++) num+=fun(a[i]); printf("num=%d\n",num); } int fun(int x) { if (x<60) return 1; else return 0; }

  37. 2. 数组名作函数参数(实参和形参均为数组名) • 要求在主调函数和被调函数中分别定义数组; • 实参数组和形参数组类型应一致; • 数组名作函数参数时,传递的时数组首地址;即实参数组和形参数组共用同一段内存单元,二者互相影响; • 形参数组可不定义大小; 实参score 形参array

  38. 例7.20 计算成绩数组的平均分 float fun (int b[],int n) { float s=0; int i; for (i=0;i<n;i++) s+=b[i]; return s/n; }

  39. #include <stdio.h> #define N 10 float fun(int b[],int n); void main() { int a[]={90,65,48,82,52,67,45,92,58,87}; float avg; avg=fun(a,N); printf("avg=%g\n",avg); }

  40. 例7.21 分析程序结果 #include <stdio.h> #define N 10 void fun(int b[],int n) { int i,temp; for (i=0;i<n/2;i++) { temp=b[i]; b[i]=b[n-i-1]; b[n-i-1]=temp; } }

  41. void main() { int a[N],i; for (i=0;i<N;i++) a[i]=2*i; for (i=0;i<N;i++) printf("%d ",a[i]); printf("\n"); fun(a,N); for (i=0;i<N;i++) printf("%d ",a[i]); printf("\n"); }

  42. 7.7 递归函数 • 递归调用指一个函数又直接或间接调用它本身。形如: • 直接递归:A->A • 间接递归:A->B->A • 年龄问题: • age(n)=age(n-1)+2 (n>1) • age(n)=10 (n=1) • 递归函数: int age(int n) {int c; if (n==1) c=10; else c=age(n-1)+2; return(c); }

  43. 递归函数 • age(5)=age(4)+2 • =age(3)+2 • =age(2)+2 • =age(1)+2 • =10+2 递推 回推 • 递归调用过程: • 回推 • 递推 • 递归函数的条件: • 递推公式 age(n)=age(n-1)+2 (n>1) • 结束条件 age(n)=10 (n=1)

  44. 例: 求n! • n!=1 (n=0或1) • n!=n*(n-1)! (n>1) long factl(long m) { if(m==1) return (1); else return(m * factl(m-1)); }

  45. /*文件名:exam7_22.cpp*/ #include <stdio.h> int fun(int i) { if (i==1) return i; else return i*fun(i-1); } void main() { printf("%d\n",fun(4)); }

  46. /*文件名:exam7_23.cpp*/ #include <stdio.h> int gcd(int x,int y) { if (y<=x && x%y==0) return y; else if (y>x) return gcd(y,x); else return gcd(y,x%y); } void main() { int a,b; printf("输入两个正整数:"); scanf("%d,%d",&a,&b); printf("最大公因子为:%d\n",gcd(a,b)); }

  47. 例8-9:Hanoi 塔问题。 移n 个盘子从A柱到C柱借助B柱。 • 可分解为以下三步: • 移n-1个盘子从A柱到B柱借助C柱 • 移1个盘子从A柱到C柱 • 移n-1个盘子从B柱到C柱借助A柱

More Related