「c++小学期」实验题目及代码
面向对象编程的C++,和平时做题用的C++还是有差距的。实验的题目都是小题目,就都做一下吧。
实验一 简单C++程序设计
1、 猜价格游戏
编写C++程序完成以下功能:
(1) 假定有一件商品,程序用随机数指定该商品的价格(1-1000的整数);
(2) 提示用户猜价格,并输入:若用户猜的价格比商品价格高或低,对用户作出相应的提示;
(3) 直到猜对为止,并给出提示。
1 #include <iostream> 2 #include <ctime> 3 #include <cstdlib> 4 using namespace std; 5 int main() { 6 srand((int)time(0)); 7 int price=rand()%1000+1;//产生1到1000的随机数 8 int l=1,r=1000; 9 while(1) { 10 cout<<"您可以猜一个价格,当前范围["<<l<<","<<r<<"]的整数。"<<endl; 11 int guess; 12 cin>>guess; 13 if(guess>1000||guess<1||cin.fail()) { 14 cout<<"输入不合法,请重新输入"<<endl; 15 cin.clear(); 16 cin.ignore(10000,'\n'); 17 continue; 18 } 19 if(guess>price) { 20 cout<<"猜大了"<<endl; 21 if(r>guess) 22 r=guess;//缩小范围 23 } else if(guess<price) { 24 cout<<"猜小了"<<endl; 25 if(l<guess) 26 l=guess;//缩小范围 27 } else { 28 cout<<"您猜对了,价格就是"<<price<<endl; 29 break; 30 } 31 } 32 return 0; 33 }
View Code
实验问题
- 如何产生随机数
通过srand((int)time(0));生成随机数种子
然后用rand()%1000+1来产生1到1000的随机数 - 是否要提示当前范围
为了人性化,每次猜了一个价格,就会根据猜大了或者小了来缩小下一次猜的范围。但是如果用户输入的数字不在当前范围内,则不改变猜的范围。 - 如果输入的不是数字怎么办
cin.fail()为真则代表输入失败然后就
cout<<"输入不合法,请重新输入"< cin.clear();
cin.ignore(10000,'\n');
continue;
(可是这样真麻烦,后面的程序就不写了)
2、 计算 N 以内的所有素数
编写C++程序完成以下功能:
(1) 提示用户输入N;
(2) 计算出从2到N之间的所有素数;
(3) 将结果保存在一个文本文件中。
#include <iostream> #include <cstring> #include <fstream> #define N 1000000 using namespace std; int prime[N],cnt,n; void getPrime(){ for(int i=2;i<=n;i++){ if(!prime[i])prime[++cnt]=i; for(int j=1;j<=cnt&&prime[j]<=N/i;j++){ prime[prime[j]*i]=1; if(i%prime[j]==0)break; } } } int main(){ ofstream f("prime.txt"); cout<<"请输入n"<<endl; cin>>n; getPrime(); for(int i=1;i<=cnt;i++) f<<prime[i]<<" "; f.close(); return 0; }
3、 袋中取球
编写C++程序完成以下功能(使用 enum):
(1) 袋子中有 red, yellow, blue, white, black 五种颜色的球多个;
(2) 一次从袋子里取出3个颜色不同的球,有几种取法;
(3) 将每种方法的所有取法输出到屏幕上。
#include <iostream> using namespace std; enum ball{ red,yellow,blue,white,black }; void output(int i){ switch(i){ case red:cout<<"red ";break; case yellow:cout<<"yellow ";break; case blue:cout<<"blue ";break; case white:cout<<"white ";break; case black:cout<<"black ";break; } } int main(){ for(int i=red;i<=black;i++) for(int j=i+1;j<=black;j++) for(int k=j+1;k<=black;k++){ output(i); output(j); output(k); cout<<endl; } return 0; }
View Code
4、 乘法口诀表
编写C++程序完成以下功能:
(1) 输出乘法口诀表;
(2) 显示格式如下所示。
1*1=1 1*2=2 1*3=3 1*4=4 1*5=5 1*6=6 1*7=7 1*8=8 1*9=9
2*2=4 2*3=6 2*4=8 2*5=10 2*6=12 2*7=14 2*8=16 2*9=18
3*3=9 3*4=12 3*5=15 3*6=18 3*7=21 3*8=24 3*9=27
4*4=16 4*5=20 4*6=24 4*7=28 4*8=32 4*9=36
5*5=25 5*6=30 5*7=35 5*8=40 5*9=45
6*6=36 6*7=42 6*8=48 6*9=54
7*7=49 7*8=56 7*9=63
8*8=64 8*9=72
9*9=81
#include <iostream> #include <iomanip> using namespace std; int main(){ for(int i=1;i<=9;i++){ for(int j=1;j<=i*7;j++) cout<<" "; for(int j=i;j<=9;j++) cout<<i<<"*"<<j<<"="<<setw(3)<<left<<i*j; cout<<endl; } }
5、 最大公约数和最小公倍数
编写C++程序完成以下功能:
(1) 提示用户输入两个无符号整数;
(2) 计算两者的最大公约数和最小公倍数,并输出。
#include <iostream> #define uint unsigned int using namespace std; uint gcd(uint a,uint b){ return b?gcd(b,a%b):a; } int main(){ uint a,b; cout<<"请输入两个无符号整数"<<endl; cin>>a>>b; cout<<a<<"和"<<b<<"的最大公约数是"<<gcd(a,b); cout<<",最小公倍数是"<<b/gcd(a,b)*a<<endl; return 0; }
6、 计算Fibonacci级数
fib(1) = fib(2) = 1
fib(n) = fib(n-1) + fib(n-2)
分别编写递归和非递归的C++程序完成以下功能:
(1) 提示用户输入整数n;
(2) fib(n),并输出结果。
//递归 #include <iostream> using namespace std; int fib(int x){ if(x==1||x==2)return 1; return fib(x-1)+fib(x-2); } int main(){ int n; cout<<"请输入整数n"<<endl cin>>n; cout<<"fib("<<n<<")="<<fib(n)<<endl; return 0; }
//非递归 #include <iostream> using namespace std; int fib(int x){ int a=1,b=1; for(int i=3;i<=x;i++){ int t=b; b+=a; a=t; } return b; } int main(){ int n; cout<<"请输入整数n"<<endl; cin>>n; cout<<"fib("<<n<<")="<<fib(n)<<endl; return 0; }
7、 计算n 阶勒让德多项式
编写C++程序完成以下功能:
(1) 提示用户输入整数n和实数x;
(2) Pn(x),并输出结果。
#include <iostream> using namespace std; double p(int n,int x){ if(!n)return 1; if(n==1)return x; return ((2*n-1)*p(n-1,x)-(n-1)*p(n-2,x))/n; } int main(){ int n,x; cout<<"请输入n、x"<<endl; cin>>n>>x; cout<<"Pn("<<x<<")="<<p(n,x)<<endl; return 0; }
实验二 类与对象
1、 矩形
编写C++程序完成以下功能:
(1) 定义一个Point类,其属性包括点的坐标,提供计算两点之间距离的方法;
(2) 定义一个矩形类,其属性包括左上角和右下角两个点,提供计算面积的方法;
(3) 创建一个矩形对象,提示用户输入矩形左上角和右下角的坐标;
(4) 观察矩形对象以及Point类成员的构造函数与析构函数的调用;
(5) 计算其面积,并输出。
1 #include <iostream> 2 #include <cstdlib> 3 using namespace std; 4 class Point { 5 private: 6 int x,y; 7 public: 8 Point(int _x=0,int _y=0):x(_x),y(_y) {}; 9 Point(Point &p):x(p.x),y(p.y) {}; 10 ~Point() {}; 11 int disX(const Point &b) { 12 return b.x-x; 13 }; 14 int disY(const Point &b) { 15 return b.y-y; 16 } 17 }; 18 19 class Rectangle { 20 private: 21 Point a,b; 22 public: 23 Rectangle(Point _a,Point _b):a(_a),b(_b) {}; 24 Rectangle(int ax=0,int ay=0,int bx=1,int by=1):a(ax,ay),b(bx,by) {} 25 Rectangle(Rectangle &r):a(r.a),b(r.b) {}; 26 ~Rectangle() { 27 cout<<"hh"<<endl; 28 }; 29 int area() { 30 return abs(a.disX(b)*a.disY(b)); 31 }; 32 }; 33 34 int main() { 35 cout<<"请输入矩形的左上角和右下角坐标(整数)"<<endl; 36 int ax,ay,bx,by; 37 while(1) { 38 cin>>ax>>ay>>bx>>by; 39 if(ax>bx||ay<by||cin.fail()) { 40 cout<<"输入的矩形不合法"<<endl; 41 cin.clear(); 42 cin.ignore(10000,'\n'); 43 } else { 44 Rectangle myRectangle(ax,ay,bx,by); 45 cout<<"该矩形的面积为"<<myRectangle.area()<<endl; 46 break; 47 } 48 } 49 return 0; 50 }
View Code
实验问题
- 构造函数和析构函数写在哪?
写在public里(声明必须在..里,定义里外都可以) - 析构函数里面要写什么?
留空就可以了吧,如果有动态申请的内存就delete掉 - 拷贝构造函数怎么写?
Point(Point &p){ x=p.x;y=p.y; };
或者
Point(Point &p):x(p.x),y(p.y){}; - 编译错误提示 call of overloaded `Point()' is
ambiguous
Point()构造时,Point(){};和Point(int _x=0,int _y=0):x(_x),y(_y){};都可以被调用,于是就被overloaded了。 - 编译错误提示 In member function int
Rectangle::area()':
int Point::x' is private
因为x是Point类的私有成员,不能在Rectangle类里面使用,关于x的计算函数都要写在Point类的public里。 - 初始化时Rectangle myRectangle=Rectangle(ax,ay,bx,by);报错.
应该为Rectangle myRectangle(ax,ay,bx,by); - 析构函数怎么调用
不用显式调用,需要显式时:p.~Point();即可
2、 圆形
编写C++程序完成以下功能:
(1) 定义一个Point类,其属性包括点的坐标,提供计算两点之间距离的方法;
(2) 定义一个圆形类,其属性包括圆心和半径;
(3) 创建两个圆形对象,提示用户输入圆心坐标和半径,判断两个圆是否相交,并输出结果。
#include <iostream> #include <cmath> #define sqr(x) ((x)*(x)) using namespace std; class Point{ private: int x,y; public: Point(int x=0,int y=0):x(x),y(y){} double dis(Point &b)const{ return sqrt(sqr(x-b.x)+sqr(y-b.y)); } }; class Circle{ private: Point c; double r; public: Circle(int x=0,int y=0,double r=0):c(x,y),r(r){} double dis(Circle &b)const{ return c.dis(b.c); } double getR()const{ return r; } }; int main(){ int x,y,r; cout<<"请输入a 圆心坐标半径"<<endl; cin>>x>>y>>r; Circle a(x,y,r); cout<<"请输入b 圆心坐标半径"<<endl; cin>>x>>y>>r; Circle b(x,y,r); if(a.dis(b)<=a.getR()+b.getR()) cout<<"两圆相交"<<endl; else cout<<"两圆相离"<<endl; return 0; }
3、 友元
编写C++程序完成以下功能:
(1) 定义一个Boat和Car两个类,他们都具有私用属性——重量;
(2) 编写一个函数,计算两者的重量和。
double TotalWeight(Boat& b, Car& c);
1 #include <iostream> 2 using namespace std; 3 class Car; 4 class Boat { 5 private: 6 double weight; 7 public: 8 Boat() {}; 9 Boat(double w=0):weight(w) {}; 10 ~Boat() {}; 11 friend double TotalWeight(Boat&,Car&); 12 }; 13 14 class Car { 15 private: 16 double weight; 17 public: 18 Car() {}; 19 Car(double w=0):weight(w) {}; 20 ~Car() {}; 21 friend double TotalWeight(Boat&,Car&); 22 }; 23 double TotalWeight(Boat& b,Car& c) { 24 return b.weight+c.weight; 25 } 26 int main() { 27 cout<<"请输入Boat、Car的重量"<<endl; 28 while(1) { 29 double bw,cw; 30 cin>>bw>>cw; 31 if(cin.fail()) { 32 cout<<"输入不合法"<<endl; 33 cin.clear(); 34 cin.ignore(10000,'\n'); 35 } else { 36 Boat myBoat(bw); 37 Car myCar(cw); 38 cout<<"Boat和Car的总重量为"<<TotalWeight(myBoat,myCar)<<endl; 39 break; 40 } 41 } 42 return 0; 43 }
View Code
实验问题
- 什么时候需要用友元?
当一个函数要用到这个类时(可能还有其他类)的私有成员,但是它不是这个类独享的函数,调用时不需要通过对象或指针。 - 友元函数定义在哪?
定义在主函数外面,类定义后面,要加上friend然后声明在类的公有属性里。
4、 分数
编写C++程序完成以下功能:
(1) 定义一个分数类,他们都具有私用属性——分子和分母;
(2) 定义分数类的构造函数和析构函数;
(3) 定义方法Set,设置分子和分母;
(4) 定义方法print,打印分数,格式如:2/7;
(5) 定义方法value,返回double型的分数值;
(6) 定义方法invert, 分子和分母交换。
#include <iostream> using namespace std; class Fractions{ private: int num,den; public: Fractions(int n=0,int d=0):num(n),den(d){} ~Fractions(){} void set(int n,int d){ num=n;den=d; } void print(){ cout<<num<<"/"<<den<<endl; } double value(){ return num*1.0/den; } void invert(){ int t=den; den=num; num=t; } }; int main(){ return 0; }
实验三 数组与指针
1、 矩阵(一)
编写C++程序完成以下功能:
(1) 假定矩阵大小为4×5(整型数组表示);
(2) 定义矩阵初始化函数,可以从cin中输入矩阵元素;
(3) 定义矩阵输出函数,将矩阵格式化输出到cout;
(4) 定义矩阵相加的函数,实现两个矩阵相加的功能,结果保存在另一个矩阵中;
(5) 定义矩阵相减的函数,实现两个矩阵相减的功能,结果保存在另一个矩阵中;
(6) 定义三个矩阵:A1、A2、A3;
(7) 初始化A1、A2;
(8) 计算并输出:A3 = A1加A2,A3 = A1减A2。
1 #include <iostream> 2 #define ROW 4 3 #define COL 5 4 using namespace std; 5 class Matrix { 6 private: 7 int mat[ROW][COL]; 8 public: 9 Matrix() {}; 10 void init() { 11 cout<<"please input the Matrix(4 row and 5 col)"<<endl; 12 for(int i=0; i<ROW; i++) 13 for(int j=0; j<COL; j++) 14 cin>>mat[i][j]; 15 } 16 void output() { 17 cout<<"The Matrix:"<<endl; 18 for(int i=0; i<ROW; i++) { 19 for(int j=0; j<COL; j++) 20 cout<<mat[i][j]<<"\t"; 21 cout<<endl; 22 } 23 } 24 void add(Matrix &a,Matrix &b) { 25 for(int i=0; i<ROW; i++) 26 for(int j=0; j<COL; j++) 27 mat[i][j]=a.mat[i][j]+b.mat[i][j]; 28 } 29 void sub(Matrix &a,Matrix &b) { 30 for(int i=0; i<ROW; i++) 31 for(int j=0; j<COL; j++) 32 mat[i][j]=a.mat[i][j]-b.mat[i][j]; 33 } 34 }; 35 int main() { 36 Matrix A1,A2,A3; 37 A1.init(); 38 A2.init(); 39 A3.add(A1,A2); 40 A3.output(); 41 A3.sub(A1,A2); 42 A3.output(); 43 return 0; 44 }
View Code
2、 矩阵(二)
编写C++程序完成以下功能:
(1) 假定矩阵大小为4×5(整型);
(2) 矩阵空间采用new动态申请,保存在指针中;
(3) 定义矩阵初始化函数,可以从cin中输入矩阵元素;
(4) 定义矩阵输出函数,将矩阵格式化输出到cout;
(5) 定义矩阵相加的函数,实现两个矩阵相加的功能,结果保存在另一个矩阵中;
(6) 定义矩阵相减的函数,实现两个矩阵相减的功能,结果保存在另一个矩阵中;
(7) 动态申请三个矩阵:A1、A2、A3;
(8) 初始化A1、A2;
(9) 计算并输出A3 = A1加A2,A3 = A1减A2;
(10) 释放矩阵空间。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 const int row = 4; 5 const int col = 5; 6 using namespace std; 7 bool malloc_array(int **&a,int row,int col) { 8 a=new int *[row]; 9 if(a==NULL) { 10 cout<<"error:no enough space"<<endl; 11 return 0; 12 } 13 for(int i=0; i<row; i++) { 14 *(a+i)=new int[col]; 15 if(a+i==NULL) { 16 cout<<"error:no enough space"<<endl; 17 return 0; 18 } 19 } 20 return 1; 21 } 22 class Matrix 23 { 24 private: 25 int **mat; 26 public: 27 Matrix() 28 { 29 malloc_array(mat, row, col); 30 } 31 Matrix(Matrix &b) 32 { 33 if(malloc_array(mat, row, col)) 34 for(int i = 0; i < row; i++) 35 for(int j = 0; j < col; j++) 36 mat[i][j] = b.mat[i][j]; 37 } 38 ~Matrix() 39 { 40 for(int i = 0; i < row; i++) 41 delete [] *(mat + i); 42 delete [] mat; 43 mat = NULL; 44 } 45 void input() 46 { 47 cout << "please input the Matrix:" << endl; 48 for(int i = 0; i < row; i++) 49 for(int j = 0; j < col; j++) 50 cin >> mat[i][j]; 51 } 52 void output() 53 { 54 for(int i = 0; i < row; i++) 55 { 56 for(int j = 0; j < col; j++) 57 cout << mat[i][j] << "\t"; 58 cout << endl; 59 } 60 } 61 void cal(Matrix &a, Matrix &b, int op) 62 { 63 for(int i = 0; i < row; i++) 64 for(int j = 0; j < col; j++) 65 mat[i][j] = a.mat[i][j] + b.mat[i][j] * op; 66 } 67 }; 68 int main() 69 { 70 Matrix *A1 = new Matrix(); 71 A1->input(); 72 Matrix *A2 = new Matrix(); 73 A2->input(); 74 Matrix *A3 = new Matrix(); 75 A3->cal(*A1, *A2, 1); 76 cout << "Matrix A1 + Matrix A2 =" << endl; 77 A3->output(); 78 A3->cal(*A1, *A2, -1); 79 cout << "Matrix A1 - Matrix A2 =" << endl; 80 A3->output(); 81 A1->~Matrix(); 82 A2->~Matrix(); 83 A3->~Matrix(); 84 A1 = NULL; 85 A2 = NULL; 86 A3 = NULL; 87 return 0; 88 }
View Code
实验问题
- 动态分配内存?
定义:int **mat;
分配:
mat=new int *[ROW];
for(int i=0; i *(mat+i)=new int[COL];
加上判断是否分配成功 - 释放空间?
for(int i=0;i delete [] *(mat+i);
delete [] mat;
3、 矩阵(三)
编写C++程序完成以下功能:
(1) 用类来实现矩阵,定义一个矩阵的类,属性包括:
- 矩阵大小,用 lines, rows(行、列来表示);
- 存贮矩阵的数组指针,根据矩阵大小动态申请(new)。
(2) 矩阵类的方法包括:
- 构造函数,参数是矩阵大小,需要动态申请存贮矩阵的数组;
- 析构函数,需要释放矩阵的数组指针;
- 拷贝构造函数,需要申请和复制数组;
- 输入,可以从cin中输入矩阵元素;
- 输出,将矩阵格式化输出到cout;
- 矩阵相加的函数,实现两个矩阵相加的功能,结果保存在另一个矩阵类,但必须矩阵大小相同;
- 矩阵相减的函数,实现两个矩阵相减的功能,结果保存在另一个矩阵类,但必须矩阵大小相同。
(3) 定义三个矩阵:A1、A2、A3;
(4) 初始化A1、A2;
(5) 计算并输出A3 = A1加A2,A3=A1减A2;
(6) 用new动态创建三个矩阵类的对象:pA1、pA1、pA3;
(7) 初始化pA1、pA2;
(8) 计算并输出pA3=pA1加pA2,pA3=pA1减pA2;
(9) 释放pA1、pA1、pA3。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 bool malloc_array(int **&a,int row,int col) { 6 a=new int *[row]; 7 if(a==NULL) { 8 cout<<"error:no enough space"<<endl; 9 return 0; 10 } 11 for(int i=0; i<row; i++) { 12 *(a+i)=new int[col]; 13 if(a+i==NULL) { 14 cout<<"error:no enough space"<<endl; 15 return 0; 16 } 17 } 18 return 1; 19 } 20 class Matrix { 21 private: 22 int **mat; 23 int row,col; 24 public: 25 Matrix(int _row=0,int _col=0):row(_row),col(_col) { 26 malloc_array(mat,row,col); 27 } 28 Matrix(Matrix &b):row(b.getRow()),col(b.getCol()) { 29 if(malloc_array(mat,row,col)) 30 for(int i=0; i<row; i++) 31 for(int j=0; j<col; j++) 32 mat[i][j]=b.mat[i][j]; 33 } 34 ~Matrix() { 35 for(int i=0; i<row; i++) 36 delete [] *(mat+i); 37 delete [] mat; 38 mat=NULL; 39 } 40 int getRow() { 41 return row; 42 } 43 int getCol() { 44 return col; 45 } 46 void input() { 47 cout<<"please input the Matrix:"<<endl; 48 for(int i=0; i<row; i++) 49 for(int j=0; j<col; j++) 50 cin>>mat[i][j]; 51 } 52 void output() { 53 for(int i=0; i<row; i++) { 54 for(int j=0; j<col; j++) 55 cout<<mat[i][j]<<"\t"; 56 cout<<endl; 57 } 58 } 59 int cal(Matrix &a,Matrix &b,int op) { 60 if(a.getRow()!=b.getRow()||a.getCol()!=b.getCol()) { 61 cout<<"error:These two Matrix don't have the same size."<<endl; 62 return 0; 63 } 64 for(int i=0; i<row; i++) 65 for(int j=0; j<col; j++) 66 mat[i][j]=a.mat[i][j]+b.mat[i][j]*op; 67 return 1; 68 } 69 }; 70 int main() { 71 int row,col; 72 cout<<"please input Matrix A1's row and col:"<<endl; 73 cin>>row>>col; 74 Matrix *pA1=new Matrix(row,col); 75 pA1->input(); 76 cout<<"please input Matrix A2's row and col:"<<endl; 77 cin>>row>>col; 78 Matrix *pA2=new Matrix(row,col); 79 pA2->input(); 80 Matrix *pA3=new Matrix(row,col); 81 if(pA3->cal(*pA1,* pA2,1)) { 82 cout<<"Matrix A1 + Matrix A2 ="<<endl; 83 pA3->output(); 84 pA3->cal(*pA1,* pA2,-1); 85 cout<<"Matrix A1 - Matrix A2 ="<<endl; 86 pA3->output(); 87 } 88 pA1->~Matrix(); 89 pA2->~Matrix(); 90 pA3->~Matrix(); 91 pA1=NULL; 92 pA2=NULL; 93 pA3=NULL; 94 return 0; 95 }
View Code
实验问题
- line和row,不应该是row和col吗?
那就用row和col - 加减的函数基本一样,我可以写在一起吗?
其实用了乘法会降低速度,不过,这种同一级别的计算量,差别微小。 - 拷贝函数怎么写
里面不能用memcpy(mat,b.mat,sizeof mat); - 遇到错误error: passing ‘const Matrix’ as ‘this’
argument discards qualifiers [-fpermissive] in call to ‘int
Matrix::getRow()’
这是因为const型的Matrix参数要调用getRow,要在getRow的大括号前加上const。不过这个const型的Matrix参数我改回引用了。 - 怎么释放
显式调用析构函数,再将指针指向NULL
4、 字符串翻转
编写C++程序完成以下功能:
(1) 输入一段字符串;
(2) 将字符串翻转以后输出(不要利用库函数)。
#include <iostream> using namespace std; int main(){ char s[1000]; cin>>s; int len; for(len=0;s[len];len++); len--; for(int i=0;i<=len/2;i++){ char c=s[i]; s[i]=s[len-i]; s[len-i]=c; } cout<<s; return 0; }
5、 函数指针
实现二分法求解方程。编写以下函数求方程 f(x)=0的解:
double RolveRoot(double (*pf)(double x), double a, double b, int n);
其中pf是一个函数指针(指向f(x)),RolveRoot(),用来获得f(x)=0在区间[a,b]内的解,f(x)的形式如 f(x)=x*x-3x+6等。a,b指定了方程 f(x)=0解存在的区间。n是迭代次数,次数越多,精度越高。
二分法的步骤:
(1) 计算 f(a) 、f(b)、f((a+b)/2);
(2) 若f(a)与f((a+b)/2)异号,则在[a,(a+b)/2]区间内有解,令b = (a+b)/2, 回到第一步继续迭代,直到到达足够精度;
(3) 否则,令a = (a+b)/2, 回到第一步继续迭代,直到到达足够精度。
实现RolveRoot(),并采用不同 f(x) 验证。
#include <iostream> using namespace std; double RolveRoot(double (*pf)(double x), double a, double b, int n){ double fa,fm; for(int i=1;i<=n;i++){ double m=(a+b)/2; fa=pf(a); fm=pf(m); if(fa*fm<0)b=m; else a=m; } return a; } double f1(double x){ return x*6+16; } double f2(double x){ return x+1; } int main(){ cout<<RolveRoot(f1,-10,10,20)<<endl; cout<<RolveRoot(f2,-10,10,20)<<endl; return 0; }
实验四 继承与派生
1、 形状(一)
编写C++程序完成以下功能:
(1) 声明一个基类Shape(形状),其中包含一个方法来计算面积;
(2) 从Shape派生两个类矩形和圆形;
(3) 从矩形派生正方形;
(4) 分别实现派生类构造函数、析构函数和其他方法;
(5) 创建派生类的对象,观察构造函数、析构函数调用次序;
(6) 不同对象计算面积。
1 #include <iostream> 2 #include <cmath> 3 #define output(a) cout<<"The Area of "<<#a<<" is "<<a.getArea()<<endl 4 using namespace std; 5 const double pi=acos(-1.0); 6 class Shape { 7 public: 8 double getArea(); 9 }; 10 class Rectangle: public Shape { 11 private: 12 int w,h; 13 public: 14 Rectangle(int _w=0,int _h=0):w(_w),h(_h) {} 15 ~Rectangle() {} 16 double getArea() { 17 return w*h; 18 } 19 20 }; 21 class Square:public Rectangle { 22 private: 23 int a; 24 public: 25 Square(int _a=0):a(_a) {} 26 ~Square() {} 27 double getArea() { 28 return a*a; 29 } 30 }; 31 class Circle:public Shape { 32 private: 33 int r; 34 public: 35 Circle(int _r=0):r(_r) {} 36 ~Circle() {} 37 double getArea() { 38 return pi*r*r; 39 } 40 }; 41 int main() { 42 Circle c(1); 43 Square s(2); 44 Rectangle r(2,3); 45 output(c); 46 output(s); 47 output(r); 48 return 0; 49 }
View Code
实验问题
- 基类要面积这个参数吗,怎么计算面积?
不用,不用计算,只是有这个方法放在那。 - 怎么继承,区别是什么?
公有继承,父类的私有成员都是不可访问,公有成员只有公有继承时是都可访问,私有继承则只能类内访问。
2、 形状(二)——虚函数
(1) 将【形状(一)】 中的基类计算面积的方法定义为虚函数,比较与【形状(一)】程序的差异;
(2) 将【形状(一)】中的基类定义抽象类,比较与【形状(一)】程序的差异。
1 #include <iostream> 2 #include <cmath> 3 using namespace std; 4 const double pi=acos(-1.0); 5 class Shape { 6 public: 7 virtual double getArea()=0; 8 }; 9 class Rectangle: public Shape { 10 private: 11 int w,h; 12 public: 13 Rectangle(int _w=0,int _h=0):w(_w),h(_h) {} 14 ~Rectangle() {} 15 double getArea() { 16 return w*h; 17 } 18 }; 19 class Square:public Rectangle { 20 private: 21 int a; 22 public: 23 Square(int _a=0):a(_a) {} 24 ~Square() {} 25 double getArea() { 26 return a*a; 27 } 28 }; 29 class Circle:public Shape { 30 private: 31 int r; 32 public: 33 Circle(int _r=0):r(_r) {} 34 ~Circle() {} 35 double getArea() { 36 return pi*r*r; 37 } 38 }; 39 int main() { 40 Shape *ptr[5]; 41 ptr[1]=new Circle(1); 42 ptr[2]=new Square(2); 43 ptr[3]=new Rectangle(2,3); 44 for(int i=1; i<=3; i++) 45 cout<<"The Area of Shape "<<i<<" is "<<ptr[i]->getArea()<<endl; 46 return 0; 47 }
View Code
实验问题
- 虚函数是什么?
C++的虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类提供默认的函数实现。
子类可以重写父类的虚函数实现子类的特殊化。 - 虚函数程序差异在哪里?
在函数前面加了个virtual 关键字 - 抽象类是什么?
就是不能new出对象的类,有纯虚函数,“只提供声明,没有实现”,是对子类的约束,是“接口继承”。
抽象类的区别?
虚函数基础上在基类中不给定义函数,只声明。体现了面向对象编程的多态性。
3、 高斯消去法解线性方程组(选做)
阅读理解和掌握教材第7.6节实例,编程实现用高斯消去法解线性方程的程序,并且上机调试通过。
#include <iostream> #define N 100 using namespace std; void Gauss(double c[][N],int n,int cnt){ if(cnt<n){ cout<<"无穷个解"<<endl; return ; } for(int i=0,s=0;i<cnt&&s<n;i++){ int r=i; while(c[r][i]==0&&r<cnt)r++; if(c[r][i]){ swap(c[r],c[i]); for(int j=i+1;j<cnt;j++){ double t=c[j][i]/c[i][i]; for(int k=i;k<=n;k++) c[j][k]-=c[i][k]*t; } s++; }else{ for(int j=i;j<cnt;j++)if(c[j][n]){ cout<<"无解"<<endl; return; } cout<<"无穷个解"<<endl; return; } } double x[N]; for(int i=n-1;i>=0;i--){ x[i]=c[i][n]/c[i][i]; for(int j=0;j<i;j++){ c[j][n]-=x[i]*c[j][i]; c[j][i]=0; } } for(int i=0;i<n;i++) cout<<x[i]<<" "; cout<<endl; } int main(){ int n,m; cout<<"请输入变量个数"<<endl; cin>>n; cout<<"请输入方程个数"<<endl; cin>>m; cout<<"请输入系数矩阵"<<endl; double mat[N][N]; for(int i=0;i<m;i++) for(int j=0;j<=n;j++) cin>>mat[i][j]; Gauss(mat,n,m); return 0; }
实验五 多态性
1、 对Point类重载++和――运算符
编写C++程序完成以下功能:
(1) Point类的属性包括点的坐标(x,y);
(2) 实现 Point类重载++和――运算符:
- ++p,--p,p++,p--。
- ++和――分别表示x,y增加或减少1。
1 #include<iostream> 2 using namespace std; 3 class Point{ 4 private: 5 int x,y; 6 public: 7 Point(int x=0,int y=0):x(x),y(y){} 8 Point(Point &b):x(b.x),y(b.y){} 9 Point operator++(int){//p++ 10 Point t(x,y); 11 x++; 12 y++; 13 return t; 14 } 15 Point operator++(){//++p 16 x++; 17 y++; 18 return *this; 19 } 20 Point operator--(int){//p-- 21 Point t(x,y); 22 x--; 23 y--; 24 return t; 25 } 26 Point operator--(){//--p 27 x--; 28 y--; 29 return *this; 30 } 31 Point operator+(Point &b){ 32 Point t(x+b.x,y+b.y); 33 return t; 34 } 35 void out(){ 36 cout<<"("<<x<<","<<y<<")"<<endl; 37 } 38 }; 39 int main(){ 40 Point p(0,0); 41 (p++).out(); 42 p.out(); 43 (++p).out(); 44 p.out(); 45 (p--).out(); 46 p.out(); 47 (--p).out(); 48 p.out(); 49 return 0; 50 }
View Code
实验问题
- 如何实现左右的两种不同运算?
重载 operator++ 和 operator--时带一个 int 参数表示后缀,不带参数表示前缀 - 怎么验证运算符?
通过(++p).out()来输出验证。
2、 实现复数类的运算重载
编写C++程序完成以下功能:
(1) 实现复数类的运算重载:+,-,*,/,^(乘方)。
#include <iostream> using namespace std; class Complex{ private: double re,im; public: Complex(double r=0,double i=0):re(r),im(i){} Complex(Complex &b):re(b.re),im(b.im){} ~Complex(){} Complex operator +(Complex &b){ Complex t(re+b.re,im+b.im); return t; } Complex operator -(Complex &b){ Complex t(re-b.re,im-b.im); return t; } Complex operator *(Complex &b){ Complex t(re*b.re-im*b.im,re*b.im+im*b.re); return t; } Complex operator /(Complex &b){ double t=im*im+b.im*b.im; Complex a((re*b.re+im*b.im)/t,(im*b.re-re*b.im)/t); return a; } Complex operator ^(int b){ Complex t(*this); for(int i=0;i<b;i++) t=t*(*this); return t; } void out(){//我自己加了严格的输出要求 if(re){ cout<<re; if(im>0)cout<<"+"; } if(im==-1)cout<<"-"; else if(im!=1)cout<<im; if(im)cout<<"i"; cout<<endl; } }; int main(){ int r,i; cout<<"请输入a的实部和虚部"<<endl; cin>>r>>i; Complex a(r,i); cout<<"请输入b的实部和虚部"<<endl; cin>>r>>i; Complex b(r,i); cout<<"a*b="; (a*b).out(); cout<<"a+b="; (a+b).out(); cout<<"a/b="; (a/b).out(); cout<<"a-b="; (a-b).out(); cout<<"a^3="; (a^3).out(); return 0; }
3、 参考【实验二】中分数类,为分数类重载运算符,使之能够进行+,-,*,/,^(乘方)的运算。
#include <iostream> using namespace std; class Fractions{ private: int num,den; public: Fractions(int n=0,int d=0):num(n),den(d){} Fractions(Fractions &b):num(b.num),den(b.den){} ~Fractions(){} Fractions operator +(Fractions &b){ Fractions t(num+b.num,den+b.den); return t; } Fractions operator -(Fractions &b){ Fractions t(num-b.num,den-b.den); return t; } Fractions operator *(Fractions &b){ Fractions t(num*b.num,den*b.den); return t; } Fractions operator /(Fractions &b){ Fractions a(num*b.den,den*b.num); return a; } Fractions operator ^(int b){ Fractions t(*this); for(int i=0;i<b;i++) t=t*(*this); return t; } void set(int n,int d){ num=n;den=d; } void print(){ cout<<num<<"/"<<den<<endl; } }; int main(){ Fractions a(1,2),b(2,3); (a/b).print(); return 0; }
4、 参考【实验三】中矩阵(三),重载运算符+和-,实现矩阵的加减。(懒得做了- -)
5、 求积分(选做)(懒得做了- -)
阅读理解和掌握教材第8.5节实例,编程实现求函数定积分的程序,并且上机调试通过
实验六 流式IO
1、 流式IO(一)
编写C++程序完成以下功能:
(1) 使用ofstream 向一个文本文件中输出各种类型的数据,并打开文件观察结果:
- 整数、无符号整型、长整型、浮点型、字符串、……
(2) 用十进制、八进制、十六进制方式向文本文件中输出整数;
(3) 使用控制符和成员函数来控制输出的格式:
- set() precision() ...
1 #include <iostream> 2 #include <iomanip> 3 #include <fstream> 4 5 using namespace std; 6 int main(){ 7 int hh=2333; 8 unsigned int un=100; 9 long l=100000; 10 double d=123.533456780123; 11 12 ofstream f("out.txt"); 13 f<<"整数:"<<hh<<endl; 14 f<<"无符号整型:"<<un<<endl; 15 f<<"长整型:"<<l<<endl; 16 f<<"浮点型:"<<d<<endl; 17 f<<"我是一个字符串"<<endl; 18 f.close(); 19 20 cout <<showbase;//显示进制的格式 21 cout<<"十进制:"<<hh<<endl; 22 cout<<"十六进制:"<<hex<<hh<<endl; 23 cout<<"八进制:"<<oct<<hh<<endl; 24 cout<<"回到十进制:"<<dec<<hh<<endl<<endl; 25 26 cout<<"精度10位:"<<setprecision(10)<<d<<endl; 27 cout<<"当前精度:"<<cout.precision()<<endl; 28 cout<<"定点小数:"<<fixed<<d<<endl ; 29 return 0; 30 }
View Code
2、 流式IO(二)
编写C++程序完成以下功能:
(1) 输入一个文本文件名
(2) 使用ofstream 向一个二进制文件中输出各种类型的数据,并打开文件观察结果:
- 整数、无符号整型、长整型、浮点型、字符串、……
#include <iostream> #include <iomanip> #include <fstream> using namespace std; int main(){ int hh=2333; unsigned int un=100; long l=100000; double d=123.533456780123; char file[1000]; cout<<"请输入文件名"<<endl; cin>>file; ofstream f(file, ios::binary); f<<"整数:"<<hh<<endl; f<<"无符号整型:"<<un<<endl; f<<"长整型:"<<l<<endl; f<<"浮点型:"<<d<<endl; f<<"我是一个字符串"<<endl; f.close(); return 0; }
3、 流式IO(三)
编写C++程序完成以下功能:
(1) 输入一个文本文件名;
(2) 打开文件名,在该文件的每一行前面加上一个行号,保存在另外一个文本文件中。
1 #include <iostream> 2 #include <cstdio> 3 #include <string> 4 #include <fstream> 5 using namespace std; 6 int main(){ 7 char file[1000]; 8 cout<<"请输入文件名"<<endl; 9 cin>>file; 10 ifstream in(file); 11 if(!in){ 12 cout<<"文件打开失败!\n"; 13 return 0; 14 } 15 ofstream out("out.txt"); 16 if(!out){ 17 cout<<"文件打开失败!\n"; 18 return 0; 19 } 20 21 int i=1; 22 string s; 23 /*另一种实现方式 24 cout<<i++<<" "; 25 while(in>>s){ 26 cout<<s; 27 if(in.peek()=='\n')cout<<endl<<i++<<" "; 28 }*/ 29 while(getline(in,s)) 30 cout<<i++<<s<<endl; 31 in.close(); 32 out.close(); 33 return 0; 34 }
View Code
实验问题
- 怎么读入一行?
一是用string库函数的getline,另一种是通过判断peek()=='\n'。
实验七 C++程序设计应用
1、 电话本
编写C++程序完成以下功能:
(1) 实现简单电话本功能,用姓名来搜索电话号码;
(2) 用户输入姓名,程序查找并输出结果;
(3) 用户可以通过输入,添加姓名和电话号码;
(4) 用户可以删除姓名和电话号码;
(5) 电话本可以保存在指定文件中;
(6) 电话可被从指定文件中读入到内存。
1 #include <iostream> 2 #include <string> 3 #include <fstream> 4 using namespace std; 5 class People{ 6 private: 7 string name,tel; 8 public: 9 People* next; 10 People(string n="\0",string t="\0"):name(n),tel(t){next=NULL;} 11 People(People& p):name(p.name),tel(p.tel){} 12 ~People(){next=NULL;} 13 string Name(){return name;} 14 string Tel(){return tel;} 15 }; 16 17 string n,t; 18 char op,file[1000]; 19 class TelBook{ 20 private: 21 People *head,*p; 22 public: 23 TelBook(){head=p=NULL;} 24 ~TelBook(){ 25 People *tp; 26 while(head!=NULL){ 27 tp=head->next; 28 delete head; 29 head=tp; 30 } 31 p=NULL; 32 head=NULL; 33 } 34 void find(string n){ 35 People *q=head; 36 while(q!=NULL){ 37 if(q->Name()==n){ 38 cout<<"找到了(下一个? y/n)"<<q->Name()<<": "<<q->Tel()<<endl; 39 while(cin>>op){ 40 if(op=='n'||op=='N')return; 41 if(op=='y'||op=='Y')break; 42 } 43 } 44 q=q->next; 45 } 46 cout<<"已遍历结束,找不到了。"<<endl; 47 } 48 void add(string n,string t){ 49 People *q=p; 50 p=new People(n,t); 51 if(q!=NULL)q->next=p; 52 else head=p; 53 cout<<"添加了一条记录"<<endl; 54 } 55 void remove(string n){ 56 People *last=NULL,*q=head; 57 while(q!=NULL){ 58 if(q->Name()==n){ 59 cout<<"是否删除(y/n(下一个))"<<q->Name()<<": "<<q->Tel()<<endl; 60 while(cin>>op){ 61 if(op=='n'||op=='N')break; 62 if(op=='y'||op=='Y'){ 63 if(head==q) 64 head=p=NULL; 65 else{ 66 last->next=q->next; 67 if(p==q)p=last; 68 } 69 q->~People(); 70 cout<<"删除成功"<<endl; 71 break; 72 } 73 } 74 } 75 last=q; 76 q=q->next; 77 } 78 cout<<"已遍历结束。"<<endl; 79 } 80 void input(){ 81 cout<<"请输入需要打开电话本的文件名:"<<endl; 82 cin>>file; 83 ifstream in(file); 84 if(!in){ 85 cout<<"文件打开失败!\n"; 86 return; 87 } 88 while(in>>n>>t) add(n,t); 89 cout<<"电话本打开成功!"<<endl; 90 in.close(); 91 } 92 void output(){ 93 cout<<"请输入需要保存电话本的文件名:"<<endl; 94 cin>>file; 95 ofstream out(file); 96 if(!out){ 97 cout<<"文件打开失败!\n"; 98 return; 99 } 100 People *q=head; 101 while(q!=NULL){ 102 out<<q->Name()<<" "<<q->Tel()<<endl; 103 q=q->next; 104 } 105 cout<<"电话本保存成功!"<<endl; 106 out.close(); 107 } 108 }b; 109 int main(){ 110 while(1){ 111 cout<<"(1)打开电话本(2)保存电话本(3)查找(4)添加(5)删除"<<endl; 112 while(cin>>op && (op<'1'||op>'5')); 113 switch(op){ 114 case '1':b.input();break; 115 case '2':b.output();break; 116 case '3': 117 cout<<"请输入需要查找的姓名:"<<endl; 118 cin>>n; 119 b.find(n); 120 break; 121 case '4': 122 cout<<"请输入姓名 电话:"<<endl; 123 cin>>n>>t; 124 b.add(n,t); 125 break; 126 case '5': 127 cout<<"请输入需要删除的人的姓名:"<<endl; 128 cin>>n; 129 b.remove(n); 130 break; 131 default:break; 132 } 133 } 134 return 0; 135 }
View Code
实验问题
- 用什么实现删除、插入数据?
很容易想到链表,于是在电话本这个类里面就有一个head指针指向开头和p指针指向最后一个。 - 电话号码用整型?
不行,不但是因为位数不够,还有可能有前导0或短线。 - 删除时,也需要查找,是否调用find?
不好,因为需要另外传递参数,这样find的设计就变复杂了,而且在指针传参时,没有改变指针的值,所以干脆在remove函数里另外写过查找。 - error: no matching function for call to
'std::basic_ifstream::open(std::string&)
原因是C++的string类无法作为open的参数,string file 改为char file[1000]。
┆凉┆暖┆降┆等┆幸┆我┆我┆里┆将┆ ┆可┆有┆谦┆戮┆那┆ ┆大┆始┆ ┆然┆
┆薄┆一┆临┆你┆的┆还┆没┆ ┆来┆ ┆是┆来┆逊┆没┆些┆ ┆雁┆终┆ ┆而┆
┆ ┆暖┆ ┆如┆地┆站┆有┆ ┆也┆ ┆我┆ ┆的┆有┆精┆ ┆也┆没┆ ┆你┆
┆ ┆这┆ ┆试┆方┆在┆逃┆ ┆会┆ ┆在┆ ┆清┆来┆准┆ ┆没┆有┆ ┆没┆
┆ ┆生┆ ┆探┆ ┆最┆避┆ ┆在┆ ┆这┆ ┆晨┆ ┆的┆ ┆有┆来┆ ┆有┆
┆ ┆之┆ ┆般┆ ┆不┆ ┆ ┆这┆ ┆里┆ ┆没┆ ┆杀┆ ┆来┆ ┆ ┆来┆