1、函数定义函数定义函数调用函数调用函数参数及函数间的数据传递函数参数及函数间的数据传递数组与函数参数数组与函数参数函数的嵌套与递归函数的嵌套与递归变量的存储属性及作用域变量的存储属性及作用域编译预处理编译预处理 主主 要要 内内 容容函数的分类函数的分类 函数的基本结构函数的基本结构函数的定义函数的定义 基本内容:基本内容:1.1.从用户使用的角度看,函数可分为两种:从用户使用的角度看,函数可分为两种:(1)(1)标准函数标准函数(即库函数即库函数)。例如例如:sin(x):sin(x)、pow(x,y)pow(x,y)、exp(x)exp(x)、fabs(x)fabs(x)(2)(2)用户自定
2、义函数。用户自定义函数。2.2.从函数的作用上看,函数可分为两种:从函数的作用上看,函数可分为两种:(1)(1)完成某种计算并返回一个函数值。完成某种计算并返回一个函数值。(2)(2)完成某种操作不返回函数值。完成某种操作不返回函数值。3.3.从函数的形式上看,函数可分为两种:从函数的形式上看,函数可分为两种:(1)(1)无参函数,即不带参数表的函数。无参函数,即不带参数表的函数。(2)(2)有参函数,即带有参数表的函数。有参函数,即带有参数表的函数。函数的基本结构如下:函数的基本结构如下:存储类型类型说明符函数名存储类型类型说明符函数名(形式参数表形式参数表)形式参数说明;形式参数说明;内部
3、变量说明;内部变量说明;执行语句;执行语句;说明:说明:(1)(1)函数名是函数名是C C语言中任一合法的标识符。语言中任一合法的标识符。(2)(2)形式参数表可以由零个或多个形式参数组成。形式参数表可以由零个或多个形式参数组成。(3)(3)形式参数说明必须在花括号形式参数说明必须在花括号“”之前。之前。(4)(4)函数中最外层花括号括起来的部分称为函数体。函数中最外层花括号括起来的部分称为函数体。(5)(5)按照函数的基本结构可知,按照函数的基本结构可知,C C语言不允许在一个语言不允许在一个 函数内又包含另一个函数,构成程序的多个函函数内又包含另一个函数,构成程序的多个函 数在程序中都是平
4、行的。数在程序中都是平行的。(6)(6)函数返回值的数据类型为该函数的数据类型。函数返回值的数据类型为该函数的数据类型。基本概念:基本概念:函数的定义:是指按照函数的定义:是指按照C C语言所规定的函数基本结语言所规定的函数基本结 构编写一段所需功能的源程序。构编写一段所需功能的源程序。1.1.空函数的定义形式空函数的定义形式 空函数的形式为:空函数的形式为:函数名函数名()()例如:例如:merge()merge()注:空函数是没有任何操作的函数。注:空函数是没有任何操作的函数。2.2.无参函数的定义形式为:无参函数的定义形式为:类型说明符类型说明符 函数名函数名()()void print
5、star()void printstar()内部变量说明;内部变量说明;printf(”printf(”*n”);n”);执行语句;执行语句;printf(”printf(”*n”);n”);printf(”printf(”*n”);n”);打印打印:printf(”:printf(”*n”);n”);*printf(”printf(”*n”);n”);*#include#includestdio.hstdio.h *void main()void main()*printstar();printstar();说明:说明:被调用的无参函数并不是不返回值,而是不被调用的无参函数并不是不返回值,而
6、是不 返回有用的值,通常是一个不确定的值。返回有用的值,通常是一个不确定的值。例如:例如:x=printstar();x=printstar();printf(“%d”,x);printf(“%d”,x);为了表明一个被调用函数不返回值,在函数定义中为了表明一个被调用函数不返回值,在函数定义中可将它定义为可将它定义为“空类型空类型”。其一般形式为。其一般形式为 :void void 函数名函数名()()内容变量说明;内容变量说明;执行语句;执行语句;注:其中 void void 即为“空类型”的函数类 型说明符,void void 又称无类型说明符。为使程序严谨明确,防止错误 调用,凡不要求返
7、回值的无参 函数,一般应定义为“void”类型。3.3.有参函数定义的形式为:有参函数定义的形式为:存储类型存储类型 类型说明符类型说明符 函数名函数名(形式参数形式参数)形式参数说明;形式参数说明;内部变量说明;内部变量说明;执行语句;执行语句;例:例:#include power(int x,int n)#include power(int x,int n)void main()void main()int i,p;int i,p;int n,m,k;p=1;i=1;int n,m,k;p=1;i=1;scanf(scanf(”%d,%d%d,%d”,&m,&n);for(;i=n;i+)
8、,&m,&n);for(;i=n;i+)k=power(m,n);p=p k=power(m,n);p=p*x;x;printf(printf(”%d%d”,k);return(p);,k);return(p);注注:类型说明符省时类型说明符省时,其函数返回值为整型或字其函数返回值为整型或字 符型。符型。函数的调用形式函数的调用形式 函数的调用方式函数的调用方式 对被调用函数的说明对被调用函数的说明基本内容:基本内容:调用函数对被调用函数进行调用调用函数对被调用函数进行调用 一般形式为一般形式为:函数名函数名(实参表实参表);在在C C语言中,调用函数对被调用函数调用时,按函语言中,调用函数对
9、被调用函数调用时,按函数在程序中出现的位置来分,可以有以下三种调用方数在程序中出现的位置来分,可以有以下三种调用方式。式。1.1.函数调用语句由函数调用加上分号构成,函数调用语句由函数调用加上分号构成,在调用函数中可作为在调用函数中可作为 一个独立的语句。一个独立的语句。#include#includestdio.hstdio.h void main()void main()printfstar();printfstar();2.2.函数表达式的一个运算对象函数表达式的一个运算对象 函数调用作为一个运算对象直接出现在一个函数调用作为一个运算对象直接出现在一个表达式中,这时要求函数带回一个确定的
10、值以表达式中,这时要求函数带回一个确定的值以参加表达式的运算,这种表达式称为函数表达参加表达式的运算,这种表达式称为函数表达式。式。例如例如:s=3.14159:s=3.14159*pow(r,2);pow(r,2);3.3.作为函数调用的一个实际参数作为函数调用的一个实际参数 将函数调用放在另一个函数调用的实际参数将函数调用放在另一个函数调用的实际参数表中,以其值作为该函数调用的一个实参,传表中,以其值作为该函数调用的一个实参,传递给被调用函数的形序。递给被调用函数的形序。例如例如:printf(:printf(”%d%d”,power(m,n);,power(m,n);在程序中调用另一个函
11、数时,要满足以在程序中调用另一个函数时,要满足以下三个条件:下三个条件:(1)(1)被调用函数必须存在是函数调用的必被调用函数必须存在是函数调用的必 要条件,这个被调用函数可以是用户要条件,这个被调用函数可以是用户 自定义函数或库函数。自定义函数或库函数。(2)(2)若是库函数,还必须用若是库函数,还必须用#include#include命令命令 将有关库函数所需的信息包含到本文将有关库函数所需的信息包含到本文 件中。件中。例如:例如:#include#include stdio.hstdio.h(3)(3)若是用户自定义的函数,且该函数与调若是用户自定义的函数,且该函数与调 用它的函数用它的
12、函数(即调用函数即调用函数)在同一个源文在同一个源文 件中,则在调用函数中应对被调用函数件中,则在调用函数中应对被调用函数 返回值的类型加以说明。返回值的类型加以说明。这种类型说明的一般形式为:这种类型说明的一般形式为:类型说明符类型说明符 被调用函数名被调用函数名()();其中,类型说明与被调用函数在函数定其中,类型说明与被调用函数在函数定义中的函数类型说明一致。这种说明称为义中的函数类型说明一致。这种说明称为显式说明。显式说明。C C语言允许在以下三种情况下,在调用函数中,可以语言允许在以下三种情况下,在调用函数中,可以不在调用函数前对被调用函数作函数类型说明。不在调用函数前对被调用函数作
13、函数类型说明。(1)(1)当被调用函数返回值是一个整型或字符型数据时,当被调用函数返回值是一个整型或字符型数据时,可以不作说明,系统将自动按整型说明处理。可以不作说明,系统将自动按整型说明处理。(2)(2)当被调用函数的定义当被调用函数的定义(注意,不是函数类型说明注意,不是函数类型说明)在在 调用函数之前,调用函数调用它时,可以对被调用调用函数之前,调用函数调用它时,可以对被调用 函数类型不作说明。因为调用时系统已预先知道了函数类型不作说明。因为调用时系统已预先知道了 它已定义的函数类型,会自动按其类型说明处理。它已定义的函数类型,会自动按其类型说明处理。(3)(3)在文件开头,所有函数定义
14、之前,在函数外部已说在文件开头,所有函数定义之前,在函数外部已说 明了函数类型时,则各个调用函数中可以不对所调明了函数类型时,则各个调用函数中可以不对所调 用的函数再作函数用的函数再作函数 类型说明,但各个被调用函数类型说明,但各个被调用函数 的定义中,仍须对函数类型进行说明。的定义中,仍须对函数类型进行说明。#include#includestdio.hstdio.h char str(char c);char str(char c);float ct(float f);float ct(float f);int gt(ink k);int gt(ink k);void main()floa
15、t ct(float f)void main()float ct(float f).char str(char c)int gt(ink k)char str(char c)int gt(ink k).函数参数函数参数 函数间的数据传递函数间的数据传递 基本内容:基本内容:形式参数和实际参数就是函数参数,它们都是函数形式参数和实际参数就是函数参数,它们都是函数间数据传递的载体。间数据传递的载体。1.1.关于形式参数关于形式参数 凡 出 现 在 函 数 定 义 中 函 数 名 后 圆 括 号 内凡 出 现 在 函 数 定 义 中 函 数 名 后 圆 括 号 内 的参数称为形式参数,形式参数又称为
16、形参或哑元。的参数称为形式参数,形式参数又称为形参或哑元。形参说明的一般形式为:形参说明的一般形式为:形参类型说明符形参类型说明符 形参表;形参表;例如例如:int power(x,n):int power(x,n)int x,n;int x,n;或或 int power(int x,int n)int power(int x,int n)2.2.关于实际参数关于实际参数实际参数实际参数:凡出现在调用语句的函数名后圆括凡出现在调用语句的函数名后圆括 号内的参数,又称为实参或实元。号内的参数,又称为实参或实元。例如例如:y=power(2,3);:y=power(2,3);实际参数实际参数(实参
17、实参):):实参可以是常量、已赋值的变量或表达式实参可以是常量、已赋值的变量或表达式;实参在次序、类型和个数上应与相应形参实参在次序、类型和个数上应与相应形参 表中的形参保持一致。表中的形参保持一致。通常,当需要从调用函数中传值通常,当需要从调用函数中传值(或传地址或传地址)到被调用函数中的形参时,那些变量或值应到被调用函数中的形参时,那些变量或值应作为实参。作为实参。函数间的数据传递有两种情况:函数间的数据传递有两种情况:(一一)实参向形参的传递;实参向形参的传递;(二二)被调用函数向主调用函数的回传。被调用函数向主调用函数的回传。一、实参向形参的数据传递一、实参向形参的数据传递 当调用函数
18、调用有参函数时,通常需当调用函数调用有参函数时,通常需要将实参所包含的数据传递给相应的形要将实参所包含的数据传递给相应的形参。参。实参向形参的数据传递有两种不同的方式实参向形参的数据传递有两种不同的方式:1.1.值传递值传递 当实参是常数、变量、数组元素或可计算的当实参是常数、变量、数组元素或可计算的表达式时表达式时(事实上,常数、变量、数组元素都事实上,常数、变量、数组元素都是简单的表达式是简单的表达式),对应的形参是变量,此时,对应的形参是变量,此时,主调用函数将实参的值传递到为被调用函数,主调用函数将实参的值传递到为被调用函数形参设置的临时变量存储单元中,调用结束形参设置的临时变量存储单
19、元中,调用结束后,形参单元被释放,实参仍保持原值不变。后,形参单元被释放,实参仍保持原值不变。这种只能由实参向形参的数据传递称为这种只能由实参向形参的数据传递称为“值传值传递递”,即单向传递。,即单向传递。#include#includestdio.hstdio.h void main()void main()int f(int a,int b);int f(int a,int b);int x=1,y=2,z;static int a=0,1,2,3,4;int x=1,y=2,z;static int a=0,1,2,3,4;z=f(x,y);z=f(x,y);printf(“z=%d,x
20、=%d,y=%d printf(“z=%d,x=%d,y=%dn”,z,x,y);n”,z,x,y);z=f(a3,a4);z=f(a3,a4);printf(“z=%d,a3=%d,a4=%d printf(“z=%d,a3=%d,a4=%dn,”,z,a3,a4);n,”,z,a3,a4);z=f(x,y+1);z=f(x,y+1);printf(“z=%d,x=%d,y=%d printf(“z=%d,x=%d,y=%dn”,z,x,y);n”,z,x,y);运行结果运行结果:a=3,b=6 a=3,b=6f(int a,int b)z=3,x=1,y=2 f(int a,int b)z
21、=3,x=1,y=2 a=a+2;b=b+4;a=5,b=8 a=a+2;b=b+4;a=5,b=8 printf(“a=%d,b=%d printf(“a=%d,b=%dn”,a,b);z=5,a3=3,a4=4 n”,a,b);z=5,a3=3,a4=4 return(a);a=3,b=7 return(a);a=3,b=7 z=3,x=1,y=2 z=3,x=1,y=22.2.地址传递地址传递 当实参是数组名或指针型变量当实参是数组名或指针型变量(或实参变量地或实参变量地址址)时,实参向形参传递的是地址。时,实参向形参传递的是地址。#include#includestdio.hstdio
22、.h void main()void main()void swap(int void swap(int*x,int x,int*y);y);int a,b;int a,b;scanf(“%d,%d”,&a,&b);scanf(“%d,%d”,&a,&b);if(ab)swap(&a,&b);if(a0)b=sign(a);else if(x0)printf(printf(“b=%db=%dn n”,b);return(1);,b);return(1);else else return(-1);return(-1);#include#includestdio.hstdio.h void mai
23、n()void main()float a,b;float a,b;int max(float x,float y),m;int max(float x,float y),m;scanf(“%f,%f”,&a,&b);scanf(“%f,%f”,&a,&b);m=max(a,b);m=max(a,b);printf(“printf(“n max=%dn max=%dn”,m);n”,m);max(float x,float y)max(float x,float y)float n;float n;n=xy?x:y;n=xy?x:y;return(n);return(n);程序运行结果如下:程
24、序运行结果如下:2.3,4.52.3,4.5 max=4max=4 2.2.利用函数参数的利用函数参数的“地址传递地址传递”返回多个值。返回多个值。#include#include void main()void main()float a,b,c,d,e,f;float a,b,c,d,e,f;float calcu(float x,float y,float float calcu(float x,float y,float*r,float r,float*s,float s,float*t);t);scanf(“%f,%f”,&a,&b);scanf(“%f,%f”,&a,&b);f=c
25、alcu(a,b,&c,&d,&e);f=calcu(a,b,&c,&d,&e);printf(“printf(“n c=%fn c=%fn d=%fn d=%fn e=%fn e=%fn f=%fn f=%fn”,c,d,e,f);n”,c,d,e,f);float calcu(float x,float y,float float calcu(float x,float y,float*r,float r,float*s,float s,float*t)t)*r=x+y;r=x+y;*s=x-y;s=x-y;*t=xt=x*y;y;return(x/y);return(x/y);程序运行结
26、果如下程序运行结果如下:10.0,2.010.0,2.0c=12.000000c=12.000000d=8.000000d=8.000000e=20.000000 e=20.000000 f=5.000000f=5.000000基本内容:函数间数组参数的数据传送。函数间数组参数的传递是程序设计中常见的操作。采用地址传递方式,可以圆满解决数组中大量数据在函数间传递的问题。函数间数组的传递通常有以下四种方式。函数间数组的传递通常有以下四种方式。(1)(1)传递数组的实参用数组名,按收数组的形参传递数组的实参用数组名,按收数组的形参 用确定大小的数组名。用确定大小的数组名。例如例如:实参用数组为实参
27、用数组为:sort(a);:sort(a);形参用数组为形参用数组为:void sort(b):void sort(b)int b10 int b10 设:起始地址为设:起始地址为100 (100 (注注:整型数组元素占整型数组元素占2 2个字节个字节)数组数组:a0 a1 a2 a3 a4 a5 a6:a0 a1 a2 a3 a4 a5 a6a7 a8 a9a7 a8 a9地址地址:100 102 104 106 108 10a 10c 10e 110 112:100 102 104 106 108 10a 10c 10e 110 112 数组数组:b0 b1 b2 b3 b4 b5 b6
28、b7 b8 b9:b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 用函数实现有用函数实现有1010个元素的数组选择排序。程序如下:个元素的数组选择排序。程序如下:#include#include stdio.hstdio.hvoid main()void main()int a10,i;int a10,i;void sort(int array10);void sort(int array10);for(i=0;i10;i+)for(i=0;i10;i+)scanf(“%d”,&ai);scanf(“%d”,&ai);sort(a);sort(a);printf(“The sort
29、ed array:printf(“The sorted array:n”);n”);for(i=0;i10;i+)for(i=0;i10;i+)printf(“%d,”,ai);printf(“%d,”,ai);printf(“n”);printf(“n”);程序运行结果如下:程序运行结果如下:输出输出:The sorted array:The sorted array:输入输入:9,8,7,6,5,4,3,2,1,0 0,1,2,3,4,5,6,7,8,9:9,8,7,6,5,4,3,2,1,0 0,1,2,3,4,5,6,7,8,9 程序中以数组名程序中以数组名a a为实参为实参,即表示数
30、组的起始地址即表示数组的起始地址.所以所以,当把数组当把数组传递给函数时,实质上传递的是数组的首地址。实参数组的起始地传递给函数时,实质上传递的是数组的首地址。实参数组的起始地址传递给形参数组后,两个数组就共占用同一段内存单元址传递给形参数组后,两个数组就共占用同一段内存单元(如图如图6.16.1的示的示)。从而实现了函数间数组的传递。从而实现了函数间数组的传递.void sort(int array10)void sort(int array10)int i,j,k,t;int i,j,k,t;for(i=0;i9;i+)for(i=0;i9;i+)k=i;k=i;for(j=i+1;j10
31、;j+)for(j=i+1;j10;j+)if(arrayjarrayk)if(arrayjarrayk)k=j;k=j;t=arrayk;t=arrayk;arrayk=arrayi;arrayk=arrayi;arrayi=t;arrayi=t;(2)(2)用数组名作实参数组,用不确定大小的数组名作形参。用数组名作实参数组,用不确定大小的数组名作形参。#include#include stdio.hstdio.hvoid main()void main()void chang(int array,int n);void chang(int array,int n);int a10,i;in
32、t a10,i;for(i=0;i10;i+)for(i=0;i10;i+)scanf(“%d,”,&ai);scanf(“%d,”,&ai);chang(a,10);chang(a,10);printf(“The result:printf(“The result:n”);n”);for(i=0;i10;i+)for(i=0;i10;i+)printf(“%d,”,ai);printf(“%d,”,ai);printf(“printf(“n”);n”);void chang(int array,int n)void chang(int array,int n)int i;int i;for(
33、i=0;in;i+)for(i=0;i0)if(arrayi0)arrayi=1;arrayi=1;else if(arrayi0)else if(arrayi0)arrayi=-1;arrayi=-1;else else arrayi=0;arrayi=0;程序运行结果如下:程序运行结果如下:1,2,3,0,0,-1,-2,-3,0,61,2,3,0,0,-1,-2,-3,0,6The result:The result:1,1,1,0,0,-1,-1,-1,0,1,1,1,1,0,0,-1,-1,-1,0,1,(3)(3)传递数组的实参用数组名传递数组的实参用数组名,按收数组的形参用指针变
34、量。按收数组的形参用指针变量。例如例如:求数组求数组a a中的最大元素值。程序如下:中的最大元素值。程序如下:#include#include stdio.hstdio.h void main()void main()int maxv(int int maxv(int*p,int n),m;p,int n),m;static int a10=5,3,2,3,8,9,12,6,7,10;static int a10=5,3,2,3,8,9,12,6,7,10;m=maxv(a,10);m=maxv(a,10);printf(“The maximum value:printf(“The maxim
35、um value:n”);n”);printf(“%d”,m);printf(“%d”,m);int maxv(int int maxv(int*p,int n)p,int n)int i,t=int i,t=*p;p;for(i=0;in;i+,p+)for(i=0;it)t=pt)t=*p;p;return(t);return(t);程序运行结果如下:程序运行结果如下:The maximum value:12(4)(4)多维数组名作函数参数。多维数组名作函数参数。使二维数组使二维数组a33a33的行列互换。程序如下:的行列互换。程序如下:#include#include stdio.hst
36、dio.hvoid main()void main()void void convert(int array33);convert(int array33);int i,j,a33;int i,j,a33;for(i=0;i3;i+)for(i=0;i3;i+)for(j=0;j3;j+)for(j=0;j3;j+)scanf(“%d,”,&aij);scanf(“%d,”,&aij);convert(a);convert(a);printf(“The result:printf(“The result:n”);n”);for(i=0;i3;i+)for(i=0;i3;i+)for(j=0;j
37、3;j+)for(j=0;j3;j+)printf(“%3d”,aij);printf(“%3d”,aij);printf(“printf(“n”);n”);void convert(int array33)void convert(int array33)int i,j,t;int i,j,t;for(i=0;i3;i+)for(i=0;i3;i+)for(j=i+1;j3;j+)for(j=i+1;j3;j+)t=arrayij;t=arrayij;arrayij=arrayji;arrayij=arrayji;arrayji=t;arrayji=t;程序运行结果如下:程序运行结果如下:输
38、入输入:输出输出:1,2,31,2,3 The result:The result:4,5,64,5,6 1 4 7 1 4 77,8,97,8,9 2 5 8 2 5 8 3 6 9 3 6 9(1)(1)应该在调用函数中用数组名作为实参,而在接收应该在调用函数中用数组名作为实参,而在接收 数组的被调用函数中,相应的形参可以被说明为数组的被调用函数中,相应的形参可以被说明为 数组或指针变量。数组或指针变量。(2)(2)实参数组与形参数组类型应一致,否则会出错。实参数组与形参数组类型应一致,否则会出错。(3)(3)实参数组和形参数组的大小可以一致,也可以不实参数组和形参数组的大小可以一致,也可
39、以不 一致,在编译时对形参数组的大小不作检查,只一致,在编译时对形参数组的大小不作检查,只 是将实参数组的首地址给形参数组,因此,在被是将实参数组的首地址给形参数组,因此,在被 调用函数中说明形参时应注意数组的大小和访问调用函数中说明形参时应注意数组的大小和访问 越界问题,以免出错。越界问题,以免出错。(4)(4)形参数组是一维时,可以不指定大小,高维时,建形参数组是一维时,可以不指定大小,高维时,建 议指定各维的大小。议指定各维的大小。(5)(5)当字符串数组传递给函数时,也是采用地址传递当字符串数组传递给函数时,也是采用地址传递 方式,把字符串首地址传递给函数的形参。函数方式,把字符串首地
40、址传递给函数的形参。函数 的形参可以是字符数组形式,也可以是字符指针。的形参可以是字符数组形式,也可以是字符指针。在函数中对字符串处理时,判别字符数组是否结在函数中对字符串处理时,判别字符数组是否结 束的方法通常不是采用计数的办法,而是以是否束的方法通常不是采用计数的办法,而是以是否 读到读到00来判别结束。来判别结束。(6)(6)再次强调,数组名作函数参数时,不是再次强调,数组名作函数参数时,不是“值传递值传递”,不是单向传递,而是,不是单向传递,而是“地址传递地址传递”,是双向传,是双向传 递。虽然可以将数组元素作为参数传递到函数中,递。虽然可以将数组元素作为参数传递到函数中,但数组一旦比
41、较大,处理起来但数组一旦比较大,处理起来 就很麻烦,一般不就很麻烦,一般不 提倡用数组元素作为参数传递的方式提倡用数组元素作为参数传递的方式函数的嵌套调用函数的嵌套调用 函数的递归调用函数的递归调用 基本内容:基本内容:C C语言允许函数的嵌套调用,即程序在调用语言允许函数的嵌套调用,即程序在调用一个函数的过程中,该函数又可以调用其它一个函数的过程中,该函数又可以调用其它函数。函数。main()main()主函数主函数 a a函数函数 b b函数函数 调用调用a a函数函数 调用调用b b函数函数 结束结束 结束结束 结束结束 例:用弦截法求方程例:用弦截法求方程 x x3 3-2x-2x2
42、2+8x-16=0 +8x-16=0 的近似根。的近似根。程序如下:程序如下:弦截法的算法思想如下:弦截法的算法思想如下:(1)(1)先取两个不同的点先取两个不同的点x1x1和和x2x2,需使,需使f(x1)f(x1)、f(x2)f(x2)的符号相反,否的符号相反,否 则,重新取则,重新取x1x1、x2x2。但。但x1x1与与x2x2相差不宜太大,以免在相差不宜太大,以免在(x1,x2)(x1,x2)区区 间出现多根。间出现多根。(2)(2)连接连接f(x1)f(x1)与与f(x2)f(x2)得一弦线交得一弦线交x x轴于轴于x x,可求得,可求得x x点的坐标为:点的坐标为:x=x1x=x1
43、*(f(x2)-x2(f(x2)-x2*f(x1)/(f(x2)-f(x1)f(x1)/(f(x2)-f(x1)将将x x代入方程,可求出代入方程,可求出f(x)f(x)。(3)(3)判别判别f(x)f(x)与与f(x1)f(x1),若符号相同,则根在,若符号相同,则根在(x,x2)(x,x2)区间内,可将区间内,可将x x 作为新的作为新的x1x1;若符号相异,则根在;若符号相异,则根在(x1(x1,x)x)区间内,可将区间内,可将x x作为作为 新的新的x2x2。(4)(4)重复上述重复上述(2)(2)、(3)(3)步骤,直到步骤,直到|f(x)|f(x)|math.hfloat f(fl
44、oat x)float f(float x)float y;float y;y=(x-2.0)y=(x-2.0)*x+8.0)x+8.0)*x-16.0;x-16.0;return(y);return(y);float xpoint(float x1,float x2)float xpoint(float x1,float x2)float y;float y;y=x1 y=x1*(f(x2)-x2(f(x2)-x2*f(x1)/(f(x2)-f(x1);f(x1)/(f(x2)-f(x1);return(y);return(y);float root(float x1,x2)float ro
45、ot(float x1,x2)float x,y,y1;float x,y,y1;y1=f(x1);y1=f(x1);do x=xpoint(x1,float x2);do x=xpoint(x1,float x2);y=f(x);y=f(x);if(y if(y*y10)y1=y;x1=x;y10)y1=y;x1=x;else elsex2=x;x2=x;while(fabs(y)0.000001);while(fabs(y)0.000001);return(x);return(x);void main()void main()float x1,x2,f1,f2,x;float x1,x2,
46、f1,f2,x;do do printf(“Input x1,x2:n”);printf(“Input x1,x2:n”);scanf(“%f,%f”,&x1,&x2);scanf(“%f,%f”,&x1,&x2);f1=f(x1);f2=f(x2);f1=f(x1);f2=f(x2);while(f1 while(f1*f2=0);f2=0);x=root(x1,x2);x=root(x1,x2);printf(“The root of equation printf(“The root of equation is:%8.4f is:%8.4fn”,x);n”,x);运行结果:运行结果:I
47、nput x1,x2:Input x1,x2:-1,3-1,3The root of equation is:2.0000The root of equation is:2.0000递归调用:在调用一个函数过程中间又出现直接或间接地调用递归调用:在调用一个函数过程中间又出现直接或间接地调用 该函数本身。该函数本身。在在C C程序中,函数调用它本身称为递归调用。函数程序中,函数调用它本身称为递归调用。函数a a直接调用直接调用a a本身称为直接递归,函数本身称为直接递归,函数a a调用函数调用函数b b,b b为调用为调用a,a,称为间接递称为间接递归。归。例如间接递归例如间接递归:int a(
48、x)int b(t)int a(x)int b(t)int x;int t;int x;int t;int y;int p;int y;int p;y=b(x);p=a(t);y=b(x);p=a(t);return(y);return(2 return(y);return(2*p);p);例:求例:求m m与与n n的最大公约数的最大公约数gcdgcd。分析分析:求求m m与与n n的最大公约数等价于求的最大公约数等价于求n n与与(m mod n)(m mod n)的的 最大公约数。若将最大公约数。若将“求求m m与与n n的最大公约数的最大公约数”记为记为 gcd(m,n)gcd(m,n
49、),则有下式成立:,则有下式成立:gcd(m,n)gdc(n,(m mod n)gcd(m,n)gdc(n,(m mod n)对于等价式的右边,问题又变成了求新的对于等价式的右边,问题又变成了求新的m m与与n n新新的的n n的最大公约数,即将的最大公约数,即将n n项当作新的项当作新的m m,而,而(m mod n)(m mod n)项作为新的项作为新的n n。如此这样继续下去,直到新的。如此这样继续下去,直到新的n=0n=0时,时,其最大公约数就是新的其最大公约数就是新的m m。例:求例:求2424与与1616的最大公约数,等价于求的最大公约数,等价于求1616与与(24 mod(24
50、mod 16)16)的最大公约数,即:的最大公约数,即:gcd(24,16)gdc(16,(24 mod 16)gcd(24,16)gdc(16,(24 mod 16)。由于由于(24 mod 16)=8,(24 mod 16)=8,又有等价式:又有等价式:gcd(16,8)gdc(8,(16 mod 8)gcd(16,8)gdc(8,(16 mod 8),因因(16 mod 8)=0(16 mod 8)=0,又有等价式:,又有等价式:gcd(8gcd(8,0)gcd(0,(8 mod 0)0)gcd(0,(8 mod 0)。因因(8 mod 0)=8,(8 mod 0)=8,故故gcd(0,