C语言复习第二十二课.docx
- 文档编号:10357499
- 上传时间:2023-02-10
- 格式:DOCX
- 页数:21
- 大小:23.62KB
C语言复习第二十二课.docx
《C语言复习第二十二课.docx》由会员分享,可在线阅读,更多相关《C语言复习第二十二课.docx(21页珍藏版)》请在冰豆网上搜索。
C语言复习第二十二课
第二十二课
※主要内容
(1)、函数
※主要知识点
1个C源程序=1个主函数+若干子函数
【引例】
任意读入2个数,输出较大数。
intmax(a,b)/*子函数-被调函数*/
inta,b;/*形式参数、形参*/
{intc;
if(a>b)c=a;
elsec=b;
return(c);
}
main()/*主调函数*/
{intx,y,z;
scanf("%d%d",&x,&y);
z=max(x,y);/*实际参数、实参*/
printf("MAX=%d\n",z);
}
一、程序设计的总体思想
“自上而下、逐步细化”的模块化
函数就是一个个功能相对独立的模块。
二、函数的定义
1、C中函数的定义是独立且平等的,即:
“主、子函数的定义不分前后,且不可以嵌套定义。
”
2、使用函数,是因为任务的功能比较复杂。
3、函数的分类:
(1)有参函数
【书写格式】
格式一:
函数返回类型函数名(形参1,形参2)
对形参进行说明;
{函数体
return语句;
}
格式二:
函数返回类型函数名(类型名形参1,类型名形参2)
{函数体
return语句;
}
(2)无参函数
函数返回类型函数名()
{函数体
return语句;
}
另外的划分:
系统函数(库函数)和自定义函数;有返回值的函数和无返回值的函数。
4、例题:
哥德巴赫猜想
任意一个大偶数(>=4)都可以拆成两个素数之和。
【题目:
任意读入一个大偶数>=6,然后输出被拆成的两个素数。
】
/*主函数拆分,子函数判断素数*/
intPDSS(x)
longx;/*与主函数的同名*/
{intflag=1;
longk;
for(k=3;k<=x-1;k=k+2)if(x%k==0){flag=0;break;}
return(flag);
}
main()
{longx;
longs1,s2;
do
scanf("%ld",&x);
while(x<6||x%2!
=0);
s1=3;s2=x-s1;
while(!
PDSS(s1)||!
PDSS(s2))
{s1=s1+2;s2=s2-2;}
printf("%ld=%ld+%ld\n",x,s1,s2);
}
三、自定义子函数的使用说明
1、主、子函数的书写不分前后,但是当被调函数书写在主调函数的后面且返回值不为整型int时,必须在主调函数的说明部分(或在函数体外加以说明)对被调函数加以说明:
【格式】
返回类型名函数名();
2、主函数一般做主调函数(即使带参数,也只能自己调用自己),子函数通常做被调函数,但也可以做主调函数,调用别的子函数或自己。
3、程序的执行总是从主函数到主函数结束,除非遇到exit函数语句。
4、return语句的格式:
格式一:
return(表达式);
格式二:
return表达式;
格式三:
return;
【功能】格式一与格式二的功能完全相同:
将表达式的值(一个值)带回到主调函数的调用点,且立即终止所在函数的执行。
格式三只能终止所在函数的执行并返回主调函数的调用点,但不带回值(因此很少用,通常可以省略)。
四、实参与形参之间的关系
1、实参和形参在个数、类型、顺序上一一对应一致。
2、实参总是单向地传值给形参:
传的值有两种(内容或地址),一般,传内容时常常简称“值传递”,传地址时简称“地址传递”。
3、实参可以是常量、变量(通常有值)、表达式;形参通常是变量。
五、参数的地址传递
例1:
任意读入两个数,调用函数求得二者的和与积。
main()
{floatx,y,h,j;
voidHJ();
scanf("%f%f",&x,&y);
HJ(x,y,&h,&j);
printf("%f,%f\n",h,j);
}
voidHJ(a,b,p,q)
floata,b,*p,*q;
{*p=a+b;
*q=a*b;
}
1、当被调函数没有返回值时,定义时函数名前加void,在主调函数中调用语句的格式:
被调函数名(参数系列);省略类型名时,默认int型。
2、当需要从被调方获得一个以上的值时,通常使用地址传递。
例2:
任意读入10个数,然后进行升序排列。
【分工:
】
main()
{inta[10],i;
voidPX();
for(i=0;i<10;i++)
scanf("%d",&a[i]);
PX(a,10);
for(i=0;i<10;i++)
printf("%d\n",a[i]);
}
voidPX(p,n)
int*p,n;
{inti,j;intt;
for(j=1;j<=n-1;j++)
for(i=0;i<=n-1-j;i++)
if(*(p+i)>*(p+i+1))
{t=*(p+i);*(p+i)=*(p+i+1);
*(p+i+1)=t;}
}
【说明】
(1)当需要将多个值传给被调函数时,通常使用数组名作为实参,同时为了增大被调函数的灵活性,将数组元素的个数也作为实参。
(2)与数组名这个实参对应的形参的格式有两种:
①指针变量;②通常省略了元素个数的数组。
系统会主动将第二种格式转换成相应的指针。
voidPX(intp[],intn)
(3)在形参中出现的一维数组,通常省略元素的个数,系统立刻将之转化成相应的指针变量,本例中即为:
int*p
(4)实参还可以是二维数组的名字,对应形参可以有两种格式:
①行指针变量;②通常省略了第一维的行数的二维数组。
系统会主动将第二种格式转换成相应的指针。
例3:
主函数生成如下5阶方阵,然后调用子函数求得副对角线上所有元素之积,以及方阵所有元素之和,再由主函数输出。
12345
12345
12345
12345
12345
intfun(p,he)
int(*p)[5],*he;
{intji=1;
inti,j;
for(i=0;i<5;i++)
ji=ji*p[i][4-i];
*he=0;
for(i=0;i<5;i++)
for(j=0;j<5;j++)
*he=*he+p[i][j];
returnji;
}
main()
{inta[5][5],i,j;
intji,he;
for(i=0;i<5;i++)
for(j=0;j<5;j++)
a[i][j]=j+1;
ji=fun(a,&he);
printf("JI=%d,HE=%d\n",ji,he);
}
intfun(p,he)
intp[][5],*he;
【归纳】
形参和实参之间的联系方式(单向传递:
实参→形参)
传递方式形参实参(同类型的)说明通过函数调用能否改变实参的值
值传递变量常量、有值的变量、数组元素或表达式实参必须事先获得合法的值不能
地址
传递“共用存贮单元”实质依然是“遥控”
数组名数组的地址(数组名、指向数组的指针等)即使将形参书写成数组名(通常[]内为空),系统立即转换成相应的指针能
“遥控”指针
变量变量(通常原先没有值)的地址、指针变量、数组名等就是想通过调用函数,使实参获得值(或发生变化)能
6、全局变量与局部变量
函数间还可以运用全局变量来交流信息。
1.定义
凡是定义在函数体外的变量称为全局变量或外部变量,其作用域从定义处开始直到程序末尾(但是也可以通过exturn拓展其作用域)。
凡是定义在函数体内的变量称为局部变量或内部变量,其作用域是本函数体内。
而在复合语句开始处定义的变量只在该复合语句中有效。
形参也是局部变量。
2.同名问题
同一个函数内的局部变量不可以同名;同一个程序中的全局变量不可以同名;全局变量与局部变量可以同名,在函数体内与局部变量同名的全局变量失效。
七、变量的存储类别和生命周期(生存期)
1、变量在内存中的存储区域
(1)静态区(从程序开始执行到整个结束)
(2)动态区(函数调用开始到被调结束)
2、存储类别
(1)auto型(自动型)
①只有局部变量(包含形参)可以定义成auto型,定义格式:
[auto]类型名变量名;
②局部变量若定义成auto型,此关键字auto可省略。
③auto型处于内存的动态区,auto型变量随所在函数被调用才被分配内存空间(活了),一旦调用完毕内存空间被收回(即释放,死了)
(2)register型(寄存器型)
少量被反复多次使用的变量一般才定义成register型。
若定义多了,系统会自动转成auto型。
除调用速度更大,其余特性同auto型。
只有局部变量(包含形参)可以定义成register型,定义格式:
register类型名变量名;
(3)static型(静态型)
①全局变量全是静态型的,且通常省略static关键字
②局部变量也可以定义成静态型,形参不可以定义成静态型。
引例:
读程题
main()
{ints,n,i;
n=100;
for(i=1;i<=n;i++)s=f(i);
printf("%d\n",s);
}
intf(intn)
{staticints=0;
s=s+n;
returns;
}
以上输出为:
5050
但若将其中的“static”改为“auto”,则输出为100。
③静态型变量如果进行初始化(即定义的同时赋予值),只有第一次执行定义语句时随着分配内存赋予初值,当退出所定义的函数时,将保留其当时值。
再次调用所在的函数时,将不重新定义,也不进行初始化,此时,该变量值是上次离开时的值。
④静态型变量如果不进行初始化,系统自动为其赋予“0”值。
3、外部变量作用域拓展声明
extern
举例:
voidfun(inta)
{externy;/*拓展声明*/
a=a*a;
printf("%d",a+y);}
inty=9;/*定义变量y*/
main()
{fun(y);}
【声明格式】
extern[原定义类型名]定义在后的全局变量;
八、递归调用
某子函数直接或间接调用自身,被称为“递归调用”。
【引例】5个小孩从大到小一次编号,问5号小孩几岁,告知比4号小2岁;
问4号,说比3号小2岁……问1号,告知10岁。
求5号的年龄。
【“栈”的特点:
“先进后出”或“后进先出”;有底“无”顶。
】
intage(intn)/*求出n号小孩年龄*/
{intnl;
if(n==1)
nl=10;
else
nl=age(n-1)-2;
returnnl;
}
main()
{printf("%d\n",age(5));
}
1、能够运用“递归”解决的问题的特点:
(1)递归的出口(1号说出年龄)
(2)有重复的操作
例:
求n!
【分析:
(1)n!
=(n-1)!
×n
(2)n=1(n=0或1)】
#include
main()
{intn;/*n>=0,n<=20*/
longJC();
FILE*fp;
if((fp=fopen("D:
\\my\\1.out","w"))==NULL)
{printf("OpenFileError\n");exit(0);}
do
scanf("%d",&n);
while(n<0||n>20);
{printf("%ld\n",JC(n));
fprintf(fp,"%ld\n",JC(n));}
fprintf(fp,"20090901007");
fclose(fp);
}
/*子函数求任意合法数的阶乘*/
longJC(intn)
{longjc;
if(n==0||n==1)
jc=1;
else
jc=JC(n-1)*n;
return(jc);
}
2、好多能用循环解决的问题都可以改用递归描述。
例如:
、进制转换等。
但是,不提倡,因为递归的时间和空间复杂度高!
九、函数的指针
函数名就是函数的首地址。
【引例】
intmax(a,b)
inta,b;
{intc;
if(a>b)c=a;
elsec=b;
return(c);
}
main()
{intx,y,z;
int(*fp)();
fp=max;
scanf("%d%d",&x,&y);
z=(*fp)(x,y);
printf("MAX=%d\n",z);
}
1、定义
所指函数的返回值类型(*指针名)();
2、说明
(1)*和指针名是一个整体,外加()提高优先级。
(2)后一个()也不能省,表示所指的是函数。
(3)定义时的“类型名”,必须和所指函数定义时的“类型名”一致,若无返回值则用void。
(4)定义后使用前,必须先赋值“函数名”(因为函数名就是函数的首地址)
(5)凡是写“函数名”的地方(除定义函数外)从此可以用“(*指针名)”替代。
十、主函数的参数
主函数(main)可以带参数,但只能是两个,且格式如下:
intargc,char**argv;
或
intargc,char*argv[];
【说明】
(1)第一个参数必须是整型,名字公认写成“argc”,但可以自定;
(2)第二个参数是指向字符串的指针数组。
名字公认写成“argv”,但可以自定;
(3)任何函数不可以调用主函数,因此实参的给定必须在DOS环境下给出。
练习题
一、选择题
(1)C语言总是从()函数开始执行。
A.mainB.处于最前的C.处于最后的D.随机选一个
(2)函数在定义时,省略函数类型说明符,则该函数值的类型为()
A.intB.floatC.longD.double
(3)以下()函数,真正地没有返回值。
A.inta(){inta=2;return(a);}B.voidb(){printf("c");}
C.inta(){inta=2;returna;}D.以上都是
(4)在C语言中,有关函数的说法,以下正确的是()
A.函数可嵌套定义,也可嵌套调用B.函数可嵌套定义,但不可嵌套调用
C.函数不可嵌套定义,但可嵌套调用D.函数不可嵌套定义,也不可嵌套调用
(5)以下函数调用语句中,含有实参的个数为()
fun((2,3),(4,5+6,7));
A.1B.2C.5D.6
(6)函数调用可以在()
A.函数表达式中B.函数语句中C.函数参数中D.以上都是
(7)被调函数返回给主调函数的值称为()
A.形参B.实参C.返回值D.参数
(8)(),可以不进行函数类型说明。
A.被调函数的返回值是整型或字符型时B.被调函数的定义在主调函数定义之前时
C.在所有函数定义前,已在函数外预先说明了被调函数类型D.以上都是
(9)被调函数通过()语句,将值返回给主调函数。
A.ifB.forC.whileD.return
(10)被调函数调用结束后,返回到()。
A.主调函数中该被调函数调用语句处
B.主函数中该被调函数调用语句处
C.主调函数中该被调函数调用语句的前一语句
D.主调函数中该被调函数调用语句的后一语句
(11)以下对C语言函数的有关描述中,正确的是()。
A.在C中,调用函数时,只能把实参的值传送给形参,形参的值不能传送给实参
B.C函数既可以嵌套定义又可递归调用
C.函数必须有返回值,否则不能使用函数
D.C程序中有调用关系的所有函数必须放在同一个源程序文件中
(12)C语言中函数的隐含存储类型是()。
A.autoB.staticC.externD.无存储类型
(13)能把函数处理结果的两个数据返回给主调函数,在下面的方法中不正确的是()。
A.return这两个数B.形参用两个元素的数组
C.形参用两个这种数据类型的指针D.用两个全局变量
二、填空题
(1)变量的作用域主要取决于变量,变量的生存期既取决于变量,又取决于变量。
(2)说明变量时,若省略存储类型符,系统默认其为存储类别,该存储类别的类型符为:
。
(3)静态型局部变量的作用域是,生存期是。
(4)函数中的形参和调用时的实参都是数组名时,传递方式为,都是变量时,传递方式为。
(5)函数的形式参数的作用域为,全局的外部变量和函数体内定义的局部变量重名时,变量优先。
(6)若自定义函数要求返回一个值,则应在该函数体中有一条语句,若自定义函数要求不返回一个值,则应在该函数说明时加一个类型说明符。
(7)若函数的形式参数是指针类型,则实参可以是、或。
(8)函数的参数为char*类型时,形参与实参结合的传递方式为。
(9)函数的实参为常量时,形参与实参结合的传递方式为。
(10)对数组按值从大到小的顺序排序后输出,请填空。
#include
voidmain()
{
floata[7]={2,6,3,8,3,12,9};
inti ;
voidsort(float*,int);
;
for(i=0;i<7;i++)printf("%f",a[i]);
printf("\n");
}
voidsort()
{
inti,j,k;floatt;
for(i=0;i { k=i; for(j=i+1;j if()k=j; {t=*(p+i);*(p+i)=*(p+k);*(p+k)=t;} } } (11)下列函数在n个元素的一维数组中,找出最大值、最小值并传送到调用函数,请填空。 #include voidfind(float*p,float*max,float*min,intn) { intk; ; *max=*p;; for(k=1;k { t=*(p+k); if()*max=t; if(t<*min)*min=t; } } 三、程序执行题 (1) main() { inti=1,p; p=fun(i,i+1); printf("%d\n",p); } intfun(inta,intb) { intf; if(a>b) f=1; elseif(a==b) f=0; else f=-1; returnf; } 输出: (2)键盘输入abcdef #include voidfun() { charc; if((c=getchar())! ='\n') fun(); putchar(c); } voidmain() {fun();} 输出: (3) #include #defineC5 intx=1,y=C; voidmain() { intx; x=y++;printf("%d%d\n",x,y); if(x>4) {intx;x=++y;printf("%d%d\n",x,y);} x+=y--; printf("%d%d\n",x,y); } 输出: (4) #include intc,a=4; func(inta,intb) {c=a*b;a=b-1;b++;return(a+b+1);} voidmain() { intb=2,p=0;c=1; p=func(b,a); printf("%d,%d,%d,%d\n",a,b,c,p); } 输出: (5) unsignedfun6(unsignednum) { unsignedk=1; do{k*=num%10;num/=10;} while(num); returnk; } voidmain() { unsignedn=26; printf("%d\n",fun6(n)); } 输出: 时间: 2012年11月14号 热点作文5 Directions: Forthispart,youareallowed30minutestowriteacompositiononthetopicSecondhandGoods.Youshouldwriteatleast150words,andbaseyourcompositionontheoutline(giveninChinese)below: 1)目前购买二手货的人越来越多 2)分析产生这一现象的原因 3)二手货交易可能带来的问题 【思路点拨】 本题属于提纲式文字命题。 提纲第1点指出一种现象,提纲第2点要求分析该现象产生的原因,提纲第3点要求谈谈该现象可能带来的问题,由此可判断本文应为现象解释型作文 根据所给提纲,本文应包含以下内容: 描述目前二手货的交易现状;说明二手货交易增加的原因;分析二手货交易可能带来的问题。 【参考范文】 SecondhandGoods Inrecentyears,second-handtransactionshavebecomequitecommon.Nowadaystherearemoreandmoresecondhandgoodsinthemarket,suchassecondhandbooks,furniture,appliances,cars,andsoon.Whydosomanypeopleliketobuysecondhandgoods? Thefollowingreasonscanaccountforthisphenomenon.Aboveall,secondhandgoo
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 复习 第二十二