C语言程序设计吉林大学珠海学院计算机系李昱E-mail:826450556@QQ.comTEL:13631284762(66762)第8章函数学习的意义模块化程序设计方法:人们在求解某个复杂问题时,通常采用逐步分解、分而治之的方法,也就是将一个大问题分解成若干个比较容易求解的小问题,然后分别求解。程序员在设计一个复杂的应用程序时,往往也是把整个程序划分成若干个功能较为单一的程序模块,然后分别予以实现,最后再把所有的程序模块象达积木一样装配起来,这种在程序设计中分而治之的策略,被称为模块化程序设计方法。子模块1子模块2子模块n学习的意义功能模块1功能模块2功能模块n……………………软件项目C语言程序C语言函数搭积木学习的意义使用函数,不仅可以实现程序的模块化,程序设计得简单和直观,提高了程序的易读性和可维护性。编写自定义函数库。把一些常用的或某些特定功能的程序制作成自己的函数库,以供随时调用,这样可以大大减轻日后编写代码的工作量。通过对函数的学习,掌握模块化程序设计的理念,为将来进行团队合作,协同完成大型应用软件奠定一定的基础。学习目标正确理解函数在C语言程序设计中的作用和地位;理解函数、形参、实参、作用域、生存期的概念;掌握各种函数的定义、原型声明和调用的方法;理解全局变量、局部变量、静态变量、静态函数的作用域和生存期;掌握递归函数的编写规则;掌握利用工程管理程序的方法;学习内容函数概述函数的定义与调用无参数无返回值的函数无参数有返回值的函数带参数无返回值的函数带参数有返回值的函数函数参数传递的传递方式变量的作用域和生存期变量的存储类型函数的嵌套和递归调用函数的作用域函数应用综合举例本章小结8.1函数概述1、函数的概念函数其实就是一段可以重复调用的、功能相对独立完整的程序段。C是函数式语言必须有且只能有一个名为main的主函数C程序的执行总是从main函数开始,在main中结束函数不能嵌套定义,可以嵌套调用2、函数的分类从用户角度标准函数(库函数):由系统提供用户自定义函数从函数形式无参数无返回值无参数有返回值有参数无返回值有参数有返回值使用库函数应注意:1、函数功能2、函数参数的数目和顺序,及各参数意义和类型3、函数返回值意义和类型4、需要使用的包含文件8.2函数的定义和调用1、无参数无返回值的函数定义格式void函数名(void){变量声明部分执行部分}函数体空类型,表明函数无返回值,不可省!表明无参数,可缺省!必须为合法的标识符函数用途此类函数用于完成某项固定的处理任务,执行完成后不向调用者返回函数值。它类似于其它语言的过程。函数的原型声明void函数名(void);或void函数名();C语言规定,对函数调用之前必须对其原型加以声明,否则会出现编译错!1、无参数无返回值的函数函数的调用函数名();注意:不能将这种函数调用赋值给任何变量,因为它没有返回值。调用时,()中间不能有void。实例#includestdio.h#includemath.hvoidshowerror();//声明showerror函数的原型voidmain(){inta;scanf(%d,&a);while(a0){showerror();scanf(%d,&a);}printf(sqrt(a)=%.2f\n,sqrt(a));}voidshowerror()//函数的定义,无参数无返回值{printf(inputerror!\n);//函数体,没有声明变量}调用showerror函数返回注意:对函数调用之前,必须要先声明或先定义,否则编译错!编写C程序的一般格式文件包括(如includestdio.h等,用于标准库库函数原型声明)常量定义(根据需要而定,如#definePI3.1415等)变量定义(根据需要而定)用户自定义函数原型声明main函数用户自定义函数函数的返回形式①rerurn(表达式);//有返回值②rerutn表达式;//有返回值③return;//无返回值使程序控制从被调用函数返回到调用函数中,如果有返回值,同时把返值带给调用函数。功能说明函数中可以有多个return语句。在无返回值的函数中,return语句的形式只能是第③种形式。例如:voidshowyes(){charkey;key=getch();if(toupper(key)!='Y')return;printf(YES!);}函数showyes的功能是:如果输入的字符不是'Y'或'y',则什么都不输出,直接返回,否则,输出YES!标准库函数,其功能是将小写字符转换成大写字符2、无参数有返回值的函数定义格式返回值类型符函数名(void){变量声明部分执行部分}函数体可以为除数组类型外的任何类型,缺省时,默认为int型表明无参数,可缺省!必须为合法的标识符函数用途此类函数用于完成某项固定的处理任务,执行完成后向调用者返回函数值。函数的原型声明返回值类型符函数名(void);或返回值类型符函数名();2、无参数有返回值的函数函数的调用函数名(void);或变量=函数名();实例#includestdio.h#includeconio.h#includectype.hintsum();voidmain(){inttot;tot=sum();if(tot==-1)printf(\nnotselect!\n);elseprintf(\ntheresultis:%d\n,tot);}intsum(){inti,tot=0;charkey;key=getche();if(key!='0'&&key!='1')return(-1);for(i=(key=='0')?2:1;i=100;i+=2)tot+=i;return(tot);}声明sum函数的原型调用sum函数函数的定义,无参数有返回值变量声明部分函数sum的功能是:输入‘0’:计算1~100之间所有偶数之和输入‘1’:计算1~100之间所有奇数之和2、无参数有返回值的函数函数的返回表达式的值即是函数的返回值;函数体中一般都包含return(表达式)语句,如果没有,函数也会返回一个值。这个值是不可预知的,将会使程序可能犯有逻辑错;一般情况下,表达式值的类型应与函数返回值类型一致;当return(表达式)语句中的表达式的类型与函数的返回值类型不一致时,编译器将对表达式进行强制类型转换,将表达式的值强制转换成函数返回值类型,然后返回给调用者。格式rerurn(表达式);或rerutn表达式;说明#includestdio.hintsum();voidmain(){intx;x=sum();printf(“x=%d\n,x);}intsum(){inti,tot=0;for(i=1;i=100;i++)tot+=i;}因sum函数无return语句,x的值将是无法预知的!应加上returntot;语句intfunc(){floatf=5;f=f/2;return(f);}函数将返回2,而不是2.5注意:如果不将函数调用赋值给任何变量,它的返回值将被丢弃!3、有参数无返回值的函数定义格式void函数名(类型符1形参名1,类型符2形参名2,…,类型符n形参名n){变量声明部分执行部分}函数体函数用途此类型的函数主要是根据形参的值来进行某种事务的处理。灵活性上要比无形参的函数强,它更能体现调用函数与被调函数之间的数据联系。函数的原型声明void函数名(类型符1形参名1,类型符2形参名2,…,类型符n形参名n);或void函数名(类型符1,类型符2,…,类型符n);形参列表至少要有一项,形参之间要用逗号“,”分开指明形参类型不允许对形参赋初值3、有参数无返回值的函数函数调用函数名(实参1,实参2,……,实参n);实参可以是常量、变量、表达式、函数等注意事项:(1)实参列表中的实参必须与函数定义时的形参数量相同、类型相符。(2)赋值对应关系:实参1-形参1实参2-形参2……实参n-形参n(3)实参表求值顺序(即实参赋值给形参的顺序)因系统而定。TC、BC、VC均是自右向左,也就是说最右边的实参最先赋值给最右边的形参,最左边的实参最后赋值给最左边的形参。但VC与TC、BC在具体赋值时稍有不同,注意它们之间的区别。3、有参数无返回值的函数#includestdio.hvoidcompare(inta,intb);voidmain(){inti=2;compare(i,i++);printf(i=%d\n,i);}voidcompare(inta,intb){printf(a=%db=%d\n,a,b);if(ab)printf(ab\n);elseif(a==b)printf(a=b\n);elseprintf(ab\n);}i为实参a、b为形参原型声明a=3b=2abi=3运行结果(在TC或BC下)a=2b=2a=bi=3运行结果(在VC下)①i2i++2ab实参形参2②i+13③3i2i++2ab实参形参①2②234、有参数有返回值的函数定义格式返回值类型符函数名(类型符1形参名1,……,类型符n形参名n){变量声明部分执行部分}函数体函数用途此类型的函数主要是根据形参的值来进行某种事务的处理,同时可将处理后的结果值返回给调用函数。它最能体现调用函数与被调函数之间的数据联系。函数的原型声明返回值类型符函数名(类型符1形参名1,……,类型符n形参名n);或返回值类型符函数名(类型符1,类型符2,……,类型符n);形参列表4、有参数有返回值的函数函数调用函数名(实参1,实参2,……,实参n);或变量名=函数名(实参1,实参2,……,实参n);#includestdio.hintmax(inta,intb);//函数的原型声明voidmain(){inta,b,c;scanf(%d%d,&a,&b);c=max(a,b);//函数调用(a、b为实参)printf(thebiggestnumberis:%d\n,c);}intmax(inta,intb)//函数定义(a、b为形参){return(ab?a:b);}运行结果:59↙thebiggestnumberis95、函数调用和函数说明小结函数调用函数语句:例:printstar();printf(“Hello,World!\n”);函数表达式:例:m=max(a,b)*2;函数参数:例:printf(“%d”,max(a,b));m=max(a,max(b,c));函数说明对被调用函数要求:必须是已存在的函数库函数:#include*.h用户自定义函数:函数类型说明函数说明一般形式:函数类型函数名(形参类型[形参名],…..);或函数类型函数名();作用:告诉编译系统函数类型、参数个数及类型,以便检验函数定义与函数说明不同函数说明位置:程序的数据说明部分(函数内或外)下列情况下,可不作函数说明若函数返值是char或int型,系统自动按int型处理被调用函数定义出现在主调函数之前有些系统(如BC、VC)要求函数说明指出函数返值类型和形参类型,并且对void和int型函数也要进行函数说明例:函数说明举例floatadd(floatx,floaty){floatz;z=x+y;return(z);}voidmain(){floata,b,c;scanf(%f,%f,&a,&b);c=add(a,b);printf(sumis%f,c);}被调函数出现在主调函数之前,不必函数说明voidmain(){floatadd(float,float);//函数原型声明floata,b,c;scanf(%f,%f,&a,&b);c=add(a,b);printf(sumis%f,c);}floatadd(floatx,floaty){floatz;z=x+y;ret