用函数实现模块化程序设计_第1页
用函数实现模块化程序设计_第2页
用函数实现模块化程序设计_第3页
用函数实现模块化程序设计_第4页
用函数实现模块化程序设计_第5页
已阅读5页,还剩220页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、信息科学与工程学院计算机系信息科学与工程学院计算机系卡米力卡米力C程序设计程序设计(第三版)(第三版) 学好程序设计语言的唯一途径学好程序设计语言的唯一途径是上机练习。是上机练习。你的编程能力与你在计算机上你的编程能力与你在计算机上投入的时间成正比。投入的时间成正比。 课程要求课程要求 课前请做好预习课前请做好预习 保持课堂安静,头脑清醒,思维活跃保持课堂安静,头脑清醒,思维活跃 做好课堂笔记做好课堂笔记 认真、独立、按时完成并提交作业认真、独立、按时完成并提交作业 重视上机实践,有效利用宝贵的上机时重视上机实践,有效利用宝贵的上机时间间7.1 为什么要用函数为什么要用函数 7.2怎样定义函数

2、怎样定义函数7.3调用函数调用函数7.4 对被调用函数的声明和函数原型对被调用函数的声明和函数原型 7.5 函数的嵌套调用函数的嵌套调用7.6函数的递归调用函数的递归调用 7.7数组作为函数参数数组作为函数参数7.8局部变量和全局变量局部变量和全局变量7.9变量的存储方式和生存期变量的存储方式和生存期 7.10 关于变量的声明和定义关于变量的声明和定义7.11 内部函数和外部函数内部函数和外部函数 第第7章章 函数函数 7.1 为什么要用函数为什么要用函数问题:问题:如果程序的功能比较多,规模比较大,如果程序的功能比较多,规模比较大,把所有代码都写在把所有代码都写在main函数中,就会使函数中

3、,就会使主函数变得庞杂、头绪不清,阅读和维主函数变得庞杂、头绪不清,阅读和维护变得困难护变得困难。有时程序中要多次实现某一功能,就需有时程序中要多次实现某一功能,就需要多次重复编写实现此功能的程序代码要多次重复编写实现此功能的程序代码,这使程序冗长,不精炼这使程序冗长,不精炼。 解决的方法:解决的方法: 用用模块化程序设计的思路模块化程序设计的思路采用采用“组装组装”的办法简化程序设计的过的办法简化程序设计的过程程事先编好一批实现各种不同功能的函数事先编好一批实现各种不同功能的函数把它们保存在函数库中把它们保存在函数库中,需要时需要时直接用直接用.函数就是功能函数就是功能:函数函数就是就是用来

4、用来完成完成特定的功能特定的功能的代码的代码函数名就是给该函数名就是给该( (函数函数) )功能起的名字功能起的名字函数的名字应反映其代表的功能函数的名字应反映其代表的功能函数名应该遵循函数名应该遵循“见名知意见名知意”。在设计一个较大的程序时,在设计一个较大的程序时,往往把它分往往把它分为为若干个程序模块,若干个程序模块,每一个模块包括每一个模块包括一一个或多个函数个或多个函数,每个函数实现一个特定每个函数实现一个特定的功能的功能。程序可由一个主函数和若干个其他函程序可由一个主函数和若干个其他函数构成数构成;主函数调用其他函数,主函数调用其他函数,其他函数也可以其他函数也可以互相调用互相调用

5、;同一个函数可以被一个或多个函数调用同一个函数可以被一个或多个函数调用任意多次任意多次。由主函数调用其他函数,由主函数调用其他函数,其他函数也可以互相调其他函数也可以互相调用。用。同一个函数可以被一个或多个函数调用任意同一个函数可以被一个或多个函数调用任意多次。多次。在程序开发中,在程序开发中,常将一些常用的功能模块常将一些常用的功能模块编写成编写成函数,函数,放在公共函数库中放在公共函数库中供大家选用。供大家选用。图图7-1 7-1 函数之间的调用关系示意图函数之间的调用关系示意图例例7.1 7.1 输出一行信息,用函数调用来实现输出一行信息,用函数调用来实现# include void m

6、ain() void printstar(); / *函数函数printstar的声明的声明 * / void print_message(); /* 函数函数print_message的声明的声明 */ printstar(); /* 调用自定义函数调用自定义函数printstar */ print_message(); /* 调用自定义函数调用自定义函数print_message */ printstar(); /* 调用自定义函数调用自定义函数printstar */ void printstar() *printstar函数的定义函数的定义* printf(* * * * * * *

7、* * * * * *n);void print_message() printf(How do you do!n); 解题思路:解题思路:在输出的文字上下分在输出的文字上下分别有一行别有一行“*”号,显然不必重复号,显然不必重复写这段代码,用一个函数写这段代码,用一个函数print_star来实现输出一行来实现输出一行“*”号的功能。号的功能。再写一个再写一个print_message函数来函数来输出中间一行文字信息用主函数输出中间一行文字信息用主函数分别调用这两个函数分别调用这两个函数。#include int main() void print_star(); void print_me

8、ssage(); print_star(); print_message(); print_star(); return 0; void print_star() printf(“*n”); void print_message() printf(“ How do you do!n”); 声明函数声明函数定义函数定义函数函数的调用函数的调用(1)一个一个C程序程序由一个或多个由一个或多个程序模块组成程序模块组成,每一个程序模块每一个程序模块作为一个源程序文件作为一个源程序文件。对较大的程序,对较大的程序,一般不希望把所有内容全放一般不希望把所有内容全放在一个文件中,在一个文件中,而是将他们分别

9、放在若干个而是将他们分别放在若干个源文件中,源文件中,再由若干源程序文件再由若干源程序文件组成一个组成一个C C程程序。序。这样便于分别编写、这样便于分别编写、分别编译,提高调试效分别编译,提高调试效率。率。一个源程序文件可以为多个一个源程序文件可以为多个C C程序公用。程序公用。(2) 一个源程序文件一个源程序文件由一个由一个或或多个函数多个函数以以及其他有关内容及其他有关内容(如命令行、数据定义等)(如命令行、数据定义等)组成。组成。一个源程序文件一个源程序文件是一个编译单位,是一个编译单位,在程序编在程序编译时译时是以源程序文件为单位是以源程序文件为单位进行编译的,进行编译的,而而不是以

10、函数为单位不是以函数为单位进行编译的。进行编译的。(3)C程序的执行程序的执行是是从从main函数开始函数开始的,的,如是在如是在main函数中函数中调用其他函数,调用其他函数,在调用后在调用后流程返回到流程返回到main函数,函数,在在main函数中函数中结束整个程序的运行。结束整个程序的运行。(4) 所有函数都是平行的,所有函数都是平行的,即在定义即在定义函数时是分别进行的,函数时是分别进行的,是互相独立的。是互相独立的。一个函数一个函数并不从属于另一函数,并不从属于另一函数,即函数即函数不能嵌套定义。不能嵌套定义。函数间可以互相调用,函数间可以互相调用,但不能调用但不能调用main函数。

11、函数。main函数是函数是系统调用的。系统调用的。(5)从用户使用的角度看,函数有两种:)从用户使用的角度看,函数有两种: 标准函数,即库函数。标准函数,即库函数。这是由系统提供的,这是由系统提供的,用户不必自己定义这些用户不必自己定义这些函数,函数,可以直接使用它们。可以直接使用它们。应该说明,应该说明,不同的不同的C系统提供的库函数的系统提供的库函数的数数量量和和功能功能会有一些不同会有一些不同。 用户自己定义的函数。用户自己定义的函数。用以解决用户的专用以解决用户的专门需要。门需要。(6) 从函数的形式看,函数分两类:从函数的形式看,函数分两类:无参函数。无参函数。如例如例7.1中的中的

12、printstar和和print_message就是就是无参函数。无参函数。在调用无参函数时,在调用无参函数时,主调函数主调函数不向不向被调用函被调用函数数传递数据。传递数据。无参函数无参函数一般用来执行一般用来执行指定的指定的一组操作。一组操作。void print_message() *定义定义print_message函数函数* printf(How do you do!n); 有参函数。有参函数。在调用函数时,在调用函数时,主调函数主调函数在调用在调用被调用函数被调用函数时,时,通过参数通过参数向被调用函数向被调用函数传递数据,一般传递数据,一般情况下,情况下,执行被调用函数时执行被调

13、用函数时会得到一个函数会得到一个函数值,值,供主调函数使用。供主调函数使用。例如:例如:int max(int x,int y) int z; / *函数体中的声明部分函数体中的声明部分* z=xy?x:y ; / *函数体中的执行语句函数体中的执行语句* return(z); 形式参数形式参数7.2.1. 为什么要定义函数为什么要定义函数C语言要求,在程序中用到的所有函数,必语言要求,在程序中用到的所有函数,必须须“先定义,后使用先定义,后使用”。例如,例如,想调用想调用max函数函数来求出两个数中的大来求出两个数中的大者,者,必须事先定义要调用的必须事先定义要调用的max函数,即函数,即指

14、指定定函数函数名字名字、函数、函数返回值类型返回值类型、函数实现的、函数实现的功能功能以及以及参数的个数与类型参数的个数与类型,将这些信息通,将这些信息通知编译系统。知编译系统。定义函数应包括以下几个内容:定义函数应包括以下几个内容: 指定函数的名字指定函数的名字,以便以后按名调用,以便以后按名调用; 指定函数类型指定函数类型,即函数返回值的类型,即函数返回值的类型; 指定函数参数的名字和类型指定函数参数的名字和类型,以便在调用,以便在调用函数时向它们传递数据函数时向它们传递数据; 指定函数的功能。指定函数的功能。这是最重要的,这是在这是最重要的,这是在函数体中解决的函数体中解决的。对于对于库

15、函数,库函数,程序设计者只需用程序设计者只需用#include指指令令把有关的头文件把有关的头文件包含到本文件模块中即可包含到本文件模块中即可.在有关的头文件中包括了对函数的声明,例在有关的头文件中包括了对函数的声明,例如,在程序中若用到数学函数如,在程序中若用到数学函数(sqrt,fabs),则在源文件的开头写上:,则在源文件的开头写上: #include当然,当然,程序设计者需要在程序中自己定义想程序设计者需要在程序中自己定义想用的用的而库函数并没有提供的函数而库函数并没有提供的函数1. 定义无参函数定义无参函数在定义函数时要用在定义函数时要用“类型名类型名”指定函数值的指定函数值的类型,

16、类型,即函数带回来的值的类型。即函数带回来的值的类型。例例7.中的中的printstar和和print_message函数函数都是都是无参函数无参函数,函数名后面的括号中是空的,函数名后面的括号中是空的( void ),没有任何参数。),没有任何参数。定义无参函数的格式:定义无参函数的格式:定义无参函数的一般形式为定义无参函数的一般形式为:类型名类型名 函数名函数名(void) 函数体函数体 类型名类型名 函数名函数名() 函数体函数体 包括声明部分包括声明部分和语句部分和语句部分例例 无参函数无参函数 printstar( ) printf(“*n”); 或或 printstar(void

17、) printf(“*n”); 定义函数时要用定义函数时要用“类型名类型名”指定函数值的类型,指定函数值的类型,即函数即函数带回来的值的类型带回来的值的类型.函数名后函数名后的的void表示空,即函数无参数表示空,即函数无参数定义有参函数的一般形式为定义有参函数的一般形式为:返回值类型返回值类型函数名函数名(形式参数表列形式参数表列) 声明部分声明部分 语句部分语句部分 函数体函数体例如:例如:int max(int x,int y) int z; /声明部分声明部分 z=xy?x:y ; /执行部分执行部分 return(z); 花括号内是函数体,它包括声明部分和语句部分。花括号内是函数体,

18、它包括声明部分和语句部分。在声明部分定义在声明部分定义所用的变量,所用的变量,此外此外对将要调用的函数作声明对将要调用的函数作声明。在函数体的语句中求出的值(为在函数体的语句中求出的值(为x与与y中大者);中大者);return(z)的作用的作用是将是将z的值作为函数值带回到主调函数中。的值作为函数值带回到主调函数中。return后面的括弧中的后面的括弧中的值值(z)作为函数带回的值(或称函数返回值)。作为函数带回的值(或称函数返回值)。在函数定义时已指定在函数定义时已指定max函数为整型,在函数体中定义函数为整型,在函数体中定义z为整型,为整型,二者是一致的二者是一致的,将,将z作为函数作为

19、函数max的值带回调用函数。的值带回调用函数。如果在定义函数时如果在定义函数时不指定函数类型不指定函数类型,系统会隐含指定函数类型为,系统会隐含指定函数类型为int型型。因此上面定义的因此上面定义的max函数左端的函数左端的int可以省写可以省写.这是一个求这是一个求x和和y二者中大者的函数,二者中大者的函数,笫笫1行第一个关键字行第一个关键字int表示函数值是表示函数值是整的。整的。max为函数名。括号中有两为函数名。括号中有两个形式参数个形式参数x和和y,它们都是整型的。,它们都是整型的。在调用此函数时,主调函数把实际在调用此函数时,主调函数把实际参数的值传递给被调用函数中的形参数的值传递

20、给被调用函数中的形式参数式参数x和和y。3. 空函数空函数调用此函数时,什么工作也不做,没有任何调用此函数时,什么工作也不做,没有任何实际作用。实际作用。在主调函数中写上在主调函数中写上“dummy();”表明表明“这这里要调用一个函数里要调用一个函数”,而现在这个函数没有而现在这个函数没有起作用,起作用,等以后扩充函数功能时补充上。等以后扩充函数功能时补充上。 例如:例如:void dummy( ) 定义空函数的一般形式为定义空函数的一般形式为:返回值类型函数名()返回值类型函数名() /函数体为空函数体为空 在程序设计中在程序设计中往往根据需要确定若干模往往根据需要确定若干模块,块, 分别

21、由一些分别由一些函数来实现。函数来实现。 而在第一阶段而在第一阶段只设计最基本的模块,只设计最基本的模块, 其其他一些次要功能他一些次要功能或或锦上添花锦上添花的功能的功能则在则在以后以后需要时需要时陆续补上。陆续补上。在编写程序的开始阶段,在编写程序的开始阶段,可以在将来准备扩可以在将来准备扩充功能的地方充功能的地方写上一个空函数写上一个空函数(函数名取将(函数名取将来采用的实际函数名来采用的实际函数名(如用(如用merge()()、matproduct()()、oncatenate()()、shell()()等,分别代表合并、矩阵相乘、字符串连接、等,分别代表合并、矩阵相乘、字符串连接、希

22、尔法排序等),希尔法排序等),只是这些函数未编好,只是这些函数未编好,先先占一个位置,以后用一个编好的函数代替它。占一个位置,以后用一个编好的函数代替它。这样做,程序的结构清楚,可读性好,这样做,程序的结构清楚,可读性好,以后以后扩充新功能方便,对程序结构影响不大。扩充新功能方便,对程序结构影响不大。空空函数在程序设计中常常是有用的。函数在程序设计中常常是有用的。 7.3 函数调用函数调用定义函数的目的就是为了调用此函数,以得定义函数的目的就是为了调用此函数,以得到预期的结果。到预期的结果。7.3.1 函数调用的形式函数调用的形式调用一个函数的方法很简单调用一个函数的方法很简单,如:如: pr

23、int_star(); /调用无参函数调用无参函数 c=max(a,b); /调用有参函数调用有参函数函数调用形式:函数调用形式: 函数名(实参表列);函数名(实参表列);如果是调用如果是调用无参函数无参函数,则,则“实参表列实参表列”可以可以没有,但括号不能省略没有,但括号不能省略;如果实参表列如果实参表列包含多个实参包含多个实参,则各参数间用,则各参数间用逗号隔开逗号隔开。按函数调用按函数调用在程序中出现的形式和位置来在程序中出现的形式和位置来分分,可以有以下,可以有以下3种函数调用方式种函数调用方式:1. 函数调用语句函数调用语句把函数调用单独作为一个语句把函数调用单独作为一个语句。例如

24、:例如: printf_star();这时不要求函数带回值,只要求函数完成一这时不要求函数带回值,只要求函数完成一定的操作定的操作。2. 函数表达式函数表达式函数调用出现在另一个表达式中函数调用出现在另一个表达式中。例如:例如:c=max(a,b); 。c=max(a,b); 是一次函数调用,它是赋值表是一次函数调用,它是赋值表达式中的一部分。达式中的一部分。这时要求函数带回一个确定的值以参加表达这时要求函数带回一个确定的值以参加表达式的运算式的运算。3. 函数参数函数参数函数调用作为另一函数调用时的实参函数调用作为另一函数调用时的实参。例如:例如: mmax(a,max(b,c);其中其中m

25、ax(b,c)是一次函数调用,是一次函数调用,它的值作为它的值作为max另一次调用的实参另一次调用的实参。经过赋值后,。经过赋值后,m的的值是值是a,b,c三者中的最大者,三者中的最大者,又如:又如:printf(“%d”,max(a , b); 也是把也是把max(a , b)作作为为printf函数的一个参数。函数的一个参数。 7.3.2 函数调用时的数据传递函数调用时的数据传递1. 形式参数和实际参数形式参数和实际参数在调用函数时,在调用函数时,大多数情况下,大多数情况下,主调函数主调函数和和被调用函数被调用函数之间之间有数据传递关系。有数据传递关系。 这就是这就是前面提到的前面提到的有

26、参函数。有参函数。 在定义函数时在定义函数时函数名后面函数名后面括号中的变量名括号中的变量名 称为称为“形式参数形式参数”(简称(简称“形参形参”);); 在主调函数中在主调函数中调用一个函数调用一个函数时,时,函数名后函数名后 面括号中的参数面括号中的参数(可以是一个表达式可以是一个表达式)称为称为 “实际参数实际参数”(简称(简称“实参实参”)。)。 实参可以是常量、变量或表达式实参可以是常量、变量或表达式。 在不同的函数之间在不同的函数之间传递数据时传递数据时,可以可以使用的法:使用的法: 参数:参数:通过形式参数和实际参数通过形式参数和实际参数 返回值:返回值:用用return语句返回

27、计算结果语句返回计算结果 全局变量:全局变量:外部变量外部变量函数参数及其传递方式:函数参数及其传递方式:形参与实参:形参与实参: 实际参数:实际参数:调用函数时调用函数时函数名后面函数名后面 括号中的括号中的变量名。变量名。 形式参数:形式参数:定义函数时定义函数时函数名后面函数名后面 括号中的括号中的变量名。变量名。 函数参数传递方式:函数参数传递方式:函数调用时函数调用时将将 实参值实参值传递给传递给形参。形参。2. 实参和形参间的数据传递实参和形参间的数据传递在调用函数过程中,在调用函数过程中,系统会把实参的值传系统会把实参的值传递给被调用函数的形参递给被调用函数的形参,或者说,或者说

28、,形参从形参从实参得到一个值实参得到一个值。该值在函数调用期间有效,该值在函数调用期间有效,可以参加可以参加被调被调函数中的运算函数中的运算。在调用函数过程中发生的在调用函数过程中发生的实参与形参间的实参与形参间的数据传递数据传递,称为,称为虚实结合虚实结合。例例7.2 输入两个整数,要求输出其中值较大输入两个整数,要求输出其中值较大者。要求用函数来找到大数。者。要求用函数来找到大数。解题思路:解题思路:1)函数名应是函数名应是见名知意见名知意,今定名为,今定名为max;2) 由于给定的两个数是整数,返回主调函数由于给定的两个数是整数,返回主调函数 的值的值(即较大数)(即较大数)应该是整型应

29、该是整型。3) max函数应当有两个参数,以便从主函函数应当有两个参数,以便从主函数接收两个整数,数接收两个整数,因此因此参数的类型应当参数的类型应当是整型是整型先编写先编写max函数:函数:int max(int x,int y) /函数的定义,函数的定义,x和和y是形参是形参 int z; z=xy?x:y; return(z); 在在max函数上面,函数上面,再编写主函数再编写主函数#include int main() int max(int x,int y); /函数的声明函数的声明 int a,b,c; printf(“two integer numbers: ); scanf(“

30、%d,%d”,&a,&b); c=max( a , b ); /函数的调用,函数的调用,实参可以是实参可以是常量常量变量变量或表达式或表达式 printf(“max is %dn”,c); #include int main() int max(int x,int y); /函数的声明函数的声明 int a,b,c; printf(“two integer numbers: ); scanf(“%d,%d”,&a,&b); c=max( a , b ); /函数的调用,函数的调用,实参可以是实参可以是常量常量变量变量或表或表达式达式 printf(“max is %dn”,c); int ma

31、x(int x,int y) /函数的定义,函数的定义,x和和y是形参是形参 int z; z=xy?x:y; return(z); 在调用此函数时,主调函数把实在调用此函数时,主调函数把实参的值传递给参的值传递给max函数中的形参函数中的形参x和和y,实现了参数值的传递,实现了参数值的传递,把二者组合为一个程序文件,主函数在前面,把二者组合为一个程序文件,主函数在前面,max函数在下面。函数在下面。如:文件名为如:文件名为ka1.c说明:说明:在笫在笫2行的行的int表示函数值是整的。表示函数值是整的。主主函数中给出了被调用函数函数中给出了被调用函数max的声明,的声明,max为函数名。为函

32、数名。括号中有两个括号中有两个int型的形式型的形式参数参数x和和y。用。用c=max(a,b);调用了调用了max函数函数这时在这时在max函数中得到了要处理的函数中得到了要处理的两个数据,得到的最大值返回给两个数据,得到的最大值返回给c注意:注意:1) 实参可以是常量、变量或表达式,如:实参可以是常量、变量或表达式,如:max(3,a+b),但要求它们有确定的值;但要求它们有确定的值; 在函数调用时在函数调用时将实参的值传递给形参。将实参的值传递给形参。2) 实参与形参的类型应相同实参与形参的类型应相同或赋值兼容。或赋值兼容。例例7.2中实参和形参的类型相同,都是中实参和形参的类型相同,都

33、是int 型型,这是合法的,这是合法的 ;如果实参为如果实参为int型而形参型而形参x为为float型,或者相型,或者相反,则按不同类型数值的赋值规则进行转换反,则按不同类型数值的赋值规则进行转换.例如,实参例如,实参a为为float型变量,其值为型变量,其值为3.5,而而形参形参x为为int型,型,则在传递时先将实数则在传递时先将实数3.5转换转换成成3,然后送到形参,然后送到形参x。char型和型和int型通用型通用.main() int a,b,c; scanf(%d,%d,&a,&b); c=max(a,b); printf(Max is %d,c);max(int x, int y)

34、 /函数定义函数定义 int z; z=xy?x:y; return(z);形参形参实参实参(max 函数)函数)c=max(a , b);(main 函数)函数)max( int x, int y ) int z; z=xy?x:y; return(z); 实参和形参间的数据传递实参和形参间的数据传递void main() int x, y, z;int max( int a,int b );printf(请输入两个整数:请输入两个整数:n);scanf(“%d%d”,&x,&y); z=max( x , y ); printf(“max=%dn”,z);int max( int a , i

35、nt b ) int c; c=ab ? a : b; return c; 实参与形参,参数传递实参与形参,参数传递:x 3y 5zabc 5355 求两个数中的最大数:求两个数中的最大数:在定义函数中在定义函数中指定的形参,指定的形参,在未出现在未出现函数函数调用调用时,时,它们并不占它们并不占内存中的存储单元。内存中的存储单元。只有在发生只有在发生函数调用时函数调用时,函数函数max中的中的形参形参才被分配内存单元。才被分配内存单元。在调用结束后,在调用结束后,形参所占的内存单元形参所占的内存单元也也被释放。被释放。 7.3.3 函数调用的过程函数调用的过程2a3bxy23实参实参形参形参

36、调用函数时将实参对应的值传递给形参,调用函数时将实参对应的值传递给形参,如图如图7.3所示,实参的值为所示,实参的值为2,把把2传递给相应传递给相应的形参的形参x,这时形参,这时形参x就得到值就得到值2,同理,形同理,形参参y得到值得到值3。#include int main() int max(int x,int y); /函数的声明函数的声明 int a,b,c; printf(“two integer numbers: ); scanf(“%d,%d”,&a,&b); c=max( a , b ); /函数的调用函数的调用 printf(“max is %dn”,c); int max(

37、int x,int y) /函数的定义函数的定义 int z; z=xy?x:y; return(z); 在执行在执行max函数期间,函数期间,由于形参已经有值由于形参已经有值,就可以利用形参进行有关的运算就可以利用形参进行有关的运算(例如,(例如,x和和y比较,把最大值赋给比较,把最大值赋给z等)等)。#include int main() int max(int x,int y); /函数的声明函数的声明 int a,b,c; printf(“two integer numbers: ); scanf(“%d,%d”,&a,&b); c=max( a , b ); /函数的调用函数的调用

38、printf(“max is %dn”,c); int max(int x,int y) /函数的定义函数的定义 int z; z=xy?x:y; return(z); 通过通过return语句将函数值带回到主函数。语句将函数值带回到主函数。例例7.2中在中在return语句中语句中指定的返回值是指定的返回值是z,这个,这个z就是就是函函数数max的返回值的返回值。执行执行return语句就把这个函数返语句就把这个函数返回值带回主函数回值带回主函数main。注意:注意:返回值返回值z的类型与的类型与max函数的类型一致。函数的类型一致。若函数不需要返回值,若函数不需要返回值,则则不需要不需要r

39、eturn语句,语句,这时函数类型应定义为这时函数类型应定义为 main() int max(int x,int y); /函数的声明函数的声明 int a,b,c; scanf(“%d,%d”,&a,&b); c=max( a , b ); /函数的调用函数的调用 printf(“max is %dn”,c); int max(int x,int y) /函数的定义函数的定义 int z; z=xy?x:y; return(z); 函数函数调用结束,调用结束,则则形参单元被释放形参单元被释放。注意:注意:实参单元仍保留并维持原值,实参单元仍保留并维持原值,实参的实参的值并值并

40、没有改变没有改变。如果在执行一个被调用函数时,如果在执行一个被调用函数时,若若形参的值形参的值发生改变发生改变,则则不会改变主调函数的实参的值不会改变主调函数的实参的值.例如:形参在执行例如:形参在执行max函数的过程中,形参函数的过程中,形参x,y的值变为的值变为10和和15,但但a和和b的值仍为的值仍为2和和3,这是因为,这是因为实参与形参在内存中占用不同实参与形参在内存中占用不同的存储单元。的存储单元。2a3bxy1015实参实参形参形参/例子例子 函数参数为普通变量时形参对实参的影响函数参数为普通变量时形参对实参的影响 void main() int swap(int x,int y)

41、; /被调用函数被调用函数swap的声明的声明 int a,b,result; printf(请输入需要交换的两个整数请输入需要交换的两个整数:n); scanf(a=%d,b=%d,&a,&b); printf(交换之前的值是交换之前的值是:a=%d, b=%dn,a,b); swap(a,b); /swap函数的调用函数的调用printf(返回到返回到main函数后的最终交换结果是函数后的最终交换结果是:a=%d, b=%dn,a,b); int swap(int x,int y) /swap函数的定义函数的定义 int temp; temp=x; x=y; y=temp;printf(在

42、在swap函数中两个数交换的结果是函数中两个数交换的结果是:a=%d, b=%dn,x,y); 在语言中,在语言中,实参实参向向形参的形参的数据传递是数据传递是“值值传递传递”,单向传递,单向传递,只由只由实参实参传给传给形参形参,而而不不能能由形参传回来给实参。由形参传回来给实参。在内存中,在内存中,实参单元实参单元与与形参单元形参单元是不同的单是不同的单元。元。 c=max(a , b ); (main 函数)函数)max(int x, int y) int z; z=xy?x:y; return(z); (max 函数)函数)2a3bxy1015实参实参形参形参【例例】 编写求任意数之幂

43、的程序编写求任意数之幂的程序即求即求xn。分析:分析:在前面已给出了求在前面已给出了求x的的n次方的函数次方的函数power(),所以只要在主函数中,所以只要在主函数中,输入输入x和和n的值,的值,并作为并作为power()的参数,的参数,加上调用加上调用power(x,n) 语句即可,语句即可,完整的程序清单如下:完整的程序清单如下:#include void power(float x,int n) ;/*函数说明函数说明*/ void main( ) float x; int n; printf(“输入输入x=? n=? n”); scanf(“%f%d”,&x,&n); power(x

44、,n); /*函数调用函数调用*/ void power(float x,int n) /*函数定义函数定义*/ int i; double p=1.0; for (i=1,p=1;i=n;i+) p *= x; /* xn=x*x*x.*x 即即n次连乘次连乘 */ printf(“%f的的%d次方次方=%fn”,x,n,p); 7.3.4 函数的返回值函数的返回值通常,希望通过函数调用通常,希望通过函数调用使主调函数能得到使主调函数能得到一个确定的值,一个确定的值,这就是这就是函数的返回值。函数的返回值。例如例如:例例7.2中,中,c=max(2,3) ; 的值是的值是3; c=max(5

45、,2); 的值是的值是5。赋值语句赋值语句将这个函数值将这个函数值3或或5赋给变量赋给变量c。例如:例如: c=max(5,2);main()() int max(int x,int y); int a,b,c;scanf(d,d,a,b);); cmax(a,b);); /*函数的调用函数的调用*/ printf(ax isd,c);); max(int x,int y) * 定义有参函数定义有参函数max* int z zxy?x y; return(z);); return语句将被调用函数语句将被调用函数中的一个确定值带回主调中的一个确定值带回主调函数中去。函数中去。见图见图8.2中从中

46、从return语句返回的箭头。语句返回的箭头。关于函数返回值的一些说明:关于函数返回值的一些说明: 函数的返回值函数的返回值是通过函数中的是通过函数中的return语句语句获得的获得的。 return语句将语句将被调用函数中的一个被调用函数中的一个确定确定值值带回主调函数中去。带回主调函数中去。见图见图7.2中从中从return语句返回的箭头。语句返回的箭头。如果需要如果需要从被调用函数从被调用函数带回一个函数值供主带回一个函数值供主调函数使用,调函数使用,被调用函数中被调用函数中必须包含必须包含return语句。语句。如果不需要如果不需要从被调用函数从被调用函数带回函数值带回函数值可以不可以

47、不要要return语句。语句。一个函数中一个函数中可以有一个以上的可以有一个以上的return语句,语句,执行到哪一个执行到哪一个return语句,语句,哪一个语句起作哪一个语句起作用。用。return语句后面的括弧语句后面的括弧也可以不要,如也可以不要,如: “ return z; ” 等价于等价于 “ return (z);); ” max(int x,int y)return(xy?x y););return后面的值后面的值可以是一个表达式可以是一个表达式。例如,例例如,例7.2中的函数中的函数max可以改写成:可以改写成:这样的函数更为简短,只用一个这样的函数更为简短,只用一个retu

48、rn语句语句就把就把求值求值和和返回返回都解决了。都解决了。函数的返回值函数的返回值应当属于应当属于某一个确定的类型,某一个确定的类型,在定义函数时在定义函数时指定函数指定函数返回值的类型。返回值的类型。例如例如:下面是下面是3个函数的首行:个函数的首行:int max(float x,float y) /* 函数值为整型函数值为整型 */char letter(char c1,char c2) /* 函数值为字符型函数值为字符型 */ double min(int x,int y) /* 函数值为双精度型函数值为双精度型 */在在C语言中,语言中,凡不加类型说明凡不加类型说明的函数,的函数,

49、自动自动按整型按整型(int)处理。)处理。例例7.2中的中的max函数函数首行的函数类型首行的函数类型int可以可以省写,省写,用用TC 2.0编译程序时编译程序时能通过能通过,但用,但用TC+ 3.0编译程序时编译程序时不能通过,不能通过,因为因为C+要要求求所有函数所有函数都必须指定都必须指定函数类型。函数类型。因此因此,建议在定义时建议在定义时对所有函数对所有函数都指定都指定函数类函数类型。型。在定义函数时在定义函数时指定的指定的函数类型函数类型一般应该一般应该和和return语句中的语句中的表达式类型表达式类型一致。一致。如果函数值的类型如果函数值的类型和和return语句中表达式的

50、语句中表达式的值值不一致,不一致,则则以函数类型以函数类型为准。为准。对数值型数据,对数值型数据,可以自动进行类型转换可以自动进行类型转换。即即函数类型函数类型决定决定返回值的类型返回值的类型。 例例 7.3 返回值类型与函数类型不同返回值类型与函数类型不同#includevoid main() int max(float x,float y); float a,b; int c; printf(请输入请输入2个实数:个实数:n); scanf(%f,%f,&a,&b); c=max(a,b); printf(max is %dn,c); int max(float x,float y) fl

51、oat z; z=xy?x:y; return(z);自定义函数自定义函数max定义为定义为int型,型,而而return语句中的语句中的z为为float型,型,类型不一致,类型不一致,按按上述规定上述规定,先将先将z转换成转换成int型,型,然后然后max(x,y)带回一带回一个个整型值整型值2返回主调函数返回主调函数main。如果将如果将main函数中的函数中的c定定义为义为float型,型,用用%f格式输格式输出,出,也是输出也是输出2.000000。因为调用因为调用max函数得到的函数得到的是是2,然后把,然后把2赋给赋给float型型的的c则得到则得到2.000000。对于对于不带回

52、值的函数,不带回值的函数,应当用应当用“void”定定义函数为义函数为“无类型无类型”(或称或称“空类型空类型”)。)。这样,这样,系统就保证系统就保证不使函数带回任何值不使函数带回任何值,即即禁止在调用函数中禁止在调用函数中使用使用被调用函数的返回值。被调用函数的返回值。此时此时在函数体中在函数体中不得出现不得出现return语句。语句。7.4 对被调用函数的声明和函数原型对被调用函数的声明和函数原型 在一个函数中调用另一个函数在一个函数中调用另一个函数需要具备如下需要具备如下条件条件:(1) 被调用函数必须是已经定义的函数被调用函数必须是已经定义的函数(是(是库库 函数或用户自己定义的函数

53、)函数或用户自己定义的函数);(2) 如果使用库函数,应该在本文件开头如果使用库函数,应该在本文件开头加加相相 应的应的#include指令指令将调用有关库函数时将调用有关库函数时所所 需用到的信息包含到本文件中来需用到的信息包含到本文件中来。例如:。例如: #include如果如果不包含不包含文件中的信息,在程文件中的信息,在程序中序中就就无法使用无法使用输入输出库中的函数。输入输出库中的函数。若使用数学库函数中的函数若使用数学库函数中的函数,则使用:,则使用: #include(3) 如果使用如果使用自己定义的函数自己定义的函数,而该函数的而该函数的位位置在调用它的函数置在调用它的函数(m

54、ain函数函数)后面后面(在同(在同一个文件中)一个文件中),应该,应该在主函数中给出在主函数中给出被被调用函数的调用函数的声明声明。声明的作用是:声明的作用是:把函数名,函数参数的个把函数名,函数参数的个数和参数类型等信息数和参数类型等信息通知编译系统通知编译系统,以,以便在遇到函数调用时,便在遇到函数调用时,编译系统能正确编译系统能正确识别函数识别函数并检查并检查调用是否合法调用是否合法。 如果使用如果使用自己定义的函数自己定义的函数,而该函数而该函数的位的位置在调用它的函数置在调用它的函数(main函数函数)之前之前,则在则在主函数中不需要给出主函数中不需要给出被调用函数的被调用函数的声

55、明声明。函数的定义:函数的定义:对函数功能的确立,对函数功能的确立,包括指包括指定定函数的返回值类型,函数名、形参及其函数的返回值类型,函数名、形参及其类型、函数体等,类型、函数体等,它是一个完整的、独立它是一个完整的、独立的函数单位;的函数单位;函数的声明:函数的声明:把函数的返回值类型,函数名,把函数的返回值类型,函数名, 函数参数后面加分号,函数参数后面加分号,即函数定义中的第即函数定义中的第1行行(函数首部)(函数首部)加一个分号加一个分号,就成了函数原,就成了函数原型或型或函数的声明函数的声明。例例7.4 输入两个实数,用一个函数求出它们输入两个实数,用一个函数求出它们之和。之和。解

56、题思路:解题思路:用用add函数实现。首先要定义函数实现。首先要定义add函数,它为函数,它为float型,它应有两个参数,型,它应有两个参数,也应为也应为float型。型。分别编写分别编写add函数和函数和main函数,它们组成一函数,它们组成一个源程序文件个源程序文件。由于由于main函数的位置在函数的位置在add函数之前函数之前,因此因此在在main函数中对函数中对add函数进行声明函数进行声明。注意:注意:在在main函数中函数中要要给出给出add函数函数的的声明声明#include int main() float add(float x, float y); float a,b,c

57、; printf(Please enter a and b:); scanf(%f,%f,&a,&b); c=add(a,b); printf(sum is %fn,c); return 0;float add(float x,float y) float z; z=x+y; return(z); 对对add函数声明函数声明:函数定义:函数定义中的首行加分号中的首行加分号由于被调用由于被调用函数函数add的定义在的定义在main函数的函数的下面下面,因此在,因此在main函函数中数中必须给出该函数必须给出该函数的声明的声明。add函数函数的定义:的定义:包括包括函数的返回值类型,函数的返回值类

58、型,函数名、形参及其类函数名、形参及其类型、函数体。型、函数体。函数的首行加分号函数的首行加分号函数的声明。函数的声明。 为什么要用函数的首部来作为函数的声明?为什么要用函数的首部来作为函数的声明?这是为了便于对函数调用的合法性进行检查这是为了便于对函数调用的合法性进行检查.因为在函数的首部包含了因为在函数的首部包含了检查调用函数是否检查调用函数是否合法的基本信息合法的基本信息(它包括了函数的返回值类(它包括了函数的返回值类型、函数名、函数的参数个数、参数类型和型、函数名、函数的参数个数、参数类型和参数顺序),参数顺序),在检查函数调用时要求在检查函数调用时要求函数名、函数名、函数类型、参数个

59、数和参数顺序函数类型、参数个数和参数顺序必须与必须与函数函数声明一致声明一致,实参类型必须与函数声明中的形实参类型必须与函数声明中的形参类型相同参类型相同,否则就按出错处理,否则就按出错处理,这样就能这样就能保证函数的正确调用。保证函数的正确调用。函数原型的一般形式有两种函数原型的一般形式有两种:如:如: float add(float x, float y); 或者或者 float add(float, float);实际上,在函数声明中的形参名可以省写,实际上,在函数声明中的形参名可以省写,而只写形参的类型,而只写形参的类型,这是因为:这是因为:编译系统只编译系统只关心和检查参数个数和参数

60、类型,关心和检查参数个数和参数类型,而不检查而不检查参数名参数名,因为在调用函数时只要求,因为在调用函数时只要求保证实参保证实参类型与形参类型一致类型与形参类型一致,而不必考虑形参名是,而不必考虑形参名是什么。什么。若函数声明放在文件的开头,若函数声明放在文件的开头,这时下面的所这时下面的所有函数都可以使用此函数。有函数都可以使用此函数。函数类型函数类型 函数名函数名(参数类型参数类型1,参数类型,参数类型2);函数类型函数类型 函数名函数名(参数类型参数类型1,参数名,参数名1,参数类型,参数类型2,参数名,参数名2); 如果使用如果使用用户自己定义的函数,用户自己定义的函数,而该函数而该函

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论