c笔记之函数.docx
- 文档编号:25710768
- 上传时间:2023-06-11
- 格式:DOCX
- 页数:33
- 大小:21.64KB
c笔记之函数.docx
《c笔记之函数.docx》由会员分享,可在线阅读,更多相关《c笔记之函数.docx(33页珍藏版)》请在冰豆网上搜索。
c笔记之函数
函数
一个C程序可由一个主函数和若干个子函数组成。
每个子函数完成一个特定的功能(功能相对独立的程序段)。
用户角度分类
标准函数,即库函数
自定义函数
函数形式分类
无参数函数
有参数函数
函数定义一般形式
类型说明函数名([形式参数说明])
{
函数体
}
形式参数说明
类型说明变量名[,类型说明变量名。
。
。
]
1.一个C程序可以分为若干个函数
2.每个程序有且只能有一个主函数(main),其他函数都是“子函数”
3.子函数可以相互调用,但主函数不能被调用
4.一个C源程序由一个或多个文件构成,一个源程序文件是一个编译单位
各函数间的信息的往来是由参数传递和返回语句实现的。
函数的参数:
调用时,实参值传给形参;
仅与位置有关,与名字无关;
注意二者的个数、类型。
形式参数和实际参数
1.定义参数时,必须说明形参的类型。
形参只能是变量或数组。
2.函被调用前,形参不占用内存;函数调用结束后,形参所占有的内存也将被回收。
3.实参可以是常量、变量或表达式。
4.实参与形参的类型必须一致。
字符型和整型可以互相匹配。
5.C语言中实参对形参的数据传递是“值传递”,即单向传递。
它仅由参数的对应位置确定,与名字无关。
实参形参传递方式
常量、变量、表达式、变量传递(单向)
数组元素
数组名数组传递组首地址(“双向”)--〉共享同一个存储空间
eg1:
#include
intsum(inta,intb)
{
a=a+b;
b=a+b;//无效语句
returna;
}
main()
{
inta=1,b=3,c;
c=sum(a,b);//a,b值不变
printf("Sumof%d,%dis%d\n",a,b,c);
}
eg2:
#include
intmax(intx,inty)
{
intz;
z=(x>y)?
x:
y;
returnz;
}
main()
{
inta,b,c;
scanf("%d%d",&a,&b);//输入:
空格或换行隔开
c=max(a,b);
printf("Maxis%d\n",c);
}
eg3:
函数返回值
#include
intmax(intx,inty)
{
//intz;
//z=(x>y)?
x:
y;
//returnz;
//if(x>y)
//returnx;
//else
//returny;
return(x>y)?
x:
y;
}
main()
{
inta,b,c;
scanf("%d%d",&a,&b);//输入:
空格或换行隔开
c=max(a,b);
printf("Maxis%d\n",c);
}
eg4:
按从右往左的顺序,计算实参各个表达式的值。
#include
intf(inta,intb)
{
intc;
printf("a=%d,c=%d\t",a,b);
if(a>b)c=1;
elseif(a==b)c=0;
elsec=-1;
returnc;
}
intmain()
{
inti=2,p;
p=f(i,i);//a=2,c=20
printf("%d\n",p);
i=2;
p=f(++i,i);//a=3,c=30
printf("%d\n",p);
i=2;
p=f(i++,i);//a=2,c=3-1
printf("%d\n",p);
i=2;
p=f(i,++i);//a=3,c=30
printf("%d\n",p);
i=2;
p=f(i,i++);//a=3,c=21
printf("%d\n",p);
}
函数的调用
1.先定义,再使用
#include
floatf(floatx)
{
return2*x*x+3*x+1;
}
main()
{
floatx;
scanf("%f",&x);
printf("y=%f\n",f(x));
}
2.如果被调函数的定义在主调函数之前,可以先给出原形说明。
原形说明
类型说明函数名(参数类型[变量名],
参数类型,...);变量名可写可不写
#include
floatf(float);//原形说明
main()
{
floatx;
scanf("%f",&x);
printf("y=%f\n",f(x));
}
floatf(floatx)
{
return2*x*x+3*x+1;
}
3.调用库函数
#include
#include
floatf(float);
main()
{
floatx,y;
scanf("%f",&x);
y=sin(x*3.1415926/180);
printf("sin(%f*3.1415926/180)=%f\n",x,y);
}
函数的嵌套调用
一个函数又调用另一个函数
注意点:
返回到主调函数的调用处
参数传递是单向的
eg:
#include
voidb(intx);
voida(intx)
{
x+=11;
b(x);
printf("a_sub:
%d\n",x);
}
voidb(intx)
{
x+=22;
printf("b_sub:
%d\n",x);
}
main()
{
intx=0;
a(x);
printf("main:
%d\n",x);
}
/*
b_sub:
33
a_sub:
11
main:
0
--------------------------------
*/
eg1:
用弦截法求方程的根。
x*x*x-5*x*x+16*x-80=0
#include
#include
floatf(floatx)
{
return((x-5)*x+16)*x-80;
}
floatxpoint(floatx1,floatx2)//求弦截点x的坐标
{
return(x1*f(x2)-x2*f(x1))/(f(x2)-f(x1));
}
floatroot(floatx1,floatx2)//求区间(x1,x2)上的根
{
inti;
floatx,y,y1;
y1=f(x1);
do
{
x=xpoint(x1,x2);
y=f(x);
if(y*y1>0)
{
y1=y;
x1=x;
}
else
{
x2=x;
}
}while(fabs(y)>0.00001);
returnx;
}
main()
{
floatx,x1,x2,y1,y2;
do
{
printf("inputx1,x2:
");
scanf("%f%f",&x1,&x2);
y1=f(x1);
y2=f(x2);
}while(y1*y2>0);//是否存在根
x=root(x1,x2);
printf("arootis%f\n",x);
}
eg2:
mn!
编写求C=------------的程序。
nm!
(n-m)!
分析:
重复三次求阶乘的运算,只是每次的值不同。
#include
floatfac(intk)//求阶乘
{
floatt=1;
inti;
for(i=2;i<=k;i++)
t*=i;
returnt;
}
main()
{
floatc;
intm,n;
printf("inputm,n:
");
scanf("%d%d",&m,&n);
c=fac(n)/(fac(m)*fac(n-m));
printf("%d!
/(%d!
*(%d-%d)!
)=%.0f\n",n,m,n,m,c);
}
/*
inputm,n:
58
8!
/(5!
*(8-5)!
)=56
--------------------------------
*/
函数的递归调用
是指在调用一个函数时又直接或间接地调用了函数本身。
直接递归调用
eg:
intf(intx)
{
inty,z;
...注意:
这两个递归都无法结束。
z=f(y);因此应含有某条件控制
...递归调用结束。
}
间接递归调用
eg:
intf1(intx)
{
inty,z;
...
z=f2(y);
...
}
intf2(intt)
{
intu,v;
...
v=f1(u);
...
}
eg1:
有5个人坐在一起,问第5个人多少岁?
答,比第4个人大2岁。
第4个人说他比
第3个人大2岁,第3个人比第2个人大2岁,第3个人比第2个人大2岁,第2个人
比第1个人大2岁,问第1个人时回答是10岁。
那么第5个人到底多大?
#include
intage(intn)
{
intc;
if(n==1)c=10;//递归结束条件
elsec=age(n-1)+2;//相当于数据结构“栈”
returnc;
}
main()
{
printf("%d\n",age(5));
}
eg2:
求阶乘n!
(n>0)
①循环法
floatfac(intn)
{
floatf=1;
if(n>1)
for(i=2;i<=n;i++)
f*=i;
elsef=-1;
returnf;
}
②递归法
递归公式:
n!
=1(n=0,1)
n*(n-1)!
(n>1)
#include
floatfac(intn)
{
floatf;
if(n>1)f=fac(n-1)*n;
elseif(n==0||n==1)f=1;
elsef=-1;
returnf;
}
main()
{
intn;
floaty;
printf("inputaintegernumber:
");
scanf("%d",&n);
y=fac(n);
if(y<0)
printf("error:
%d<0\n",n);
else
printf("%d!
=%.0f",n,y);
}
数组作为函数的参数
1.数组元素做函数实参
eg:
求5个任意整数中的最大数。
#include
intmax(intx,inty)
{
return(x>y?
x:
y);
}
main()
{
inta[5],i,m;
printf("enter5integers:
\n");
for(i=0;i<5;i++)
scanf("%d",&a[i]);
m=a[0];
for(i=0;i<5;i++)
m=max(m,a[i]);
printf("maxis%d\n",m);
}
2.一维数组作为函数的参数
函数的形参是数组,对应的实参必须是数组名。
1.实参数组与形参数组的类型必须一致。
2.用数组名做参数时,传递的是数组的首地址。
因此形参数组也可以不指定大小。
但需另设一个参数,传递数组元素的个数。
3.数组做函数参数时,形参数组和实参数组共享同一内存单元。
如果形参数组的元素的值被修改,实参数组的元素的值也就被改变了。
eg1:
求5个任意整数中的最大数。
#include
#defineN5
intmax(intx[N])
{
inti,m;
m=x[0];
for(i=0;i if(m m=x[i]; returnm; } main() { inta[N],i; printf("enter5integers: \n"); for(i=0;i scanf("%d",&a[i]); printf("maxis%d\n",max(a)); } 形参数组不指定大小,另设一个参数传递数组元素的个数。 #include #defineN5 intmax(intx[],intn) { inti,m; m=x[0]; for(i=0;i if(m m=x[i]; returnm; } main() { inta[N],i; printf("enter5integers: \n"); for(i=0;i scanf("%d",&a[i]); printf("maxis%d\n",max(a,N)); } eg2: 用比较法排序(从大到小) #include #defineN5 voidsort(intx[],intn) { inti,j,t; for(i=0;i for(j=i+1;j if(x[i] { t=x[i]; x[i]=x[j]; x[j]=t; } } main() { inta[N],i; printf("enter5integers: \n"); for(i=0;i scanf("%d",&a[i]); sort(a,N);//a是数组名,传递数组的首地址 printf("enterthearray: \n"); for(i=0;i printf("%d",a[i]); } 3.多维数组作为函数的参数 如果形参是多维数组,可以省略第一维的大小,但不能省略其他维的大小。 eg: 有一个3×4的矩阵,求最大元素的值。 #include intmax(intx[][4]) { inti,j,m; m=x[0][0]; for(i=0;i<3;i++) for(j=0;j<4;j++) if(m m=x[i][j]; returnm; } main() { staticinta[3][4]={{1,3,5,7},{2,4,6,8},{15,13,17,5}}; printf("maxis%d\n",max(a)); } 局部变量与全局变量 局部变量(多用) 在函数内定义的变量;形参也是局部变量;作用域为本函数。 局部变量只在自己的范围内有效。 如果局部变量的有效范围有重叠,则有效范围小的优先。 1.在一个函数内部定义的变量 2.函数的形式参数 3.在某个复合语句中定义的变量 全局变量/外部变量(少用) 在函数之外定义的变量(外部/全程变量)是全局变量 有效范围: 从定义变量的位置开始到源文件结束 1.利用全局变量可以在传递数据 利用全局变量可以减少函数的参数。 2.应尽量少使用全局变量。 3.如果全局变量与局部变量同名,则全局变量优先。 eg: 有5个学生的学习成绩,求平均分、最高分和最低分。 分析: 用一个函数返回三个数据,除了用函数值外,可以借助于全局变量。 #include #defineN5 floatmax=0,min=0; floataverage(floatscore[],intn) { inti; floatsum=score[0]; max=min=score[0]; for(i=1;i { sum=sum+score[i]; if(max if(min>score[i])min=score[i]; } returnsum/n; } main() { floatavg,score[N]; inti; for(i=0;i scanf("%f",&score[i]); avg=average(score,N); printf("max: %f,min: %f,average: %f\n",max,min,avg); } 变量的存储类别 静态存储方式: 编译时分配空间,在程序运行期间占有固定存储空间(static变量、全局变量) 动态存储方式: 程序执行时动态分配存储空间(auto变量、register变量、形参) 若没有指定存储方式,默认动态存储方式auto变量。 eg: #include intsub() { staticinty=1;//保留值 y++; returny; } main() { intj; for(j=1;j<=10;j++) printf("%d",sub()); printf("\n"); } /* 234567891011 -------------------------------- */ 1.变量的动态存储和静态存储 变量的划分 ⑴全局变量与局部变量: 按变量的作用域 局部变量: 1.自动变量 2.静态局部变量 3.寄存器变量 4.形式参数 全局变量 ⑵静态存储变量和动态存储变量: 按变量的存储类别,即生存期 动态存储: 1.自动变量 2.寄存器变量 3.形式参数 静态存储: 1.静态局部变量 2.全局变量 ⑶按变量的存放位置: 动态存储区: 1.自动变量 2.形式参数 静态存储区: 1.静态局部变量 2.全局变量 寄存器: --寄存器变量 (内存中供用户使用的存储空间包括: 程序区 静态存储区: 编译时分配空间 动态存储区: 执行时分配空间) 变量或函数的属性: 数据类型: 1.整型、2.字符型... 存储类别: 1.自动型auto 2.静态型static 3.寄存器register 4.外部型extern 2.局部变量的存储类别 ⑴自动变量 存储在动态存储区,用auto说明--〉通常,将auto省略 eg: intfunc1(inta)形参a,变量b、c都是自动变量。 {调用该函数时,系统给它们分配 autointb,c=3;存储空间,函数调用结束时自动 ...释放存储空间 } ⑵局部静态变量 占用静态存储区,用static说明 1.局部静态变量属于静态存储类别。 在程序整个运行期间都不释放存储空间。 2.局部静态变量在编译时赋初值(仅赋一次初值)。 3.如果定义局部静态变量时没有赋初值,编译时会自动赋初值。 4.局部静态变量只能在定义它的函数内被使用。 (它存在但不能被其他函数使用) eg: 打印1到5的阶乘。 #include floatfac(intn) { staticfloatf=1; f=f*n;//f=1,1,2,6,24 returnf; } main() { intj; for(j=1;j<=5;j++) printf("%d! =%.0f\n",j,fac(j)); } /* 1! =1 2! =2 3! =6 4! =24 5! =120 -------------------------------- */ ⑶寄存器变量(了解) 存储在寄存器中,用register说明 1.计算器的寄存
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 笔记 函数