C++第一部分介绍基础:c++:-0,本节介绍C++中函数使用。
调用函数需要先声明函数原型
嵌套调用:
传引用比传对象计算消耗小
C++中提供了两种方法:
initializer_list是一种标准库类型,用于表示某种特定类型的值的数组,该类型定义在同名的头文件中
使用:
应用:
作用:编译时在调用处用函数体进行替换,节省了参数传递、控制转移等开销。
声明时使用关键字: inline
注意:
C++-11中新增,用于初始化常量表达式。
(1)constexpr函数语法规定
(2)constexpr函数举例
constexpr int get_size() { return 20; } constexpr int foo = get_size(); //正确:foo是一个常量表达式
(1)默认参数值的说明次序
函数名相同,参数类型和返回类型不同;参数个数不同
C++的系统库中提供了几百个函数可供程序员使用,例如:
计算x的n次方
#include <iostream> using namespace std; //计算x的n次方 double power(double x, int n) { double val = 1.0; while (n--) val *= x; return val; } int main() { cout << "5 to the power 2 is " << power(5, 2) << endl; return 0; }
输入一个8位二进制数,将其转换为十进制数输出。
#include <iostream> using namespace std; double power (double x, int n); //计算x的n次方 int main() { int value = 0; cout << "Enter an 8 bit binary number "; //cin:只有在输入完数据再按回车键后,该行数据才被送入键盘缓冲区,形成输入流,提取运算符“>>”才能从中提取数据。需要注意保证从流中读取数据能正常进行。 for (int i = 7; i >= 0; i--) { char ch; cin >> ch; if (ch == '1') value += static_cast<int>(power(2, i));//tatic_cast()强制类型转换 } cout << "Decimal value is " << value << endl; return 0; } double power (double x, int n) { double val = 1.0; while (n--) val *= x; return val; }
π的计算公式如下:
#include <iostream> using namespace std; //求arctan 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); //注意:因为整数相除结果取整,如果参数写1/5,1/239,结果就都是0 cout << "PI = " << a - b << endl; return 0; }
寻找并输出11~999之间的数M,它满足(M、M^2和M^3)均为回文数。
回文:各位数字左右对称的整数。
例如:11满足上述条件:112=121,113=1331。
分析:
用除以10取余的方法,从最低位开始,依次取出该数的各位数字。按反序重新构成新的数,比较与原数是否相等,若相等,则原数为回文。
#include <iostream> using namespace std; //判断n是否为回文数 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() { for(unsigned m = 11; m < 1000; m++) if (symm(m) && symm(m * m) && symm(m * m * m)) { cout << "m = " << m; cout << " m * m = " << m * m; cout << " m * m * m = " << m * m * m << endl; } return 0; }
计算分段函数,并输出结果
分析:
计算(sin(x))的公式,精度为(10^{-10}):
#include "iostream" #include "cmath" using namespace std; const double T=1e-10; //定义计算精度10^{-10} //计算sin(x) double tsin(double x) { double g=0; double t=x; int n=1; do{ g+=t; n++; t=-t*x*x/(2*n-1)/(2*n-2); }while(fabs(t)>=T);//fabs:绝对值 return g; } int main() { double k,r,s; cout << "r="; cin >>r; cout << "s="; cin >>s; if(r*r<=s*s) { k= sqrt(tsin(r)*tsin(r)+tsin(s)*tsin(s)); }else k=tsin(r*s)/2; cout <<k <<endl; return 0; }
每个骰子有六面,点数分别为1、2、3、4、5、6。游戏者在程序开始时输入一个无符号整数,作为产生随机数的种子。每轮投两次骰子,第一轮如果和数为7或11则为胜,游戏结束;和数为2、3或12则为负,游戏结束;和数为其它值则将此值作为自己的点数,继续第二轮、第三轮...直到某轮的和数等于点数则取胜,若在此前出现和数为7则为负。
分析:
(1)rand函数
函数原型:int rand(void);
所需头文件:
功能和返回值:求出并返回一个伪随机数
(2)srand函数
void srand(unsigned int seed);
参数:seed产生随机数的种子
所需头文件:
功能:为使rand()产生一序列伪随机整数而设置起始点。使用1作为seed参数,可以重新初化rand()。
#include "iostream" #include "cmath" 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 << die1<<"+"<<die2<<"="<<sum<<endl; return sum; } int main() { int sum,myPoint; GameStatus status; unsigned seed; int rollDice(); cout <<"请输入种子:"; 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 << "点数为"<<myPoint<<endl; break; } //第二轮以后 while (status==Playing) { sum=rollDice(); if(sum==myPoint) //某轮和数等于点数取胜 { status=Win; }else if(sum ==7)//出现和数为7则负 { status=Lose; } } //输出 if(status==Win) { cout << "Win"<<endl; } else cout << "Lose" <<endl; return 0; }
疑问:为什么die1和die2是一样的?
种子一样!
srand(2); int die1=1+rand()%6; srand(1); int die2=1+rand()%6; cout<<die1<<","<<die2<<endl;
#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 << "请输入n和k:"; cin >> n>>k; cout <<"C("<<n<<","<<k<<")="<< commit(n,k)<<endl; return 0; }
有三根针A、B、C。A针上有N个盘子,大的在下,小的在上,要求把这N个盘子从A针移到C针,在移动过程中可以借助B针,每次只允许移动一个盘,且在移动过程中在三根针上都保持大盘在下,小盘在上。
分析:
将n 个盘子从A针移到C针可以分解为三个步骤:
#include <iostream> using namespace std; //将src针的最上面一个盘子移动到dest针上 void move(char src, char dest) { cout << src << " --> " << dest << endl; } //将n个盘子从src针移动到dest针,以medium针作为中转 void hanoi(int n, char src, char medium, char dest) { if (n == 1) move(src, dest); else { //将A 上n-1个盘子移到 B针上(借助C针); hanoi(n - 1, src, dest, medium); //把A针上剩下的一个盘子移到C针上; move(src, dest); //将n-1个盘子从B针移到C针上(借助A针) hanoi(n - 1, medium, src, dest); } } int main() { int m; cout << "Enter the number of diskes: "; cin >> m; cout << "the steps to moving " << m << " diskes:" << endl; hanoi(m,'A','B','C'); return 0; }
输入两个整数并交换
分析:
参数传递有两种:值传递和引用传递
引用就是别名,定义int &a=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; } 运行结果: x = 5 y = 10 x = 5 y = 10
引用传递:
#include<iostream> using namespace std; //a和b分别是x和y的引用 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; } x = 5 y = 10 x = 10 y = 5
#include <iostream> using namespace std; const double PI = 3.14159265358979; inline double calArea(double radius) { return PI * radius * radius; } int main() { double r = 3.0; double area = calArea(r); cout << area << endl; return 0; }
有三个形参:length(长)、width(宽)、height(高),其中width和height带有默认值2和3。
#include <iostream> #include <iomanip> using namespace std; int getVolume(int length, int width = 2, int height = 3);//声明在前,定义默认参数值 int main() { const int X = 10, Y = 12, Z = 15; cout << "Some box data is " ; cout << getVolume(X, Y, Z) << endl; cout << "Some box data is " ; cout << getVolume(X, Y) << endl; cout << "Some box data is " ; cout << getVolume(X) << endl; return 0; } //定义中不定义默认参数值 int getVolume(int length, int width, int height) { cout << setw(5) << length << setw(5) << width << setw(5) << height << 't';//setw用于设置字段的宽度 return length * width * height; }
编写两个名为sumOfSquare的重载函数,分别求两整数的平方和及两实数的平方和。
#include <iostream> using namespace std; //类型不同 int sumOfSquare(int a, int b) { return a * a + b * b; } double sumOfSquare(double a, double b) { return a * a + b * b; } int main() { int m, n; cout << "Enter two integer: "; cin >> m >> n; cout<<"Their sum of square: "<<sumOfSquare(m, n)<<endl; double x, y; cout << "Enter two real number: "; cin >> x >> y; cout<<"Their sum of square: "<<sumOfSquare(x, y)<<endl; return 0; }
从键盘输入一个角度值,求出该角度的正弦值、余弦值和正切值。
#include <iostream> #include <cmath> using namespace std; const double PI = 3.14159265358979; int main() { double angle; cout << "Please enter an angle: "; cin >> angle; //输入角度值 double radian = angle * PI / 180; //转为弧度 cout << "sin(" << angle << ") = " << sin(radian) <<endl; cout << "cos(" << angle << ") = " << cos(radian) <<endl; cout << "tan(" << angle << ") = " << tan(radian) <<endl; return 0; }
(1)已知函数FA调用FB,若要把这两个函数定义在同一个文件中,则
函数原型,就是函数的声明
(2)在()时为形参分配存储空间。
(3)可以定义指向引用的指针.
错。因为引用不是对象,引用并没有在程序中占据内存空间,故没有地址的说法.
(4)类内实现好的成员函数是内联函数,在类体外实现的函数不能是内联函数
错。因为内联函数主要的作用是在某些情况(某个函数被调用多次)下可以提高程序的运行效率。定义内联函数,可以显式用inline声明,也可以直接在类内定义好实现. 扩展阅读
(5)已知程序中有以下声明:
分析:
constexpr的变量的值必须是编译器在编译的时候就可以确定的。上例中因为nonconst_var的值在语法上来讲,运行期间可能被更改,所以编译期间无法确定,不属于常数表达式。因为const_var2是由非常数表达式来初始化的,所以const_var2也不是常数表达式。但const_var2本身的声明,定义及初始化是合法的。constexpr比const更严格,用来初始化constexpr_var2和constexpr_var3的也都不是常数表达式,所以他们的定义都是错误的。
(6)例3-15中的getVolume函数,如果直接调用int a=getVolume();后,会有什么样的结果?
(7)判断两个浮点数是否相等
abs(a-b)<1e-10 //abs求绝对值