C++面向对象程序设计实验指导手册.docx
《C++面向对象程序设计实验指导手册.docx》由会员分享,可在线阅读,更多相关《C++面向对象程序设计实验指导手册.docx(22页珍藏版)》请在冰点文库上搜索。
C++面向对象程序设计实验指导手册
C++面向对象程序设计
实验指导手册
班级:
_______________
学号:
_______________
姓名:
_______________
电子与信息工程学院计算机科学系
第一部分上机实验的指导思想和要求
一、上机实验的目的
学习C++程序设计不能满足于“懂得了”,满足于了解了语法和能看懂书上的程序,而应当掌握程序设计的全过程,即能独立编写出源程序,独立上机调试程序,独立运行程序和分析结果。
设计C++的初衷是为方便开发大型程序,虽然在学校中初学C++时还没有机会接触到大型程序,更不可能编写出能供实际应用的大型程序,而只能接触到比较简单的程序。
但是应当通过学习C++课程,对C++有比较全面的、然而是初步的认识,为今后进一步学习和应用C++打下良好的基础。
程序设计是一门实践性很强的课程,必须十分重视实践环节。
许多实际的知识不是靠听课和看书学到手的,而是通过长时间的实践积累的。
要提倡通过实践去掌握知识的方法。
必须保证有足够的上机实验时间,学习本课程应该至少有30小时的上机时间,最好能做到与授课时间之比为1:
1。
除了学校规定的上机实验以外,应当提倡学生自己课余抽时间多上机实践。
上机实验的目的,绝不仅是为了验证教材和讲课的内容,或者验证自己所编的程序正确与否。
学习程序设计,上机实验的目的是:
(1)加深对讲授内容的理解,尤其是一些语法规定,光靠课堂讲授,既枯燥无味又难以记住,但它们是很重要的,初学者的程序出错往往错在语法上。
通过多次上机,就能自然地、熟练地掌握。
通过上机来掌握语法规则是行之有效的方法。
(2)熟悉所用的计算机系统的操作方法,也就是了解和熟悉C++程序开发的环境。
一个程序必须在一定的外部环境下才能运行,所谓“环境”,就是指所用的计算机系统的硬件和软件条件,或者说是工作平台。
使用者应该了解为了运行一个C++程序需要哪些必要的外部条件(例如硬件配置、软件配置),可以利用哪些系统的功能来帮助自己开发程序。
每一种计算机系统的功能和操作方法不完全相同,但只要熟练掌握一两种计算机系统的使用,再遇到其他系统时便会触类旁通,很快地学会。
(3)学会上机调试程序。
也就是善于发现程序中的错误,并且能很快地排除这些错误,使程序能正确运行。
经验丰富的人,在编译连接过程中出现“出错信息”时,一般能很快地判断出错误所在,并改正之。
而缺乏经验的人即使在明确的“出错提示”下也往往找不出错误而求助于别人。
要真正掌握计算机应用技术,就不仅应当了解和熟悉有关理论和方法,还要求自己动手实现。
对程序设计来说,则要求会编程序并上机调试通过。
因此调试程序不仅是得到正确程序的一种手段,而且它本身就是程序设计课程的一个重要的内容和基本要求,应给予充分的重视。
调试程序固然可以借鉴他人的现成经验,但更重要的是通过自己的直接实践来累积经验,而且有些经验是只能“会意”难以“言传”。
别人的经验不能代替自己的经验。
调试程序的能力是每个程序设计人员应当掌握的一项基本功。
因此,在做实验时千万不要在程序通过后就认为万事大吉、完成任务了,而应当在己通过的程序基础上作一些改动(例如修改一些参数、增加程序一些功能、改变某些语句等),再进行编译、连接和运行。
甚至于“自设障碍”,即把正确的程序改为有错的(例如语句漏写分号;比较符“==”错写为赋值号“=”;使数组下标出界;使整数溢出等),观察和分析所出现的情况。
这样的学习才会有真正的收获,是灵活主动的学习而不是呆板被动的学习。
二、上机实验前的准备工作
在上机实验前应事先做好准备工作,以提高上机实验的效率,准备工作至少应包括:
(1)了解所用的计算机系统(包括C++编译系统和工作平台)的性能和使用方法;
(2)复习和掌握与本实验有关的教学内容;
(3)准备好上机所需的程序。
手编程序应书写整齐,并经人工检查无误后才能上机,以提高上机效率。
初学者切忌不编程序或抄别人程序去上机,应从一开始就养成严谨的科学作风;
(4)对运行中可能出现的问题事先作出估计,对程序中自己有疑问的地方,应作出记号,以便在上机时给予注意;
(5)准备好调试和运行时所需的数据。
三、上机实验的步骤
上机实验时应该一人一组,独立上机。
上机过程中出现的问题,除了是系统的问题以外,一般应自己独立处理,不要轻易举手问教师。
尤其对“出错信息”,应善于自己分析判断。
这是学习调试程序的良好机会。
上机实验一般应包括以下几个步骤:
(1)进入C++工作环境(例如VisualC++6.0)。
(2)输入自己所编好的程序。
(3)检查一遍已输入的程序是否有错(包括输入时打错的和编程中的错误),如发现有错,及时改正。
(4)进行编译和连接。
如果在编译和连接过程中发现错误,屏幕上会出现“出错信息”,根据提示找到出错位置和原因,加以改正。
再进行编译……,如此反复直到顺利通过编译和连接为止。
(5)运行程序并分析运行结果是否合理和正确。
在运行时要注意当输入不同数据时所得到的结果是否正确。
(6)输出程序清单和运行结果。
四、实验报告
实验后,应整理出实验报告,实验报告应包括以下内容:
(1)题目;
(2)程序清单(计算机打印出的程序清单);
(3)运行结果(必须是上面程序清单所对应打印输出的结果);
(4)对运行情况所作的分析以及本次调试程序所取得的经验。
如果程序末能通过,应分析其原因。
第二部分关于程序的调试和测试
一、程序错误的类型
为了帮助各位同学调试程序和分析程序,下面简单介绍程序出错的种类。
(1)语法错误
即不符合C++语言的语法规定,例如将main错写为naim,括号不匹配,语句最后漏了分号等,这些都会在编译时被发现并指出。
这些都属于“致命错误”,不改正是不能通过编译的。
对一些在语法上有轻微毛病但不影响程序运行的错误(如定义了变量但始终未使用),编译时会发出“警告”,虽然程序能通过编译,但不应当使程序“带病工作”,应该将程序中所有导致“错误(error)”和“警告(warning)”的因素都消除,再使程序投入运行。
(2)逻辑错误
这是指程序无语法错误,也能正常运行,但是结果不对。
例如求s=l+2+3+…+100,有人写出以下语句:
for(s=0,i=1;i<100;i++)
s=s+i;
语法没有错,但求出的结果是l+2+3+…+99之和,而不是l+2+3+…+100之和,原因是少执行了一次循环。
这类错误可能是设计算法时的错误,也可能是算法正确而在编写程序时出现疏忽所致。
这种错误计算机是无法检查出来的。
如果是算法有错,则应先修改算法,再改程序。
如果是算法正确而程序写得不对,则直接修改程序。
(3)运行错误
有时程序既无语法错误,又无逻辑错误,但程序不能正常运行或结果不对。
多数情况是数据不对,包括数据木身不合适以及数据类型不匹配。
如有以下程序:
intmain()
{inta,b,c;
cin>>a>>b;
c=a/b;
cout<return0;
}
当输入的b为非零值时,运行无问题。
当输入的b为零时,运行时出现“溢出(overflow)”的错误。
如果在执行上面的cin语句时输入456.7834.56,则输出c的值为2,显然是不对的。
这是由一于输入的数据类型与输入格式符不匹配而引起的。
二、程序的测试
程序调试的任务是排除程序中的错误,使程序能顺利地运行并得到预期的效果。
程序的调试阶段不仅要发现和消除语法上的错误,还要发现和消除逻辑错误和运行错误。
除了可以利用编译时提示的“出错信息”来发现和改正语法错误外,还可以通过程序的测试来发现逻辑错误和运行错误。
程序测试的任务是尽力寻找程序中可能存在的错误。
在测试时要设想到程序运行时的各种情况,测试在各种情况下的运行结果是否正确。
程序测试是程序调试的一个组成部分。
有时程序在某些情况下能正常运行,而在另外一些情况下不能正常运行或得不到正确的结果,因此,一个程序即使通过编译并正常运行而且结果正确,还不能认为程序没有问题了。
要考虑是否在任何情况下都能正常运行并且得到正确的结果。
测试的任务就是要找出那些不能正常运行的情况和原因。
下而通过一个典型的和容易理解的例子来说明测试的概念。
求一元二次方程ax2+bx+c=0的根。
有人根据求根公式x1,2=(-b±sqrt(b2-4ac))/2a编写出以下程序:
#include
#include
usingnamespacestd;
intmain()
{floata,b,c,disc,x1,x2;
cin>>a>>b>>c;
disc=b*b-4*a*c;
x1=(-b+sqrt(disc))/(2*a);
x2=(-b-sqrt(disc))/(2*a);
cout<<”x1=”<return0;
}
当输入a,b,c的值为1,-2,-15时,输出xl的值为5,x2的值为-3。
结果是正确无误的。
但是若输入a,b,c的值为3,2,4时,屏幕上出现了出错信息,程序停止运行,原因是此时b2-4ac小于0,出现了对负数求平方根的运算,故出错。
因此,此程序只适用b2-4ac≥0的情况。
我们不能说上面的程序是错的,而只能说程序对可能出现的情况“考虑不周”,所以不能保证在任何情况下都是正确的。
使用这个程序必须满足一定的前提(b2-4ac≥0),这样,就给使用程序的人带来不便。
人们在输入数据前,必须先算一下,看b2-4ac是否大于或等于0。
一个程序应能适应各种不同的情况,并且都能正常运行并得到相应的结果。
下面分析一下求方程ax2+bx+c=0的根,有几种情况:
(1)a≠0时
①b2-4ac>0有两个不等的实根:
x1,2=(-b±sqrt(b2-4ac))/2a
②b2-4ac=0有两个相等的实根:
x1=x2=-b/2a
③b2-4ac<0有两个不等的共轭复根:
x1,2=(-b±sqrt(b2-4ac)i)/2a
(2)a=0时,方程就变成一元一次的线性方程:
bx+c=0
①当b≠0时,x=-c/b
②当b=0时,方程变为0x+c=0
当c=0时,x可以为任何值;
当c≠0时,x无解。
综合起来,共有6种情况:
①a≠0,b2-4ac>0
②a≠0,b2-4ac=0
③a≠0,b2-4ac<0
④a=0,b≠0
⑤a=0,b=0,c=0
⑥a=0,b=0,c≠0
应当分别测试程序在以上6种情况下的运行情况,观察它们是否符合要求。
为此,应准备6组数据。
用这6组数据去测试程序的“健壮性”。
在使用上面这个程序时,显然只有满足①②情况的数据才能使程序正确运行,而输入满足③~⑥情况的数据时,程序出错。
这说明程序不“健壮”。
为此,应当修改程序,使之能适应以上6种情况。
可将程序改为:
#include
#include
usingnamespacestd;
intmain()
{floata,b,c,disc,x1,x2,p,q;
cout<<"inputa,b,c:
";
cin>>a>>b>>c;
if(a==0)
if(b==0)
if(c==0)
cout<<"Itistrivial."<else
cout<<"Itisimpossible.""<else
{cout<<"Ithasonesolution:
"<cout<<"x="<<-c/b<}
else
{disc=b*b-4*a*c;
if(disc>=0)
if(disc>0)
{cout<<"Ithastworealsolutions:
"<x1=(-b+sqrt(disc))/(2*a);
x2=(-b-sqrt(disc))/(2*a);
cout<<"x1="<}
else
{cout<<"Ithastwosamerealsolutions:
"<cout<<"x1=x2="<<-b/(2*a)<}
else
{cout<<"Ithastwocomplexsolutions:
"<p=-b/(2*a);
q=sqrt(-disc)/(2*a);
cout<<"x1="<
}
}
return0;
}
为了测试程序的“健壮性”,我们准备了6组数据:
①3,4,1②1,2,1③4,2,1④0,3,4⑤0,0,0⑥0,0,5
分别用这6组数据作为输入的a,b,c的值,得到以下的运行结果:
①inputa,b,c:
341
Ithastworealsolutions:
x1=-0.33,x2=-1
②inputa,b,c:
121
Ithastwosamerealsolutions:
x1=x2=-1
③inputa,b,c:
421
Ithastwocomplexsolutions:
x1=-0.25+0.43i,x2=-0.25-0.43i
④inputa,b,c:
034
Ithasonesolutions:
x1=-1.33
⑤inputa,b,c:
000
Itistrivial.
⑥inputa,b,c:
005
Itisimpossible.
经过测试,可以看到程序对任何输入的数据都能正常运行并得到正确的结果。
以上是根据数学知识知道输入数据有6种方案。
但在有些情况下,并没有现成的数学公式作为依据,例如一个商品管理程序,要求对各种不同的检索作出相应的反应。
如果程序包含多条路径(如由if语句形成的分支),则应当设计多组测试数据,使程序中每一条路径都有机会执行,观察其运行是否正常。
以上就是程序测试的初步知识。
测试的关键是正确地准备测试数据。
如果只准备4组测试数据,程序都能正常运行,仍然不能认为此程序己无问题。
只有将程序运行时所有的可能情况都作过测试,才能作出判断。
测试的目的是检查程序有无“漏洞”。
对于一个简单的程序,要找出其运行时全部可能执行到的路径,并正确地准备数据并不困难。
但是如果需要测试一个复杂的大程序,要找到全部可能的路径并准备出所需的测试数据并非易事。
例如:
有两个非嵌套的if语句,每个if语句有两个分支,它们所形成的路径数目为2×2=4。
如果一个程序包含100个if语句,则可能的路径数目为2100=1.267651×1030,要测试每一条路径儿乎是不可能的。
实际上进行测试的只是其中一部分(执行几率最高的部分)。
因此,经过测试的程序一般还不能轻易宣布为“没有问题”,只能说“经过测试的部分无问题”。
正如检查身体一样,经过内科、外科、眼科、五官科……各科例行检查后,不能宣布被检查者“没有任何病症”,他有可能有隐蔽的、不易查出的病症。
所以医院的诊断书一般写为“未发现异常”,而不能写“此人身体无任何问题”。
我们应当了解测试的目的,学会组织测试数据,并根据测试的结果修改完善程序。
第三部分实验内容与安排
实验一C++程序的运行环境和运行C++程序的方法
1.实验目的
(1)了解所用的计算机系统的基本操作方法,学会独立使用该系统。
(2)了解在该系统上如何编辑、编译、连接和运行一个C++程序。
(3)通过运行简单的C++程序,初步了解C++源程序的结构和特点。
应学会在一种以上的编译环境下运行C++程序,建议学习并掌握VisualC++6.0的使用方法。
2.实验内容和步骤
(1)检查所用的计算机系统是否己安装了VisualC++6.0编译系统
(2)在VisualC++6.0环境下编译和运行C++程序
在第一次上机时,按以下步骤建立和运行C++程序:
①先进入VisualC++6.0环境。
②在自己指定的子目录中建立一个名为test.cpp的新文件(此时尚未向文件输入内容)。
③从键盘输入以下程序(第l章第8题):
intmain();
{inta,b;
c=a+b;
cout>>“a+b=”>>a+b;
}
④选择Build→Compiletest.cpp命令,对此源程序进行编译。
观察和分析编译信息。
⑤根据编译信息指出的错误,修改程序。
再进行编译,如果还有错,再重复此过程,直到编译不出错为止。
⑥选择Build→Buildtest.exe命令,对程序进行连接,如果不出错,就会生成可执行程序test.exe。
⑦选择Build→Executetest.exe命令,执行可执行程序test..exe观察屏幕的变化。
在输出窗口应显示程序运行结果。
⑧分析结果是否正确,如果不正确或认为输出格式不理想,可以修改程序,然后重新执行以上④至⑧步骤。
此外,还可利用已有的源程序建立一个新程序。
由于刚才已建立了一个名为test.cpp的源程序,可以以它为基础建立一个新程序,这样更方便些。
按以下步骤:
①通过“资源管理器”或“我的电脑”,按文件路径找到已有源程序test.cpp。
②双击“test.cpp”图标,进入VisualC++集成环境,打开test.cpp。
③在test.cpp基础上将源程序修改为以下内容(第1章第9题):
#include
usingnamespacestd;
intmain()
{inta,b;
c=add(a,b)
cout<<"a+b="<return0;
}
intadd(intx,inty);
{z=x+y;
return(z);
}
④选择File→Saveas命令,用新的文件名other.cpp保存。
此时,other.cpp与test.cpp在同一子目录下。
⑤对新文件other.cpp进行编译、连接和运行。
步骤与前相同。
3.预习内容
《C++面向对象程序设计》第1章。
这是第一个实验,写得比较详细。
希望大家能在实验中多思考,多给自己提问题,多设想几种可能性。
做实验时不要满足于验证书本知识。
在以后的实验中,请大家自己设计具体的实验步骤,尽可能自己补充增加一些内容,以提高自己的实践能力。
实验二C++对C的扩充
1.实验目的
(1)了解在面向过程程序设计中C++对C功能的扩充与增强,并善于在编写程序过程中应用这些新的功能。
(2)进一步熟悉在所用的系统上编辑、编译、连接和运行C++程序的方法。
(3)进一步熟悉C++程序的结构和编程方法。
2.实验内容和步骤
要求事先编好解决下面问题的程序,然后上机输入程序并调试运行。
(1)输入以下程序,进行编译,观察编译情况,如果有错误,请修改程序,再进行编译,直到没有错误,然后进行连接和运行,分析运行结果(本题是《C++面向对象程序设计》第1章习题第9题)。
#include
usingnamespacestd;
intmain()
{inta,b;
c=add(a,b)
cout<<"a+b="<return0;
}
intadd(intx,inty);
{z=x+y;
return(z);
}
(2)编一个程序,用来求2个或3个正整数中的最大数。
①用不带默认参数的函数实现。
②用带有默认参数的函数实现。
(本题是《C++面向对象程序设计》第1章习题第11题)
对比两种方法,分析用带有默认参数的函数的优点和应用的场合。
总结如何选择默认参数的值。
请分析本题中默认参数的值应该在什么范围。
(3)输入两个整数,将它们按由大到小的顺序输出(本题是《C++面向对象程序设
计》第1章习题第12题)。
①使用指针方法。
②使用变量的引用。
比较这两种方法的特点和使用方法。
(4)对3个变量按由小到大顺序排序,要求使用变量的引用(本题是《C++面向对象程序设计》第1章习题第13题)。
①使用指针方法。
②使用变量的引用。
请总结使用引用时要注意什么问题。
(5)有5个字符串,要求对它们按由小到大顺序排列,用string方法(本题是《C++面向对象程序设计》第1章习题第16题)。
(6)编一个程序,用同一个函数名对n个数据进行从小到大排序,数据类型可以是整型、单精度型、双精度型(本题是《C++面向对象程序设计》第1章习题第17题和18题)。
①用重载函数实现。
②用函数模板实现。
比较这两种方法各有什么特点,什么情况下可以用函数模板代替重载函数?
什么情况下不可以用函数模板代替重载函数?
3.预习内容
《C++面向对象程序设计》第l章。
实验三类和对象
(一)
1.实验目的
(1)掌握声明类的方法,类和类的成员的概念以及定义对象的方法。
(2)初步掌握用类和对象编制基于对象的程序。
(3)学习检查和调试基于对象的程序。
2.实验内容
(1)有以下程序:
#include
usingnamespacestd;
classTime//定义Time类
{public:
//数据成员为公用的
inthour;
intminute;
intsec;
};
intmain()
{Timetl;//定义t1为Time类对象
cin>>tl.hour;//输入设定的时间
cin>>tl.minute;
cin>>tl.sec;
cout<”<return0;
}
改写程序,要求:
①将数据成员改为私有的;
②将输入和输出的功能改为由成员函数实现;
③在类体内定义成员函数。
然后编译和运行程序。
请分析什么成员应指定为公用的?
什么成员应指定为私有的?
什么函数最好放在类中定义?
什么函数最好在类外定义?
本题是《C++面向对象程序设计》第2章第2题。
(2)分别给出如下的3个文件:
①含类定义的头文件student.h。
//student.h(这是头文件,在此文件中进行类的声明)
classStudent//类声明
{public:
voiddisplay();//公用成员函数原型声明
private:
intnum;
charname[20];
charsex;
};
②包含成员函数定义的源文件student.cpp。
//student.cpp(在此文件中进行函数的定义)
#include
#