C 实例教学-基础知识(3)

2008-02-23 05:34:22来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

在本节以前给出的程式都是由一个函数组成的,实际上,一个真正的C 程式几乎都包含若干个由用户自定义的函数。
在下面的几个程式实例中,都调用了由用户定义的函数。

4.1 三次方程求根
按照Cardan公式,计算三次方程x3 px q=0的一个实根的公式为:


在计算实根xr的程式中,把计算一个浮点数的立方根的程式作为一个用户定义的函数,而在主程式中两次调用这个函数。


程式代码如下:
// program 4_1
#include<iostream.h>
#include<math.h>
float cuberoot(float); // 自定义函数的原型
void main()
{
float p,q,xr;
cout<<"Input paramerters p,q:";
cin>>p>>q;
float a=sqrt(q/2*q/2 p/3*p/3*p/3);
xr=cuberoot(-q/2 a) cuberoot(-q/2-a); // 调用cuberoot函数
cout<<endl<<"The real root of the equation is "<<xr;
}
float cuberoot(float x) // 自定义函数代码从这里开始
{
float root,croot;
const float eps=1e-6;
croot=x;
do
{
root=croot;
croot=(2*root x/(root*root))/3;
}
while(abs(croot-root)>eps);
return croot;
}

------------------------------------------------------------------------------------

4.2 四元排序程式
对于任意的四个整数,经过处理,令其按从大到小的顺序排序。
// program 4_2.cpp
#include<iostream.h>
void swap(int &,int &); // 自定义函数原型
void main()
{
int a,b,c,d;
cout<<"Input 4 integers: ";
cin>>a>>b>>c>>d;
if(a<b)swap(a,b); // 调用自定义函数 swap()
if(b<c)swap(b,c);
if(c<d) swap(c,d);
if(a<b) swap(a,b);
if(b<c) swap(b,c);
if(a<b) swap(a,b);
cout<<endl<<a<<" "<<b<<" "<<c<<" "<<d;
}
void swap(int &x,int &y) // 自定义函数代码从这里开始
{
int temp;
temp=x;
x=y;
y=temp;
}
程式运行结果如下:
Input 4 integers: 17 25 8 41
41 25 17 8

说明:
这是个简单的程式。函数swap()是void类型,这表明他没有返回值,任何用户定义函数都必须指明返回类型,无返回值的函数必须说明为void类型。
函数swpa()有两个整型参数,在参数表中的符号'&'表明参数x和y是“引用参数”。这和上节中的float x不同,后者称为赋值参数。引用参数和赋值参数在使用中主要有下面几点区别:
1)在形参表中增加符号'&'
2)在调用该函数时,引用参数对应的实参必须是指定类型的变量。如调用swap(a,b)中的实参a,b都是整型变量。而在上节中的赋值参数却是个表达式,表达式的念是包含了常量、变量和一般的表达式。比如在本例中,写成swap(a b,a-c)或swap(41,a*a d*d)等都是错误的。
引用参数和引用调用是C 语言的一种重要功能,假如swap()的两个参数说明为赋值形参,会出现什么情况?
本例中的排序并不是个好的方法,实际上,关于排序有很多好的算法可用。

注意:在编程中函数的作用是太重要了,但是,函数有利于编程、用利于程式结构,却不能提高程式的效率。相反,在函数调用时由于要保留“现场”以备在函数计算完成返回时继续运行原来的程式。因此,函数的每次调用,系统都要额外在时间和空间上付出一些代价。
为了解决这个问题,C 语言配置了内联函数“inline",其具体规定是:
1)在函数定义和说明之前增加关键字inline:
inline void swap(int &x,int &y){......}
2)调用内联函数和调用非内联函数的调用效果完全相同,不同的是,在对源程式进行编译时,对于非内联函数,其程式代码只有一份,在每个调用语句处,通过转移控制语句来运行,然后返回。
对于内联函数处理则不同,他是把函数体的程式代码放到每个调用该函数的语句处。例如能够把swap()函数说明为内联的:
inline void swap(int &x,int &y)
{
int temp;
temp=x;
x=y;
y=temp;
}
经过这一改变,主函数仍不变,通过编译生成的目标程式将使swap()的函数体程式代码在其中出现6次。
由此,我们能够看出,采用内联函数一方面在源程式的编写中仍可因使用函数而使程式简短清楚,另一方面在执行中又不必付出调用过程的时间和空间代价,唯一的代价是目标程式加长了。
一般说,调用次数不多的函数或函数体规模较大的函数,其调用代价相对能够忽略,不宜采内联函数。而函数体积短小且又频繁被调用的函数能够说明为内联函数。
例如对于更多个整数的排序算法,假如需要调用swap()的话,那么swap()函数应该说明为内联的。

-----------------------------------------------------------------------------------------

4.3 ”三色冰激淋“程式
这是个由冰激淋商提出来的问题,有28种颜色的原料,能够组合成多少种三色冰激淋。一种答案是有 19656=28*27*26种,称为(28,3)的排列数A 3 28 ,他是把同样三种颜色的不同排列数也计算进来了,另一答案是3276=19656/3!种,称为(28,4)的组合数。其中28为元素数,3为选择数。下面的程式对输入的元素数和选择数计算相对应的排列数和组合数。
// program 4_3.cpp
#include<iostream.h>
long factorial(int number); // 函数原型,功能计算C(m,n)=A(m,n)/n!
void main()
{
int i,selections,elements;
cout<<"Number of selections: ";
cin>>selections;
cout<<"Out of how many elements: ";
cin>>elements;
double answer=elements;
for(i=1;i<selections;i ) // 计算排列数A(m,n)=m*(m-1)*...*(m-n 1)
answer*=--elements;
cout<<"A("<<elements selections-1<<","<<selections<<")=";

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: 教您理解复杂的C/C 声明

下一篇: C 实例教学-基础知识(2)