C++语言程序设计教程 第4章 函数 第4章 函数
第4章 函数 学习目标 1. 掌握函数的声明和定义、函数的调用及函数的参数传递过程; 2. 掌握关键字inline的含义与使用; C++语言程序设计教程 第4章 函数 第4章 函数 学习目标 1. 掌握函数的声明和定义、函数的调用及函数的参数传递过程; 2. 掌握关键字inline的含义与使用; 3. 掌握递归函数的使用; 4. 掌握函数重载的使用方法; 5. 掌握函数模板的使用方法; 6. 了解各类系统函数,掌握常用的系统函数的使用。
C++语言程序设计教程 第4章 函数 4.1 函数的定义和声明 4.1.1 函数的定义 函数是一个命名的程序代码块,是程序完成其操作的场所,是将功能重复的程序段抽象出来所形成一个独立的、可重复使用的功能模块。 定义函数的一般格式为: 返回类型 函数名 (数据类型1 参数1, 数据类型2 参数2,... ) { 语句序列; } 形参表 说明: 函数必须先定义才可以使用 定义函数就是编写完成函数功能的程序块。
C++语言程序设计教程 第4章 函数 4.1 函数的定义和声明 在函数的定义中: 返回类型为函数返回值的类型,可以是系统任一基本数据类型或用户已定义的一种数据类型,它是函数执行过程中通过return语句要求的返回值的类型,又称为该函数的类型。当一个函数不需要通过return语句返回一个值时,称为无返回值函数或无类型函数,此时需要使用void作为类型名。 函数名是用户为函数所起的名字,它是一个标识符,应符合C++标识符的一般命名规则,用户通过使用这个函数名和实参表可以调用该函数。 形式参数表可以包含任意多项(可以没有),当多于一项时,前后两个参数之间必须用逗号分开。 用花括号括起来的语句序列组成了函数体,即函数所完成的具体操作,函数体一般分为3部分:第1部分为定义部分,定义函数所需要的局部常量与局部变量;第2部分为函数的功能部分,完成函数的功能;第3部分为返回值部分,返回函数的结果。如果函数体中没有任何语句,该函数称作空函数。 每个函数都是一个功能独立的模块,绝不允许在一个函数体内定义另一个函数。
4.1 函数的定义和声明 运行结果: 5 15 ↙ 15 函数定义 函数体:函数所完成的具体操作 主函数 C++语言程序设计教程 第4章 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 /********************************** * p4_1.cpp * * 函数的使用, 对两个数取大 * ***********************************/ #include <iostream> using namespace std; int max(int x,int y) { int z; z=(x>y)?x:y; return z ; } void main() int a,b; cin>>a>>b; cout<<max(a,b)<<endl; 函数定义 函数体:函数所完成的具体操作 主函数 运行结果: 5 15 ↙ 15
4.1 函数的定义和声明 在C++程序中,使用函数前首先需要对函数原型进行声明,告诉编译器函数的名称、类型和形式参数。 第4章 函数 4.1 函数的定义和声明 在C++程序中,使用函数前首先需要对函数原型进行声明,告诉编译器函数的名称、类型和形式参数。 在C++中,函数原型声明原则如下: (1) 如果函数定义在先,调用在后,调用前可以不必声明; 如果函数定义在后,调用在先,调用前必须声明。 (2) 在程序设计中,为了使程序设计的逻辑结构清晰,一般 将主要的函数放在程序的起始位置声明,这样也起到了 列函数目录的作用。
4.1.2 函数原型的声明 在C++中,函数原型声明原则如下: 第4章 函数 4.1.2 函数原型的声明 在C++中,函数原型声明原则如下: (1) 如果函数定义在先,调用在后,调用前可以不必声明;如果函数定义在后,调用在先,调用前必须声明。 (2) 在程序设计中,为了使程序设计的逻辑结构清晰,一般将主要的函数放在程序的起始位置声明,这样也起到了列函数目录的作用。 声明函数原型的形式如下: 例如: int max(int x,int y) ; int max(int,int) ; 返回类型 函数名 (数据类型1 参数1, 数据类型2 参数2,... ); 加上参数名会使函数的 功能和参数更清晰。
4.1.2 函数原型的声明 注意: 函数名 (参数1, 参数2,... ); 函数调用的一般形式为: 实际参数表 C++语言程序设计教程 第4章 函数 4.1.2 函数原型的声明 函数调用的一般形式为: 各实际参数表中的实际参数应与形参表中的形参一一对应,即个数相等且对应参数的数据类型相同。 函数调用是一个表达式,函数名连同括号是函数调用运算符。表达式的值就是被调函数的返回值,它的类型就是函数定义中指定的函数返回值的类型,即函数的类型。 如果函数的返回值为void,说明该函数没有返回值。 例如: cout<<max(a,b)<<endl; 函数名 (参数1, 参数2,... ); 实际参数表 注意: 主函数main()不需要进行原型语声明,也不允许任何函数调用它,它只由操作系统调用并返回操作系统。
4.2.2 函数调用的执行过程 ⑦ 返回过程执行的是函数体中的return语句。 当调用一个函数时,整个调用过程分为三步进行: C++语言程序设计教程 第4章 函数 4.2.2 函数调用的执行过程 当调用一个函数时,整个调用过程分为三步进行: 第一步:函数调用; ① 将函数调用语句下一条语句的地址保存在一种称为“栈”的内存中空间中, 以便函数调用完后返回。将数据放到栈空间中的过程称为压栈。 ② 对实参表从后向前,依次计算出实参表达式的值,并将值压栈。 ③ 转跳到函数体处。 第二步:函数体执行,即逐条运行函数体中语句的过程。 ④ 如果函数中还定义了变量,将变量压栈。 ⑤ 将每一个形参以栈中对应的实参值取代,执行函数的功能体。 ⑥ 将函数体中的变量、保存在栈中的实参值,依次从栈中取出,以释放栈 空间。从栈中取出数据称为出栈,x出栈用pop(x)表示。 第三步:返回,即返回到函数调用表达式的位置。 ⑦ 返回过程执行的是函数体中的return语句。
C++语言程序设计教程 第4章 函数 4.2.2 函数调用的执行过程 以函数max()为例,演示函数调用的详细过程如图4-1所示
C++语言程序设计教程 第4章 函数 4.2.3 函数参数的按值传递 函数调用过程实际上执行了一个从参数传递----执行函数体----返回的过程。其中的函数参数传递过程的实质是将实参值通过栈空间一一传送给实参的过程,这种把实参表达式的值传送给对应的形参变量传递方式称为“按值传递”。
4.2.3 函数参数的按值传递 函数定义 传值调用 运行结果: x=7 y=11 after swap: x=7 y=11 C++语言程序设计教程 第4章 函数 4.2.3 函数参数的按值传递 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 /************************************** * p4_2.cpp * * 函数的传值调用, 将两个数交换 * **************************************/ #include<iostream> using namespace std; void swap(int a,int b) { int t; t=a, a=b, b=t; } void main() int x=7,y=11; cout<<"x="<<x<<" y="<<y<<endl; swap(x,y); cout<<"after swap:"; 函数定义 传值调用 运行结果: x=7 y=11 after swap: x=7 y=11
C++语言程序设计教程 第4章 函数 4.2.4 嵌套调用 在一个函数中调用其它函数叫函数的嵌套。C++中函数的定义是平行的,除了main()以外,都可以互相调用。函数不可以嵌套定义,但可以嵌套调用。比如函数1调用了函数2,函数2再调用函数3,这便形成了函数的嵌套调用。 1 2 3 4 5 6 7 8 9 10 11 12 /************************************************************** * p4_3.cpp * * 函数的嵌套调用, 求三个数中最大数和最小数的差值 * **************************************************************/ #include<iostream> using namespace std; int max(int x,int y,int z) { int t; t=x>y?x:y; return(t>z?t:z); } 函数定义
运行结果: 注意: 嵌套调用 5 -6 15↙ 21 函数不可以嵌套定义,但可以嵌套调用。 C++语言程序设计教程 第4章 函数 13 14 16 17 18 19 20 21 22 23 24 25 26 27 28 int min(int x,int y,int z) { int t; t=x<y?x:y; return(t<z?t:z); } int dif(int x,int y,int z) return max(x,y,z)-min(x,y,z); void main() int a,b,c; cin>>a>>b>>c; cout<<"Max-Min="<<dif(a,b,c)<<endl; 嵌套调用 运行结果: 5 -6 15↙ 21 注意: C++中函数的定义是平行的,除了main()以外,都可以互相调用。 函数不可以嵌套定义,但可以嵌套调用。
4.2.4 递归调用 在调用一个函数的过程中又直接或间接地调用该函数本身的这一现象,叫做函数的递归调用。 1 (n=0) n!= C++语言程序设计教程 第4章 函数 4.2.4 递归调用 在调用一个函数的过程中又直接或间接地调用该函数本身的这一现象,叫做函数的递归调用。 1 (n=0) n!= n(n-1)! (n>0) 递归可以分为直接递归调用和间接递归调用。 直接递归调用:是在调用函数的过程中又调用该函数本身; 间接递归调用:是在调用f1()函数的过程中调用f2()函数,而f2()中 又需要调用f1()。
C++语言程序设计教程 第4章 函数 4.2.4 递归调用 递归方法是从结果出发,归纳出后一结果与前一结果直到初值为止存在的关系,要求通过分析得到:初值+递归函数,然后设计一个函数(递归函数),这个函数不断使用下一级值调用自身,直到结果已知处。 递归函数设计的一般形式是: 函数类型 递归函数名f (参数x ) { if(满足结束条件) 结果=初值; else 结果=含f(x-1)的表达式; 返回结果; }
4. 2.4 递归调用 递归函数定义 C++语言程序设计教程 第4章 函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /************************************************ * p4_4.cpp * * 函数的递归调用, 求n! * ************************************************/ #include<iostream> using namespace std; int fac(int n) { int t; if(n==1) t=1; else t=n*fac(n-1); return (t); } 递归函数定义
C++语言程序设计教程 第4章 函数 4. 2.4 递归调用 16 17 18 19 20 21 22 23 24 25 void main() { const int max_n=12; // int 类型数能表示的n!的最大的n int n; cout<<"Input a integer number:"; cin>>n; if (n>=1&&n<=max_n) cout<<"Factorial of "<<n<<" is: "<<fac(n)<<endl; else cout<<"Invalid n."<<endl; } 递归函数调用 运行结果: 12↙ 479001600 递归程序分两个阶段执行: ① 调用:欲求fac(n)→先求fac(n-1)→fac(n-2) → … → fac(1) 若fac(1)已知,回推结束。 ② 回代:知道fac(1)→可求出fac(2)→fac(3)→ … → (n)
C++语言程序设计教程 第4章 函数 4. 2.4 递归调用 函数参数传递过程 :
4.2.4 递归调用 【例4-5】汉诺塔(Tower of Hanoi)问题。 C++语言程序设计教程 第4章 函数 4.2.4 递归调用 【例4-5】汉诺塔(Tower of Hanoi)问题。 有三根柱子A、B、C。A柱上有从小到大排列的n个盘,要求把这些盘全部搬到C柱上,可以利用空的B柱;但是每次只能搬动一个盘,且在搬动时每个柱子上必须保持盘从小到大的排列次序。如, 当盘数n=3时搬动步骤为: (1, A->C), (2, A->B), (2, C->B), (3, A->C), (1, B->A), (2, B->C), (1,A->C)。
C++语言程序设计教程 第4章 函数 4.2.4 递归调用 分析: 将n个盘子从A柱移到C柱可分解为以下3步:
4. 2.4 递归调用 递归函数定义 C++语言程序设计教程 第4章 函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 /******************************* * p4_5.cpp * * 汉诺塔问题 * *******************************/ #include <iostream> using namespace std; void move(int n, char source, char target) { cout<<"( "<<n<<", "<<source<<"--->"<<target<<" )"<<endl; } void hanoi(int n,char A,char B,char C) if(n==1) move(1, A, C); else { hanoi(n-1, A, C, B); move(n, A , C); hanoi(n-1, B, A, C); 递归函数定义
4. 2.4 递归调用 运行结果: 21 22 23 24 25 26 27 void main() { int num; C++语言程序设计教程 第4章 函数 4. 2.4 递归调用 21 22 23 24 25 26 27 void main() { int num; cout<<"Input the number of diskes"; cin>>num; hanoi(num,'A','B','C'); } 递归函数调用 运行结果: Input the number of diskes3↙ (1, A--->C) (2, A--->B) (2, C--->B) (3, A--->C) (1, B--->A) (2, B--->C)
C++语言程序设计教程 第4章 函数 4.3 内联函数 内联函数: 是通过在编译时将函数体代码插入到函数调用处,将调用函数的方式改为顺序执行方式来节省程序执行的时间开销,这一过程叫做内联函数的扩展。因此,内联函数实际上是一种用空间换时间的方案。 内联函数的定义形式如下: inline 函数类型 函数名 (形式参数表) { 函数体; } 在内联函数扩展时也进行了实参与形参结合的过程:先将实参名(而不是实参值),将函数体中的形参处处替换,然后搬到调用处。但从用户的角度看,调用内联函数和一般函数没有任何区别。
4.3 内联函数 运行结果: 内联函数定义 内联函数调用 12↙ 479001600 C++语言程序设计教程 第4章 函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 //********************************** * p4_6.cpp * * 内联函数的使用 * **********************************/ #include<iostream> using namespace std; inline double CirArea(double radius) { return 3.14*radius*radius; } void main() double r1(1.0),r2(2); cout<<CirArea(r1)<<endl; cout<<CirArea(r1+r2+4)<<endl; 内联函数定义 内联函数调用 运行结果: 12↙ 479001600
C++语言程序设计教程 第4章 函数 4.3 内联函数 由于计算机的资源总是有限的,使用内联函数虽然节省了程序运行的时间开销,但却增大了代码占用内存的空间开销。因此在具体编程时应仔细地权衡时间开销与空间开销之间的矛盾,以确定是否采用内联函数。 与处理register变量相似,是否对一个内联函数进行扩展完全由编译器自行决定。因此,说明一个内联函数只是请求而不是命令编译器对它进行扩展。事实上,如果将一个较复杂的函数定义为内联函数,大多数编译器会自动地将其作为普通函数处理。 注意: 如果仅在声明函数原型时加上关键字inline,并不能达到内联效果。 内联函数的定义必须出现在对该函数的调用之前,因为编译器在 对函数调用语句进行替换时,必须事先知道替换该语句的代码是 什么。这也是仅在声明函数原型时加上关键字inline,并不能达到 内联效果的原因。
C++语言程序设计教程 第4章 函数 4.4 带默认形参值的函数 C++语言允许在函数说明或函数定义中为形参预赋一个默认的值,这样的函数就叫做带有默认形参值的函数。在调用带有默认参数值的函数时,若为相应形参指定了实参,则形参将使用实参的值;否则,形参相使用其默认值。这就大大地方便了函数的使用。 例如: int sub(int x=8,int y=3) { return x-y; } void main(void) sub(20,15); //传递给形参x,y的值分别为20和15 sub(10); //传递给形参x,y的值分别为10和3 sub(); //传递给形参x,y的值分别为8和3
C++语言程序设计教程 第4章 函数 4.4 带默认形参值的函数 (1) 若函数具有多个形参,则缺省形参值必须自右向左连续地定义,并且在一个缺省形参值的右边不能有未指定缺省值的参数。这是由于C++语言在函数调用时参数是自右至左入栈这一约定所决定的。 例如: int f(int a,float b=5.0,char c='.',int d=10); //正确 int f(int a=1,float b=5.0,char c='.',int d); //错误, d未给值 int f(int a=1,float b,char c='.',int d=10); //错误, b未给值 (2) 在调用一个函数时,如果省去了某个实参,则直到最右端的实参都要省去(当然,与它们对应的形参都要有缺省值)。 例如: 假如有如下声明: int f(int a,float b=5.0,char c='.', int d=10); 采用如下调用形式是错误的: f(8, , ,4); //语法错误
C++语言程序设计教程 第4章 函数 4.4 带默认形参值的函数 (3) 缺省形参值的说明必须出现在函数调用之前。这就是说,如果存在函数原型,则形参的缺省值应在函数原型中指定;否则在函数定义中指定。另外,若函数原型中已给出了形参的缺省值,则在函数定义中不得重复指定,即使所指定的缺省值完全相同也不行。 例如: int sub(int x=8,int y=3); //缺省形参值在函数原型中给出 void main(void) { sub(20,15); //20-15 sub(10); //10-3 sub(); //8-3 } int sub(int x,int y) //缺省形参值没有在函数定义时给出 return x-y;
4.4 带默认形参值的函数 (4)在同一个作用域,一旦定义了缺省形参值,就不能再定义它。 C++语言程序设计教程 第4章 函数 4.4 带默认形参值的函数 (4)在同一个作用域,一旦定义了缺省形参值,就不能再定义它。 例如: int f(int a,float b,char,int d=10); int f(int a,float b,char c='.',int d=10); //错误:企图再次定义缺省参数c和d (5) 如果几个函数说明出现在不同的作用域内,则允许分别为它们提供不同的缺省形参值。 例如: int f(int a=6,float b=5.0,char c='.',int d=10); void main(void) { int f(int a=3,float b=2.0,char c='n',int d=20); cout<<f( )<<endl; //f函数使用局部缺省参数值 }
4.4 带默认形参值的函数 (7) 在函数原型给出了形参的缺省值时,形参名可以省略。 //d参数的缺省值是函数调用。 C++语言程序设计教程 第4章 函数 4.4 带默认形参值的函数 (6) 对形参缺省值的指定可以是初始化表达式,甚至可以包含函数调用。 例如: //d参数的缺省值是函数调用。 int f(int a,float b=5.0,char c='.',int d= sub(20,15)); (7) 在函数原型给出了形参的缺省值时,形参名可以省略。 例如: int f(int , float =5.0, char =’.’, int = sub(20,15));
C++语言程序设计教程 第4章 函数 4.5 函数重载 函数重载: 就是两个以上的函数,取相同的函数名,但是形参的个数和类型不同,编译器根据实参和形参的类型及个数的最佳匹配,自动决定调用哪一个函数。 例如: int max(int,int); int max(int,int,int); float max(float,float); double max(double,double);
函数重载 函数重载 函数重载 C++语言程序设计教程 第4章 函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 /****************************** * p4_7.cpp * * 函数的重载 * *******************************/ #include<iostream> using namespace std; int add(int x,int y) { cout<<"(int, int)\t"; return x+y; } double add(double x,double y) cout<<"(double, double)\t"; int add(int x,double y) cout<<"(int, double)\t"; return int(x+y); 函数重载 函数重载 函数重载
运行结果: (int, int) 17 (double,double) 17 (int, double) 17 C++语言程序设计教程 第4章 函数 21 22 23 24 25 26 27 28 29 30 31 32 double add(double x,int y) { cout<<"(double,int)\t"; return x+y; } void main() cout<<add(9,8)<<endl; cout<<add(9.0,8.0)<<endl; cout<<add(9,8.0)<<endl; cout<<add(9.0,8)<<endl; 函数重载 重载函数的调用 运行结果: (int, int) 17 (double,double) 17 (int, double) 17 (double, int) 17
C++语言程序设计教程 第4章 函数 4.5 函数重载 注意: (1) 各个重载函数的返回类型可以相同,也可以不同。但如果函数名相同、形参表也相同,仅仅是返回类型不同,则是非法的。在编译时会认为是语法错误。 // C++无法区分这两个函数。因为在没有确定函数调用是对哪一个重载的函数之前, //返回类型是不知道的。 int add(int i1,int i2); float add(int f1,int f2); (2) 确定对重载函数的哪个函数进行调用的过程称为绑定(binding), 绑定的优先次序为精确匹配、对实参的类型向高类型转换后的匹配、实参类型向低类型及相容类型转换后的匹配。 //将char型转换成int型,然后与add(int,int)绑定。 add('A','A'+'0'); //函数实参向(double,double)转换,然后与add(double,double)绑定。 add(float(8),float(9)); //实参类型为(long double, int),向低类型转化。 add(long double(8),9);
void add(int x, int y, int z=0); C++语言程序设计教程 第4章 函数 4.5 函数重载 绑定(匹配)二义性 两个重载函数,编译器不知道进行哪种类型的转换,与哪个函数绑定,这种现象就叫绑定(匹配)二义性。 消除这种二义性的办法有: ① 添加重载函数定义,使调用获得精确匹配。如:增加定义add(long double,int) ② 将函数的实参进行强制类型的转换,使调用获得精确匹配。 例如: 调用形式可改为add(double(long double(8)),9),但改为add(long double(8),long double(9))同样出现绑定二义性。 注意: 重载函数与带默认形参值的函数一起使用时,有可能引起二义性。 例如: void add(int x, int y, int z=0); 当调用add(8,9)时,不知与add(int,int) 还是add(int,int,int=0)绑定。 消除这种二义性的办法是增加或减少实参个数。
4.6 函数模板 template <class 类型名1,class 类型名2,...> 函数模板: 第4章 函数 4.6 函数模板 函数模板: 可以用来创建一个通用功能的函数,以支持多种不同形参,进一步简化重载函数的函数体设计。 函数模板的定义形式为: template <class 类型名1,class 类型名2,...> 返回类型 函数名 (形参表) { 函数体; } 模板参数表 意义: 对于功能完全一样,只是参数类型不同函数,能写一段通用代码适用于多种不同的数据类型,会使代码的可重用性大大提高,从而提高软件的开发效率。
4.6 函数模板 注意: template关键字表示声明的是模板。 C++语言程序设计教程 第4章 函数 4.6 函数模板 注意: template关键字表示声明的是模板。 < >中是模板的参数表,可以有一项或多项,其中的类型名称为参数化类型,是一种抽 象类型或可变类型。 class是类型关键字,也可以用typename作为关键字。 函数返回值类型可以是普通类型,也可以是模板参数表中指定的类型。 模板参数表中的参数类型可以是普通类型。 例如: //将add函数定义成了一个函数模板: template <class T> T add(T x, T y) { return x+y; }
C++语言程序设计教程 第4章 函数 4.6 函数模板 函数模板定义后,就可以用它生成各种具体的函数(称为模板函数)。在函数调用时,用函数模板生成模板函数实际上就是将模板参数表中的参数化类型根据实参实例化(具体化)成具体类型。这个过程称为模板的实例化。函数模板实例化分为显式实例化与隐式实例化。 (1) 显式实例化 函数名<具体类型名1,具体类型名2,..., 常量表达式> (实参表) 说明: 根据< >中给出的具体类型,用类似于函数调用实参与形参结合的方式,将模板参数表中的参数化类型一一实例化成具体的类型, 函数中的参数化类型也一一实例化。 如果模板参数表中有形式参数,还需要用常量表达式去初始化。 例如: 使用add<double>(8, 9)将T add(T x, T y) 实例化成: double add(double, double) 使用sum<int, 100> 将T sum() 实例化成: int sum(), size获得初值100;
C++语言程序设计教程 第4章 函数 4.6 函数模板 (2) 隐式实例化: 隐式实例化的格式为函数调用式,实例化过程是在实参与形参结合时,用实参的类型实例化形参对应的参数化类型。 例如: 使用add( ‘A’,‘B’) 将T add(T x, T y) 实例化成: char add(char, char) 注意: 使用隐式实例化无法初始化模板参数表中的普通类型的形参,如果模板参数表中使用普通类型参数,必须使用显式初始化。
4.6 函数模板 运行结果: 函数模板定义 模板函数调用 C++语言程序设计教程 第4章 函数 (4, 4) 17 (8, 8) 17 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 //****************************** * p4_8.cpp * * 函数模板 * *******************************/ #include<iostream> using namespace std; template <class T1,class T2> T1 add(T1 x, T2 y) { cout<<"("<<sizeof(T1)<<","<<sizeof(T2)<<")\t"; return x+y; } void main() cout<<add(9,8)<<endl; cout<<add(9.0,8.0)<<endl; cout<<add(9,8.0)<<endl; cout<<add(9.0,8)<<endl; cout<<add('A','A'-'0')<<endl; cout<<add(long double(8),9)<<endl; 函数模板定义 模板函数调用 运行结果: (4, 4) 17 (8, 8) 17 (4, 8) 17 (8, 4) 17 (1, 4) R
C++语言程序设计教程 第4章 函数 4.7 C++系统函数 C++不仅允许我们根据自己的需要定义函数,C++系统为我们提供了大量的标准库函数,这些函数原型在相应的头文件中,使用时要包含相应的头文件。 C++函数分类表 类别 原型 功能简述 C++头文件 C式头文件 数学 double sqrt(double x) 求x的平方根 cmath math.h int abs(int i) long labs(long n) double fabs(double x) 分别求整型数、长整型、浮点数的绝对值 double pow(double x, double y) double exp(double x) x的y次幂 e的x次幂 double log(double x) double log10(double x) ln x即logex log10x double sin(double x) double cos(double x) double tan(double x) 分别求x 的正弦值、 余弦值、 正切值; x为弧度数
4.7 C++系统函数 C++语言程序设计教程 第4章 函数 类别 原型 功能简述 C++头文件 C式头文件 数学 double asin(double x) double acos(double x) double atan(double x) 分别求x 的反正弦值、 反余弦值、 反正切值 cmath math.h 字符 int isalpha(int c),int isdigit(int c) c是否是字母,c 是否是数字 iostream ctype.h int tolower(int c),int toupper(int c) 将c转换成小写、大写字母 串 char *strcpy(char *s1, char *s2) string.h unsigned strlen(char *str) 内存操作 void *memcpy( void *d, void *s, int c ) 将s指向的内存区域的c个字节拷贝到d指向的区域 memory.h 类型 转换 int atoi(char *s) 将字符串转化成整数 stdlib.h char *itoa( int v, char *s, int x) 将整数v按x进制转成字符串s 时间 time_t time( time_t *timer ) 返回1970/1/1零点到目前的秒数 ctime time.h rand( unsigned seed ) int rand() 设置随机数的种子 产生0-RAND_MAX的随机数 其它 exit(int) 终止正在执行的程序 注意: 在C++中,旧式的C风格的头文件去掉了后缀.h,加上了前缀C,如stdlib.h在C++中变成了Cstdlib。 当使用了:#include <iostream> using namespace std; 时,许多头文件不需要包含了。在上面的表中,用 iostream表示不再需 要包含相应的C++风格的头文件。
4.7 C++系统函数 解释: 【例4-9】产生100个学生的某门功课的成绩,要求精确到0.5分。 随机函数 第4章 函数 4.7 C++系统函数 【例4-9】产生100个学生的某门功课的成绩,要求精确到0.5分。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 /********************************************* * p4_9.cpp * * 利用系统函数rand()随机产生学生成绩 * **********************************************/ #include<iostream> using namespace std; void main() { int x,i(0); srand(124); //设置种子 do x=rand(); if(x>=5&&x<=1000) x=(x/5)*5; cout<<x/10.0<<"\t"; i++; } } while (i<100); 随机函数 解释: 第10行设置随机数种子,使用rand()产生随机数时,以种子为基准,种子相同,每次产生的随机数也相同。
C++语言程序设计教程 第4章 函数 4.8 本章小结 ◇ 函数是一个功能独立的具有名称的程序代码。在程序的其他地方通过使用函 数名与传递参数对函数进行调用。 ◇ 一个函数只有先被声明或定义后,才能被调用。函数声明语句与函数定义中 的函数头基本相同,所不同的是:声明语句必须以分号结束,形参表中可以 为任意形参名或者不给出形参名。 ◇ 函数调用过程包括通过栈内存保存返回地址传递参数、执行函数体、返回三 个阶段。将实参的值传递给形参的这种传值调用方式不改变实参的值。 ◇ 递归函数适用于以递归方式定义的概念。 ◇ 带inline关键字定义的函数为内联函数,在编译时将函数体展开到所有调用 处。内联函数的好处是节省函数调用过程的开销。 ◇ 函数名相同,但对应形参表不同的一组函数称为重载函数。参数表不同是指 参数个数不同或在个数相同的情况下至少有一个参数对应类型不同。 ◇ 确定对重载函数中函数进行绑定的优先次序为精确匹配、对实参的类型向高 类型转换后的匹配、实参类型向低类型及相容类型转换后的匹配。 ◇ 对重载函数绑定时可能产生二义性,重载函数与带默认形参值的函数一起使 用时,有可能引起二义性。 ◇ 当既存在重载函数,又有函数模板,优先绑定重载函数,只有不能精确匹配 重载函数时,才实例化类模板。 ◇ 内联函数的展开、重载函数的绑定、类模板的实例化与绑定均在编译时进行。