1、Chap_9 函数,函数的组织 递归函数 变量与函数 宏定义,一个例子,#include double fact( int n); void main() int i, m; double s=0;while( scanf(“%d“, ,本程序中出现了哪些函数?,double fact(int n) int i; double f=1;for(i=1; i=n; i+)f*= i;return f; ,函数类型_1,从用户角度: 库函数: scanf(), printf(), getchar(), putchar(), puts(), gets() fabs(), sqrt(), exp(),
2、 strcpy(), strcat(), strcmp(), strlen() isdigit(), isalphar(), isupper(), islower(), toupper(), 自定义函数: 主函数 main() 其他函数 fact(), ,#include,函数类型_2,从函数的参数: 无参函数 如 void main() 有参函数 如 double fact( int n) 从函数的返回值: 无返回值函数 如 void main() 有返回值函数 如 double fact( int n),函数体中带return 语句,【09春试题】函数的定义与调用,定义函数fact(n),
3、计算n!,形参n的类型是int,函数类型是double。 定义函数cal(x,e),计算多项式s,直到最后一项绝对值小于e,形参x和e的类型都是double,函数类型是double,要求调用fact(n)函数,调用库函数pow(x,n)来计算xn。 定义函数main(),输入两个浮点数x和e,计算多项式的值,直到最后一项的绝对值小于精度e。要求调用cal(x,e),【函数功能分析】,主函数main(): 输入 x 和 e;调用函数cal(x,e);输出结果自定义函数cal(x, e): 累加求和;调用函数fact(i), 求i!调用库函数pow(x,i) , 求xi;向主调函数main() 返
4、回s自定义函数fact(n): 求n!;向主调函数cal() 返回n!,函数调用关系,void main(),double cal(),double fact(),double pow(),x,e,i,x,i,i!,xi,s,函数的嵌套调用,定义函数fact(),/*定义函数fact(n),计算n!,形参n的类型是int,函数类型是double */ double fact( int n) int i;double f=1;for( i=1; i=n; i+)f*= i;return f;,定义函数cal(),/*定义函数cal(x,e),计算多项式s的值,直到最后一项绝对值小于e,形参x和e
5、的类型是double,函数类型是double */ #include /库函数pow(),fabs() double cal(double x, double e) double item, s=0; int i=1;do item= fact(i)/pow(x,i); s+= item; i+; while ( fabs(item)=e )return s; ,定义主函数main(),/*定义函数main(),输入两个浮点数x和e,计算多项式s的值(最后一项绝对值小于e) */ # include void main() double x,e; printf(“Input x, e:“);s
6、canf(“%lf%lf”, ,当函数定义在前,无需函数声明,9.2 递归函数,求阶乘!,解法一: 递推定义n!= 1*2*3*nfor (f=1, i=1; i=n; i+)f* = i;,解法二: 递归定义 n! 1 n=1 n*(n-1)! n1,9.2 递归函数-求!,#include void main() int n; double fact(); scanf(“%d“, ,不可写成 fact(n) = n*fact(n-1);,递归式子,递归出口,double fact(int n) double r;if (n=1)r =1;else r =n*fact(n-1);return
7、 r; ,递归函数 fact( n )的实现过程,fact(3)= 3*fact(2) 2*fact(1) fact(1)1,2*1= 2,3*2=6,递归函数,递归函数:函数体中直接或间接地调用该函数本身。 哪些问题可以用递归函数实现? 问题可逐步简化成自身较简单的形式,即递归式子,如:!()!2. 有递归的最终结束条件,即递归出口如: if (n=1) r=1;两个条件缺一不可!,Fibonacci数列,1 n=1,2fib(n) fib(n-1)+fib(n-2) n2,int fib(int n) int r ;if (n=1 | n=2) r=1 ;else r= fib(n-1)+
8、 fib(n-2);return r ; ,递归出口,递归式子,用递归函数求 1+2+n,1 n=1sigma(n) sigma(n-1)+n n1,int sigma(int n) int i,s=0;for(i=1; i=n; i+)s+=i;return s; ,int s; if (n=1) s=1 ;else s= sigma(n-1)+ n;return s ;,Hanoi 塔问题,A (源) B(辅助) C(目标),规则: 1) 一次只能搬一个盘子2)盘子只能插在A、B、C三个杆上3)大盘不能压在小盘上,定义函数hanoi(n, a, c, b): 将n个盘子从a杆搬到c杆, 中
9、间可借助b杆,Hanoi 塔: 1个盘子,A (源) B(辅助) C(目标),Hanoi 塔:2个盘子,A (源) B(辅助) C(目标),(1),(2),(3),问:3个、4个、更多个盘子如何搬?,算法分析,递归出口: 当只有一个盘子(n=1),直接将它从源塔a搬到目标塔c; 递归式子: 当超过1个盘子(n1): 先将上面的n-1个盘子搬到辅助塔b; 再将第n个盘子从源塔搬a到目标塔c; 最后将放在辅助塔b上的n-1个盘子搬到目标塔c,Hanoi 塔,A B C,A B C,n,n-1,n-1,n-1,hanoi(n,a,c,b),hanoi(n-1,a,b,c),hanoi(n-1,b,c
10、,a),Hanoi 塔的递归函数,void hanoi( int n, char a, char c, char b)if (n=1) printf( “%c%cn” , a, c );else hanio( n-1, a, b, c);printf( “%c%cn” , a, c );hanio( n-1, b, c, a);,直接搬1个盘子 ac,相关主函数,#include void hanoi( int n, char a, char c, char b); void main() int n;printf(“Input n:”); scanf(“%d”, ,9.3 变量与函数,在函数
11、内定义的变量(包括形参) 局部变量 作用范围:本函数内部在复合语句内定义的变量作用范围:复合语句内部 全局变量:在函数以外定义的变量,不属于任一函数作用范围:整个程序有效(包括各函数),全局or 局部? -在何处定义,局部变量 & 全局变量,#include int x=1 ; void main( ) int a=2; int b=3 ; f( ); int y=4 ; void f( ) int x=5, b=6 ;. int a=7 ;,x=? a=? y=?,b=?,x=? a=? y=?,如果函数中的局部变量与全局变量重名,则以局部变量起作用。,int x=1; int f(int
12、x) return(x+); void main( ) int y;y=f(2) ;x=f(x) ;printf(“%d %d“, y, x); 输出,x=1 a=2 y=4,b未定义,x=5 a=7 y=4,x=1,2 1,如果某函数的局部变量与全局变量重名,则局部变量起作用。 不要滥用全局变量,它会产生副作用,局部变量 & 全局变量,9.3.2 变量生命周期和静态局部变量,自动变量(auto) 普通的局部变量。int x, y ; auto int x, y ; 特点:执行到定义语句,系统动态产生存储单元;一旦函数结束,系统自动回收存储单元。,int f( int y ) int x=1;
13、return y+ x+; void main() f( f( f( 1) ) ); ,x=12,y=1,返回2,x=12,y=2,返回3,x=12,y=3,返回4,静态变量(static) 静态局部变量静态全局变量特点:不随函数的结束而自动回收存储单元。同一函数的两次调用,所用的存储单元为同一个单元,保存原来的值。,x=12,y=1,返回2,x=23,y=2,返回4,x=34,y=4,返回7,int f( int y ) static int x=1;return y+ x+; void main() f( f( f( 1) ) ); ,静态变量(static)的说明: 静态变量若不赋初值,
14、自动取或0。 局部静态变量在函数调用结束后,只要主函数未结束,它仍保留原值,当再次进入函数时才能使用。 函数中的静态变量,仅在第一次调用时才赋初值。,【例9-9】写出下列程序的输出结果。 void fun(int k) ; void main() int k;for (k=1; k=3; k+) fun(k); void fun(int k) static int a; /a初值=0 printf(”%d,”, a); a += k ; /静态变量a保留上一次调用产生的值 ,运行结果: 0,1,3,、外部变量(extern)在一个文件中要使用在另一文件中定义的全局变量,应使用外部变量: ext
15、ern x;、寄存器变量(register)定义: register int x ;register char c ; 使用寄存器变量比普通变量运行速度更快,9.4 宏定义,格式:#define 宏名 宏定义字符串 作用:编译时,把程序中所有与宏名相同的字符串,替换成 宏定义字符串#define PI 3.14#define arr_size 4 说明:宏名一般用大写字母,以与变量名区别 宏定义不是语句,后面不得跟分号 宏定义可以嵌套使用#define PI 3.14#define AA 2*PI*PI4 宏名中间不能有空格,ARR_SIZE,#define AA for (i=0; i10;
16、 i+),空格,不可: #define A A for (i=0; i10; i+),宏定义的作用,1、保持符号常量精度的一致性及可读性,如PI 2、数组大小的定义#define N 6main() int aN;for (i=0; iN; i+)scanf(“%d”, 3、 可以实现一些简单的函数 4、 对程序的一些固定的书写可以偷一下懒,但不得降低程序的可读性。,带参数的宏定义,#define f(a) a*a*avoid main( ) /* 水仙花数 */ int i, x, y, z;for (i=1; i1000; i+) x=i%10; y=i/10%10; z=i/100 ;i
17、f(x*x*x+y*y*y+z*z*z=i)printf(“%dn” ,i);,F(x+y) (x+y)3,#define F(a) (a)*(a)*(a),水仙花数:13+53+33=153,if ( F(x) + F(y) + F(z) =i ),= x+y*x+y*x+y,带参数的宏定义实现简单的函数功能 例:用宏实现两个变量值的交换 #define F(a,b,c) c=a; a=b; b=c;main( ) int x,y,temp ;scanf(“%d%d” ,temp=x ; x=y ; y=temp ;,编译时被替换,注意:(1) 带参数的宏定义不是函数,宏与函数是两种不同的概
18、念。 (2) 宏可以实现简单的函数功能,【例9-12】程序输出结果?,#define F(x) x - 2 #define Q(x) x*F(x) void main() printf(“%d,%d“, Q(3), Q(Q(3) ) ; ,分析:先替换所有宏,再统一代入计算不可一边代入一边计算 Q(3) = x*F(x) = x*x-2 = 3*3-2 = 7 Q(Q(3) = Q(x*x-2) = x*x-2* F(x*x-2) = x*x-2* x*x-2-2 = 3*3-2*3*3-2-2 = -13运行结果:7 -13,#define F(x) x-2 #define Q(x) x*F(x),代入x=3,代入x=3,小结与作业,小结: 函数的嵌套调用 递归函数 局部/全局变量,静态变量 宏 作业: 1,2,3 6,8,9上机实验题12,