第八章 函数第一节 函数的定义方法
1.函数的概念函数从本质上来说就是能完成一定功能的程序段,
其标识叫函数名。
若有其他程序要完成该函数的功能,可以通过调用。
函数可以反复多次调用。
2.引入函数解决的问题
1)解决代码的重复
2)结构化、模块化编程的需要
main()
h()
b() c()a()
e() f()d() g()
main( )
{
printstar( );
print_message( );
printstar( );
}
printstar( )
{ printf(“\t\t*****\n”); }
print_message( )
{ printf(“\t\t \n”); }
例,一个简单的函数调用
star(
star(
tstar(
t_m
/*调用 printstar( ) 函数 */
/*调用 printstar( ) 函数 */
/*调用 print_message( )函数 */
/* printstar( ) 函数 */
/* print_message( )函数 */
( 1)一个文件由一个或多个函数组成,一个源文件是一个编译单位
( 2) 一个程序总是从 main()函数开始执行,调用其他函数后,流程回到 main()主函数结束。
main()主函数是系统定义的
( 3) 所有函数都是平行的,它们的定义都是相互独立的说明,
说明,
( 4)从用户的角度看,有两种函数:
( 5)从函数的形式看,函数分为,
标准函数(库函数)
用户自定义函数有参函数无参函数
( 1)无参函数的定义形式:
类型说明符 函数名( )
{
说明部分;
语句;
…
}
第二节 函数的定义方式
( 2)有参函数的定义形式:
类型说明符 函数名(形式参数列表)
{
说明部分;
语句;
…
}
例,一个简单的有参函数调用
max(int x,int y)
{
int z;
z=x>y?x:y;
return(z);
}
( 3)空函数的定义形式:
类型说明符 函数名(形式参数列表)
{
}
第三节 函数参数和函数的值
1.形式参数和实际参数形式参数:定义函数时,函数名后面括号中的变量名称为,形式参数,
实际参数:在调用函数时,函数名后面括号中的表达式称为,实际参数,
main()
{ int a,b,c;
scanf(“%d,%d”,&a,&b);
c=max(a,b);
printf(“max=%d”,c);
}
int max(int x,int y)
{ int z;
if(x>y) z=x;
else z=y;
reutrn(z);
}
例,形参和实参
/*调用 max函数,将得到的值赋给 c*/
/*定义 max函数,x,y为形式参数 */
/*将 z的值返回,通过 max函数带回调用值 */
( 1)在未出现函数调用时,形式参数不占内存单元,只有在发生函数调用时函数 max( )中的形式参数才被分配内存单元,且在调用结束后,
形式参数占用的内存将被释放关于形式参数和实际参数的说明,
( 2)实际参数可以是常量、变量、表达式如,max(3,a+b);
但要求有确切的值,在调用时,把实际参数的值传给形式参数关于形式参数和实际参数的说明,
( 3)在定义函数时,必须指定形式参数的类型如,int max(int x,int y)
( 4)实际参数和形式参数的类型要求一致
( 5)实际参数对形式参数的数值传递是:
单向值传递如,a b2 3
x y2 3
main()
{ int a,b,c;
scanf(%d,%d”,&a,&b);
c=max(a,b);
printf(“max=%d”,c);
}
int max(int x,int y)
{ int z;
if(x>y) z=x;
else z=y;
reutrn(z);
}
例,形参和实参运行时输入,4,6
2.函数的返回值通过函数调用,使得主函数得到一个确定的值如,main()
{ …
c=max(a,b);
…
}
int max(int x,int y)
{ int z;
if(x>y) z=x;
else z=y;
reutrn(z);
}
运行时输入,4,6
关于函数返回值的说明,
( 1)函数的返回值总是通过函数中 return语句获得的,一个函数可以有一个以上的 return语句如,int max(int x,int y)
{ if(x>y)
return(x);
else
reutrn(y);
}
关于函数返回值的说明,
( 2) return后面的( )可以省略如,return z;
return后面也可以是一个表达式如,return x+y;
( 3)函数的类型
C语言规定,凡不加类型说明的函数,
一律按整型处理,函数的类型一般应与 return后面的表达式类型一致关于函数返回值的说明,
( 4)若函数的值的类型与 return后面的表达式类型不一致,则以函数类型为准,函数值的类型决定返回值的类型如,
main()
{ float a,b,
int c;
scanf(“%f,%f”,&a,&b);
c=max(a,b);
printf(“max=%d”,c);
}
max(float x,float y)
{ float z;
z=x>y?x:y;
reutrn(z);
}
运行时输入,1.5,2.5
输出,2
int
第四节 函数的调用
1.函数调用一般形式
◆ 有返回值的函数调用形式:
函数名 (实际参数列表)
如,c=max(a,b);
max(a,b);
◆ 无返回值的函数调用形式:
函数名 ()
如,printstar( );
2.函数调用方法
( 1)函数语句:
( 2)函数表达式:
( 3)函数参数:
如,printstar( );
如,c=max(a,b);
如,m=max(a,max(b,c));
printf(“%d”,max(a,b));
对被调用函数的说明:
在一个函数中调用另一个函数,需要具备的条件:
1.首先被调用函数必须已经存在
2.如果使用库函数,还须用 #include命令将调用有关函数时,所需用到的信息包含到本文件中如,#include,math.h”
3.若用户自己定义一函数,且该函数与调用它的函数在同一个文件中,一般还应在主调函数中对被调用函数返值的类型作说明类型标识符 函数名 (实际参数列表)
对被调用函数的说明:
第五节 函数的嵌套调用
C语言不能嵌套定义函数,但可在嵌套调用一个函数时,又调用另一个函数函数都是相互独立的,互相平行的调用 a() 调用 b()
main() 函数 a() 函数 b() 函数结束第六节 函数的递归调用在调用一个函数的过程中,直接或间接地调用该函数本身 -----,递归调用,
f( )函数调用 f()
如果要求递归的过程不是无限制进行下去,
必须有一个结束递归的条件调用 f2()
f1( )函数 f2( )函数调用 f1()
第七节 数组作为函数参数
1.数组元素作为函数实际参数 ----单向值传递例,两个数组,各有 10个元素,将它们以一对应,
逐个相比,如果 a中元素大于 b中元素的数目大于 b中元素大于 a中元素的数目,则认为 a>b
试统计出两数组大于、等于、小于的数目
main()
初始化 a[10],b[10]
调用 large()
large() 函数
2.数组名作为函数实际参数,此时参数都应为数组名 -----传递的是数组的首地址例,有一维数组 score[10],用于放 10个学生的成绩,
求出该 10个学生的平均成绩,用 average( )函数
main()
初始化 score[10],aver
调用 average()
aver=average(score)
large() 函数数组作为函数参数说明:
1.用数组名作为参数,在主调函数和被调函数中应分别定义数组
2.实际参数和形式参数类型应一致
3.实际参数和形式参数大小可以不一致
4.强调:数组名作为参数时,不是值传递,而是数组的首地址,这样,两个数组共用一段内存空间第八节 局部变量和全局变量
1.局部变量:(离开函数,值将被释放)
如,float f1(int a)
{ int b,c;
… }
char f2(int x,int y)
{ int i,j;
… }
main( )
{ int a,x,y,i,j;
… }
如,main()
{ int a,b;
…
{ int c;
c=a+b;
}
…
}
a,b c
2.局部静态变量(离开函数,值仍然存在)
如,main( )
{ int i=0;
printf(“i=%d\n”,i);
abc( );
abc( );
abc( );
}
abc( )
{ int i=1;
static int k=1;
i=i+1;
k=k+1;
printf(“i=%d,k=%d\n”,i,k);
}
i=0
i=2,k=2
i=2,k=3
i=2,k=4
3.全局变量:在函数外定义的变量,在整个程序内都有意义如,int a=10;
main( )
{ int i;
extern int b;
for(i=1;i<=5;i++)
++a;
s( );
}
int b=10;
s( )
{ ++a;
printf(“%d”,a+b);
}
b
a
26
全局变量说明:
若在同一个源文件中,外部变量与局部变量同名,则在局部变量起作用的范围内外部变量不起作用如,extern int a;
main( )
{ int i;
for(i=1;i<=5;i++)
{ ++a; printf(“%d”,a); }
s( );
}
int a=10;
s( )
{ int a=100;
printf(“%d”,a);
}
/*外部变量说明 */
/*外部变量定义 */
/*a为局部变量 */
15
100
习题例 1,int a=0,b=0;
fun( )
{
int a=5;
printf(“%d,%d\n”,a,b);
}
main( )
{
b=5;
fun( );
printf(“%d,%d\n”,a,b);
}
5,5
0,5
习题例 2,int x,y;
one( )
{
int a=25,b=10,x,y;
x=a-b;y=a+b;
return;
}
main( )
{
int a=9,b=5;
x=a+b;y=a-b;
one( );
printf(“%d,%d\n”,x,y);
}
14,4
习题例 3,int x,y;写一个函数 digit(n,k),其功能是取出数 n从右边起的第 k位数字,如 digit(1234,3)=2,
digit(1234,6)=0
int digit(int n,int k )
{ int i;
n=abs(n);
for(i= ) n=n/10;
return( );
}
main( )
{ int x,l;
scanf(“%d,%d”,&x,&l);
printf(“digit=%d\n”,digit(x,l));
}
1;i<k;i++
n%10
习题例 4,编写一函数求任意一个整型数据各位数字之和。
在主函数中调用它求得从键盘输入的一个整数的各位数字之和
sum(int x)
{ int s=0;
while(x>0)
{
s=s+x%10;
x=x/10;
}
return s;
}
main()
{ int a,st;
scanf(“%d”,&a);
st=sum(a);
printf(“%d,st);
}
习题例 5,编写一函数求任意一个整型数据各位数字之和及各位数字的平方和。在主函数中调用它求得从键盘输入的一个整数的各位数字之和及各位数字的平方和
sum(int x)
{ int s=0,t;
while(x>0)
{ t=x%10;
s=s+t*t*t;
x=x/10;
}
return s;
}
main()
{ int a,st;
scanf(“%d”,&a);
st=sum(a);
printf(“%d,st);
}
习题例 6,编写一函数求某一维数组的平均值并返回,
并在主函数中调用进行验证
avg(int x[],int n)
{
int sum=0,i;
for(i=0;i<n;i++)
sum+=x[i];
return sum/10;
}
main()
{
int a[10],i,av;
for(i=0;i<10;i++)
scanf(“%d”,&a[i]);
av=avg(a,10);
printf(“%d,av);
}
例 7,编写一函数求某二维数组的最大值并返回,
并在主函数中调用进行验证习题
avg(int x[10][10])
{
int m,i,j;
m=x[0][0];
for(i=0;i<10;i++)
for(j=0;j<10,j++)
if(m<x[i][j])
m=x[i][j];
return m;
}
main()
{
int a[10][ 10],i,j,max;
...
max=avg(a);
printf(“%d,max);
}
1.函数的概念函数从本质上来说就是能完成一定功能的程序段,
其标识叫函数名。
若有其他程序要完成该函数的功能,可以通过调用。
函数可以反复多次调用。
2.引入函数解决的问题
1)解决代码的重复
2)结构化、模块化编程的需要
main()
h()
b() c()a()
e() f()d() g()
main( )
{
printstar( );
print_message( );
printstar( );
}
printstar( )
{ printf(“\t\t*****\n”); }
print_message( )
{ printf(“\t\t \n”); }
例,一个简单的函数调用
star(
star(
tstar(
t_m
/*调用 printstar( ) 函数 */
/*调用 printstar( ) 函数 */
/*调用 print_message( )函数 */
/* printstar( ) 函数 */
/* print_message( )函数 */
( 1)一个文件由一个或多个函数组成,一个源文件是一个编译单位
( 2) 一个程序总是从 main()函数开始执行,调用其他函数后,流程回到 main()主函数结束。
main()主函数是系统定义的
( 3) 所有函数都是平行的,它们的定义都是相互独立的说明,
说明,
( 4)从用户的角度看,有两种函数:
( 5)从函数的形式看,函数分为,
标准函数(库函数)
用户自定义函数有参函数无参函数
( 1)无参函数的定义形式:
类型说明符 函数名( )
{
说明部分;
语句;
…
}
第二节 函数的定义方式
( 2)有参函数的定义形式:
类型说明符 函数名(形式参数列表)
{
说明部分;
语句;
…
}
例,一个简单的有参函数调用
max(int x,int y)
{
int z;
z=x>y?x:y;
return(z);
}
( 3)空函数的定义形式:
类型说明符 函数名(形式参数列表)
{
}
第三节 函数参数和函数的值
1.形式参数和实际参数形式参数:定义函数时,函数名后面括号中的变量名称为,形式参数,
实际参数:在调用函数时,函数名后面括号中的表达式称为,实际参数,
main()
{ int a,b,c;
scanf(“%d,%d”,&a,&b);
c=max(a,b);
printf(“max=%d”,c);
}
int max(int x,int y)
{ int z;
if(x>y) z=x;
else z=y;
reutrn(z);
}
例,形参和实参
/*调用 max函数,将得到的值赋给 c*/
/*定义 max函数,x,y为形式参数 */
/*将 z的值返回,通过 max函数带回调用值 */
( 1)在未出现函数调用时,形式参数不占内存单元,只有在发生函数调用时函数 max( )中的形式参数才被分配内存单元,且在调用结束后,
形式参数占用的内存将被释放关于形式参数和实际参数的说明,
( 2)实际参数可以是常量、变量、表达式如,max(3,a+b);
但要求有确切的值,在调用时,把实际参数的值传给形式参数关于形式参数和实际参数的说明,
( 3)在定义函数时,必须指定形式参数的类型如,int max(int x,int y)
( 4)实际参数和形式参数的类型要求一致
( 5)实际参数对形式参数的数值传递是:
单向值传递如,a b2 3
x y2 3
main()
{ int a,b,c;
scanf(%d,%d”,&a,&b);
c=max(a,b);
printf(“max=%d”,c);
}
int max(int x,int y)
{ int z;
if(x>y) z=x;
else z=y;
reutrn(z);
}
例,形参和实参运行时输入,4,6
2.函数的返回值通过函数调用,使得主函数得到一个确定的值如,main()
{ …
c=max(a,b);
…
}
int max(int x,int y)
{ int z;
if(x>y) z=x;
else z=y;
reutrn(z);
}
运行时输入,4,6
关于函数返回值的说明,
( 1)函数的返回值总是通过函数中 return语句获得的,一个函数可以有一个以上的 return语句如,int max(int x,int y)
{ if(x>y)
return(x);
else
reutrn(y);
}
关于函数返回值的说明,
( 2) return后面的( )可以省略如,return z;
return后面也可以是一个表达式如,return x+y;
( 3)函数的类型
C语言规定,凡不加类型说明的函数,
一律按整型处理,函数的类型一般应与 return后面的表达式类型一致关于函数返回值的说明,
( 4)若函数的值的类型与 return后面的表达式类型不一致,则以函数类型为准,函数值的类型决定返回值的类型如,
main()
{ float a,b,
int c;
scanf(“%f,%f”,&a,&b);
c=max(a,b);
printf(“max=%d”,c);
}
max(float x,float y)
{ float z;
z=x>y?x:y;
reutrn(z);
}
运行时输入,1.5,2.5
输出,2
int
第四节 函数的调用
1.函数调用一般形式
◆ 有返回值的函数调用形式:
函数名 (实际参数列表)
如,c=max(a,b);
max(a,b);
◆ 无返回值的函数调用形式:
函数名 ()
如,printstar( );
2.函数调用方法
( 1)函数语句:
( 2)函数表达式:
( 3)函数参数:
如,printstar( );
如,c=max(a,b);
如,m=max(a,max(b,c));
printf(“%d”,max(a,b));
对被调用函数的说明:
在一个函数中调用另一个函数,需要具备的条件:
1.首先被调用函数必须已经存在
2.如果使用库函数,还须用 #include命令将调用有关函数时,所需用到的信息包含到本文件中如,#include,math.h”
3.若用户自己定义一函数,且该函数与调用它的函数在同一个文件中,一般还应在主调函数中对被调用函数返值的类型作说明类型标识符 函数名 (实际参数列表)
对被调用函数的说明:
第五节 函数的嵌套调用
C语言不能嵌套定义函数,但可在嵌套调用一个函数时,又调用另一个函数函数都是相互独立的,互相平行的调用 a() 调用 b()
main() 函数 a() 函数 b() 函数结束第六节 函数的递归调用在调用一个函数的过程中,直接或间接地调用该函数本身 -----,递归调用,
f( )函数调用 f()
如果要求递归的过程不是无限制进行下去,
必须有一个结束递归的条件调用 f2()
f1( )函数 f2( )函数调用 f1()
第七节 数组作为函数参数
1.数组元素作为函数实际参数 ----单向值传递例,两个数组,各有 10个元素,将它们以一对应,
逐个相比,如果 a中元素大于 b中元素的数目大于 b中元素大于 a中元素的数目,则认为 a>b
试统计出两数组大于、等于、小于的数目
main()
初始化 a[10],b[10]
调用 large()
large() 函数
2.数组名作为函数实际参数,此时参数都应为数组名 -----传递的是数组的首地址例,有一维数组 score[10],用于放 10个学生的成绩,
求出该 10个学生的平均成绩,用 average( )函数
main()
初始化 score[10],aver
调用 average()
aver=average(score)
large() 函数数组作为函数参数说明:
1.用数组名作为参数,在主调函数和被调函数中应分别定义数组
2.实际参数和形式参数类型应一致
3.实际参数和形式参数大小可以不一致
4.强调:数组名作为参数时,不是值传递,而是数组的首地址,这样,两个数组共用一段内存空间第八节 局部变量和全局变量
1.局部变量:(离开函数,值将被释放)
如,float f1(int a)
{ int b,c;
… }
char f2(int x,int y)
{ int i,j;
… }
main( )
{ int a,x,y,i,j;
… }
如,main()
{ int a,b;
…
{ int c;
c=a+b;
}
…
}
a,b c
2.局部静态变量(离开函数,值仍然存在)
如,main( )
{ int i=0;
printf(“i=%d\n”,i);
abc( );
abc( );
abc( );
}
abc( )
{ int i=1;
static int k=1;
i=i+1;
k=k+1;
printf(“i=%d,k=%d\n”,i,k);
}
i=0
i=2,k=2
i=2,k=3
i=2,k=4
3.全局变量:在函数外定义的变量,在整个程序内都有意义如,int a=10;
main( )
{ int i;
extern int b;
for(i=1;i<=5;i++)
++a;
s( );
}
int b=10;
s( )
{ ++a;
printf(“%d”,a+b);
}
b
a
26
全局变量说明:
若在同一个源文件中,外部变量与局部变量同名,则在局部变量起作用的范围内外部变量不起作用如,extern int a;
main( )
{ int i;
for(i=1;i<=5;i++)
{ ++a; printf(“%d”,a); }
s( );
}
int a=10;
s( )
{ int a=100;
printf(“%d”,a);
}
/*外部变量说明 */
/*外部变量定义 */
/*a为局部变量 */
15
100
习题例 1,int a=0,b=0;
fun( )
{
int a=5;
printf(“%d,%d\n”,a,b);
}
main( )
{
b=5;
fun( );
printf(“%d,%d\n”,a,b);
}
5,5
0,5
习题例 2,int x,y;
one( )
{
int a=25,b=10,x,y;
x=a-b;y=a+b;
return;
}
main( )
{
int a=9,b=5;
x=a+b;y=a-b;
one( );
printf(“%d,%d\n”,x,y);
}
14,4
习题例 3,int x,y;写一个函数 digit(n,k),其功能是取出数 n从右边起的第 k位数字,如 digit(1234,3)=2,
digit(1234,6)=0
int digit(int n,int k )
{ int i;
n=abs(n);
for(i= ) n=n/10;
return( );
}
main( )
{ int x,l;
scanf(“%d,%d”,&x,&l);
printf(“digit=%d\n”,digit(x,l));
}
1;i<k;i++
n%10
习题例 4,编写一函数求任意一个整型数据各位数字之和。
在主函数中调用它求得从键盘输入的一个整数的各位数字之和
sum(int x)
{ int s=0;
while(x>0)
{
s=s+x%10;
x=x/10;
}
return s;
}
main()
{ int a,st;
scanf(“%d”,&a);
st=sum(a);
printf(“%d,st);
}
习题例 5,编写一函数求任意一个整型数据各位数字之和及各位数字的平方和。在主函数中调用它求得从键盘输入的一个整数的各位数字之和及各位数字的平方和
sum(int x)
{ int s=0,t;
while(x>0)
{ t=x%10;
s=s+t*t*t;
x=x/10;
}
return s;
}
main()
{ int a,st;
scanf(“%d”,&a);
st=sum(a);
printf(“%d,st);
}
习题例 6,编写一函数求某一维数组的平均值并返回,
并在主函数中调用进行验证
avg(int x[],int n)
{
int sum=0,i;
for(i=0;i<n;i++)
sum+=x[i];
return sum/10;
}
main()
{
int a[10],i,av;
for(i=0;i<10;i++)
scanf(“%d”,&a[i]);
av=avg(a,10);
printf(“%d,av);
}
例 7,编写一函数求某二维数组的最大值并返回,
并在主函数中调用进行验证习题
avg(int x[10][10])
{
int m,i,j;
m=x[0][0];
for(i=0;i<10;i++)
for(j=0;j<10,j++)
if(m<x[i][j])
m=x[i][j];
return m;
}
main()
{
int a[10][ 10],i,j,max;
...
max=avg(a);
printf(“%d,max);
}