《C语言第6章函数》由会员分享,可在线阅读,更多相关《C语言第6章函数(48页珍藏版)》请在金锄头文库上搜索。
1、7.1 C 7.1 C 7.1 C 7.1 C 程序的模块结构程序的模块结构程序的模块结构程序的模块结构2 2 2 27.2 C 7.2 C 7.2 C 7.2 C 函数的定义函数的定义函数的定义函数的定义5 5 5 57.3 C 7.3 C 7.3 C 7.3 C 函数的调用函数的调用函数的调用函数的调用.13.13.13.137.4 7.4 7.4 7.4 函数间数据传递方式一函数间数据传递方式一函数间数据传递方式一函数间数据传递方式一 哑实结合哑实结合哑实结合哑实结合.22.22.22.227.5 7.5 7.5 7.5 函数间数据传递方式二函数间数据传递方式二函数间数据传递方式二函数间
2、数据传递方式二 函数返回值函数返回值函数返回值函数返回值.37.37.37.377.6 7.6 7.6 7.6 函数间数据传递方式三函数间数据传递方式三函数间数据传递方式三函数间数据传递方式三 全局变量全局变量全局变量全局变量 .404040407.77.77.77.7函数的嵌套调用和递归调用函数的嵌套调用和递归调用函数的嵌套调用和递归调用函数的嵌套调用和递归调用.42.42.42.42目目录录1上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出7.17.1 C C程序的模块结构程序的模块结构 一个一个 C C 程序可由一个主函数(即程
3、序可由一个主函数(即 mainmain函数)和若干子函数)和若干子函数组成。下面给出一个程序中函数之间调用关系示意图:函数组成。下面给出一个程序中函数之间调用关系示意图:main( )abcdefghehig2上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出主调函数:主调函数:调用其它函数的函数。调用其它函数的函数。被调函数:被调函数:被其它函数调用的函数。被其它函数调用的函数。从用户使用角度来看,函数可分为两类:从用户使用角度来看,函数可分为两类: (1 1)标准库函数:由)标准库函数:由 C C 编译系统提供,存放在不同编译系统提
4、供,存放在不同的标题文件中。的标题文件中。 (2 2)用户自定义函数:用户程序设计时,根据需要)用户自定义函数:用户程序设计时,根据需要自己定义的。自己定义的。 下面先举一个函数调用的例子。下面先举一个函数调用的例子。3上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出例例 # # include “include “stdiostdio.h”.h”main( )main( ) printstar printstar( );( );/*/* 调用调用printstarprintstar( )( )函数函数 * */ / print-me
5、ssage( );print-message( );/* /* 调用调用print-messageprint-message函数函数 * */ / printstarprintstar( ); ( ); /*/* 调用调用printstarprintstar( )( )函数函数 * */ / printstar( )printstar( )/* /* 定义定义printstar( )printstar( )函数函数 * */ / printf printf(“*(“*n”);n”); print_message( )print_message( )/*/*定义定义print-message(
6、)print-message( )函数函数 * */ / printf printf(“ How do you do!n”);(“ How do you do!n”); 运行结果:运行结果:* How do you do!How do you do!*4上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出7.2 7.2 C C 函数的定义函数的定义 用户自定义函数有两种:用户自定义函数有两种:主函数(函数名为主函数(函数名为 mainmain):):系统定义的。系统定义的。子函数:用户自己定义的。子函数:用户自己定义的。C C 函数定义一
7、般格式有两种:函数定义一般格式有两种:(1 1)传统格式:又称)传统格式:又称 K&R K&R 格式。其一般定义形式为:格式。其一般定义形式为: 存储类型存储类型 数据类型数据类型 函数名(形式参数名表)函数名(形式参数名表)形式参数类型说明;形式参数类型说明; 函数体函数体 (2 2)现代格式:又称)现代格式:又称 ANSiANSi 格式。其一般定义形式为:格式。其一般定义形式为: 存储类型存储类型 数据类型数据类型 函数上名(形式参数表)函数上名(形式参数表) 函数体函数体 5上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出例如,
8、例如,int max(x,y)int max(x,y)int x,y;int x,y;/* /* 形式参数的类型说明形式参数的类型说明 */ */ int z;int z; if (xy) if (xy)z=x;z=x; else elsez=y;z=y; return (z); return (z); 6上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出也可以定义成:也可以定义成:int max(int x,int y)int max(int x,int y) int z; int z; if (xy) if (xy)z=x;z=x;
9、 else elsez=y;z=y; return (z); return (z); 通过上面的例子,可以看出函数定义应明确以下几点:通过上面的例子,可以看出函数定义应明确以下几点:(1 1)函数名)函数名 函数名是编译系统识别函数的依据,函数名与其后圆括号之间不函数名是编译系统识别函数的依据,函数名与其后圆括号之间不能有空格。能有空格。7上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出(2 2)函数的形式参数(也称形参、虚参或哑元)函数的形式参数(也称形参、虚参或哑元) 形式参数是函数被调用时,将从主调函数得到具体的值。如果函形式参
10、数是函数被调用时,将从主调函数得到具体的值。如果函数被调用时,不需要从主调函数取得任何值,则定义时可以不带参数。数被调用时,不需要从主调函数取得任何值,则定义时可以不带参数。 例如:例如:int printstarint printstar(void)(void) printf(“* printf(“*n”);n”); 也可以写成:也可以写成:int printstarint printstar( )( ) printf(“* printf(“*n”);n”); 8上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出(3 3)函数的数据类
11、型:函数的返回值类型)函数的数据类型:函数的返回值类型 函数的数据类型可以是:函数的数据类型可以是:intint、charchar、floatfloat、doubledouble 以及指针以及指针等类型。等类型。注意:注意:1 1)对于)对于 int int 类型的函数,定义时可以省略类型说明。类型的函数,定义时可以省略类型说明。例如,例如,int int max(int x,int y) max(int x,int y)可以写成:可以写成: max(int x,int y)max(int x,int y)9上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画
12、笔画笔菜单菜单退出退出2 2)如果一个函数不返回任何值,可以定义其为)如果一个函数不返回任何值,可以定义其为 void void 类型。类型。例如:例如:void printstar(void)void printstar(void) printf(“*n”); printf(“*n”); (4) (4) returnreturn 语句语句 return return 语句的一般形式:语句的一般形式:return(return(表达式表达式););或或return return 表达式;表达式;功能:把表达式的值返回给调用函数,并把把控制权交给调用函数。功能:把表达式的值返回给调用函数,并把把
13、控制权交给调用函数。10上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出注意:注意:1 1)如果被调函数不返回值,则可以用不带表达式的)如果被调函数不返回值,则可以用不带表达式的 returnreturn 语句语句例如,例如,void printstarvoid printstar(void)(void) printf(“* printf(“*n”);n”); return; return; 2 2)一个函数中可以有多个)一个函数中可以有多个 return return 语句,但只有一个被执行语句,但只有一个被执行。11上页上页下页下
14、页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出内部函数:内部函数:只允许同一源程序文件中的函数调用的函数。存储类型为只允许同一源程序文件中的函数调用的函数。存储类型为 staticstatic。例如例如: :static static int int max( max(intint x, x,intint y) y) 函数体函数体 外部函数:外部函数:可以被其他源程序文件中的函数调用的函数。存储类型为可以被其他源程序文件中的函数调用的函数。存储类型为 externextern。例如例如: :externextern int int max( ma
15、x(intint x, x,intint y) y) 函数体函数体 或写成:或写成:intint max( max(intint x, x,intint y) y) 函数体函数体 (5 5)函数的存储类型(内部函数和外部函数)函数的存储类型(内部函数和外部函数) 函数的存储类型只有两种:函数的存储类型只有两种:externextern 和和 staticstatic。12上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出7.3 C 7.3 C 函数的调用函数的调用1 1. . 函数调用的一般形式函数调用的一般形式形式为:形式为:函数名(
16、实参表);函数名(实参表);说明:说明:(1 1)如果被调用函数没有参数,则实参表可以没有,但括号不能)如果被调用函数没有参数,则实参表可以没有,但括号不能 省略。省略。(2 2)实参的个数应和形参一样,类型按顺序对应一致。形实结合,将)实参的个数应和形参一样,类型按顺序对应一致。形实结合,将 按顺序一一传递数据。按顺序一一传递数据。(3 3)实参可以是表达式,不同的编译系统对实参表达式求值顺序不同,)实参可以是表达式,不同的编译系统对实参表达式求值顺序不同, 有的从左到右求值,有的从右到左求值。有的从左到右求值,有的从右到左求值。TurboTurbo C C 采用自右向左采用自右向左 的顺序
17、求值。的顺序求值。(6 6)函数体)函数体 用于实现函数的预定功能,包括两部分:变量说明和可执行部分。用于实现函数的预定功能,包括两部分:变量说明和可执行部分。13上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出例例 用函数实现求解计算组合公式:用函数实现求解计算组合公式:main( ) main( ) /* /* ex7-1.cex7-1.c */ */ int int m,n; long m,n; long cmn cmn,temp;,temp; long long factor( factor(intint););/* /* 函
18、数说明,或写成函数说明,或写成: :long factor( ); long factor( ); */*/ void void print( print( ););/*/* 函数说明函数说明 */ */ printfprintf(“Input m and n(“Input m and n:”);:”); scanf scanf(“%d,%d”,&m,&n(“%d,%d”,&m,&n);); cmn cmn=factor(m);=factor(m);/* /* 函数调用,计算函数调用,计算m!m! */*/ temptemp=factor(n);=factor(n);/* /* 函数调用,计算
19、函数调用,计算n! n! */*/ cmn cmn= =cmncmn/temp;/temp;/* /* 计算计算m!/n! m!/n! */*/ cmn cmn= =cmncmn/factor(m-n);/factor(m-n);/* /* 计算计算m!/n!/(m-n)!m!/n!/(m-n)! */*/ print print( (cmncmn););/* /* 函数调用,打印结果函数调用,打印结果 */ */ long factor(int x) long factor(int x) /* /* 定义函数定义函数factor()factor() */ */ long y long y;
20、; for for(y=1;x0;x(y=1;x0;x-)-) y y=y*x;=y*x; return return(y);(y); 14上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出void print(long x) void print(long x) /* /* 定义打印函数定义打印函数print( )print( ) */ */ printfprintf(“The combinations:%dn”,x);(“The combinations:%dn”,x); 2. 2. 函数调用方式函数调用方式 按函数调用在程序中出现
21、的位置来分,函数的调用方式有三种:按函数调用在程序中出现的位置来分,函数的调用方式有三种:(1 1)函数调用语句:)函数调用语句:函数调用作为一个语句。函数调用作为一个语句。例如,例如,printprint( (cmncmn););15上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出(2 2)函数表达式:)函数表达式:函数调用出现在一个表达式中,其返回值参与表达函数调用出现在一个表达式中,其返回值参与表达式运算。式运算。例如例如: :cmn=cmn/factor(m-n);cmn=cmn/factor(m-n);(3 3)函数参数:)
22、函数参数:函数调用作为另一个函数调用的实参。函数调用作为另一个函数调用的实参。例如例如: :m=max(max(a,b),c);m=max(max(a,b),c);或者写成:或者写成:m=max(a,max(b,c);m=max(a,max(b,c);16上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出3. 3. 对被调用函数的说明对被调用函数的说明 在一个函数中要调用另一个函数(被调函数)需要具备以下条件:在一个函数中要调用另一个函数(被调函数)需要具备以下条件: (1 1)被调函数必须是已经存在的函数(库函数或自定义函数)。)被调
23、函数必须是已经存在的函数(库函数或自定义函数)。 (2 2)主调函数应该知道被调函数的返回值类型。)主调函数应该知道被调函数的返回值类型。1) 1) 如果被调函数是库函数,则在本源程序文件的开头,用如果被调函数是库函数,则在本源程序文件的开头,用 #include#include 命令将被调函数的相关头文件包含到本文件中。命令将被调函数的相关头文件包含到本文件中。例如例如: :# include “stdio,h”# include “stdio,h”或写成:或写成:# include # include 17上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回
24、画笔画笔菜单菜单退出退出2) 2) 如果被调函数是用户自定义函数,而且该函数与调用它的函如果被调函数是用户自定义函数,而且该函数与调用它的函数(主调函数)在同一个源程序文件中,一般还应该在主调函数中对被数(主调函数)在同一个源程序文件中,一般还应该在主调函数中对被调函数的返回值类型作说明。调函数的返回值类型作说明。 函数类型说明的一般形式函数类型说明的一般形式数据类型数据类型 函数名(形式参数表);函数名(形式参数表); 或或数据类型数据类型 函数名(函数名( );); 例如例如: : int max(int x,int y); int max(int x,int y); 或者或者 int m
25、ax(int,int);int max(int,int); 或者或者 int max( ); int max( ); 18上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出 函数说明的位置函数说明的位置 和变量说明一样,函数说明的位置决定了函数调用的有效区域。和变量说明一样,函数说明的位置决定了函数调用的有效区域。)在调用函数的函数体内说明。)在调用函数的函数体内说明。 例如例如: :main( )main( ) void void printstar printstar( );( ); printstar printstar( );(
26、 ); )在函数体外说明。)在函数体外说明。此时,被说明的函数的有效范围是从定义开此时,被说明的函数的有效范围是从定义开始一直到本源程序结束。始一直到本源程序结束。有效有效范围范围19上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出例如例如: : /* /* ex.cex.c */ */ # include “ # include “stdio,hstdio,h” void print( );void print( );/* 函数说明 * */ / main( ) main( ) print(); print(); float flo
27、at f(intf(int x,floatx,float y) y) print(); print(); void print() void print() /* /* 定义函数print() */print() */ print(); print(); 20上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出 ) ) 外部函数的说明。外部函数的说明。如果调用函数和被调函数不在同一个源程如果调用函数和被调函数不在同一个源程序文件中,而且被调函数定义为外部函数(定义为序文件中,而且被调函数定义为外部函数(定义为externextern存储类
28、型存储类型或缺省,即不能是或缺省,即不能是staticstatic存储类型的函数),必须在函数说明中加存储类型的函数),必须在函数说明中加上上externextern,即函数说明形式应写成:,即函数说明形式应写成:extern extern 数据类型数据类型 函数名(形参表);函数名(形参表); ) ) 函数说明的省略。函数说明的省略。C C 语言规定以下三种情况可以省略对被调语言规定以下三种情况可以省略对被调函数的说明:函数的说明: 21上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出 a. a. 被调函数的数据类型是被调函数的数据
29、类型是 charchar 或或 intint; b. b. 被调函数的定义位置在调用函数之前;被调函数的定义位置在调用函数之前; c. c. 被调函数不在调用函数所在的源文件中,但用被调函数不在调用函数所在的源文件中,但用 # include# include 包含了其所在的源文件。包含了其所在的源文件。7.4 7.4 函数间数据传递方式之一函数间数据传递方式之一哑实结合哑实结合7.4.1 7.4.1 哑实结合的概念哑实结合的概念1. 1. 哑实结合的过程哑实结合的过程 22上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出例如:例如:
30、 /* ex7-2.c */# include “# include “stdiostdio.h”.h”main( )main( ) int int m,n,k; m,n,k; scanf scanf(“%d,%d”,&m,&n);(“%d,%d”,&m,&n); k=max(m,n); k=max(m,n); /*/* 调用 max( ) 函数,m,n 是实参 * */ / printfprintf(“max=%dn”,k);(“max=%dn”,k); /* /* 定义maxmax()()函数 */*/max(max(intint x, x,intint y y) ) /*/* x,y x
31、,y 是形参 * */ / intint z; z; z=xy?x:y; z=xy?x:y; return z; return z; 控制转移控制归还调用函数23上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出2.2.传值传值(pass by valuepass by value)和传址和传址(pass by referencepass by reference)(1) (1) 传值:调用传值:调用 函数将实参的值复制给形参后,实参和形参就不在有任何联系。函数将实参的值复制给形参后,实参和形参就不在有任何联系。例例1 1 :变量交换程
32、序。:变量交换程序。 main( ) main( ) / /* * ex7-3.cex7-3.c */ */ int int x,y; x,y; int int swap( swap(intint a, a,intint b); b); x=5;y=9; x=5;y=9; printf printf(“x=%d,y=%dn”,x,y);(“x=%d,y=%dn”,x,y); swap(x,y); swap(x,y); printf printf(“x=%d,y=%dn”,x,y);(“x=%d,y=%dn”,x,y); /* /* 定义函数定义函数 swap( ) */swap( ) */ s
33、wap( swap(intint a, a,intint b) b) int int t; t; t=a,a=b,b=t: t=a,a=b,b=t: printf printf(“a=%d,b=%dn”,a,b);(“a=%d,b=%dn”,a,b); return; return; 5959xyabt传值传值传值传值24上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出(2) (2) 传址:调用函数将实参中存放的地址复制给形参,形参利用该地传址:调用函数将实参中存放的地址复制给形参,形参利用该地址就可以引用间接访问该地址所对应的存储单
34、元,因而形实拥有同一址就可以引用间接访问该地址所对应的存储单元,因而形实拥有同一地址,就可以共用相同的存储单元。地址,就可以共用相同的存储单元。( (注意:采用传址方式时注意:采用传址方式时 ,形实,形实都是地址量都是地址量) )例例2 2 例例1 1变量交换程序可以改写如下:变量交换程序可以改写如下: m main( ) /* ain( ) /* ex7-4.cex7-4.c */ */ int int x,y; x,y; int int swap( swap(intint *a, *a,intint *b); *b); x=5;y=9; x=5;y=9; printf printf(“x=
35、%d,y=%dn”,x,y);(“x=%d,y=%dn”,x,y); swap(&x,&y); swap(&x,&y); printf printf(“x=%d,y=%dn”,x,y);(“x=%d,y=%dn”,x,y); /* /* 定义函数定义函数 swap( ) */swap( ) */ swap( swap(intint *a, *a,intint *b) *b) int int t; t; t t=*=*a,*aa,*a=*=*b,*b=t:b,*b=t: printf printf(“a=%d,b=%dn”,*a,*b);(“a=%d,b=%dn”,*a,*b); return;
36、 return;59&x&yxyabt指向指向指向指向&x&y25上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出例例1 1 两数相加程序。两数相加程序。 main( ) main( ) /* ex7-5.c */ float a,b,c,d = float a,b,c,d =1.1,2.2,3.3,4.4,5.5;1.1,2.2,3.3,4.4,5.5; float plus(float,float); float plus(float,float); printf printf(“Input a and b:”);(“Input
37、a and b:”); scanf scanf(“%f,%f”,&a,&b);(“%f,%f”,&a,&b); c=plus(a,b); c=plus(a,b);/* 实参是变量 */ printfprintf(“a+b=%fn”,c);(“a+b=%fn”,c); c=plus(2.5,3.5); c=plus(2.5,3.5);/* 实参是常量 */ printfprintf(“2.5+3.5=%fn”,c);(“2.5+3.5=%fn”,c); c=plus(d0,d1); c=plus(d0,d1);/* 实参是数组元素 */ printfprintf(“d0+d1=%fn”,c(“d
38、0+d1=%fn”,c););/* 定义 plusplus()()函数 */float plus(float x,float y)float plus(float x,float y) return(x+y); return(x+y);7.4.2 7.4.2 简单变量的哑实结合简单变量的哑实结合1. 1. 当哑元是变量时,对应的实元可以是常数、变量、表达式或数组元素。哑当哑元是变量时,对应的实元可以是常数、变量、表达式或数组元素。哑实结合方式是传值法。实结合方式是传值法。26上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出2.2.当哑
39、元是指针变量时,对应的实元可以是变量的地址或指针变量。当哑元是指针变量时,对应的实元可以是变量的地址或指针变量。 哑实结合方式采用传址法传送数据。哑实结合方式采用传址法传送数据。例例2 2 指针变量的哑实结合。指针变量的哑实结合。swap(int *a,intswap(int *a,int *b *b) ) /* /* ex7-6.cex7-6.c */ */ int int *t; *t; t=a,a=b,b=t; t=a,a=b,b=t; printfprintf(“a=%d,b=%dn”,*a,*b);(“a=%d,b=%dn”,*a,*b); main( )main( ) int in
40、t x,y,* x,y,*pxpx=&x,*=&x,*pypy=&y;=&y; scanf scanf(“%d,%d”,&x,&y);(“%d,%d”,&x,&y); printf printf(“x=%d,y=%dn”x,y);(“x=%d,y=%dn”x,y); swap( swap(pxpx, ,pypy);); printf printf(“x=%d,y=%dn”,x,y);(“x=%d,y=%dn”,x,y); 形参形参 a,b 交换前:交换前:&y&xbayx形参形参 a,b 交换后:交换后:&y&xbayx27上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳
41、转跳转返回返回画笔画笔菜单菜单退出退出 1.1.当哑元是数组名当哑元是数组名(包括定尺(包括定尺寸的和不定尺寸的数组)时,实寸的和不定尺寸的数组)时,实元可以是数组名或数组指针。哑元可以是数组名或数组指针。哑实结合时,编译系统将数组名转实结合时,编译系统将数组名转换为相应类型的指针,接收实元换为相应类型的指针,接收实元的地址。也就是说,的地址。也就是说,哑实结合传哑实结合传送的是数组的首地址送的是数组的首地址,哑元数组,哑元数组和实元数组共用同一片存储区。和实元数组共用同一片存储区。编译系统不在给形参数组分配存编译系统不在给形参数组分配存储空间。储空间。 例例1 1 求一个一维数组的平均值求一
42、个一维数组的平均值。main( ) main( ) /* /* ex7-7.cex7-7.c */ */ int int i,a10; i,a10; float mean( float mean(intint *), *),mvmv; ; for(i=0;i10;i+) for(i=0;i10;i+) scanf scanf(“%d”,&ai);(“%d”,&ai); mvmv=mean(a);=mean(a); printf printf(“MEAN=%fn”,(“MEAN=%fn”,mvmv);); /* 定义 mean() mean() 函数 */float mean(float mea
43、n(intint d10) d10) intint i; float i; float avg avg=0;=0; for(i=0;i10;i+) for(i=0;i10;i+)avgavg+=di;+=di; avg avg= =avgavg/10;/10; return return avg avg ; ;7.4.3 7.4.3 数组(含字符串)的哑实结合数组(含字符串)的哑实结合ad数组的哑实结合数组的哑实结合28上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出注意注意:(:(1 1)数组作为函数参数时,形参数组的大小不能超过实
44、参大小。)数组作为函数参数时,形参数组的大小不能超过实参大小。 (2 2)形参通常使用不定尺寸的数组,调用时由实参大小决定。)形参通常使用不定尺寸的数组,调用时由实参大小决定。例例2 2 将一个数组的前五个元素排序。将一个数组的前五个元素排序。/* ex7-8.c */main( )main( ) static static int int a10=2,8,7,5,9,12,10,3,1,6;a10=2,8,7,5,9,12,10,3,1,6; int int i;void sort( ); i;void sort( ); for(i=0;i10;i+) for(i=0;i10;i+) pri
45、ntfprintf(“%d ”,ai);(“%d ”,ai); printfprintf(“n”);(“n”); sort(a,5); sort(a,5); for(i=0;i10;i+) for(i=0;i10;i+) printfprintf(“%d ”,ai);(“%d ”,ai); printfprintf(“n”);(“n”); /* /* 定义排序函数定义排序函数 * */ /void sort(void sort(int int b , b ,int int n) n) int int i,j,t; i,j,t; for(i=0;in-1;i+) for(i=0;in-1;i+)
46、 for(j=i+1;jn;j+) for(j=i+1;jn;j+)if(bibj)if(bibj) t=bi; t=bi; bi=bj; bi=bj; bj=t; bj=t; 29上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出 例例3 求二维数组中的最大元素(哑元是不定尺寸的数组,实元是指针)求二维数组中的最大元素(哑元是不定尺寸的数组,实元是指针)/* ex7-9.c */main( ) int i,j; float a34,amax,max_value( ); float (*p)4; p=a; for(i=0;i3;i+)
47、for(j=0;j4;j+)scanf(“%f”,*(p+i)+j); amax=max_value(p); printf(“MAX=%fn”,amax);/* 定义函数定义函数 max_value( ) */float max_value(float array 4) int i,j; float max=array00; for(i=0;i3;i+) for(j=0;j4;j+)if(maxarrayij) max=arrayij; return(max);p30上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出注意:如果形参是二维
48、数组,只能省略行一维的大小。注意:如果形参是二维数组,只能省略行一维的大小。 2. 当哑元是数组指针时,对应的实元可以是数组名或数组指针。当哑元是数组指针时,对应的实元可以是数组名或数组指针。 例例4 将给定字符串中的字母转换成大写。将给定字符串中的字母转换成大写。/* ex7-10.c */# include “stdio.h”# include “ctype.h”void print_upper(char *string);main( ) char s80; gets(s); print_upper(s); printf(“n original string is altered:%sn”
49、,s);void print_upper(char *string) int i; for(i=0;stringi;i+) stringi=toupper(stringi); printf(“%c”,stringi);31上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出 例例5 测试字符串的长度。测试字符串的长度。/* ex7-11.c */# include “stdio.h”/* 定义求字符串长度函数定义求字符串长度函数 */userstrlen(char *s) int n; for(n=0;*s;s+) n+; return(
50、n); /* 返回字符串长度返回字符串长度 */* 定义主函数定义主函数 */main( ) char s180,s280; gets(s1);gets(s2); printf(“The first string s length is %dn”,userstrlen(s1); printf(“The second string s length is %dn”,userstrlen(s2);32上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出 3. 当实元是数组元素时,哑元只能是简单变量。哑实结合采用当实元是数组元素时,哑元只能是简
51、单变量。哑实结合采用传值传值。 例例6 逐个显示数组元素。逐个显示数组元素。/* ex7-12.c */* 定义子函数定义子函数 */void display(int x) printf(“%d “,x);/* 定义主函数定义主函数 */main( ) int i,a10; for(i=0;i10;i+) scanf(“%d”,&ai); for(i=0;iy?x:y);指针变量所指针变量所指向的函数指向的函数返回值类型返回值类型相当于相当于34上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出说明:(说明:(1)函数的调用可以用函数名
52、调用,也可以用函数指针调用。)函数的调用可以用函数名调用,也可以用函数指针调用。 (2)用函数指针调用时,只需用()用函数指针调用时,只需用(*p)代替函数名即可(代替函数名即可(p为函为函数指针)。数指针)。 (3)给函数指针变量赋值时,只需给出函数名即可。如,)给函数指针变量赋值时,只需给出函数名即可。如,p=max;或或p=max( ); (4) 函数指针变量进行函数指针变量进行 + +、- -和加减整数和加减整数 n等运算没有意义。等运算没有意义。 例如,设例如,设 p是一个函数指针变量,则下列用法是没意义的。是一个函数指针变量,则下列用法是没意义的。 P+,p-,p+n,p-n 函数
53、指针的一个重要应用是作为函数的参数函数指针的一个重要应用是作为函数的参数,此时,实元可以是,此时,实元可以是函数名或函数指针,随着每次调用实元的不同,就可以实现通过函数指函数名或函数指针,随着每次调用实元的不同,就可以实现通过函数指针调用不同函数的目的。关于这方面的应用下面举一个简单的例子。更针调用不同函数的目的。关于这方面的应用下面举一个简单的例子。更 深入的应用在以后的进一步学习中慢慢掌握。深入的应用在以后的进一步学习中慢慢掌握。 例例 设计一个函数设计一个函数 process ,在调用它的时候,每次实现不同的在调用它的时候,每次实现不同的功能。输入功能。输入 a 和和 b 两个数,每次调
54、用分别求两个数,每次调用分别求 a 和和 b的和、差、积、商。的和、差、积、商。程序转下页:程序转下页:35上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出/* ex7-13.c */main( ) int a,b; scanf(“%d,%d”,&a,&b); printf(“a+b=%dn”,process(a,b,add); printf(“a-b=%dn”,process(a,b,sub); printf(“a*b=%dn”,process(a,b,mult); printf(“a/b=%dn”,process(a,b,div)
55、;process(int x,int y,int (*fp)( ) int result; result=(*fp)(x,y); return(result);/* 求二数之和求二数之和 */add(int x,int y) return(x+y);/* 求二数之差求二数之差 */sub(int x,int y) return(x-y);/* 求二数之积求二数之积 */mult(int x,int y) return(x*y);/* 求二数之商求二数之商 */div(int x,int y)return(x/y);36上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转
56、返回返回画笔画笔菜单菜单退出退出7.5 函数间数据传递方式之二函数间数据传递方式之二 函数返回值函数返回值 1. 返回数值和字符的返回数值和字符的基本类型函数基本类型函数基本型函数:基本型函数:返回值为整型、实型、字符型和双精度型的函数称为返回值为整型、实型、字符型和双精度型的函数称为基本基本 类型函数类型函数或或基本型函数基本型函数。这类函数只能通过。这类函数只能通过 return 语句返语句返 回一个值。回一个值。 2。返回地址的。返回地址的指针型函数指针型函数指针型函数:指针型函数:返回值为地址或指针的函数。这类函数定义的一般形式为:返回值为地址或指针的函数。这类函数定义的一般形式为:存
57、储类型存储类型 数据类型数据类型 *函数名(形参表)函数名(形参表)static或或extern例如,例如,int *sub(int a,int b)static char *name(int n)void *f(int *p)等都可以定义指针型函数。等都可以定义指针型函数。37上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出 例例1 两个字符串的连接(子函数返回字符串首地址)。两个字符串的连接(子函数返回字符串首地址)。/* ex7-14.c */# include “stdio.h”char *userstrcat(char *s
58、1,char *s2) char *temp; temp=s1; while(*s1)s1+;/* 移动指针到移动指针到s1字符串末尾字符串末尾 */ while(*s2)/* 实现字符串实现字符串s2逐个追加到逐个追加到s1的末尾的末尾 */ *s1=*s2; s1+;s2+; *s1=0; return temp;main( ) char *s1,*s2,*s; gets(s1);gets(s2); s=userstrcat(s1,s2); /* 连接后字符串的首地址连接后字符串的首地址 */ printf(“concatenated string is :%sn”,s);38上页上页下页
59、下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出 例例2 有一个二维数组,要求从键盘输入一个行号,将该行的各元素打有一个二维数组,要求从键盘输入一个行号,将该行的各元素打印出来(子函数返回指定行首地址)。印出来(子函数返回指定行首地址)。/* ex7-15.c */float * find(float (*p)4,int n) float *pt; pt=*(p+n);/* pt 指向第指向第 n 行的首地址行的首地址 */ return pt;main( ) float a34,*p; int i,j,n; for(i=0;i3;i+) for
60、(j=0;j4;j+)scanf(“%f”,&aij); scanf(“%d”,&n); p=find(a,n); for(i=0;iy?x:y; return z;int a=12,b=8;/* 全局变量定义全局变量定义 */41上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出7.7 函数的嵌套调用和递归调用函数的嵌套调用和递归调用7.7.1 函数的嵌套调用函数的嵌套调用 C 语言规定:语言规定:C 函数不允许嵌套定义,但允许嵌套调用。函数不允许嵌套定义,但允许嵌套调用。嵌套调用:一个函数调用另一个函数时,被调用函数又调用了其它函数
61、。嵌套调用:一个函数调用另一个函数时,被调用函数又调用了其它函数。 例如,例如,void aia( ),ber( ),cal( );/* 函数说明函数说明 */main( ) printf(“I am in main.n”); aia( ); /* aia()() 函数函数调用调用 */void aia( )/* aia()() 函数函数定义定义 */ printf(“ Now Im in aia.n”); ber( ); /* ber()() 函数函数调用调用 */void ber( ) /* ber()() 函数函数定义定义 */ printf(“ Now Im in ber.n”); c
62、al( ); /* cal()() 函数函数调用调用*/void cal( ) /* cal()() 函数函数定义定义 */ printf(“Now Im in cal.n”);42上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出说明说明:函数之间的调用关系是一种逻辑关系,与各函数在程序中的物理:函数之间的调用关系是一种逻辑关系,与各函数在程序中的物理位置无关。位置无关。7.7.2 函数的递归调用函数的递归调用递归调用递归调用:一个函数直接或间接的调用其本身。前者称为:一个函数直接或间接的调用其本身。前者称为直接递归直接递归,后,后
63、者称为者称为间接递归间接递归。例如,例如,main( ) sub( ); sub( ) sub( ); 直直接接递递归归main( ) sub1( ); sub1( ) sub2( ); sub2( ) sub1( ); 间接递归间接递归43上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出 1. 递归函数应用举例递归函数应用举例 例例 用递归函数求阶乘(用递归函数求阶乘(n!)。)。n!可以递归定义为:可以递归定义为:n!1(n=0 或或 n=1)n (n-1)!(n1)据此,可以编写一个求阶乘的递归函数:据此,可以编写一个求阶乘的递
64、归函数:long fac (int n) if (n= =0|n= =1)return (1); elsereturn( n*fac(n-1) );再编写一个主函数来调用上述函数,以实现对任给的整数再编写一个主函数来调用上述函数,以实现对任给的整数 x 求求 x! 。main( ) int x; long fac ( ); scanf(“%d”.&x); printf(“%d!=%ldn”,x,fac(x) );44上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出 2. 递归调用过程的分析递归调用过程的分析 递归调用过程可分为两个阶段
65、:回推和递推。递归调用过程可分为两个阶段:回推和递推。 下面以上述求阶乘的程序为例(设下面以上述求阶乘的程序为例(设 x=5)来分析递归调用的两个阶段。来分析递归调用的两个阶段。整个调用过程可用下图描述:整个调用过程可用下图描述:fac(5)=5*fac(4)fac(4)=4*fac(3)fac(2)=2*fac(1)fac(3)=3*fac(2)fac(1)=1fac(5)=120fac(4)=24fac(3)=6fac(2)=2第第一一阶阶段段“回回推推”第第二二阶阶段段“递递推推”45上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出
66、退出函数调用过程可用下图描述:函数调用过程可用下图描述: fac (5) fac(4) fac(3) fac(2) fac(1) main( ) return 1 fac(5)fac(4)fac(3)fac(2)fac(1) 3. 递归程序设计方法递归程序设计方法 递归程序设计,一般分两步:递归程序设计,一般分两步: (1)确定基始条件,即递归结束的条件。)确定基始条件,即递归结束的条件。 (2)设计)设计“回推回推”过程,通过对要解决的问题的分析来决定。过程,通过对要解决的问题的分析来决定。 例例 用递归函数求菲波那契数列的第用递归函数求菲波那契数列的第 n 项的值。菲波那契数列的定义项的值
67、。菲波那契数列的定义为:为:fib(n)=1 (n=0)1 (n=1)fib(n-1)+fib(n-2) (n1)46上页上页下页下页C语言讲义理工学院基础教育学院第七章第七章 函数函数跳转跳转返回返回画笔画笔菜单菜单退出退出程序:程序:递归函数:递归函数: /* ex7-18.c */fib(int n) int f; if(n= =0|n= =1)f=1; elsef=fib(n-1)+fib(n-2); return f;main( ) int i; for(i=0;i20;i+) printf(“%dt”,fib(i);/* 输出数列的前输出数列的前 20 项项 */ printf(“n”);非递归函数:非递归函数:fib(int n) int f,f0=1,f1=1,i; for(i=2;i=n;i+) f=f0+f1; f0=f1; f1=f; return f;第七章结第七章结第七章结第七章结束!束!束!束!47退退出出菜菜单单跳跳转转继续继续运行请选择运行请选择按钮按钮!单击单击屏幕任意处,或屏幕任意处,或按按任意键任意键则则结束结束放映!放映!关于关于C 程序设计教程程序设计教程 作者:王成霞作者:王成霞 1999.10.01 Ver 1.048