第 8章 函数主要内容:
1、函数的定义
2、函数的调用(包括嵌套调用和递归调用)
4、局部变量和全局变量
5、变量的存储类别重点,
1)如何定义函数(即如何编写函数)
2)如何调用函数(包括库函数和自定义函数)
函数的引入
函数:函数是完成某些特定功能的代码块。
使用函数的优点:
1)实现模块化设计:将一个大任务分解成一个个的小任务,然后每个任务分别用函数实现。
2)实现“编写一次,多次调用”,避免在不同的程序中重复编写相同的函数。
3)便于程序调试和维护,因为每个函数之间是相互独立的。
函数的分类:库函数和用户自定义函数
8.1 函数的定义例 8,1编写函数 max:求两个整数 x和 y中的较大数 。
int max (int x,int y) /*函数头 */
{ int z=x; /*函数体 {…… }*/
if (x<y) z=y;
return z;
}
main()
{ int a,b,d;
printf("input a and b:");
scanf{"%d %d",&a,&b};
d=max(a,b); /*函数调用 */
printf("max is,%d",d);
}
例 8.2:设某程序中需多次用到打印表头(如下所示)
的功能,该功能用函数实现:
void line( )
{ printf("\n ********************");
printf("\n* score list *");
printf("\n ********************");
}
本例中,函数的类型,void,函数名为 line,函数 无参数 。
该函数无返回值,所以函数类型为 void型。
函数定义的一般形式如下,
函数类型 函数名 (类型名 形式参数 1,类型名 形式参数 2,… )
{ 说明部分语句部分
}
1.函数名,是该函数的唯一标识符,一般函数的命名最好做到“见名知义”。
2.函数类型,函数的返回值的类型。
当函数无返回值时,规定其 类型 为,void。
当函数返回值为 int 时,函数类型可以省略。
3,形式参数,形参是函数被调用时用于接收实参值的变量。
根据实际需要可有可无。没有形参时,圆括号也不可省;多个参数之间应用逗号分隔。参数包括参数名和参数类型。
形参的类型说明可有如下两种格式:
int max(int a,int b) /*形参的类型在形参表中直接说明 */
{ return (a>b?a:b);}

int max(a,b)
int a,b; /*形参的类型在函数体前、函数名后说明 */
{ return(a>b?a:b); }
前者为标准格式,后者为传统格式,通常用前者。
4.函数体,即 函数功能的具体实现。
它包括两部分,说明部分和执行部分,其中说明部分包括函数中所用的局部变量等的说明、函数中要调用的函数的说明。
注意:
函数不能嵌套定义,即函数内不能再定义函数,这样可以保证函数间是相互独立的,以实现模块化程序设计。
5.空函数:
函数类型 函数名 ( )
{ }
调用此函数时,什么也不做。只是表明这里要 调用一个函数,而现在这个函数的功能还没实现。
空函数在程 序设计中常常用到的:
1)预留函数,便于以后扩充程序功能。
2)便于程序的模块化设计和调试:程序设计中往往根据需要确定若干模块,分别由一些函数来实现。一个大系统,需要编写很多用户函数,而这些函数不可能 也没有必要同步完成,通常足从一些基本模块开始,编写一个调试一个,对于没有编写 的函数就需要用空函数代替。从而也有利于集体创作。
空函数举例
例 8.3 编写小学生算术练习系统的主程序,显示主菜单,用户选择,根据选择执行加、减、
乘、除、退出 5项功能之一。
重复上述步骤,直至选择退出。
其中主程序调用的函数有:显示主菜单函数
list_menu(),加、减、乘、除、退出函数分别是
add(),sub(),mul(),divide(),end(),以上函数除
list_menu()外此时均为空函数。
程序,l8_1_4.c
#include "stdio.h" /*l8_1_4.c*/
main()
{ void add(),sub(),mul(),divide(),end(),list_menu(); int n;
do{ list_menu();
scanf("%d",&n); getchar();
switch(n)
{case 1,add(); break;
case 2,sub(); break;
case 3,mul(); break;
case 4,divide(); break;
case 5:end(); break;
default:printf("\n enter error,please again.");
}
}while(n!=5);
}
void list_menu()
{printf("\n **the exercise system for primitive
students***");
printf("\n ** 1,add **");
printf("\n ** 2,sub **");
printf("\n ** 3,mul **");
printf("\n ** 4,divide*");
printf("\n ** 5,end **\n");
}
void add() { }
void sub(){ }
void mul(){ }
void divide() { }
void end() { }
问题,如何定义一个函数
第一步,分析函数需要的参数,包括参数的个数以及每个参数的类型,
第二步,分析函数返回值的类型,若无返回值,
则为 void。
函数的返回值可看作是函数执行完后需输出的 一个数据。
第三步,编写函数体说明:
参数和返回值是函数之间的接口,即函数之间通过参数和返回值进行通信。参数包括执行该函数时需要的数据信息,以及返回数据的有关信息。
例如:
1) 求 n!,要处理的数据是 n,因此必须有一个参数 n,类型为
int。返回值为 long 型。即
long fact( int n) { }
2) 打印表头,不需输入任何数据即可执行该函数,因此无参数。执行该函数无返回值,因此函数类型为 void。即 void
line( ) { }
3)求两个整数 m和 n的最小公倍数,执行该功能时必须有两个整型参数,返回值为整型。程序,l8_1_5.c
int min_multiple(int m,int n) { } (见下页)
4)求一批整型数据( n个)中的最大值。实现该功能的函数的参数有两个:该批数据的首地址及数据的个数。返回值为一个整型数。
int max( int data[ ],int n) { }
/*例 3,计算两个整数的最小公倍数 l8_1_5.c*/
main()
{int m,n,min; int min_multiple( int,int ); /*函数声明 */
printf("\n input m,n:");
scanf("%d%d",&m,&n);
min=min_multiple(m,n); /*函数调用 */
printf("\n bei shu:%d",min);
}
int min_multiple(int x,int y) /*函数定义 */
{ int i;
i=1;
while(x*i%y!=0) i++;
return(x*i);
}
8.2 函数的调用
重点,
1、对被调函数的声明
2、如何调用一个函数
3、主调函数和被调函数之间如何进行数据传递例 8.5 调用函数 fact( )求 n!(n由用户输入)。
分三种情况:
(1)函数 fact()与主函数在同一文件中,且 main( )在 fact()前面。
(2)函数 fact()与主函数在同一文件中,且 main在 fact之后。
(3)函数 fact与 main不再同一程序文件中 。
main() /*(1) main( )在 fact()前面 */
{int n; long p;
long fact(int); /*函数声明 */
scanf("%d",&n);
p=fact(n); /*函数调用 */
printf("\n %ld",p);
}
long fact( int m) /*函数定义 */
{ int i; long s=1;
for(i=1;i<=m;i++)
s*=i;
return(s); /*函数返回 */
} 结论,被调函数在后,需在主调函数中先声明后调用。
/* (2)主调函数在被调函数之后 */
long fact( int m) /* 函数定义 */
{ int i; long s=1;
for(i=1;i<=m;i++)
s*=i;
return(s);
}
main()
{int n; long p; /*不需函数声明 */
scanf("%d",&n);
p=fact(n); /*函数调用 */
printf("\n %ld",p);
}
结论,被调函数先于主调函数被编译,因此在编译主调函数时已知被调函数的类型等信息。故不需函数声明 。
/*(3)设 fact()函数存放在文件 f1.c中,则编写主调函数时需用
include 命令对被调函数声明 */
#include <f1.c>
main()
{int n; long p;
scanf("%d",&n);
p=fact(n);
printf("\n %ld",p);
}
结论:该程序的效果与( 2)相同,由此可 实现将多个文件连接成一个程序。
同理,对库函数的调用都要在 main函数前用 include命令将函数所在的头文件包含进来。
函数声明小结:
被调函数必须是已存在的函数,通过“函数声明”告知编译系统关于被调函数的有关信息。
函数声明的形式,函数类型 函数名(参数表);
(注意与函数定义的区别)
1、若被调函数是库函数或用户已编写的函数(与主调函数不在同一文件中),则使用前需在程序的开头用 include命令将被调函数的信息包含进来。
2、若主调函数与被调函数在同一文件内,且主调函数在前,
则必须在主调函数的说明部分或主调函数的前面对被调函数进行说明。
3、以下情况下可以省略对被调函数的说明。
a)函数类型为整型 b)被调函数在主调函数之前定义通常,将所有函数的说明集中在程序开头;或将所有函数的信息写入一个文件,编程时用 include 命令将其包含进来即可。
函数的调用与返回过程小结
1、函数调用的一般形式:
函数名 (实参表 )
如 p=fact(n);
printf(“%d”,power(2,n));等注意,实参与形参的类型、个数、顺序必须一致 。
2,调用过程:
1) 在调用函数时,首先将实参的值赋给形参;再将控制流程转到被调函数;
2)然后执行被调函数。
3)当被调函数执 行到 return语句,或执行到被调函数函数体最后的一个大花括号时,控制流程返回到 主调函数的断点处继续执行主调函数。如果被调函数有返回值,则控制流程返回的同时将该返回值带回主调函数。
3、函数的返回
函数返回的实现,
1)函数体中通过执行 return语句返回,其格式有 3种:
return( expression) ; 或 return expression ; 或
return;
2)若函数体中无 return语句,当执行到函数末尾时自动返回到调用函数。
注意:
1)函数的返回值最多只有一个,可通过 return 语句返回主调函数。
2)当有 多个值 需要返回主调函数时,用 return语句无法实现,只能通过 传地址 调用实现。如对数组元素排序等。
4,参数传递:实参与形参的结合
形参,定义函数时的参数为形参,此时的参数无具体的值,仅仅表示参数的类型、个数、以及在函数体内对其如何处理 。
其作用是:该函数被调用时用来接收实参的值,
实参 ; 调用函数时的参数为实参,它表示该函数要处理的数据的信息,因此实参必须有确定的值。调用时,将实参的值传给形参 。
要求,调用函数时,实参与形参的类型、个数必须完全一致。
分析例 8.4程序的调用过程:明确实参与形参的作用。
(传值调用:单向传递)
例 8,4以下程序企图通过调用 swap函数,交换主函数中变量 x
和 y中的数据。请观察程序的输出结果。
void swap(int a,int b)
{ int t;
printf("(2)a=%d b=%d\n",a,b);
t=a;a=b;b=t;
printf("(3)a=%d b=%d\n",a,b);
}
main()
{ int x=10,y=20;
printf("(1)x=%d y=%d\n",x,y);
swap(x,y);
printf("(4)x=%d y=%d\n",x,y);
}
程序运行结果如下:
(1)x=10 y=20
(2)a=10 b=20
(3)a=20 b=10
(4)x=10 y=20
结论,参数的传递是单向的,即只能由实参传给形参,在被调函数中对形参的改变的不影响实参的值。
例 8.12 编写函数实现:用选择法对 n个整数排序。编写主函数实现数据的输入输出 。
分析:
主程序的算法,
S1:输入一批数据 (个数为 N),存入一维数组 aa。
S2:调用函数 sort(),对一维数组中的数据按从小到大的顺序排序。 S3:输出数组 aa中的各元素。
函数 sort()的编写,
首先,确定函数的类型,void;
参数:一维数组的首地址,数据的个数,共 2个;
然后编写函数体,实现排序。
重点:分析参数的传递,比较传值与传地址的区别,各有何用处?
(图示,形参数组与实参数组的结合方式)
/*主函数 */
#define N 10
main()
{ int aa[N],i;
void sort(int b[ ],int n);
printf("\n enter integers
for sort;");
for(i=0;i<N;i++)
scanf("%d",&aa[i]);
sort(aa,N); /*函数调用 */
printf("\n after sort:\n");
for(i=0;i<N;i++)
printf("%6d",aa[i]);
}
/*函数 sort()*/
void sort(int b[ ],int n)
{ int i,j,t,k;
for(i=1;i<=n-1;i++)
{k=0;
for(j=1;j<=n-i;j++)
if(b[k]<b[j]) k=j;
t=b[k];b[k]=b[n-i];
b[n-i]=t;
} /*循环体:排一遍 */
}
数组 aa与数组 b实际上是一个数组。 b[ ]的长度无意义,
因此可以不说明。
例 8.12 运行结果与图示:
enter 5 integers:1 2 5 7 3↙
after sort,7 5 3 2 1
比较两种参数传递方式
传值调用,单向数据传递,对形参的改变不影响实参的值,且只能通过 return语句返回最多一个值 例 8.4
传地址调用,实参传给形参的是数据的地址,所达到的目的是,形参与实参共用同一片存储单元,对形参的改变实际上是对实参的改变,从而实现主、被调函数之间的多个数据传递。例
8.12
5,函数的嵌套调用例 8,6 嵌套调用实例,
f(int x)
{ int t;
t=x+x;
return(t);
}
g( int a,int b)
{ int z;
z=f(a*b);
return(z);
}
函数类型省略,默认为整型。
main()
{ int x1=2,x2=5,y;
y=g(x1,x2);
printf("%d",y);
} 被调函数在前,不需函数声明。
调用过程:
在 main函数中调用 g(),执行 g函数的的过程中调用 f();执行完 f()函数后返回到 g()接着执行,
执行完 g()后返回到
main().(图示)
例 8,7 编写函数,验证陈景润研究的哥德巴赫猜想:任意大偶数为两个素数之和并输出这两个素数 ( 所谓大偶数是指 6开始的偶数 ) 。
分析,isprime(int a)实现判断一个数 a是否为素数; even(int x)
实现找到并输出两个素数 ( 其和等于 x) ; main()实现输入一个大偶数,并调用 even()输出该大偶数对应的两个素数 。
设变量 x为任意大偶数,可从 x中依次减去 i,i从 2变化到 x/2;
依次判断 i,x-I是否为素数 。 步骤如下:
① i初值为 2。
② 判断 i是否是素数 。 若是,执行步骤 ③ ;若不是,执行步骤
⑤ 。
③ 判断 x-i是否是素数 。 若是,执行步骤 ④ ;若不是,执行步骤 ⑤ 。
④ 输出结果,返回调用函数 。
⑤ 使 i增 1。
⑥ 重复执行步骤 ② 。
/*例 8.7程序 */
#include "math.h"
int isprime (int); /*函数声明 */
void even(int);
main()
{ int a;
printf("Enter a even number(≥6):");
scanf("%d",&a);
if(a%2==0&&a>=6)
even(a); /*函数调用语句 */
else
printf("The %d isn't even number\n",a);
}
void even(int x) /*函数定义 */
{ int i;
for(i=2;i<=x/2;i++)
if(isprime(i))
if(isprime(x-i))
{printf("%d=%d+%d\n",x,i,x-i); return ;
}
}
int isprime(int a) /*函数定义 */
{ int i,k= sqrt(a);
for(i=2; i<=k; i++)
if (a%i==0) return 0;
return 1;
}
8.4递归调用
递归:一个函数直接或间接的调用自己。
分析递归问题的关键,
1)每次调用自己时参数的变化规律。
2)递归结束的条件。
例 8.8 求 n!.
分析,f(n)=f(n-1)*n (n>1)------规律
f(1)=1 (n=1)-------递归结束条件程序,l8_4_1.c
分析程序的执行过程,理解递归中的“递进”与“回推”。
main() /*程序,L8_4_1.c*/
{ int n; long p;
long f(int); /*对被调函数的声明 */
printf("\n input n:");
scanf("%d",&n);
p=f(n); /*函数调用 */
printf("\n n!=%ld",p);
}
long f(int m) / *函数定义 */
{ long t;
if(m==1) t=1;
else t=m*f(m-1); /*函数递归调用 */
return(t); /*函数的返回 */
}
类似的递归问题:
1。猴子吃桃:
int peach( int day)
{ int n;
if(d==10) n=1;
else n=2*(peach(day+1)+1);
return n;
}
2。猜年龄:第一个人说它比第二个人大 4岁,第二个人说它比第三个人大 4岁,第三个人说它比第四个人大四岁,第四个人 10岁,问:第一个人多大?
8.5 局部变量和全局变量
指变量的作用范围不同。
局部变量,在函数体内定义的变量。
作用范围:只在本函数内有效如前面例题中的变量、数组等。
全局变量,在函数体外定义的变量作用范围:从定义该变量的位置开始,到本源程序文件结束。
程序:
/*全局变量 x,y*/
int x=100; float y=66.6;
f1()
{float y=0; /*局部变量 y*/
printf(“x=%d \t”,x);
printf(“y=%f \t”,y);
}
int z=1;
f2()
{int i; /*局部变量 i*/
for(i=1;i<5;i++) putchar('*');
printf("\n z=%d\t ",z);
} /*全局变量 z 从 定义起至程序末起作用 */
main()
{f1(); f2();
printf(“y=%f \n”,y);
/*输出全局变量 y*/
}
运行结果:
x=100 y=0.000000
****
z=1 y=66.600000
/*全局变量 x,y在本程序内起作用 */
/*局部变量 y的作用范围内,全局变量 y不作用 */
int d=1; /*全局变量 d*/
fun(int p)
{int d=5; /*局部变量 d*/
d+=p++; /*使用局部变量 d*/
printf("%d",d);
}
main()
{int a=3;
fun(a);
d+=a++; /*使用全局变量 d*/
printf("%d",d);
}
运行结果,84
结论:在同一源程序文件中,若外部变量与局部变量同名,则在局部变量的作用范围内,外部变量不起作用。
局部变量和全局变量小结
局部变量:保证了函数之间的独立性。(常用)
全局变量:增加了函数之间数据传递的通道,但降低了函数间的独立性,降低了程序的清晰性,
因此副作用太大。除非特别需要时,一般不用。
占用内存情况:
局部变量 仅当他所在的函数被调用时才存在,执行完该函数返回后,该变量不再存在全局变量 在程序的全部执行过程中一直存在,直至程序执行完,才释放它所占的内存空间
8.6 变量的存储类别
变量和函数均有两个属性:
数据类型和存储类别存储类别指数据在内存中的存储方式。根据变量的
“生存期”不同,变量的存储类别包含以下四种:
自动的,auto
静态的,static
寄存器的,register
外部的,extern
自动的( auto)变量
函数的形参和在函数中定义的变量(通常省略存储类别,)即隐含指定为自动变量。前面
1~7章中的变量均属自动变量。
自动变量在需要时系统给他门分配存储空间,
在函数调用结束时自动释放这些存储空间。
例 auto int a=2,b=3; 与 int a=2,b=3;等价。
静态的( static)
1、静态局部变量:
作用域为本函数内部存储类别为静态存储类,因此其生存期与该函数所在程序运行期间相同。即当函数调用结束时能保留原值,在下一次调用该函数时该变量的值是上一次函数调用结束时的值,直至程序运行结束。。
例 (next page)
func(int a,int b) /*例 8.6.1*/
{static int m=0,i=2;/*静态局部变量 m,I*/
i+=m+1;
m=i+a+b;
return(m);
}
main()
{int k=4,m=1,p; /*局部变量 k,m,p*/
p=func(k,m);
printf("%5d",p);
p=func(k,m);
printf("%5d\n",p);
} 运行结果,8 17
/*图示执行过程中变量的存储空间占用及值的变化情况 */
int d=1; /*全局变量 d*/ /*例 8.6.2*/
fun(int p)
{static int d=5; /*静态局部变量 d*/
d+=p;
printf("%5d",d);
return(d);
}
main()
{int a=3; /*自动变量 a*/
printf("%5d\n",fun(a+fun(d)));
}
运行结果,6 15 15
Register 变量
register int k;
则给变量 k分配的空间为某个寄存器。
优点:速度快。
只有局部变量和形参可以定义为 register变量。
因为机器的寄存器数量有限,因此该类型不常用。
外部的( extern)变量
用 extern声明外部变量,是为了扩展外部变量的作用域。
因外部变量不常用,因此 extern也很少使用。
必须使用外部变量时,一般建议使用静态全局变量。即在函数体外定义变量时存储类别为:
static
如 static int a=2;
f( ){ ……}
变量 a的作用范围仅限于本源程序文件内。其它程序中即使用 extern int a;声明也不能引用 a。
8.7内部函数与外部函数
外部函数:如不加特别说明,函数都是全局的,
即外部的,一个函数可以调用另一文件中的函数。
(项目文件的使用 )
内部函数:存储类别为 static,该函数仅限于本程序文件使用,其它程序不能 调用之。
综合题 1
编程实现小学生算术练习系统:主菜单包括 5项(加法、减法、乘法、除法、退出),前四项中每一项又包括子菜单(一级、二级、三级、返回 4项),其中一级实现 10以内的运算,二级实现 50以内的整数运算,三级实现 100以内的整数运算;进入某一级后,
反复练习(由机器产生两个随机数,用户输入运算结果,输出正确或错误)待结束时给出本级题目中计算正确的百分比。
要求每个功能分别用函数实现。程序,l8_t.c
综合题 2
自动阅卷程序,设单选题 20个( 2分 /题),多选题 20
个(每题 4个供选答案,3分 /题,且只要与答案不一致即错)。编写函数实现:阅单选题,阅多选题,
阅一个人的答题;编写主函数实现批阅 N个人的答题卡(正确答案在主程序中输入)。
分析:
Main(),1)输入正确答案,分别存入一维数组 dd,二维数组 ss; 2) 批阅 N个人的答题(用循环),将成绩存入数组 sc。 3)输出每个人的最后成绩。
Person(),函数类型为 int; 参数两个,dd,ss; 函数体,1)输入某人的答案,分别存入 dd1和 ss1,2)
分别调用函数 single()和 many()判别对错并计分,
返回总成绩。
Single():函数类型 int,参数 dd,dd1; 函数体:
统计数组 dd与 dd1中相同元素的个数,乘 2即得单选题的成绩,返回该成绩。
Many():函数类型 int,参数 ss,ss1; 函数体:
统计数组 ss与数组 ss1中对应行元素相同的行数,乘 3
即得多选题的成绩,并返回。
然后分析各函数的具体实现算法。
程序 1,l8_3_2.c
分析程序中的传地址调用,嵌套调用时程序的执行过程。
程序 2,l8_3_2_q.c 定义存放正确答案的数组为全局的,
则 dd,ss将不作为参数使用。(一般情况使用参数传递)
#include "stdio.h" /*程序 1*/
#define N 400 /*num of person*/
#define NUM 20 /*num of question*/
main()
{ char dd[NUM+1],ss[NUM+1][5];
int sc[N+1],i;
printf("\n enter right answer of single select:\n");
printf("\n(format:press enter after finished inputing all of
answers.\n");
for(i=1;i<=NUM;i++)
dd[i]=getchar();
getchar();
printf("\n enter answer of multi select:\n");
printf("\nformat:(press enter after inputing a
question)\n");
for(i=1;i<=NUM;i++)
gets(ss[i]);
for(i=1;i<=N;i++)
sc[i]=person(dd,ss);
printf("\n no,score,");
for(i=1;i<=N;i++)
printf("\n %-6d%-6d",i,sc[i]);
}
int person(char dd[],char ss[][5])
{ char dd1[21],ss1[31][5];
int s,i; int signle(),many();
printf("\n enter answer of single select:");
for(i=1;i<=NUM;i++)
dd1[i]=getchar();
getchar();
printf("\n enter answer of multi select:");
for(i=1;i<=NUM;i++)
gets(ss1[i]);
s=single(dd,dd1)+many(ss,ss1);
return(s);
}
int single(char dd[ ],char dd1[ ])
{ int n=0,i;
for(i=1;i<=NUM;i++)
if(dd[i]==dd1[i]) n++;
return(2*n);
}
int many(char ss[ ][5],char ss1[ ][5])
{ int n=0,i;
for(i=1;i<=NUM;i++)
if(!strcmp(ss[i],ss1[i])) n++;
return(n*3);
}
多个文件组成一个程序的方法:
1、使用 project生成项目文件见 ch16.8
2、使用 include 将所有的文件包含到一个文件中。
例 8.5 (3)
作业
8.1,8.2,8.3,8.4,8.10
练习
1、求一元二次方程的根,要求,a,b,c由主函数输入,用 3
个函数分别求 b2-4ac的值大于 0、等于 0、小于 0时方程的根并输出。
分析:
主函数,(1)输入 a,b,c (2)计算 d= b2 - 4ac,然后根据 d
的值大于 0、等于 0、小于 0分别调用三个函数,f1()
f2() f3()
分析各个函数的实现:
函数类型 函数名(形参及类型)
程序,x8_1.c (常见错误)
练习例 8.2(程序 x8_2.c)
main()
{void add(float,float );
float a,b;
scanf("%f%f",&a,&b);
add(a,b);
}
void add(float x,float y)
{float s;
s=x+y ;
printf("\n %f",s);
}
问题:
若将函数 add()的类型改为
float,则运行时出错,
4 6CR
10.000000float point
error:domain
若改为 float后在 add函数体末加 return(s); 则结果正确。
若将 add声明中的参数去掉,则实参并未传给形参。
若参数为整型,则函数声明时参数类型可可省略。
递归调用练习
x8.9:
分析:
函数类型,float 函数名,pp
参数,2个 n(整型 ),x(实型 )
函数体:根据 n的值决定采用 3个公式中的一个计算函数值。 (用选择结构)
当 n>1时,计算函数值的过程中又调用函数 pp,即递归调用。参数的变化规律为,n-1,n-2 。即 if(n>1)
h=2*x*pp(n-1,x)-2*(n-1)*pp(n-2,x)
递归结束的条件为,n等于 0或 n等于 1
程序,x8_13.c
通过参数在函数间传递数据
X8.14 分析:
主函数调用 4个函数,设函数名分别为 average1,
average2,max_sc,jun,参数分别为:
void average1(float s[][5],float a[])
void average(float s[][5] )
void max_sc(float s[][5])
void jun(float a[])
分别实现的功能为: