第5章 函数与宏定义2017年5月(第12_13周).ppt
12022/10/25第第5 5章章 函数与宏定义函数与宏定义主要内容主要内容5.1 5.1 函数的定义与调用函数的定义与调用5.2 5.2 函数间参数的传递函数间参数的传递5.3 5.3 变量的属性变量的属性5.4 5.4 函数的递归调用函数的递归调用5.5 5.5 宏定义宏定义2n模块化程序设计模块化程序设计n基本思想:将一个基本思想:将一个大程序大程序按功能按功能分割成分割成一些一些小模块小模块n分而治之分而治之5.1 函数的定义与调用函数的定义与调用C C语言是模块化程序设计语言语言是模块化程序设计语言C C程序结构程序结构n一个完整的一个完整的语言程序:语言程序:2 2种种1 1、是由一个、是由一个main()函数(又称主函数)和若干个其函数(又称主函数)和若干个其它函数结合而成的,它函数结合而成的,如:如:例例1.21.22 2、或仅由一个、或仅由一个main()函数构成,函数构成,如:引例,例如:引例,例1.11.1例例1.2 求两个数中的较大数求两个数中的较大数#include /*预处理理*/int max(int x,int y)/*定义定义max函数函数*/int z;if(xy)z=x;else z=y;return z;int main()/*定义主函数定义主函数*/int a,b,c;scanf(%d,%d,&a,&b);c=max(a,b);printf(max=%dn,c);return 0;4程序运行结果:程序运行结果:键盘输入键盘输入 5,9程序输出为程序输出为 max=9 调用调用max函函数进行数进行处理处理分工:分工:主函数主函数 输入、输出输入、输出,max函数函数 处理处理联系:联系:主函数主函数把输入的把输入的2个实个实参传给参传给max函数的函数的2个个形参,形参,max函数函数把求出的最把求出的最大值返回给主函数输大值返回给主函数输出出 52022/10/25n什么是函数?什么是函数?n预先编好的一段能实现特定功能的模块预先编好的一段能实现特定功能的模块。n函数名:通常以该功能命名。函数名:通常以该功能命名。例例 int max(int x,int y)/*/*定义定义maxmax函数函数*/int z;if(xy)z=x;else z=y;return z;n作用:简化程序,模块化。作用:简化程序,模块化。函数名函数名(名字而已)(名字而已)函数体:函数体:对对需要实现的需要实现的功能的详细功能的详细描述描述(本质)(本质)n函数是语言程序的函数是语言程序的基本单位基本单位n每个程序有且只有一个每个程序有且只有一个main函数函数n总是从总是从main函数开始执行,在函数开始执行,在main函数结束函数结束n函数是完成既定任务的函数是完成既定任务的功能体功能体n它涵盖了数学函数和一般过程它涵盖了数学函数和一般过程n在在C C语言中:语言中:库函数库函数P317P317和和自定义函数自定义函数P113P113n编写程序编写程序就是编写一个个组成程序的就是编写一个个组成程序的自定义函数自定义函数6程序与函数程序与函数72022/10/25n分类:分类:1.1.标准函数标准函数(库函数)(库函数)nC C语言中语言中事先编好事先编好一批常用的功能一批常用的功能n分若干个分若干个头文件头文件存放,如:存放,如:stdio.h,math.h,string.h,time.h等,参考等,参考P317P317n使用标准函数前,必须加其所在的头文件,即使用标准函数前,必须加其所在的头文件,即预编译命令预编译命令例如:例如:若要用若要用 printf()函数函数 则必须要用则必须要用#include 2.2.用户自定义函数用户自定义函数n用户用户根据需要自己编写根据需要自己编写的函数,如:例的函数,如:例1.2中中 max()第第5章详解章详解函数的一般结构函数的一般结构n任何任何函数函数都是由都是由函数首部函数首部和和函数体函数体两部分组成。两部分组成。n其一般结构如下:其一般结构如下:函数返回值的类型函数返回值的类型 函数名函数名(函数参数表函数参数表)说明语句部分;说明语句部分;执行语句部分;执行语句部分;8函数首部函数首部函数体函数体例例 有参函数有参函数 int max(int x,y)int z;z=xy?x:y;return(z);合法标识符合法标识符函数返回值类型函数返回值类型无返回值无返回值voidvoid函数体函数体函数类型函数类型 函数名(函数名(形参类型说明表形参类型说明表)说明部分说明部分语句部分语句部分 例例 有参函数有参函数 int max(int x,int y)int z;z=xy?x:y;return(z);注意:注意:x,y 要分别说明要分别说明n一般格式一般格式5.1.1 函数函数的的定义定义例例 无参函数无参函数 printstar()printf(“*n”);或或 printstar(void)printf(“*n”);例例 空函数空函数dummy()函数体为空函数体为空n形式参数与实际参数形式参数与实际参数n形形式式参参数:数:定义函数时定义函数时函数名后面括号中的变量名函数名后面括号中的变量名n实实际际参参数:数:调用函数时调用函数时函数名后面括号中的表达式函数名后面括号中的表达式 c=max(a,b);(main 函数函数)(max 函数函数)max(int x,int y)int z;z=xy?x:y;return(z);例例 比较两个数并输出大者比较两个数并输出大者#include int main()int a,b,c;int max(int x,int y);scanf(%d,%d,&a,&b);c=max(a,b);printf(Max is%d,c);return 0;max(int x,int y)int z;z=xy?x:y;return(z);形参形参实参实参n n说明:说明:说明:说明:n n实参必须有确定的值实参必须有确定的值实参必须有确定的值实参必须有确定的值n n形参必须指定类型形参必须指定类型形参必须指定类型形参必须指定类型n n形参与实参形参与实参形参与实参形参与实参类型一致,个数相同类型一致,个数相同类型一致,个数相同类型一致,个数相同n n若形参与实参类型不一致,自动按形参类型转换若形参与实参类型不一致,自动按形参类型转换若形参与实参类型不一致,自动按形参类型转换若形参与实参类型不一致,自动按形参类型转换 函数调用转换函数调用转换函数调用转换函数调用转换n函数的返回值函数的返回值n返回语句返回语句n形式:形式:return(表达式表达式);或或 return 表达式表达式;或或 return;n功能:功能:n使程序控制从被调用函数返回到调用函数中,使程序控制从被调用函数返回到调用函数中,n同时把返同时把返回回值带给调用函数值带给调用函数n说明:说明:n函数中可有多个函数中可有多个return语句语句,执行到哪个执行到哪个return语句,那么该语句,那么该return语句就起作用。语句就起作用。n若无若无return语句,遇语句,遇 时,自动返回调用函数时,自动返回调用函数n若函数类型与若函数类型与return语句中表达式值的类型不一致,按前者为语句中表达式值的类型不一致,按前者为准,自动转换准,自动转换-函数调用转换函数调用转换nvoid型型函数函数用来明确表明函数不带回任何值用来明确表明函数不带回任何值例例 无返回值函数无返回值函数void swap(int x,int y)int temp;temp=x;x=y;y=temp;例例 函数返回值类型自动转换为函数类型函数返回值类型自动转换为函数类型#includeint main()float a,b;int c;int max(float x,float y);scanf(%f,%f,&a,&b);c=max(a,b);printf(Max is%dn,c);return 0;int max(float x,float y)float z;z=xy?x:y;return(z);输入:输入:1.5,4.7结果:结果:Max is 4n函数调用的一般形式函数调用的一般形式 函数名函数名(实参表实参表);n说明:说明:n实参与形参实参与形参个数相等,类型一致,按顺序一一个数相等,类型一致,按顺序一一对应对应5.1.2 函数的调用函数的调用n函数调用的方式函数调用的方式n 函数语句函数语句例例printstar();printf(“Hello,World!n”);n 函数表达式函数表达式例例m=max(a,b)*2;n 函数参数函数参数例例printf(“%d”,max(a,b);m=max(a,max(b,c);n对被调用函数的声明和函数原型对被调用函数的声明和函数原型n对被调用函数要求:对被调用函数要求:n必须是必须是已存在已存在的函数的函数n库函数库函数:使用使用#include n用户自定义函数用户自定义函数:主调函数对被调函数作主调函数对被调函数作函数函数声明声明n函数声明函数声明n一般形式:一般形式:函数类型函数类型 函数名函数名(形参类型形参类型11形参名形参名1,1,.);.);或:或:函数类型函数类型 函数名函数名();();(不提倡使用)(不提倡使用)n作用:告诉编译系统作用:告诉编译系统函数类型、参数个数及类型,函数类型、参数个数及类型,以便检验以便检验n函数声明与函数定义不同函数声明与函数定义不同n函数声明位置:函数声明位置:程序的数据说明部分(函数内或外)程序的数据说明部分(函数内或外)n下列情况下,可不作函数声明下列情况下,可不作函数声明被调用函数定义出现在主调函数之前被调用函数定义出现在主调函数之前在所有的函数定义之前,在函数的外部已做了函数声明在所有的函数定义之前,在函数的外部已做了函数声明#include int main()float add(float x,float y);/*/*函数声明函数声明*/float a,b,c;scanf(%f,%f,&a,&b);c=add(a,b);printf(sum is%f,c);return 0;float add(float x,float y)float z;z=x+y;return(z);例例 函数声明举例函数声明举例#include float add(float x,float y)float z;z=x+y;return(z);int main()float a,b,c;scanf(%f,%f,&a,&b);c=add(a,b);printf(sum is%f,c);return 0;被调函数出现在被调函数出现在主调函数之前,主调函数之前,不必函数声明不必函数声明#include long sum(int a,int b);long factorial(int n);int main()int n1,n2;long a;scanf(%d,%d,&n1,&n2);a=sum(n1,n2);printf(a=%ld,a);return 0;long sum(int a,int b)long c1,c2;c1=factorial(a);c2=factorial(b);return(c1+c2);long factorial(int n)long f=1;int i;for(i=1;i=n;i+)f=f*i;return(f);long sum(int a,int b);long factorial(int n);文件包含编译预处理命令文件包含编译预处理命令函数声明函数声明函数定义函数定义函数调用函数调用函数调用函数调用函数返回值函数返回值形参形参实参实参n函数的嵌套调用函数的嵌套调用nC C规定:函数规定:函数不可嵌套定义不可嵌套定义,但可以,但可以嵌套调用嵌套调用函数函数n示意图:示意图:main()调用函数调用函数a结束结束a函数函数b函数函数调用函数调用函数b例例 求三个数中最大数和最小数的差值求三个数中最大数和最小数的差值#include int dif(int x,int y,int z);int max(int x,int y,int z);int min(int x,int y,int z);void main()int a,b,c,d;scanf(%d%d%d,&a,&b,&c);d=dif(a,b,c);printf(Max-Min=%dn,d);return 0;int dif(int x,int y,int z)return max(x,y,z)-min(x,y,z);int max(int x,int y,int z)int r;r=xy?x:y;return(rz?r:z);int min(int x,int y,int z)int r;r=xy?x:y;return(rz?r:z);main()调用函数调用函数dif输出输出结束结束dif函数函数max函数函数调用函数调用函数max调用函数调用函数minmin函数函数232022/10/255.2 函数间参数的传递函数间参数的传递n一个函数的函数体,只有在该函数被调用时才会执行。一个函数的函数体,只有在该函数被调用时才会执行。n形参形参是被调函数中变量,是被调函数中变量,实参实参是主调函数中的变量,每个实参是主调函数中的变量,每个实参都是一个表达式,其类型必须与形参相符。都是一个表达式,其类型必须与形参相符。n函数被调用时才为形参分配存储单元,并将实参值赋值给形参。函数被调用时才为形参分配存储单元,并将实参值赋值给形参。n函数的参数传递指函数的参数传递指的就是实参与形参结合的过程,将实参值赋的就是实参与形参结合的过程,将实参值赋值给形参,也称为虚实结合传值调用。值给形参,也称为虚实结合传值调用。n分:分:值传递值传递、址传递址传递n n值传递值传递n n函数调用时函数调用时函数调用时函数调用时,为形参分配单元为形参分配单元为形参分配单元为形参分配单元,并将实参的值并将实参的值并将实参的值并将实参的值复制复制复制复制到形参中;到形参中;到形参中;到形参中;n n调用结束,形参单元调用结束,形参单元调用结束,形参单元调用结束,形参单元被释放被释放被释放被释放,实参单元仍保留并维持原值。实参单元仍保留并维持原值。实参单元仍保留并维持原值。实参单元仍保留并维持原值。n n特点:特点:特点:特点:形参与实参占用不同的内存单元形参与实参占用不同的内存单元形参与实参占用不同的内存单元形参与实参占用不同的内存单元;单向单向单向单向传递传递传递传递例例 计算计算x x的立方的立方#include float cube(float x)return(x*x*x);int main()float a,product;printf(Please input value of a:);scanf(%f,&a);product=cube(a);printf(Cube of%.4f is%.4fn,a,product);return 0;xaproduct1.21.21.728000运行结果:运行结果:Please input value of a:1.2Cube of 1.2000 is 1.7280Press any key to continue7 71111x:x:y:y:调用前:调用前:调用结束:调用结束:7 71111x:x:y:y:例例 交换两个数交换两个数#include int main()int x=7,y=11;printf(x=%d,ty=%dn,x,y);printf(swapped:n);swap(x,y);printf(x=%d,ty=%dn,x,y);return 0;void swap(int a,int b)int temp;temp=a;a=b;b=temp;调用参数传递:调用参数传递:7 71111a:a:b:b:7 71111x:x:y:y:swap:7 71111x:x:y:y:11117 7a:a:b:b:temptemp运行结果:运行结果:x=7,y=11 swapped:x=7,y=11值传递方式,单向传递值传递方式,单向传递没有换过来!没有换过来!解决方法:址传递解决方法:址传递n址传递址传递n方式:函数调用时,将数据的方式:函数调用时,将数据的存储地址存储地址作作为参数传递给形参为参数传递给形参n特点特点:形参与实参占用形参与实参占用同样同样的存储单元的存储单元“双向双向”传递传递实参和形参必须是实参和形参必须是地址地址常量或变量常量或变量282022/10/255.3 变量的属性变量的属性n变量变量:对程序中数据存储的抽象:对程序中数据存储的抽象n变量变量数据类型数据类型:对变量的运算属性的抽象,决定了:对变量的运算属性的抽象,决定了该变量的取值范围和运算方法。该变量的取值范围和运算方法。n变量的其它属性,例如:变量的其它属性,例如:(1 1)变量的)变量的作用域作用域:代表一个变量在什么范围内有效、可见。:代表一个变量在什么范围内有效、可见。(2 2)变量的)变量的生存期生存期:代表一个变量什么时候创建,什么时候:代表一个变量什么时候创建,什么时候撤销。撤销。(3 3)变量的)变量的存储区存储区:代表变量存储在哪种类型的存储器中以:代表变量存储在哪种类型的存储器中以及采用什么方式存储。及采用什么方式存储。5.3.1 变量的作用域变量的作用域n局部变量(内部变量)局部变量(内部变量)n定义:在定义:在函数内函数内定义,定义,只在本函数内有效只在本函数内有效float f1(int a)int b,c;.char f2(int x,int y)int i,j;int main()int m,n;.a,b,c有效有效x,y,i,j有效有效m,n有效有效例例 局部变量局部变量n说明:说明:n不同函数中同名变量,不同函数中同名变量,是不同的是不同的2 2个变量个变量#include void sub()int a,b;a=6;b=7;printf(sub:a=%d,b=%dn,a,b);int 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);return 0;运行结果:运行结果:main:a=3,b=4sub:a=6,b=7main:a=3,b=4n形参属于局部变量形参属于局部变量n全局变量全局变量(外部变量)(外部变量)n定义:在定义:在函数外函数外定义的变量定义的变量n有效范围:从有效范围:从定义变量的位置开始定义变量的位置开始到本源文件结束到本源文件结束。n说明:说明:n习惯将全局变量的第一个字母大写习惯将全局变量的第一个字母大写n应尽量少使用全局变量应尽量少使用全局变量,n若外部变量与局部变量同名,则外部变量被屏蔽若外部变量与局部变量同名,则外部变量被屏蔽int p=1,q=5;float f1(int a)int b,c;.int f3().char c1,c2;char f2(int x,int y)int i,j;main()int m,n;.c1,c2的作用范围的作用范围p,q的作用范围的作用范围例例 全局变量全局变量#include int a=3,b=5;int max(int a,int b)int c;c=ab?a:b;return(c);int main()int a=8;printf(max=%d,max(a,b);return 0;例例 全局变量与局部变量同名全局变量与局部变量同名运行结果:运行结果:max=8max=85.3.2 变量的生存期变量的生存期静态存储:程序运行期间分配固定存储空间静态存储:程序运行期间分配固定存储空间动态存储:程序运行期间根据需要动态分配存储空间动态存储:程序运行期间根据需要动态分配存储空间n 内存用户区内存用户区程序区程序区静态存储区静态存储区动态存储区动态存储区全局变量、局部静态变量全局变量、局部静态变量形参变量形参变量局部动态变量(局部动态变量(auto register)函数调用现场保护和返回地址等函数调用现场保护和返回地址等n 生存期生存期静态变量:从程序开始执行到程序结束静态变量:从程序开始执行到程序结束动态变量:从包含该变量定义的函数开始执行至函数动态变量:从包含该变量定义的函数开始执行至函数执行结束执行结束362022/10/25n存储类别指的是数据在内存中存储的方式存储类别指的是数据在内存中存储的方式n如:静态存储和动态存储。如:静态存储和动态存储。可将作用域和生存期整合成可将作用域和生存期整合成4 4种存储类型。种存储类型。(1 1)自动变量)自动变量auto(2 2)静态局部变量)静态局部变量static(3 3)寄存器变量)寄存器变量register(4 4)全局变量)全局变量extern5.3.3 变量的存储类别变量的存储类别nauto变量变量n函数中的局部变量,如不做专门的说明,属于函数中的局部变量,如不做专门的说明,属于动态存储类,存储在动态存储区。这类变量称动态存储类,存储在动态存储区。这类变量称为自动变量,用关键字为自动变量,用关键字(autoauto)作存储类型的声作存储类型的声明明 ,也可省略关键字,也可省略关键字(autoauto)。int f(int a)auto int b,c=3;/*等价于等价于 int b,c=3;*/#include f(int a)auto int b=0;static int c=3;b=b+1;c=c+1;return(a+b+c);int main()int a=2,i;for(i=0;i3;i+)printf(%d,f(a);printf(n);return 0;nstatic局部静态变量局部静态变量n局部变量的值在函数调用后不消失而保留原值,局部变量的值在函数调用后不消失而保留原值,n用用static加以声明。加以声明。运行结果运行结果:7 8 9n n说明:说明:说明:说明:局部静态变量属静态存储类别,在静态存储区内分配存储单元。在程局部静态变量属静态存储类别,在静态存储区内分配存储单元。在程局部静态变量属静态存储类别,在静态存储区内分配存储单元。在程局部静态变量属静态存储类别,在静态存储区内分配存储单元。在程序整个运行期都不释放。序整个运行期都不释放。序整个运行期都不释放。序整个运行期都不释放。局部静态变量的初值只赋一次。局部静态变量的初值只赋一次。局部静态变量的初值只赋一次。局部静态变量的初值只赋一次。如果不对静态变量赋初值,则其变量的初值为如果不对静态变量赋初值,则其变量的初值为如果不对静态变量赋初值,则其变量的初值为如果不对静态变量赋初值,则其变量的初值为0 0 0 0;虽然局部静态变量在函数调用结束后仍然存在,但其它函数是不能引虽然局部静态变量在函数调用结束后仍然存在,但其它函数是不能引虽然局部静态变量在函数调用结束后仍然存在,但其它函数是不能引虽然局部静态变量在函数调用结束后仍然存在,但其它函数是不能引用它的。用它的。用它的。用它的。n n什么情况下使用局部静态变量:什么情况下使用局部静态变量:什么情况下使用局部静态变量:什么情况下使用局部静态变量:需要保留函数上一次调用结束时的值。需要保留函数上一次调用结束时的值。需要保留函数上一次调用结束时的值。需要保留函数上一次调用结束时的值。例例例例 打印打印打印打印1 1 1 1到到到到5 5 5 5的阶乘的阶乘的阶乘的阶乘#include int fac(int n)static int f=1;f=f*n;return(f);int main()int i;for(i=1;i=5;i+)printf(%d!=%dn,i,fac(i);return 0;运行结果:运行结果:1!=12!=23!=64!=245!=120如果初始化后,变量只被引用而不必改变其值,用局部静态变量较好。如果初始化后,变量只被引用而不必改变其值,用局部静态变量较好。nregister变量变量n局部变量的值存储在寄存器中,局部变量的值存储在寄存器中,n用关键字用关键字register说明说明 。#include int fac(int n)register int i,f=1;for(i=1;i=n;i+)f=f*i;return(f);int main()int i;for(i=1;i=5;i+)printf(%d!=%dn,i,fac(i);return 0;n n说明:说明:说明:说明:只有局部自动变量和形式参数可作为寄存器变量;只有局部自动变量和形式参数可作为寄存器变量;只有局部自动变量和形式参数可作为寄存器变量;只有局部自动变量和形式参数可作为寄存器变量;局部静态变量不能定义为寄存器变量。局部静态变量不能定义为寄存器变量。局部静态变量不能定义为寄存器变量。局部静态变量不能定义为寄存器变量。寄存器变量个数有限;寄存器变量个数有限;寄存器变量个数有限;寄存器变量个数有限;由于对寄存器的存取速度远高于对内存的存取速度,使用寄存器由于对寄存器的存取速度远高于对内存的存取速度,使用寄存器由于对寄存器的存取速度远高于对内存的存取速度,使用寄存器由于对寄存器的存取速度远高于对内存的存取速度,使用寄存器变量可以提高执行效率。但是实际上这个工作可以由编译器自动变量可以提高执行效率。但是实际上这个工作可以由编译器自动变量可以提高执行效率。但是实际上这个工作可以由编译器自动变量可以提高执行效率。但是实际上这个工作可以由编译器自动完成,完成,完成,完成,一般程序设计者不必要特别定义使用一般程序设计者不必要特别定义使用一般程序设计者不必要特别定义使用一般程序设计者不必要特别定义使用registerregisterregisterregister变量。变量。变量。变量。n extern声明外部变量声明外部变量n全局变量是在函数外部定义的,有效范围从定义变量的位置开始到本全局变量是在函数外部定义的,有效范围从定义变量的位置开始到本源文件结束。静态存储。源文件结束。静态存储。n可以可以使用使用extern 扩展外部变量的作用域扩展外部变量的作用域。n在一个文件内声明外部变量在一个文件内声明外部变量:在定义外部变量的定义点之前的函数在定义外部变量的定义点之前的函数想引用该外部变量,则在引用之前用关键字想引用该外部变量,则在引用之前用关键字extern做做“外部变量声外部变量声明明”,声明时类型名可省略,声明时类型名可省略。#include int max(int x,int y)int z;z=xy?x:y;return(z);int main()extern A,B;printf(%dn,max(A,B);return 0;int A=13,B=-8;/没见过吧?没见过吧?运行结果:运行结果:13n用用static声明外部变量声明外部变量n在定义外部变量时加一个在定义外部变量时加一个static声明,则这些声明,则这些外部变量只能被本文件使用,而不能被其他文外部变量只能被本文件使用,而不能被其他文件引用。称为静态外部变量件引用。称为静态外部变量局部变量局部变量外部变量外部变量存储类别存储类别autoregister局部局部static外部外部static外部外部存储方式存储方式动态动态静态静态存储区存储区动态区动态区寄存器寄存器静态存储区静态存储区生存期生存期函数调用开始至结束函数调用开始至结束程序整个运行期间程序整个运行期间作用域作用域定义变量的函数或复合语句内定义变量的函数或复合语句内本文件本文件其它文件其它文件赋初值赋初值每次函数调用时每次函数调用时编译时赋初值,只赋一次编译时赋初值,只赋一次未赋初值未赋初值不确定不确定自动赋初值自动赋初值0或空字符或空字符n变量存储类别小结变量存储类别小结u局部变量默认为局部变量默认为auto型型u局部局部static变量具有全局寿命和局部可见性变量具有全局寿命和局部可见性u局部局部static变量具有可继承性变量具有可继承性uextern不是变量定义不是变量定义(而是声明变量而是声明变量),),可扩展外部可扩展外部变量作用域变量作用域5.4 函数的递归调用函数的递归调用n n定义定义定义定义:函数直接或间接的调用自身函数直接或间接的调用自身函数直接或间接的调用自身函数直接或间接的调用自身f()调调f调调f2调调f1f1()f2()int f(int x)int y,z;z=f(y);.return(2*z);例例 5 5个人坐一起,问第个人坐一起,问第5 5个人多少岁?他说比第个人多少岁?他说比第4 4个人大个人大2 2岁。问第岁。问第4 4个人多少个人多少岁?他说比第岁?他说比第3 3个人大个人大2 2岁。问第岁。问第3 3个人多少岁?他说比第个人多少岁?他说比第2 2个人大个人大2 2岁。问第岁。问第1 1个个人多少岁?他说人多少岁?他说1010岁。请问第岁。请问第5 5个人多大?个人多大?#include int age(int n)int c;if(n=1)c=10;else c=age(n-1)+2;return(c);int main()printf(%dn,age(5);return 0;age(5)=age(4)+2age(4)=age(3)+2age(3)=age(2)+2age(2)=age(1)+2age(1)=10age(2)=12age(3)=14age(4)=16age(5)=18递递 归归 调调 用用递递 归归 返返 回回主函数主函数 1 2 3 4 3 2返回返回1 例例 求求n的阶乘的阶乘#include int factorial(int n)int f;if(n0)printf(n0,data error!);else if(n=0|n=1)f=1;else f=factorial(n-1)*n;return(f);int main()int n,y;printf(Input a integer number:);scanf(%d,&n);y=factorial(n);printf(%d!=%15d,n,y);return 0;482022/10/25n例例5.12 汉诺塔汉诺塔(Tower of Hanoi)问题问题参考参考P131P131492022/10/25汉诺塔问题示意图汉诺塔问题示意图n算法描述算法描述:将:将n n个盘子从个盘子从A A针移到针移到C C针可以分针可以分解为下面解为下面3 3个步骤:个步骤:(1 1)将)将A A针上针上n-1n-1个盘子借助个盘子借助C C针移动到针移动到B B针上。针上。(2 2)将)将A A针上剩下的针上剩下的1 1个盘子移动到个盘子移动到C C针上。针上。(3 3)将)将B B针上针上n-1n-1个盘子借助个盘子借助A A针移动到针移动到C C针上。针上。502022/10/25n编写程序:编写程序:#include void move(char src,char dest);void hanoi(int n,char src,char medium,char dest);int main()int m;printf(请输入盘子数:请输入盘子数:);scanf(%d,&m);printf(移动移动%d盘子步骤如下:盘子步骤如下:n,m);hanoi(m,A,B,C);/A,B,C代表代表3根针根针return 0;void hanoi(int n,char src,char medium,char dest)if(n=1)move(src,dest);elsehanoi(n-1,src,dest,medium);move(src,dest);hanoi(n-1,medium,src,dest);void move(char src,char dest)printf(%c-%cn,src,dest);512022/10/255.5 宏定义宏定义n编译之前进行编译之前进行的的预处理预处理n格式:格式:n以以“#”开头开头n单独占用一行单独占用一行n末尾没有分号末尾没有分号n可以出现在程序中的任何位置。可以出现在程序中的任何位置。n参考参考P134P134522022/10/25(1 1)文件包含指令)文件包含指令#include(2 2)宏定义)宏定义#define、#undef(3 3)条件编译)条件编译#if、#ifdef、#ifndef、#else、#elif、#endif532022/10/25本章小结本章小结n函数函数n定义、调用定义、调用n形参、实参形参、实参n函数返回值函数返回值n函数间参数传递函数间参数传递n函数的递归调用函数的递归调用n变量的属性变量的属性n局部变量局部变量、全局变量全局变量n动态存储方式动态存储方式、静态存储方式静态存储方式n4 4种存储类别种存储类别n宏定义宏定义