函数及其应用_第1页
函数及其应用_第2页
函数及其应用_第3页
函数及其应用_第4页
函数及其应用_第5页
已阅读5页,还剩64页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

函数及其应用1第一页,共六十九页,编辑于2023年,星期五

10.1函数的基本概念一个较大的程序一般由若干个程序模块(子程序)组成,每一个模块(子程序)来完成一定的功能。在C语言中,子程序的作用是由函数来实现的。

一个C程序可由一个主函数和若干个函数构成,由主函数调用其它函数,其它函数也可互相调用。同一个函数可以被一个或多个函数调用任意多次。下图是一个程序中函数调用的示意图:2第二页,共六十九页,编辑于2023年,星期五main()A()B()C()D()E()F()G()E()H()H()H()G()函数调用示意图:调用3第三页,共六十九页,编辑于2023年,星期五

(1).

一个源程序文件由一个或多个函数组成.一个源程序

文件是一个编译单位,而不是以函数为单位进行编译.说明:(2).一个C程序可由一个或多个源程序文件组成.

这样可以分别进行编写,编译,调试.一个源文件可以为

多个C程序公用.(3).所有函数是平行的,一个函数并不从属于另一个函

数,函数可以相互调用,但不能调用main()函数.4第四页,共六十九页,编辑于2023年,星期五(4).从使用角度来分,函数可分为:数学函数(#include"math.h")

字符函数(#include"ctype.h")

库函数字符串函数(#include"string.h")

输入输出函数(#include"stdio.h")

动态存储分配函数(#include"stdlib.h")

…..

自定义函数:5第五页,共六十九页,编辑于2023年,星期五从函数的形式来分;

无参函数:主调函数没有数据传给被调函数

有参函数:主调函数可以将数据传给被调函数空函数:什么也不干,先占位置,以后扩展功能6第六页,共六十九页,编辑于2023年,星期五一.函数定义的一般形式:(自定义函数)

(1).无参函数的定义形式:

类型标识符函数名(){函数体}

函数定义一律

不能加分号(;)!说明:

类型标识符是指函数返回值的类型.

如果函数不要返回值,可写上void.7第七页,共六十九页,编辑于2023年,星期五(2).有参函数定义:类型标识符函数名(形式参数表列){声明部分语句}形式参数例:intadd(intx,inty){intz;z=x+y;returnz;}注:

返回值z的类型(int)

应与类型标识符统一。8第八页,共六十九页,编辑于2023年,星期五1、函数参数与函数值;(1)形参与实参:例:main(){inta,b,c;

scanf(“%d,%d”,&a,&b);

c=max(a,b);printf(“maxis%d”,c);}intmax(intx,inty)

/*定义有参函数max*/{intz;z=x>y?x:y;return(z);}x,y为形参a,b为实参10.2函数的参数9第九页,共六十九页,编辑于2023年,星期五b.实参可以是常量、变量、或表达式,但要求有确定值.

如:

max(3,a+b);c.实参与形参的类型应一致,一一对应。说明:a.形参变量(上例中的x,y),在未调用时,并不占用存储单元,当进行函数调用时,形参才分配内存单元,调用结束后,形参就释放掉。10第十页,共六十九页,编辑于2023年,星期五d.实参对形参的数据传递是单向传值,只能是由实参传给形参,而不能相反进行。

实参、形参在内存中,占据不同单元。

2

a

b32

x

3

y

即使形参单元中的值发生变化,也不会影响实参单元的值.

函数调用后,形参单元释放掉,实参单元仍保留。11第十一页,共六十九页,编辑于2023年,星期五例10.9阅读一下程序,写出程序运行结果#include<stdio.h>intswap(intx,inty){ inttemp; temp=x; x=y; y=temp; return0;}intmain(){ inta,b; scanf("%d%d",&a,&b);

swap(a,b); printf("%d,%d\n",a,b); return0;}Ch10_10_9.c

即使形参单元中的值发生变化,也不会影响实参单元的值.

两变量进行交换.12第十二页,共六十九页,编辑于2023年,星期五2.函数的返回值与return语句:

执行C语言程序就是调用一个个函数,函数被调用时,可以返回某一个值作为该函数的值(供主函数使用)。需要返回值时,在函数中返回的地方使用return语句:

return(表达式);

这里表达式的值就是函数的返回值。13第十三页,共六十九页,编辑于2023年,星期五说明:

a.return语句后面的括号可省去:

如:return(z);returnz;return后面可以是一个表达式.

14第十四页,共六十九页,编辑于2023年,星期五

b.当函数不需要带回返回值,C语言有二种方法处理:

①.使用不带表达式的return语句,如:return;②.连return也不用,这是因为函数末尾,隐含一个return

语句,当遇到后面的大括号“}”,就把控制权交给主调

函数。15第十五页,共六十九页,编辑于2023年,星期五为了明确表示不带回值,可用“void“定义。如:voidprintstar();这样可以保证函数不带回任何值.c.若函数不指定带值返回,并不是不返回什么值,可能返回一个不定值。

因为不考虑使用,即使返回是不定值,也无多大关系。

16第十六页,共六十九页,编辑于2023年,星期五#include<stdio.h>intadd(intx,inty){ intz; z=x+y; returnz;}intmain(){ inta,b,c; scanf("%d%d",&a,&b); c=add(a,b); printf("c=%d\n",c); return0;}例:10.1函数值传递的例子.(P149)函数在被调用前必须先定义或说明!Ch10_10_1.c17第十七页,共六十九页,编辑于2023年,星期五例:10.2

函数地址传递的例子.(P150)

输入一个由数字组成的字符串,转换成一个整数.#include<stdio.h>intctoi(char*p){intsum=0;while(*p){sum=sum*10;sum=sum+(*p-'0');p++;

}returnsum;}intmain(){charstr[5];intx;

printf(“stringis:\n");scanf("%s",str);x=ctoi(str);

printf(“integeris%d\n",x);return0;}数组名作为函数的参数

Ch10_10_2.c*p-’0’

把一个字符数字转成数字.18第十八页,共六十九页,编辑于2023年,星期五3、函数的调用:(1).函数调用的方式:有以下三种函数调用方式:a.函数语句:函数作为一条语句,不要求函数带回值,完成一定的功能、操作。如:

printstar();b.函数表达式:函数调用出现在一个表达式中。如:

c=z*max(a,b);这时要求函数带回一个确定的值,以参加运算。19第十九页,共六十九页,编辑于2023年,星期五c.函数参数:

如:printf(“%d”,max(a,b));max(a,b)作为printf函数的一个参数。

20第二十页,共六十九页,编辑于2023年,星期五10.3系统函数的应用C语言提供了十分丰富的库函数.这些函数可分为:

1.数学函数,如:

sin(),sqrt()函数等.它们的包含文件是:“math.h”.

2.字符串函数,如:gets(),strcmp()函数等.它们的包含文件是:“string.h”.

3.输入输出函数,它们的包含文件是:“stdio.h”.

21第二十一页,共六十九页,编辑于2023年,星期五10.3.1数学函数常用的数学函数有:

(1).sqrt():doublesqrt(doublex);计算;x应>=0

(2).fabs():doublefabs(doublex);计算x的绝对值

x(3).pow():

doublepow(doublex,doubley);计算xy

的值

(4).exp():doubleexp(doublex);计算ex

的值22第二十二页,共六十九页,编辑于2023年,星期五例10.3

求z=xy+c

的值,在C语言中xy可调用系统函数

pow()函数来求得。#include<stdio.h>#include<math.h> //必须加入数学库头文件intmain(){ doublex,y,z,c; printf("Pleaseinputxyc\n");

scanf("%lf%lf%lf",&x,&y,&c);

z=pow(x,y)+c; printf("z=%lf\n",z); return0;}C++另一注解方法23第二十三页,共六十九页,编辑于2023年,星期五例10.4

利用循环的方法产生1~100间的10个随机数,并在屏幕上显示.关于rand()随机函数:

rand()会返回一随机数值,范围在0至RAND_MAX间.

24第二十四页,共六十九页,编辑于2023年,星期五#include<stdio.h>#include<stdlib.h>voidmain(){printf("RAND_MAX=%ld\n",RAND_MAX);}说明:

RAND_MAX是一宏定义值.是系统最大的被rand()返回的值.

其值可用下列程序输出:视系统不同而不同(32767).25第二十五页,共六十九页,编辑于2023年,星期五2.srand(seed)函数:

srand()用来设置rand()产生随机数时的随机数种子。参数seed必须是个整数,通常可以利用time(0)的返回值来当做seed.

如果每次seed都设相同值,rand()所产生的随机数值每次就会一样。

3.time()函数返回从1970年开始经历时间的秒数。26第二十六页,共六十九页,编辑于2023年,星期五例10.4

利用系统函数rand(),此函数产生1~100间的10个随机数,此函数在头件stdlib.h进行了声明.#include<time.h>#include<stdio.h>#include<stdlib.h>intmain(){

inti,j;

srand(time(0));

for(i=0;i<10;i++) {

j=1+(int)(100.0*rand()/(RAND_MAX+1.0));

printf("%4d",j); }printf("\n"); return0;}初始化随机数发生器ch10_4_1.c27第二十七页,共六十九页,编辑于2023年,星期五

在C语言提供的库函数中,有丰富的关于字符串操作的函数。它们的头文件有的是stdio.h,有的是string.h.

1.puts(字符数组名)(头文件是stdio.h)

功能:将一个字符串输出到终端。如:charstr[]=“China”;puts(str);

10.3.2字符串处理函数将输出:China

注:只能输出一个字符串,不能写作:puts(str1,str2);28第二十八页,共六十九页,编辑于2023年,星期五2.gets(字符数组名):(头文件为Stdio.h)

功能:从终端输入一串字符到字符数组。如:charstr[10];gets(str);——输入一串字符

gets()函数以回车结束输入。3.其它常用的字符串操作函数有:

a.strcpy(s1,s2)功能:拷贝字符串s2到s1,s1必须写成数组名形式,s2可以是

数组名,也可是字符串常量。29第二十九页,共六十九页,编辑于2023年,星期五

b.strcat(S1,S2)功能:

把字符串S2接到S1的结尾。自动去掉S1结尾的‘\0’,只在新字符串结尾保留‘\0’。

c.strlen(S1)功能;函数返回S1的实际长度(不包括‘\0’).

如:charstr[10]=“China”;

printf(“%d”,strlen(str));

输出不是10,也不是6,而是5.

30第三十页,共六十九页,编辑于2023年,星期五d.strcmp(S1,S2)功能;

对两个字符串自左到右逐个字符进行比较,按

ASCII的值比较。直到出现不同字符或遇到‘\0’为止。

S1==S2

……函数返回值为0

S1>S2

……函数返回值为>0

S1

<S2

……函数返回值<031第三十一页,共六十九页,编辑于2023年,星期五例10.5

从键盘输入两个字符串,把两个字符串连接后输出到屏幕#include<stdio.h>#include<string.h>intmain(){ chars1[80],s2[80];

gets(s1); gets(s2);

strcat(s1,s2); puts(s1); return0;}gets()以回车结束输入.ch10_5.c32第三十二页,共六十九页,编辑于2023年,星期五例10.6从键盘输入一个字符串,求这一字符串长度#include<stdio.h>#include<string.h>intmain(){ intx; charstr[80]; gets(str);

x=strlen(str); printf("该字符串长度:%d\n",x); return0;}ch10_6.c33第三十三页,共六十九页,编辑于2023年,星期五10.3.3字符操作函数与转换函数1.isalnum():函数原型:

intisalnum(intch);检查ch是否为字母或数字.是字母或数字返回1,否则返回0.2.isalpha():

函数原型:

intisalpha(intch);检查ch是否为字母.是字母返回1,否则返回0.34第三十四页,共六十九页,编辑于2023年,星期五3.islower():函数原型:

intislower(intch);检查ch是否为小写字母(a~z).是返回1,否则返回0.4.isxdigit():函数原型:

intisxdigit(intch);检查ch是否为一个十六进制字符(0~9或a~f或A~F).是返回1,否则返回0.35第三十五页,共六十九页,编辑于2023年,星期五5.atoi()

函数原型:

intatoi(char*str)

函数功能:

将(一含有数字内容的)字符串转换成一个整数数值.

头文件:

<stdlib.h>

#include<stdlib.h>#include<stdio.h>

intmain(){

intn;

charstr[

]="12345.78";

n=atoi(str);

printf("string=%s

integer=%d\n",str,n);

return0;}36第三十六页,共六十九页,编辑于2023年,星期五例10.7

从键盘输入一些字符,输出其中的大写字符与十六进制字符,当输入字符@结束字符#include<stdio.h>#include<string.h>intmain(){ charch; while((ch=getchar())!='@') {

if(isupper(ch)||isxdigit(ch)) printf("%3c",ch); } printf("\n"); return0;}ch10_7.c37第三十七页,共六十九页,编辑于2023年,星期五10.4自定义函数C语言允许用户自定义函数.例如:下面是一个自定义函数,功能是求两个整数之和.

intadd(intx,inty){intz;z=x+y;returnz;}38第三十八页,共六十九页,编辑于2023年,星期五

关于对被调用函数的声明和函数原型:

在一个函数中调用另一个函数(即被调函数)需要具备哪些条件?

a.函数要存在(库函数或自定义函数).

此外还要:

b.如果是库函数,一般应在文件开头用#include命令把

相关函数的一些信息包括进去.

39第三十九页,共六十九页,编辑于2023年,星期五如果用户自己定义了一个函数,同时主调函数与被调函数在同一源文件中:一般情况下,主调函数中要对被调用函数的作一声明.

函数声明即向编译系统声明将要调用此函数,并将有关信息通知编译系统.40第四十页,共六十九页,编辑于2023年,星期五例:main(){floata,b,c;scanf(“”%f,%f”,&a,&b);c=add(a,b);printf(“sumis%f”,c);}

floatadd(floatx,floaty)

{floatz;z=x+y;return(z);}

对被调函数的声明floatadd(floatx,floaty);

函数声明是一语句,

要加分号;自定义add函数.

C语言在进行编译时是从上到下逐行进行的,如果没有对函数进行声明,如上例,当编译到“c=add(a,b);”时,

并不知道add是不是函数名,也无法判断实参(a和b)的类型与个数正确与否?41第四十一页,共六十九页,编辑于2023年,星期五

(1).“定义”与“声明”不是一回事.“定义”:是指对函数功能的确定,包括指定函数名,函数值类型,

形参及其类型,函数体等.它是一个完整的,独立的函数

单位.

说明:而“声明”的作用:则是把函数的名字,函数的类型,以及形参的类型,个

数和顺序通知编译系统,以便在调用该函数时系统按此

检查.42第四十二页,共六十九页,编辑于2023年,星期五(2).其实,在函数声明中也可以不写形参名,而只写形参的

类型.如:floatadd

(float,

float);

(3).在C语言中,以上的函数声明称为函数原型.

使用函数原型的主要作用是:利用它在程序的编译阶

段,对被调函数的合法性进行全面检查.43第四十三页,共六十九页,编辑于2023年,星期五

函数原型的一般形式:(a).函数类型函数名(参数类型1,参数类型2,…..)(b).函数类型函数名(参数类型1参数名1,

参数类型2参数名2,…..)函数原型第一种是基本的形式,为了便于阅读,也允许加上参数名.但编译系统并不检查参数名,因此参数名是什么都无所谓.44第四十四页,共六十九页,编辑于2023年,星期五(4).对被调函数声明,在下列三种情况下可省略:说明:(a).如果函数的返回值是整型,或字符型可以省去(以

前我们遇到的大多是这种情况)。系统自动按整型处理,建议加以说明为好。(b).被调用函数的定义位置出现在主调函数之前,可省

去声明,这时编译系统已知道了已定义的函数类型,

会自动处理.

如下例:45第四十五页,共六十九页,编辑于2023年,星期五

floatadd(floatx,floaty)

/*定义add函数*/

{floatz;z=x+y;return(z);}

main(){floatadd(floatx,floaty);

floata,b,c;scanf(“”%f,%f”,&a,&b);c=add(a,b);printf(“sumis%f”,c)}

此处不必对

add()作声明(c).此外,在文件开头(所有函数定义之前),对函数进

行了函数的统一声明,可省去在主调函数中的声明。46第四十六页,共六十九页,编辑于2023年,星期五如:

charletter(char,char);/*这三行处于所有函数之前,

floatf1(float,float);且在函数外部.*/

inti2(float,float);

main(){…}/*main内不必说明所调用函数类型*/

charletter(charc1,charc2)/*定义letter()函数*/{...}

floatf1(floatx,floaty)/*定义f1()函数*/{...}

inti2(floatj,floatk)/*定义i2()函数*/{...}47第四十七页,共六十九页,编辑于2023年,星期五#include<stdio.h>intfun(intn){ ints=1,i; if(n==0) s=1; else for(i=1;i<=n;i++) s=s*i; returns;}intmain(){ inta,b; scanf("%d",&a); b=fun(a); printf("%d的阶乘为%d\n",a,b); return0;}例10.8从键盘输入一个整数(0-16),求此数的阶乘。Ch10_10_8.c48第四十八页,共六十九页,编辑于2023年,星期五例10.10

输入二个整数,进行函数调用,问能否实现实参a,b的交换。#include<stdio.h>intswap(int*p3,int*p4){intm;m=*p3;*p3=*p4;*p4=m;return0;}intmain(){inta,b;int*p1,*p2;printf("Pleaseinputa,b:");scanf("%d,%d",&a,&b);p1=&a;p2=&b;

swap(p1,p2);printf("a=%d,b=%d\n",a,b);return0;}

8P1

a运行:8,3(回车)输出:3,83P2

8P33P4Ch10_10_10.c指针为参数49第四十九页,共六十九页,编辑于2023年,星期五10.5函数的应用例10.11

在main函数中定义了一个整型数组并初始化,通过调用自定义函数sum把数组中-1前的所有元素值相加.#include<stdio.h>intsum(intb[]){ints=0,i=0;while(b[i]!=-1)s+=b[i++];returns;}intmain(){staticinta[]={1,2,3,4,5,6,7,8,9,-1,6};printf("Total=%d\n",sum(a));return0;}Ch10_10_11.c数组名作为函数的参数进行调用.50第五十页,共六十九页,编辑于2023年,星期五例10.14输入一行英文字符,统计其中有多少单词,单词之间以空格为分隔#include<stdio.h>intmain(){ charstring[81]; intnum; gets(string); num=numword(string); printf("Thereare%dwords\n",num); return0;}51第五十一页,共六十九页,编辑于2023年,星期五intnumword(char*str){ inti,num=0,word=0; charch; for(i=0;(ch=str[i])!='\0';i++)

if(ch==‘')word=0; elseif(word==0) {word=1; num++;} returnnum;}

num统计单词个数,word用来判断是否单词的标志.(1).当前字符为空格:

未出现新单词,word=0,

num不累加。(2).当前字符为非空格(分两种情况):

a.前一字符为空格(word=0),新词出

现,word=1,

num加1.

b.前一字符为非空格(word=1),未出

现新单词,num不加1.Youarestudents.52第五十二页,共六十九页,编辑于2023年,星期五

(1).函数的嵌套调用:

C语言中的函数是平行的,不允许嵌套定义。

所有函数的作用域都处于同一嵌套深度,即不允许在函数体中又定义另一个函数.但允许嵌套调用函数,即在调用一个函数的过程中,又调用另一个函数。10.6函数的嵌套与递归调用53第五十三页,共六十九页,编辑于2023年,星期五

main()a()函数b()函数{{{

调用函数a()调用函数b()….

结束returnreturn}}}如:54第五十四页,共六十九页,编辑于2023年,星期五例求三角形面积area2=s(s-a)(s-b)(s-c)s=(a+b+c)/2smainarea#include<stdio.h>#include<math.h>voidmain(){floata,b,c;floatarea(floata,floatb,floatc);floats(floata,floatb,floatc);scanf("%f%f%f",&a,&b,&c);printf("%f\n",area(a,b,c));}floatarea(floata,floatb,floatc){floatss;ss=s(a,b,c);returnsqrt(ss*(ss-a)*(ss-b)*(ss-c));}

floats(floata,floatb,floatc){return(a+b+c)/2;}对被调函数的声明55第五十五页,共六十九页,编辑于2023年,星期五开始调用(2).函数的递归调用(recursive)调用一个函数的过程中,出现了直接或间接地调用

该函数本身,称之为函数的递归调用。

C语言的特点之一是允许函数的递归调用。递归调用可以简明,高效的解决问题(问题的一方面)。a.直接递归调用;

intf(intx){inty,z;….z=f(y);return(z*z);}56第五十六页,共六十九页,编辑于2023年,星期五b.间接递归调用:

intf1(intx){inty,z;z=f2(y);return(z*z);}

intf2(inta){intc;c=f1(a);return(3+c);}

两种调用都是无休至的自我调用。可以用if语句来控制这种情况.

57第五十七页,共六十九页,编辑于2023年,星期五

通常用求一个数的阶乘为例来说明递归函数。

1(n=0,1)n!=

n*(n-1)!(n>1)例:10.1858第五十八页,共六十九页,编辑于2023年,星期五floatfac(intn){floatf;if(n<0){printf(“n<0,dataerror!”);exit(0);

}elseif(n==0||n==1)f=1;elsef=fac(n-1)*n;return(f);}intmain(){intn;floaty;printf(“inputaintegernumber:”);scanf(“%d”,&n);y=fac(n);printf(“%d!=%f”,n,y);}

n

n-1

下面设n=3,进行调用:ch10_10_18.c59第五十九页,共六十九页,编辑于2023年,星期五fac(intn){…elseif(n==1||n==0)f=1;elsef=fac(n-1)*3;return(f);}main()

{….(n==3

)

y=fac(n);

…..}

fac(intn)

{…..(n==2)elseif(n==1||n==0)f=1;elsef=fac(n-1)*2;return(f);}fac(intn)

{…..(n==1)elseif(n==1||n==0)f=1;

elsef=fac(n-1)*n;return(f);}

11*260第六十页,共六十九页,编辑于2023年,星期五

调用fac函数计算3的阶乘时的情况:

f=fac(2)*3

1.这时函数将调用自己,因此仍然要理解为调用一个单

独的函数。

2.每一次当C语言中的任意函数被调用(不管是否递归),函数都将获得自己的一套局部变量和形式参数。

3.函数递归时,必须有个if语句,迫使函数返回,进而结

束递归.61第六十一页,共六十九页,编辑于2023年,星期五1.数组名作函数参数:

如:main(){in

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论