C++程序设计课上机作业

这是一次学校C++课程上机作业的整理,包含17道题目。

目录

2.1质因数分解

2.2矩阵旋转

2.3字符串基本操作

2.4整数加一

2.5回文字符串

3.1摄氏华氏温度转换

3.2 简易计算器

3.3时间类Time的编写

❄️4.1 矩形相交

❄️4.2成绩表里找同学

❄️4.3动态二维double型数组类Matrix的编写

⚽5.1日期推算

⚽5.2 矩形

⚽5.3人员信息

6.1动态顺序表

6.2由圆派生出圆柱

6.3虚函数--交通工具


2.1质因数分解

【问题描述】

编写一个程序,先读入一个正整数 N,对其做质因数分解。

例如:90 = 2 * 3 * 3 * 5

【问题分析】

  • 分解质因数只针对合数(质数不需要分解)
  • 一个数分解质因数,要从最小的质数(2)除起,直到商也为质数

其实不需要判断除数是否为质数:除数从2开始增加,能整除就整除,并继续用2除,直到2不能整除,除数再加1变成3,再用3去除......

【完整代码】

#include
using namespace std;
void Prime(int n);

void Prime(int n)
{
	int i = 2;
	while (i < n)
	{
		if (n % i == 0)
		{
			cout << i << " ";
			n /= i;
		}
		else
			i++;
	}
	cout << n;
}

int main()
{
	int n;
	cin >> n;
	Prime(n);
	return 0;
}

2.2矩阵旋转

【问题描述】

编写一个程序,读入一个矩阵,输出该矩阵以第一行第一列数字为中心,顺时针旋转90度后的新矩阵,例如:
输入的矩阵为:

123

456
顺时针旋转90度后输出的矩阵为:

41

52

63

【样例输入】第一行为2行3列,后两行为矩阵

2 3
1 2 3
4 5 6

【样例输出】

3 2
4 1
5 2
6 3

【问题分析】

先读入矩阵,从第一列最后一行向上开始输出,紧接着是第二列最后一行向上......

【完整代码】

#include
using namespace std;
int a[15][15];
int main()
{
	int m, n;
	cin >> m >> n;
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			cin >> a[i][j];

	cout << n << " " << m << endl;
	for (int i = 0; i < n - 1; i++)
		for (int j = m - 1; j >= 0; j--)
		{
			if (j != 0)
				cout << a[j][i] << " ";
			else
				cout << a[j][i] << endl;
		}
	for (int j = m - 1; j >= 0; j--)
	{
		if (j != 0)
			cout << a[j][n - 1] << " ";
		else
			cout << a[j][n - 1];
	}
	return 0;
}

2.3字符串基本操作

【问题描述】

编写一个程序,输入一个正整数n和字符串A,对字符串A作如下处理:

  • 去掉重复的字符

  • 去掉所有非字母非数字的字符

  • 将字母大小写互换

  • 按照字符的ASCII码从大到小排序

最后在同一行里输出n个处理后的字符串A

【样例输入】

2 abcd123

【样例输出】

DCBA321DCBA321

【问题分析】

本题对字符串的处理顺序非常重要。

  • 如果一来就对原字符串去掉重复字符,实现难度很大;
  • 应该先进行字母大小写互换,再进行排序;(同一个字母的大小写ASCII码相差32)

我的顺序:

大小写转换->排序->不输出重复字符与非数字非字母字符串(排序后重复字符相邻

注:我并未将重复字符与非数字非字母字符删去,而是在输出时进行判断。

若要删除重复字符,可参见此文4.3.3

泛型算法(sort、unique)https://blog.csdn.net/weixin_54186646/article/details/123276875?spm=1001.2014.3001.5501

【完整代码】

#include
#include
#include
using namespace std;

int main()
{
	int n;
	string s;
	cin >> n >> s;
	int l = s.length();
	for (int i = 0; i < l; i++)
	{
		if (s[i] <= 'Z' && s[i] >= 'A')
			s[i] += 32;
		else if (s[i] <= 'z' && s[i] >= 'a')
			s[i] -= 32;
	}
	sort(s.begin(), s.end(), greater());
	for(int j=0;j= 'A') || (s[i] <= 'z' && s[i] >= 'a') || (s[i] <= '9' && s[i] >= '0')))
				cout << s[i];
		}
	return 0;
}

2.4整数加一

【问题描述】

编写一个程序,读入一个以字符串表示的非负整数(串中每个字符代表一个数字),输出该正整数加一后的结果。

【问题分析】

此题用字符串存放数字,说明数字可以非常大,甚至超出long long类型的存储范围,实为一道简单的高精度加法问题。我采用通用做法,即不一定是加1。

  1. 倒序输入
  2. 逐位相加(确定位数)
  3. 向高位进一位(调整位数)a[i+1]+=a[i]/10;a[i]%=10;
  4. 倒序输出

【完整代码】

#include
#include
using namespace std;
string s;
int a[55];
int main()
{
	cin >> s;
	a[0] = s.length();
	for (int i = 1; i <= a[0]; i++)
		a[i] = s[a[0] - i] - '0';
	a[1] += 1;
	for (int i = 1; i <= a[0]; i++)
	{
		a[i + 1] += a[i] / 10;
		a[i] %= 10;
	}
	if (a[a[0] + 1] > 0) a[0]++;

	for (int i = a[0]; i > 0; i--)
		cout << a[i];
	return 0;
}

2.5回文字符串

【问题描述】

回文字符串是具有回文特性的字符串:即该字符串从左向右读和从右向左读都一样,单独的字母不作为回文字符串,例如abcddcba即为一个长度为8的回文字符串。

编写一个程序,输入一个全是字母的字符串,找出字符串中最长的回文字符串,输出最长回文字符串的长度和最长的回文字符串(长度相同的输出第一个),若无回文字符串,只输出0。

【样例输入】

aAabccbaABcdcBA

【样例输出】

8 AabccbaA

【问题分析】

问题1:需要判断一个字符串是否为回文序列

可用两指针指向序列头尾,并移动指针同时向中间靠拢,判断指向的两字符是否相等,直到两指针相遇(奇数个字符)或相差一个位置(偶数个字符)。递归实现

问题2:需要在一个大的字符串中找到最长的一段回文序列

挨个遍历并截取小段字符判断是否为回文序列(若是,则记录字符串长度),若有更长的回文序列,则进行更新,直到将整个字符串遍历完。

【完整代码】

#include
#include
using namespace std;

typedef struct 
{
	int max;//当前字符长度
	int a;//当前序列第一个字符
	int b;//当前序列最后一个字符
}H;

/*递归*/
bool Huiwen(string s, int low, int high)
{
	if (s[low] != s[high])
		return false;
	if(low==high||low==high-1)
		return true;
	return Huiwen(s, low + 1,high - 1);
}
int main()
{
	string s;
	cin >> s;
	int l = s.length();
	H h;
	h.max = 0;
	h.a = 0;
	h.b = l - 1;
	//挨个截取出子字符串
	for (int i = 0; i < l; i++) 
	{
		for (int j = l - 1; j > i; j--)
		{
			bool ret = Huiwen(s, i, j);
			//是回文字符串且比记录的字符串长度还要长,则记录此字符串
			if (ret == true && (j - i + 1) > h.max)
			{
				h.max = j - i + 1;
				h.a = i;
				h.b = j;
			}
		}
	}
	if (h.max != 0)
	{
		cout << h.max << endl;
		for (int i = h.a; i <= h.b; i++)
			cout << s[i];
	}
	else
		cout << h.max;
	return 0;
}

3.1摄氏华氏温度转换

【问题描述】

建立一个类,在类中使用一个方法完成摄氏华氏温度的转换。假如用C表示摄氏温度,F表示华氏温度,则有:F=C*9/5+32。输入一整数表示摄氏温度,根据该公式编程求对应的华氏温度,结果小数点后保留一位有效数字。

【问题分析】

考察类的相关语法,注意C++中采用cout输出时的小数点保留问题

头文件#include

cout <

代表保留一位小数

【完整代码】

#include
#include
using namespace std;

class Tep
{
public:
	int c;
	double f;
	void convert()
		{
			f = double(c) * 9 / 5 + 32;
		}
};
int main()
{
	Tep t;
	cin >> t.c;
	t.convert();
	cout <

3.2 简易计算器

【问题描述】

用类和对象实现简易的计算器:读入两个整数运算数(data1和data2)及一个运算符(op),计算表达式data1 op data2的值,
其中op可以是+,-,*,/。

【问题分析】

注意:控制台输出运算结果,作除法运算时,若能够整除,则输出为整数,否则输出结果小数点后应保留两位有效数字。

【完整代码】

#include
#include
#include
using namespace std;
class Cal
{
public:
	int data1, data2;
	string s;
	void calculate()
	{
		if (s == "+")
			cout << data1 + data2;
		else if (s == "-")
			cout << data1 - data2;
		else if (s == "*")
			cout << data1 * data2;
		else if (s == "/")
		{
			if (data1 % data2 == 0)
				cout << data1 / data2;
			else
				cout << fixed << setprecision(2) << double(data1) / double(data2);
		}
	}
};
int main()
{
	Cal c;
	cin >> c.data1 >> c.data2 >> c.s;
	c.calculate();
	return 0;
}

3.3时间类Time的编写

本题专门出了一篇博客,讨论运算符重载问题。

C++运算符重载(输入输出、自增自减、累加累减)https://blog.csdn.net/weixin_54186646/article/details/123384926?spm=1001.2014.3001.5501

C++程序设计课上机作业_第1张图片

❄️4.1 矩形相交

【问题描述】

设置一个矩形类,其属性为左上和右下两点的坐标(x1, y1)和(x2,y2)。平面上有两个矩形A和B,其位置是任意的。编程求出其相交部分(如图中阴影部分)的面积。(0≤a,b≤1000)

 C++程序设计课上机作业_第2张图片

 【输入形式】

从标准输入读取两行以空格分隔的整数,格式如下:

Ax1 Ay1 Ax2 Ay2
Bx1 By1 Bx2 By2

其中(x1,y1)和(x2,y2)为矩形对角线上端点的坐标。各坐标值均为整数,取值在0至1000之间。
 
【输出形式】

向标准输出打印一个整数,是两矩形相交部分的面积(可能为0)。

【输入样例】

0 0 2 2
1 1 3 4

【输出样例】

1

【问题分析】

输入的两点可以是矩阵任一对角线上的端点,求相交面积可以先求矩形在X轴和Y轴上的交集。

矩形在X轴上的交集可以按照如下算法进行求解:

假设AX1和AX2中较大值为MAX_AX,较小值为MIN_AX;BX1和BX2中较大值为MAX_BX,较小值为MIN_BX。用MAX_AX和MAX_B中较小者减去MIN_AX和MIN_BX中的较大者,结果为正表示两矩形在X轴上的交集,若为负则表示不相交

【完整代码】

#include
#include
using namespace std;
class C
{
public:
	int x1, y1, x2, y2;
	int xmin = min(x1, x2);
	int xmax = max(x1, x2);
	int ymin = min(y1, y2);
	int ymax = max(y1, y2);
};
int main()
{
	C c1, c2;
	int a, b, flag = 0;
	cin >> c1.x1 >> c1.y1 >> c1.x2 >> c1.y2;
	cin >> c2.x1 >> c2.y1 >> c2.x2 >> c2.y2;
	c1.xmax = max(c1.x1, c1.x2);
	c1.xmin = min(c1.x1, c1.x2);
	c1.ymax = max(c1.y1, c1.y2);
	c1.ymin = min(c1.y1, c1.y2);

	c2.xmax = max(c2.x1, c2.x2);
	c2.xmin = min(c2.x1, c2.x2);
	c2.ymax = max(c2.y1, c2.y2);
	c2.ymin = min(c2.y1, c2.y2);
	//cout << c1.xmax;
	if (min(c1.xmax, c2.xmax) > max(c1.xmin, c2.xmin))
	{
		a = min(c1.xmax, c2.xmax) - max(c1.xmin, c2.xmin);
		flag = 1;
	}
	else
		flag = 0;
	if (min(c1.ymax, c2.ymax) > max(c1.ymin, c2.ymin))
	{
		b = min(c1.ymax, c2.ymax) - max(c1.ymin, c2.ymin);
		flag = 1;
	}
	else
		flag = 0;
	if (flag == 1)
		cout << a * b;
	else
		cout << 0;
	return 0;
}

❄️4.2成绩表里找同学

【问题描述】

编写一个程序,读入 N 个同学的姓名和语数外三门功课的单科成绩,对其按照一定的排序规则排序形成一张成绩表(先按总分从高到低排序,总分相同则按语文成绩由高到低排序,仍然相同则按数学成绩由高到低排序,若总分和单科成绩均相同则最后按姓名的字典序排序)。最后给定一个数字 K(K<=N) ,输出在这张排好序的成绩表中位置在第 K 位的同学的姓名和总分。

字典序举例说明:

abc > abd
a > aa

【输入形式】

  • 第一行输入一个正整数 N(1<=N<=1024),代表接下来将录入 N 个学生的成绩。

  • 接下来 N 行录入 N 条学生的成绩记录,每条记录依次为姓名,语文成绩,数学成绩,英语成绩,这四个字段以空格分隔。姓名为字符串(仅包含小写字母,不含空格,长度<=19),学生之间不会重名。三科成绩均为整数(0~100)。

  • 最后输入一个正整数 K(1<=K<=N),代表需要在成绩表中从前往后找到的位置。

【输出形式】

  • 在成绩表中从前往后处在第 K 位的同学的姓名和总分,中间以空格分隔。

【样例输入】

4
lily 90 100 88
jack 87 79 95
hanz 90 89 71
david 90 89 71
4

【样例输出】

hanz 250

【问题分析】

这是一个排序问题,而且需要对一个人的多个属性都进行排序,属性之间也存在优先级,所以我们可以将一个人用结构体表示,姓名、语文、数学、英语、总分为其四个属性。

在C++的题目里,我们通常采用sort()进行排序,但对于结构体的排序,需要我们自定义函数cmp来实现。(关于泛型算法的自定义,我后面也会出篇文章的,介绍自定义函数与lambda表达式,这里是关于泛型算法的第一篇文章)

STL中的sort()是结合了快速排序与插入排序的一种排序,目前是STL中最好的排序,但最近有一种新的算法应该应用在了Java里,比这种排序更好。

4.3.1sort()icon-default.png?t=M276https://blog.csdn.net/weixin_54186646/article/details/123276875?spm=1001.2014.3001.5501

 【完整代码】

#include
#include
#include
const int N = 1030;
using namespace std;
class Grade
{
public:
	int C, M, E;
	string s;
	int sum;
};
//return true就不排序;false就要排序
//string中的>、<按字典序排序
bool cmp(const Grade& g1, const Grade& g2)
{
	if (g1.sum > g2.sum)
		return true;
	else if (g1.sum == g2.sum && g1.C > g2.C)
		return true;
	else if (g1.sum == g2.sum && g1.C == g2.C && g1.M > g2.M)
		return true;
	else if (g1.sum == g2.sum && g1.C == g2.C && g1.M == g2.M && g1.s< g2.s)
		return true;
	else
		return false;
}
int main()
{
	int n,k;
	cin >> n;
	Grade g[N];
	for (int i = 0; i < n; i++)
	{
		cin >> g[i].s >> g[i].C >> g[i].M >> g[i].E;
		g[i].sum = g[i].C + g[i].M + g[i].E;
	}
	sort(g , g + n,cmp);
	cin >> k;
	cout << g[k-1].s << " " << g[k-1].sum;
	return 0;
}

❄️4.3动态二维double型数组类Matrix的编写

本题专门出了一篇博客,讨论动态二维数组类问题。

动态二维数组类(C++ Vector)https://blog.csdn.net/weixin_54186646/article/details/123442733?spm=1001.2014.3001.5501

C++程序设计课上机作业_第3张图片

5.1日期推算

【问题描述】

设计一个类用于存放日期,并向后推算指定日期经过n天后的具体日期。

【问题分析】

来说说我的想法:

  1. 首先计算从今天到1年1月1号的天数n1(把相应年、月、日的天数相加,用循环实现)
  2. 加上n天
  3. 再计算n2=n+n1天后的日期(看n2够减多少年,一年不够减,再减月,一个月不够减,再减天数)

【完整代码】

#include
#include
using namespace std;
class Date
{
public:
	static int a[2][12];
	static int b[2];
	int y0;
	int m0;
	int d0;
	//这里的构造函数不必要,只是练练而已
	Date(int y = 0, int m = 0, int d = 0)
	{
		y0 = y;
		m0 = m;
		d0 = d;
	}
	int judge(int a);
	friend istream& operator>>(istream& is, Date& d);
	friend ostream& operator<<(ostream& os, Date& d);
	int days_1(Date& d);
	void days_2(int sum, Date& d);
};

/*b[0]:非闰年天数 b[1]:闰年天数*/
int Date::b[2] = { 365,366 };
/*a[0][12]:非闰年的每月天数 a[1][12]闰年的每月天数*/
int Date::a[2][12] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };
/*是否是闰年,是则返回1,不是则返回0*/
int Date:: judge(int a)
{
	if ((a % 4 == 0 && a % 100 != 0) || a % 400 == 0)
		return 1;
	else 
		return 0;
}
/*按字符串读入,并分别按int型保存年月日*/
istream& operator>>(istream& is, Date& d)
{
	string s;
	is >> s;
	d.y0 = (s[0] - '0') * 1000 + (s[1] - '0') * 100 + (s[2] - '0') * 10 + (s[3] - '0');
	d.m0 = (s[4] - '0') * 10 + (s[5] - '0');
	d.d0 = (s[6] - '0') * 10 + (s[7] - '0');
	return is;
}
/*主要是添0,与超出限制*/
ostream& operator<<(ostream& os, Date& d)
{
	if (d.y0 < 1000)
	{
		os << "0" << d.y0;
		if (d.m0 < 10)
		{
			os << "0" << d.m0;
			if (d.d0 < 10)
				os << "0" << d.d0 ;
			else
				os << d.d0;
		}
		else
		{
			os << d.m0;
			if (d.d0 < 10)
				os << "0" << d.d0;
			else
				os << d.d0;
		}
	}
	else if (d.y0 >= 1000 && d.y0 <= 9999)
	{
		os << d.y0;
		if (d.m0 < 10)
		{
			os << "0" << d.m0;
			if (d.d0 < 10)
				os << "0" << d.d0 ;
			else
				os << d.d0 ;
		}
		else
		{
			os << d.m0;
			if (d.d0 < 10)
				os << "0" << d.d0 ;
			else
				os << d.d0 ;
		}
	}
	else
		os << "out of limitation!";
	return os;
}
/*计算从1年1月1日到今天有多少天,保存在sum里*/
int Date::days_1(Date &d)
{
	int sum = 0;
	//从(今年-1)到1年,把每年的天数相加(今年还没满)
	for (int i = d.y0-1; i > 0; i--)
	{
		sum += b[judge(i)];
	}
	//从(本月-1)到1月,把每月的天数相加(本月还没满)
	for (int j = d.m0-1; j >0; j--)
	{
		sum += a[judge(d.y0)][j - 1];
	}
	//加入当月的天数
	sum += d.d0 -1;
	return sum;
}
/*输入n(n大于0),则返回从1年1月1日(包括当天)开始经过了n天后的日期(不包括当天)*/
void Date:: days_2(int sum, Date &d)
{
	//sum够减多少年的
	for (d.y0 = 1; sum >= b[judge(d.y0)]; d.y0++)
	{
		sum -= b[judge(d.y0)];
	}
	//一年已经不够减了,再来减月
	for (d.m0 = 0; sum >= a[judge(d.y0)][d.m0]; d.m0++)
	{
		sum -= a[judge(d.y0)][d.m0];
	}
	//一月已经不够减了,剩下的天数+1就是几号了,此时又要加一个月
	d.m0++;
	d.d0 = sum + 1;
}

int main()
{
	Date d1;
	cin >> d1;
	int n;
	cin >> n;
	n += d1.days_1(d1);
	//此时的n为从1年1月1日到再经过原来的n日的总共天数
	d1.days_2(n, d1);
	cout << d1;
}

5.2 矩形

【问题描述】

设计一个Rectangle类。要求:

(1)包含两个成员变量m_length和m_width,其默认值为1。

(2)包含成员函数Perimeter()计算长方形的周长,Area()计算长方形面积。

(3)包含成员函数SetWidth()和GetWidth()用来设置和得到m_width的值,SetLength()和GetLength()用来设置和得到m_length的值。SetRange()函数应验证m_length和m_width均为0.0到20.0之间的浮点数。

(4)编写主函数,测试Rectangle类。

【样例输入】

4 5

【样例输出】

Length: 4    Width: 5
length and width are both in 0.0 - 20.0
Perimeter: 18
Area: 20

【完整代码】

#include
using namespace std;

class Rectangle
{
public:
	double m_length,m_width;
	double p, a;
	Rectangle(double l=1, double w=1)
	{
		m_length = l;
		m_width = w;
	}
	Rectangle& Perimeter();
	Rectangle& Area();
	Rectangle& SetWidth(double w);
	void GetWidth(Rectangle& r);
	Rectangle& SetLength(double l);
	void GetLength(Rectangle& r);
	void SetRange(Rectangle& r);
};
Rectangle& Rectangle::Perimeter()
{
	p = 2 * (m_length + m_width);
	cout << "Perimeter: " << p << endl;
	return *this;
}
Rectangle& Rectangle::Area()
{
	a = m_length * m_width;
	cout << "Area: " << a;
	return *this;
}
void GetWidth(Rectangle &r)
{
	double w;
	cin >> w;
	r.SetWidth(w);
}
Rectangle& Rectangle::SetWidth(double w)
{
	m_width = w;
	cout << "Width: " << m_width << endl;
	return *this;
}
void GetLength( Rectangle& r)
{
	double l;
	cin >> l;
	r.SetLength(l);
}
Rectangle& Rectangle::SetLength(double l)
{
	m_length = l;
	cout << "Length: " << m_length<<"    ";
	return *this;
}
void SetRange(Rectangle& r)
{
	if (r.m_length <= 20 && r.m_width <= 20 && r.m_length > 0 && r.m_width > 0)
		cout << "length and width are both in 0.0 - 20.0"< 20 && r.m_length > 0)
		cout << "width is not in 0.0 - 20.0" << endl;
	else if (r.m_length > 20 && r.m_width <= 20 && r.m_width > 0)
		cout << "length is not in 0.0 - 20.0" << endl;
	else
		cout << "length and width are not in 0.0 - 20.0"<

5.3人员信息

【问题描述】

编写一个Person类,包括:

1、普通数据成员:姓名,性别,年龄。

2、三个构造函数:无参数构造函数,有参数构造函数(参数:姓名的指针,年龄,性别),拷贝构造函数。

编写main()函数,分别调用三种构造函数,创建三个对象P1、P2、P3,其中P3的创建是用P2通过深拷贝复制得到的。

【问题分析】

三种构造函数

1.无参构造函数

person(){}

2.有参构造函数

person(int a){}

3.拷贝构造函数

person(const person &p){}

三种调用方法

1.括号法
   person p1;//默认构造函数调用
   person p2(10);//有参构造函数 
   person p3(p2);//拷贝函数构造

2.显示法
    person p4=person(10); //有参构造 
    person p5=person(p3);//拷贝构造
   注意: person(10)为匿名对象,当前行执行结束后,系统会立即回收匿名对象,不要利用拷贝构造函数初始化匿名对象 ,会被认为无参构造函数

3.隐式转换法
    person p6=10;//相当于person p6=person(10)
    person p7=p6; 

【完整代码】

#include
#include
using namespace std;

class Person
{
public:
	string name,s;
	int g;
	int age;
	Person()
	{
		string n;
		int g0;
		int a;
		cin >> n >> g0 >> a;
		cout << "Parameterless constructor" << endl;
		cout << "Information:" << endl;
		if (g0 == 1)
			s = "female";
		else
			s = "male";
		name = n;
		g = g0;
		age = a;
		cout << "Name: " << name << "    Sex: " << s << "    Age: " << age << endl;
	}
	Person(string n,int g0,int a)
	{
		cout << "Parameter constructor" << endl;
		cout << "Information:" << endl;
		
		if (g0 == 1)
			s = "female";
		else
			s = "male";
		name = n;
		g = g0;
		age = a;
		cout << "Name: " << name << "    Sex: " << s << "    Age: " << age << endl;
	}
	Person(const Person& p)
	{
		cout << "Copy constructor" << endl;
		cout << "Information:" << endl;
		cout << "Name: " << p.name << "    Sex: " <> n >> g >> a;
	Person p2(n, g, a);
	Person p3(p2);
	return 0;
}

6.1动态顺序表

【问题描述】

设计动态顺序表类,实现表内数据的自动排序。初始化时输入5个整数,使表内数据完成排序并输出。之后在表的最后插入数字8,再次排序并输出。最后通过拷贝构造函数得到另一个相同的表并输出,并使用析构函数释放内存。

【问题分析】

考察构造函数与析构函数。

【完整代码】

#include
#include
#include
using namespace std;
class List
{
public:
	vector v;
	void Input()
	{
		int x;
		for (int i = 0; i < 5; i++)
		{
			cin >> x;
			v.push_back(x);
		}
	}
	void Sort()
	{
		sort(v.begin(), v.end());
	}
	void insert()
	{
		v.push_back(8);
		Sort();
	}
	void show()
	{
		for (auto it = v.begin(); it != v.end(); it++)
			cout << *it << " ";
	}
	~List()
	{
		vector(v).swap(v);
	}
	List(const List &l)
	{
		v = l.v;
	}
	List()
	{}
};
int main()
{
	List l;
	l.Input();
	l.Sort();
	l.show();
	cout << endl;
	l.insert();
	l.Sort();
	l.show();
	cout << endl;
	List l1(l);
	l1.show();
	return 0;
}

6.2由圆派生出圆柱

【问题描述】

定义一个Circle圆形类,在此基础上派生出Cylinder圆柱体类。要求在主程序中输入圆的半径后输出对应半径的圆的面积(area),再在输入圆柱的高之后输出对应圆底半径和高的圆柱体表面积(area)和体积(volume)。

【问题分析】

考察有参构造函数、类的继承

我在刚开始时,把输入(cin>>)写在了构造函数里面,这时出现了一个问题:子类虽然可以继承父类的属性,但似乎不能继承父类已经给半径r赋好的值,这就导致子类的r没有被赋值。

于是,我们还是应该在主函数main里定义半径r与圆柱高h,通过有参构造函数,将r与h分别传递给Circle类与Cylinder类。

【完整代码】

#include
using namespace  std;
const double pi = 3.14;

class Circle
{
public:
	double r;
	Circle(double x) :r(x) {}
	double Area() { return r * r * pi; }
};
class Cylinder :public Circle
{
public:
	double h;
	Cylinder(double x, double y) :Circle(x), h(y) { }
	double S() { return  2 * r * r * pi + h * 2 * pi * r; }
	double V() { return  h *r * r * pi; }
};
int main()
{
	double r, h;
	cout << "Please enter the radius of the circle:";
	cin >> r;
	cout << "Please enter the height of the cylinder:";
	cin >> h;
	Circle c(r);
	Cylinder C(r,h);
	cout << "The area of the circle is:" << c.Area() << endl;
	cout << "The area of the cylinder is:" << C.S() << endl;
	cout << "The volumn of the cylinder is:" << C.V();
	return 0;
}

6.3虚函数--交通工具

【问题描述】

定义一个交通工具类vehicle,其具有三种基本属性:速度、轮子数量和重量。将它作为基类派生校车类car,卡车类truck和轮船类boat,定义类并定义虚函数来显示三种交通工具的各类信息。

其中,car类需显示速度、轮子数量、重量和载客量;truck类需显示速度、轮子数量、重量和额定负载;boat类需显示速度、轮子数量、重量和轮船类别(如客轮为'k')。

【问题分析】

考察类的继承与多态(虚函数)。

虚函数

1.格式

 virtual 类型 函数名(参数表)

2.作用

通过虚函数实现运行时的多态性

3.说明

  • 虚函数声明只能出现在类声明中的成员函数原型声明中。
  • 只有类的普通成员函数才能声明为虚函数,全局函数及静态成员函数不能声明为虚函数。
  • 虚函数可以在一个或多个派生类中被重复定义,因此它属于函数重载的情况。但是,这种函数重载与一般的函数重载是不同的。虚函数在派生类中重新定义时必须与基类中的原型完全相同(函数名、参数个数、参数类型、参数顺序、返回值类型)。

纯虚函数

1.来源

在多态中,通常父类中虚函数的实现毫无意义,主要都是调用子类重写的内容,因此可以将虚函数改为纯虚函数。

2.格式

virtual 返回值类型 函数名 (参数类别) = 0;

3.抽象类

当类中有了纯虚函数,这个类称为抽象类。

抽象类特点:

  • 无法实例化对象

  • 子类必须重写抽象类中的纯虚函数,否则也属于抽象类

【完整代码】

#include
using namespace std;
class vehicle
{
public:
	int speed;
	int wheel;
	int weight;
	vehicle() {}
};
class car :public vehicle
{
public:
	int people;
	car()
	{
		speed = 80;
		wheel = 4;
		weight = 1000;
		people = 4;
	}
	virtual void show()
	{
		cout << "car message" << endl;
		cout << speed << " " << wheel << " " << weight << " " << people << endl;
	}
};
class truck :public vehicle
{
public:
	int load;
	truck()
	{
		speed = 80;
		wheel = 4;
		weight = 2500;
		load =3000;
	}
	virtual void show()
	{
		cout << "truck message" << endl;
		cout << speed << " " << wheel << " " << weight << " " << load << endl;
	}
};
class boat :public vehicle
{
public:
	char m;
	boat()
	{
		speed = 30;
		wheel = 0;
		weight = 12000;
		m = 'k';
	}
	virtual void show()
	{
		cout << "boat message" << endl;
		cout << speed << " " << wheel << " " << weight << " " << m;
	}
};
int main()
{
	car c;
	c.show();
	truck t;
	t.show();
	boat b;
	b.show();
	return 0;
}

 谢谢你能够看到这里!

你可能感兴趣的:(C++,算法,c++)