程序设计与问题求解II实验指导书V10.docx
《程序设计与问题求解II实验指导书V10.docx》由会员分享,可在线阅读,更多相关《程序设计与问题求解II实验指导书V10.docx(24页珍藏版)》请在冰豆网上搜索。
程序设计与问题求解II实验指导书V10
程序设计与问题求解II
实验指导书
《程序设计与问题求解II》教改项目组编
2011年3月
目录
实验一数组、结构体和函数综合编程3
一、实验目的3
二、实验内容3
三、实验结果与分析5
实验二递归程序设计6
一、实验目的6
二、实验内容6
三、实验结果与分析7
实验三类与对象
(一)8
一、实验目的8
二、实验内容8
三、实验结果与分析11
实验四类与对象
(二)12
一、实验目的12
二、实验内容12
三、实验结果与分析14
实验五继承与多态15
一、实验目的15
二、实验内容15
实例讲解:
18
三、实验结果与分析20
实验六运算符重载和模板类21
一、实验目的21
二、实验内容21
三、实验结果与分析22
实验七流与文件操作编程23
一、实验目的:
23
二、实验内容:
23
三、实验结果与分析23
实验八链表编程24
一、实验目的:
24
二、实验内容:
24
三、实验结果与分析25
实验一数组、结构体和函数综合编程
一、实验目的
1.复习数组,结构体和函数的相关知识;
2.掌握利用数组存储数据和进行编程的方法;
3.进一步掌握函数的编写。
二、实验内容
1.学生成绩统计
从键盘输入一个班(全班最多不超过30人)学生某门课的成绩,当输入成绩为负值时,输入结束,分别实现下列功能:
(1)统计不及格人数并打印不及格学生名单;
(2)统计成绩在全班平均分及平均分之上的学生人数,并打印这些学生的名单;
(3)统计各分数段的学生人数及所占的百分比。
注:
将成绩分为六个分数段,60分以下为第0段,60~69为第1段,70~79为第2段,80~89为第3段,90~99为第4段,100分为第5段。
编程要求:
1.较好的用户输入输出提示信息
2.使用子函数来实现上述各个功能,并且要使用结构体数组来实现,该结构体中包括学生学号和成绩
3.最好不要使用全局变量
提示:
typedeftagStudent
{
longnum;//学生学号
floatscore;//学生分数
}Student;
供参考的函数原型如下:
/*函数功能:
从键盘输入一个班学生某门课的成绩及其学号
当输入成绩为负值时,输入结束
函数参数:
存放学生信息的Student结构体数组
函数返回值:
学生总数
*/
intReadScore(Studentstu[]);
/*函数功能:
统计不及格人数并打印不及格学生名单
函数参数:
存放学生信息的Student结构体数组
整型变量n,存放学生总数
函数返回值:
不及格人数
*/
intGetFail(Studentstu[],intn);
/*函数功能:
计算全班平均分
函数参数:
存放学生信息的Student结构体数组,整型变量n,存放学生总数
函数返回值:
平均分
*/
floatGetAver(Studentstu[],intn);
/*函数功能:
统计成绩在全班平均分及平均分之上的学生人数并打印其学生名单
函数参数:
存放学生信息的Student结构体数组,整型变量n,存放学生总数
函数返回值:
成绩在全班平均分及平均分之上的学生人数
*/
intGetAboveAver(Studentstu[],intn);
/*函数功能:
统计各分数段的学生人数及所占的百分比
函数参数:
存放学生信息的Student结构体数组,整型变量n,存放学生总数
函数返回值:
无
*/
voidGetDetail(Studentstu[],intn);
2.成绩排名次
某班期末考试科目为数学(MT)、英语(EN)和物理(PH),有最多不超过30人参加考试。
要求:
(1)计算每个学生的总分和平均分;
(2)按总分成绩由高到低排出成绩的名次;
(3)打印出名次表,表格内包括学生编号、各科分数、总分和平均分;
(4)任意输入一个学号,能够查找出该学生在班级中的排名及其考试分数
编程要求:
1.较好的用户输入输出提示信息
2.使用子函数来实现上述各个功能
3.必须用结构体数组实现
提示:
设计好存放学生信息的结构体,方便编程。
用函数编程实现计算每个学生的总分;
用函数编程实现按总分由高到低对学生成绩排序
用函数编程实现查找学号为k的学生在班级中的排名名次及相关成绩等信息,找不到时返回-1值
三、实验结果与分析
将源程序、运行结果和分析以及实验中遇到的问题和解决问题的方法,写在实验报告上。
实验二递归程序设计
一、实验目的
1.学习递归程序的一般设计方法;
2.了解和熟练多参数的递归函数的使用;
3.掌握用递归程序设计方法解决实际问题。
二、实验内容
1.求游戏人员的年龄
有5个人围坐在一起,问第五个人多大年纪,他说比第4个人大2岁;问第4个人,他说比第3个人大2岁;问第3个人,他说比第2个人大2岁;问第2个人,他说比第1个人大2岁。
第一个人说自己10岁,问第5个人多大年纪。
提示:
此程序为递归问题,递归公式为:
2.计算最大公约数
利用计算最大公约数的三条性质,用递归方法计算两个整数的最大公约数。
性质1:
如果x>y,则x和y的最大公约数与x-y和y的最大公约数相同,即
性质2:
如果y>x,则x和y的最大公约数与x和y-x的最大公约数相同,即
性质3:
如果x=y,则x和y的最大公约数与x值和y值相同,即
注意:
上述两个代码的编写都非常简单,在代码编写成功后,需要自己再回忆一下代码的编写过程,复习以前学过的内容,学习代码的调试。
3.整数划分问题
将正整数n表示成一系列正整数之和:
n=n1+n2+…+nk,其中n1≥n2≥…≥nk≥1,k≥1。
正整数n的这种表示称为正整数n的划分。
求正整数n的不同划分个数。
例如正整数6有如下10种不同的划分:
5+1;4+2,4+1+1;3+3,3+2+1,3+1+1+1;
2+2+2,2+2+1+1,2+1+1+1+1;1+1+1+1+1+1。
前面的几个例子中,问题本身都具有比较明显的递归关系,因而容易用递归函数直接求解。
在本例中,如果设p(n)为正整数n的划分数,则难以找到递归关系,因此考虑增加一个自变量:
将最大加数n1不大于m的划分个数记作q(n,m)。
可以建立q(n,m)的如下递归关系。
如要求解6的整数划分,即是求q(6,5).其中n=6,m=5。
编程要求:
(1)编程求出任意10以内的整数的所有可能划分总数。
(必做!
)
(2)选作部分:
打印输出6的所有划分形式。
三、实验结果与分析
将源程序、运行结果和分析以及实验中遇到的问题和解决问题的方法,写在实验报告上。
实验三类与对象
(一)
一、实验目的
1.初步掌握面向对象的思想,类的封装,多文件项目;
2.掌握类的概念、类的成员的概念和类的封装性;
3.掌握类对象的定义;
4.理解类的成员的访问控制的含义,公有、私有和保护成员的区别;
5.初步掌握用类和对象编制基于对象的编程;
6.学习检查和调试基于对象的程序;
7.掌握工程文件的编译方法;
8.逐步从面向过程编程转到面向对象编程。
二、实验内容
1、验证题目
将下面的程序正确划分到不同的文件中,编译链接运行,观测运行结果与期望是否相符。
时间类:
//mytime.h
#ifndefMYTIME_H_
#defineMYTIME_H_
#include
usingnamespacestd;
classTime
{
private:
inthours;
intminutes;
public:
Time();
Time(inth,intm=0);
voidAddMin(intm);
voidAddHr(inth);
voidReset(inth=0,intm=0);
TimeSum(constTime&t)const;
voidShow()const;
};
#endif
//mytime.cpp
#include"mytime.h"
Time:
:
Time()
{
hours=minutes=0;
}
Time:
:
Time(inth,intm)
{
hours=h;
minutes=m;
}
voidTime:
:
AddMin(intm)
{
minutes+=m;
hours+=minutes/60;
minutes%=60;
}
voidTime:
:
AddHr(inth)
{
hours+=h;
}
voidTime:
:
Reset(inth,intm)
{
hours=h;
minutes=m;
}
TimeTime:
:
Sum(constTime&t)const
{
Timesum;
sum.minutes=minutes+t.minutes;
sum.hours=hours+t.hours+sum.minutes/60;
sum.minutes%=60;
returnsum;
}
voidTime:
:
Show()const
{
cout<cout<}
//usetime.cpp
#include
usingnamespacestd;
#include"mytime.h"
intmain()
{
TimeA;
TimeB(5,40);
TimeC(2,55);
cout<<"A=";
A.Show();
cout<<"B=";
B.Show();
cout<<"C=";
C.Show();
A=B.Sum(C);
cout<<"B.Sum(C)=";
A.Show();
return0;
}
2、找错误
请检查下面程序,找出其中的错误(先不要上机,自己先检查),并改正之。
然后上机调试,使之能正常运行,运行时从键盘输入时、分、秒的值,检查输出是否正确。
#include
usingnamespacestd;
classTime
{
inthour;
intminute;
intsec;
voidset_time();
voidshow_time();
};
Timet;
intmain()
{
set_time();
show_time();
return0;
}
voidset_time()
{
cin>>t.hour;
cin>>t.minute;
cin>>t.sec;
}
voidshow_time()
{
cout<"<"<}
3、应用类和对象编程求出长方体的体积
需要求三个长方柱的体积,请编写一个基于对象的程序,数据成员包括length(长)、width(宽)、height(高)。
要求用成员函数实现以下功能:
(1)、由键盘输入三个长方柱的长、宽、高;
(2)、计算三个长方柱的体积;
(3)、输出三个长方柱的体积;
三、实验结果与分析
将源程序、运行结果和分析以及实验中遇到的问题和解决问题的方法,写在实验报告上。
实验四类与对象
(二)
一、实验目的
1.进一步加深对类和对象的理解;
2.掌握构造函数和析构函数的含义与作用、定义方式和使用方法,能够根据要求正确定义和重载构造函数。
能够根据给定的要求定义类并实现类的成员函数;
3.掌握友元函数的含义和使用,友元函数和成员函数的区别。
二、实验内容
1、设计一个类Cdateinfo,其私有数据成员有year(年)、month(月)、day(日),要求其满足下述要求。
(1)要求有一个无参数的构造函数,其初始的年、月、日分别为:
2000,1,1。
(2)要求有一个带参数的构造函数,起参数分别对应年、月、日。
(3)要求用一个成员函数实现日期的设置。
(4)要求用一个成员函数实现日期的输出。
在上述程序的基础上将
(1)和
(2)的两个构造函数改为一个带默认参数的构造函数,并使年、月、日的默认值分别为:
2000,1,1。
2、分析以下程序,掌握程序的运行过程,进一步掌握普通构造函数、复制构造函数和析构函数:
#include
usingnamespacestd;
classBox
{public:
Box(int=10,int=10,int=10);
Box:
:
Box(Box&b);
intvolume();
private:
intheight;
intwidth;
intlength;
};
Box:
:
Box(Box&b)
{
height=b.height;
width=b.width;
length=b.length;
cout<<"copyconstructor"<}
Box:
:
Box(inth,intw,intlen)
{
height=h;
width=w;
length=len;
cout<<"constructor"<}
intBox:
:
volume()
{
return(height*width*length);
}
voidfunc1(Boxb)
{
cout<}
Boxfunc2()
{
Boxb(20,30);
returnb;
}
intmain()
{
Boxbox1(10,20,10);
Boxbox2(box1);
cout<func1(box1);
Boxbox3;
box3=func2();
cout<return0;
}
3、分析和运行下面的程序,注意友元函数dist(pointa,pointb)的作用。
将友元函数dist(pointa,pointb)改为Point类的公有成员函数Point:
:
dist(point&b),请修改主函数中的相应代码,使程序功能不变。
#include
#include
usingnamespacestd;
classPoint
{
doublex;
doubley;
public:
Point(doublea,doubleb)
{
x=a;
y=b;
}
frienddoubledist(Pointa,Pointb);
};
doubledist(Pointa,Pointb)
{
returnsqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
voidmain()
{
Pointp1(1,2);
Pointp2(5,2);
cout<}
三、实验结果与分析
将源程序、运行结果和分析以及实验中遇到的问题和解决问题的方法,写在实验报告上。
实验五继承与多态
一、实验目的
1.理解继承的含义,掌握派生类的定义方法和实现;
2.理解公有继承下基类成员对派生类成员和派生类对象的可见性,能正确地访问继承层次中的各种类成员;
3.理解保护成员在继承中的作用,能够在适当的时候选择使用保护成员以便派生类成员可以访问基类的部分非公开的成员;
4.理解虚函数在类的继承层次中的作用,虚函数的引入对程序运行时的影响,能够对使用虚函数的简单程序写出程序结果。
二、实验内容
1、编写一个学生和教师数据输入和显示程序,要求:
学生数据有编号、姓名、班级和成绩,教师数据有编号、姓名、职称和部门。
要求将编号、姓名输入和显示设计成一个类person,并作为学生数据操作类student和教师类数据操作类teacher的基类。
2、利用虚函数实现的多态性来求四种几何图形的面积之和。
这四种几何图形是:
三角形、矩形、正方形和圆。
几何图形的类型可以通过构造函数或通过成员函数来设置。
为设置几何图形的数据并求出几何图形的面积,需要定义一个包含两个虚函数的类:
classShape
{public:
virtualfloatArea(void)=0;//求面积
virtualvoidSetdata(float,float=0)=0;//设置图形数据
};
因面积的计算依赖于几何图形,故在类中只能定义一个纯虚函数Area。
同理,设置几何图形数据的函数Setdata也只能定义为虚函数。
把这个基类派生出其它几何图形类。
如派生出的三角形类为:
classTriangle:
publicShape
{floatW,H;//三角形边长为W,高为H
public:
Triangle(floatw=0,floath=0){W=w;H=h;}
floatArea(void){returnW*H/2;}
voidSetdata(floatw,floath=0){W=w;H=h;}
};
在派生类中定义了基类中两个虚函数的实现。
为了实现求面积和设置数据的多态性,必须定义一个类,该类中定义一个指向基类Shape的指针数组,其元素分别指向由基类Shape派生出的不同的几何图形类,并完成求出所有几何图形面积之和,以及设置参数的函数。
一个完整的参考程序如下:
#include
#include
classShape
{public:
virtualfloatArea(void)=0;//虚函数
virtualvoidSetdata(float,float=0)=0;//虚函数
};
classTriangle:
publicShape
{floatW,H;//三角形边长为W,高为H
public:
Triangle(floatw=0,floath=0){W=w;H=h;}
floatArea(void){returnW*H/2;}//定义虚函数
voidSetdata(floatw,floath=0){W=w;H=h;}//定义虚函数
};
classRectangle:
publicShape
{floatW,H;//矩形边长为W,高为H
public:
Rectangle(floatw=0,floath=0){W=w;H=h;}
floatArea(void){returnW*H;}//定义虚函数
voidSetdata(floatw,floath=0){W=w;H=h;}//定义虚函数
};
classSquare:
publicShape
{floatS;//正方形边长S
public:
Square(floata=0){S=a;}
floatArea(void){returnS*S/2;}//定义虚函数
voidSetdata(floatw,floath=0){S=w;}//定义虚函数
};
classCircle:
publicShape
{floatR;//圆的半径为R
public:
Circle(floatr=0){R=r;}
floatArea(void){return3.1415926*R*R;}//定义虚函数
voidSetdata(floatw,floath=0){R=w;}//定义虚函数
};
classCompute
{Shape**s;//指向基类的指针数组
public:
Compute()
{s=newShape*[4];//给几何图形设置参数
s[0]=newTriangle(3,4);
s[1]=newRectangle(6,8);
s[2]=newSquare(6.5);
s[3]=newCircle(5.5);
}
floatSumArea(void);
~Compute();
voidSetdata(intn,floata,floatb=0)//A
{s[n]->Setdata(a,b);}//B
};
Compute:
:
~Compute()//释放动态分配的存储空间
{for(inti=0;i<4;i++)deletes[i];
delete[]s;
}
floatCompute:
:
SumArea(void)
{floatsum=0;
for(inti=0;i<4;i++)
sum+=s[i]->Area();//通过基类指针实现多态性
returnsum;
}
voidmain(void)
{Computea;
cout<<"四种几何图形的面积="<a.Setdata(2,10);//设置正方形的边长
cout<<"四种几何图形的面积="<a.Setdata(0,10,12);//设置三角形的边长和高
cout<<"四种几何图形的面积="<a.Setdata(1,2,5);//设置正方形的长和宽
cout<<"四种几何图形的面积="<a.Setdata(3,15.5);
cout<<"四种几何图形的面积="<}
程序中A行的Setdata函数属于函数重载,它不是虚函数。
该函数中的B行通过基类指针实现多态性。
实例讲解:
#include
usingstd:
:
cout;
usingstd:
:
endl;
classBaseClass{
public:
/*virtual*/voidprint(){//请去掉注释后查看结果有何不同,