《C++语言程序设计(4).ppt》由会员分享,可在线阅读,更多相关《C++语言程序设计(4).ppt(37页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、C+语言程序设计Lecture 41沈洋 南京航空航天大学第4章 函数o函数的概念o函数的调用过程o如何使用函数使程序具有更好的结构o局部变量与全局变量o递归函数o一些例子2沈洋 南京航空航天大学4.1 函数的概念o 函数的例子:ndouble myAVG=avg(1.0,4.0);o函数的作用:代码重用、使程序的结构更加清晰n一般来说,任何有实际应用价值的代码都由多个函数构成o函数可以有参数和返回值n在C+中,即使没有参数,括号仍然不能省略o函数的两种类型nC+标准库函数n自定义函数3沈洋 南京航空航天大学插曲:再论结构化o结构化程序设计方法的思想:自顶向下,逐自顶向下,逐步细化。基本结构,
2、组合而成。清晰第一,步细化。基本结构,组合而成。清晰第一,效率第二。书写规范,缩进格式。效率第二。书写规范,缩进格式。o一个简单的例子:求a,b,c三个数中的最大值4沈洋 南京航空航天大学举例o找出三个数中最大数输入三个数a,b,c找出a,b,c中最大数max输出最大数max找出a,b中最大数max找出max,c中最大数设max=aab?max=bmax c?max=c5沈洋 南京航空航天大学输出最大数max输入三个数a,b,cmax=aab?max=bmax c?max=c把它们组合起来,就得到完整解用函数可以更好地解决用函数可以更好地解决6沈洋 南京航空航天大学无参数函数类型 函数名()函
3、数体例:int getint()int c;cinc;return c;7沈洋 南京航空航天大学有参数函数类型 函数名(参数表)函数体 例:int max(int x,int y)int z;z=xy?x:y;return z;/返回值 类型函数名形参表函数体两者类型要求一致8沈洋 南京航空航天大学基本规则o调用一个函数前,必须完整地声明它的类型调用一个函数前,必须完整地声明它的类型信息信息o“类型”信息是什么?o对C+库函数而言,使用#include进行声明o对自定义函数而言,在使用前进行显式地声明n如何声明?n在程序代码的什么位置进行声明?9沈洋 南京航空航天大学4.2 函数调用过程 C+
4、程序执行从main()开始,调用其它函数后回到main()。在main中结束整个程序 int main()double a=1.2;double b=2.7;cout avg(a,b);return 0;double avg(double a,double b)double v=(a+b)/2;return v;123410沈洋 南京航空航天大学4.3 函数的使用o在程序开头,以原型形式声明声明函数o在程序的某个地方定义定义函数o在程序任何其他地方调用调用函数,函数可以不限次地调用o必须既声明又定义吗?不能将其合并进行吗?n可以,但这不是最好的做法11沈洋 南京航空航天大学4.3.1 声明函数
5、o声明函数的语法结构ntype function_name(argument_list);ntype:一种已知的数据类型nfunction_name:函数名nargument_list:参数列表(多个参数用逗号隔开)ndouble avg(double x,double y);n注意:函数声明是一个语句,因此在末尾有分号”;”ndouble avg(double x,y);正确吗?ndouble avg(double,double);正确吗?12沈洋 南京航空航天大学4.3.2 定义函数o形式上与声明类似,但需将;改为 o含义上定义是描述了函数所要实现的功能n插曲:“声明”的含义是什么?odo
6、uble avg(double x,double y)return(x+y)/2;o如果函数类型为void,则可以一个不带参数的return语句进行返回,也可以不写return语句n不写return会怎样呢?n那么为什么还要写return?13沈洋 南京航空航天大学4.3.3 调用函数o声明、定义完成的函数可被多次调用o函数调用相当于一个表达式(当类型不是void时),可以在任何表达式能够出现的场合出现n合理的例子:z=x+y+avg(a,b)+25.3;n极端的例子:无谓的调用 avg(a,b);o在使用函数进行赋值时应注意类型的一致需要时进行强制类型转换o在编译时会进行参数类型检查14沈洋
7、 南京航空航天大学4.4 示例:triangle函数o功能:计算1+2+no函数声明:nint triangle(int num);o函数定义:nint triangle(int n)int i;int sum=0;for(i=1;i=n;i+)sum=sum+i;return sum;可以不同15沈洋 南京航空航天大学调用情况o一定要triangle(n)吗?能否将main中的变量声明为m?o直接调用triangle(4)可以吗?o形式参数和实际参数int main()int n1;cout n1;cout“Function returned”triangle(n1);return 0;16
8、沈洋 南京航空航天大学练习o写一个阶乘函数factorialn貌似简单的事情往往也有值得注意之处o写一个print_out函数,用它打印1N的所有整数。17沈洋 南京航空航天大学4.5 质数函数o把检验一个数是否为质数的功能抽取到一个函数中o在主函数main中无限地循环调用该函数,直到用户发出停止测试的指令o程序代码见P68o练习:写一个程序来查找大于10亿的第一个质数18沈洋 南京航空航天大学4.6 局部变量和全局变量o局部变量:n在函数内部定义的变量称为局部变量,它只在本函数内有效。也就是说只有在本函数内才能使用它们,在此函数外是不能使用这些变量的。n不同的函数中的局部变量可以同名,但它们
9、之间没有任何关系。n形式参数也是局部变量n在一个函数内部,可以在复合语句中定义变量,这些变量只在本复合语句中有效19沈洋 南京航空航天大学全局变量o在函数之外定义的变量称为全局变量。全局变量可以为本文件中其它函数所共用。它的有效范围为从定义变量的位置开始到本源文件结束。o在某全局变量声明之前的函数不能访问该全局变量o若在同一源文件中,全局变量与局部同名,则在局部变量的作用范围内,全局变量被“屏蔽”,即它不起作用20沈洋 南京航空航天大学int func();int n=5;/n为全局变量void main()int x;coutn;x=func();coutx“n;int func()int
10、a=4;n=a;return n;若改为int func();void main()int x,n=5;coutn;x=func();coutx“n;int func()int a=4;n=a;/错,变量n没定义 return n;21沈洋 南京航空航天大学4.7 递归函数o在main函数中可以调用其他自定义函数。但是,一个函数能调用它自己吗?o是的,在函数体内直接或间接地调用函数本身的函数被称为递归函数otriangle的递归表示int triangle(int n)if(n=1)return 1;else return n+triangle(n-1);22沈洋 南京航空航天大学另一个简单的
11、例子:factorialo1!=1o2!=1*2=1!*2o3!=1*2*3=2!*3o4!=1*2*3*4=3!*4o.on!=1*2*3*.*(n-1)*n=(n-1)!*n23沈洋 南京航空航天大学函数(假设n=3)的执行过程 long fact(int n)long c;if(n=1|n=0)c=1;else c=fact(n-1)*n;return c;long fact(int n)long c;if(n=1|n=0)c=1;else c=fact(n-1)*n;return c;24沈洋 南京航空航天大学递归的条件o有终止递归调用的语句。o要有递归调用的语句。o一般一般 先判断是
12、否到达终止条件,后递归调用。25沈洋 南京航空航天大学4.9 示例:素因子分解o目的:在发现一个自然数不是质数的时候,能够将其素因子素因子打印出来。o素因子:能够整除该自然数的那些质数o例如:n输入36,打印出2,2,3,3n输入99,打印出3,3,11n输入质数时,直接打印出该数,如1726沈洋 南京航空航天大学(1)思路o设输入的数为n,计数变量为ioi从2开始判断n是否能被i整除,如果能,则i是n的素因子,将i打印出来n在这个问题中,第一个整除n的数一定是质数吗?o将n的值改写为n/io重复这个过程o如果n已经是质数,即找不出能整除n的i,则直接打印出n27沈洋 南京航空航天大学(2)实
13、例演算o36o打印出2on=36/2=18o打印出2on=18/2=9o打印出3o9=9/3=3o找不出素因子,即3已经是质数,打印出328沈洋 南京航空航天大学(3)将步骤用C+描述void getDivisors(int n)for(i=2;i=n-1;i+)if(n%i=0)cout i;getDivisors(n/i);coutn;有问题吗?有问题吗?让我们验证一下!让我们验证一下!29沈洋 南京航空航天大学return的作用o在找到一个素因子,将其打印出来,并进行递归调用结束后,会返回到调用语句之后继续执行后续的内容o那么,就会打印出非质数因子并最终打印出n本身,而这并不是我们希望的
14、o可在任何需要的位置使用return终止函数30沈洋 南京航空航天大学更正的版本void getDivisors(int n)for(i=2;i=n-1;i+)if(n%i=0)cout i;getDivisors(n/i);return;cout0)hanoi(n-1,A,C,B);coutA”,C);hanoi(n-1,B,A,C);void main()int m;coutm hanoi(m,A,B,C);34沈洋 南京航空航天大学4.10 示例:随机数生成器o随机数生成器是很多游戏中不可少的元素o在后续课程中还要用到该函数o使用rand()获取随机数o在此之前应使用srand()设置随
15、机数的“种子”o使用当前时间作为种子是个不错的选择otime(NULL)返回当前时间“刻度”o代码见P79o有问题吗?35沈洋 南京航空航天大学#include#include#include#include using namespace std;int rand_0toN1(int n);int main()int n,i;int r;srand(time(NULL);/Set a seed for random-num.generation.cout n;for(i=1;i=n;i+)r=rand_0toN1(6)+1;/Get a number from 1 to 6 cout r ;/Print it out return 0;/Random 0-to-N1 Function./Generate a random integer from 0 to N-1,giving each integer an equal probability./int rand_0toN1(int n)return rand()%n;36沈洋 南京航空航天大学讨论:为什么把srand放在main函数中?在一个应用程序中,随机数种子只需设置一次37沈洋 南京航空航天大学
限制150内