do
{ printf (\; \\n“); scanf(”%f, %f\; f1=f(xl ); f2= f ( x2 );
}while (fl*f2>=0); x=root (xl, x2); printf (''A root of equation is %8? 4f”,x); }
7.7函数的递归调用
在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用,C语 言的特点Z—就在于允许函数的递归调用。
例如:
int f (int a)
{ int b, c; c = f (b); rctum(2*c); }
显然,程序中不应出现无终止的递归调用,只应出现有限次数的、有终止的递归调用,这可 以用if语句來控制,只有在某一条件成立时才继续执行递归调用,否则就不再继续。
【例7?13】有5个人坐在一起,问第5个人多少岁?他说比第4个人大2岁。问第4个人岁 数,他说比第3个人大2岁。问第3个人,又说比第2个人大2岁。问第2个人,说比第1个人 大2岁。最后问第1个人,他说是10岁。请问第5个人多大。
age (int n) { int z;
if (n = =1) z = 10; else z = age (n ? 1) +2; return (z ); }
main ()
{printf (“%d”, age ( 5 ) ); }
【例7.14] 用递归方法求n!。
求n!可以用递推方法,即从1开始,乘2,再乘3……一直乘到n。递推法的特点是从一个 已知的事实出发,按一定规律推出下一个事实,再从这个新的已知的事实出发,再向下推出一个 新的事实……这是和递归不同的。
求n!也可以用递归方法,即5!等于4! X5,而4! =3! X4……1! =1。
float fac (int n) {float x ;
if (n<0 ) printf (\; else if( n = = 0 ||n = =1) x=l ; else x = fac (n -1 )*n; return (x ); }
main () {int n; float y;
printf (\; scanf (“ %d\; y= fac ( n );
?
printf C%d ! =.0£\\ n, y);
}
【例7.15] Hanoi(汉诺)塔问题。这是一个古典的数学问题,是一个只有用递归方法(而不可 能用其他方法)解决的问题。问题是这样的:古代有一个梵塔,塔内有3个座A、B、C,开始时 A座上有64个盘子,盘子大小不等,大的在下,小的在上。有一个老和尚想把这64个盘子从A 座移到C座,但每次只允许移动一个盘,且在移动过程中在3个座上都始终保持大盘在下,小盘 在上。在移动过程中可以利用B座,要求编程序打印出移动的步骤。
void move ( char x, char y) {printf(<4%c ----- >%c\\n\; }
void hanoi (int n, char one, char two, char three)
{讦(口 = = 1) move ( one, three);
else
{hanoi ( n - 1 , one, three, two); move (one, three);
Hanoi (n -1 , two, one, three); } } main () { int m;
printf (44 input the number of diskes:\; scanf(\;
printf (“ The step to moving % 3d diskes: \\nM, m); hanoi (m, 'A', 'B‘,’C'); }
7.8作用域和存储类型
7. 8. 1变量存在性和可见性
一、静态存储区和动态存储区
从变量值存在的时间(即生存期)角度来分,可以分为静态存储方式和动态存储方式。所谓 静态存储方式是指在程序运行期间分配固定的存储空间的方式。动态存储方式则是在程序运行期 间根据需要进行动态的分配存储空间的方式。
二、静态存储方式和动态存储方式
存储空间可以分为三部分:
1、 程序区 2、 静态存储区 3、 动态存储区
数据分别存放在静态存储区和动态存储区中。全局变量全部存放在静态存储区中。在动态存 储区中存放以下数据:
1、 函数形式参数。 2、 自动变量。
3、 函数调用时的现场保护和返回地址等。
如果在一个程序中两次调用同一函数,分配给此函数中局部变量的存储空间地址可能是不相 同的。
7. & 2局部变量和全局变量
一、 局部变量
在一个函数内部定义的变量走内部变量,它只在本函数范围内有效,也就是说只有在本函数 内才能使用它们,在此函数以外是不能使用这些变量的。这称为“局部变量”。
float fl( int x)
{ int y, z; .......
]
I x、y、z 有效
int f2 (int a , int b) { intcl,c2; ' ...... ? a、b、cl、c2 有效
} }
J
main () { int al , a2; ……
、
al、a2有效
}
【说明】
1、 主函数main中定义的变量(al, a2)也只在主函数中有效,而不因方在主函数中定义 而在整
个文件或程序中有效。主函数也不能使用其他函数中定义的变量。 2、 不同函数中可以使用相同名字时变量,它们代表不同的对象,互不干扰° 3、 形式参数也是局部变量。其他函数不能调用。
4、 在一个函数内部,可以在复合语句屮定义变量,这些变塑只在本复合语句中有效,这种 复
合语句也可称为“分程序”或“程序块”。 二、 全局变量
程序的编译单位是源程序文件,一个源文件可以包含一个或若干个函数。在函数内定义的变 量是局部变量,而在函数Z外定义的变量称为外部变量,外部变暈是全局变量(也称全程变量)。 全局变量可以为本文件屮其他函数所共用。它的有效范围为从定义变量的位置开始到本源文件结 束。
int cl = 1 ; c2 = 5; float fl (x) int x; {inty, z:
/*外部变量*/
char ah a2; char f2 (int a,int b) {int m, k; main () {inti, j,
/*外部变量*/ >
全局变量cl、c2 的作用范围。
>全局变量al、a2 的作用范围。
在一个函数中既可以使用本函数中的局部变量,又可以使用有效的全局变量。
【说明】设全局变量的作用是增加了函数间数据联系的渠道。由于函数的调用只能带回一 个返回值,因此有时可以利用全局变暈增加与函数联系的渠道,从函数得到一个以上的返回值。 为了便于区别全局变量和局部变量,在C程序设计人员中有一个不成文的约定,将全局变量名的 笫一个字母用大写表示。
【例7.16]有一个一维数组,内放10个学生成绩,写一个函数,求出平均分,最高分和最 低分。
float max = 0; min = 0; float average (float array[ ], int n) {int i;
float aver, sum=arraylOJ max=min=array[OJ; for( i = 1 ; i {讦(array[i]>Max )Max = array[i]; else if (array[i]>Min) Min = array[i]; sum二sum + array [ij; } aver=sum / n; retum(aver); } main () {float ave, score[ 10 ]; int i; for (i=0; i<10; i++) scanf (\,&score [ i ]); ave = average (score, 10); printf(Mmax = %6.2f\\nmin= %6.2f\\naverage= %6.2f\\Max, Min, ave); } 2、建议不在必要吋不要使用全局产量,因为: (1) 全局变量在程声的全部执行过程中都占用存储单元,而不是仅在需要时才开辟 单元。 (2) 它使函数的通用性降低了,因为函数在执行时要依赖于其所在的外部变量。 使用全局变量过多,会降低程序的清晰性,人们往往难以清楚地判断出每个瞬 时各个外部变量的值。 (3) 3、如果在同一个源文件中,外部变量与局部变量同名,则在局部变量的作用范围内、外部 变量 被“屏蔽”,即它不起作用。 7.8.3变量的存储类型 从变量的作用域角度来分,可以分为全局变量和局部变量。 存储类别指的是数据在内存中存储的方法。存储方法分为两大类:静态存储类和动态存储类。 具体包含四种:自动的(auto),静态的(static),寄存器的(register),外部的(extern)<> 一、 auto变量 函数小的局部变量,如不专门声明为static存储类别,都是动态地分配存储空间的,数据存 储在动态存储区中。函数中的形参和在函数中定义的变量(包括在复合语句中定义的变量),都 属此类,在调用该函数时系统会给它们分配存储空间,在函数调用结束时就自动释放这些存储空 间。因此这类局部变量称为自动变量。自动变量用关键字auto作存储类别的声明。 关键字“auto”可以省略,auto不写则隐含确定为“自动存储类别”,它属于动态存储方式。 二、 extern 变量 外部变量(即全局变量)是在函数的外部定义的,它的作用域为从变量的定义处开始,到本 程序文件的末尾。在此作用域内,全局变量可以为程序屮各个函数所引用。编译时将外部变量分 配在静态存储区。 (一) 在一个文件内声明外部变量 如果外部变量不在文件的开头定义,其有效的作用范围只限于定义处到文件终了。如果在定 义点之前的函数想引用该外部变量,则应该在引用之前用关键字extern对该变量作“外部变量声 明”。表示该变量是一个已经定义的外部变量。 【例7.17]用extern声明外部变量,扩展程序文件中的作用域。 int max (int a, int b) {int c; c = a>b?a: b; return ( c ): } main () {extern x, y; printf ( u%d max ( x, y )); } int x = 13, y =?8; (二) 在多文件的程序中声明外部变量 如果一个程序包含两个文件,在两个文件屮都要用到同一个外部变量Num,不能分别在两个 文件屮各自定义一个外部变量Num,否则在进行程序的连接时会出现“重复定义”的错误。正确 的做法是:在任一个文件中定义外部变量Num,而在另一文件中用extern对num作“外部变量 声明”。即 extern num; 三、 static变量 (一)用static声明局部变量 有吋希望函数中的局部变量的值在函数调用结束后不消失而保留原值,即其占用的存储单元 不释 放,在下一次该函数调用时,该变量已有值,就是上一次函数调用结束时的值。这时就应该 指定该局部变暈为“静态局部变暈”,用关键字static进行声明。 【例7.18]考察静态局部变量的