C语言学习笔记之(函数)序
C语言中函数的定义是相互平行的,在定义函数时,一个函数不能包含另一个函数,但是,一个函数在被调用的过程中可以调用其他函数,这就是函数的嵌套调用。
一、函数的嵌套调用
例子:计算1!+2!+3!+…+10!的值并输出,使用函数的嵌套调用实现。
#include <stdio.h>
#define N 10 /*宏定义*/
int main()
{
float sum(int n); /*对sum函数进行声明*/
printf("1!+2!+3!…10!=%-12.5le\n",sum(N)); /*调用sum函数*/
return 0;
}
float sum(int n) /*定义sum函数,求累加*/
{
float fac(int k); /*对fac函数进行声明*/
int i;
float s=0;
for(i=1;i<=n;++i)
s+=fac(i); /*调用fac函数*/
return s;
}
float fac(int k) /*定义fac函数,计算阶乘*/
{
int i;
float t=1;
for(i=2;i<=k;++i)
t*=i;
return t;
}
二、函数的递归调用
C语言支持函数的递归调用,所谓递归就是函数直接或间接地调用其本身。直接递归调用如左图所示,在调用f函数的过程中,又调用f函数。间接递归调用如右图所示,在调用f函数的过程中要调用f1函数,而在调用f1函数的过程中又要调用f函数。
例子:用递归函数实现例6-11中提出的求Fibonacci数列的前20项。
#include <stdio.h>
int f(int n) /*定义函数f用于计算数列的每一项*/
{
if(n==1||n==2) /*当n==1或者n==2时,返回1*/
return 1;
else
return (f(n-2)+f(n-1)); /*递归调用*/
}
int main()
{
int num=20;
int i;
for(i=1;i<=num;i++) /*循环20次*/
{
printf("%-6d",f(i)); /*调用f函数*/
if(i%4==0) /*每输出4个数后输出一个回车符*/
printf("\n");
}
return 0;
}
三、数组作为函数的参数
数组元素可以作为函数的实参,其用法与普通变量相同,是单向传递,即“值传递”方式;但数组元素不能作为函数的形参使用。
例子1:有下列代码,试分析输出结果。
#include<stdio.h>
void swap(int i,int j)
{
int t;
t=i;
i=j;
j=t;
printf("In function i=%d,j=%d\n",i,j);
}
int main()
{
int a[2]={4,9};
printf("Before function a[0]=%d,a[1]=%d\n",a[0],a[1]);
swap(a[0],a[1]);
printf("After function a[0]=%d,a[1]=%d\n",a[0],a[1]);
return 0;
}
主函数中定义了一个只有两个数据元素的数组a,并赋初值a[0]等于4,a[1]等于9。毫无疑问,主函数中的第一次输出a[0]=4,a[1]=9。
然后调用swap函数,将a[0]和a[1]作为实参传递给swap函数中的形参i和j,这里定义的swap函数实现交换两数的功能,因此,在swap函数中输出结果为:i=9,j=4。
由于数组元素作为函数的实参时其用法与普通变量相同,是单向传递的,也就是说,只能从实参传递给形参,因此,在调用完swap函数后,主函数中的a[0]和a[1]的值没有发生改变,故主函数中第二次输出结果还是a[0]=4,a[1]=9。
例子2:修改例8-10程序,交换a[0]和a[1]的值。
除了可以用数组元素作为函数参数外,还可以用数组名作为函数参数。数组名既可以作为实参也可以作为形参。
#include<stdio.h>
void swap(int x[2]) /*定义函数实现交换x[0]和x[1]*/
{ int t;
t = x[0]; /*交换x[0]和x[1]*/
x[0] = x[1];
x[1] = t;
printf("In function x[0]=%d,x[1]=%d\n",x[0],x[1]); /*输出x[0]和x[1]*/
}
int main()
{ int a[2]={4,9}; /*定义数组a并初始化*/
printf("Before function a[0]=%d,a[1]=%d\n",a[0],a[1]); /*输出a[0]和a[1]*/
swap(a); /*调用函数,数组名作为函数实参*/
printf("After function a[0]=%d,a[1]=%d\n",a[0],a[1]); /*输出a[0]和a[1]*/
return 0;
}
-
用数组名作函数参数,应该在主调函数和被调用函数中分别定义数组,本例中x是形参数组名,a是实参数组名,分别在其所在函数中定义,不能只在一方定义。
-
实参数组与形参数组数据类型应一致(这都为整型),如不一致,结果将出错。
-
数组名作函数参数时,是把实参数组的起始地址传递给形参数组,这样两个数组将共占同一段内存单元,从而达到“地址传递”的效果。假如数组a的起始地址为2000,则x数组的起始地址也是2000,显然,数组a和x将共占同一段内存单元,a[0]和x[0]共占同一个单元。由此可见,形参数组中各元素的值如发生变化,将会使实参数组元素的值同时发生变化。因此,调用swap函数可实现a[0]和a[1]的交换。
-
在定义swap函数时,声明形参数组x的大小为2,但实际上,指定其大小是不起作用的,因为C编译系统并不检查形参数组的大小,只是将实参数组的首地址传给形参数组。因此,形参数组可不指定大小,在定义数组时在数组名后跟一个空的方括号即可。例如,上述的函数头可写成:
void swap(int x[]) 定义swap函数,形参数组不指定大小
例子3:编写函数,统计某一维数组中非0元素的个数。
#include <stdio.h> #define N 5 count(int a[],int n) /*定义函数,形参为数组名和数组长度*/ { int num=0,i; for(i=0;i<n;i++) /*计算非0个数*/ if(a[i]!=0) num++; return num; /*返回num的值*/ } int main() { int b[N],i,sum; printf("enter N integer numbers:"); for(i=0;i<N;i++) scanf("%d",&b[i]); /*输入数组元素*/ sum=count(b,N); /*函数调用,实参为数组名和数组长度*/ printf("The number is %d\n",sum); /*输出结果*/ return 0; }
C语言学习笔记之(函数)序
https://www.wsjj.top/archives/c12
评论