




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第十七讲函数2函数的定义函数说明和函数体函数的调用(递归)参数传递:实参和形参返回值变量的作用域:全局变量和局部变量函数示例分治思想本讲内容3C语言与函数C语言是一种函数式语言,它的一个函数实际上就是一个功能模块——C程序的基本组成是函数。一个C程序是由一个固定名称为main的主函数和若干个其他函数(可没有)组成。一个C程序必须有一个、也只能有一个主函数。主函数在程序中的位置可以任意,但程序执行时总是从主函数开始,在主函数内结束。C语言程序是通过函数调用来完成复杂功能。4函数的定义函数的定义语句如下:返回值类型
函数名([参数1类型
参数名1,参数2类型
参数名2,…]){
语句1;
//语句可能与参数有关
语句2;
//语句可能与参数有关
…… return返回值表达式;
//该表达式的值的类型必需和返回值类型一致
//如果返回值类型为void,则不需return语句,或者返回值表达式为空}参数:函数在完成其功能时需要由函数调用者传递给函数的数据。返回值:函数在完成其功能后得到的结果。5函数定义的例子下面是一个函数定义的例子:两个数相加
intadd(intx,inty){intz;z=x+y;
return
z;}voidadd2num(){ intx,y,z; scanf(“%d%d”,&x,&y);z=x+y; printf(“%d”,z);
return;//或者不要此语句}6函数的调用
在C语言中,函数是语句的一种组织方式。把完成某一特定功能的语句按照一定的规则组合在一起,起一个名字,就构成了函数。在一段程序中,一个函数可以当作一条语句来运行,这称为函数的调用(函数调用语句)。一个函数在实际被调用时,它所包含的语句才会执行,并且,它的参数的具体取值也是在调用时给定的。在函数执行后,它的执行结果(如果有的话)可以通过返回值返回给调用它的程序。7函数的调用intadd(intx,inty){intz;z=x+y; returnz;}intminus(intx,inty){ returnx-y;}8函数的调用voidmain(){ intn1,n2; scanf(“%d%d”,&n1,&n2); n1=add(n1,n2);//函数调用语句
n2=minus(n1,n2);//函数调用语句
if(n1>0&&n2>0){ printf(“%d\n”,add(n1,n2));//包含函数调用的语句
}else{printf(“%d\n”,minus(n1,n2));//包含函数调用的语句
}}9函数调用的过程intmax(intx,inty){ if(x>=y)returnx; elsereturny;}voidmain(){ intx=0,y=0,z=0; x=20; y=45; z=max(x,y);
……}10函数调用的过程11函数调用的过程12函数调用的过程13函数调用的过程14函数调用的过程15函数调用的过程16函数的调用一个函数在调用前必须是已经定义过的(“先定义,后使用”原则)。函数体函数说明17intmultiple(intx,inty);//函数说明declarationvoidmain(){ inta=0,b=0,c; scanf(“%d%d”,&a,&b);c=multiple(a,b);//函数调用
printf(“%d\n”,c);}//main()的返回值类型为void,因此没有return语句intmultiple(intx,inty) //函数体,在函数调用之后给出{intz;z=x*y; returnz;}函数说明和函数体18函数说明和函数体另一种形式:不需要函数说明intmultiple(intx,inty)//函数体,在函数调用之前给出{intz;z=x*y; returnz;}voidmain(){ inta=0,b=0,c; scanf(“%d%d”,&a,&b);c=multiple(a,b);//函数调用
printf(“%d\n”,c);}19函数的递归调用一个关于递归的故事一个没有去过北京的人问:天安门是什么样子?去过北京的人答道:天安门有个城楼,城楼上有个国徽,国徽里有个天安门,天安门有个城楼,城楼上有个国徽,国徽里有个天安门,……20函数的递归调用intfactorial(intn){if(n<=0)return–1;if(n==1)return1;returnn*factorial(n-1);//递归调用}
递归是常用的编程技术,其基本思想是“自己调用自己”。数学上最常见、最简单的递归问题就是自然数的阶乘。
n=1n!=1;n>1n!=n*(n-1)!;21适合用递归方法求解的问题满足两个条件出口条件:在某一条件下,递归不再继续递推公式–必需向出口条件推进:后续的情况可由前面的状态推出阶乘:n!=1,n=1;n!=n*(n-1)!,n>1Fibonacci数列:F1=F2=1;
Fn=Fn-1+Fn-2(n>=3)解决问题的思想将问题逐步向更小规模的同类问题推进函数的递归调用22其他递归问题河内塔(HanoiTower)问题:这是一个流传很久的游戏。1.有三根杆子A,B,C。A杆上有n只碟子2.每次移动一块碟子,小的只能叠在大的上面3.把所有碟子从A杆经C杆全部移到B杆上.递归求解:1.若只有一只碟子,直接将它从A杆移到B杆;2.把n-1只碟子从A杆经B杆移动到C杆,将A杆上第n只碟子移到B杆;然后再将n-1只碟子从C杆经A杆移到B杆。函数的递归调用23其他递归问题8皇后问题:把8个皇后放在8x8的棋盘上,使得任何一个都不将其他7个的军。骑士巡游问题:给出一个nxn的棋盘,一位骑士按国际象棋的规则移动——放在第(0,0)格里,找出一种可以走遍整个棋盘的方案(如果存在的话)。即做n2-1次移动,使得棋盘上每个格子都恰好只被访问一次。函数的递归调用24函数参数:实参和形参在调用函数时,向函数传递的参数—实参:可以是数值。也可以是内存地址(指针)。
函数内部进行运算的参数—形参实参形参:参数类型必须一一对应,采用值传递25指针形参voids*x,int*y){ inttmp=0; tmp=*x; *x=*y; *y=tmp;}26指针实参voidmain(){ inta=0,b=0; a=20; b=45; if(a<b)s,&b);
……}27程序运行过程28程序运行过程29程序运行过程30程序运行过程31程序运行过程32程序运行过程33程序运行过程34voidsx,inty){ inttmp=0; tmp=x; x=y; y=tmp;}voidmain(){ inta=0,b=0; a=20; b=45; if(a<b)swap(a,b);
……}此时会有什么效果?35if(a<b)s);参数
xy变量tmp代码段swaptmp=x; x=y;
y=tmp;2045045202036再看scanf()和printf()函数scanf(char*control,……)每一个希望从键盘中输入的变量,都需要使用指针传递参数。printf(char*control,……)当输出变量是字符串时,也需要使用指针传递参数。39函数的返回值
函数执行完以后可以向调用它的程序返回一个值,表明函数运行的状况。很多函数的功能就是对参数进行某种运算,之后通过函数返回值给出运算结果。函数的返回值可以有不同的类型,返回值类型在函数定义时说明。函数的返回值是通过return语句来实现的,一旦一个函数执行了return语句,则表明函数任务已经完成了,函数到此结束了。在main()函数中执行了return语句,表明什么?40函数的返回值intmin(intx,inty);
//返回值类型为int,有两个整型参数,函数名为mindoublecalculate(inta,doubleb);
//返回值类型为double,有一个整型参数,一个双精度浮点型参数//函数名为calculatecharjudge();
//返回值类型为char,没有参数,函数名为judgevoids*x,int*y);
//返回值类型为void,表示不返回任何值,有2个整型指针参数//函数名为swap41intadd(intx,inty){intz;z=x+y; returnz;}intminus(intx,inty){ returnx-y;}函数的返回值voids*x,int*y){ inttmp=0; tmp=*x; *x=*y; *y=tmp;}42
问题:当需要从函数中返回多个数据时,该如何处理?函数的返回值使用指针形参!43变量的作用域:全局变量和局部变量
在程序中,每一个变量都有一个可以起作用的范围,这个范围就是变量的作用域。根据变量作用域的不同,变量可分为全局变量和局部变量。44全局变量:在函数之外定义的变量#include<stdio.h>inttotal;//全局变量inttryit(inta){if(a>100&&a<200&&a%2==0)returna;
total++;return0;}voidmain(){intn,j;
total=0;for(j=0;j<1000;j++){ scanf(“%d”,&n); printf(“%d\n”,tryit(n));}printf(“%d\n”,total);}全局变量的作用域:从变量定义开始,到源程序结束。45局部变量:在代码段之内定义的变量#include<stdio.h>intcalculate(inta){
intn=a;if(a<100&&a>=0)n=2*a;if(a>=200)n=a*a;returnn;}voidmain(){
intn,j,c;c=300;for(j=0;j<1000;j++){
intc; scanf(“%d”,&n); c=calculate(n); printf(“%d\n”,c);}}局部变量的作用域:从变量定义开始,到当前代码段结束。46变量的作用域参数pp的作用域:整个函数全局变量作用域:
从变量定义处开始,一直到整个源文件结束。
不同源文件之间:extern局部变量作用域:
从变量定义处开始,到第离它最近的左大括号所匹配的右大括号为止。47全局变量和局部变量当需要静态分配较大的内存空间时,需要使用全局变量。#include<stdio.h>voidmain(){inti,j,image[10000][10000];for(i=0;i<10000;i++){for(j=0;j<10000;j++){ scanf(“%d”,&image[i][j]);}}}#include<stdio.h>intimage[10000][10000];voidmain(){inti,j;for(i=0;i<10000;i++){for(j=0;j<10000;j++){ scanf(“%d”,&image[i][j]);}}}48函数示例:假币问题问题描述
赛利有12枚银币。其中有11枚真币和1枚假币。假币看起来和真币没有区别,但是重量不同。赛利不知道假币比真币轻还是重。于是他向朋友借了一架天平。赛利希望称三次就能找出假币并且确定假币是轻是重。例如:如果赛利用天平称两枚硬币,发现天平平衡,说明两枚都是真的。如果赛利用一枚真币与另一枚银币比较,发现它比真币轻或重,说明它是假币。经过精心安排每次的称量,赛利保证在称三次后一定能够确定假币。
任务
编写一个程序,根据三次称量的结果,确定哪一个是假币,并指出其轻重。
49输入输入有三行,每行表示一次称量的结果。赛利事先将银币标号为A-L。每次称量的结果用三个以空格隔开的字符串表示:天平左边放置的硬币
天平右边放置的硬币
平衡状态其中平衡状态用“up”,“down”或“even”表示,分别为右端高、右端低和平衡。天平左右的硬币数总是相等的。函数示例:假币问题50输出输出哪一个标号的银币是假币,并说明它比真币轻还是重。
函数示例:假币问题51输入样例ABCDEFGHevenABCIEFJKupABIJEFGHeven
输出样例K是假币,它比较轻。函数示例:假币问题52算法思路
依次假设A-L是假币并且轻,再依次假设A-L是假币并且重,检查每次假设是否与称得的结果矛盾,如果矛盾,则假设不成立,否则假设成立。53假币问题定义全局变量存储称量结果charleft[3][7],right[3][7],result[3][5];数组下标3和7代表什么,为什么?54假币问题总体构想——逐一试探法对于每一枚硬币isLight?Yes.输出,No.isHeavy?Yes.输出55假币问题:利用函数来解决问题#include<stdio.h>charleft[3][7],right[3][7],result[3][5];//全局变量,在各个函数中都可以使用voidmain(){scanf(“%s%s%s”,left[0],right[0],result[0]);scanf(“%s%s%s”,left[1],right[1],result[1]);scanf(“%s%s%s”,left[2],right[2],result[2]);for(charc=‘A’;c<=‘L’;c++){if(isLight(c)){printf("%c是假币,它比较轻。\n",c);break;}elseif(isHeavy(c)){printf(“%c是假币,它比较重。\n",c);break;}}}56intisLight(charx)//假设银币x是轻假币,看输入的条件是否满足{inti;for(i=0;i<3;i++)//判断3个条件是否矛盾
{switch(result[i][0]){case‘u’://右边轻,假币应该在右边
if(!inRight(i,x))return0;break;case‘e’://两边相等,假币应该不在称上
if(inRight(i,x)||inLeft(i,x))return0;break;case‘d’://右边重,假币应该在左边
if(!inLeft(i,x))return0;break;}}return1;}57intisHeavy(charx)//假设银币x是重假币,看输入的条件是否满足{inti;for(i=0;i<3;i++)//判断3个条件是否矛盾
{switch(result[i][0]){case‘u’://右边轻,假币应该在左边
if(!inLeft(i,x))return0;break;case‘e’://两边相等,假币应该不在称上面
if(inRight(i,x)||inLeft(i,x))return0;break;case‘d’://右边重,假币应该在右边
if(!inRight(i,x))return0;break;}}return1;}58intinLeft(inti,charx)//判断x
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 设计咨询类合同协议
- 起诉赡养协议书范本
- 订货单合同协议
- 赎回股权协议书范本
- 财务合同协议简约版模板
- 购买期房全款合同协议
- 解除采购合同协议范本
- 课程顾问岗位合同协议
- 购买建材包安装合同协议
- 《第03节 探究感应电流的方向》教学设计2
- 应急救援技能培训
- 2025年广东省深圳市中考一模联考英语试题(原卷版+解析版)
- 文书拟写与档案管理 3.1.任务1 组件 学习资料
- 2025年山东济南先行投资有限责任公司招聘笔试参考题库含答案解析
- 2025年全球及中国依西美坦片行业头部企业市场占有率及排名调研报告
- 某院护理人员对常用中医护理技术知信行现状研究【复制】
- 《西游记》讲解学习
- 江苏省苏州市(2024年-2025年小学六年级语文)部编版小升初真题(下学期)试卷及答案
- 部编版小学语文四年级下册教师教学用书
- DB36T 540-2017 汽车维修连锁经营服务规范
- 《海航集团案例》课件
评论
0/150
提交评论