-
实验十八 虚函数与多态、纯虚函数
一.实验目的
1. 在掌握继承与派生关系的基础上,进一步理解虚函数与多态性的关系,实现运行时的多态。
2. 学会定义和使用纯虚函数
二、实验内容
1.范例:了解"单界面,多方法"的概念。现有称为figure的基类,存放了各二维对象(三角形、矩形和圆形三个类)的各维数据,set_dim()设置数据,是标准成员函数。
show_area()为虚函数,因为计算各对象的面积的方法是不同的。
【程序】
#include < iostream >
using namespace std; class figure{
protected:
double x,y;
public:
void set_dim(double i,double j=0)
{ x=i; y=j; }
virtual void show_area()
{ cout<<"No area computation defined for this class.\n";
}
};
class triangle:public figure{
public:
void show_area()
{ cout<<"Triangle with height "<< x<<" and base "<< y<<" has an area of "<< x*0.5*y<< endl;
}
};
class square:public figure{
public:
void show_area()
{ cout<<"Square with dimensions "<< x<<" and "<< y<<" has an area of "<< x*y<< endl;
}
};
class circle:public figure{
public:
void show_area()
{ cout<<"Circle with radius "<< x<<" has an area of "<<3.14159*x*x<< endl;
}
};
int main(){
figure *p;
triangle t;
square s;
circle c;
p=&t;
p->set_dim(10.0,5.0);
p->show_area();
p=&s;
p->set_dim(10.0,5.0);
p->show_area();
p=&c; p->set_dim(10.0);
p->show_area();
return 0;
}
【要求】
(1) 建立工程,录入上述程序,调试运行并记录运行结果。
(2) 修改上述程序,将virtual void show_area()中的virtual去掉,重新调试运行观察结果有何变化?为什么?
(3) 修改上述程序入口函数,使其动态建立三角形、矩形和圆形3个对象,通过基类指针访问这3个对象,然后释放这3个对象。
(4) 修改类定义中的析构函数,使之适应用户动态定义对 2、使用纯虚函数和抽象类对实验十六中的题1进行改进。
【要求】先定义一个抽象类Element,提供显示、求面积等公共接口(虚函数),派生出Point、Line、Circle等图形元素类,并重新定义(override)这些虚函数,完成各自的任务。
在这里,Element是抽象基类,它不能提供具体的显示操作,应将其成员函数定义为纯虚函数。只有采用指向基类的指针或对基类的引用进行调用,实现的才是动态绑定,
完成运行时的多态性。
3、编写计算定积分的类。采用纯虚函数和抽象基类往往是建立一个类的框架,并非是要建立一个完整的类。要求首先定义定积分抽象基类basic_inte,
该基类数据包括积分左右边界、划分区间的数量、步长和定积分值,同时包括一个计算积分的纯虚函数:virtual void integrate()=0。
第二步,由该基类派生出矩形法、梯形法和辛普生定积分类:rectangle、ladder和simpson。
第三步,编写一个积分函数,以指向定积分抽象基类basic_inte的指针为参数,实现动态的多态性。
-
实验十七 继承和派生的基本概念
一、 实验目的
继承与派生是面向对象的特性,是面向对象程序设计模拟客观世界的手段之一,本实验的内容包括介绍MFC基础类的派生关系,通过实验要求掌握以下内容。
1. 掌握类继承与派生关系以及实现方法,理解类的层次结构。
2. 掌握派生类构造函数初始化基类成员和对象成员的方法。
3. 掌握赋值兼容原则,掌握派生类的复制构造函数和赋值运算符的定义。
二、 实验内容
1.范例:定义一个继承与派生关系的类体系,在派生类中访问基类成员。先定义一个点类,包含x,y坐标数据成员,显示函数和计算面积的函数成员;以点为基类派生一个圆类,
增加表示半径的数据成员,重载显示和计算面积的函数;定义一个线段类,以两个点类对象作数据成员,定义显示、求面积及长度函数,线段类采用聚合方式,因为有两个端点,
不能用派生方式。编程测试所定义的类体系。
【程序】
cl3=cl1;
cout<<"cl3圆面积:"<< cl3.Area()<< endl;
cl3.Show();
cout<<"线面积:"<< ln1. Area()<<'\t'<<"线长度:"<< ln1. GetLength()<< endl;
ln1.Show();
ln2.Show();
return 0;
}
【注意】
在Point 类中,将Line 类定义为友元,便于在Line 类中访问;Point 类的x和y 定义为Protected 访问权限,便于派生类访问。
注意派生类的构造函数中对基类数据成员的初始化方法(即 Circle(double xv,double yv,double vv):Point(xv,yv)),
以及构造函数中对对象成员的初始化方法(即 Line(double xv1,double yv1,double xv2,double yv2) : start(xv1,yv1),end(xv2,yv2){ } )
【要求】
(1) 建立工程,录入上述程序,改变数据实验之。
(2) 修改Point 类的数据成员x ,y 的访问权限为private ,再运行,结果如何?
(3) 如果不将Line 类设为 Point 类的友元,应采取什么措施?为哪个类增加数据或函数成员?
2. 编程:多层派生练习,由上题Point 类和Circle 类继续派生出Cylinder 类。要求计算圆柱体的底面积、侧面积、全面积和体积。
-
实验十六 动态内存分配与深复制
一、 实验目的
1. 理解运行时内存分配的概念,掌握自由存储区内存动态分配的方法。
2. 理解内部包含为指针动态分配内存的类对象复制时的浅复制和深复制的概念,会编写深复制构造函数和赋值复制运算符。
二、 实验内容
1. 编程: 仿照标准字符串类string ,采用动态字符数组来改造主教材5.6.3节中的自定义字符串类,要求可自动适应不同的串长度。
【提示】 新的自定义字符串类mysring 如下:
请读者完成各函数的定义,并测试。
【分析】
本题的难点是判断串长是否超出串的最大允许长度,以及怎样重新分配字符数组,并保留原来的字符数组。
2.将实验十五改为动态内存分配,依然用实验十五测试代码进行测试,模板声明如下
3. 附加题: 从程序运行效率的角度,尝试改进第二题的设计和代码,提示,考虑如下代码内存释放和分配的频率: myVector<int> vi; vi.push_back(0); vi.push_back(0);
vi.push_back(0);
-
1. 锟斤拷锟矫撅拷态锟斤拷锟介(锟斤拷锟斤拷1000锟斤拷锟斤拷锟斤拷一锟斤拷MyVector锟斤拷模锟藉,锟缴参匡拷 http://www.cplusplus.com/reference/vector/vector/ 要锟斤拷实锟斤拷锟斤拷锟铰癸拷锟斤拷(注锟斤拷const锟斤拷&锟斤拷使锟斤拷)
1锟斤拷 锟斤拷锟届函锟斤拷锟斤拷默锟较癸拷锟届函锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟侥癸拷锟届函锟斤拷锟酵匡拷锟斤拷锟斤拷锟届函锟斤拷;
2锟斤拷 operator =();
3锟斤拷 size(), resize(),empty();
4锟斤拷 operator[](), at(), front(), back();
5锟斤拷 push_back(),pop_back(),insert(),erase(),clear();
6锟斤拷 sort(); 锟斤拷小锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷, binarySearch():锟斤拷锟街诧拷锟斤拷锟姐法锟斤拷锟杰诧拷锟皆o拷锟街憋拷锟斤拷string锟斤拷int锟斤拷实锟斤拷十锟斤拷2锟斤拷目锟斤拷实锟斤拷十锟斤拷锟斤拷3锟解,锟斤拷锟皆达拷锟斤拷锟斤拷锟斤拷
-
实验十四 指针与数组
一、 实验目的
数组在处理同类型的多个数据问题时非常有效,是C++的重要数据类型。指针是C++中最灵活、最有特色的部分,没有熟练掌握指针,则不能说学会了C++。
指针的教学重点应放在数组与指针之间的密切关系上。通过本实验要求掌握以下内容:
1. 指针的定义和使用方法
2. 指针与数组的相互关系
3. 指针或数组作为函数参数的函数定义及调用方法。
4. C字符串及其运算
5. 标准字符串
二、 实验内容
1.范例:判断用户输入的C字符串是否为"回文",所谓"回文"是指顺读和反读都一样的串, 例如串 12321、madam。
【程序】
【要求】
(1) 重新定义回文为:滤去所有非字母字符(包括空格)后,不考虑字母的大小写,从左向右和从右向左读都相同的词或短语。
如,”Madam, I’m adam” 和 “Golf ,No Sir ,prefer prison flog!”
(2) 编写一个判断输入字符串是否为回文的函数,并使用指针形式访问数组元素。
2. 范例:按一定的规则可以将一个字符串经加密转换为一个新的串,例如加密的简单方法是当为'a'~'y'的小写字母时用后一个字母代替前一个字母,
其中'z'变换为'a',其他字符时不变。
例如: 原串为 This is a secret code!
加密后的串为 Tijt jt b tfdsfu dpef!
编写一个程序对输入串加密,输出加密前和加密后的串,再将加密后的字符串解密输出。 主函数如下,请编写加密函数和解密函数。
【程序】
int main()
{ char st[]="This is a secret code!";
cout<< st<< endl;
secret(st);
cout<< st<< endl;
desecret(st);
cout<< st<< endl;
return 0;
}
【要求】
(1) 阅读程序,如果将两个函数中else if(*s==122) *s='a';和else if(*s==97) *s='z';处的else 去掉,对程序有何影响?使用数据”I am a boy !” 重新测试看看。
(2) 仿造上例编写程序:设计一个带密钥的加密算法,例如密钥可以是一个常数,字符串加密的方法是将每个字符的ASCII码值加上该常数,然后对128求模。
要求以密钥将加密的字符串加密输出,再以相同的密钥将加密字符串解密输出。
3.编程:重新编写实验十三中题3的字符串处理函数,用指针作为参数。
-
实验十三 数组与多维数组
一、 实验目的
1、 熟练应用数组与多维数组
2、 掌握数组作为函数参数的函数定义及调用方法。
二、 实验内容
1. 范例:求一个 3×4 矩阵中的最大元素,将求矩阵中的最大元素的过程定义为一个函数。函数的第一个参数是矩阵本身,第二个参数是第一维的大小。
这种方法的优点是使函数具有通用性,即无论一个矩阵的第一维是多大,只要该矩阵的第二维是 4 个元素,都可用该函数求最大元素;
也可用该函数求一个矩阵开始几行中的最大元素。
【程序】
【要求】
修改上述程序使其不仅求矩阵中的最大元素而且还能求最大元素的行列值。
2. 打印杨辉三角形(10行)。使用二维数组并利用每个系数等于其上两系数之和。
3. 分别编写实现下列字符数组处理的函数,用数组作为参数:
(1)void trim(char s[ ]) //删除字符串s 的尾部空格。
(2)void lefstring(char s1[ ], char s2[ ],int n) //得到指定字符串s1中前n个字符的子串s2.
(3)int index(char s1[ ], char s2[ ] )
//检查字符串s2是否为字符串s1 的子串,根据查找结果返回s2在s1中的开始位置,如果s2不是s1的子串,则返回-1
主程序如下,请编写相应函数。
4.编程:编写函数itoa0(int n, char s[ ], int b),将十进制整数n转换为以十六进制为基数的数字字符数组。
-
实验十二 运算符重载
一、 实验目的
1、 掌握运算符重载为成员函数的方法
2、 理解友元函数和友元类。
3、 掌握运算符重载为友元函数的方法。
4、 使用静态数据成员。
二、 实验内容
1、为主教材中例4.2 的Rectangle类增加加减复合赋值和加减运算符重载函数。加减复合赋值语义定义为固定长方形的左上角,
对右下角的坐标进行加减运算,使新矩形的长宽为原两矩形长宽之和或差,对加和减复合赋值定义为成员函数。两个矩形加减运算定义为友元函数。
【要求】 (1) 主程序如下,请完成类的定义及相关成员函数和友元函数的实现,并分别保存为rect.h文件和rect.cpp文件。
2、编程:修改上题,要求如下:
(1)将加、减运算重载为成员函数。
(2)为矩形类在增加一个静态数据成员Counter,并统计共产生了多少个矩形对象。为Counter 添加定义、赋初值以及随程序运行而变化的代码,并在main()函数中将其输出。注意静态数据成员应该有定义性说明。
3、将实验十第四题分数类中 add,sub,mul,div,equalTo,lessThan和greaterThan等函数分别用+,-,*,/,==,<,>重载运算符代替,并添加+=,-=,/=,和*=复合赋值运算符重载。并测试。
-
实验十一 引用与复制构造函数
一.实验目的
1、 掌握引用的概念及应用,掌握引用作为函数参数的方法。 2、 学会编写与应用复制构造函数。
二. 实验内容
1、范例:编写一个函数,其原型为:void Index(int a[], int n,int & sub),其功能是,在大小为n的数组a中,查找某个数sub,
若找到,将其下标存放在sub中,若没找到,将-1存放在sub中,在主调函数中通过判断值来判断数组中是否有该数。在这里,sub是引用类型的参数,但起返回值的作用。
【程序】
【要求】
(1)修改主程序连续查找数字的循环语句,使程序能在输入特定数字后退出循环。
(2)将void Index(int a[], int n,int & sub); 改为void Index(int a[], int n,int sub);程序还能正确执行吗?试分析其结果并解释。
(3)在上述修改的基础上如果结果不正确,怎样修改可以同样得到正确的结果。
2、一个声明为返回引用的函数,既可以作为右值出现在赋值号的右边,也可以作为左值出现在赋值号的左边。下面是一个函数调用本身作为左值的例子。
【要求】
修改程序使用非返回引用的函数实现上述功能。试分析两者之间的区别。
3、为矩形类定义复制构造函数。矩形类见主教材的例4.2.
在rect.h 头文件中的类rect定义中加入以下代码:
Rectangle(const Rectangle & rhs);
在rect.cpp文件中添加以下代码:
Rectangle::Rectangle(const Rectangle & rhs):m_left(rhs.m_left),m_top(rhs.m_top),m_right(rhs.m_right),m_bottom(rhs.m_bottom){
}//复制构造函数
在main( )函数中添加以下代码,单步调试时进入复制构造函数,查看其调用情况:
Rectangle rect2(rect1);
cout < < ”由复制构造函数生成的rect2:”<<< endl;
rect2.Show( );
-
实验十 类与对象的基本概念
一、 实验目的
类是C++扩展数据类型,可以封装不同类型的数据成员和函数成员。类是面向对象程序设计的基础。本次实验内容包括面向对象的基本概念、构造函数与析构函数,从实际问题抽象出类等,通过实验要求掌握以下内容:
1、 掌握面向对象的基本概念和类的定义方法。
2、 掌握类成员的访问权限以及访问类成员的方法。
3、 掌握内联函数和默认函数。
4、 掌握构造函数和析构函数的意义及使用方法。
二、 实验内容
1、 范例:设计并测试一个矩形类(Rectangle)。属性为矩形的左下角与右上角的坐标,矩形水平放置。操作为计算矩形的周长和面积。
程序】
【要求】
(1) 将Rectangle(double l=0, double t=0, double r=0, double b=0); 改为Rectangle(double l, double t, double r, double b);
程序仍能正确运行吗?为什么?
(2) 注意成员函数void show( )、int calArea () 、int calPerimeter( )的使用,因为在第三章如果需编写类似功能的一般函数是需要带参数(形参)的。
而在此处作为类的成员函数又不需要带参数。思考为什么?
(3) 理解void Assign(double l,double t,double r,double b);函数的作用。将Rectangle(double l=0, double t=0, double r=0, double b=0);
改为Rectangle(double l, double t, double r, double b);这时,有人认为Rectangle(double l, double t, double r, double b) 和void assign(double l,double t,
double r,double b)的功能相同,那么assign 函数能否去掉呢?请试一试,结果会怎样?
2、 定义一个圆类(Circle),要求用两种方法定义:
方法一: 要求属性为半径,操作为计算圆的周长和面积。
方法二: 要求属性为半径(radius)、圆周长和面积,操作为输入半径,并计算周长、面积,输出半径、周长和面积。要求定义构造函数(以半径为参数,缺省值为0,周长和面积在构造函数中生成)和拷贝构造函数。
3、设计一个学校在册人员类(Person)。数据成员包括:身份证号(IdPerson),姓 名(Name),性别(Sex),生日(Birthday)和家庭住址(HomeAddress)。成员函数包 括人员信息的录入和显示等。使用多文件结构(参考课程主页给出的例子)
★选做题 4、编程建立一个分数类。分数类的数据成员包括分子和分母,操作包括约分、通分、加、减、乘、除、求倒数、比较、显示和输入。分数类的定义如下:
【要求】完成上述所有成员函数并进行检验。 请用多文件结构完成,包括后续章节的题目
★选做题 5、集合是具有同一属性(共性)而又能互相区别(个性)的多个成员汇集起来的整体,构成集合的每个成员称为集合的元素,元素间没有顺序关系。
例如,所有的大写英文字母是一个集合,它包括26个元素:A、B、…、Z。不包含任何元素的集合称为空集合。
【实验要求]】
自定义一个集合类set,采用数组存放集合的元素。实现以下成员函数并完成主函数的测试。自定义集合运算包括:
1) 判断元素elem是否为集合set的元素。
2) 为集合添加一个元素elem。
3) 从集合中删除一个元素elem。
4) 复制一个集合,其元素与原集合完全一样。
5) 显示集合中的所有元素。
6) 求两个集合中相同的元素,即求两个集合的交集。
7) 求两个集合中所有的元素,即求两个集合的并集。
8) 判断两集合包含的元素是否完全相同。
9) 判断一个集合是否被包含在另一个集合之中,即是否为另一个集合的子集。*/
【程序】
-
实验九 函数的重载和变量的作用域
一、实验目的
1、 了解内联函数、重载函数、带默认参数函数的定义及使用方法。
2、 掌握作用域的概念、变量的存储类型及它们之间的差别。
3、 掌握程序的多文件组织。
二、实验内容
1、 重载函数允许不同的函数使用相同的名字,这使得完成类似的任务时可以使用相同的函数名。
范例:编写几个计算面积的函数,分别计算圆、矩形、梯形和三角形的面积, 计算边长为1的正方形及其内切圆、内接等腰三角形和等腰梯形面积。
函数原型如下: double area(double radius=0);
//圆面积,参数为半径,默认参数为0,表示点面积 double area(double a, double b);
// 计算矩形面积,参数为长和宽 double area(double a, double b, double h);
//计算梯形面积,参数为两底和高 double area(double a, double b, double c, int);
//计算三角形面积,参数为三边长,int 型参数起标示作用,以区别于梯形,不参加计算。
【要求】
(1) 编译运行程序,并记录运行结果,注意函数调用时,实参与形参之间的关系(包括类型、个数)。
(2) 若将计算矩形面积的函数原型改为 double area(double a=0, double b=0);重新编译运行情况会怎样?为什么?
(3) 若将计算三角形面积的函数原型改为 double area(double a, double b,double c);程序还能正确运行吗?为什么?
(4) 若将计算三角形面积的函数原型改为 double area(double a, double b,double c=0,int); 程序还能正确运行吗?为什么?
2、 编程:将上题以多文件方式组织,在area.h 中声明各个area( )函数原型,在area.cpp中定义函数,然后在Exp9_2.cpp中包含area.h,并定义main( )函数并执行。
【注意:】VC++6.0中以c开头的头文件,如
不在标准名字空间中,所以area.cpp中不可以加 using namespace std; 3、范例:全局变量、局部变量和静态局部变量的应用示例。
【要求】
(1) 分析并写出下列程序的执行结果,然后输入计算机执行,比较分析结果与执行结果。如果两结果不相同请分析原因。
4、设计两个重载函数,分别求两个整数相除的余数和两个实数相除的余数。两个实数求余定义为实数四舍五入取整后相除的余数。
-
实验八 函数递归算法
一、 实验目的
1、 掌握函数的嵌套调用和递归调用
2、 掌握递归算法
二、 实验内容
1. 函数嵌套调用是在被调用的函数内在调用其他函数,而递归调用时在被调用函数内调用自身。
嵌套调用的层数没有限制,而递归调用函数必须包含使递归终止的语句。
范例:求组合数 Cnm=n!/[m! (n-m)!](m为指数)
【分析】 求组合数要用到求阶乘,可将求阶乘定义为一个函数,在求组合数的函数中嵌套调用阶乘函数。
由于n!=n*(n-1)!,求阶乘是一个典型的递归算法,在此用递归方法实现。
【程序】
【注意】
(1) 因为阶乘极易发生溢出,所以n最大值取12,否则运算中会发生溢出。
(2) 在函数内定义局部变量时,变量名不应与函数名相同。例如,在A行,不可定义变量名为com; 否则程序编译会出错误。
(3)还有一种常见错误,例如:
long fac(int i)
{ if(i==0||i==1) fac(i)=1;
else fac(i)=i*fac(i-1);
return fac(i); }
编译此程序,会出现提示信息 Left_value required 的错误,请思考这是为什么?然后修改正确。
2、 用递归函数实现勒让德多项式。
在主函数中求P4(1.5)。
★ 选做题3、定义递归函数实现Ackman函数。
其中m,n为正整数。 设计程序求Acm(2,1),Acm(3,2)。
-
实验七 函数的基本概念
一、 实验目的
1、 掌握函数的定义及调用方法
2、 掌握函数参数的传递(传值)、形参与实参的关系以及函数声明。
3、 理解局部变量的作用。
二、 实验内容
1、 将教材中【例2.12】改为用函数实现,编写一个用迭代法求平方根的函数。
【分析】 编写一个通用的求平方根的函数,参数(形参)为待求平方根的数,返回值为该数的平方根。
由于平方数不能为负数,因此在主调函数中,需要判断输入数的正、负,为正则用该参数(实参)调用求平方根函数;为负责输出错误信息。
【程序】
2、 设计一个简单的计算器程序,从键盘输入“+ 3 5 ”代表表达式“3+5”,程序读入运算符和数据,
调用Calculate( )函数,根据运算符进行加、减、乘、除四则运算。要求能反复执行这一过程,直到用户输入“#”符号作为运算符为止。
函数原型如下:
double add(double ,double ); //加
double minus(double ,double ); //减
double multi(double ,double ); //乘
double div(double ,double ); //除
double Calculate (double ,double ,char ); // 运算符作为字符数读入
3、 设计一个求两个数的最大公约数和最小公倍数的通用函数,要求能反复输入数据并输出其结果。
【提示】 可用枚举法,从两数中的小者开始尝试,并逐步往下取值,直到找到最大公约数。
4、歌德巴赫猜想指出:任何一个充分大的偶数都可以表示为两个素数之和。
例如: 4=2+2 6=3+3 8=3+5 10=3+7 10=5+5 … … 50=3+47 将4 -50之间的所有偶数用两个素数之和表示。判断一个整数是否为素数用函数完成。
-
实验六 文本文件的简单应用
一.实验目的
(1)学会将程序运行的结果存入文本文件
(2)学会从文本文件中读取数据,并进行运算。
二.实验内容
1.范例:修改实验五中的第二题,求出水仙花数后不是在屏幕上显示而是存入文本文件。请在退出程序后,用记事本打开该文本文件,查看结果。
【分析】(使用文件的格式)
(1)首先,说明一个文件流对象(内部文件)。文件流类型ifstream支持从输入文件中提取数据的操作,
而文件流类型ofstream用于完成将数据写入输出文件中各种操作。
ifstream ifile ;//定义文件输入流对象ifile
ofstream ofile ; ///定义文件输出流对象ofile
特别注意:输入文件用于读操作,输出文件用于写操作。(2)然后打开文件。在文件流对象和磁盘文件名之间建立联系。
ifile.open(“my_in_file.txt”);
ofile.open(“my_out_file.txt”);(3)对文件进行读/写操作。可以使用C++的提取运算符(>>)和插入运算符(<<)进行,
也可以使用读字符的get( )函数和读字符串的getline( )函数。
读写文件时,使用输出文件(如ofile)代替cout,用输入文件(如 ifile)代替cin。
(4)最后关闭文件。
ifile.close( );
Ofile.close( );
关闭文件时,系统把与该文件相关联的文件缓冲区中的数据写到磁盘文件中,保证文件的完整性;同时把磁盘文件名与文件流对象之间的关联断开,可防止误操作修改了磁盘文件。
【程序】
2.范例:编程从上题生成的文本文件读取水仙花数,并显示在屏幕上。
【程序】【思考】
(1)本程序在读到文件的结束符之前,先读了一个空串,所以输出时多了一个空行。能去掉该空行吗?请试试。
(2)请尝试使用别的方法对文件进行读/写操作。
3. 编写程序求500 以内的勾股弦数,即满足 c2=b2+a2(2为指数)的3个数,要求b>a。将所有符合要求的组合存入文本文件中。
4.编写程序从上题建立的文本文件中读取500以内的勾股弦数并显示在屏幕上。
-
实验五 常用算法-----枚举法、递推法、迭代法
一.实验目的
掌握枚举法、递推法、迭代法这3个常用的算法
二.实验内容
1、范例:由0到4五个数字,组成5位数,每个数字用一次,但十位和百位不能为3(当然万位不能为0),输出所有可能的五位数。
【程序】【思考】 穷举法采用循环语句,对必须剔除的情况应在循环体内用条件语句实现,并使用continue语句,不可以使用break语句;
如果将其放在循环条件中,则必然会出错。
2、编程求和:s=a+aa+aaa+aaaa+ ……+aaaa…aaa(n个),其中a为1~9中的一个数字。
【提示】若第一项为a , 以后每一项由前一项乘以10加上a递推得到,然后求和。3、编程求出所有的“水仙花数”。所谓“水仙花数”是指一个3位数,其中各位数字的立方和等于该数本身,例如153就是一个“水仙花数”,
因为153=1^3+5^3+3^3。要求采用枚举法。
4、有两队选手每队5人进行一对一的比赛,甲队为A、B、C、D、E,乙队为J、K、L、M、N,经过抽签决定比赛对手名单。规定A不和J比赛,
M不和D及E比赛。列出所有可能的比赛名单。
【提示:】先固定甲队,A在0号位,B在1号位,依次排列,最后E在4号位;然后乙队排对应的对手,用循环变量j、k、l、m、n分别对应0号位的选择、1号位的选择、依次类推,直到到4号位的选择,每一层循环应剔除上一轮已选过的选手,和指定不与比赛的对手。用变量i统计不同情况数。
5、给定一个大于2的正整数,求出小于该数的所有素数。
【提示】 利用递推法来求解,用vector来存储已经求出的素数(初始化为有一个数据元素,值为2),下一个素数条件为不能被小于该数的所有素数整除
★ (选做题)6、设函数f(x)定义在区间[a,b]上,f(x)连续且满足f(a)*F(b)<0,求f(x)在[a,b]上的根。
采用弦位法,迭代公式为: xi+1= xi+( xi-1- xi)/(f(xi)-f(xi-1))*f(xi)
其代换规律为:首先用两端点函数值的绝对值较大者的对应点作为x[i-1],较小者作为x[i],即如果
|f(a)|<|f(b)|,则xi←a,xi-1←b。用迭代公式得出xi+1,f(xi+1)。误差定义为: ⊿x =( xi-1-xi/(f(xi)-f(xi-1))*f(xi)
当⊿x <ε或f(xi+1)==0则结束运算。否则用(xi,f(xi))代替(xi-1,f(xi-1)),用(xi+1,f(xi+1))
代替(xi ,f(xi)),继续迭代。
求方程 xlg(x)=1 的实根的近似值,要求误差不超过0.001。
【提示】 令 f(x)=xlgx-1 ,则f(2)≈-0.398<0,而 f(3) ≈0.431>0 ,由此可知f(x)的根在2与3之间。
-
实验四 循环结构程序设计
一、实验目的
1.掌握3种循环结构:while ,do—while ,for 的区别与联系,以及它们之间相互转换的方法,并能正确使用它们。
2.掌握与循环语句相关的break 语句和continue 语句的使用方法
二. 实验内容
1.输入正整数n, 计算n的阶乘。
【分析】 由于n!=1*2*3*……*n,因此,要计算n的阶乘可以从1开始,由1的阶乘乘以2得到2的阶乘,再乘以3得到3的阶乘.......以此类推。
【程序】【要求】
(1)分别输入数据 -2, 1 ,5, 10, 20 调试运行程序,并记录程序结果。
输入
结果
(2) 删除程序中//A 处的赋值语句 return 1; 重新以上述数据调试运行程序,结果是否正确,如果不正确,该如何修改?
(3) 删除程序中//B处的语句 result=1;重新以上述数据调试运行程序,结果是否正确,如果不正确,该如何修改?
(4) 将程序中语句 double result=0; 改为 int result=0; 重新以上述数据调试运行程序,结果如何?为什么?
2. 范例:编程计算求π的近似值(要求小数点后面10位)。
提示: 可利用下列公式计算π值:
【程序】
【要求】
(1)输入程序编译后使用Debug跟踪,单步执行程序,记录以下变量值的变化。
iterm
sum
0
1
2
3
4
5
:
回答以下问题:
a)从跟踪结果分析,term和sum的值有什么错误?
b)循环结束后,i的值是多少?用什么简单的办法可以看到?
c)对程序作何修改可以使其得到正确的结果?3.将输入的一段文本中的小写字母转换成大写字母。
【分析】由ASCII码表可以看出,大写英文字母的ASCII码值在65至90之间,小写英文字母的ASCII码值在97至122 之间,每一个英文字母的大写和小写的ASCII码相差32。4. 编程:设计一个程序,输入一个日期,要求算出这一天是本年的第几天。
【分析】要算出某天是当年的第几天,应该将当年中本月之前所有月的天数相加,再加上本月至此的天数。
但这里有一个闰年问题,2月是一个特殊月,闰年的2月有29天,非闰年的2月只有28天。
【提示】判断某年是闰年的条件是:该年号能被4整除但不能被100整除,或者能被400整除。例如,1996、2000是闰年,但1800不是闰年。5. 猜数字小游戏。 程序随机产生0-1000之间的一个整数,玩家开始猜测这个数字是多少, 如果玩家猜测的数比程序产生的数字小,提醒玩家所猜的数字小了,请重试,如果猜测的数字比程序产生的数字大,告诉玩家所猜数字大了,请重试,直到玩家猜对为止,告诉玩家总共的猜测次数,并提醒玩家是否继续猜下一个数。
【提示】 产生一个随机数利用rand() 函数,需要包含#include <cstdlib>,并利用srand()初始化随机数发生器的种子(一般用time()函数获取一个系统时间作为种子,包含#include <ctime>),具体用法见第9题
6. 约瑟夫(Josephus)问题:n 个人围坐成一圈,从 1 开始顺序编号;游戏开始,从第一个人开始由 1 到 m 循环报数,
报到 m 的人退出圈外,问最后留下的那个人原来的序号。
【分析]】本题可定义一个容器(vector<bool>),初始化大小(元素个数)为n。 容器里元素的值标识该人是否出局,1在圈内,0出局。值为0的元素不参加报数。可用一个整型数k做计数器,采用倒计数,记录留下的人数。
【提示】容器里的元素是线性排列的,而人是围成圈的,用容器表示要有一种从容器尾部跳到其头部的技巧,即下标加1除以n求余数。7. 输入一定数目的成绩(最少5个学生的成绩),利用vector将这些成绩存储起来, 统计平均分,最高分和最低分,然后将每个同学的成绩转换成等级制,如100:A++, 98-99:A+,93-97: A,90-92: A-,...,68-69:D+,63-67: D,60-62: D- , 0-59: F
如: 输入 59 68 95 74 82 100
输出结果:
最高分:100 最低分: 59 平均分:80
1 [59:F]
2 [68: D+]
3 [95: A]
4 [74: C]
5 [82: B-]
6 [100: A++]
★ (选做题)8. 输入若干字符,统计其中数字字符、空白字符和其他字符的个数,输入EOF结束。
【分析】 要对字符进行统计,需要循环语句反复输入字符,读入字符后用switch 语句判断字符的种类:要统计3种字符数,需要定义3个用于计数的变量 nDigit ,nWhite ,nOther,并置初始值0;读入字符用cin.get()函数,在这里用while循环比较合适。白字符指空白键、Tab键和回车键。EOF表示End of File ,其值为-1,从键盘输入 CTRL+Z键即可。
这里采用重载的 int cin.get( )函数,它返回的是整型数,所以能返回EOF。
【要求】程序中的变量c ,可以定义为char 类型吗? 请试之,并解释原因。
请注意程序中case 分支语句后的break语句,break能去掉吗?为什么?
如果要分别统计0-9中个数字出现的次数,怎样才能有效地实现,请修改程序。
如果要统计输入的一段文字中出现的行数、单词数和字符数,又怎样有效地实现,请完成之。
(选做题) 9.猜字游戏,规则如下,程序初始化一个单词集合,每次游戏开始时,程序随机选择一个单词让玩家来猜,玩家每次只能猜一个字母,如果选择的单词里有玩家所猜的字母,则玩家猜测成功,程序将显示单词里所有猜中的字母,如果单词里没有所猜字母,则猜测失败,共有六次机会。 提示: 假如系统选择了单词good, 玩家第一次猜测为a, 程序提醒玩家猜错,还有5次机会,并显示玩家已经猜过的字母和到当前为止所猜的单词中正确的猜测(没有猜中的字母用*代替,第一次没有猜中所以显示****); 第二次如果玩家猜o, 猜测正确,显示玩家到当前为止所猜的单词中正确的猜测,其他未猜中的用*代替(*oo*);第三次如果玩家猜a,提醒玩家此字母已经猜过,请重试,并显示玩家所有猜错的字母。依次进行,直到玩家猜中或者猜错的次数达到最大限制次数,此次猜单词游戏结束,询问玩家是否继续下一个单词的猜测
-
实验三 分支程序设计
一.实验目的
流程控制语句用于实现基本程序结构,是程序设计的基础。本实验要求掌握条件语句和开关语句的使用。
二.实验内容
1.输入一个数,判断它的奇偶性后输出结果。
【分析】判断一个数是否为偶数,只需要判断它是否能被2整除,若能整除,则为偶数,则为奇数。
【程序】【要求】
(1)分别使用数据 345 680 -34 -23.5 作为输入数据,测试程序,分析程序结果,并记录结果。
输入
结果
(2)使用上述数据测试结果正确吗?如果有不正确之处请修改。
(3)如果对输出结果的显示格式不满意,请修改。
(4)请修改if (input %2) 中的表达式,使程序仍然能正确执行。
2. 编程求一元二次方程ax2+bx+c=0的根。包括以下判断和结果,若输入a=0,给出提示;△=b2-4ac ,若△>0,输出两个不等的实根;
若△=0,输出两个相等实根;若△<0,输出两个复数根。
【要求】
(1)分别利用嵌套的if-else 和if-else if -else 结构 编写源程序并调试运行,并记录结果。比较两者的不同之处。
输入
结果
a=0 b=0 c=4
a=0 b=2 c=4
a=1 b=2 c=0
a=2 b=5 c=1
(2)思考 if –else 嵌套使用时的注意事项是什么?
3. 编写程序:输入一门课程的成绩,若高于90分,输出“A grade ”;若高于80分而低于90分,输出“B grade ”;若高于70分而低于80分,输出“C grade ”;
若高于60分而低于70分,输出“D grade ”;否则输出“Not passed ”。
【要求】
使用if –else 语句和switch 语句两种方法实现。
分析if –else 语句和switch 语句的区别,switch 语句特别适合于什么情况使用?
思考使用switch 语句时应注意什么?
4、 编写程序: 输入一个数,判断其是否是3或7的倍数,可分为4种情况输出。
(1) 是3的倍数,但不是7的倍数。
(2) 不是3的倍数,是7的倍数。
(3) 是3的倍数,也是7的倍数。
(4) 既不是3的倍数,也不是7的倍数。
★ (选做题)5. 编程计算个人所得税。个人所得税率表如下:月收入1200元起征,超过起征点500元以内部分税率5%,超过500元到2,000元部分税率10%,
超过2,000元到5,000元部分税率15%,超过5,000元到20,000元部分税率20%,超过20,000元到40,000元部分税率25%,超过40,000元到60,000元部分税率30%,
超过60,000元到80,000元部分税率35%,超过80,000元到100,000元部分税率40%,超过100,000元部分税率45%。
-
实验二 简单的C++程序设计
一、 实验目的
1. 掌握C++程序的基本结构
2. 掌握C++基本数据类型和运算符
3. 熟悉输入、输出方法
二、 实验内容
1、 输入两个数,将它们交换后输出。 【分析】要交换两个整数,一般是使用一个中间变量经过几次赋值实现。
(1) 进入Visual C++开发环境,选择File|New菜单,弹出New对话框,打开Projects选项卡,在列表框中选择Win32 Console Application 工程类型,
在Project Name 文本框中输入工程名Exp2_1,选择合适的路径,单击OK按钮。
(2) 在随后的对话框中选择An empty project ,单击Finish 按钮。
(3) 选择File|New菜单,在New对话框的Files选项卡中选择C++ Source File,,输入文件名Exp2_1.cpp,选中Add to project 复选框,单击OK按钮,
打开源文件编辑窗口,输入以下源代码:
【要求】
(1) 仔细阅读程序,掌握程序的结构,找到程序的数据定义部分和操作部分,辨识各部分功能,注意输入、输出语句的使用。
(2) 运行程序,输入数据观察结果,并进行测试。
(3) 去掉输出语句cout << "a,b = " ; 对程序的功能有影响吗?如果没有,那么该语句在程序中起何作用?请解释。
(4) 将程序中的三个赋值语句换成a=b; b=a; 重新运行修改后的程序,观察并记录结不果。a,b能交换吗?试解释原因。
(5) 输出语句cout<<"a=" << a <<'\t'<<"b="<< b << endl;中,'\t'和endl 的作用分别是什么?还有别的方法能代替它们吗?请尝试修改,并运行之。
(6)" 在输入语句 cin >> a >> b ;可以加入’\t’ 和 endl之类的符号吗?请试之,并解释为什么?
2、 建立简单控制台程序。使用VC开发环境来调试以下源程序。
【程序】
【要求】
(1)根据操作过程填写以下表格。
内容操作
说明或结果分析
进入VC6
在D盘建立一个名为“ex2_2.cpp”的控制台程序
输入代码
编译连接程序
运行程序
(2)采用以下各组数据输入测试,记录输出结果。分析原因,思考如何解决?
3 4 5
3 4 12
0 6 2
-2 7 9(3) 修改程序。
a) 把double 改为 int,重新编译程序,会出现什么编译信息?什么原因?
b) 把s和area定义为double可以消除编译错误吗?为什么?
c) 采用以下数据输入测试,记录输出结果,分析原因。
3.45 5.618 4.012
d)增加输出a、b、c变量值的语句,观察不同输入时变量值的变化。e) 调试程序,在监视窗口分别输入变量a,b,c,s,和area,单步执行(F10),在监视窗口观察所有变量的值的变化情况,分析原因。
3、用sizeof运算符计算C++中char,short,int,long,float,double等基本数据类型所占的字节数,并按以下格式输出:
sizeof(char)=1 byte
sizeof(short)=2 bytes
sizeof(int)=4 bytes
……..
【程序】【要求】
(1)修改程序, 使计算结果以表格形式输出:
char 1
short 2
int 4
……………
(2)修改程序,将计算结果保存在数组中,再按表格形式输出。4. 编写满足下列要求的程序:根据输入的球半径,分别计算球的表面积、体积和质量(假设球的密度为7.8kg/dm3),并输出计算结果。
【提示】球的表面积计算公式为 s=4πr2,球体积计算公式为v=4/3∏r3.(红色的为指数)
【要求】
注意输入、输出形式,要求输入前应有提示性输出,如“Please input the radius of the ball ”.注意变量的命名,最好能见文知义,如radius, volume ,weight 等。另外,由于两整数相除取整,注意在计算公式中使用正确的变量数据类型。★ (选做题)5. 演示C++程序中输入、输出易出错的几个地方。
【分析】采用cin输入将跳过空白符(包括空格、制表、垂直制表、换页、换行和回车等)。如果要求把从键盘上输入的所有字符(包括空白字符)都作为输入字符赋给字符变量,必须使用函数cin.get(字符变量),但这时如果前面曾有输入,会读入不希望获取的表示输入结束的回车符。
向一个字符数组中输入字符串时,应该使用函数getline(字符数组,字符数量)。这时如果前面曾有输入,会读入代表输入结束的回车符,形成空串。
【程序】
【要求】
读懂程序,理解程序中演示的输入、输出中易出错的情况。理解为什么两次输入It’s a book。所得到的结果不一样。
程序中使用cin.get(a[ ])输入时,为什么需要cin.get(a[12]),能够像cin>>a[9]只输入到a[9]吗?
程序最后两次输入“This is a cat。”,输出结果一样吗?为什么?
-
实验一 Visual C++集成开发环境入门
一、 实验目的
1. 初步学会使用Visual C++集成开发环境(IDE)。
①进入和退出 ;
② 菜单、工具的使用;
③用户窗口区的划分:workspace\ source file 和 message.
2. 初步了解调试程序的方法。
二、 实验内容
范例:Visual C++控制台应用程序设计步骤。
作为学习面向对象的C++的第一步,学习的重点是算法,必须避免用户图形界面的干扰,这时可采用控制台应用程序进行练习。
下面是一个控制台应用程序实例,该程序要求用户从键盘输入3个整数,然后按照从小到大的顺序在屏幕上输出。
【步骤一】 进入和退出Visual C++集成开发环境。
启动并进入Visual C++集成开发环境至少有3种方法:
(1)选择开始菜单的“程序”,然后选择Microsoft Visual Studio 级联菜单,再选择Microsoft Visual Studio菜单項,以版本6.0为例 如图1.1 所示。图1.1 进入Microsoft Visual C++集成开发
(2)在桌面上创建Microsoft Visual C++ 6.0 的快捷方式,直接双击该图标。
(3)如果已经创建了某个Visual C++ 工程,双击该工程的扩展名为.dsw的文件图标,也可进入集成开发环境,并打开该工程。
选择 【文件|退出】菜单,可退出集成开发环境。
【步骤二】创建一个控制台应用程序工程(1)进入Microsoft Visual C++ 6.0集成开发环境后,选择【文件|新建】菜单項,弹出新建对话框。单击【工程】标签,
打开其选项卡,在其左边的列表框中选择【Win32 Console Application 】工程类型,
在【工程名称】文本框中输入工程名EXP1_1,在【位置】文本框中输入工程保存的位置,单击【确定】按钮,如图1.2 所示。
图1.2 创建新的应用程序界面
(2)在弹出的对话框(如图1.3所示),选择【一个空工程】,单击【完成】按钮
图1.3 Win32 Console Application Step 1 of 1
(3)此时出现【新建工程信息】对话框,如图1.4 所示。次对话框中提示用户创建了一个空的控制台应用程序,并且没有任何文件被添加到新工程中,此时,工程创建完成。
图1.4 新工程信息对话框
【步骤三】程序的编辑、编译、生成和执行。 (1)选择【文件|新建】菜单項,弹出新建对话框。单击【文件】选项卡,
在列表框中选择C++ Source File ,在【文件名】文本框中输入文件名Exp1_1.cpp,选中【添加到工程】复选框,如图1.5所示。
然后单击【确定】按钮,打开源文件编辑窗口,在其中输入源代码:如图1.6所示。
图1.5
图1.6 编辑源代码
源代码如下:
对于已经存在的源文件,选择【工程|添加到工程|文件】菜单项,在随后打开的插入文件对话框中选择待添加文件,单击【确定】按钮即可将其添加到工程。
(2)源代码输入完后,选择【组建】|【编译】菜单项,即可编译源文件exp1_1.cpp。系统会在输出窗口显示出错(error)信息以及警告(warning)信息。
当错误为0时。可以得到目标文件(Exp1_1.obj)。
编译器在(output)输出窗口给出语法错误和编译错误信息。语法错误处理: 鼠标双击错误信息可跳转到错误源代码位置处,然后进行修改,一个语法错误可能引发系统给出很多条error信息,
因此,发现一个错误并修改后最好重新编译一次,以便提高工作效率。
警告错误处理: 一般是触发了C/C++的自动规则,如将一个单精度(浮点)型数据赋给整型变量,需要系统将单精度型数据自动转换为整型,此时小数部分会丢失,因而系统给出警告信息,警告信息不会影响程序执行,本例可以通过强制转换去掉警告信息。
(3)编译完成后选择【组建】|【组建】菜单项,连接并建立工程的.EXE文件,得到可执行文件Exp1_1.exe。这时编译器可能给出连接错误(linking error)。
产生连接错误的原因可能是缺少所需的库文件或目标文件,或程序中调用的外部函数没有定义等,只要补充相应文档再重新建立即可。
(4)组建完成后选择【组建】|【执行】菜单项,执行工程文件,会出现一个类似DOS的窗口,按要求输入3个不等的整数后按Enter键,屏幕上由大到小输出这3个整数,如图1.7所示。
图1.7 运行结果
【步骤四】程序的调试 运行程序时,可能发现程序没有编译错误,而且也能执行,但执行结果不对,此时除了仔细分析源程序,还可借助调试工具进行跟踪调试。
例如,若在exp1_1.cpp 的B行中else后面多加一个分号,即: ……..else ; {max=b; min=a; } 使用 88、 45、67 这组数据测试此程序,发现输出结果为67 45 88 ,显然结果不对。
此时需要对源程序进行调试,下面介绍调试过程。 首先,在源程序中可能出现错误的行上设置断点,方法是将光标移至该行,然后按F9键,或单击工具栏上的手形按钮(再按一次F9键或单击手形按钮将取消断点)
,此时该行左侧出现一个红色圆点,断点设置成功,如图1.8就是在A行设置了断点。
然后选择【组建】|【开始调试】|【GO】菜单命令(也可直接单击工具栏上的 图标),程序开始执行,但执行到断点处停止,这时选择【查看】|调试窗口|子菜单的Watch 和Variables两个菜单项,
打开监视窗口和变量窗口来观察变量的值,分析并查找出错原因。 在Watch窗口加入max和min两个变量,进行监视。Watch窗口的每一行可以显示一个变量,其中左栏显示变量名,双击它可进行编辑;
右栏显示变量的值。接下来可按F10键(不跟踪进入函数内部)或F11键(跟踪进入函数内部)从断点位置处单步执行。通过单步执行(一条一条语句执行)可以看出我们所观察的变量的变化以及程序执行流程是否正确,
如果不正确是由那条语句引起的,因而有针对性的检查错误原因。例如在本例中,尽管a>b,在执行了if后面的{max=a; min=b; }后,通过单步执行发现仍然执行了else后面的 {max=b; min=a; }
所以当程序执行到箭头所指位置时,max=45, min=48,如图1.8所示,与预期结果不相符,说明程序的流程有问题。此时再仔细分析源程序,发现问题在于else后多余的分号。
图1.8 Visual c++程序的调试
调试过程中,Variables窗口动态显示各变量值随程序执行而变化的结果。在面向对象程序设计中,若程序中有类的对象,Variables窗口的this页可显示当前this指针所指向对象的各个值。 经过反复的修改和调试,
使程序中所有问题得到改正后,可得到正确的执行结果。