第8 章函数文档格式.docx

上传人:b****6 文档编号:20407587 上传时间:2023-01-22 格式:DOCX 页数:36 大小:28.80KB
下载 相关 举报
第8 章函数文档格式.docx_第1页
第1页 / 共36页
第8 章函数文档格式.docx_第2页
第2页 / 共36页
第8 章函数文档格式.docx_第3页
第3页 / 共36页
第8 章函数文档格式.docx_第4页
第4页 / 共36页
第8 章函数文档格式.docx_第5页
第5页 / 共36页
点击查看更多>>
下载资源
资源描述

第8 章函数文档格式.docx

《第8 章函数文档格式.docx》由会员分享,可在线阅读,更多相关《第8 章函数文档格式.docx(36页珍藏版)》请在冰豆网上搜索。

第8 章函数文档格式.docx

识符;

3.函数原型及其一般格式:

(P153)

【说明】在函数的声明中也可以不写形参名,只写形参的类型,这种函数声明称之为函数原型。

floatadd(float,float);

【说明】因为编译系统部检查函数名,故函数名有无都无所谓。

4.对被调函数不需声明的情形:

(P154)

①被调函数定义在主调函数之前;

intmax(intx,inty){}main(){max(x,y);

}

②在所有函数定义之前,在函数的外部已作声明;

③函数的类型为int、char型时可不作声明(但实参和形参的类型应一致,否则可能出错)

四、函数的调用(P150)

1.函数调用的一般格式:

函数名(实际参数列表)(P150)

【说明】

①即使函数没有参数,但函数名后面的()不能省略。

②实际参数在类型、个数、顺序上要求和形式一致;

实参与形参按顺序对应,一一传递数据;

③系统对数据参数的求值顺序不定;

者将影响结果(TC中为从右到左)。

(P150)

50

intsa(inta,intb){

if(a>

b)return

(1);

elsereturn(a==b?

0:

-1);

main(){

inti=3;

printf(“”,sa(i,i++));

intsa(inta,intb){

return(a==b?

0:

a>

b?

1:

inti=2;

printf("

%d"

sa(i,++i));

2.函数调用的方式和调用形式(P150)

1)调用的方式:

(1)函数语句。

printf(“Thisisacprogram”);

(2)函数表达式。

c=max(2,3);

(3)函数参数(函数作为其他函数的参数)。

mx=max(a,max(b,c))

2)调用的形式:

(1)传值调用:

传递数据本身,实参与形参互不影响(实参与形参分别占用不同的存储空间)

(2)传址调用:

传递装载数据的空间的地址;

实参与形参分别占用不同的存储空间

(3)嵌套调用:

函数之间互相调用

(4)递归调用:

函数自己调用自己

3.函数的传值调用

【传值调用过程】

①实参与形参分别占用不同的存储空间,形参值的改变不能传回给对应的实参;

②形参的存储空间是在函数被调用时分配的,然后将实际参数的值传递到该空间中。

③函数调用结束,形式参数所占的存储空间自动释放;

【实例1】voidswap(intx,inty){

x=x+y,y=x-y,x=x-y;

swap:

x=%dy=%d\n"

x,y);

inta=3,b=5;

swap(a,b);

main:

a=%db=%d\n"

a,b);

结果为:

x=5y=3

a=3b=5

【实例2】用数组元素作为参数(实际参数,形式参数为变量)

voidswap(inta,intb);

inta[]={4,9};

a[0]=%da[1]=%d\n"

a[0],a[1]);

swap(a[0],a[1]);

51

voidswap(inta,intb){

intt;

t=a,b=a,b=t;

a[0]=4a[1]=9

4.函数的传地址调用(例:

8.13,P166)

【传址调用过程】①实参与形参分别占用同一的存储空间,形参值的改变将传回给对应的实参中;

【实例1】用指针变量作为参数(形式参数)

voidswap(int*x,int*y){

*x=*x+*y;

*y=*x-*y;

*x=*x-*y;

*x=%d*y=%d\n"

*x,*y);

main(){inta=3,b=5;

*x=5*y=3

a=5b=3

【实例2】用一维数组名作为参数(实际参数和形式参数)

voidswap(inta[2]);

swap(a);

voidswap(intb[2]){

t=b[0];

b[0]=b[1];

b[1]=t;

a[0]=9a[1]=4

【实例3】用数组名作为参数(实际参数用二维数组,形式参数用一维数组)

intmaxvalue(intb[]);

intn;

inta[][4]={{100,300,500,980},{12,24,36,57},{10,20,30,40}};

max=%d\n"

maxvalue(*a,12));

intmaxvalue(intb[],intn){

inti=0,k=0;

52

for(;

i<

n;

i++)if(b[i]>

b[k])k=i;

returnb[k];

5.函数嵌套调用(P155):

voidsb(){

Subfunction\'

sb()\becalledbysunfunction\'

sa()\'

\n"

);

voidsa(){

sb();

sa()\becalledbysubfunction\'

SubFunction\'

becalledbymainFunction.\n"

sa();

6.函数递归调用(P158):

在函数的过程中出现直接或间接调用该函数本身

1)直接递归调用:

在函数的过程中直接调用该函数本身。

【例1】求n!

(P160)

floatfac(intn){

floatf=1;

if(n<

0){

n<

0,DataError"

exit

(1);

if(n==0||n==1)f=1;

elsef=fac(n-1)*n;

return(f);

n=?

"

scanf("

&

n);

%d!

=%-15.0f"

n,fac(n));

if(n==0||n==1)return

(1);

elsereturn(n*fac(n-1));

【例2】要求不用循环语句(用直接递归),求1+2+3+┅┅+100(n属于正自然数)

longsum(intn){

if(n>

0)return(n+sum(n-1));

elsereturn(0);

53

sum=%ld"

sum(100));

【例3】输入一字符串后,再反向输出(用直接递归)。

程序1:

voidconver(char*p){

charq=*p;

if(*p)conver(++p);

%c"

q);

char*p="

;

Inputastring:

gets(p);

conver(p);

程序2:

#include"

stdio.h"

voidgt(char);

gt(getchar());

voidgt(chars){

if(s!

='

\n'

)gt(getchar());

s);

【例4】求1-100的合计(用直接递归,n大于100,且由参数输入)。

floatsum(int);

sum=%f"

sum(1000));

floatsum(inti){

if(i>

0)return(i+sum(i-1));

实现系统函数strcmp()的功能

string.h"

intsum=0;

voidum(inti,intn){

if(i<

=n)um(sm(i),n);

intsm(inti){

sum=sum+i;

return(i+1);

intscmp(chara,charb){/*实现系统函数strcmp()的功能*/

*b&

&

*a;

a++,b++)if(*a!

=*b)break;

return(*a-*b);

54

main(){chara[]="

China"

b[]="

American"

strcmp(%s,%s)=%d\n"

a,b,scmp(a,b));

um(1,100);

1+2+...+100=%d\n"

sum);

【例5】Hanoi问题(用直接递归)(P161)。

【例6】求1!

+2!

+……+n!

(用直接递归)(P161)。

floata=1,m=0;

voidsum(inti,intn){

if(i<

=n)sum(ss(i),n);

intss(inti){

a=a*i;

m=m+a;

inti=1,n=10;

sum(i,n);

1!

+2!

+....+%d!

=%f"

n,m);

floatfac(inti){

floatp=1;

intk=1;

k<

=i;

k++)p=p*k;

=%f\n"

i,p);

return(p);

main(){floatsum=0;

inti=1;

=10;

i++)sum=sum+fac(i);

+....+10!

程序3:

floatpt(intn){

=1)return

(1);

elsereturn(n*pt(n-1));

floatfat(inti){

elsereturn(fat(i-1)+pt(i));

fat(10));

55

程序4:

1)return(n*fac(n-1));

elsereturn

(1);

floatsum(intn){

0)return(fac(n)+sum(n-1));

intn=1;

20;

n++)printf("

+"

n);

n,sum(20));

程序5:

#defineN10

floatfas(intn){

staticfloatp=1;

p*=n;

floatsm(intn){

=N)return(fas(n)+sm(n+1));

N;

for(n=1;

n,sm

(1));

【例8】用循环和递归求任意两个正整数的最大公约数

intgcd(intm,intn){

if(m%n)gcd(n,m%n);

elsereturn(n);

main(){inta=26,b=20,cs=0,r;

GCDINSUNF:

%d\n"

gcd(a,b));

a=20,b=26;

while((r=a%b)!

=0){

a=b;

b=r;

cs++;

GCDINMAIN:

%dcs:

%d"

b,cs);

intscmp(char*a,char*b){

56

chara[]="

2)间接递归调用:

在函数的过程中直接调用其他函数,其他函数又调用该函数本身。

五、函数的参数、返回值与属性(P164)

1.函数参数的类别(实际参数:

调用函数时传递;

形式参数:

定义函数时指定):

1)实际参数:

简称为实参。

有两种形式:

值参数:

传递的是数值;

址参数:

传递的是地址;

(1)值参数的具体形式:

实参数的形式可以是:

常量、变量(含数组元素)、表达式、函数调用;

(2)值参数的数据类型:

int(6种)、char(2种)、float、void、结构体(或共同体)类型;

【说明】对应形式参数值的改变不影响实际参数的值;

因它们分别占用不同的存储单元(内存空间);

(3)址参数的具体形式:

指针、数组名(一维数组名或二维数组必须是列地址);

(4)址参数的数据类型:

指针、数组;

【说明】①实参的数据类型:

int(6种)、char(2种)、float、void、指针、数组名、结构体、共同体;

②对应形参数值的改变影响实参的值;

因它们占用同一的存储空间;

2)形式参数:

简称形参,在定义函数时指定其名称和数据类型;

(1)形参的具体形式:

只能是一般变量名、数组名、指针变量;

不能是常量、表达式或函数调用;

(2)形参的数据类型:

int(6种)、char(2种)、float、void、结构体、共同体、指针、数组;

(P165)

①实际参数与形式参数的数据类型应该一致,否则可能发生类型转换,具体情形有:

int(short,long)→unsignedint;

int(short,long)→char;

int→long;

int(short,long)→float;

double→float;

char→unsignedchar及其逆运算;

②形参的形式只能是一般变量名或数组名或指针变量;

实际参数的形式和类型要而与形式参数的形式

和类型对应(相容);

当实参是值参时(形如常量、变量、数组元素、表达式、函数调用),对应

的形式参数只能是一般变量的形式;

当实参是地址时(形如变量(数组元素)地址、数组名、指针

变量),对应的形式参数只能是地址形式(数组名或指针变量)。

③实参数组与形参数组的大小可以不一致,因编译系统对此不做检查;

只将其首地址传递给形参;

④形参数组的可以不指定大小,另设一参数传递其大小(当为字符数组时可以不传递数组的大小);

⑤当实参为址(指针、数组名)传递时,对应形式参值的改变要影响实参值的改变;

因它们共同占用

同一存储单元(即内存空间)。

P166

⑥实参为一般变量、数组名、指针变量时,应在主调函数中对其给予定义。

2.函数的类型

通常把函数返回值的类型称之为函数的类型,即定义时所指定的类型(函数的类型以定义的类型为

准)。

【说明】①int和char型函数在定义时可以不指定其类型(系统默然指定为整型)

②函数在定义时未指定其类型,系统默然指定其类型为整型

3.函数的返回值

①函数的返回值通过程序中的return(表达式)返回;

57

②在程序中有多个表达式时,由被执行到的第一个return(表达式)返回函数的结果值;

③函数在返回时将返回值的类型自动转化为该函数定义的类型;

即以定义的类型为准;

④函数可以没有返回语句。

⑤当函数类型指定为void类型时,在函数中可有return语句,但不能返回表达式否则出错;

【函数递归实现的原理与递归终结条件】

函数的递归调用从某种意义上说相当与循环,但又有别于循环。

函数的递归调用就是在执行过程中,函

数的可执行部分尚未终止,接着又直接或间接的调用函数自己。

函数的递归调用分为直接递归和间接递

归。

直接递归就是一次函数的执行尚未结束,在本身的函数体中又调用自己。

函数直接递归调用的关键是:

怎样才能实现递归调用?

怎样使递归调用终结?

终结条件是什么?

1)实现有条件的递归调用,即当条件满足时函数才递归调用,否则就结束递归调用。

2)递归调用的终结条件:

(1)至少有一次不用递归调用的情况,关键是在不同的情况如何实现。

(2)递归实现的条件要能够向非递归转化。

要不然可能造成无限的递归调用;

输入若干字符,以回车作为输入结束标志。

要求反向输出。

若输入为:

ABCDEFGHIJK↙

要求输出:

KJIHGFEDCBA

自己定义函数如下:

voidsa(charch){

if(ch!

='

)sa(getchar());

/*递归实现的条件ch!

*/

printf(“%c”,ch);

/*自动变量的特点,不同函数中的同名变量互不影响*/

请注意该递归调用过程中递归条件是怎样向非递归转化的?

思考题:

将上述函数改为如下程序后,能否实现上述要求?

为什么?

elseprintf(“%c”,ch);

【问题】利用静态变量和自定义函数与函数的递归调用实现求1-100的合计,不能用循环结构。

8.2函数的属性(内部函数与外部函数)

根据函数能否被其他函数调用,将函数分为内部函数和外部函数

一、内部函数

1.概念:

如果一个函数只能被本文件中的其他函数所调用,则称之为内部函数;

又称之为静态函

数。

2.定义格式:

static类型名称函数名称(形式参数列表)

【说明】不同文件之间的静态同名函数互不影响。

二、外部函数

如果一个函数能被本文件外的其他函数所调用,则称之为外部函数;

又称之为全局函数。

extern类型名称函数名称(形式参数列表)

【说明】在需要调用此函数的文件中,用extern声明所用的函数为外部函数。

三、多个源文件的编译、连接(P184)

【工程文件的建立】

1.先编辑每个需要的源文件

2.编辑工程文件(即项目文件)(.prj);

工程文件中只包含需要连接、编译的每个源文件名称即

可。

3.通过alt+p打开主菜单,选择“ProjectName”,输入工程文件名

4.最后编译为一个可执行文件

【外部函数调用实例分析:

多个源文件的连接、编译】

58

/*enterab.prj文件的内容:

*/

entabgetmaxgetmingetsum

/*源程序文件entab.c的内容*/

inta,b;

/*externintmax(int,int);

externintmin(int,int);

externintsum(int,int);

Inputab:

scanf("

%d%d"

a,&

b);

max=%d\nmin=%d\nsum=%d\n"

max(a,b),min(a,b),sum(a,b));

/*源程序文件getmin.c的内容*/

intmin(inta,intb){

return(a>

b:

a);

/*源程序文件getmax.c的内容*/

intmax(inta,intb){

a:

/*源程序文件getsum.c的内容*/

intsum(inta,intb){

return(a+b);

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1