资源描述
第七章第七章第七章第七章 函数函数函数函数第1页第第7章章 函数函数7.1 7.1 函数定义函数定义 7.2 7.2 函数调用函数调用7.3 7.3 函数说明函数说明7.4 return7.4 return语句语句7.5 7.5 函数形参加实参函数形参加实参7.6 7.6 递归递归7.7 7.7 函数变量函数变量 7.8 7.8 内部函数与外部函数内部函数与外部函数 7.9 7.9 作用域规则作用域规则第2页一、引入一、引入 某学生成绩管理系统:某学生成绩管理系统:输输入入若若干干个个学学生生姓姓名名、某某课课程程期期中中和和期期末末成成绩绩,并计算每个学生总评成绩;并计算每个学生总评成绩;计算总评成绩分数段情况;计算总评成绩分数段情况;输出全部学生姓名、期中、期末和总评成绩;输出全部学生姓名、期中、期末和总评成绩;查询某个学生总评成绩。查询某个学生总评成绩。7.1 函数定义第3页 模模块块化化设设计计思思想想:将将一一个个程程序序按按照照功功效效分解成一个一个模块。分解成一个一个模块。在在C语言中,一个函数就是一个模块。语言中,一个函数就是一个模块。第4页C程序有一个主函数和若干个其它函数程序有一个主函数和若干个其它函数主函数调用其它函数,其它函数可相互主函数调用其它函数,其它函数可相互调用调用函数需要定义后才能使用函数需要定义后才能使用函数分为库函数和自定义函数函数分为库函数和自定义函数注:注:第5页例:例:#include stdio.h void print();/*函数说明函数说明*/void main()int i;for(i=0;iy?x:y;return(z);例 无返回值函数 void swap(int x,int y)int temp;temp=x;x=y;y=temp;第9页 注意:函函数数定定义义中中不不能能包包含含另另一一个个函函数数定定义义。也也就就是是说说,函函数数定定义义不不能能嵌嵌套套。在在C语语言言中中,函函数数定定义义是是并并列列关关系系,不能一个包含另一个。不能一个包含另一个。例例:下下面面定定义义是是错错误误,该该程程序序试试图图在在print函函数数定定义中定义另一个函数义中定义另一个函数prnline。void print()putchar(*);void prnline()/*错误错误 */putchar(n);第10页7.2 函数调用1、函数调用形式、函数调用形式 调用有参函数:调用有参函数:被调用函数名(参数列表)被调用函数名(参数列表)调用无参函数:调用无参函数:被调用函数名()被调用函数名()注注:其其中中参参数数表表示示式式个个数数与与函函数数定定义义个个数数、数数据据类类型型都都应应该该匹匹配配,若若不不匹匹配配可可能能会会出出现现预预料料不不到到结结果果。此时参数叫实际参数,简称实参。此时参数叫实际参数,简称实参。第11页2、函数调用方式、函数调用方式 函数调用形式出现在表示式中。函数调用形式出现在表示式中。这种方式要求函数是带返回值。这种方式要求函数是带返回值。比如,比如,x=sum(n1,n2);函数调用形式作为独立语句出现。函数调用形式作为独立语句出现。这种情况下,函数普通不带返回值。这种情况下,函数普通不带返回值。比如:比如:print();函数调用形式作为另一个函数实参出现。函数调用形式作为另一个函数实参出现。这时,函数必须是有返回值。这时,函数必须是有返回值。printf(sum=%d,sum(n1,n2);第12页不使用自定义函数求最大值不使用自定义函数求最大值main()int a,b,c,d,m;scanf(%d%d%d%d,&a,&b,&c,&d);a=ab?a:b;c=cd?c:d;m=ac?a:c;printf(max is%d,m);使用自定义函数求最大值使用自定义函数求最大值int max(int x,int y)int z;z=xy?x:y;return(z);main()int a,b,c,d,m;scanf(%d%d%d%d,&a,&b,&c,&d);a=max(a,b);c=max(c,d);m=max(a,c);printf(max is%d,m);第13页3、函数嵌套调用、函数嵌套调用 在在C语语言言中中,函函数数是是并并列列、独独立立一一个个一一个个模模块块,经经过过调调用用与与被被调调用用相相关关联联。在在一一个个函函数数定定义义中中不不能能够够定定义义另另一一个个函函数数,不不过过允允许许在在一一个个函函数数中中调调用用另另一一个个函函数数,这这就就是是所所谓谓函函函函数数数数定定定定义不能够嵌套,函数调用则允许嵌套。义不能够嵌套,函数调用则允许嵌套。义不能够嵌套,函数调用则允许嵌套。义不能够嵌套,函数调用则允许嵌套。第14页#include stdio.hvoid print();/*函数说明函数说明*/void prnline();/*函数说明函数说明*/void main()int i;for(i=0;i10;i+)print();/*函数调用函数调用*/putchar();void print()/*函数定义函数定义*/putchar(*);prnline();/*函数调用函数调用*/return;void prnline()/*函数定义函数定义*/putchar(-);例:例:第15页调用关系图void main()int i;for(i=0;i10;i+)print();putchar();void print()putchar(*);prnline();return;void prnline()putchar(-);调用调用返回返回返回返回调用调用第16页7.3 函数说明函数说明其普通形式为:函数说明其普通形式为:函函函函数数数数返返返返回回回回值值值值数数数数据据据据类类类类型型型型说说说说明明明明符符符符 被被被被调调调调用用用用函函函函数数数数名名名名(形形形形参参参参表表表表);括括号号内内形形参参表表能能够够给给出出形形参参数数据据类类型型名名和和形形参参名名,也也能够只给出形参类型名。能够只给出形参类型名。第17页 在在语语言言中中,并并不不需需要要在在任任何何情情况况下下都都必必须须对对函函数数进进行行函函数数说说明明,能能够够省省略略对对被被调调用用函函数数函函数数说说明明用用三种情况。三种情况。(1)被调用函数函数定义出现在调用它函数之前。被调用函数函数定义出现在调用它函数之前。(2)对对C编编译译提提供供库库函函数数调调用用不不需需要要再再作作函函数数说说明明,但但必必须须把把该该函函数数头头文文件件用用#include 命命令令包包含含在在源源程程序序最前面。最前面。第18页#include stdio.h#include stdio.hvoid print()/*void print()/*函数定义函数定义函数定义函数定义*/*/putchar(*);putchar(*);void main()void main()int i;int i;for(i=0;i10;i+)for(i=0;i10;i+)print();/*print();/*函数调用函数调用函数调用函数调用*/*/putchar(n);putchar(n);例:例:第19页随堂练习随堂练习1、定义函数返回两个数中较大数,在主函数、定义函数返回两个数中较大数,在主函数中经过调用该函数求三个数之中较大数并输中经过调用该函数求三个数之中较大数并输出。编写主函数调用该函数。出。编写主函数调用该函数。第20页2、编写、编写power函数实现求函数实现求xn使程序完整。使程序完整。#include double power(double x,int n)main()int i;double p;scanf(“%d”,&);p=power(3.0,i);printf(“%f”,p);随堂练习随堂练习第21页7.4 return 语句语句函数被调用时函数被调用时,可使用可使用return语句返回语句返回,当当执行执行Return语句时语句时,程序控制马上返回到程序控制马上返回到调用环境。语法:调用环境。语法:return;或或return 表示式;表示式;第22页注意:注意:(1)return(1)return(表示式表示式);和和return return 表示式;都是正表示式;都是正确。确。(2)(2)带返回值函数只能返回一个值。带返回值函数只能返回一个值。(3)(3)若定义若定义函数不带返回值函数不带返回值,可用可用void定义函数类型定义函数类型(4)return(4)return语句中表示式与函数返回值类型不匹配语句中表示式与函数返回值类型不匹配时,以函数定义时返回类型为准。时,以函数定义时返回类型为准。第23页7.5 函数形参加实参函数形参加实参 函数调用时需要传递数据。调用函数要将实参值函数调用时需要传递数据。调用函数要将实参值传送给被调用函数形参。传送给被调用函数形参。若函数定义首部是若函数定义首部是 double power(double x,int n)/*函数定义函数定义*/调用形式是能够是调用形式是能够是power(y,m),也能够是也能够是power(3.0,5)。其中,其中,x和和n是形式参数,是形式参数,y和和m是实际参数,是实际参数,3.0和和5也是实际参数。也是实际参数。第24页函数参数调用方式:函数参数调用方式:传值传值 普通变量普通变量 传(地)址传(地)址 指针或数组指针或数组第25页 实际参数与形式参数参数个数、数据类型和次序都实际参数与形式参数参数个数、数据类型和次序都应该一致,假如数据类型不一致,系统将按照自动转应该一致,假如数据类型不一致,系统将按照自动转换规则进行转换。换规则进行转换。调用函数实参能够是调用函数实参能够是0、1或多个。实参能够是常量、或多个。实参能够是常量、变量或表示式,形参只能是变量。变量或表示式,形参只能是变量。数据传递是单向,只能是从实参向形参传递。函数数据传递是单向,只能是从实参向形参传递。函数运行时,形参改变不影响实参,实参和形参占用不一运行时,形参改变不影响实参,实参和形参占用不一样内存单元。样内存单元。当一个函数调用另一个函数时,被调用函数必须存当一个函数调用另一个函数时,被调用函数必须存在。在。形参变量只有在被调用时,才分配内存单元,形参形参变量只有在被调用时,才分配内存单元,形参只在该函数内有效。只在该函数内有效。传值调用特点传值调用特点第26页 形参是标识了一个存放空间变量名,这个存形参是标识了一个存放空间变量名,这个存放空间是在函数被调用时由系统分配,被调用函放空间是在函数被调用时由系统分配,被调用函数执行完成,则形参空间将被系统释放掉。假如数执行完成,则形参空间将被系统释放掉。假如是屡次调用,每次调用系统都会重新为形参分配是屡次调用,每次调用系统都会重新为形参分配空间。所以,形参所占空间是没有空间。所以,形参所占空间是没有“记忆记忆”。被。被调用函数内形参值不论怎样改变,都不会影响实调用函数内形参值不论怎样改变,都不会影响实参改变参改变。第27页void swap(int x,int y)int temp;printf(before change x=%d,y=%dn,x,y);temp=x;x=y;y=temp;printf(changed x=%d,y=%dn,x,y);Void main()int a,b;printf(input two number:n);scanf(%d,%d,&a,&b);printf(input number is:a=%d,b=%dn,a,b);swap(a,b);printf(input number is:a=%d,b=%dn,a,b);例例:第28页例例:求求3到到100之间全部素数。用函数判断一个数是否是之间全部素数。用函数判断一个数是否是素数,函数返回值是素数,函数返回值是1表示该数是素数,函数返回值是表示该数是素数,函数返回值是0,则表示该数不是素数。,则表示该数不是素数。#include stdio.h#include math.h int prime(int);/*函数说明函数说明 */void main()int i;for(i=3;i=100;i+)if(prime(i)=1)/*函数调用函数调用 */printf(%4d,i);printf(n,i);第29页int prime(int i)/*函数定义函数定义 */int j,k,flag=1;k=i;i=sqrt(i);for(j=2;j=i;j+)if(k%j=0)flag=0;break;return flag;第30页作作 业业1、定义一个函数、定义一个函数MYABS,求,求x+y绝对值,用绝对值,用主函数调用该函数。主函数调用该函数。2、定义一个函数、定义一个函数IS_DIGIT(ch),当,当ch是是0-9数字,返回数字,返回1,不然返回,不然返回0。用主函数调用该。用主函数调用该函数。函数。第31页#include stdio.h#include stdlib.hlong factorial(int);/*函数说明函数说明 */void main()int i,j;long sum;sum=0;for(i=0;i=1;i-)product=product*i;return product;第33页7.6 递递 归归 调调 用用 一个函数定义中使用调用形式间接或直接调一个函数定义中使用调用形式间接或直接调用自己就称为递归调用。用自己就称为递归调用。含有直接或间接调用自己函数称为递归函数。含有直接或间接调用自己函数称为递归函数。语言允许函数递归调用。执行递归函数将重复语言允许函数递归调用。执行递归函数将重复调用其本身,每调用一次就进入新一层。调用其本身,每调用一次就进入新一层。递归调用需要设置条件来终止自调用过程。递归调用需要设置条件来终止自调用过程。第34页 void f()printf(*);f();直接调用自己直接调用自己第35页 int f1(int x)int y;f2(y);直接调用自己直接调用自己 int f2(int x)int y;f1(y)第36页 void f()printf(*);f();假如在主函数中直接调用该函数,程序将假如在主函数中直接调用该函数,程序将不停地打印不停地打印“*”号,无休止地调用其本身。号,无休止地调用其本身。第37页int sum(int n)if(n1)f=power(n-1)*n;else f=1;return f;main()int n;long x;printf(“input an integer number:n”);scanf(“%d”,&n);x=power(n);printf(“%d!=%ldn”,n,x);getch();第39页编写递归程序关键是:编写递归程序关键是:(1)结构递归表示式。将结构递归表示式。将n阶问题转化为比阶问题转化为比n阶小问题(当然也能够将阶小问题(当然也能够将n阶问题转化为比阶问题转化为比n阶大阶大问题),转化以后问题与原来问题解法是相同。问题),转化以后问题与原来问题解法是相同。(2)寻找一个明确递归结束条件,称为递归出寻找一个明确递归结束条件,称为递归出口。口。第40页7.7 内部变量与外部变量内部变量与外部变量 在在C语言中,每个变量都有自己作用域,变语言中,每个变量都有自己作用域,变量作用域是指变量作用范围。按作用域可分:量作用域是指变量作用范围。按作用域可分:内部变量和外部变量。内部变量和外部变量。内部变量内部变量局部变量局部变量 定义:定义:在函数内定义,只在本函数内有效在函数内定义,只在本函数内有效 注意:注意:*main中定义变量只在中定义变量只在main中有效。中有效。*不一样函数中同名变量不一样函数中同名变量,占不一样内存单占不一样内存单元。元。*形参属于局部变量。形参属于局部变量。第41页float f1(int a)int b,c;.char f2(int x,int y)int i,j;main()int m,n;.a,b,c有效x,y,i,j有效m,n有效例题例题:不一样函数中同名变量不一样函数中同名变量main()int a,b;a=3;b=4;printf(main:a=%d,b=%dn,a,b);sub();printf(main:a=%d,b=%dn,a,b);sub()int a,b;a=6;b=7;printf(sub:a=%d,b=%dn,a,b);第42页 外部变量外部变量全局变量全局变量 定义:定义:在函数外定义在函数外定义,为本文件全部函数共用为本文件全部函数共用 有效范围有效范围:从定义变量位置开始到根源文件结从定义变量位置开始到根源文件结束束,及有及有extern说明其它源文件说明其它源文件 说明说明:extern 数据类型数据类型 变量表;变量表;注意注意:在一个源程序全部文件中只能定义一次在一个源程序全部文件中只能定义一次 若外部变量与局部变量同名,则外部变量被屏蔽若外部变量与局部变量同名,则外部变量被屏蔽 第43页例例:外部变量外部变量说明说明与与定义定义int max(int x,int y)int z;z=xy?x:y;return(z);main()extern int a,b;printf(max=%d,max(a,b);int a=13,b=-8;extern int a,b;int max()int z;z=ab?a:b;return(z);main()printf(max=%d,max();int a=13,b=-8;运行结果:max=13说明说明定义定义第44页外部变量定义与外部变量说明不一样外部变量定义与外部变量说明不一样 定义定义 说明说明u次数:次数:只能只能1次次 可说明屡次可说明屡次u位置:位置:全部函数之外全部函数之外 函数内或函数外函数内或函数外u分配内存:分配内存:分配内存分配内存,可初始化可初始化 不分配内存不分配内存,不可初始化不可初始化第45页int a=3,b=5;max(int a,int b)int c;c=ab?a:b;return(c);main()int a=8;printf(max=%d,max(a,b);例例:外部变量与局部变量外部变量与局部变量运行结果:max=8第46页int f1(int xb)extern int xa;return(xa*xb);main()extern int xb;int xa=5;printf(“xa=%d,xb=%d,result=%d”,xa,xb,f1(xa);int xa=3,xb=4;例例:外部变量定义和使用外部变量定义和使用运行结果:xa=5,xb=4,result=15第47页变量属性:变量属性:数据类型数据类型 存放类型存放类型存放属性:存放属性:生存期:变量在某一时刻存在生存期:变量在某一时刻存在-静态变量静态变量与动态变量与动态变量 作用域:变量在某区域内有效作用域:变量在某区域内有效-局部变量局部变量与全局变量与全局变量存放类型:存放类型:自动(自动(auto)存放器(存放器(register)外部(外部(extern)静态(静态(static)7.8 静态变量与动态变量静态变量与动态变量动态方式动态方式静态方式静态方式第48页存放方式存放方式静态存放:程序运行期间分配固定存放空间静态存放:程序运行期间分配固定存放空间动态存放:程序运行期间依据需要动态分配动态存放:程序运行期间依据需要动态分配存放空间存放空间生存期生存期静态变量静态变量:从程序开始执行到程序结束从程序开始执行到程序结束动态变量动态变量:从包含该变量定义函数开始执行从包含该变量定义函数开始执行至函数执行结束至函数执行结束第49页变量存放类型变量存放类型auto -自动型自动型register-存放器型存放器型static -静态型静态型extern -外部型外部型变量定义格式变量定义格式:存放类型存放类型 数据类型数据类型 变量表变量表;如如:int sum;auto int a,b,c;register int i;static float x,y;extern int a,b;第50页 依据函数是否能被其它文件中函数调用,依据函数是否能被其它文件中函数调用,将函数分为内部函数和外部函数。将函数分为内部函数和外部函数。7.9 内部函数与外部函数内部函数与外部函数 内部函数:内部函数:普通语法:普通语法:static 函数返回值类型函数返回值类型 函数名(参数表)函数名(参数表)关键字关键字static能限定函数作用域能限定函数作用域 第51页 外部函数:外部函数:普通语法:普通语法:extern 函数返回值类型函数返回值类型 函数名(参数表)函数名(参数表)外部函数需要在调用环境中说明。外部函数需要在调用环境中说明。extern 函数返回值类型函数返回值类型 函数名(参数表);函数名(参数表);第52页1、求三个数中最大数和最小数差值。、求三个数中最大数和最小数差值。2、显示、显示x到到y之间全部偶数之间全部偶数(假定假定x2 依据数据公式,很轻易将依据数据公式,很轻易将n阶问题转化成阶问题转化成n-1阶和阶和n-2阶问题,即阶问题,即f(n)=f(n-1)+f(n-2),递归出递归出口:口:n=1或者或者n=2作作 业业f=第53页
展开阅读全文