290 likes | 464 Views
第六章 函数. 主要内容. C 程序的模块化结构 函数的定义 函数的参数与返回值 函数的调用 函数的嵌套调用 数组作为函数参数. 函数概念. 基本思想:将一个大的程序按功能分割成一些小模块, 函数对应于程序的模块,一般 先定义后使用 。. ATM 自动查询系统. 读取银行卡信息. 取款. 查询帐户. 转帐. 修改密码. 人民币帐户. 人民币帐户. 卡内转帐. 港元帐户. 其它帐户. 港元帐户. 其它帐户. 美元帐户. 美元帐户. 基本思想:将一个大的程序按功能分割成一些小模块, 函数对应于程序的模块,一般 先定义后使用 。.
E N D
主要内容 • C程序的模块化结构 • 函数的定义 • 函数的参数与返回值 • 函数的调用 • 函数的嵌套调用 • 数组作为函数参数
函数概念 • 基本思想:将一个大的程序按功能分割成一些小模块,函数对应于程序的模块,一般先定义后使用。 ATM自动查询系统 读取银行卡信息 取款 查询帐户 转帐 修改密码 人民币帐户 人民币帐户 卡内转帐 港元帐户 其它帐户 港元帐户 其它帐户 美元帐户 美元帐户
基本思想:将一个大的程序按功能分割成一些小模块,函数对应于程序的模块,一般先定义后使用。基本思想:将一个大的程序按功能分割成一些小模块,函数对应于程序的模块,一般先定义后使用。
C是模块化程序设计语言 C程序结构 • C是函数式语言 • 必须有且只能有一个名为main的主函数 • C程序的执行总是从main函数开始,在main中结束 • 函数不能嵌套定义,可以嵌套调用
fun11() { … retrun; } fun1() { … fun11(); … retrun; } Void main() { … fun1(); … fun2(); … } fun21() { … retrun; } fun2() { … fun21(); … fun22(); … retrun; } fun22() { … retrun; }
例: 打印图形: ****************** How do you do! ****************** ****************** void printstar() { printf(“**************\n” ); } main() { printstar(); printf(“ How do you do!\n”): printstar(): printstar(): } 编程: main() { printf(“****************\n”); printf(“How do you do! \n”); printf(“******************\n”); printf(“******************\n”); } 三个语句一样,可编写成函数:
函数分类 • 从用户角度 • 标准函数(库函数):由系统提供,如printf(),scanf(),putchar,getchar • 用户自定义函数 • 从函数形式 • 无参函数 • 有参函数 使用库函数应注意: 1、函数功能 2、函数参数的数目和顺序,及各参数意义和类型 3、函数返回值意义和类型 4、需要使用的包含文件: #include <*.h>
例 有参函数(现代风格) float max(float x, y) {float m; if (x>y) m=x; else m=y; return(m); } 例 空函数 dummy( ) { } 函数体为空 6-1 函数的定义 合法标识符 • 一般格式 现代风格: 函数属性 函数类型 函数名(形参类型说明表) { 说明部分 语句部分 } 像普通变量一样定义,在函数中也像普通变量一样使用 内部函数:static 外部函数:extern 函数体 例 有参函数(现代风格) float max(float x, float y) {float m; if (x>y) m=x; else m=y; return(m); } 例 无参函数 printstar( ) { printf(“**********\n”); } 或 printstar(void ) { printf(“**********\n”); }
函数传统风格和例子 函数类型 函数名(形参表) 形参类型说明 { 说明部分 语句部分 } 传统风格: 例 有参函数(传统风格) float max(x,y) float x,y; { float z; z=x>y?x:y; return(z); }
6-3 函数的调用 • 调用形式 函数名(实参表);或者函数名(); 说明: 1、调用的是有参函数,则要求 • 实参与形参个数相等,类型一致,按顺序一一对应 • 实参表求值顺序,因系统而定(Turbo C 自右向左) • 实参可以是表达式。如果是表达式实参,先计算表达式的值再将数据传递给形参。 2、如果调用的是无参函数,则无实参表,此时小括号不能省略。
6-2 函数的返回值 例 无返回值函数 void swap(int x,int y ) { int temp; temp=x; x=y; y=temp; } 例 有参函数(现代风格) float max(float x, float y) {float m; if (x>y) m=x; else m=y; return(m); } • 返回语句 • 形式: return(表达式); 或return 表达式; 或return; • 功能:使程序控制从被调用函数返回到调用函数中,同时把返值带给调用函数 • 说明: • 函数中可有多个return语句 • 若无return语句,遇}时,自动返回调用函数 • 若函数类型与return语句中表达式值的类型不一致,按前者为准,自动转换------函数调用转换 • void型函数,可以不用return
b x a y a b 10 10 20 10 20 20 t t 10 例子:6—4 #include <stdio.h> int swap(int a,int b); main() { int x=10,y=20; printf("(1)x=%d y=%d\n",x,y); swap(x,y); printf("(4)x=%d y=%d\n",x,y); } int swap(int a,int b) { int t; printf("(2)a=%d b=%d\n",a,b); t=a;a=b;b=t; printf("(3)a=%d b=%d\n",a,b); }
t 7.0 7.0 2.0 2.0 3.0 3.0 x a y b c z m 函数调用 被调用函数 #include <stdio.h> float max(x,y,z) float x,y,z; { float t; t=x; if(y>t) t=y; if(z>t) t=z; return t; } main() { float m,a=3.0,b=7.0,c=2.0; m=max(a,b,c); printf("%f",m); } a b c max(a,b,c) <>m x y z t 主调用函数, 值与return后的参数一样
函数调用方式 • 表达式方式,调用后返回一个值参加运算:y=max(a,b)+max(c,d) • 语句方式: max(a,b); • 函数调用作为另外一个函数的参数。 • 如:m=max(max(a,b),max(c,d)) #include <stdio.h> float max(float x,float y) { float t; t=x; if (y>t) t=y; return t; } main() { float y,a=3.0,b=7.0,c=2.0; y=max(a,b)+max(c,d); printf("%f",y); }
被调函数的说明 • 被调函数返回类型 被调函数名(形参表); • 一般函数要在主调函数前说明,如果在主调函数前定义则不用说明。 #include <stdio.h> float max(float x,float y) { float t; t=x; if (y>t) t=y; return t; } main() { float y,a=3.0,b=7.0,c=2.0; y=max(a,b)+max(c,d); printf("%f",y); } #include <stdio.h> float max(float x,float y); main() { float y,a=3.0,b=7.0,c=2.0; y=max(a,b)+max(c,d); printf("%f",y); } float max(float x,float y) { float t; t=x; if (y>t) t=y; return t; }
函数的参数 • 参数传递分为传值与传地址两种方式。 • 传值方式将对应表达式的值传给相应的实参,实参与形参占有不同的存储单元,形参的改变不会影响实参。 • 传地址方式将实参的地址传递给形参,实参与形参共享存储单元,这时形参的改变引起实参的改变。一般用指针与数组完成,用以带回多个值。
t 7.0 7.0 2.0 2.0 3.0 3.0 x a y b c z m 函数调用 被调用函数 • 例子:6—3 #include <stdio.h> float max(x,y,z) float x,y,z; { float t; t=x; if(y>t) t=y; if(z>t) t=z; return t; } main() { float m,a=3.0,b=7.0,c=2.0; m=max(a,b,c); printf("%f",m); } a b c max(a,b,c) <>m x y z t 主调用函数, 值与return后的参数一样
b x a y a b 10 10 20 10 20 20 t t 10 例子:6—4 #include <stdio.h> int swap(int a,int b); main() { int x=10,y=20; printf("(1)x=%d y=%d\n",x,y); swap(x,y); printf("(4)x=%d y=%d\n",x,y); } int swap(int a,int b) { int t; printf("(2)a=%d b=%d\n",a,b); t=a;a=b;b=t; printf("(3)a=%d b=%d\n",a,b); }
x y x y 10 20 20 10 a b t t 10 例子:6—4 #include <stdio.h> int swap(int* a,int* b); main() { int x=10,y=20; printf("(1)x=%d y=%d\n",x,y); swap(&x,&y); printf("(4)x=%d y=%d\n",x,y); } int swap(int* a,int* b) { int t; printf("(2)a=%d b=%d\n",*a,*b); t=*a;*a=*b;*b=t; printf("(3)a=%d b=%d\n",*a,*b); }
6-6 只能被1和它本身整除的数为素数。 int pf(n) { int i; int flag; flag=1; for(i=2;i<=n/2;i++) if(n%i==0) {flag=0;break;} return (flag); } main() { int i; int count=0; for(i=2;i<=100;i++) if(pf(i)==1) { printf("%6d",i); count++; if(count%5==0) printf("\n"); } }
函数的嵌套调用 函数的嵌套调用是指,在执行被调用函数时,被调用函数又调用了其它函数,其关系可表示如图所示。C规定:函数定义不可嵌套,但可以嵌套调用函数。
f( ) f1( ) f2( ) int f2(int t) { int a,c; …… c=f1(a); ……. return(3+c); } int f1(int x) { int y,z; …… z=f2(y); ……. return(2*z); } 调f 调f2 调f1 函数的递归调用 • 定义:函数直接或间接的调用自身叫函数的递归调用。 int f(int x) { int y,z; …… z=f(y); ……. return(2*z); } • 说明 • C编译系统对递归函数的自调用次数没有限制 • 每调用函数一次,在内存堆栈区分配空间,用于存放函数变量、返回值等信息,所以递归次数过多,可能引起堆栈溢出
分析:例子6——9 • 第5个人年龄 • 第4个人年龄+2 转化为:age(n)=age(n-1)+2 18 • 第3个人年龄+2 16 • 第2个人年龄+2 14 • 第1个人年龄+2 12 • 第1个人年龄:10 终止:age(1)=10
age(5)=18 age(5)=age(4)+2 age(4)=16 age(4)=age(3)+2 age(3)=14 age(3)=age(2)+2 age(2)=12 age(2)=age(1)+2 age(1)=10
例子6——9 age(n) int n; { int a; if(n==1) a=10; else a=age(n-1)+2; return a; } main() {printf("the five pepole's age=%d\n",age(5));}
函数与数组 • 数组元素作函数实参——值传递 • 数组名作函数参数——地址传递 在主调函数与被调函数分别定义数组,且类型应一致 形参数组大小(多维数组第一维)可不指定 形参数组名是地址变量
0 1 2 3 4 5 6 7 8 9 s 49 a 9 例子6—13 arrin (int* a) arrin (int a[ ]) arrin (int a[M]) #define M 10 void arrout(int*,int); int arrin(int*); main() {int s[M],k=0; k=arrin(s); arrout(s,k);} arrin(int* a) {int i,x=0; i=0; scanf("%d",&x); while(x>=0) {*(a+i)=x;i++;scanf("%d",&x);} return i;} void arrout(int* a,int n) { int i; for(i=0;i<n;i++) printf(((i+1)%5==0)?"%4d\n":"%4d",*(a+i)); printf("\n"); } i=0