1、第第2 2章章 函数函数第第2章章 函函 数数 2.1 函数的定义与使用函数的定义与使用2.2 函数调用机制函数调用机制 2.3 递归函数递归函数 2.4 默认参数的函数默认参数的函数 2.5 内联函数内联函数 2.6 函数重载函数重载 2.7 函数模板函数模板 2.8 使用使用C+系统函数系统函数 第第2 2章章 函数函数2.1 函数的定义与使用函数的定义与使用 在编辑一个大型程序时,即使各个函数的前后顺序不同,程序执行的开始点永远是主函数。主函数按照调用与被调用关系调用子函数。子函数如果与其它子函数又存在调用与被调用关系,当然还可以再调用其它子函数。 第第2 2章章 函数函数 在一对调用与
2、被调用关系中,我们把调用其它函数的函数称为主调函数,被其它函数调用的函数称为被调函数。在一个较为复杂的大型程序中,一个函数很可能同时扮演两种不同的角色主调函数与被调函数,即既调用别的函数(被调函数)又被另外的函数(主调函数)调用。函数一般应遵守先定义后调用的原则,否则应在调用函数中先进行原形说明。第第2 2章章 函数函数2.1.1 函数的定义一个完整的函数定义由两部分组成,即函数头与函数体。1. 函数定义的一般语法形式 (形式参数表) 说明性语句序列;实现函数功能的语句系列;第第2 2章章 函数函数 函数头是指上述格式中的 (形式参数表)。其中函数名可由函数设计者命名,可以是任何一个不重复的合
3、法的标识符(唯一的例外是,主函数必须命名为main)。 函数体是指上述格式中被一对大括号括起的复合语句部分。该函数所应实现的功能由相应的复合语句完成。第第2 2章章 函数函数 2. 函数的类型和返回值 函数头部分的类型标识符规定了函数的返回值类型。函数的返回值是返回给主调函数的处理结果,由函数体部分的return语句带回。例如,return value1。 无返回值的函数其类型标识符为void,不必有return语句。第第2 2章章 函数函数 3. 形式参数 函数头部分的形式参数(简称形参)表的内容如下:类型l 形参名1,类型2 形参名2,.,类型n 形参名n其中类型1、类型2、.、类型n是类
4、型标识符,表示形参的数据类型(int、double、float、char、bool等);形参名1、形参名2、.、形参名n是形参名(合法的自定义标识符)。形参是用来实现主调函数与被调函数之间的数据联系,通常将函数所处理的数据、影响函数功能的因素或者函数处理的结果作为形参。对于无形参的函数,其形参表的内容应该为空,但代表函数的小括号对不能省略。第第2 2章章 函数函数 函数在没有被调用的时候其形参只是一个符号,它标志着在形参出现的位置应该有一个什么类型的数据。函数在被调用时才由主调函数将实际参数(简称实参)赋予形参。从这一点上说,C+中的函数与数学中的函数概念极其相似。例如,我们都熟悉的如下数学中
5、的函数形式: f(x)=3x2+5x-2 这个函数只有当自变量x被赋以确定的值以后,才能计算出函数的值。第第2 2章章 函数函数 2.1.2 函数的调用 如果没有遵守先定义后调用的原则,调用函数之前先要在主调函数中声明函数原型。在主调函数中,或所有函数之前,按如下形式进行函数原型声明: (含类型说明的形参表);第第2 2章章 函数函数 如果是在所有函数之前声明了函数原型,那么该函数原型在本程序文件中任何地方都有效,也就是说,在本程序文件中任何地方都可以依照该原型调用相应的函数。如果是在某个主调函数内部声明了被调函数原型,那么该原型就只能在这个函数内部有效。 声明了函数原型之后,便可以按如下形式
6、调用子函数: (实参1,实参2,实参n)第第2 2章章 函数函数 实参列表中应给出与函数原型中形参个数相同、类型相符的实参,每个实参都可以是常量、变量或表达式三者之一。实参与实参之间用逗号作为分隔符。注意,这里的逗号不是顺序求值运算符。函数调用可以作为一条语句,这时函数可以没有返回值。函数调用也可以出现在表达式中,这时就必须有一个明确的返回值。函数调用示例如下。第第2 2章章 函数函数 【例2-1】 编写一个函数,把华氏温度转换为摄氏温度,公式为C=(F-32)*5/9,公式中F代表华氏温度,C代表摄氏温度。在主函数中提示用户输入一个华氏温度,并完成输入及输出,由函数完成转化功能。 程序代码如
7、下: #include float hstoss(float fHuashi);/原型说明 void main( ) 第第2 2章章 函数函数float fHuashi;coutendlfHuashi;cout华氏fHuashi度对应摄氏温度hstoss(fHuashi)度endl;/函数调用作为一个表达式出现在输出语句中float hstoss(float fHuashi)float fSheshi;fSheshi = (fHuashi-32)*5/9;return(fSheshi);第第2 2章章 函数函数程序运行结果为输入一个华氏温度值:68华氏68度对应摄氏20度第第2 2章章 函数函
8、数【例2-2】 编写一个求x的n次方的函数。分析:求x的n次方,实际是求x自乘n次的乘积。程序代码如下:#include double power(double dDishu,int iMi);/原型说明void main( )cout底数1.8 的 3 次幂是 power(1.8,3)endl; /函数调用作为一个表达式出现在输出语句中第第2 2章章 函数函数double power(double dDishu,int iMi)int iCount;double dResult = 1.0;for(iCount=1;iCount=iMi;iCount+)dResult = dResult*d
9、Dishu;return(dResult);程序运行结果为底数1.8 的 3 次幂是 5.832第第2 2章章 函数函数 【例2-3】 输入一个8位的二进制数,将其转换为十进制数后再输出。对于非法输入(除0和1以外的任何字符)应给出提示信息。 分析:将二进制数转换为十进制数,只要将二进制数的每一位乘以该位的权,然后相加。所以,如果输入00001101,则应输出13。第第2 2章章 函数函数可以直接引用例2-2中的函数power来求2的各次方。程序代码如下:#include double power(double dDishu,int iMi);/函数原型说明void main( )int iC
10、ount=8;int iValue=0;char cChar;bool bFlag=true; 第第2 2章章 函数函数cout0)cincChar;if(cChar!=1&cChar!=0)cout这不是一个二进制数!不能正确转换endl;bFlag=false;if(cChar=1)iValue=iValue+int(power(2,iCount-1); 第第2 2章章 函数函数iCount-;if(bFlag)cout十进制值为:iValueendl;double power(double dDishu,int iMi)int iCount;double dResult = 1.0;fo
11、r(iCount=1;iCount=iMi;iCount+)dResult = dResult*dDishu;return(dResult);第第2 2章章 函数函数 输入符合要求时(仅有字符0和1)的程序运行结果为 输入一个8位的二进制数:11010011 十进制值:211 输入不符合要求时(含有除0和1以外的任何字符)的程序运行结果为 输入一个8位的二进制数:110lao11 这不是一个二进制数! 不能正确转换第第2 2章章 函数函数 【例2-4】 编写一个函数可用来判断任给的一个正整数是否为素数(或质数)。再编写主程序完成输入、调用和输出。素数是指只能被1和它自身整除的数。 分析:素数的
12、逆定义就是,一但某数n能被2、3、.、n-1中的任何一个数除尽(只要除法中有一次余数为零),则n肯定不是一个素数;某数n若依次除以2、3、.、n-1,结果都除不尽(有余数),则n肯定是一个素数。第第2 2章章 函数函数程序代码如下:#include int iIsprime(int iNum);void main( )int iNum;coutiNum;if(iIsprime(iNum)=1) coutiNum 是一个素数.endl;第第2 2章章 函数函数else coutiNum 不是一个素数.endl;int iIsprime(int iNum)int iChushu;bool bFla
13、g=false;for(iChushu=2;iChushu=iNum-1;iChushu+)if(iNum%iChushu=0)bFlag=true; 第第2 2章章 函数函数break;if(bFlag=false)return 1;elsereturn 0;第第2 2章章 函数函数第一次程序运行结果为请输入一个正整数:3131是一个素数第二次程序运行结果为请输入一个正整数:119119不是一个素数第第2 2章章 函数函数 2.1.3 函数的参数传递 函数的参数用于在调用函数与被调用函数之间进行数据传递。在函数定义时,函数名后面括号内的参数称为形式参数(简称形参)。在函数被调用时,函数名后面
14、括号内的参数称为实际参数(简称实参)。第第2 2章章 函数函数 当函数未被调用时,C+编译系统并没有给函数的形参分配相应的内存空间,函数的形参更不会有实际的值。只有在函数被调用时,C+编译系统这时才为形参分配实际的存储单元,并将实参与形参结合。实参可以是常量、变量或表达式,其类型必须与形参相符。函数的参数传递,指的就是形参与实参结合(简称形实结合)的过程。形实结合的方式有值调用和引用调用两种。第第2 2章章 函数函数 1. 值调用 值调用是指当发生函数调用时,编译系统为形参分配相应的存储空间并且直接将实参的值复制给形参,这样形参和实参就各自拥有不同的存储单元,且形参是实参的副本。因此,值调用过
15、程是参数值的单向传递过程,一旦形参获得了与实参相同的值就与实参脱离关系,以后不论形参发生多大的改变,都决不会反过来影响到实参。前面2.1.2节中的四道例题均属于值调用方式。第第2 2章章 函数函数【例2-5】 从键盘输入两个整数,交换位置后输出(交换未成功)。#include void swap(int a,int b);void main( )int x,y;x=5;y=10;coutx=x y=yendl;swap(x,y); /交换x,y的值第第2 2章章 函数函数coutafter swapendl;coutx=x y=yendl;void swap(int a,int b)int t
16、;t=a;a=b;b=t;第第2 2章章 函数函数 程序运行结果为 x=5 y=10 after swap x=5 y=10 分析:从上面的程序运行结果可以看出,并没有达到交换的目的。这是因为采用的传递方式不合乎问题的要求。在单向值传递方式中,形参值虽确实进行了交换,但这些改变对实参不起任何作用。第第2 2章章 函数函数 执行主调函数中的函数调用语句swap(x、y)后,编译系统将实参x中的值5传递给虚参a,将实参y中的值10传递给虚参b;在swap函数中,a、b中的值完成互换;返回主函数时,实参x、y中的值不受虚参a、b的影响,并未进行交换。第第2 2章章 函数函数 2. 引用调用 显而易见
17、,值调用时参数的传递方式是实参单向复制其值给虚参,如果我们想使子函数中对形参所做的任何更改也能及时反映给主函数中的实参(即希望形参与实参的影响是互相的或称是双向的),又该怎么办呢?这就需要改变调用方式,即采用第二种参数传递方式引用调用。 引用是一种特殊类型的变量,可以被认为是某一个变量的别名。通过引用名与通过被引用的变量名访问变量的效果是一样的。这就是说,对形参的任何操作也就直接作用于实参。 第第2 2章章 函数函数 例如: int a,b; int &ra=a;/建立一个int型的引用ra,并将其初始化为变量a的一个别名 b=10; ra=b;/相当于a=b; 注意: 声明一个引用时,必须同
18、时对它进行初始化,使它与一个已存在的对象关联。第第2 2章章 函数函数 一旦一个引用被初始化后,就不能改变关联对象。换言之,一个引用从它被声明之后,就必须确定是哪个变量的别名,而且自始至终只能作为这一个变量的别名,不能另作他用。 形参也可以引用的方式出现在形参表中。引用作为形参的情况与变量的引用稍有不同。这是因为,形参的初始化不在类型说明时进行,而是在执行主调函数中的调用语句时,才为形参分配内存空间,同时用实参来初始化形参。 第第2 2章章 函数函数 【例2-6】 使用引用调用改写例2-5的程序,使两实参中的数真正进行互换。#include void swap(int &a,int &b);v
19、oid main( )int x,y;x=5;y=10;coutx=x y=yendl;swap(x,y); /交换x,y的值coutafter swapendl;coutx=x y=yendl; 第第2 2章章 函数函数void swap(int &a,int &b)int t;t=a;a=b;b=t;程序运行结果为x=5 y=10after swapx=10 y=5第第2 2章章 函数函数 分析:子函数swap的两个参数都是引用,当被调用时,它们分别被初始化成为a和b的别名。因此,在子函数swap中将两个参数的值进行交换后,交换结果可以返回主函数main。第第2 2章章 函数函数2.2 函
20、数调用机制函数调用机制 一个C+的源程序经过编译以后形成与源程序主名相同但后缀为.exe的可执行文件,且存放在外存储器中。当该 .exe的可执行程序被运行时,首先从外存将程序代码装载到内存的代码区,然后从main函数的起始处开始执行。程序在执行过程中,如果遇到了对其它函数的调用,则暂停当前函数的执行, 第第2 2章章 函数函数 保存下一条指令的地址(即返回地址,作为从子函数返回后继续执行的入口点),并保存现场(主要是一些寄存器的内容),然后转到子函数的入口地址,执行子函数。当遇到return语句或者子函数结束时,则恢复先前保存的现场,并从先前保存的返回地址开始继续执行。图2-1说明了函数调用和
21、返回的过程,图中标号标明了执行顺序。第第2 2章章 函数函数图2-1 函数调用和返回的示意图 第第2 2章章 函数函数 【例2-7】 求 设N=10,X=2、4、6、8,即求N事件中每次取2、4、6、8的组合数。 分析:这个问题需要反复利用两个公式: N! N!/X!/(N-X)! 设计两个函数:一个求整数阶乘的函数lJiecheng和一个求组合数的函数lComb。由主函数main调用lComb,lComb又调用lJiecheng。!()!XNNCXNX第第2 2章章 函数函数程序代码如下:#include long lJiecheng(int n)long rt=1;int i;for(i=
22、1;i=n;i+)rt=rt*i;return rt;long lComb(int N,int X)第第2 2章章 函数函数return lJiecheng(N)/lJiecheng(X)/lJiecheng(N-X);long lJiecheng(int n);long lComb(int N,int X);void main( )int iNum,x;do第第2 2章章 函数函数coutiNum;while(iNum10);for(x=2;x10;x+=2)coutC(iNum,x)=lComb(iNum,x)0) 这是一个递归形式的公式,在描述阶乘算法时,又用到了阶乘,只不过求阶乘的数在
23、逐次减1,因而编程时也自然采用递归算法。递归的结束条件是n=0。第第2 2章章 函数函数程序代码如下:#include long jc(int n)long rt;if(n0)coutData error!endl;else if(n=0) rt=1;/递归的结束条件else rt=n*jc(n-1);/以参数减1的方式继续递归return rt;第第2 2章章 函数函数void main( )int n;long result;docoutn;while(n=0);第第2 2章章 函数函数result=jc(n);/首次调用处coutn!=resultendl; 程序运行结果为输入一个正整数
24、:66!=720第第2 2章章 函数函数 【例2-9】有5个人坐在一起,问第1个人多少岁,他说比第2个人大2岁。问第2个人多少岁,他说比第3个人大2岁。问第3个人多少岁,他说比第4个人大2岁。问第4个人多少岁,他说比第5个人大2岁。最后问第5个人,他说是12岁。请问第1个人多少岁? 分析:这是一个递归问题。每一个人的年龄都比其后那个人的年龄大2,即第第2 2章章 函数函数age(1)=age(2)+2age(2)=age(3)+2age(3)=age(4)+2age(4)=age(5)+2age(5)=12可以用公式表示如下: 12 (n=5)age(n)= age(n+1)+2 (n5)第第
25、2 2章章 函数函数程序代码如下:#include int age(int n)int ss;if(n=5) ss=12;else ss=age(n+1)+2;return(ss);void main( )第第2 2章章 函数函数int age(int n);cout第一个人的年龄为age(1)岁endl;程序运行结果为第一个人的年龄为20岁第第2 2章章 函数函数2.4 默认参数的函数默认参数的函数 在函数定义中通过赋值运算就可指定默认参数值。一旦程序在调用该函数时,如果给出实参,则用实参初始化形参;如果没有给出实参,则C+编译系统自动以预先赋值的默认参数值作为传入数值。一般情况下都将调用该
26、函数时经常用到的常数作为默认参数值,这样在调用时就无需每次都写出该值了。指定默认参数值可以使函数的使用更为简单,同时也增强了函数的可重用性。 第第2 2章章 函数函数【例2-10】带默认形参值的函数例题。#include int mult(int n,int k=2)/第二个形参具有默认值 if(k=2)return (n*n);elsereturn (mult(n,k-1)*n);void main( )第第2 2章章 函数函数coutendlmult(5)endl;/* 形参n用实参来初始化为5,形参k采用默认值2,实现5*5*/coutmult(5,3)endl;/* 用实参来初始化形参
27、,n为5,k为3,实现5*5*5*/程序运行结果为25125第第2 2章章 函数函数 默认形参值必须按从右向左的顺序定义。在有默认值的形参右面,不能出现无默认值的形参。因为在调用时,实参初始化形参是按从左向右的顺序。例如:void try(int j=3,int k)/非法void try(int j,int k=2,int m)/非法void try(int j,int k=7)/合法void try(int j,int k=2,int m=3) /合法void try(int j=3,int k=2,int m=3)/合法第第2 2章章 函数函数默认形参值应该在函数原型中给出。例如:int
28、 multi(int x=2,int y=5);/默认形参值在函数原型中给出void main( )multi( );/并非无参调用,而是采用默认值,x取值2,y取值5int multi(int x,int y)return(x*y);第第2 2章章 函数函数 在相同的作用域内,默认形参值的说明应保持唯一。但如果在不同的作用域内,允许说明不同的默认形参。这里的作用域是指直接包含着函数原型说明的大括号所界定的范围。对作用域概念的详细介绍请参阅第5章。例如: int add(int x=2,int y=5); /全局默认形参值 void main( ) int add(int x=1,int y=
29、9); /局部默认形参值第第2 2章章 函数函数add( ); /此处调用时,采用局部默认形参值,x取值1,y取值9void func(void)add( ) /此处调用时,采用全局默认形参值,x取值2,y取值5第第2 2章章 函数函数2.5 内内 联联 函函 数数 内联函数(也称在线函数)是在C+中为提高程序运行效率而引入的。所有函数调用时都会产生一些额外的开销,主要是系统栈的保护、代码的传递、系统栈的恢复以及参数传递等。对于一些函数体很小但又经常使用的函数,由于被调用的频率非常高,这种额外开销也就很可观,有时甚至会对运行效率产生本质的影响。 第第2 2章章 函数函数 使用内联函数正是解决这
30、一问题的手段。 内联函数不是在调用时发生转移,而是在编译时将函数体嵌入在每一个调用语句处。这样就相对节省了参数传递、系统栈的保护与恢复等的开销。 内联函数在定义时使用关键字inline区别于一般函数,其语法形式如下: (含类型说明的形参表) 函数体 第第2 2章章 函数函数 例如: inline int mul(int a,int b) return a*b; 当程序中出现mul(2+3,4)的函数调用时,编译程序就会将其扩展为(2+3)*4。关键字inline是一个编译命令,编译程序在遇到这个命令时将记录下来,在处理内联函数的调用时,编译程序就试图产生扩展码。这样从使用者的角度来看,内联函数
31、在语法上与一般函数没有什么区别,只是在编译程序生成目标代码时才区别处理。第第2 2章章 函数函数 注意: 内联函数体内一般不能有循环语句和switch语句。 内联函数的定义必须出现在第一次被调用之前。 对内联函数不能进行异常接口声明。 如果违背了上述注意事项中的任一项,编译程序就会无视关键字inline的存在,像处理一般函数一样处理,不生成扩展代码。因此,只有很简单而使用频率很高的函数才被说明为内联函数。内联函数会扩大目标代码,使用时要谨慎。 第第2 2章章 函数函数【例2-11】内联函数例题。#include #include inline int max(int a,int b)if(ab
32、)return a;elsereturn b;第第2 2章章 函数函数void main( )int a,b,c,d;a=210;b=150;c=20;d=max(a,b);d=max(d,c);/编译时两个调用处均被替换为max函数体语句。coutThe biggest ofsetw(5)asetw(5)b第第2 2章章 函数函数setw(5)c is dendl;程序运行结果为The biggest of21015020is210第第2 2章章 函数函数2.6 函函 数数 重重 载载 函数的重载也称多态函数。C+编译系统允许为两个或两个以上的函数取相同的函数名,但是形参的个数或者形参的类型
33、不应相同,编译系统会根据实参和形参的类型及个数的最佳匹配,自动确定调用哪一个函数,这就是所谓的函数重载。第第2 2章章 函数函数 对于没有重载机制的C语言,每个函数必须有其不同于其它函数的名称,即使操作是相同的,仅仅数据的类型不相同,也需要定义名称完全不同的函数,这样就显得重复且效率低下。例如,定义求平方函数,就必须对整数的平方、浮点数的平方以及双精度数的平方分别用不同的函数名: int isq(int x,int y); float fsq(float x,float y); double dsq(double x,double y); 第第2 2章章 函数函数 程序在调用这三个不同类型的函
34、数时,是以名字加以区别的,需要记住并区别它们的名称。显然,这样就造成了代码的重复,使用起来也不方便,更不利于代码的维护。 对于具有重载机制的C+语言,允许功能相近的函数在相同的作用域内以相同函数名定义,因而使函数方便使用,便于记忆,也使程序设计更加灵活。仍以上例而言,在C+中只要用一个函数名即可,如square( ),然后以赋给此函数的参数类型来决定是要计算int型、float型,还是double型的数的平方。上例在C+中的定义形式如下:第第2 2章章 函数函数 int square(int x); float square(float x); double square(double x);
35、 要计算square(3)时,C+自动使用第一种形式;计算square(3.25)时,C+自动使用第三种形式;计算square(3.25f)时,C+自动使用第二种形式。 但是决不可以定义两个具有相同名称、相同参数类型和相同参数个数,只是函数返回值不同的重载函数。第第2 2章章 函数函数 例如,以下定义是C+不允许的: int func(int x); float func(int x); 由此可见,C+是按函数的参数表分辨相同名称的函数。如果参数表相同,则认为是错误的说明。 C+允许重载函数有数量不同的参数个数。当函数名相同而参数个数不同时,C+会自动按参数个数定向到正确的要调用的函数。下例说
36、明了C+的这一特性。 第第2 2章章 函数函数【例2-12】重载函数应用例题。#include int add(int x,int y)int sum;sum=x+y;return(sum);int add(int x,int y,int z)第第2 2章章 函数函数int sum;sum=x+y+z;return(sum);void main( )int a,b;a=add(5,10);b=add(5,10,20);couta=ab=bendl;程序运行结果为a=15b=35第第2 2章章 函数函数2.7 函函 数数 模模 板板 有很多时候,我们希望所设计的算法可以处理多种数据类型。但是,即
37、使这一算法被设计为重载函数,也只是使用相同的函数名,函数体仍然要分别定义。如下面两个求较小值的函数: int small(int x,int y) return xy?x:y; 第第2 2章章 函数函数 double small(double x,double y) return xy?x:y; 考察以上两个函数,有如下特点:只有参数类型不同,返回值类型不同,功能则完全一样。类似这样的情况,可以使用函数模板,从而避免函数体的重复定义。 第第2 2章章 函数函数 函数模板可以用来创建一个通用功能的函数,以支持多种不同形参,简化重载函数的函数体设计。它的最大特点是把函数所使用的数据类型作为参数。
38、函数模板的定义形式如下: 函数定义 第第2 2章章 函数函数【例2-13】定义一个能交换两个变量值的函数,要求用模板函数实现。#include template void swap(T &x,T &y)T z;z=y;y=x;x=z;void main( )第第2 2章章 函数函数int m=1,n=8;double u= -5.5,v=99.3;coutm=m n=nendl;coutu=u v=vendl;swap(m,n);/整型swap(u,v);/双精度型coutm与n,u与v交换以后:endl;coutm=m n=nendl;coutu=u v=vendl;第第2 2章章 函数函数
39、 程序运行结果为 m=1 n=8 u= -5.5 v=99.3 m与n,u与v交换以后: m=8 n=1 u=99.3 v= -5.5 分析:编译系统从调用swap( )时,根据实参的类型推导出函数模板的类型参数。 第第2 2章章 函数函数 于调用swap(m,n),由于实参m及n为int类型,所以,推导出模板中类型参数T为int。 当类型参数的含义确定后,编译器将以函数模板为样板生成一个函数: int swap(int &x,int &y) int z; z=y;y=x;x=z; 同样,对于调用swap(u,v),由于实参u、v为double类型,所以,推导出模板中类型参数T为double。
40、 第第2 2章章 函数函数 接着,编译器将以函数模板为样板,生成如下函数: double swap(double &x,double &y) double z; z=y;y=x;x=z; 因此,当主函数第一次调用swap( )时,执行的实际上是由函数模板生成的函数: int swap(int &x,int &y) 当主函数第二次调用swap( )时,执行的实际上是由函数模板生成的函数: double swap(double &x,double &y)第第2 2章章 函数函数2.8 使用使用C+系统函数系统函数 C+不仅允许我们根据需要自定义函数,而且C+的系统库中还提供了几百个常用函数可供程序
41、员使用。如求平方根函数(sqrt)、求浮点数或双精度数的绝对值函数(fabs)、对数函数(log)、指数函数(exp)、三角函数等都属于数学函数。输入/输出格式控制函数有setw( )、setprecision( )等。第第2 2章章 函数函数 由前面已学习的知识可知,调用函数之前必须先声明函数原型。系统函数的原型声明已经全部由系统提供了,并且已分类存在于不同的头文件中。程序员需要做的事情,就是用include指令嵌入相应的头文件,然后便可以使用系统函数了。例如,要使用基本输入/输出流函数cin( )/cout( )函数,就必须嵌入头文件iostream.h。 第第2 2章章 函数函数 若要使
42、用数学函数,如求绝对值函数abs( )、fabs( ),三角函数sin( )、cos( )、tan( ),开平方函数sqrt( ),对数值函数log( ),以e为底的指数函数exp( ),就要嵌入头文件math.h。同样,要使用输入/输出格式控制函数setw( )/setprecision( ),就要嵌入头文件iomanip.h。 第第2 2章章 函数函数 【例2-14】系统函数应用例题。 从键盘输入一个角度值,求出该角度的正弦值、余弦值和正切值。 分析:系统函数中提供了求正弦值、余弦值和正切值的函数sin( )、cos( )及tan( )函数的说明在头文件math.h中。同样,系统函数中也提
43、供了输入/输出格式控制函数,如输出域宽控制函数setw( )、输出精度控制函数setprecision( ),函数的说明在头文件iomanip.h中。因此,需要用到这些系统函数时,就必须将该函数所属的头文件以#include 或#include“头文件名”的形式写在程序代码开始部分。第第2 2章章 函数函数程序代码如下:#include #include #include const double pi=3.14159265;void main( )double a,b;cina;b=a*pi/180;第第2 2章章 函数函数 coutsin(a)=setw(10)sin(b)endl;cou
44、tcos(a)=setw(10)cos(b)endl;couttan(a)=setw(10)tan(b)endl;程序运行结果为输入:30sin(30)= 0.5cos(30)=0.866025tan(30)= 0.57735第第2 2章章 函数函数 充分利用系统函数,可以大大减少编程的工作量,提高程序的运行效率和可靠性。要使用系统函数,应该注意以下两点: 了解所使用的C+开发环境提供了哪些系统函数。不同的编译系统提供的系统函数有所不同。 确定要使用的系统函数的声明在哪个头文件中。这也可以在库函数参考手册或联机帮助中查到。 第第2 2章章 函数函数 例如,在MSDN Library Visua
45、l Studio 6.0中查找VC+6.0系统函数的分类列表:首先在“活动子集”栏选择Visual C+ Documentation,然后按如下路径选择:Visual C+ Documentation Using Visual C+ Visual C+ Programmers Guide Run-Time Library Reference Run-Time Routines by Category Run-Time Routines byCategory,如图2-2。该帮助系统中将函数按如下分类列出: 第第2 2章章 函数函数获取参数(Argument access)浮点支持(Floatin
46、g-point support)缓冲区操作(Buffer manipulation)输入与输出(Input and output)字节分类(Byte classification)国际化(Internationalization)字符分类(Character classification)内存分配(Memory allocation)数据转换(Data conversion)第第2 2章章 函数函数处理机与环境控制(Process and environment control)调试(Debug)查找与排序(Searching and sorting)目录控制(Directory control)字符串操作(String manipulation)错误处理(Error handling)系统调用(System calls)异常处理(Exception handling)时间管理(Time management)文件处理(File handling)第第2 2章章 函数函数图2-2 MSDN Library Visual Studio 6.0窗口