C++大学基础教程
第4章 函数
北京邮电大学电信工程学院
计算机技术中心
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-2-
程序设计中,把具有一定功
能的程序模块用函数或类来
实现
第4章 函 数
4.1 函数概述
4.2 函数定义
4.3 函数调用
4.4 内联函数
4.5 重载函数
4.6 默认参数值的函数
4.7 全局变量与局部变量
4.8 变量的存储类型
4.9 编译预处理
4.1 函数概述
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-5-
4.1 函数概述
1.函数简介
一般是将整个程序分为若干个程序模块
每个模块用来实现一个特定的的功能
C++中模块的实现
? 函数
?库函数
?自定义函数
? 类
? 技巧:要熟悉C++标准库提
供的类和函数集合。不要
事事从头做起,要尽可能
利用C++标准库提供的函数
而不是生成新函数,以便
减少程序开发的时间。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-6-
#include <iostream>
#include <cmath>
using namespace std;
int main() {
cout << "Enter Quadratic coefficients: ";
double a, b, c;
cin >> a >> b >> c;
if ( (a != 0) && (b*b - 4*a*c > 0) )
{
double radical = sqrt(b*b - 4*a*c);
double root1 = (-b + radical) / (2*a);
double root2 = (-b - radical) / (2*a);
cout << "Roots: " << root1 << " " << root2;
}
else
{
cout << "Does not have two real roots";
}
return 0;
}
调用函数 或主调函数
被调函数
库函数
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-7-
#include <iostream>
using namespace std;
float CircleArea(float r);
// main(): manage circle computation
int main() {
cout << "Enter radius: ";
float MyRadius;
cin >> MyRadius;
float Area = CircleArea(MyRadius);
cout << "Circle has area " << Area;
return 0;
}
// CircleArea(): compute area of radius r circle
float CircleArea(float r) {
const float Pi = 3.1415;
return Pi * r * r;
}
自定义函数
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-8-
2.数学库函数
C++语言提供的库函数中有一些是专门完成特定的数
学运算的,称为数学库函数。
实现常见的数学计算
例如: 求绝对值、平方根等。
调用数学函数: 函数名(参数1, … ,参数n)
例如: cout<<sqrt(900.0);
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-9-
2.数学库函数
数学函数库中的多数函数都返回double类型结果。
使用数学库函数,需要在程序中包含m ath.h头文
件,这个头文件在新的C++标准库中称为cmath。
函数参数可取常量、变量或表达式。
例: 如果c=13.0、d=3.0和f=4.0,则下列语句:
cout<<sqrt(c+d*f);
计算并显示13.0+3.0*4.0=25.0的平方根,即5.0。
4.2 函数定义
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-11-
4.2 函数定义及使用
main()
function1() function2()
function3()
function4() function5()
图4 -1 层次化的函数关系
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-12-
4.2 函数定义及使用
函数定义
函数原型
return语句
函数使用的三种方式
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-13-
1.函数的定义
包括接口和函数体
? 接口
?函数类型 函数名 形 式参数表
? 函数体
?完成函数功能的语句集合
?返回值
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-14-
函数定义语法形式
函数类型 函数名 (形式参数表)
{
函数体(变量声明和语句)
return 表达式;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-15-
函数定义
float CircleArea (float r) {
const float Pi = 3.1415;
return Pi * r * r;
}
函数体
返回值语句
局部变
量定义
形式参数
函数类型
函数名
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-16-
函数名
函数名是这个独立代码段(函数体)的外部标识符
函数定义之后,即可通过函数名调用函数(函数体代
码段)。
例:
cout << CircleArea(MyRadius) << endl;
函数名的构成可以是任何有效标识符
(一般多以反映函数功能的单词组合命名,以增
强程序的可读性)
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-17-
Sum()
// Sum(): compute sum of integers in a ... b
int Sum(int a, int b) {
int Total = 0;
for (int i = a; i <= b; ++i) {
Total += i;
}
return Total;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-18-
形式参数表
函数的形式参数表,简称形参表
形式:
(类型1 形式参数1, …,类型n 形式参数n)
形式参数表示主调函数和被调函数之间需要交换的信息
(1)传给被调函数的待处理的数据;
(2)控制被调函数操作执行的信息;
(3)被调函数执行的结果。
形式参数表从参数的类型、个数、排列顺序上规定了主调函
数和被调函数之间信息交换的形式。
如果函数之间没有需要交换的信息,也可以没有形参,形参
表内写void或空着。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-19-
Sum()
// Sum(): compute sum of integers in a ... b
int Sum(int a, int b) {
int Total = 0;
for (int i = a; i <= b; ++i) {
Total += i;
}
return Total;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-20-
PromptAndRead()
// PromptAndRead(): prompt and extract next
// integer
int PromptAndRead() {
cout << "Enter number (integer): ";
int Response;
cin >> Response;
return Response;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-21-
函数返回值
函数返回值类型 规定了函数返回给主调函数的值的
类型,也称为 函数类型 。
当需要函数向主调函数返回一个值时,可以使用
return语句,将需要返回的值返回给主调函数,故
称之为 返回值 。
需要注意的是由return语句返回的值的类型必须与
函数定义时指定的函数返回值类型一致。
如果不需要向主调函数返回值,函数可以定义成无
类型的,函数类型写成void,函数结束时也不必用
return语句。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-22-
Sum()
// Sum(): compute sum of integers in a ... b
int Sum(int a, int b) {
int Total = 0;
for (int i = a; i <= b; ++i) {
Total += i;
}
return Total;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-23-
函数体
函数体 是实现函数功能的代码部分
? 变量声明
? 完成函数功能的语句两部分
从组成结构看,函数体是由程序的三种基本控
制结构即顺序、选择、循环结构组合而成的。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-24-
Sum()
// Sum(): compute sum of integers in a ... b
int Sum(int a, int b) {
int Total = 0;
for (int i = a; i <= b; ++i) {
Total += i;
}
return Total;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-25-
函数是由函数名、函数类型、形参表
和函数体四部分组成的,使用时通过
函数名和参数表调用函数.
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-26-
例 4.1
编写一个函数cube,计算整数的立方。调用函数
cube计算从1到10相邻整数的立方差。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-27-
//计算整数的立方
#include <iostream>
using namespace std;
int cube( int ); // 函数原型声明
void main()
{
int last,nowcb;
last=1;
cout <<"the difference of cube: "<<endl;
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-28-
for ( int x = 2; x <= 10; x++ )
{
nowcb=cube( x );
cout <<nowcb-last << " ";
last=nowcb;
}
cout << endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-29-
//函数定义
int cube( int y )
{
return y*y*y;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-30-
例 4.2
在三个浮点中确定最大值,使用自定义函数
maximum完成。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-31-
// 在三个浮点中找出最大值
#include <iostream>
using namespace std;
float maximum(float, float, float ); // 函数原型声明
void main()
{
float a, b, c;
cout << "Enter three floating numbers: ";
cin >> a >> b >> c;
//调用 maximum函数, a,b,c为实际参数
cout << "Maximum is: " << maximum( a, b, c ) << endl; //函数调用
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-32-
// maximum函数定义
// 函数的形式参数 x, y , z
float maximum(float x, float y, float z)
{
float max;
max = x>=y?x:y;
max = max>=z?max:z;
return max;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-33-
2.函数原型
引用函数之前,要先指定函数的接口形式
? 函数原型
? 函数定义
函数原型声明格式:
函数类型 函数名(形式参数表);
例: int Max(int a, int b)
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-34-
函数原型
函数原型声明 使编译器获得关于函数名称、函
数类型、函数形参个数、形参类型和形参顺序
的信息。
函数调用时,编译器根据函数原型声明验证函
数调用正确与否。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-35-
函数原型
? 库函数的声明在相应的库的头文件中,使用库函数
时要包含相应的头文件。
例: #include <cmath>
调用数学库函数:
sqrt(…)
sin(…)
abs(…)
……
fstream
? File stream processing
assert
? C-based library for assertion
processing
iomanip
? Formatted input/output (I/O)
requests
ctype
? C-based library for character
manipulations
math
? C-based library for trigonometric
and logarithmic functions
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-36-
函数原型
? 程序中,如果调用自定义的函数,且函数定义在后,
调用在先,则必须在调用函数之前有函数原型声明。
void subfun1( …); //原型声明
main()
{
┆
sunfun1( …); //函数调用
┆
}
void subfun1( …) //函数定义
{
…
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-37-
函数原型
? 如果是函数定义在先,调用在后,则不必进行函数原
型声明。因为编译器已经从函数定义得到关于函数的
信息。
void subfun1( …) //函数定义
{
…
}
main()
{
┆
sunfun1( …); //函数调用
┆
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-38-
函数原型
? 源文件中,如果在所有函数定义体之外声明函数
原型,则该函数可被位于其原型声明之后的所有
函数调用。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-39-
void subfun1( …);//原型声明
main()
{
┆
sunfun1( …);//函数调用
┆
}
void sunfun2()
{
┆
sunfun1( …);//函数调用
┆
}
void subfun1( …)//函数定义
{
…
}
main()
{
void subfun1( …); //函数原型
声明
┆
sunfun1( …); //函数调用
┆
}
void sunfun2()
{
┆
sunfun1( …); //函数调用,┆
}
void subfun1( …)
{
…
}
错误,编译
器不识别
sunfun1标识
符。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-40-
3.return语句
return语句使程序执行流程从被调函数返 回主调
函数,有两种形式:
(1) 不 返回值的形式:
return;
(2) 返 回值的形式
return 表达式;
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-41-
例4.3
从键盘输入三角形的三个边长,计算三角形
的面积。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-42-
//给定三角形的三个边长,计算三角形的面积。
#include<iostream>
#include <cmath>
using namespace std;
void TriangleAreabySide(float a, float b, float c);
void main()
{
float a,b,c;
cout<<"input three numbers of the triangle sides:";
cin>>a>>b>>c;
TriangleAreabySide(a, b, c);
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-43-
//利用边长计算三角形的面积
void TriangleAreabySide(float a, float b, float c)
{
float area;
float s;
if (a+b<=c || a+c<=b || b+c<=a )
{
cout<<"Not a triangle!"<<endl;;
return;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-44-
else
{
s=(a+b+c)/2;
area=sqrt(s*(s-a)*(s-b)*(s-c));
cout<<"area of the triangle("<<a<<","<<b<<","<<c<<"):
"<<area<<endl;
return;
}
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-45-
例 4.4
利用随机数产生函数rand()产生的随机数模拟
考试成绩,统计成绩的平均值。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-46-
//统计分数均值
#include<iostream>
#include<cstdlib>
#include <ctime>
using namespace std;
int CalMean(int count);
void main()
{
int count;//数据个数
int mean;//均值
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-47-
//输入数据
cout<<"input number:";
cin>>count;
mean=CalMean(count);
cout<<"mean= "<<mean<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-48-
//计算均值
int CalMean(int count)
{
int score;//分数
int sum(0), mean;
srand( (unsigned)time( NULL ) );//种子
//累积求和
int k(0);
cout<<"the scores:"<<endl;
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-49-
while(k<=count)
{
score=rand()%100;
if (score<10)
continue;//假设没有低于 10分的,舍弃此数据。
else
{
cout<<score<<" ";
sum+=score;//累积分数
k++;//累积个数
}
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-50-
cout<<endl;
//计算平均值
if(count>0)
mean=sum/count;
else
mean=0;
return mean;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-51-
? 当被调函数只 需 要 把 一 个 数 值 结 果 返 回 给 主 调 函
数时,使用return语句返回比较合适。
? 如果使用return语句给主调 函数返回一个值,则
returnu语 句 必 须 返 回 一 个 与 所 在 函 数 的 函 数 类
型一致的表达 式 。 若 表 达 式 的 结 果 与 函 数 类 型 不
一致,不能通 过 编 译 , 需 要 作 强 制 类 型 转 换 , 将
表达式的类型强制成与函数类型。
例如,如果mean是float型,则return语句应为:
return (float)mean;
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-52-
4.函数使用的三种方式
(1) 函数语句
函数语句形式:
函数名(实参数表);
例如: TriangleAreabySide(a, b, c);
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-53-
实际参数表
实际参数表 ,简称为 实参表
实 参 表 是 按与被调函数形参表一一对应的格式组织的参数
表,即参数的类型、个数和排列顺序必须与被调函数声明的
形参数表严格一致。
实 际 参 数 表的各实际参数以逗号间隔,实际参数可以是常
量、变量和表达式(常量和变量都是最简单的表达式)。
在 执 行 到 函数调用语句时,由主调函数提供给被调函数的
数据和控制信息的参数(视为输入参数)必须具有确定值。
如果被调函数无形参,则实参表也是空的。
实际参数以数据值(值传递)或实际存储空间(地址传
递)提供了形式参数所需的内容。
实际编程中,从可读性考虑,一般使用变量(普通变量或
指针变量)作实际参数。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-54-
调用无参数的函数
#include<iostream>
using namespace std;
void DisplayMessage();
void main()
{
DisplayMessage (); //函数调用语句
}
void DisplayMessage ()
{
cout<<"只显示确定信息的简单函数不带参数 "<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-55-
( 2)函数表达式
?函数调用出现在一个表达式中,其形式:
函数名(实际参数表)
?这种表达式称为函数表达式,由函数名和实参表组
成。
?此时函数要使用return语句向主调函数返回一个确
定的值,参与它所在的表达式的运算。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-56-
例4.5
编写程序,实现坐标旋转公式:
θθ
θθ
cossin
sincos
00
00
yxy
yxx
+=
?=
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-57-
//实现坐标旋转公式
#include<iostream>
#include <cmath>
using namespace std;
void main()
{
const double PI=3.14;
int x,y;//旋转后坐标
int x0,y0;//原始坐标
int angle; //旋转角度
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-58-
//输入数据
cout<<"input point(x,y):";
cin>>x0>>y0;
cout<<"input angle of rotation:";
cin>>angle;
//计算旋转后的坐标
double theta=angle*PI/180;
x=x0*cos(theta)-y0*sin(theta);
y=x0*sin(theta)+y0*cos(theta);
//输出结果
cout<<"x="<<x<<endl;
cout<<"y="<<y<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-59-
?注意:
当函数调用出现在表达式中时,函数一定要通过
return语句返回一个与函数类型一致的值,作为
这个函数表达式的值参与相关计算。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-60-
(3)函数参数
利用函数的返回值作实际参数,再作函数调
用。
例如: m=max( a, max( b, c) );
实质上也是函数表达式形式调用的一种 。
4.3 函数调用
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-62-
4.3 函数调用
函数调用的执行机制
值调用
嵌套调用
递归调用
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-63-
1.函数调用的执行机制
系统在调用函数时,在特定内存空间中为函数
建立一个 活动记录 。
函数的活动记录存储
? 在函数内定义的每个变量的值
? 主调函数的断点地址
? 被调函数的返回值
(保存信息的具体内容与所使用的编译器有关 )
活动记录是函数正常执行、调用和返回的物理
基础。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-64-
?在程序执行过程中,如果遇到调用其它函数,则系
统暂停当前函数的执行,将下一条指令的地址( 返回
地址 , 当流程从被调函数返回当前函数后,从此地址
继续执行当前函数的语句 。亦称 断点地址 )存入活动
记录,流程转去执行被调函数。 系统为被调函数建立
一个活动记录,被调函数的形参和在被调函数内定义
变量将存入它的活动记录。 当执行完被调函数时,系
统撤销它的活动记录,流程重新回到主调函数,恢复
其断点处的运行状态,继续执行程序的后序语句,直
至结束。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-65-
void fun(…);
void main()
{
┆
fun(…);
┆
}
void fun(…)
{
┆
return;
}
main()
调f un()
结束
fun()
返回
保存:
返回地址
当前现场
恢复:
主调函数现场
返回地址
1
2
3
4
5
6
7
图4 -2 函 数调用和返回的过程
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-66-
例 4.6
从键盘输入屏幕上两点的坐标(x, y),计算两点
之间的距离。
(分析函数调用时活动记录 )
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-67-
//计算两点之间的距离
#include<iostream>
#include <cmath>
using namespace std;
float CalDistance(int x1, int y1, int x2, int y2);
int square(int x);
void main()
{
int x1,y1,x2,y2;//两点坐标
float dist; //两点间距离
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-68-
//输入数据
cout<<"input point 1 (x1,y1):";
cin>>x1>>y1;
cout<<"input point 2 (x2,y2):";
cin>>x2>>y2;
//计算距离
dist=CalDistance(x1,y1,x2,y2);
//输出结果
cout<<"distance between point ("<<x1<<","<<y1<<") and
point ("<<x2
<<","<<y2<<"): "<<dist<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-69-
//计算距离
float CalDistance(int xx1, int yy1, int xx2, int yy2)
{
int dx2,dy2;
dx2=square(xx2-xx1);
dy2=square(yy2-yy1);
float dist=sqrt(dx2+dy2);
return dist;
}
//计算一个数的平方
int square(int x)
{
return x*x;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-70-
运行结果:
input point 1 (x1,y1):10 20
input point 2 (x2,y2):110 120
distance between point (10,20) and point (110,120):
141.421
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-71-
void main()
{ int x1,y1,x2,y2;//两点坐标
float dist; //两点间距离
cout<<"input point 1 (x1,y1):";
cin>>x1>>y1;
cout<<"input point 2 (x2,y2):";
cin>>x2>>y2;
dist=CalDistance(x1,y1,x2,y2);
cout<<"distance between point ("<<x1<<","<<y1<<") and
point ("<<x2<<","<<y2<<"): "<<dist<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-72-
void main()
{ int x1,y1,x2,y2;//两点坐标
float dist; //两点间距离
cout<<"input point 1 (x1,y1):";
cin>>x1>>y1;
cout<<"input point 2 (x2,y2):";
cin>>x2>>y2;
dist=CalDistance(x1,y1,x2,y2);
cout<<"distance between point ("<<x1<<","<<y1<<") and
point ("<<x2<<","<<y2<<"): "<<dist<<endl;
}
y1
x1
x2
y2
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-73-
void main()
{ int x1,y1,x2,y2;//两点坐标
float dist; //两点间距离
cout<<"input point 1 (x1,y1):";
cin>>x1>>y1;
cout<<"input point 2 (x2,y2):";
cin>>x2>>y2;
dist=CalDistance(x1,y1,x2,y2);
cout<<"distance between point ("<<x1<<","<<y1<<") and
point ("<<x2<<","<<y2<<"): "<<dist<<endl;
}
y1
x1
x2
y2
dist
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-74-
void main()
{ int x1,y1,x2,y2;//两点坐标
float dist; //两点间距离
cout<<"input point 1 (x1,y1):";
cin>>x1>>y1;
cout<<"input point 2 (x2,y2):";
cin>>x2>>y2;
dist=CalDistance(x1,y1,x2,y2);
cout<<"distance between point ("<<x1<<","<<y1<<") and
point ("<<x2<<","<<y2<<"): "<<dist<<endl;
}
y1
x1
x2
y2
dist
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-75-
void main()
{ int x1,y1,x2,y2;//两点坐标
float dist; //两点间距离
cout<<"input point 1 (x1,y1):";
cin>>x1>>y1;
cout<<"input point 2 (x2,y2):";
cin>>x2>>y2;
dist=CalDistance(x1,y1,x2,y2);
cout<<"distance between point ("<<x1<<","<<y1<<") and
point ("<<x2<<","<<y2<<"): "<<dist<<endl;
}
y1
10
x1
x2
20
y2
dist
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-76-
void main()
{ int x1,y1,x2,y2;//两点坐标
float dist; //两点间距离
cout<<"input point 1 (x1,y1):";
cin>>x1>>y1;
cout<<"input point 2 (x2,y2):";
cin>>x2>>y2;
dist=CalDistance(x1,y1,x2,y2);
cout<<"distance between point ("<<x1<<","<<y1<<") and
point ("<<x2<<","<<y2<<"): "<<dist<<endl;
}
y1
10
x1
x2
20
y2
dist
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-77-
void main()
{ int x1,y1,x2,y2;//两点坐标
float dist; //两点间距离
cout<<"input point 1 (x1,y1):";
cin>>x1>>y1;
cout<<"input point 2 (x2,y2):";
cin>>x2>>y2;
dist=CalDistance(x1,y1,x2,y2);
cout<<"distance between point ("<<x1<<","<<y1<<") and
point ("<<x2<<","<<y2<<"): "<<dist<<endl;
}
y1
10
x1
x2
20
110
y2
120
dist
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-78-
//计算距离
float CalDistance(int xx1, int yy1, int xx2, int yy2)
{
int dx,dy;
dx=square(xx2-xx1);
dy=square(yy2-yy1);
float dist=sqrt(dx+dy);
return dist;
}
//计算一个数的平方
int square(int x)
{
return x* x;
}
10
xx1
20
110
yy1
120
xx2
yy2
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-79-
//计算距离
float CalDistance(int xx1, int yy1, int xx2, int yy2)
{
int dx,dy;
dx=square(xx2-xx1);
dy=square(yy2-yy1);
float dist=sqrt(dx+dy);
return dist;
}
//计算一个数的平方
int square(int x)
{
return x* x;
}
10
xx1
20
110
yy1
120
xx2
yy2
dx
dy
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-80-
//计算距离
float CalDistance(int xx1, int yy1, int xx2, int yy2)
{
int dx,dy;
dx=square(xx2-xx1);
dy=square(yy2-yy1);
float dist=sqrt(dx+dy);
return dist;
}
//计算一个数的平方
int square(int x)
{
return x*x;
}
10
xx1
20
110
yy1
120
xx2
yy2
dx
dy
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-81-
//计算距离
float CalDistance(int xx1, int yy1, int xx2, int yy2)
{
int dx,dy;
dx=square(xx2-xx1);
dy=square(yy2-yy1);
float dist=sqrt(dx+dy);
return dist;
}
//计算一个数的平方
int square(int x)
{
return x**x;
}
20
110
yy1
120
xx2
yy2
dx
dy
100
x
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-82-
//计算距离
float CalDistance(int xx1, int yy1, int xx2, int yy2)
{
int dx,dy;
dx=square(xx2-xx1);
dy=square(yy2-yy1);
float dist=sqrt(dx+dy);
return dist;
}
//计算一个数的平方
int square(int x)
{
return x**x;
}
20
110
yy1
120
xx2
yy2
dx
dy
100
x
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-83-
//计算距离
float CalDistance(int xx1, int yy1, int xx2, int yy2)
{
int dx,dy;
dx=square(xx2-xx1);
dy=square(yy2-yy1);
float dist=sqrt(dx+dy);
return dist;
}
//计算一个数的平方
int square(int x)
{
return x**x;
}
20
110
yy1
120
xx2
yy2
dx
dy
100
x
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-84-
//计算距离
float CalDistance(int xx1, int yy1, int xx2, int yy2)
{
int dx,dy;
dx=square(xx2-xx1);
dy=square(yy2-yy1);
float dist=sqrt(dx+dy);
return dist;
}
//计算一个数的平方
int square(int x)
{
return x**x;
}
20
110
yy1
120
xx2
10000
yy2
dx
dy
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-85-
//计算距离
float CalDistance(int xx1, int yy1, int xx2, int yy2)
{
int dx,dy;
dx=square(xx2-xx1);
dy=square(yy2-yy1);
float dist=sqrt(dx+dy);
return dist;
}
//计算一个数的平方
int square(int x)
{
return x**x;
}
20
110
yy1
120
xx2
10000
yy2
dx
dy
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-86-
//计算距离
float CalDistance(int xx1, int yy1, int xx2, int yy2)
{
int dx,dy;
dx=square(xx2-xx1);
dy=square(yy2-yy1);
float dist=sqrt(dx+dy);
return dist;
}
//计算一个数的平方
int square(int x)
{
return x**x;
}
20
110
yy1
120
xx2
10000
yy2
dx
dy
100
x
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-87-
//计算距离
float CalDistance(int xx1, int yy1, int xx2, int yy2)
{
int dx,dy;
dx=square(xx2-xx1);
dy=square(yy2-yy1);
float dist=sqrt(dx+dy);
return dist;
}
//计算一个数的平方
int square(int x)
{
return x**x;
}
20
110
yy1
120
xx2
10000
yy2
10000
dx
dy
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-88-
//计算距离
float CalDistance(int xx1, int yy1, int xx2, int yy2)
{
int dx,dy;
dx=square(xx2-xx1);
dy=square(yy2-yy1);
float dist=sqrt(dx+dy);
return dist;
}
//计算一个数的平方
int square(int x)
{
return x**x;
}
20
110
yy1
120
xx2
10000
yy2
10000
dx
dy
141.421
dist
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-89-
//计算距离
float CalDistance(int xx1, int yy1, int xx2, int yy2)
{
int dx,dy;
dx=square(xx2-xx1);
dy=square(yy2-yy1);
float dist=sqrt(dx+dy);
return dist;
}
//计算一个数的平方
int square(int x)
{
return x**x;
}
20
110
yy1
120
xx2
10000
yy2
10000
dx
dy
141.421
dist
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-90-
void main()
{ int x1,y1,x2,y2;//两点坐标
float dist; //两点间距离
cout<<"input point 1 (x1,y1):";
cin>>x1>>y1;
cout<<"input point 2 (x2,y2):";
cin>>x2>>y2;
dist=CalDistance(x1,y1,x2,y2);
cout<<"distance between point ("<<x1<<","<<y1<<") and
point ("<<x2<<","<<y2<<"): "<<dist<<endl;
}
y1
10
x1
x2
20
110
y2
120
141.421
dist
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-91-
void main()
{ int x1,y1,x2,y2;//两点坐标
float dist; //两点间距离
cout<<"input point 1 (x1,y1):";
cin>>x1>>y1;
cout<<"input point 2 (x2,y2):";
cin>>x2>>y2;
dist=CalDistance(x1,y1,x2,y2);
cout<<"distance between point ("<<x1<<","<<y1<<") and
point ("<<x2<<","<<y2<<"): "<<dist<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-92-
//计算距离
float CalDistance(int xx1, int yy1, int xx2, int yy2)
{
int dx2,dy2;
dx2=square(xx2-xx1);
dy2=square(yy2-yy1);
float dist=sqrt(dx2+dy2);
return dist;
}
//计算一个数的平方
int square(int x)
{
return x*
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-93-
返回值
函数输入数据流
输出数据流
函数能够从输入数据或参数
获得信息
参数
函数处理完的信息用
返回值或输出数据流
输出
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-94-
2. 函数的参数传递(值调用)
函 数 之 间 的 信 息 交 换 的 一种重要形式是函数的
参数传递,由函数的形式参数和实际参数实现。
函 数 在 没 有 被 调 用 时 , 函数的形式参数并不占
有实际的内存空间,也没有实际的值。C ++语言
中函数的参数传递方式分为两种:
·值传递
·地址传递
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-95-
值传递
如果函数的形式参数为普通 变量,当函数被调用
时 , 系统为这些形式参数分配内存空间,并用实际
参 数 值初始化对应的形式参数,形式上实际参数的
值 传 递给了形式参数。这就是函数调用时参数的值
传递。
值传递方式,实际参数和形 式参数各自占有自己
的内存空间; 参数传递方向只能由实际参数到形式
参 数 ;不论函数对形式参数作任何修改,对相应的
实际参数都没有影响。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-96-
例4.7
如果一个数的所有真因子(包括1,但不包括这
个数本身)之和正好等于这个数本身,则称此数
为完美数。例如:
6=1×2×3,而 1+2+3=6;
28=1×4×7=1×2×14, 而 1+2+4+7+14=28。
如何确定完美数,欧几里得发现,只要是一个素
数,则 一定是一个完美数 。编写程序找出最小
的5个完美数。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-97-
//寻找最小的五个完美数
#include <iostream>
#include<cmath>
using namespace std;
bool DecidePrime(unsigned int number);
unsigned int power(unsigned int x, unsigned int y);
void main()
{
unsigned int perfect_number;
unsigned int num,temp;
short n(2);
short counter(0);//计数器
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-98-
while (counter<5)
{ temp=power(2,n);
num=temp-1;
if(DecidePrime(num))
{ perfect_number=temp/2*num;
cout<<"n="<<n<<","<<"perfect
number="<<perfect_number<<endl;
counter++;
}
n++;
}
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-99-
//计算指数
unsigned int power(unsigned int x, unsigned int y)
{
unsigned int mul(1);
for(int i=1;i<=y;i++)
mul*=x;
return mul;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-100-
//判别素数
bool DecidePrime(unsigned int number)
{
unsigned int i, k;
k=sqrt(number);
for(i=2; i<=k; i++) //找 number的因数
{
if(number%i==0)
break;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-101-
if(i>=k+1) //判断 number是否被小于 number的数整除
return true;
else
return false;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-102-
例4.8
从键盘输入两整数,交换次序后输出。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-103-
//演示函数参数值传递单向性的例程
#include<iostream.h>
void swap(int a, int b);
int main()
{
int x(5), y(10);
cout<<"x="<<x<<" y="<<y<<endl;
swap(x,y);
cout<<"x="<<x<<" y="<<y<<endl;
return 0;
}
5
10
x 1024
y 1028
运行结果:
x=5 y=10
x=5 y=10
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-104-
void swap(int a, int b)
{
int t;
t=a;
a=b;
b=t;
}
5a2048
10b252
t2065
10
5
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-105-
3. 嵌套调用
C++的函数不能 嵌套定义
C++的函数可以 嵌套调用
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-106-
例4.9
编程计算一个空心圆柱体的体积。用函数
CylinderVolume()计算一个半径为r、高度为h
的圆柱体的体积:
hr
2
π
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-107-
//计算空心圆柱体的体积
#include <iostream>
#include <string>
using namespace std;
float DonutSize(float Outer, float Inner, float Width);
float CylinderVolume(float Radius, float Width);
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-108-
void main( )
{
cout<<"Outer edge donut radius:";
float OuterEdge;
cin>>OuterEdge;
cout<<"Hole radius: ";
float InnerEdge;
cin>>InnerEdge;
cout<<"Donut thickness:";
float Thickness;
cin>>Thickness;
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-109-
//计算空心圆柱体的体积
cout<<endl<<"Size of donut with radius "<<
OuterEdge<<endl;
cout<<" hole radius "<<InnerEdge <<endl;
cout<<" thickness "<<Thickness<<endl;
cout<<" is "<<DonutSize(OuterEdge, InnerEdge,
Thickness)<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-110-
//计算空心圆柱体体积
float DonutSize(float Outer, float Inner, float Width)
{
float OuterSize = CylinderVolume(Outer, Width);
float HoleSize = CylinderVolume(Inner, Width);
return OuterSize-HoleSize;
}
//计算圆柱体体积
float CylinderVolume(float r, float h)
{
const float pi=3.1415f;
return pi*r*r*h;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-111-
函 数 main ()
调用函数
DonutSize
结束
函数
DonutSize(...)
函 数 CylinderVolume(...)
的第一次执行
1
2 3
4
5
6
10
图4-4 函数嵌套调用示意图
调用函数
CylinderVolum
e
调用函数
CylinderVolum
e
7
函 数 CylinderVolume(...)
的第二次执行
8
9
11
12
13
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-112-
例4.10
用弦割法求方程
在x=1.5 附近的根。
01
23
=?? xx
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-113-
弦割法
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-114-
解:
分析:设 ,1)(
23
??= xxxf
)()(
)()(
01
0110
xfxf
xfxxfx
x
?
?
=
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-115-
//用弦割法求方程的根。
#include<iostream>
#include<cmath>
using namespace std;
float function(float x);
float xIntersection(float x1, float x2);
float eqRoot(float x1, float x2);
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-116-
void main()
{ float x0,x1,x;
float y0, y1;
do
{ cout<<"enter x0(1.5),x1:"<<endl;
cin>>x0>>x1;
y0=function(x0);
y1=function(x1);
} while(y0*y1>=0);
x=eqRoot(x0,x1);
cout<<"root :"<<x<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-117-
float function(float x)
{
float y= (x -1)*x*x -1;
return y;
}
float xIntersection(float x0, float x1)
{
float y=(x0*function(x1)-x1*function(x0))/(function(x1)-
function(x0));
return y;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-118-
float eqRoot(float x0, float x1)
{ float x, y, y0;
y0=function(x0);
do
{ x=xIntersection(x0,x1);
y=function(x);
if( y*y0>0)
{ y0=y;
x0=x;
}
else x1=x;
}while(fabs(y)>=0.000001);
return x;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-119-
4. 递归调用
递归函数 是函数体内有调用函数自己的语句或
通过其它函数间接调用函数自己的函数。
递归调用 是调用递归函数而形成的一种函数调
用方式。
递归函数用于实现数学中的递归问题比较直观
方便。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-120-
经典递归调用问题
阶乘定义式:
?
?
?
?×
=
)!1(
1
!
nn
n
0n
0n若
>
=
若
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-121-
int factorial( int n)
{
int fn
if(n==0)
fn = 1;
else
fn=n*factorial(n-1);
return fn;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-122-
#include <iostream>
using namespace std;
void main()
{
cout<<"enter a position integer:";
int n, n_fact;
cin>>n;
n_fact=factorial(n);
cout<<"the factorial of "<<n<<"is: "<<n_fact<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-123-
main()
调用函数
factorial(3)
1
n = 3
n_fact=?
17
结束
n = 3
n_fact=6
第一次调用函数
factorial(int n)
2
调用函数
factorial(2)
3
n = 3
fn=?
第二次调用函数
factorial(int n)
4
5
n = 2
fn=?
调用函数
factorial(1)
第三次调用函数
factorial(int n)
第四次调用函数
factorial(int n)
调用函数
factorial(0)
7
n = 1
fn=?
6 8
n = 0
fn=1
9
10
11
n = 1
fn=1
14
12
16
1315
n = 2
fn=2
n = 3
fn=6
n_fact=返回值 fn=3*返回值 fn=2*返回值 fn=1*返回值
return fn
return fnreturn fnreturn fn
图4.5 factorial函数递归调用过程示意图
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-124-
递归问题的求解实际分成两个阶段:
?化简问题的递推阶段;
?达到递归终止条件得到基本情况的结果,并逐
步回推结果阶段。
递归函数的主要两部分
?具有更简单参数的递归调用
?停止递归的终止条件(递归终止条件)
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-125-
例4.11
整数x和y的最大公约数是x和y能够整除的最
大整数。编写一个递归函数GcommonDivisor,返
回整数x和y的最大公约数。
整数x和y的最大公约数的递归定义如下:如
果y等于0,则GcommonDivisor(x,y)为x,否则
GcommonDivisor(x,y)为GcommonDivisor(y,
x%y),其中%是求模运算符。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-126-
//计算 x和 y的最大公约数 (递归函数 )
#include<iostream>
using namespace std;
int GcommonDivisor(int x, int y);
void main()
{ int x,y;
cout<<"input x,y:";
cin>>x>>y;
cout<<"the greatest common divisor of "<<x<<"and "<<y<<": "
<<GcommonDivisor(x,y)<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-127-
int GcommonDivisor(int x, int y)
{
if (y==0)
return x;
else
return GcommonDivisor(y, x%y);
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-128-
ABC
例4.12
汉诺塔问题
汉诺塔问题是著名的经典问 题之 一。 传说 远东 地区 有一
座庙,僧人要把盘子(64个)从第一个柱(A )移到第三个
柱(C ),这64个盘子从上至下逐渐增大。僧人移动盘子的
规则是:每次只能移动一个 盘子 ;柱 子上 任何 时候 都要
保持大盘在下,小盘在上的 放置 方式 ;移 动过 程中 ,可
以借助于第二个柱(B ) , 暂时 放置盘子。据传说,僧人
们完成这个任务时,世界的 末日 就来 临了 。十 九世 纪法
国数学家鲁卡斯指出,完成 这个 任务 ,僧 人们 移动 盘子
的 总 次 数 为 : 。假设一秒钟移动一个,每天24小
时不停地移动,需要5800亿年。
12
64
?
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-129-
解:
分析:
这个问题适合用递归法解决,递归函数为hanoi()。设A柱上
需要移动的盘子的个数为n,移动n个盘子可以利用递归法降阶
为移动n-1个盘子,具体步骤为:
步 骤1. 如 果 n=1, 则 盘 子 直 接 从 A柱 到 C柱 : A-->C; 执 行 步 骤 3;
否则执行步骤2。
步 骤2. 如 果 n>1, 则 将 盘 子 分 成 最 大 的 1个 和 其 它 ( n-1) 个 , 先
把(n -1)移到B柱上,再把最大的盘直接 移到 C柱 上, 然后 把B
柱上的n-1个盘移到C柱上。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-130-
即:
①将A柱上( n-1)个盘子:借助C柱,由A柱移到B柱: hanoi(n-
1,A,C,B);
②将最大的一个盘子由A柱移到C柱:move(A,C);
③再将B柱上( n-1)个盘子借助A柱移到C柱上: hanoi(n-
1,B,A,C)。
步骤3. 结束。
其中,函数move()为直接移动盘子函数。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-131-
//汉诺塔问题程序
#include"iostream"
using namespace std;
void move(char x,char z);
void hanoi(int n,char x,char y,char z);
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-132-
void main()
{
int num;
cout<<"请输入盘子数: ";
cin>>num;
cout<<"按 \"汉诺塔 \"的规则,把 "<<num
<<"个盘子从 a针搬到 c针的步骤是: "<<endl;
hanoi(num,'A','B','C');
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-133-
void move(char x, char z)
{
static int i;
i++;
cout<<i<<" : "<<x<<" → "<<z<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-134-
void hanoi(int n,char x,char y,char z)
(1){
(2) if(n==1)
(3) move(x,z);
(4) else {
(5) hanoi(n-1,x,z,y);
(6) move(x,z);
(7) hanoi(n-1,y,x,z);
(8) }
(9)}
递归运
行的层
次
运行语
句行号
递归工作栈状态
(返址、n值、
x值、y值、z值)
1 1,2,4,5 0,2,a,b,c
2 1,2,3,9
6,1,a,c,b
0,2,a,b,c
1 6 0,2,a,b,c
2 1,2,3,9
8,1,b,a,c
0,2,a,b,c
1 8,9 0,2,a,b,c
0栈空
4.4 内联函数
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-136-
4.4 内联函数
函数调用时,系统首先要保存主调函数的相
关信息,再将控制转入被调函数,这些操作增加
了程序执行的时间开销。
C++提供的内联函数形式可以减少函数调用
的额外开销(时间空间开销),特别是一些常用的
短小的函数适合采用内联函数形式。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-137-
内联函数
内联函数的定义形式:
inline 函数类型 函数名(形式参数表)
{
函数体
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-138-
例4.13
使用内联函数求三个整数中的最大值。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-139-
//内联函数例
#include<iostream>
using namespace std;
inline int max(int x, int y, int z)
{
return ((x>=y) ? (x>=z ? x : z) : (y>=z ? y : z));
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-140-
void main()
{
int a,b,c;
cout<<"enter three integers:"
cin>>a>>b>>c;
cout<<"Maximum is "<<max(a,b,c)<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-141-
内联函数之所以能够减少函数调 用时 的系 统 空 间
和时间开销,是因为系统在编译程序时就已经 把内联
函数的函数体代码插入到相应的函数调用位置 ,成为
主调函数内的一段代码,可以直接执行,不必 再转换
流程控制权。
这样的结构,自然节省了时间和空间开销,但 使得主
调函数代码变长。
一般是只把短小的函数写成内联函数。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-142-
注意:
(1)内联函数体不能包含循环 语句 、s witch语 句 和
异常接口声明。
(2)内联函数要先定义,后调用。因为编译 器 需 要
用内联函数的函数体代码替换对应的函数调用。
如果内联函数不符合要求,编译器就将内联函 数当一
般函数处理。
4.5 重载函数
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-144-
4.5 重载函数
重载函数也是函数的一种特殊情况。
C++允许几个功能类似函数同名,但这些同名
函数的形式参数必须不同,称这些同名函数为
重载函数 。
例:
int max(int x, int y){return x>y?x:y; }
float max(float x, float y) {return x>y?x:y; }
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-145-
?各重载函数形式参数的不同是指参数的 个数、类型或
顺序彼此不同,不包括参数标识符的不同。如:
① int max(int a, int b){return a>b?a:b;}
② int max(int x, int y){return x>y?x:y; }
③ int max(int x, int y, int z)
{return (x>y?x:y)>z? (x>y?x:y):z; }
①②实际是一个函数,如果写在同一个文件中,编译
时会出现编译错误。若①③或②③在同一个文件中可
形成重载函数。编译器将以形式参数个数的不同来认
定和区分重载函数。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-146-
#include<iostream>
using namespace std;
int min(int x, int y)
{
return x<y?x:y;
}
double min(double x, double y)
{
return x<y?x:y;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-147-
void main()
{
int ia(10),ib(20);
double da(0.1), db(0.5);
cout<<"minimum of integer . is "<<min(ia,ib)<<endl;
cout<<"minimum of double is "<<min(da,db)<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-148-
在使用重载函数时需要注意下面三点:
(1) 编译器不以形式参数的标识符区分重载函数。例
int max(int a, int b);
int max(int x, int y);
编译器认为这是同一个函数声明两次,编译时出错。
(2) 编译器不以函数类型区分重载函数。
float fun(int x,int y);
int fun(int x,int y);
如果函数名和形式参数表相同,只是函数类型不同,编译器同
样认为它们是同一个函数声明两次,编译出错。
(3) 不应该将完成不同功能的函数写成重载函数,破坏程序
的可读性。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-149-
重载函数常用于实现功能类似而所处理的数据
类型不同的问题,
4.6 默认参数值的函数
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-151-
4.6 默认参数值的函数
具有默认参数值的函数是一种特殊的函数形
式, C++允许函数的形式参数有默认值。
例如:计算圆面积的函数:
double CircleArea(double radius=1.0)
{
const double PI=3.14;
return PI*radius*radius;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-152-
调用具有默认参数值的函数时,如果提供 实际参数
值,则函数的形参值取自实际参数;如果不提 供实际
参数值,函数的形参采 用默认参数值。例如调用
CircleArea函数:
#include<iostream>
using namespace std;
void main()
{
cout<<CircleArea(10.0)<<endl; //提供实际参数值
cout<<CircleArea()<<endl; //不提供实际参数值
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-153-
默认参数值函数如果有多个 参数 ,而其中只有部分参数具有默认
值,则这些具有默认值的参 数值 应该位于形参表的最右端。或者
说,形参表中具有默认参数 值的 参数的右边,不能出现没有默认
值的参数。例如:
int CuboidVolume(int length=1, int width=1, int height=1); //正确
int CuboidVolume(int length, int width=1, int height=1); //正确
int CuboidVolume(int length, int width, int height=1); //正确
int CuboidVolume(int length=1, int width, int height=1); //错误
int CuboidVolume(int length, int width=1, int height); //错误
int CuboidVolume(int length=1, int width=1, int height); //错误
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-154-
?如果默认参数值函数是先声明,后定义的,则在
声明函数原型时就指定默认参数值。
?如果函数定义在先(无需原型声明),则在函数定
义的形参表中指定默认值。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-155-
例4.14
编写具有默认函数值的函数,计算直角三角形的
面积。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-156-
//使用默认形式参数值的函数编写计算直角三角形面积的程序
#include <iostream>
using namespace std;
float areaRATriangle( int side1 = 3, int side2 = 4);
void main()
{ cout<< "The area of default right-angled triangle(3,4) is: “
<< areaRATriangle()<<endl;
cout << "The area of right-angled triangle(6,4) is:“
<< areaRATriangle(6)<<endl;
cout<< "The area of right-angled triangle(6,8) is:"
<< areaRATriangle(6, 8)<< endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-157-
// 计算直角三角形面积
float areaRATriangle( int side1, int side2)
{
return side1* side2 /2.0;
}
4.7 全局变量和局部变量
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-159-
4.7 全局变量与局部变量
在程序中,根据变量定义的位置编译器把它
们分为局部变量和全局变量。在函数内部定义的
变量、函数的形式参数为 局部变量 ,在函数外部
定义的变量为 全局变量 。
由于变量定义的位置不同,所以变量起作用
的范围也不同。我们把程序中一个标识符起作用
的范围称为其 作用域 。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-160-
局部变量
局部变量 包括在函数体内定义的变量和函数的
形式参数,它们的作用域就在函数体内,只能在
本函数内使用,不能被其它函数直接访问。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-161-
#include <iostream>
using namespace std;
int fun1(int x, int y);
int fun2(int x, int y);
void main()
{
int a,b;
cout<<"input a,b:"
cin>>a>>b;
cout<<fun1(a,b) <<endl;
cout <<fun2(a,b) <<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-162-
int fun1(int x, int y)
{
int n;
n=x*x+y*y;
return n;
}
int fun2(int x, int y)
{
int m;
m=x*x-y*y;
return m;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-163-
局部变量能够随其所在的函数被调用而被分配 内存空
间,也随其所在的函数调用结束而消失(释放 内 存 空
间),所以使用这种局部变量能够提高内存利 用 率 。
同时,由于局部变量只能被其所在的函数访问 ,所以
这种变量的数据安全性也比较好(不能被其它 函 数 直
接读写)。局部变量在我们实际编程中使用 频 率 最
高。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-164-
全局变量
一个C++的源文件(.cpp)可以由多个函数组
成,我们可以在函数外部定义变量,即全局变
量。全局变量能够被位于其定义位置之后的所
有函数(属于本源文件的)共用。也就是说全
局变量起作用的范围是从它定义的位置开始至
源文件结束。
全局变量的作用域是整个源文件。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-165-
#include<iostream>
using namespace std;
int maximum;
int minimum;
void fun(int x,int y int z)
{
int t;
t=x>y?x:y;
maximum=t>z?t:z;
t=x<y?x:y;
minimum=t<z?t:z;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-166-
void main()
{
int a,b;
cout<<"input data a,b:";
cin>>a>>b;
fun(a,b);
cout<<"maximum="<<maximum<<endl;
cout<<"minimum="<<minimum<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-167-
全 局 变 量 在程序执行的整个过程中,始终位于全
局 数 据 区 内固定的内存单元;如果程序没有初始
化全局变量,系统会将其初始化为0。
在 定 义 全 局变量的程序中,全局变量可以被位于
其 定 义 之 后的所有函数使用(数据共享),这给
编 程 者 带 来很大方便;但也因此带来数据安全性
和 程 序 可 读性不好的缺点。在我们实际编程时一
般不要随意使用全局变量。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-168-
作用域
程序中标识符的作用域也就是标识符起作用的
范围,标识符只能在其起作用的范围内被使用。
从标识符起作用的范围上划分,作用域主要分为
全局作用域和局部作用域两种。从标识符在程序
中所处的位置,又可区分作用域为块作用域、函
数作用域、类作用域和文件作用域。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-169-
块作用域
块作用域是指标识符起作用的范围为块内范
围,在块内定义的标识符具有块作用域。这个
块,可以是复合语句的块,也可以是函数定义的
函数体块。块内定义的局部变量的作用域是从变
量定义起至本块结束。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-170-
#include<iostream>
using namespace std;
void main()
{ int a, b;
cout<<"input a,b:"
cin>>a>>b;
if (a<b)
{ int t;
t=a;
a=b;
b=t;
}
int c=a*a-b*b;
cout<<a<<"*"<<a" - "<<b<<"*"<<b
<<"="<<c<<endl;
}
t的作用域 a和 b的
作用域
c的作用域
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-171-
函数作用域
函数作用域
? 语句标号标识符的作用域为函数范围
? 函数体内定义的语句标号标识符具有函数作用域,
即语句标号的作用域是其所在的函数范围 。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-172-
文件作用域
文件作用域 也即全局作用域,指标识符的作用
域为文件范围。
在源文件所有函数之外声明或定义的标识符具
有文件作用域,全局变量和函数名(不包括在
其它函数内部声明原型的函数名)具有全局作
用域,起作用的范围是从声明或定义点开始,
直至其所在文件结束。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-173-
#include<iostream>
using namespace std;
int counter1, counter2, counter3;
char color;
inline void getColor()
{
cout<<"input color of ball(r-red, y-yellow, g-green):";
cin>>color;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-174-
void displayResult ()
{
switch(color)
{
case 'r':
counter1++;
cout<<"The number of red balls :
"<<counter1<<endl;
break;
case 'y':
counter2++;
cout<<"The number of yellow balls :
"<<counter1<<endl;
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-175-
case 'g':
counter3++;
cout<<"The number of green balls :
"<<counter1<<endl;
break;
default:
break;
}
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-176-
void main()
{
for(int k=0;k<10;k++)
{
getColor();
displayResult();
}
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-177-
4.可见性
标识符的 可见性 ,是研究标识符在其作用域内
能否被访问到的问题。
标识符在其作用域内,能被访问到的位置称其
为 可见的 ,
不能被访问到的位置称其为 不可见的 。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-178-
#include<iostream>
using namespace std;
double pi=3.1415926;
double BallVolume(double radius)
{
double volume=pi*radius*radius*radius*4/3;
//此处使用的是全局变量 pi
return volume;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-179-
double CircleArea(double radius)
{
double area=pi*radius*radius; //此处使用的是全局变量 pi
return area;
}
float CircleArea( float radius)
{
float pi=3.14f;
float area=pi*radius*radius;
//此处使用的是局部变量pi,全局变量pi在此处不可见。
return area;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-180-
void main()
{
float r;
cout<<"input radius: ";
cin>>r;
double dr=(double) r;
cout<<"Ball volume: "<<BallVolume(dr)<<endl;
cout<<"Circle area: "<<CircleArea(dr)<<"(double)"<<endl;
cout<<"Circle area: "<<CircleArea(r)<<"(float)"<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-181-
C++规定:内层标识符与外层标识符同名时,内层标
识符可见,外层标识符不可见。 对 于 变 量 也 即 内 层 变
量屏蔽外层同名变量。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-182-
如果函数内的局部变量与全局变量同名,且在函数
内一定要使用这个同名全局变量,可以用全局作用域
符号(::)指定要访问的全局变量。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-183-
#include<iostream>
using namespace std;
double pi=3.1415926;
void BallVolume(double radius)
{
double volume=pi*radius*radius*radius*4/3;
//此处使用的是全局变量 pi
cout<<"Ball volume: "<<volume<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-184-
void CircleArea( float radius)
{
float pi=3.14f;
float area=pi*radius*radius;
//此处使用的是局部变量 pi,全局变量 pi在此处不可见。
cout<<"Circle area: "<<area<<"(float)"<<endl;
area=::pi*radius*radius; //此处使用的全局变量 pi
cout<<"Circle area: "<<area<<"(double)"<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-185-
void main()
{
float r;
cout<<"input radius: ";
cin>>r;
BallVolume(r);
CircleArea(r);
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-186-
关于标识符的使用
(1)标项识符应该先声明,后使用。
(2)在同一作用域中,不能声明同名的标识符。
(3)对于两个嵌套的作用域,如果某个标识符在外层
中声明,且在内层中没有同一标识符的声明,则该标
识符在内层可见;如果在内层作用域内声明了与外层
作用域中同名的标识符,则外层作用域的标识符在内
层不可见。
4.8 变量的存储类型
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-188-
4.8 变量的存储类型
一 个 变 量 在 内 存 中 存 在 的时间取决于变量的存
储类型
C++程序中使用的变量可分为四种存储类型:
?auto
? register
?Extern
?static
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-189-
auto型变量
auto型变量包括函数体内部定义的局部变量、
函数的形式参数,称为自动变量。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-190-
#include<iostream>
using namespace std;
int max(int x, int y) { return x>y?x:y; }
void main()
{
int a,b;
cout<<"input a,b:";
cin>>a>>b;
cout<<max(a,b)<<endl;
}
auto int a,b;
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-191-
自动变量因其所在的函数被调用而产
生,随其所在的函数调用结束而消失。因为
自动变量存于动态存储区,不长时间占据固
定内存,有利于内存资源的动态使用,故程
序中大量使用的都是自动变量。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-192-
register型变量
寄存器型变量
定义格式:
register 类型标识符 变量标识符 ;
例:
register int counter;
访 问 寄 存 器 中 的 变 量 要 比访问内存中的变量速
度快,但由于寄存器数量有限,如果设置过多的
register型变量,编译器将把这些变量按普通局
部变量处理,依然放在内存空间
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-193-
extern关键字
多个源文件程序结构
在 多 文 件 程 序 结 构 中 , 如果一个文件中的函数
需要使用其它文件里定义的全局变量,可以用
extern关键字声明所要用的全局变量。
//file1.cpp
int x,y;
void main()
{
…
}
//file2.cpp
extern int x,y;
void fun()
{
…
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-194-
extern关键字
关键字e xtern提供了多文件程序结构中不同源文
件共享数据的一个途径。但实际编程中,共享数
据时要注意数据的安全性问题。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-195-
静态变量
声明变量时加上关键字 static,则 该变量为静态变
量,定义格式:
static 类型标识符 变量标识符 ;
静态变量
? 静态局部变量
static加在局部变量的定义前,则生成静态局部变量
? 静态全局变量
static加在全局变量定义前,则形成静态全局变
量。
静态变量在程序运行期间一直在 静 态 存 储 区 占 有 固
定的存储空间。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-196-
#include<iostream>
using namespace std;
int squareMean(int data)
{
static int sum(0);
static int counter(0);
sum+=data*data;
counter++;
return sum/counter;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-197-
void main()
{
int number(1);
while(number!=-1)
{
cout<<"input number:";
cin>>number;
cout<<"the mean of square is:"<<
squareMean(number)<<endl;
}
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-198-
静态局部变量在其所在的函数第一次被调用时,
被初始化为一定的值,系统仅对它们作一次初始化。
如果程序中指定初始化值,则初始化为程序指定值;
如果程序在定义它们时未指定初始值,则系统将静态
局部变量初始化为0。此后静态局部变量能够保持其
在前一次函数调用结束时所获得的值,直到下次函数
调用时被修改。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-199-
静态全局变量只能在其定义文件 中 使 用 , 不 能 被 多 文
件程序结构的其它文件访问。除 此 之 外 , 静 态 全 局 变
量在定义它的文件中的用法与前面 介绍的不加static
的全局变量一样使用。静态全局 变 量 的 数 据 安 全 性 好
于普通全局变量,但不便于多文 件 程 序 结 构 不 同 文 件
之间的数据共享,实际编程时要 根 据 具 体 问 题 决 定 是
否加static。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-200-
生存期
一个变量在内存中存在的时间为变量的 生存
期。
不 同 的 存 储 类 型 的 变 量 的生存期不同,按生存
期可以将变量分为两种:
? 静态生存期变量
? 全局变量,静态变量
? 动态生存期变量
? auto型变量,register型变量
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-201-
生存期
具有静态生存期的变量在程序运行期间一直存在。
具有动态生存期的变量的取决于所在的函数是否被调
用,函数被调用,动态生存 期的 变量 存在 ;函 数调 用结
束,动态生存期变量消失。
具有静态生存期的变量,如果定义时未指定初始值, 则
系统将它们初始化为0;
具有动态生存期的变量,如果未作初始化,则为随机
值。在循环结构中,使用具 有动 态生 存期 的变 量时 ,要
特别注意是否需要先赋值的 问题 ,例 如迭 代求 和( 和变
量初始化为0)或乘积(积变量初始化为1)等。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-202-
多文件结构
用C ++编写处理比较复杂的问题的程序,一般 采
用多文件结构程序,即由多个源程序分别完成不
同的子功能,这样的程序组织便于管理和维护。
C++既支持面向过程的程序设计,也支持面向对
象的程序设计。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-203-
多文件结构
在面向过程的程序设计中,为方便开发和维护程
序,将程序的功能分成相对独立的子功能,然后
用不同的源程序分别实现各个子功能。在实现每
个子功能时,一般可使用两个源文件:一个是包
含程序自定义类型、符号常量定义和函数的声明
等的头文件(*.h文件),一 个是 由实 现算 法 的 函
数构成的.c pp文件(即由函数定义构成的文
件)。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-204-
加入多文件结构图
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-205-
例4.15
模拟投币的程序,每次结果应为正面或反
面,打印HEADS或TAILS。让程序投币100次,计
算每面出现的次数并打印结果。程序应调用一个
Flip函数,该函数无参数,返回0表示正面,1表
示反面。如果程序真实,模拟投币,则每一面出
现的次数应近似相等。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-206-
//Mainprog.cpp
//模拟投币程序
#include<iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include"flip.h"
using namespace std;
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-207-
void main()
{
cout<<"now let's begin:"<<endl;
int k(1);
int Hcounter(0),Tcounter(0);
srand( (unsigned)time( NULL ) );
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-208-
while(k<=100)
{ if(!Flip())
{
cout<<"HEADS(k="<<k<<") ";
Hcounter++;
}
else
{ cout<<"TAILS(k="<<k<<") ";
Tcounter++;
}
if(k%4==0)
cout<<endl;
k++;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-209-
cout<<"total:"<<k-1<<endl;
cout<<"HEADS:"<<Hcounter<<endl;
cout<<"TAILS:"<<Tcounter<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-210-
//flip.h
int Flip();
//Flip.cpp
//投币
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include"flip.h"
using namespace std;
int Flip()
{
return rand()%2;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-211-
在多文件结构程序中,函数的声明和函数定
义、使用分别放在*.h文件和*.cpp文件中,使用
时要在cpp文件的最开始使用include将要用的头
文件包含进来。
4.9 编译预处理
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-213-
4.9编译预处理
编译器在编译源程序之前,先由预处理器处
理预处理指令
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-214-
预处理命令 #include
格式
#include<头文件名>
#include“头文件名 ”
功能
将一个头文件嵌入(包含)到当前文件
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-215-
预处理命令 #define
格式
#define 标识符 字符串
功能
把字符串命名为标识符(用标识符代表字符串)
标识符可以表示符号常量或宏名,编写源程序时
代替 ”字符串 ”出现在程序中,编译时又被替换
为 ”字符串 ”内容。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-216-
预处理命令 #undef
格式
#undef 标识符
功能
撤销前面用#define定义的标识符
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-217-
预处理命令 #ifdef
格式
#ifdef 标 识符
语句
#endif
功能
如果已定义了 “标识符 ”,则编译 “语句 ”
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-218-
预处理命令 #ifndef
格式
#ifndef 标识符
语句
#endif
功能
如果未定义了 “标识符 ”,则编译 “语句 ”
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-219-
预处理命令
#if #elif #else
#endif
功能
条件编译指令,如果某个表达式成立,则编译相应
的语句。几种形式是:
#if-#endif、
#if-#else-#endif、
#if-#elif-#elif-…#endif
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-220-
预处理命令
#if #elif #else #endif
格式
#if 常量表达式
语句
#endif
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-221-
预处理命令
#if #elif #else #endif
格式
或:
#if 常量表达式1
语句1
#else
语句2
#endif
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-222-
预处理命令
#if #elif #else #endif
格式
或:
#if 常量表达式1
语句1
#elif常量表达式2
语句2
┇
#else
语句n
#endif
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-223-
例4 .16
从键盘输入数据完成复数运算(加、减、乘、
除、模、辐角)。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-224-
//myFile.cpp
#include<iostream>
using namespace std;
#include "complex.h"
void main()
{
char ch;
do
{
displayMessage();
cin>>ch;
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-225-
switch(ch)
{
case '1': Add();
break;
case '2': Minus();
break;
case '3': Multiply();
break;
case '4': Divide();
break;
case '5': Modul();
break;
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-226-
case '6': amplitude();
break;
default:
break;
}
cout>>"continue?(y/n)"
cin>>ch;
}while(ch=='y');
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-227-
inline void displayOperation()
{
cout<<"Enter your choice:">>endl;
cout<<"add(1)">>endl;
cout<<"minus(2)">>endl;
cout<<"multiply(3)">>endl;
cout<<"divide(4)">>endl;
cout<<"modul(5)">>endl;
cout<<"amplitude(6)">>endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-228-
//complex.h
#ifndef COMPLEX_H //防止此文件被多次嵌入
#define COMPLEX_H
#define DEBUG_COMPLEX //调试时为显示某些中间结果; //在最终版
本,如果不需要,可将此句注释掉。
#define PI 3.14 //定义符号常量 PI,用 PI表示常量 3.14
#define ANGLE180 180 //定义符号常量
void Add();
void Minus();
void Multiply();
void Divide();
void Modul();
void amplitude();
#endif
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-229-
//complex.cpp
#include<iostream>
#include<cmath>
#include"complex.h"
using namespace std;
void Add()
{
double real1,real2,imag1,imag2;
cout<<"input real part and imaginary part of 1rd complex
number:";
cin>>real1>>imag1;
cout<<"input real part and imaginary part of 2rd complex
number:";
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-230-
cin>>real2>>imag2;
double real,imag;
real=real1+real2;
imag=imag1+imag2;
cout<<"sum:"<<real<<"+"<<imag<<"i"<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-231-
void Minus()
{ double real1,real2,imag1,imag2;
cout<<"input real part and imaginary part of 1rd complex
number:";
cin>>real1>>imag1;
cout<<"input real part and imaginary part of 2rd complex
number:";
cin>>real2>>imag2;
double real,imag;
real=real1-real2;
imag=imag1-imag2;
cout<<" difference:"<<real<<"+"<<imag<<"i"<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-232-
void Multiply()
{ double real1,real2,imag1,imag2;
cout<<"input real part and imaginary part of 1rd complex
number:";
cin>>real1>>imag1;
cout<<"input real part and imaginary part of 2rd complex
number:";
cin>>real2>>imag2;
double real,imag;
real=real1*real2-imag1*imag2;
imag=imag1*real2+imag2*real1;
cout<<" product:"<<real<<"+"<<imag<<"i"<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-233-
void Divide()
{ double real1,real2,imag1,imag2;
cout<<"input real part and imaginary part of 1rd complex
number:";
cin>>real1>>imag1;
cout<<"input real part and imaginary part of 2rd complex
number:";
cin>>real2>>imag2;
double real,imag;
double temp;
temp=real2*real2+imag2*imag2;
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-234-
#ifdef DEBUG_COMPLEX
cout<<"temp="<<temp; //调试版本显示 temp,便于分析错误
#endif
if(temp>0.000001)
{
real=(real1*real2+imag1*imag2)/temp;
imag=(imag1*real2-imag2*real1)/temp;
cout<<"quotient:"<<real<<"+"<<imag<<"i"<<endl;
}
else
cout<<"divided by 0"<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-235-
void Modul()
{
double real,imag;
cout<<"input real part and imaginary part:";
cin>>real>>imag;
double modual=sqrt(real*real+imag*imag);
cout<<"modual:"<<modual<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-236-
void amplitude()
{ double real,imag;
cout<<"input real part and imaginary part:";
cin>>real>>imag;
double amp;
if(fabs(real)>0.000001)
{ amp=atan(imag/real); }
else amp=PI/2;
amp=ANGLE180*AMP/PI;//弧度转换为度显示
cout<<"amplitude:"<<amp<<endl;
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-237-
#define指令还可以定义带参数的宏 ,例如 :
#include<iostream>
using namespace std;
#define MIN(a,b) (a<b?a:b)
void main()
{
int x,y;
cout<<”input x,y:”;
cin>>x>>y;
cout<<”minimum:”<<MIN(x,y);
}
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-238-
总结
本 章 详 细 介 绍 了 关 于 函数的知识,重点介绍了对函数的
引 入 、 定 义、原型声明、函数的参数及函数调用,函数是
实 现 算 法 的基本单位,函数的设计和使用是学习程序设计
必须掌握的基本知识。
函数还有一些特殊的形式,如递归函数、内联函数、 具
有 默 认 参 数值的函数等。递归函数便于递归问题的实现,
尤 其 适 合 数学上的一些递归问题。用递归函数实现算法,
优 点 是 思 路简单;缺点是函数执行效率一般不高,因为频
繁 的 递 归 调用造成的进栈出栈很花时间。内联函数等函数
的特殊形式,使我们在利用函数实现算法时更方便灵活。
本章介绍的变量的存储类型以及标识符的作用域等概
念,也是我们必须掌握的基本知识。
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-239-
作业
2005-4-28
北京邮电大学电信工程学院计算机技术中心
-240-