函数----程序的功能模块
- 函数:定义好的可重用的语言模块
- 定义函数:将一个模块的算法用C++语言描述出来
- 函数的参数:计算所需的数据,条件
- 函数的返回值:需要返回的计算结果
2.函数定义的语法形式‘
类型标识符 函数名 (形参列表)
{
语句序列
}
- 形参在定义时是不占存储空间,在函数调用,新参实参结合时才分配储存空间
3.函数调用
- 在函数调用之前,必须做一个函数原型的声明,因为函数的定义不一定在这个程序中,或在函数调用之后
函数原型声明:类型标识符 被调用函数名 (含类型说明的形参表)
- 函数调用形式:
函数名 (实参列表)
在调用时使用实参去初始化形参 - 嵌套调用:在一个函数的函数体中,调用另一函数
- 递归调用:函数直接或间接调用自身
4.例3-1
//计算x的n次方
#include <iostream>
using namespace std;
double power(double x,int n){
double val=1.0;
while(n--)
val*=x;
return val;
}
int main(){
double pow;
pow=power(5,2);
//函数调用作为一个表达式出现在语句中
cout<<"5 to the power 2 is "<<pow<<endl;
return 0;
}
5.例3-3
//1.编写程序计算Π的值 Π=16arctan(1/5)-4arctan(1/239)
//2.其中arctan用如下形式的技术进行计算:arctanx=x-x^3/3+x^5/5-x^7/7+...
//直到级数某项不大于10^-15为止,Π和x均为double型
#include <iostream>
using namespace std;
double arctan(double x) {
double sqr=x*x;
double e=x;
double r=0;
int i=1;
while((e/i)>1e-15){
double f=e/i;
r=(i%4==1)?r+f:r-f;
e=e*sqr;
i+=2;
}
return r;
}
int main() {
double a=16.0*arctan(1/5.0);
double b=4.0*arctan(1/239.0);
cout<<"the final is "<<a-b<<endl;
return 0;
}
6.例3-4
//判断回文
#include <iostream>
using namespace std;
bool symm(unsigned n) {
unsigned i=n;
unsigned m=0;
while(i>0) {
m=m*10+i%10;
i/=10;
}
return m==n;
}
int main(){
}
7.例3-5
8.例3.6
1.生成随机数
- rand函数
- 函数原型:int rand(void)
- 所需头文件:
<cstdlib>
- 功能和返回值:求出并返回一个伪随机数(每次出现的随机序列都是相同的)
2.C++使用种子解决伪随机数
- 原型: void srand ( unsigned int seed )
- 参数:seed 产生随机数的种子
- 所需头文件:
<cstdlib>
- 功能:为使rand()产生一序列伪随机整数而设置起始点。使用1作为seed参数,可以重新初始化rand()。
//投骰子游戏
#include <iostream>
#include <cstdlib>
using namespace std;
enum GameStatus{WIN,LOSE,PLAYING};
//投骰子函数
int rollDice() {
int die1=1+rand()%6;
int die2=1+rand()%6;
int sum=die1+die2;
cout<<"player rolled "<<die1<<" + "<<die2<<" = "<<sum<<endl;
return sum;
}
int main()
{
//第一部分:第一次扔骰子
int sum,myPoint;
GameStatus status;
unsigned seed;
cout<<"please enter an unsigned integer ";
cin>>seed; //输入随机数种子
srand(seed); //将种子传递给rand()
sum=rollDice(); //第一轮投骰子,计算和数
//第二部分:第一轮结束进行判断
switch (sum)
{
case 7:
case 11: status=WIN; break;
case 2:
case 3:
case 12: status=LOSE; break;
default: status=PLAYING; myPoint=sum;
cout<<"point is "<<myPoint<<endl;
break;
}
//第三部分:继续进行游戏
while(status==PLAYING){
sum=rollDice();
if(sum==myPoint)
status=WIN;
else if(sum==7)
status=LOSE;
}
//第四部分:状态不为PLAYING
if(status==WIN)
cout<<"player wins";
else
cout<<"player loses";
return 0;
}
9.函数的嵌套调用
- 函数的调用使用栈来保存返回的地址
10.eg3_7 求两个数的平方和
//EG 3_7 求两个数的平方和
#include <iostream>
using namespace std;
int fun2(int m) {
return m*m;
}
int fun1(int x,int y) {
return fun2(x)+fun2(y);
}
int main ()
{
int a,b;
cout<<"please enter two num "<<endl;
cin>>a>>b;
cout<<"the sum of square of a and b is "<<fun1(a,b)<<endl;
return 0;
}
11.函数的递归调用
- 函数直接或间接的调用自己,称为递归调用
// EG 3_8 递归调用 阶乘
#include <iostream>
using namespace std;
unsigned fac(unsigned n) {
unsigned f;
if(n==0)
f=1;
else
f=fac(n-1)*n;
return f;
}
int main()
{
unsigned n;
cout<<"enter an interger ";
cin>>n;
unsigned y=fac(n);
cout<<n<<"! = "<<y<<endl;
return 0;
}
12.3_9 从n个人中选则k个的组合数问题
//3_9 组合数
#include <iostream>
using namespace std;
int commit(int n,int k){
if(k>n)
return 0;
else if(n==k||k==0)
return 1;
else
return commit(n-1,k)+commit(n-1,k-1);
}
int main()
{
int n,k;
cout<<"please enter two interger n and k ";
cin>>n>>k;
cout<<"C(n,k)= "<<commit(n,k)<<endl;
return 0;
}
13.函数的参数传递
- 在函数调用时才给形参分配存储单元
- 实参可以是常量变量和表达式
- 实参类型必须与形参相符(隐式转换)
- 值传递是传递参数值,是单向传递
- 引用传递可以实现双向传递
- 常引用做参数可以保障实参数据的安全
14.引用类型
- 引用&是标识符的别名
int i,j; int&ri = i ;//定义int 引用ri ,并初始化为变量i的引用
- 定义一个引用时,必须同时对他进行初始化,使他指向一个已存在的对象
- 一旦一个引用被初始化后,就不可以改为指向其他对象
- 引用可以作为形参
// 输入两个整数后交换输出(引用传递)
#include <iostream>
using namespace std;
void swap(int &a,int &b) {
int t=a;
a=b;
b=t;
}
int main()
{
int x=5,y=10;
cout<<"x= "<<x<<" y= "<<y<<endl;
swap(x,y);
cout<<"x= "<<x<<" y= "<<y<<endl;
return 0;
}
15.含有可变参数的函数
- C++提供了两种主要的方法
1.如果所有的实参类型相同,可以传递一个名为initializer_list的标准库类型:用于表示某种特定类型的值的数组,该类型定义在同名的头文件中
2.如果实参的类型不同,我们可以编写可变的参数模板 initializer_;list<string>ls; //使用方法:元素类型是string
- initializer_;list对象中的元素值永远是常量值,无法改变其对象中元素的值
16内联(inline)函数
- 在调用简单函数时,可以提高运行效率
- 内联函数是由编译器替我们实现的,在运行过程中不经过转子函数返回,在函数调用时,使用函数体中的语句,去替换函数调用表达式
1.内联函数中不可以用switch和循环语句
2.内联函数必须定义在函数第一次被调用之前
3.对内联函数不可以进行异常接口声明
//内联函数应用举例
#include <iostream>
using namespace std;
const double PI=3.1415926;
inline double calArea(double radius) {
return PI*radius*radius;
}
int main()
{
double r=3.0;
double area=calArea(r);
cout<<area<<endl;
return 0;
}
17.带有默认参数值的函数
- 可以预先设置默认的参数值,如果调用时给出了实参,则采用实参值,否则采用预先设置的默认参数值
- 默认参数值的右边不能有无默认值的实参
- 调用时,形式结合的顺序是从左到右的
- 如果函数有在函数体之前的原型声明,则在生命中给出默认参数值
18.函数重载—静态多态性
- C++允许功能相近的函数在相同的作用域内以相同的函数名声明,从而形成重载。
int add ( int x , int y ) ;
float add ( float x , float y) ;
//形参类型不同
int add ( int x , int y ) ;
int add ( int x , int y , int z ) ;
//形参个数不同
19.C++系统函数
- C++库提供了很多函数以供程序员使用:
sprt () //求平方根函数
abs() //求绝对值函数
- 使用系统函数时,应包含的头文件,例如:cmath
20
//编写递归函数 fib(),计算斐波那契数列
#include <iostream>
using namespace std;
int fib (int n) {
if(n==1||n==2)
return 1;
else
return fib(n-1)+fib(n-2);
}
int main()
{
int n,answer;
cout<<"enter num ";
cin>>n;
cout<<endl;
answer=fib(n);
cout<<answer<<" is the"<<n<<"th fib num"<<endl;
return 0;
}