版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第5章 函数中国铁道出版社1第1页第1页5.1 结构化程序设计5.1.1 过程化C+程序框架以源程序文献为单位进行编译一个源程序由一个main()函数和(或)多个其它函数构成。程序执行从main()函数开始在main()函数中调用其它函数在main()函数中结束运营。对于其它函数,通过被调用方式来执行,它能够由main()调用,也能够被多个其它函数多次地调用。 2第2页第2页函数之间调用关系示意图 函数之间调用关系:main函数调用了f1()、f2()、f3()这3个函数函数f2()调用了函数f3()函数f3()调用了函数f4()3第3页第3页C+程序框架通常由3个部分构成(1)第1部分:对每
2、一个将被调用函数进行申明void f1();void f2();void f3();void f4();(2)第2部分:定义main()函数void main() f1(); / 调用函数f1f2(); / 调用函数f2f3(); / 调用函数f3 4第4页第4页(3)第3部分:定义其它各个函数。void f1() / 定义函数f1 void f2() / 定义函数f2 f3(); / 调用函数f3 void f3() / 定义函数f3 f4(); / 调用函数f45第5页第5页【例5-1】 计算圆面积和周长输入一个圆半径值,然后计算这个圆面积和周长,并输出计算结果,其中计算圆面积和周长分别由
3、两个函数完毕,#include using namespace std; double area(double r); / 申明计算面积函数area()double len(double r); / 申明计算周长函数len()6第6页第6页【例5-1】(续)void main()double r;coutr;coutarea=area(r)endl; / 调用area()计算面积coutlen=len(r)endl; / 调用len()计算周长double area(double r) / 定义计算面积函数area() return 3.1416*r*r; double len(double
4、r) / 定义计算周长函数len() return 2*3.1416*r; 7第7页第7页5.1.2 库函数和自定义函数(1)库函数在函数库中已定义函数,也称为标准函数,分布在不同函数库中,比如iostream、cmath和string等。使用库函数时,在程序开头将该函数所在函数库进行包含包含格式:#include “函数库名”比如:#include #include using namespace std; (2)自定义函数:由用户自行编写8第8页第8页5.2 函数概念自定义函数定义方式返回值概念函数申明9第9页第9页5.2.1 函数定义1函数定义普通形式类型名 函数名(类型名 形参1,类型
5、名 形参2,) 函数体 (1)类型名:又称为函数类型,是函数调用返回时带回给主调函数值类型。(2)函数名:函数名命名要符合标识符命名规则。(3)形参类型和名称:形参用来在函数调用时接受从主调函数那里传递过来数据。(4)函数体:用来实现该函数功效。10第10页第10页2函数几种特殊形式 (1)无参函数没有形参函数称为无参函数,圆括号不能省略。(2)空函数假如函数体为空,该函数称为空函数,空函数也能够被调用,调用后也能够返回到主调函数。空函数通惯用在程序设计最初阶段,目的是确保整个程序完整性,以后再向函数体中填写详细语句11第11页第11页void使用用关键字void来定义无类型或称为空类型函数,
6、明确表示不带回值。比如:void fun() couty) return x; else return y; 14第14页第14页返回值类型与函数类型不一致情况返回值类型在定义函数时指定,假如return语句中表示式类型与函数定义时类型不一致,返回时以函数类型为准,这时系统会对return语句中表示式值自动进行类型转换。15第15页第15页【例5-2】返回值与函数类型不一致#include using namespace std;int max(float x,float y) return(xy?x:y);void main() float a,b; int c; cinab; c=max(
7、a,b); cout Max=y?x:y结果转换为int,然后再返回给main。16第16页第16页5.2.3 函数申明1函数调用原则调用任何函数之前,应当先对该函数进行申明假如被调函数出现在主调函数之前,这时,定义函数同时也对该函数进行了申明,该函数能够直接调用,能够省略对该函数申明。假如被调函数出现在主调函数之后,就要在函数调用之前对该函数进行申明。17第17页第17页【例5-3】被调函数在主调函数之前定义#include using namespace std;float f() return 3.5;void main() coutf() ;该程序能够正常运营。18第18页第18页犯错
8、程序假如将程序中两个函多顺序进行互换:#include using namespace std;void main() couty?x:y); 该函数函数原型是: int max(int x,int y); 或 int max(int , int);20第20页第20页5.3 函数调用5.3.1 函数调用普通形式1实际参数函数调用普通形式: 函数名(参数表列)调用函数时,格式中参数表列各个参数称为实际参数,简称实参,实参向被调函数形参传递数据。比如:实参是变量:c=max(a,b);实参是常量:c=max(3,4);实参是表示式:c=max(3+5,4+3);实参是另一个函数调用结果: c=s
9、qrt(max(a,3);实参个数、类型和顺序应与被调函数形参一一相应21第21页第21页【例5-4】函数调用时数据传递#include using namespace std;void print_char(char c,int n) int i; coutendl; for (i=0;in;i+) coutc;void main() print_char(-,5); print_char(,10);22第22页第22页2函数调用几种形式(1)语句调用作为函数调用语句,完毕一定操作,不返回任何值。(2)表示式调用函数调用出现在表示式中,函数值参与表示式运算比如: c=2*max(a,b);(
10、3)函数值作为另一个函数调用参数这时被调函数作为其它函数参数比如: m=max(a,max(b,c);23第23页第23页【例5-5】函数调用语句 #include using namespace std;void printstar(); void printmess();void main() printstar(); printmess(); printstar(); void printstar() cout*endl; void printmess() cout C+ Programmeendl; 24第24页第24页5.3.2 设置形参默认值C+中允许为形参指定默认值,在函数调用时
11、假如有实参,则形参使用实参值,假如没有指定与形参相应实参,形参自动使用默认值指定参数默认值能够在函数定义中进行,也能够在函数原型中进行,通常是写在函数名在程序中第一次出现位置。比如:int add(int x=0,int y=0);25第25页第25页【例5-6】默认参数值使用#include using namespace std;void add(int x=0,int y=0) coutx+y=x+yendl; void main() add(1,2); add(); add(3); 26第26页第26页对部分形参定义默认值要求: 没有默认值形参只能出现在形参表列前边,默认值出现在从右到
12、左连续若干个形参中。下面定义办法是允许: void fun(int i=1,int j=2,int k=3); void fun(int i,int j=2,int k=3); void fun(int i,int j,int k=3); 下面定义办法是不允许: void fun(int i=1,int j=2,int k); void fun(int i=1,int j,int k); void fun(int i,int j=2,int k);27第27页第27页5.4 参数传递在C+语言中,函数之间调用时通过参数进行数据传递,从传递内容上看,参数传递有值传递、地址传递和引用传递3种方式2
13、8第28页第28页5.4.1参数传递方式1值传递值传递时,将实参值依次传递给对应形参,形参变量只有在发生函数调用时才分派内存单元用来接受由实参传过来数据。值传递时,实参加形参各占不同单元,当调用结束后,形参所在内存单元被释放,而实参仍保留原值。29第29页第29页【例5-7】分析程序#include using namespace std;void swap(int x,int y); void main() int a=3,b=4; couta=a b=bendl; swap(a,b); couta=a b=bendl;void swap(int x,int y) int z; coutx=
14、x y=yendl; z=x;x=y;y=z; coutx=x y=yendl; 结论:变量a和b值并没有互换。30第30页第30页2引用传递假如形参是引用名,在函数调用时,形参变量与实参变量实际表示是同一内存单元,在被调函数中对引用变量操作就和在主调函数中使用实参效果是同样,这样,能够通过引用变量在被调函数中改变主调函数中变量值。31第31页第31页【例5-8】使用引用传递互换变量值#include using namespace std;void swap(int&,int &);/函数swap()形参是引用名void main() int a=5,b=10; couta=a,b=bend
15、l; swap(a,b); couta=a,b=b;void swap(int &m,int &n) / 引用传递 int t=m; m=n; n=t;结论:变量a和b值实现了互换。32第32页第32页5.4.2 一维数组名作为函数参数由于数组名代表了该数组所占连续内存单元中首地址,因此数组名作参数时,传送给形参数组是实参数组起始地址,这也是引用传递,主调函数和被调函数两个数组共占相同内存单元,这样,假如被调函数中各数组元素值发生改变,在返回主调函数后,实参数组中元素值也同时改变33第33页第33页【例5-9】数组名作函数参数#include using namespace std;f(int
16、 b,int m,int n) int i,s=0; for(i=m;in;i=i+2) s=s+bi; return s;void main() int x,a=1,2,3,4,5,6,7,8,9; x=f(a,3,7); coutx;34第34页第34页【例5-10】在被调函数中改变主调函数中数组元素值#include using namespace std;void f(int b) int i; for(i=0;i10;i+) bi+;void main()int i,a10=1,3,2,4,8,3,4,9,12,0; cout调用前:; for(i=0;i10;i+) coutai,
17、;coutendl; f(a); cout调用后:;for(i=0;i10;i+) coutai,;coutendl;35第35页第35页5.5 函数特殊调用5.5.1 嵌套调用在一个函数调用过程中,被调函数又调用了另一个函数。 C+中能够嵌套调用,但是不能够嵌套定义函数。36第36页第36页【例5-11】函数嵌套调用从键盘上输入两个整数,计算这两个整数平方和。#include using namespace std;int square(int n) return n*n; int sum(int x,int y) return square(x)+square(y); void main(
18、) int m,n; coutmn;coutm2+n2=sum(m,n)endl;37第37页第37页5.5.2 递归调用在调用一个函数过程中直接或间接地调用其本身,有两个阶段(1)递推阶段将本来问题不断地分解为新问题,逐步从未知向已知方向推测,最后到达已知条件。(2)回归阶段从已知条件出发,按递推逆过程,逐一求值,最后到达递推开始。38第38页第38页【例5-12】用递归调用计算阶乘n!#include using namespace std;int fac(int n)int f; if(n=0|n=1) f=1; else f=fac(n-1)*n; return f;void main
19、() int n,y; cinn; y=fac(n); coutn!=y;39第39页第39页【例5-13】使用递归计算Fibonacci数列使用递归调用办法计算示Fibonacci数列前30项,每行显示5个。#include using namespace std;int fib(int n) if(n=0|n=1) return 1; else return fib(n-1)+fib(n-2);void main() int i; for(i=0;i30;i+) if (i%5=0) coutendl; coutfib(i)t; 40第40页第40页5.6 变量作用域和生存期一个变量能否在
20、多个函数中使用,这是变量作用域;一个变量在定义之后,起作用时间有多长,这是变量生存期。41第41页第41页5.6.1 变量作用域依据变量作用域不同,能够把变量分为局部变量和全局变量。1局部变量(1)在一个函数内部定义变量(2)函数形参是局部变量。(3)在main中定义变量上局部变量。(4)在复合语句中定义是局部变量,仅在复合语句范围内有效。42第42页第42页【例5-14】不同局部变量#include using namespace std;void main() int i=1,j=3; couti,; i+; int i=0; i+=j*2; couti,j,; couti,j; 43第4
21、3页第43页2全局变量全局变量在函数之外、类之外定义变量,全局变量可认为本源程序中所有函数、类或复合语句所访问。定义全局变量如果没有初始化,系统自动将其初始化为0。全局变量和某个局部变量允许同名,这时,在局部变量作用范围内,全局变量是不起作用。44第44页第44页【例5-15】全局变量和局部变量#include using namespace std;int a=3,b=5; / 这里定义了两个全局变量int max(int a,int b) return ab?a:b;void main() int a=8; / 该处定义局部变量与全局变量同名 coutmax(a,b);45第45页第45页
22、【例5-16】使用作用域运算符全局变量和局部变量重名时,在全局变量前使用作用域运算符#include using namespace std;int avar;void main( ) int avar; avar=25; /局部变量avar :avar=10; /全局变量avar coutlocal avar = avarendl; coutglobal avar = :avarendl;46第46页第46页【例5-17】申明全局变量#include using namespace std;void main() int c; extern a,b; /* 此处申明全局变量a,b */ c=
23、a+b; /* 此处使用全局变量a,b */ coutc;int a=3,b=5; /* 此处定义全局变量a,b */47第47页第47页5.6.2 变量存储类型 1C+程序使用内存区域(1)程序代码区:存储各个函数代码;(2)全局数据区:存储全局数据和静态数据,该区域数据始终保持到程序结束;(3)栈区:存储程序局部数据,当函数被调用时,才为函数中局部变量在此区别配存储空间,函数调用结束时会收回该函数在栈区别配单元;(4)堆区:存储程序动态数据,该区能够用new或malloc分派,能够用delete或free进行释放。48第48页第48页 2局部变量存储方式变量存储类型,就是指定变量详细存储区
24、域在默认情况下,变量存储区域:全局变量保留在全局数据区;局部变量保留在栈区;用new或malloc动态分派变量保留在堆区;49第49页第49页局部变量存储类型(1)auto类型 又称为自动变量,分派在栈区,这是缺省方式,关键字auto能够省略。(2)static静态将局部变量分派到全局数据区空间,这样变量称为静态局部变量,静态局部变量有下列特点:初始值缺省为0;局部变量在函数调用结束后所占内存单元不释放,其值能够保持到函数下一次调用。50第50页第50页(3)register存储器变量用存储标识register将局部变量值放在存储器中,用来提升执行效率,使用该类型时应注意下面问题:仅局部变量和
25、形参可作为存储器变量;存储器数目有限,假如定义了多个存储器变量,多出自动作auto型处理;存储器变量没有地址,因此不能作地址运算。51第51页第51页 【例5-18】分析程序#include using namespace std;int fun(int n) static int f=1; f=f*n; return f;void main() int i; for (i=1;i=5;i+) coutfun(i)endl;52第52页第52页 3在定义全局变量时使用static 在全局变量前加上static,表示该变量只能被本编译单位引用,而不能被其它编译单位引用。比如,有两个文献file1
26、.cpp和file2.cpp。file1.cpp内容下列:static int A;void main() file2.cpp内容下列:extern int A;int fun(int n) 在file1.cpp中定义全局变量A用static 申明,因此只能用于file1.cpp中,这样,在file2.cpp中即使用了extern int A;但还是无法使用file1.cpp中全局变量。53第53页第53页4在定义全局变量时使用extern定义全局变量时,在其前面使用extern,有两种情况。(1)在同一编译单位内全局变量前加extern用于全局变量定义在后,引用变量函数在前情况,用来说明该变
27、量是已被定义了全局变量。(2)在不同编译单位内全局变量前加extern一个程序由多个编译单位组成时候,假如每个文件中需要引用同一个全局变量,可在其中一个文件中定义全部全局变量,而在其它用到这些全局变量文件中用extern对变量进行说明,申明这些变量已在其它编译单位中定义。 54第54页第54页5.6.3 变量生存期变量生存期是指一个变量从定义且分派内存单元开始,一直到该变量所占空间被释放为止。按变量存放类型不同,变量有两种生存期:(1)静态存放分派变量在编译时分派空间,在程序运行过程中一直占用空间,包含全局变量和静态局部变量,程序结束时,变量所占空间被释放。(2)自动存放分派在程序运行期间为变
28、量分派空间,这类变量就是局部变量,即在函数或复合语句内定义自动变量,程序执行到函数或复合语句时建立并分派空间,函数或复合语句结束时所占空间被释放。55第55页第55页5.7 函数重载函数重载机制两个或两个以上函数含有相同函数名,这些函数被称为重载函数,只要这些函数形参个数不同或形参类型不完全一样,编译系统依据实参和形参个数或类型匹配关系,在同名函数中自动选择调用某个函数。56第56页第56页【例5-19】按形参类型重载函数#include #include using namespace std;int max(int x,int y) return xy?x:y; / (1)求整型数最大值5
29、7第57页第57页【例5-19】(续)double max(double x,double y) return xy?x:y; / (2)求双精度型数最大值char max(char x, char y)return xy?x:y; / (3)求字符型数最大值char *max(char *s1, char *s2) return strcmp(s1,s2)0?s1:s2; / (4)求字符串最大值58第58页第58页【例5-19】(续)void main() coutmax(4,5)endl; coutmax(4.6,1.2)endl; coutmax(x,y)endl; coutmax(a
30、bc,aaa); 59第59页第59页【例5-20】按形参个数重载函数#include using namespace std;int add(int x,int y) / 有两个形参int sum; sum=x+y; return sum; int add(int x,int y,int z) / 有3个形参int sum; sum=x+y+z; return sum; int add(int x,int y,int z,int t) / 有4个形参int sum; sum=x+y+z+t; return sum; 60第60页第60页【例5-20】(续)void main() int a,
31、b,c; a=add(3,5); b=add(3,5,7); c=add(3,5,7,9); coutaendl; coutbendl; coutcendl; 61第61页第61页5.8 内联函数问题:一些代码不长又经常被调用函数,系统为调用所花费时间和空间开销较大,有时甚至会影响程序运营效率。处理办法:将函数定义为内联函数定义格式:inline 函数类型 函数名(形参及其类型表列) 函数体 程序编译将内联函数调用表示式用内联函数函数体替换,这样,就不会产生程序调用时转向、恢复等问题,以增长程序代码为代价换来时间上效率62第62页第62页【例5-21】内联函数使用#include using
32、namespace std;inline int square(int x) / 定义为内联函数 return x*x; void main() int i,sum=0; for(i=1;i=10;i+) sum=sum+square(i); coutsum=y?x:y; double max(double x,double y) return xy?x:y; char max(char x, char y) return xy?x:y; 这几个函数参数类型不同,返回值类型不同,但功效一样,而且函数体中代码完全一样问题:能否只编写一个含有通用功效函数,让该函数支持不同类型数据,从而免去相同代码
33、重复使用函数模板能够处理这个问题。64第64页第64页5.9.1 模板定义和使用函数模板定义:template 函数定义格式中“模板形参表列”必须放在尖括号中,每一个模板形参能够使用下面定义形式之一:(1)typename 参数名(2)class 参数名(3)类型名 参数名 前两种形式效果同样,申明参数称为虚拟类型参数,第3种形式申明参数称为常规参数。比如,有一个形参:template 两个形参:template 65第65页第65页在函数模板中所定义函数称为模板函数在对程序编译时,编译系统依据每次调用该模板函数所使用详细数据类型生成适当函数代码,这一过程称为函数模板实例化,实例化时,用实参详
34、细类型替换形参虚拟类型。66第66页第66页【例5-22】只带有虚拟类型参数模板#include using namespace std;template T max(T x,T y) /所定义模板形参为Treturn xy?x:y;void main() coutmax(4,5)endl; /调用模板函数实参类型是int coutmax(4.6,1.2)endl; /调用模板函数实参类型是double coutmax(x,y)y?x:y;(2)第2次调用模板函数是max(4.6,1.2),实参类型是double,实例化生成下列函数实例:double max(double x,double y
35、) return xy?x:y;(3)第3次调用模板函数以char类型进行实例化68第68页第68页【例5-23】同时带有虚拟类型参数和常规参数模板#include using namespace std;template T sum(T a,int n) /虚拟参数T和常规参数n int i; T sum=0; for(i=0;in;i+) sum=sum+ai; return sum;69第69页第69页【例5-23】(续)void main() int a10=1,2,3,4,5,6,7,8,9,10; double b10=1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0
36、,9.0,10.0; coutsum(a,5)endl; /计算数组a中前5个数之和 coutsum(a,10)endl; /计算数组a中前10个数之和 coutsum(b,5)endl; /计算数组b中前5个数之和 coutsum(b,10)endl; /计算数组b中前10个数之和70第70页第70页5.9.2 模板实参使用当从模板函数实参表中无法取得足够信息来判断形参类型时,需要使用模板实参。 带有模板实参模板函数调用形式下列:函数名 (函数实参表列)71第71页第71页1从模板函数实参表无法拟定模板参数类型template T max(T x,T y) return xy?x:y;调用m
37、ax(3.5,6) 实参类型分别是double和int,系统无法判断形参T类型是double还是int。处理办法:在函数调用时加上模板实参调用1: max(3.5,6) 形参T被替换为double调用2: max(3.5,6) 形参T作为int型72第72页第72页2需要指定特定类型返回值【例5-24】指定返回值类型。#include using namespace std;template T max(T x,T y) return (float) (xy?x:y);73第73页第73页【例5-24】(续)void main() coutmax (a,b)endl; coutmax (4.6,1)endl;第1次调用max (a,b)使用了模板实参类型为int,函数两个实参类型都为char型,它们自动转换为int型,并以int型返回,结果为98。第2次调用max (4.6f,1),两个函数实参类型不一致,而模板实参类型为float,将转换为float型,最后返回值类型也是float型。74第74页第74页3模板形参没有出现在模板函数形参表中模板形参是无法通过模板
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 合同的附合同范本
- 开发项目合同范本
- 2024年度艺术品买卖合同标的说明
- 2024年度物流配送保密合同
- 2024至2030年超声波雾化器片项目投资价值分析报告
- 2024至2030年水晶活性金人参眼霜项目投资价值分析报告
- 2024年电脑微机控制热切封背心袋机项目可行性研究报告
- 2024年度商业秘密许可合同详尽条款
- 2024版第十三节工程监理合同标的及具体描述
- 2024至2030年中国沥青比重测定仪数据监测研究报告
- 通信工程生涯发展规划
- 口腔专科护理疑难病例讨论
- 博雅汉语初级起步1-U11-北京的冬天比较冷
- 屠宰行业PEST分析
- 公交驾驶员心理疏导培训
- 《中国成人暴发性心肌炎诊断和治疗指南2024》解读
- 采购竞聘报告
- 新生儿经皮测黄疸课件
- 职业生涯规划网络工程
- 《足球-脚内侧传球》教案
- 能源托管可行性方案
评论
0/150
提交评论