第五章 C++函数
5.2 函数的调用
5.2.1函数递归调用(P113)
函数直接或间接调用自身.
传递参数4
阶乘fact(4)
返回24---------4*fact(3)----- 传递参数3
4*6
返回6
例5.1 求 n!的阶乘
编程求出1~13中每一个数的阶乘值 JC.CPP
#include<iostream.h>
long f(int n);
void main( )
{
int n;
long p;
cout<<"\n";
cout<<" 程序运行结果:\n";
cout<<"\n";
for(n=1;n<=13;n++)
{
p=f(n);
cout<<" "<<n<<"!="<<p<<"\n";
}
}
long f(int n) // n h
{ // 5 5*f(4)
long h; // 4 4*f(3)
if (n>1) h=(long)n*f(n-1); // 3 3*f(2)
else h=1; // 2 2*f(1)
return h; // 1 1
}
5.3 函数原形与头文件(P117)
1.程序结构:头文件保存函数原型,程序文件实现(定义)函数,主程序测试函数。
2.函数:原型说明、定义、调用。
3.数据流程 :变量--->实参--->形参--->计算--->返回--->显示。
4.函数原形(prototype),例如:double Area(double r);
例5.4 求圆面积Area(P119)
1: //头文件Area.h
2: double Area(double r) //原形说明
4: //程序文件Area.cpp
5: #include "Area.h" //包函头函数
7: #define PI 3.14 16
9: double Area(double r) //定义函数 3.传给形参 r
11: return r*r*PI; //函数计算
14: //主程序文件 Areat.cpp
16: #include"Area.h"
23: cin>>radius; //变量radius取值
28: area=Area(radius); //调用函数 2.实参radius 5.返回值给area
29: cout<<"area="<<area // 6.显示area
5.4 函数调用中的参数传递(P122)
例如:
......
void main( ){
int a=3,b=4; //形参
add(a,b); //函数调用
......
}
int add(int x,int y) //函数定义 实参
......
程序运行时实际参数的值(a=3,b=4)
顺序对应传递给形式参数(x, y).
5.4.2 数组参数
例5.5 计算参数数组中的元素和
3:int sum(int array[ ],int size); //函数说明
8:int sum(int array[ ],int size ) //函数定义 3.传给形参
11:for(int i=0;i<size;i++)s+=array[i]; //求和计算
12:return s; //返回s
21:int v1[ ]={1,2,3,4,5}; // 1.数组初始化
22:cout<<sum(v1,5); // 2.实参 6.显示
5.4.3 可选参数(P127)
例如:int f(int a,char b, char c='Z',char *s="READY");
其中:c,*s有默认值
5.5 内联(inline)函数
inline int add2(int n){return n+2;}
函数调用可直接用函数体代码。
5.6 函数重载与名字混成
1.函数重载(P129)
同名函数,参数数量或类型不同
int add(int a,int b){ };
long add(long a,long b){ };
2.名字混成(P130)
例:外部名字同 add
内部名字不同 add+参数信息
5.7 函数和变量的作用域(P131)
5.7.1函数的作用域:全局,文件作用域(static)。
5.7.2 变量的作用域和生存期(P132)
1.全局变量:定义于函数外部;
2.局部变量:定义于函数内部,
auto自动,register寄存器,static静态。
5.8 函数模板(P135)
例如:函数 Max(x,y)的类型说明
int Max(int a,int b){return a>b? a:b;}
long Max(long a,long b){return a>b? a:b;}
例如:Max模板
template<class T> //T是虚拟类型参数
T Max(Tx,Ty) //用实参的实际类型替代虚拟类型
{
return(x>y)?x:y;
};
例如:cout<<Max(3,5);
实参的实际类型int,生成函数实例如下:
int Max(int a,int b){return a>b? a:b;}
预处理
1. 简单的宏定义(P)
形式:#define 宏标识符 字符串
功能:用常量表达式替换程序中的宏标识符.
例
#define PI 3.14149
#include<stdio.h>
main()
{
int r=2.0,s;
s=PI*r*r;
}
2. 带参数的宏定义(P)
形式:#defin 宏标识符(形式参数表)
程序中 宏标识符(实际参数表)
功能:程序编译时实际参数的值(a+b,c+d)
顺序对应传递给形式参数( m, n).
例如:#define MAX(m,n) ((m>n)? m:n)
程序中 x=MAX(a+b,c+d);
编译后 x=((a+b)>(c+d))? (a+b):(c+d)
3. 文件包含(P)
形式:#include"头文件名"
#include<头文件名>
功能:程序文件包含另一文件的内容.
" " 自建的头文件,按标准方式检索.
< > 检索顺序:源程序文件目录,标准方式检索.
例如:#include"point.h"
#include<iostream.h>
习题五(P142)
5-5 求多边形周长(参考P123, 实验P100)
1.2 |
3.4 |
|
5.6 | p0 | p1 |
7.8 | p3 | p2 |
double arrownd(double x[ ],double y[ ],int p);
//程序文件:实现(定义)函数arrownd.cpp
#include "arrownd.h"
static double distance(double x1,double y1,double x2,double y2)
{return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));}
double arrownd(double x[ ],double y[ ],int p)
{
double s=0;
for(int j=0;j<p-1;j++)
s+=distance(x[j],y[j],x[j+1],y[j+1]);
s+=distance(x[p-1],y[p-1],x[0],y[0]);
return s;
}
//主程序:测试函数arrowndz.cpp
#include <iostream.h>
#include "arrownd.h"
void main( )
{
x[ ]={1.2,3.4,3.4,1.2};
y[ ]={5.6,5.6,7.8,7.8};
cout<<arrownd(x[ ],y[ ],4);
}
实验六 函数与程序设计(P41)
2. 用递归调用对数组求和(P45)
a[5]
元素 | a[0]
a[size-5] |
a[1]
a[size-4] |
a[2]
a[size-3] |
a[3]
a[size-2] |
a[4]
a[size-1] |
地址 | a | a+1 | a+2 | a+3 | a+4 |
内容 | 1 | 2 | 3 | 4 | 5 |
int sumAll(int a[ ],int size) //3. 形参 a[ ], size
{
if(size= =1)
return a[size-1] ;
return a[0]+ sumAll(a+1, size-1) ; //4. 计算
//或return a[0] ;
return a[sinz-1]+ sumAll(a[size-1],size-1) ;
}
void main( )
{
int d[ ] = {1,2,3,4,5}; //1. 数组 d[ ]
cout<<sumAll(d, sizeof(d)/sizeof(d[0]));
//2. 实参 数组d, 元素个数size
//5. 输出显示
}
6.1 指针概念和指针变量的定义
6.1.1 指针的概念
例如:字符串“ABCD”的地址(P145)
起始地址 | 3690 | A |
3691 | B | |
3692 | C | |
3693 | D | |
3694 | \0 |
1. 指针:存储特定类型数据的地址。(P146)
2. 空指针:地址值为0,符号常量NULL。
3. 指针类型:指针所指数据的类型。
4. 无类型(Void)指针:指向任何类型的数据。
6.1.2 指针变量的定义和初始化(P146)
格式:类型 * 变量名;
例如:double d, * pd=&d;
表明:pd是指向某一双精度变量的指针变量。
地址 | 存储单元 |
指针变量 | 变量 |
pd | d |
3690 | 1.234 |
6.1.3 常值指针(P147)
地址 |
存储单元 |
指针变量 |
变量 |
常值指针 | 常值数据 |
指针不变 | 数据不变 |
* const s | const * s |
6.2 指针的基本操作(P148)
6.2.1 赋值:char c='X',* s = &c;
6.2.2 取变量的地址:操作符 &(取地址)
int k,*p;
p=&k;
合并:int k,* p = &k;
6.2.3 间接访问:操作符 *(P148)
int *pd,d;
pd=&d;
*pd=99;
cout<< *pd <<' '<< d;
间接访问 直接访问
* & k=3;
相互抵消
地址 | 存储单元 |
指针变量 | 变量 |
pk | k |
3690 | 3 |
6.2.4 判断空指针(P149)
如果p是空指针,则……
if(P= =0)...
if(P= =NULL)...
if(!P)...
6.2.5 指针相减(P149)
int n,m[12],*p1=&m[5],*p2=&m[10];
n=p2-p1;
6.2.6 指针移动操作符(P150)
移动n个单位:+、-、+ =、- =
例如:int m[12],*p1=&m[6];
p1- =3;
m[12]
元素 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
地址 | 3690 | 3691 | 3692 | 3693 | 3694 | 3695 | 3696 | 3697 | 3698 | 3699 | ||
内容 | 333 | 666 | ||||||||||
指针 | p1 | p1 |
移动1个单位:++、- -
6.2.7 指针表达式的副作用(P151)
+ +
继续当 变量操作 |
(+ +
pk)
操作结果 视同变量 |
(pk +
+)
操作结果 视同常量地址 |
+ +
不能当 变量操作 |
6.2.8 指针类型的强制转换(P152)
short i=258;
char * p=(char *) &i; //用指针表示
char p=(char) i //用变量名表示(P33)
6.3 指针与数组
6.3.1 一维数组元素的指针访问方式(P156)
1. 数组名指向0号元素。
int A[10]; //*A 等同 A[0]
2. 设:int A[10], * pa[i]=A;
则:* (pa+i), pa[i] 访问同元素A[i]
3. 等价关系:
A[i]-----*(A+i)
A[0]-----*(A+0)-----*A
4. 不同方式访问数组元素(P156)
int s[ ]={0,1,2,3,4,5},*p=s;
cout<<*p<<p[1]<<*(p+2)<<s[3]<<p[4]<<*(s+5);
输出:012345
6.3.2 多维数组元素的指针访问方式(P157)
例如:int B[6][8];
看成六个单元的一维数组:B[0] B[1] B[3] B[4] B[5]
每个单元又是8个单元的一维数组:B[0]有元素b[0] b[1]..........b[7]
6.3.3 指向数组的指针(P159)
例如:int w[3][4];
int (*p1)[3][4]=&w; //指向整个二维数组
int (*p2)[4]=w; //指向二维数组的首行
int (*p3)=&w[0][0]; //指向二维数组的首元素
6.3.4 字符指针与字符串(P160)
char *p2="string2"; //p2指向首元素s
例6.2 设计函数STRLEN
6:while(*d++)p++; //字符串d
12:cout<<STRLEN("ABCDEF");
6.3.5 指针数组与命令行参数(P161)
1. 指针数组:数组的每个元素都是指针。
例如:int * ip[10];
double * dp[5][8];
2. 命令行参数(P162)
C:\>TREE A:\
例 6.4 显示命令参数(P163)
//文件名doscomm.cpp
3: #include<stdlib.h>
5: int main(int argc,char * argv[ ])
//argc:命令行参数个数
//argv[ ]:全路径程序文件名,命令行参数
9: cout<<"argv["<<i<<"]:">>argv[i]<<endl;
执行:D:\DATA>DOSCOMM aaa bbb ccc
显示:argv[0]: D:\DATA\DOSCOMM.EXE
argv[1]: aaa
6.4 指针与函数
6.4.1 指针参数(P167)
1. 传指针:形参指针和实参指针指向同一数据。
例如:(P168)
int addTo(int data, int * agg) //3.形参
{return *agg+=data;} //4.计算
int total=0; //1.变量
addTo(5,&total); //2. 实参, 5.返回
cout<<total; //6.显示
cout<<endl<<addTo(8,&total);
2. 定义常值指针:传递给被调用函数的数据只读不能改。(P168)
例如:
void f(const int U[ ]) //定义常值指针
{
cout<<U[3]; //数据只读不能改
U[3]=-1;
}
3.指向指针的指针传递给函数(P169)
例6.6 查找第一个不含空格的连续字符,
设形参为指向扫描指针的指针
3:char * nextWord(char * *pp); //pp是指向扫描指针的指针
12:char * pw=word;
13:while(* * pp && * * pp!=' ')* pw++=*(*pp)++; //复制词
14:*pw='\0'; //置字符串结束符
24:char s[ ]="what is your name.",*ps=s;
25:do cout<<nextWord(&ps)<<endl;while(ps);
main | ||||||||
s | w | h | a | t | i | s | ||
* *pp | ||||||||
ps | *pp |
nextWord | ||||||||
pw | pp | |||||||
Word | w | h | a | t |
|
6.4.2 返回指针值的函数(P171)
例:截去参数字符串的尾部空格
char * trim(char * s) //指针值函数
{
char * P=s+strlen(s)-1; //p指s最后字符
while(p-s>=0 && * p=' ')p--;
* (p+1)='\0'; //s字符串后置结束符
return s; //返回字符指针s
}
6.4.3 指向函数的指针(P172)
例:int f1(int n){...}
int (* pf1)(int); //指向函数的指针
pf1=f1; //函数名指向该函数的指针
6.4.4 作为参数传递的函数(P173)
例6.8 函数作为参数
2: inline int add(int a,int b){return a+b;}
4: inline int Double(int a, int b, int(* P)(int,int))
// 实参 add传给形参p
5: return P(a,b)*2; // 计算 add(a,b)*2
13: cout<<Double(3,5,add); // 显示
6.5 引用
6.5.1 引用变量和引用参数(P175)
1. 引用(reference):给变量、函数取别名。
例:int i=0;
int &ir=i; //给变量i取别名ir
ir=2; //等同i=2;
int * p=&ir; //等同int * p=&i;
2. 用引用实现按地址传递参数
例6.9 模板函数swap,变量地址通过指针参数传递。
4: void swap(T * a, T * b) //虚拟类型 T,指针形参 *a,*b
12: swap(&x,&y); //实参类型 int,实参指针&x,&y
例6.10 模板函数swap,变量地址通过引用参数传递。
4: void swap(T &a, T &b)
//虚拟类型 T,引用形参的地址 &a,&b
12: swap(x,y); //实参是变量x,y
6.6 动态空间管理
6.6.1 非数组动态空间
动态空间管理操作符(P180)
new:申请动态空间,
delete:释放动态空间。
例:p1=new int(5);
cout<<* p1;
delete p1;
6.6.2 数组动态空间(P181)
例:int * ap=new int[10];
delete [ ]ap;
习题六(P192)6-6,6-8