C语言程序设计(慕课版)函数_第1页
C语言程序设计(慕课版)函数_第2页
C语言程序设计(慕课版)函数_第3页
C语言程序设计(慕课版)函数_第4页
C语言程序设计(慕课版)函数_第5页
已阅读5页,还剩70页未读 继续免费阅读

下载本文档

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

文档简介

函数****************************************************#include<stdio.h>main(){inti;for(i=0;i<4;i++)printf("*************\n");}******************#include<stdio.h>main(){inti;for(i=0;i<3;i++)printf("******\n");}******************!!!!!!~~~~******************printf(“!!!!!!\n");

for(i=0;i<3;i++)printf("******\n");printf(“~~~~\n");

for(i=0;i<3;i++)printf("******\n");}******************#include<stdio.h>main(){inti;for(i=0;i<3;i++)printf("******\n");}******************!!!!!!~~~~******************printf(“!!!!!!\n");

for(i=0;i<3;i++)printf("******\n");printf(“~~~~\n");

for(i=0;i<3;i++)printf("******\n");}voidprintstar(){for(i=0;i<3;i++)printf("******\n");}inti;printstar();printstar();printstar();******************#include<stdio.h>main(){printf(“!!!!!!\n");printf(“~~~~\n");}!!!!!!******************************~~~~************

voidprintstar(){inti;for(i=0;i<n;i++)printf("******\n");}printstar(3);printstar(5);printstar(2);(intn)************!!!!!!****************************************~~~~****

考虑该如何实现呢?各模块相对独立、功能单一、程序结构清晰,可读性好;每个模块简单,所以可靠性高;减少重复编码的工作量,缩短开发周期;易于维护和功能扩充。使用函数的优点:是面向过程程序设计语言的核心。可由一个或多个源程序文件组成;每个源程序文件又由若干函数构成;但整个程序有且仅有一个主函数;程序运行时从main函数开始执行,main函数可调用其它函数,最终一律返回到main函数结束运行。函数之间是独立的,是非从属关系的,即不可嵌套定义的,但可以互相调用.

C程序特点:函数的分类按照函数定义的角度分为:1.标准库函数:2.用户自定义的函数是由系统定义地,也不必在程序中进行类型说明,要调用某个库函数,则要用预处理命令#include将该函数所在的头文件包含到程序中。使用库函数应注意:1)函数功能2)函数参数的数目和顺序,及各参数意义和类型3)函数返回值意义和类型4)需要使用的包含文件按照函数的参数传递形式分为:无参函数有参函数按照函数的返回值类型分为:有返回值无返回值按照函数的使用范围分为:内部函数外部函数函数的定义------无参函数的定义类型名函数名(){声明部分执行部分}说明:类型名为函数返回值类型,如果定义时未指定,系统默认为int型;无返回值的函数的类型名应为void。函数名须是合法标识符,不能与其他函数或变量重名类型标识符函数名(形参表列){声明部分执行部分}形参表列必须声明形参的类型函数的定义------有参函数的定义形参类型说明表,一般格式为:数据类型1形参1,…,数据类型n形参n#include<stdio.h>floataverage(floatx,floaty,floatz)

{floataver;aver=(x+y+z)/3;return(aver);}main(){floata,b,c,ave;a=6.5;b=4.2;c=25.3;

ave=average(a,b,c);

printf(“average=%f”,ave);}void函数名(){}函数体可以没有,表示占个位置,实现功能以后补写。函数的定义------空函数的定义函数参数和函数的值函数参数分为:实际参数和形式参数在函数定义的函数首部,函数名后的括号中说明的变量,简称形参。形参的个数可以有多个,多个形参之间用逗号隔开。形式参数:实际参数:函数被调用时,在调用处给出对应的参数,简称实参,实参往往是具有明确值的常量、变量或表达式等。#include<stdio.h>floataverage(floatx,floaty,floatz)

{floataver;aver=(x+y+z)/3;return(aver);}main(){floata,b,c,ave;a=6.5;b=4.2;c=25.3;

ave=average(a,b,c);

printf(“average=%f”,ave);}形式参数(形参)实际参数(实参)说明:1.形参在未出现函数调用时,他们并不占内存,只有发生函数调用时才会被分配空间,而且在该函数结束后,它所占的所有内存也被释放;2.实参必须是具有确定值的常量,变量或表达式;3.形参必须在定义时就声明其类型;6.实参与形参的类型应相同或赋值兼容;7.C语言规定,实参与形参之间必须是单向的值传递。4.实参的个数和形参的个数应该相等;5.实参与形参在顺序上应该一一对应;例如:编一程序,将主函数中的两个变量的值传递给swap函数中的两个形参,交换两个形参的值。#include<stdio.h>voidswap(intx,inty){intz;z=x;x=y;y=z; printf("\nx=%d,y=%d",x,y);}main(){inta=10,b=20;swap(a,b);printf("\na=%d,b=%d\n",a,b);}形式参数(形参)实际参数(实参)单向值传递例如:编一程序,将主函数中的两个变量的值传递给swap函数中的两个形参,交换两个形参的值。#include<stdio.h>voidswap(intx,inty){intz;z=x;x=y;y=z; printf("\nx=%d,y=%d",x,y);}main(){inta=10,b=20;swap(a,b);printf("\na=%d,b=%d\n",a,b);}程序输出结果:x=20,y=10a=10,b=20mainswap20b10az10y20x101020交换失败函数的值即函数的返回值,是通过函数中的return语句获得的.return语句的一般形式:return(表达式);return表达式;执行过程:执行return语句后,如果该表达式的类型与函数首部中定义的函数类型一致,则直接将结果返回主调函数;否则,系统自动将结果的类型转换成定义的函数类型。通过return语句只能返回一个数值。函数内可有多条返回语句,但每条返回语句的返回值只有一个。当函数不需指明返回值时,可以写成:

return;当函数中无返回语句时,表示最后一条语句执行完后遇

}

自动返回。说明:函数的调用函数调用是使函数进行一次实际的执行。格式:函数名(实际参数表)说明实参在调用时必须有确定的值,可以是常量、变量和表达式。函数的实参和形参应在个数、类型和顺序上一一对应,否则会发生类型不匹配的错误。对于无参函数,调用时实参表列为空,但()不能省 。按函数在程序中出现的位置有以下3种函数调用方式:函数调用的方式

1.函数语句调用把函数调用作为一个语句不要求函数带回明确的返回值只完成一定的操作#include<stdio.h>voidprintstar(){printf("*************\n");}voidprint_message(){printf("Howareyou!\n");}main(){printstar();print_message();printstar();}2.函数表达式调用以表达式形式出现在程序中要求函数必须带回确定的返回值c=2*max(a,b);3.函数参数调用作为参数出现在程序中要求函数必须带回确定的返回值m=max(a,max(b,c));函数的调用过程1.根据函数名找到被调函数,若没找到,系统将报告出错信息;若找到,为形参开辟存储空间;2.计算实参的值。将实参的值传递给形参;3.保护主调函数的现场,中断主调函数,转到被调函数的函数体中开始执行;4.遇到return语句或函数结束的花括号时,返回主调函数;5.释放形参和调用函数中临时变量的内存空间;6.恢复现场从主调函数的中断处继续执行。函数开始调用函数结束调用#include<stdio.h>floataverage(floatx,floaty,floatz)

{floataver;aver=(x+y+z)/3;return(aver);}main(){floata,b,c,ave;a=6.5;b=4.2;c=25.3;

ave=average(a,b,c);

printf(“average=%f”,ave);}mainaverage12.0ave25.3c4.2b6.5aaver12.0z25.3y4.2x6.5函数之间的位置关系在一个程序中有多个函数,那么,各函数之间的前后位置关系规定如下:(1)被调函数在前面,主调函数在后面。

即先定义后调用。(2)主调函数在前面,被调函数在后面。这时,必须在调用的语句之前,对被调用的函数进行原型声明(说明),可在主调函数的说明部分,也可在程序的开始处的说明部分进行。常用的函数原型声明方法是:

用函数定义中的函数首部,再加上一个分号。也可以省略函数首部中的形参名,但必须保留形参的类型。

intadd(intx,inty){return(x+y);}main(){inta=10,b=24,sum;printf("inputa,b:");sum=add(a,b);printf(”sum=%d\n",sum);}main(){inta=10,b=24,sum;

printf("inputa,b:");sum=add(a,b);printf(”sum=%d\n",sum);}intadd(intx,inty){return(x+y);}intadd(intx,inty);intadd(intx,inty);指针变量作为函数的参数(引用传递)以指针类型为函数的参数,作用是将变量的地址传入函数。intx,y;int*pt1;*pt2;x=8;y=6;pt1=&x;pt2=&y;if(x>y)swap(pt1,pt2);printf("x=%d,y=%d\n",x,y);swap(int*p1,int*p2)p=*p1;*p1=*p2;*p2=p;{intp;p8pt1pt2xy

{

}

main(){

}&x&yp1p2&x&y8668运行结果:

x=6,y=8intx,y;int*pt1;*pt2;x=8;y=6;pt1=&x;pt2=&y;if(x>y)swap(pt1,pt2);swap(int*p1,int*p2)p=*p1;*p1=*p2;*p2=p;{intp;printf("x=%d,y=%d\n",x,y);如:main(

)f(inta[],intn){intarray[10];{......f(array,10)}...}数组作为函数参数

数组元素作函数实参

一维数组名作函数参数

多维数组名作函数参数数组名作函数参数——地址传递在主调函数与被调函数分别定义数组,且类型应一致。形参数组大小(多维数组第一维)可不指定,但[]不能省。编译程序并不为形参数组分配空间。数组名表示数组在内存中的起始地址。例:计算数组中相邻两元素之间的差值。数组元素作函数实参——值传递intdif(intx,inty){returnx-y;}main(){inti,a[4]={0,1,2,3};for(i=0;i<3;i++){printf("thediffbetween%dand%dis",i,i+1);

printf("%d\n",dif(a[i],a[i+1])

);}}thediffbetween0and1is-1thediffbetween1and2is-1thediffbetween2and3is-1例:从键盘输入8学生的成绩,编写函数使用简

单选择排序将成绩由高到低排序,并输出成绩。#defineN10voidSelectSort(inta[],intn);voidInputArray(inta[],intn);voidOutputArray(inta[],intn);main(){ intn=8,score[N];

InputArray(score,n); SelectSort(score,n); OutputArray(score,n);}voidInputArray(inta[],intn){ inti; printf("Input%dscores:\n",n); for(i=0;i<n;i++) scanf("%d",&a[i]);}voidOutputArray(inta[],intn){ inti; printf("Thesortedscores:\n"); for(i=0;i<n;i++) printf("%4d",a[i]);}voidSelectSort(inta[],intn){ inti,j,k,t; for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) { if(a[k]<a[j]) k=j; } if(k!=i) { t=a[i];a[i]=a[k]; a[k]=t;} }}用数组名作函数参数,应该在主调函数和被调函数分别定义数组,不能只在一方定义;实参数组与形参数组类型应一致;形参数组也可以不指定大小,在定义数组时在数组名后面跟一个[];为了在被调用函数中处理数组元素的需要,将数组个数作为一个参数;用数组名作函数实参时,不是把数组的值传递给形参,而是把实参数组的起始地址传递给形参数组,这样两个数组就共占同一段内存单元。说明:例:求二维数组中所有元素的最大值。intgetmax(intb[3][4])/*或intgetmax(intb[][4])*/{inti,j,max=b[0][0];for(i=0;i<3;i++);{for(j=0;j<4;j++)if(max<b[i][j])max=b[i][j];}returnmax;}main(){inta[3][4],i,j;printf(“\nEnter6integers:");for(i=0;i<3;i++)for(j=0;j<4;j++) scanf("%d",&a[i][j]);printf(“\nMax=%d”,getmax(a));}由于数组名代表首地址,能接收并存放地址值的只能是指针变量。故编译系统将形参数组名作为指针变量来处理。例中函数首部f(inta[],intn)可写成

f(int*a,intn)两种完全等价。归纳起来,如果有一个数组,想在被调用的函数中改变其元素的值,实参与形参的对应关系有以下四种:(1).实参和形参都用数组名。(2).实参用数组名,形参用指针变量。(3).实参用指针变量,形参用数组名。(4).实参和形参都用指针变量。实质都是地址值的传递通过调用函数,将整型数组的所有元素加10。参数传递用四种方法实现。voidadd(intb[],intn){inti;for(i=0;i<n;i++)b[i]+=10;}main(){inti,a[10]={1,2,3,4,5,6,7,8,9,10};add(a,10);for(i=0;i<10;i++)printf("%4d",a[i]);}voidadd(int*p,intn){int*pend=p+n;for(;p<pend;p++)*p+=10;}main(){inti,a[10]={1,2,3,4,5,6,7,8,9,10};add(a,10);for(i=0;i<10;i++)printf("%4d",a[i]);}voidadd(intb[],intn){inti;for(i=0;i<n;i++)b[i]+=10;}main(){inti,a[10]={1,2,3,4,5,6,7,8,9,10};int*q=a;add(q,10);for(i=0;i<10;i++)printf("%4d",a[i]);}voidadd(int*p,intn){int*pend=p+n;for(;p<pend;p++)*p+=10;}main(){inti,a[10]={1,2,3,4,5,6,7,8,9,10};int*q=a;add(q,10);for(i=0;i<10;i++)printf("%4d",a[i]);}用字符数组或指针做函数参数传递字符串将字符串从一个函数传递到另一个函数,可以用地址传递的方法,即用字符数组名或用字符指针变量作参数。在被调用的函数中可以改变字符串中的内容,在主调函数中可以得到改变了的字符串。字符串复制函数主要功能的实现。voidstrcpy(chars1[],chars2[]){inti=0;while(s2[i]!='\0'){s1[i]=s2[i];i++;}s2[i]='\0';}main(){chara[20]="Iamateacher.";charb[]="youareasrudent.";printf("stringa=%s\nstringb=%s\n",a,b);strcpy(a,b);printf("\nstringa=%s\nstringb=%s\n",a,b);}(2)形参用字符指针变量。程序如下:voidstrcpy(char*s1,char*s2){for(;*s2!='\0';s2++,s1++)*s1=*s2;*s1='\0';}main(){chara[20]="Iamateacher.";char*b="youareasrudent.";printf("stringa=%s\nstringb=%s\n",a,b);strcpy(a,b);printf("\nstringa=%s\nstringb=%s\n",a,b);}{while((*s1=*s2)!='\0'){s1++;s2++;}*s1='\0';}{while(*s2!='\0')*s1++=*s2++;*s1='\0';}{while(*s2)*s1++=*s2++;*s1='\0';}{

while((*s1++=*s2++)!='\0')}{

while(*s1++=*s2++)}函数的嵌套调用在C语言中,函数调用允许嵌套,所谓函数的嵌套调用是指在主调函数调用被调函数的过程中,被调函数又调用了另一被调函数。

a函数

main()调用函数a

调用函数b

b函数

结束

例:求三个数中最大数和最小数的差值。intdif(intx,inty,intz){return

max(x,y,z)-min(x,y,z);

}main(){inta,b,c,d;scanf("%d%d%d",&a,&b,&c);

d=dif(a,b,c);printf("Max-Min=%d\n",d);}intmax(intx,inty,intz){intr;r=x>y?x:y;return(r>z?r:z);}intmin(intx,inty,intz){intr;r=x<y?x:y;return(r<z?r:z);}例:求圆环的面积。#include<math.h>#definePI3.1415926floatarea_ring(floatx,floaty);floatarea(floatr);main(){floatr,r1;printf(“inputtowfigure:\n”);scanf(“%f%f”,&r,&r1);printf(“area_ringis%f”,area_ring(r,r1));}floatarea_ring(floatx,floaty){floatc;c=fabs(area(x)-area(y));return(c);}floatarea(floatr){return(PI*r*r);}

函数的递归调用

在函数的执行过程中又直接或间接调用该函数本身

直接递归调用在函数中直接调用函数本身间接递归调用在函数中调用其它函数,其它函数又调用原函数intf1(intx){inty,z;……

z=f2(y);…….return(2*z);}intf2(intt){inta,c;……

c=f1(a);…….return(3+c);}intf(intx){inty,z;……

z=f(y);…….return(2*z);}C编译系统对递归函数的自调用次数没有限制。f()调f调f2调f1f1()f2()例:计算n!。分析:求解n的阶乘实际上有两种方法,一种是连乘法,它基于阶乘定义公式:

n!=1*2*3*…*n实现方法是用循环完成。另一种方法基于阶乘递归定义公式:n!=1(n=0)n*(n-1)!(n>1)用函数的直接递归调用实现main(){intn;longy;printf("\ninputaintegernumber:\n");scanf("%d",&n);

if(n<0)printf("dataerror\n");

else{y=fac(n);

printf("%d!=%ld",n,y);}}longfac(intn){longf;

if(n==0)f=1;elsef=n*fac(n-1);

return(f);}main()n=1n=2n=3n=4f=24f=6f=2f=1f=4*fac(3)f=3*fac(2)f=2*fac(1)f=1fac(4)递归算法的两要素:问题分解:将问题分解为相同性质且规模更小的问题。递归结束条件:必须给出递归的结束条件,否则递归会无限循环下去。例:Hanoi塔问题。一块板上有三根杆,a,b,c。a杆上套有64个圆盘,大的在下,小的在上。要把这64个圆盘从a杆移动c杆上,每次只能移动一个圆盘,b杆可以暂时存放。但在任何时候,任何杆上的圆盘都必须保持大盘在下,小盘在上。将A塔上的红、黄两盘移动到B上蓝盘放到C上将红、黄两盘从B移动到C盘上。(完成)A问题分析:n=1时,直接将其从A--->C

;n>1时,只要先将前n-1个借助C从A--->B,那么可以把第n个直接从A--->C;将剩下的n-1个借助A从B--->C,问题性质相同,因此适合采用递归过程!递归结束条件问题分解BC设将n个盘从a借助b移到c杆的算法为move(n,a,b,c),则:移动盘子算法如下:①把a上面的n-1个盘借助c移到b,记做

move(n-1,a,c,b);②把最下面的1个盘从a直接移到c;③把b上的n-1个盘借助a移到c,记做

move(n-1,b,a,c);显然这是一个递归算法,按此算法编程如下:main(){intm;printf("\nInputnumber:");scanf("%d",&n);printf("thesteptomoving%2ddiskes:\n",m);

move(n,'a','b','c');}voidmove(intn,intx,inty,intz){if(n==1)printf("%c->%c\n",x,z);

else{move(n-1,x,z,y);printf("%c--->%c\n",x,z);move(n-1,y,x,z);}}…...move(3,'a','b','c');…...move(n,x,y,z);3,'a','b','c'n!=1move(n-1,x,z,y);printf("->",x,z);move(n-1,y,x,z);move(n,x,y,z);2,'a',‘c',‘b'n!=1move(n-1,x,z,y);printf("->",x,z);move(n-1,y,x,z);move(n,x,y,z);1,'a',‘b',‘c'2,'a',‘c',‘b'1,'a',‘b',‘c'n=1printf("->",x,z);1.a->c2.a->bmove(n,x,y,z);1,‘c',‘a',‘b'1,‘c',‘a',‘b'n=1printf("->",x,z);3.c->b4.a->cmove(n,x,y,z);2,‘b',‘a',‘c'2,‘b',‘a',‘c'n!=1move(n-1,x,z,y);printf("->",x,z);move(n-1,y,x,z);move(n,x,y,z);1,‘b',‘c',‘a'1,‘b',‘c',‘a'n=1printf("->",x,z);5.b->a6.b->cmove(n,x,y,z);1,‘a',‘b',‘c'1,‘a',‘b',‘c'n=1printf("->",x,z);7.a->c指针与函数返回值为指针类型的函数指针函数的定义格式如下:类型名*函数名(参数表)例如:int*f(intx)指向函数的指针指针变量的另一的重要用途是,它可以指向一个函数(存储函数入口地址),通过它可以调用指向的函数,改变它的值就可以动态的调用不同的函数。指向函数的指针和函数参数指向函数的指针的定义一般形式:数据类型(*指针变量名)()例如:int(*p)();说明:1.在给函数指针变量赋值时,只需给出函数名;2.用函数指针调用函数时,只需用*p代替函数名即可.例:#include<stdio.h>intf(intx){return3*x*x+5*x-7;}voidmain(){int(*p)();

inta;

p=f;printf("Inputx=");scanf("%d",&a);printf("(*p)(a)=%d\n",(*p)(a));printf("p(2a)=%d\n",p(2*a));}

局部变量和全局变量根据变量作用域不同,变量分为局部变量和全局变量。所谓变量的作用域,

是指该变量定义和使用的范围。局部变量,

是指作用域在某程序块(函数)中的变量。说明:局部变量的使用

温馨提示

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

最新文档

评论

0/150

提交评论