第3章C++上机实验指导 3.1上机实验题 3.1.1实验1上机环境和C++基础编程练习 1. 实验目的 (1) 了解Visual C++或CodeBlocks集成开发环境,或Linux下的C++开发环境。 (2) 熟悉集成开发环境的基本编辑命令及其功能键,练习使用常用功能菜单命令。 (3) 学习完整的C++程序开发过程(编译、连接、调试、运行及查看结果)。 (4) 理解简单的C++程序结构。 (5) 掌握C++基本数据类型变量、常量的使用,理解其内存的概念。 (6) 学习C++中各种运算式的使用。 2. 实验内容 编写程序实现求解二次方程的解。 基本要求如下: (1) 仔细阅读上机实验环境指导,熟悉上机环境。 (2) 设置用户目录路径,编写程序,编译、调试并查看运行结果。 (3) 学习如何根据编译信息定位并排除语法错误和语法警告。 (4) 学习并模仿主教材上的程序编写风格,养成良好编程习惯。 3.1.2实验2控制结构编程练习 1. 实验目的 (1) 理解C++程序的控制结构。 (2) 熟练使用条件判断。 (3) 熟练使用各种循环结构。 (4) 进一步提高程序调试与修改编译错误的能力。 (5) 注意提高程序的可读性。 2. 实验内容 编写程序模拟实现以下游戏: 现有两人玩猜拳游戏,每人可用拳头表示3种物体(石头(rock)、剪刀(scissors)和布(cloth))中的一种,两人同时出拳,游戏胜负规则如下。 (1) 石头对剪刀: 石头赢; (2) 剪刀对布: 剪刀赢; (3) 布对石头: 布赢。 3.1.3实验3函数编程练习 1. 实验目的 (1) 掌握函数的声明、定义方法。 (2) 理解函数参数的传递。 (3) 掌握函数调用方法。 2. 实验内容 (1) 编写一个函数Take(),该函数返回正整数n的第k位数字。例如,如果n为543210,则调用函数Take(n,0)返回数字0,而调用函数Take(n,3)返回数字3。注意,数字的位次顺序为从右到左,从0开始。 (2) 编写一个带默认参数的函数,计算4次多项式的值,并测试该函数。 3.1.4实验4构造数据类型编程练习 1. 实验目的 (1) 理解数组的概念,掌握数组应用的一般方法。 (2) 理解指针的概念,掌握指针的使用。 (3) 深入理解指针与数组的区别与联系。 2. 实验内容 (1) 编写并测试一个函数,将一个二维数组顺时针旋转90°。例如将数组 123 456 789转换为741 852 963 (2) 定义一个函数invert(),将数组a中的n个整数按相反的顺序存放。程序实现要求如下: 用数组作为函数形参实现函数invert(int A[], int n),函数调用时实参为数组。 用数组作为函数形参实现函数invert(int A[], int n),函数调用时实参为指针。 用指针作为函数形参实现函数invert(int *A, int n),函数调用时实参为数组。 用指针作为函数形参实现函数invert(int *A, int n),函数调用时实参为指针。 (3) 用枚举构造数据类型改写实验2中的猜拳游戏。 3.1.5实验5类与对象编程练习 1. 实验目的 (1) 掌握类的定义,根据具体需求设计类。 (2) 深入理解C++中类的封装性。 (3) 会根据类创建各种对象。 (4) 掌握对象的各种成员的使用方法。 (5) 通过定义构造函数实现对象的初始化。 2. 实验内容 定义一个FDAccount类,用于描述一个定期存折(fixed deposit),实现现金支取、余额合计、信息显示等。存折基本信息包括账号、账户名称、存款余额、存款期限(以月为单位)、存款利率(以百分点为单位)等。 3.1.6实验6继承与派生编程练习 1. 实验目的 (1) 掌握派生与继承的概念与使用方法。 (2) 运用继承机制对现有的类进行重用。 (3) 掌握继承中的构造函数与析构函数的调用顺序。 (4) 为派生类设计合适的构造函数初始化派生类。 (5) 深入理解继承与组合的区别。 2. 实验内容 设计一个人员类person和一个日期类date,由人员类派生出学生类student和教师类professor,学生类和教师类的数据成员birthday为日期类。 3.1.7实验7多态性编程练习 1. 实验目的 (1) 理解多态性的概念。 (2) 掌握如何用虚函数实现动态联编。 (3) 掌握如何利用虚基类。 2. 实验内容 设计一个飞机类plane,由它派生出歼击机类fighter和轰炸机类bomber,歼击机类fighter和轰炸机类bomber又共同派生出歼轰机(多用途战斗机)。利用虚函数和虚基类描述飞机类及其派生的类族。 3.1.8实验8类模板编程练习 1. 实验目的 (1) 理解类模板的概念。 (2) 掌握类模板的定义、实例化过程。 (3) 掌握类模板的运用。 (4) 通过类模板进一步理解C++中代码重用的思想。 2. 实验内容 定义一个通用队列模板类,队列中的数据元素类型可以是字符型、双精度型和其他数据类型,队列的基本操作包括队列的初始化、队列的析构、进队列、出队列、判断队列是否为空和队列是否是满队列,测试该队列。 3.1.9实验9输入/输出流与文件系统编程练习 1. 实验目的 (1) 理解C++的输入/输出流的概念。 (2) 熟悉I/O流的工作过程。 (3) 熟悉各种格式标志和各种格式控制方法。 (4) 分清文本文件和二进制文件的区别。 (5) 掌握二进制文件的输入/输出的步骤与操作。 (6) 会运用文件指针以及各种标志。 2. 实验内容 定义一个学生类,包含学生的学号、姓名和成绩等基本信息,将学生信息写入二进制文件student.dat中,实现对学生信息的显示、查询和删除等基本功能。 3.1.10实验10string类字符串处理编程练习 1. 实验目的 (1) 理解C++中的string类。 (2) 使用C++标准类库中的string定义字符串对象。 (3) 能使用string类成员函数、操作符对字符串对象进行各种操作。 2. 实验内容 编写程序,对输入文件中的内容进行分析,统计文件的行数、单词数和每个单词出现的次数。 3.1.11实验11异常处理编程练习 1. 实验目的 理解与使用C++的异常处理机制。 2. 实验内容 模拟车站机场的危险品检查机,若未发现危险品,通过; 若发现危险品,抛出异常。 3.2上机实验题参考解答 3.2.1实验1上机环境和C++基础编程练习 编写程序实现求解二次方程的解。 【参考解答】 #include<iostream> #include<cmath> using namespace std; void main() { float a,b,c; //方程系数 cout<<"Enter the coefficients of a quadratic equation:"<<endl; cout<<"\ta:"; cin>>a; cout<<"\tb:"; cin>>b; cout<<"\tc:"; cin>>c; //显示方程 cout<<"The equation is : "<<a<<"*x*x+ "<<b<<"*x+ "<<c<<" =0"<<endl; float d=b*b-4*a*c; float x1=(-b+sqrt(d))/(2*a); //解一 float x2=(-b-sqrt(d))/(2*a); //解二 cout<<"The solutions are:"<<endl; //输出解 cout<<"\tx1="<<x1<<endl; cout<<"\tx2="<<x2<<endl; cout<<"Check:"<<endl; //检查解 cout<<"\ta*x1*x1+b*x1+c="<<a*x1*x1+b*x1+c<<endl; cout<<"\ta*x2*x2+b*x2+c="<<a*x2*x2+b*x2+c<<endl; } 运行结果: Enter the coefficients of a quadratic equation: a:1↙ b:3↙ c:2↙ The equation is : 1*x*x+ 3*x+ 2 =0 The solutions are: x1=-1 x2=-2 Check: a*x1*x1+b*x1+c=0 a*x2*x2+b*x2+c=0 【思考问题】 ① 尝试输入不同的方程系数,会出现什么情况? ② 程序总能够求得方程的解吗?该注意什么? ③ 如果程序出现溢出错误,怎么办? 3.2.2实验2控制结构编程练习 现有两人玩猜拳游戏,每人可用拳头表示3种物体(石头、剪刀和布)中的一种,两人同时出拳,游戏胜负规则如下。 (1) 石头对剪刀: 石头赢。 (2) 剪刀对布: 剪刀赢。 (3) 布对石头: 布赢。 【参考解答】 #include<iostream> using namespace std; #define Player1 0; #define Player2 1; #define Tie 2; void main() { int choice1,choice2,winner; cout<<"Choose rock(0),cloth(1),or scissors(2):"<<endl; cout<<"Player #1:"; //1号选手选择 cin>>choice1; cout<<"Player #2:"; //2号选手选择 cin>>choice2; switch(choice2-choice1)//判断胜负结果 { case 0: winner=Tie; cout<<"\tYou tied."<<endl; break; case -1: case 2: winner=Player1; cout<<"\tPlayer #1 wins."<<endl; break; case -2: case 1: winner=Player2; cout<<"\tPlayer #2 wins."<<endl; } } 运行结果: Choose rock(0),cloth(1),or scissors(2): Player #1:2↙ Player #2:0↙ Player #2 wins. 【思考问题】 ① 程序可以用if…else嵌套实现吗?如果可以,请加以改写。 ② 如果游戏规定比赛连续进行3次,赢两次或两次以上者最终获胜,如何改写程序? 3.2.3实验3函数编程练习 (1) 编写一个函数Take(),该函数返回正整数n的第k位数字。例如,如果n为543210,则调用函数Take(n,0)返回数字0,而调用函数Take(n,3)返回数字3。注意,数字的位次顺序为从右到左,从0开始。 【参考解答】 #include<iostream> using namespace std; int Take(long ,int); void main() { int n,k; cout<<"Enter a integer:"; cin>>n; do{ cout<<"location:"; cin>>k; cout<<"Digit number "<<k<<" of "<<n<<" is "<<Take(n,k)<<endl; }while(k>0); } int Take(long n,int k) { for(int i=0;i<k;i++) n/=10;//去掉最右边的数字 return n%10; } 运行结果: Enter a integer:2467389↙ location:3↙ Digit number 3 of 2467389 is 7 location:5↙ Digit number 5 of 2467389 is 4 location:0↙ Digit number 0 of 2467389 is 9 (2) 编写一个带默认参数的函数,计算4次多项式的值,并测试该函数。 【参考解答】 #include<iostream> using namespace std; double polynomial(double,double,double=0,double=0,double=0,double=0); //函数原型 void main() { double x; cout<<"Please enter x: "; cin>>x; cout<<"polynomial(x,1)="<<polynomial(x,1)<<endl; cout<<"polynomial(x,1,2)="<<polynomial(x,1,2)<<endl; cout<<"polynomial(x,1,2,3)="<<polynomial(x,1,2,3)<<endl; cout<<"polynomial(x,1,2,3,4)="<<polynomial(x,1,2,3,4)<<endl; cout<<"polynomial(x,1,2,3,4,5)="<<polynomial(x,1,2,3,4,5)<<endl; } double polynomial(double x,double a0,double a1,double a2,double a3,double a4) { return a0+(a1+(a2+(a3+a4*x)*x)*x)*x; } 运行结果: Please enter x:2.36↙ polynomial(x,1)=1 polynomial(x,1,2)=5.72 polynomial(x,1,2,3)=22.4288 polynomial(x,1,2,3,4)=75.0058 polynomial(x,1,2,3,4,5)=230.108 【思考问题】 ① 在C++中使用带有默认形参值的函数有什么好处? ② 在C++中使用带有默认形参值的函数时应该注意什么问题? ③ 使用带有默认形参值的函数时,如果省掉了某个实参,应该注意什么? ④ 能够将这个程序改为用函数模板实现吗? 3.2.4实验4构造数据类型编程练习 (1) 编写并测试一个函数,将一个二维数组顺时针旋转90°。例如将数组 123 456 789转换为741 852 963 【参考解答】 #include<iostream> using namespace std; const int SIZE=3; typedef int Matrix[SIZE][SIZE]; void print(Matrix); void rotate(Matrix); void main() { Matrix m={{1,2,3},{4,5,6},{7,8,9}}; cout<<"Before matrix is rotated:"<<endl; print(m); //输出旋转前的二维数组 cout<<"After matrix is rotated:"<<endl; rotate(m); //旋转二维数组 print(m); //输出旋转后的二维数组 } void print(Matrix A) //输出数组元素 { int i,j; for(i=0;i<SIZE;i++) { for(j=0;j<SIZE;j++) cout<<A[i][j]<<"\t"; cout<<endl; } } void rotate(Matrix A)//旋转二维数组 { int i,j; Matrix temp; for(i=0;i<SIZE;i++) { for(j=0;j<SIZE;j++) temp[i][j]=A[SIZE-j-1][i]; } for(i=0;i<SIZE;i++) { for(j=0;j<SIZE;j++) A[i][j]=temp[i][j]; } } 运行结果: Before matrix is rotated: 1 2 3 4 5 6 7 8 9 After matrix is rotated: 7 4 1 8 5 2 9 6 3 【思考问题】 ① 数组会溢出吗?为什么C++中的数组可能溢出,其实质是什么? ② 改写上面的程序,使得数组溢出,然后思考C++是如何处理数组溢出的。 (2) 定义一个函数invert(),将数组a中的n个整数按相反的顺序存放。程序实现要求如下: 用数组作为函数形参实现函数invert(int A[], int n),函数调用时实参为数组。 用数组作为函数形参实现函数invert(int A[], int n),函数调用时实参为指针。 用指针作为函数形参实现函数invert(int *A, int n),函数调用时实参为数组。 用指针作为函数形参实现函数invert(int *A, int n),函数调用时实参为指针。 要求1: 用数组作为函数形参实现函数invert(int A[], int n),函数调用时实参为数组。 【参考解答】 #include<iostream> using namespace std; void invert(intA[], int n)//将数组元素反序存放 { int i,j,temp;