1 / 75

程序结构概念 : 1 )较大的程序应分为 若干个程序模块 ; 2 )每个模块实现单一的特定功能; 3 )由主函数开始执行,主函数调用子函数; 4 )子函数之间可以互相调用。

第 8 章 函数. 8.1 概述. 程序结构概念 : 1 )较大的程序应分为 若干个程序模块 ; 2 )每个模块实现单一的特定功能; 3 )由主函数开始执行,主函数调用子函数; 4 )子函数之间可以互相调用。. 说明 :. 1. 一个源文件可由一个或多个函数组成; 2. 一个 源文件 是一个 编译单位 ; 3. 一个 C 程序 由一个或多个 源文件 组成。 4. 从 main() 开始,调用其它函数后, 回到 main() 结束 ; 5. 不能嵌套定义,但可互相调用 。 6. 分类 :

dakota
Download Presentation

程序结构概念 : 1 )较大的程序应分为 若干个程序模块 ; 2 )每个模块实现单一的特定功能; 3 )由主函数开始执行,主函数调用子函数; 4 )子函数之间可以互相调用。

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. 第8章 函数 8.1 概述 程序结构概念 : 1)较大的程序应分为若干个程序模块 ; 2)每个模块实现单一的特定功能; 3)由主函数开始执行,主函数调用子函数; 4)子函数之间可以互相调用。

  2. 说明 : 1. 一个源文件可由一个或多个函数组成; 2. 一个源文件是一个编译单位; 3. 一个C 程序由一个或多个源文件组成。 4. 从 main() 开始,调用其它函数后, 回到 main() 结束 ; 5. 不能嵌套定义,但可互相调用 。 6. 分类 : 1) 标准函数 和 用户自定义函数 ; 2) 无参函数 和 有参函数 。

  3. 8.2 函数定义 1. 无参函数的定义 形式:类型标识符 函数名( ) {说明部分 语句 } 例如: main( ) { int a=5,b=9 ; printf(" %d\n " , a*b*b ); } 说明:若不带回函数值,类型标识符也可以不写,无参函数一般用于完成指定的一组操作。

  4. 2.有参函数的定义 形式:类型标识符 函数名(形式参数表列) 形式参数说明 {说明部分 语句} 如:int max( x, y ) int x , y; { int z ; z=x>y ? x : y ; return ( z ) ; } 空函数定义形式: 类形标识符 函数名( ) { } 作用:备以后扩充。

  5. 8.3 函数参数和函数的值 8.3.1 形式参数和实际参数 形式参数 : 定义函数时,括号中说明的变量名 ; 实际参数 : 调用函数时,括号中给定的表达式 。

  6. main( ) main( ) { int a,b,c; { int a,b,c; scanf ("%d,%d",&a,&b); scanf ("%d,%d",&a,&b); c=max( a ,b ); 函数调用 c=max( a ,b ); printf ("max is %d\n",c); printf ("max is %d\n",c); } int max( x, y ) max( x, y ) 形参说明 int x,y; int x,y; {int z; { int z; z=x>y?x:y; z=x>y?x:y; return (z); return (z); }

  7. 说明: 1. 定义函数时,形参不占内存单元 ; 调用函数时,形参才分配内存单元 ; 调用结束后,形参所占内存单元被释放。 2. 实参可以是常量、变量或表达式,但必须有确切的值。 3. 定义函数,必须指明形参类型。 4. 实参与形参类型一致。 5. 实参变量对形参变量的数据传递是“值传递 ”,即单向传递。 6. 可在“形参表列”中说明形参类型。 int max( int x , int y ) { 函数体 }

  8. 8.3.2 函数的返回值 说明 : 1. 通过 return 语句获得返回值 ; 2. 定义函数时指定函数返回值的类型;不加类型说明 的,按整型处理。 3. 函数值的类型和 return 语句中表达式的值不一 致时,以函数类型为准。 4. 被调用函数中没有 return 语句时,带回一个不 确定的值。 5. 为了明确表示“不带回值”,可以用“ void ” 定 义 “ 无类型 ”。

  9. 看下面例子: main() {float a,b; int c; scanf(“%f,%f”,&a,&b); c=max(a,b); printf(“Max is %d\n”,c); } max(float x,float y) {float z; z=x>y?x:y; return (z)} 运行结果: 1.5,2.5 Max is 2

  10. 8. 4 函数的调用 8.4.1 函数调用的一般形式 函数名(实参表列) 说明 : 1.无参函数,括号不能省 ; 2.实参表列中,各实参与形参在 个数、顺序、 类型上一一对应,参数间用逗号分隔。 注意:计算实参时的次序不同。为了提高程序的通用性,一般都写清楚。

  11. int f(int a,int b) { int c; if (a>b) c=1; else if (a= =b) c=0; else c=-1; return (c); } 函数调用发生 函数调用结束 i 5 j 9 i 5 j 9 a,b所占的存储单元被释放 b 9 a 5 main( ) {int i,j,p; scanf("%d%d",&i,&j); p=f(i,j); printf ("%d",p); }

  12. 8.4.2 函数调用的方式 调用函数的方式有三种: 函数语句、函数表达式、函数参数。 如:printf("******"); m=max(a,b)*20; printf("%d",max(a,b));

  13. 8.4.3 对被调用函数的声明和函数原型 1.被调函数必须存在; 2.用#include命令包含有关库函数; 3.被调用函数一般应在主调函数前定义,这样在主调函数中可以不对调用函数类型进行声明。否则在主调函数中必须对调用函数类型进行声明(整型除外); 4.如果在文件开头,已声明了被调函数类型,则主调函数中不必再作类型声明。

  14. 被调用函数声明 例 1: 函数声明的作用是把函数名及函数类型、形参个数及类型通知编译系统,以便在调用该函数时系统按此进行对照检查。 main( ) {float add( ); float a,b,c; ..... } float add(x,y) float x,y; {…} float add(float,float); float add(float x,float y ); 函数定义 函数定义是指对函数功能的确立,包括指定函数名、函数值类型、形参个数及类型、函数体等。它是一个完整、独立的程序单位。

  15. 例 2: float add(x,y) float x,y; { float z; z=x+y; return(z); } main( ) { float a,b,c; scanf("%f,%f",&a,&b); c=add(a,b); printf("%f\n",c); } 在主调函数前定义

  16. char let( ); float f( ); int max( ); 例 3: 已在文件 开头声明 main( ) {......} char let(c1,c2) char c1,c2; {......} float f(x,y) float x,y; {......} int max(j,k) float j,k; {......} 定义 let 函数 定义f函数 定义max函数

  17. main( ) { float a; int y(); scanf ("%f",&a); printf ("%d", y(a)); } 1 x>0 y= 0 x=0 -1 x<0 程序举例: float x; 例1:求下列函数的值 scanf("%f",&x); y(x) y(a) int y(float x) { int z; if (x>0) z=1; else if (x<0) z=-1; else z=0; return(z); } a 5 x 5 x

  18. 例 2.求5!、16!和27! float jiec(n) int n; { float y=1; int i; for (i=1;i<=n;i++) y=y*i; return (y); } main( ) { float a,b,c; a=jiec(5); b=jiec(16); c=jiec(27); printf ("%f,%f,%f\n",a,b,c); }

  19. 3.编写函数,判定某数字是否在某正整数中,若在,打印 TRUE,否则打印 FALSE,输出结果在主函数中完成。 main( ) {int m,n; /*判断数字n是否在数m中/ int among(int m,int n); scanf("%d %d",&m,&n); if(among(m,n)) printf("TRUE"); else printf("FALSE"); }

  20. int among(m,n) int m,n; { int k,z=0; do {k=m%10; if (n==k) {z=1; break;} m=m/10; }while(m!=0); return(z); }

  21. 例 4.统计 400~499 这些数中 4 这个数字出现的次数,判一个数有几个数字4,用函数实现 。 num(x) int x; { int y,k=0; while (x!=0) {y=x%10; if(y==4) k++; x=x/10; } return(k); } main() {int i,k=0; for(i=400;i<=499;i++) k=k+num(i); printf ("number=%d\n",k); }

  22. 例 5. 找出1000之内的所有“完数”,判一个数是否为完数,用函数实现 。 wan(x) int x; { int i,k=0; for (i=1;i<=x/2;i++) if (x%i==0) k=k+i; if (k==x) return (1); else return (0); } main( ) { int i; for (i=1;i<1000;i++) if (wan(i)) printf ("%5d",i); printf ("\n"); }

  23. 例 6.求图形的面积 。 #include "math.h" float area1(a,b,c) float a,b,c; { float s,p; p=(a+b+c)/2; s=sqrt(p*(p-a)*(p-b)*(p-c)); return(s); } float area2(d) float d; { float s; s=3.14159*(d/2)*(d/2)/2; return(s); }

  24. main( ) { float a,b,c,s; scanf ("%f%f%f",&a,&b,&c); s=area1(a,b,c)+area2(a)+area2(b)+area2(c); printf ("%f\n",s); }

  25. 8.5 函数的嵌套调用 不能嵌套定义函数,可以嵌套调用函数 。 main 函数 { 调用 a 函数 } a 函数 { 调用 b 函数 return(); } b 函数 { return(); }

  26. .写两个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果 。 int lcm(a,b) int a,b; { int r; r=gcd(a,b); return(a*b/r); } int gcd(a,b) int a,b; {int r; do {r=a%b; a=b; b=r;} while (r!=0); return (a); } main( ) { int x,y; scanf ("%d%d",&x,&y); printf ("%d\n",gcd(x,y)); printf ("%d\n",lcm(x,y)); }

  27. 8.6 函数的递归调用 在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用 。 递归问题的特点 : 1 . 把一个问题转化为一个新问题,新问题与原问题解法相同 ,只是所处理的对象有所不同,但它们只是有规律的递增或递减 。 2 . 必须有某个终止递归的条件。

  28. 例 1. 用递归法求 n! 1 (n=1或n=0) n!= n*(n-1)! (n>1) main( ) { int n; float fac( ); float y; scanf ("%d",&n); if (n<0) printf ("n<0,data error\n"); else { y=fac(n); printf ("%d!=%15.0f",n,y); } } n!=n*(n-1)! (n-1)!=(n-1)*(n-2)! ... 2!=2*1! 1!=1

  29. float fac(n) int n; { float f; if (n==1||n==0) f=1; else f=fac(n-1)*n; return(f); } 以n=4为例,执行过程如下: fac(n) { ... f=fac(1)*2; return (f); } fac(n) { ... f=1; return (f); } fac(n) { ... f=fac(2)*3; return (f); } main( ) { ... y=fac(4); ... } fac(n) { ... f=fac(3)*4; return(f); } 2 1 24 6

  30. 1 (n=0) xn = x (n=1) x*xn-1 (n>1) 例 3.求xn (n>0) float f(int x,int n) { float z; if(n==0) z=1; else if (n==1) z=x; else z=x*f(x,n-1); return z; } main( ) { int x,n; float f( ); scanf ("%d%d",&x,&n); printf ("%d %d %f\n",x,n,f(x,n)); }

  31. f(5,4) float f(x,n) int x,n; { float z; if (n==0) z=1; else if (n==1) z=x; else z=x*f(x,n-1); return z; } float f(x,n) int x,n; { float z; if (n==0) z=1; else if (n==1) z=x; else z=x*f(x,n-1); return z; } 5,3 5,1 float f(x,n) int x,n; { float z; if (n==0) z=1; else if (n==1) z=x; else z=x*f(x,n-1); return z; } float f(x,n) int x,n; { float z; if (n==0) z=1; else if (n==1) z=x; else z=x*f(x,n-1); return z; } z=5; 5,2

  32. 4.用递归方法求N阶勒让德多项式的值,递归公式 为 : 1 (n=0) pn(x)= x (n=1) (( 2n-1) · x · p n-1(x)-(n-1) · p n-2(x)) /n (n>1)

  33. main( ) { float pn(float,int), x,lyd; int n; scanf ("%d %f",&n,&x); lyd=pn(x,n); printf ("pn=%f\n",lyd); } float pn(x,n) float x; int n; { float temp; if (n==0) temp=1; else if (n==1) temp=x; else temp=((2*n-1)*x*pn(x,n-1)-(n-1)*pn(x,n-2))/n; return (temp); }

  34. 8.7 数组作为函数参数 1、 数组元素作函数实参 对应的形参为简单变量。 int sushu(x) int x; {int i,k=1; if(x==1) k=0 for(i=2;i<=x/2;i++) if(x%i==0) k=0; return(k); } 例 1:求正整数数组 a[10]中的素数. main( ) { int a[10],i; for(i=0;i<10;i++) scanf("%d",&a[i]); for(i=0;i<10;i++) if(sushu(a[i])) printf("%5d",a[i]); }

  35. 例2:求正整数数组a[4][4]中的素数. main( ) { int a[4][4],i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) {scanf("%d",&a[i][j]); if(sushu(a[i][j])) printf("%5d",a[i][j]);} printf("\n"); } main( ) { int a[4][4],i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) scanf("%d",&a[i][j]); for(i=0;i<4;i++) for(j=0;j<4;j++) if(sushu(a[i][j])) printf("%5d",a[i][j]);} printf("\n"); } int sushu(x) int x; {int i,k=1; if(x==1) k=0; for(i=2;i<=x/2;i++) if(x%i==0) k=0; return(k); }

  36. a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] b[0] b[1] b[2] b[3] b[4] b[5] b[6] b[7] b[8] b[9] 2、数组名可作函数实参 对应的形参为数组名 说明 : 1. 数组名作函数参数,应在主调函数和被调函数中分别定义数组 ; 2. 实参数组与形参数组类型应一致 ; 3. 实参数组与形参数组大小可以一致也可以不一致 。形参数组可以不指定大小。 4. 数组名作函数参数时,是 “ 地址传送 ”。 a b

  37. 例3: 数组 score 存放 10 个学生成绩,求平均成绩 。 main( ) { float score[10],aver,a; float average(float); int i; for (i=0;i<10;i++) { scanf ("%f",&a); score[i]=a;} aver=average(score); printf (" %5.2f",aver); } float average(array) float array[10]; { int i; float aver,sum=0; for (i=0;i<10;i++) sum=sum+array[i]; aver=sum/10; return(aver); } score array

  38. 例4 :用选择法对数组中10个整数按升序排序 。 12 3 45 -7 6 17 4 9 2 77 -7 2 3 4 6 9 12 17 45 77 main() { int a[10],i; void sort( ); for (i=0;i<10;i++) scanf ("%d",&a[i]); sort(a,10); for (i=0;i<10;i++) printf ("%5d",a[i]); printf ("\n"); } void sort(array,n) int array[ ],n; { int i,j,k,t; for (i=0;i<n-1;i++) { k=i; for (j=i+1;j<n;j++) if (array[j]<array[k]) k=j; t=array[k]; array[k]=array[i]; array[i]=t; } } a array

  39. 例5 :用冒泡法对数组中10个整数按升序排序 。 冒泡法的思路是:将相邻两个数比较,将小的调到前头. 3 1 5 3 第二轮: (j=1) 依此类推经过 j 轮比较 第一轮: (j=0) 1 3 5 3 1 5 5 1 5 每轮比较n-j-1次 6 6 0 比较9次 比较8次 8 6 0 6 6 0 8 for(j=0;j<n-1;j++) -2 8 8 for(i=0;i<n-j-1;i++) 0 8 -2 8 if(a[i]>a[i+1]) -2 9 9 { t=a[i]; a[i]=a[i+1]; a[i+1]=t; } 9 9 4 -2 9 4 9 9 21 21 4 4 21 21

  40. 5 3 1 8 6 0 9 -2 21 4 -2 0 1 3 4 5 6 8 9 21 main() { int array[10],i; void sort( ); for (i=0;i<10;i++) scanf ("%d",&array[i]); sort(array,10); for (i=0;i<10;i++) printf ("%5d",array[i]); printf ("\n"); } void sort(a,n) int a [ ],n; { int i,j, t; for (j=0;j<n-1;j++) for (i=0;i<n-j-1;i++) if (a[i]>a[i+1]) { t=a[i]; a[i]=a[i+1]; a[i+1]=t; } } array a

  41. 11 13 10 87 43 41 79 77 76 51 53 63 33 36 47 例 6.产生15个[10,90]上的数放入a数组中,找出其中 的素数放入b数组,并求b数组中元素的和 。 要求: 1. 求素数用函数sushu( )完成 2. 求素数的和用函数sum( )完成 a b 11 13 43 41 79 53 47 k=0 1 2 3 4 5 6 7

  42. 方法一: #include "stdlib.h" main() {int a[15],b[15]; int i,m=0; for(i=0;i<15;i++) { a[i]=random(81)+10; if(sushu(a[i])==1) {b[m]=a[i]; m++;} } printf("the array A is:\n"); for(i=0;i<15;i++) printf("%5d",a[i]); printf("\n"); printf("the array B is:\n"); for(i=0;i<m;i++) printf("%5d",b[i]); printf("\n"); printf("\nthe sum of array B is:%d\n",sum(b,m)); }

  43. sushu(int k) {int n,x; x=1; if(k==1)x=0; for(n=2;n<k/2;n++) if(k%n==0) x=0; return(x); } int sum(b,n) int b[ ],n; {int i,s=0; for(i=0;i<n;i++) s=s+b[i]; return(s); }

  44. 方法二: #include ”time.h" #include "stdlib.h" main() {int a[15],b[15],i,m; randomize(); for(i=0;i<15;i++) a[i]=random(81)+10; m=sushu(a,b); for(i=0;i<m;i++) printf("%4d",b[i]); printf("\n"); printf("sum=%d\n", sum(b,m)); }

  45. int sushu(a,b) int a[ ],b[ ]; { int i,j,k=0; for(i=0;i<15;i++) {for(j=2;j<=a[i]-1;j++) if(a[i]%j==0) break; if(j>a[i]-1) {b[k]=a[i];k++;} } return(k); } int sum(b,n) int b[ ],n; {int i,s=0; for(i=0;i<n;i++) s=s+b[i]; return(s); }

  46. 3、用多维数组作函数参数 1. 用多维数组元素作函数实参,这点与前述相同。 2. 用多维数组名作函数实参和形参,在被调用函数中对形参数组定义时可以指定每一维的大小, 也可以省略第一维的大小说明。 如:int a[3][10]; int a[][10]; 二者都合法完全等价。但是不能把第二维以及其它高维的大小说明省略。

  47. 例8.有一个3×4的矩阵,求其中的最大元素 。 main( ) { static int a[3][4]={{1,3,5,7},{2,4,6,8},{15,17,34,12}}; printf ("max=%d\n",max_value(a)); } max_value(array) int array[12]; { int i,max; max=array[0]; for(i=0;i<12;i++) if(array[i]>max) max=array[i]; return(max); } max_value(array) int array[ ][4]; { int i,j,k,max; max=array[0][0]; for (i=0;i<3;i++) for (j=0;j<4;j++) if (array[i][j]>max) max=array[i][j]; return(max); }

  48. 例9: 求 3×3 矩阵转置 23 34 7 23 34 7 2 56 17 21 4 36 2 56 17 21 4 36 交换a[i][j]与a[j][i]的值

  49. void turn(array) int array[][3]; { int i,j,k; for (i=0;i<3;i++) for (j=0;j<i;j++) { k=array[i][j]; array[i][j]=array[j][i]; array[j][i]=k; } } main() { static int a[3][3]={{1,3,5}, {2,4,6},{15,17,34}}; int i,j; turn(a); for (i=0;i<3;i++) { for (j=0;j<3;j++) printf ("%5d",a[i][j]); printf ("\n"); } }

More Related