# 🗃 案例

# 案例1:通讯录管理系统

🔑 涉及知识: 编程基础switch{}if..else...函数调用、输入 cin、输出 cout、结构体 struct

📋 系统需求: 通讯录是一个可以记录亲人、好友信息的工具。本教程主要利用 C++ 来实现一个通讯录管理系统,系统中需要实现的功能如下:

  • ☑️ 添加联系人:向通讯录中添加新人,信息包括(姓名、性别、年龄、联系电话、家庭住址)最多记录1000人
  • ☑️ 显示联系人:显示通讯录中所有联系人信息
  • ☑️ 删除联系人:按照姓名进行删除指定联系人
  • ☑️ 查找联系人:按照姓名查看指定联系人信息
  • ☑️ 修改联系人:按照姓名重新修改指定联系人
  • ☑️ 清空联系人:清空通讯录中所有信息
  • ☑️ 退出通讯录:退出当前使用的通讯录

💡 实现步骤:

➰ 系统代码:

main.cpp 📄

#include "linkman.h"
using namespace std;
// 主函数 
int main() {
	linkman();
	return 0;
}
1
2
3
4
5
6
7
1
2
3
4
5
6
7

linkman.h📄

#ifndef LINKMAN_H
#define LINKMAN_H

#pragma once
#include <iostream>
#include <string> 

#define N 100

using namespace std;
/*****     结构体       ******/
/*
	联系人 
*/
typedef struct {
	string name;	// 姓名
	int sex;		// 性别
	int age;		// 年龄
	string phone;	// 联系电话 
	string address;	// 住址 
} Linkman;

/*
	通讯录 
*/
typedef struct {
	 Linkman lm[N];	// 通讯录
	 int size;	// 保存人数 
} Addrbook;
/*****     函数       ******/
/*
	继续及清屏
*/
void clr()
{
	system("pause");
	system("cls"); 
}
/*
	添加联系人 
*/
int addLinkman(Addrbook *book)
{
	// 通讯录满判断 
	if (book->size == N) {
		cout << "通讯录已满" << endl;
		return 0;
	}
	
	// 输入联系人信息 
	Linkman man;
	cout << "输入姓名:";
	cin >> man.name;
	cout << "输入性别(0-男,1-女, 其余数字及默认为女):";
	scanf("%d", &(man.sex));
	getchar();	// 吸收换行键 
	cout << "输入年龄:";
	scanf("%d", &(man.age));
	getchar();	// 吸收换行键 
	cout << "输入电话:";
	cin >> man.phone;
	cout << "输入地址:";
	cin >> man.address;
	
	// 加入通讯录 
	book->lm[(book->size) ++] = man;
	cout << ">> 已将" << man.name << "加入通讯录" << endl << endl; 
	
	clr();
	
	return 1;
}
/*
	显示联系人 
*/
void showLinkman(const Addrbook *book) 
{
	int size = book->size;	// 联系人数量
	
	// 通讯录空,提示 
	if (size == 0) {
		cout << ">> 当前通讯录为空,请先添加联系人" << endl;
		clr();
		return;
	}
	
	// 显示联系人 
	for (int i = 0; i < size; i ++)
	{
		cout << "-----------------------------------" << endl;
		cout << "【第" << (i + 1) << "位联系人】" << endl;
		cout << "\t姓名:" << book->lm[i].name << endl;
		cout << "\t性别:" << (book->lm[i].sex ? "女" : "男") << endl;
		cout << "\t年龄:" << book->lm[i].age << endl;
		cout << "\t电话:" << book->lm[i].phone << endl;
		cout << "\t地址:" << book->lm[i].address << endl;
	}
	cout << "-----------------------------------" << endl;;
	clr();
}
/*
	查找联系人 
*/
int isLinkman(const Addrbook *book)
{
	int size = book->size;
	
	// 通讯录是否为空
	if (size == 0) {
		cout << ">> 当前通讯录为空,请先添加联系人" << endl;
		clr();
		return -1;
	}
	
	// 通过姓名查找
	string name;
	cout << "联系人姓名:";
	cin >> name; 
	
	// 检测所查找的人是否在通讯录
	for (int i = 0; i < size; i ++)
		if (book->lm[i].name == name)
			return i;
	
	//  查无此人 
	return -1;
}
/*
	删除联系人 
*/
int delLinkman(Addrbook *book)
{
	int size = book->size;
	
	// 通讯录是否为空
	if (size == 0) {
		cout << ">> 当前通讯录为空,请先添加联系人" << endl;
		clr();
		return 0;
	}
	
	// 查找联系人 
	int d = isLinkman(book);
	if (d >= 0) {
		string name = book->lm[d].name;
		// 将后面的联系人往前挪 
		for (int j = d; j < size-1; j ++)
			book->lm[j] = book->lm[j+1];
		(book->size) --;
		// 成功提示
		cout << ">> 已将" << name << "从通讯录中移除" << endl;
		clr();
		return 1;
	}

	// 通讯录中查无此人
	cout << ">> 通讯录中不存在该联系人,因此无法进行删除" << endl;
	clr();
	return 0;
}
/*
	查找联系人 
*/
int searchLinkman(const Addrbook *book)
{
	int size = book->size;
	// 通讯录是否为空
	if (size == 0) {
		cout << ">> 当前通讯录为空,请先添加联系人" << endl;
		clr();
		return 0;
	}
	
	// 查找 
	int d = isLinkman(book);
	if (d >= 0) {
		cout << ">> 查找到的联系人信息如下:" << endl;
		cout << "-----------------------------------" << endl;
		cout << "【第" << (d + 1) << "位联系人】" << endl;
		cout << "\t姓名:" << book->lm[d].name << endl;
		cout << "\t性别:" << (book->lm[d].sex ? "女" : "男") << endl;
		cout << "\t年龄:" << book->lm[d].age << endl;
		cout << "\t电话:" << book->lm[d].phone << endl;
		cout << "\t地址:" << book->lm[d].address << endl;
		cout << "-----------------------------------" << endl;
		
		clr();
		return 1;
	}
	
	// 查找失败 
	cout << ">> 通讯录中不存在该联系人" << endl;
	clr();
	return 0;
} 
/*
	修改联系人 
*/
int modifyLinkman(Addrbook *book)
{
	int size = book->size;
	// 通讯录是否为空
	if (size == 0) {
		cout << ">> 当前通讯录为空,请先添加联系人" << endl;
		clr();
		return 0;
	}
	
	// 查找 
	int d = isLinkman(book);
	if (d >= 0) {
		// 查找到需要修改的联系人信息 
		cout << ">> 查找到的联系人信息如下:" << endl;
		cout << "-----------------------------------" << endl;
		cout << "【第" << (d + 1) << "位联系人】" << endl;
		cout << "\t姓名:" << book->lm[d].name << endl;
		cout << "\t性别:" << (book->lm[d].sex ? "女" : "男") << endl;
		cout << "\t年龄:" << book->lm[d].age << endl;
		cout << "\t电话:" << book->lm[d].phone << endl;
		cout << "\t地址:" << book->lm[d].address << endl;
		cout << "-----------------------------------" << endl;
		
		// 修改操作 
		int sex, age;
		string name, phone, address;
		cout << endl << ">> 接下来进行修改(若不修改某项请输入-1):" << endl;;
		
		cout << "输入姓名:";
		cin >> name;
		if (name != "-1") book->lm[d].name = name;
		
		cout << "输入性别(0-男,1-女, 其余数字及默认为女):";
		scanf("%d", &(sex));
		getchar();	// 吸收换行键 
		if (sex != -1) book->lm[d].sex = sex;
		
		cout << "输入年龄:";
		scanf("%d", &(age));
		getchar();	// 吸收换行键 
		if (age != -1) book->lm[d].age = age;
		
		cout << "输入电话:";
		cin >> phone;
		if (phone != "-1") book->lm[d].phone = phone;
		
		cout << "输入地址:";
		cin >> address;
		if (address != "-1") book->lm[d].address = address;
		
		// 修改成功
		cout << ">> 修改成功" << endl; 
		
		clr();
		return 1;
	}
	
	// 查无此人
	cout << ">> 通讯录中不存在该联系人,因此无法进行修改" << endl;
	clr();
	return 0;
}
/*
	清空通讯录 
*/
int clrLinkman(Addrbook *book)
{
	string comfirm;
	cout << ">> 再次确认,是否清空通讯录?(Y/N):  " << endl;
	cin >> comfirm;
	if (comfirm == "N")
	{
		cout << ">> 已取消清空通讯录操作" << endl;
		clr();
		return 0;
	}
	
	// 联系人数量置为0 
	book->size = 0;
	cout << ">> 通讯录已清空" << endl;
	
	clr();
	return 1;
}
/*
	显示菜单 
*/
int menu()
{
	cout << "\t***********************" << endl;
	cout << "\t**                  ** *" << endl;
	cout << "\t**                  ** *" << endl;
	cout << "\t**   1.添加联系人   ** *" << endl;
	cout << "\t**   2.显示联系人   ** *" << endl;
	cout << "\t**   3.删除联系人   ** *" << endl;
	cout << "\t**   4.查找联系人   ** *" << endl;
	cout << "\t**   5.修改联系人   ** *" << endl;
	cout << "\t**   6.清空联系人   ** *" << endl;
	cout << "\t**   7.退出通讯录   ** *" << endl;
	cout << "\t**                  ** *" << endl;
	cout << "\t**                  ** *" << endl;
	cout << "\t********************** *" << endl;
	cout << "\t * * * * * * * * * * * *" << endl;
	cout << "\t  * * * * * * * * * * **" << endl;
	
	return 1;
}
/******      主函数      ******/
/*
	通讯录管理系统 
*/
void linkman()
{
	Addrbook abook;
	abook.size = 0;
	
	bool enter = true;
	int key;
	
	while(enter)
	{
		menu();
		cout << "选择操作:";
		scanf("%d", &key);
		getchar();
		
		switch(key)
		{
			case 1: // 添加联系人 
				addLinkman(&abook);
				break;
			case 2: // 显示联系人 
				showLinkman(&abook);
				break;
			case 3: // 删除联系人 
				delLinkman(&abook);
				break;
			case 4: // 查找联系人 
				searchLinkman(&abook);
				break;
			case 5: // 修改联系人 
				modifyLinkman(&abook);
				break;
			case 6: // 清空联系人 
				clrLinkman(&abook);
				break;
			case 7: // 退出联系人
				cout << "欢迎下次使用" << endl; 
				enter = false;
				break;
			default:
				key = 1;
				break;
		}
	}
}
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356

# 案例2:职工管理系统

🔑 涉及知识: 封装 class、继承、多态、文件操作 fstream

📋 系统需求:

职工管理系统可以用来管理公司内所有员工的信息。本教程主要利用 C++ 来实现一个基于多态的职工管理系统。

公司中职工分为三类:普通员工、经理、老板,显示信息时,需要显示职工编号、职工姓名、职工岗位、以及职责:

  • 普通员工职责:完成经理交给的任务
  • 经理职责:完成老板交给的任务,并下发任务给员工
  • 老板职责:管理公司所有事务

管理系统中需要实现的功能如下:

  • ☑️ 退出管理程序:退出当前管理系统
  • ☑️ 增加职工信息:实现批量添加职工功能,将信息录入到文件中,职工信息为:职工编号、姓名、部门编号
  • ☑️ 显示职工信息:显示公司内部所有职工的信息
  • ☑️ 删除离职职工:按照编号删除指定的职工
  • ☑️ 修改职工信息:按照编号修改职工个人信息
  • ☑️ 查找职工信息:按照职工的编号或者职工的姓名进行查找相关的人员信息
  • ☑️ 按照编号排序:按照职工编号,进行排序,排序规则由用户指定
  • ☑️ 清空所有文档:清空文件中记录的所有职工信息(清空前需要再次确认,防止误删)

💡 实现步骤:

➰ 系统代码:

main.cpp 📄

#include "wmanager.h"
using namespace std;
// 主函数 
int main() {
	wmanager(); // 系统主界面运行
	return 0;
}
1
2
3
4
5
6
7
1
2
3
4
5
6
7

wmanager.h 📄系统主界面

#ifndef WMANAGER_H
#define WMANAGER_H

#pragma once
#include <iostream>
#include <algorithm>
#include <string> 
#include "workerManager.h"	// 管理系统类 WorkerManager 
#include "worker.h"			// 员工基类 class Worker {}

using namespace std;
/*
	职工管理系统运行文件 
*/
void wmanager() 
{
	WorkerManager wm;
	
	bool enter = true;	// 是否进入系统 
	int key;			// 选择码 
	
	while(enter)
	{
		wm.showMenu();
		cout << "选择操作:";
		scanf("%d", &key);
		getchar();
		
		switch(key)
		{
			case 0: // 退出管理程序
				wm.exitSystem();
				enter = false;	// 退出系统 
				break;
			case 1: // 增加职工信息 
				wm.addWorker();
				break;
			case 2: // 显示职工信息 
				wm.showWorker();
				break;
			case 3: // 删除离职职工 
				wm.delWorker();
				break;
			case 4: // 修改职工信息 
				wm.modWorker();
				break;
			case 5: // 查找职工信息 
				wm.getWorker();
				break;
			case 6: // 按照编号排序 
				wm.sortWorker();
				break;
			case 7: // 清空所有文档
				wm.clearWorker();
				break;
			default:
				system("cls");
				break;
		}
	}
}
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

workerManager.h 📄管理系统类

#ifndef WORKERMANAGER_H
#define WORKERMANAGER_H

#pragma once	// 防止头文件重复包含 

#include <iostream>
#include <fstream>
#include <sstream>	// 要使用stringstream流应包含此文件 
	
#include "worker.h"		// 员工基类,下面三个类型的员工都是继承自worker类 
#include "employee.h"	// 普通员工类  
#include "manager.h"	// 经理类 
#include "boss.h"		// 老板类 

#define FILENAME "./empFile.txt"	// 存放员工信息的文件名 
#define SUB_STR " "					// 存放员工数据时的分隔符 

using namespace std;

class WorkerManager {
public:
	// 记录文件中的人数
	int m_EmpNum;
	// 员工数组指针(指向指针的指针)
	Worker ** m_EmpArray; 
	 
public:
	// 构造函数
	WorkerManager();
	// 显示菜单
	void showMenu();
	// 退出系统
	void exitSystem(); 
	// 增加职工信息
	void addWorker();
	// 显示职工信息 
	void showWorker();
	// 删除离职职工
	void delWorker();
	// 修改职工信息 
	void modWorker();
	// 查找职工信息 
	void getWorker();
	// 按照编号排序 
	void sortWorker();
	// 清空所有文档
	void clearWorker();
	// 保存文件
	void save(); 
	// 析构函数
	~WorkerManager(); 

// 私密成员函数,只能在内部访问 
protected:
	// 编号查找,返回索引
	int searchById(int id)
	{
		for (int i = 0; i < this->m_EmpNum; ++i)
			if (this->m_EmpArray[i]->m_Id == id)
				return i;
		return -1;
	}
	// 姓名查找,返回索引
	int searchByName(string name)
	{
		for (int i = 0; i < this->m_EmpNum; ++i)
			if (this->m_EmpArray[i]->m_Name == name)
				return i;
		return -1;
	}
};
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

# 案例3:类模板仿造数组

🔑 涉及知识: 类模板template<class T>拷贝构造

📋 案例描述: 实现一个通用的数组类,要求如下:

  • 可以对内置数据类型以及自定义数据类型的数据进行存储
  • 将数组中的数据存储到堆区(new)
  • 构造函数中可以传入数组的容量
  • 提供对应的拷贝构造函数 (opens new window)以及operator=防止浅拷贝问题
  • 提供尾插法和尾删法对数组中的数据进行增加和删除
  • 可以通过下标的方式访问数组中的元素
  • 可以获取数组中当前元素个数和数组的容量

➰ 案例代码:

Box.hpp 📄数组类

/*
	通用数组类 
*/
template<class T>
class Box {
private:
	T * p;	// 指针,指向堆区开辟的数组
	int size;	// 大小 
	int capacity;	// 实际容量
public:
	// 构造函数(有参) 
	Box(int capacity)
	{
		cout << "有参构造调用" << endl;
		this->capacity = capacity;
		this->size = 0;
		this->p = new T[this->capacity];
	} 
	
	// 构造函数(拷贝)
	Box(const Box& arr)
	{
		cout << "拷贝构造调用" << endl;
		this->capacity = arr.capacity;
		this->size = arr.size;
		// 浅拷贝:this->p = arr.p;
		// 深拷贝 : 
		this->p = new T[arr.capacity];
		// 将arr中的数据拷贝过来
		for (int i = 0; i < this->size; ++i)
			this->p[i] = arr.p[i];
	} 
	
	// operator= 防止浅拷贝问题
	Box& operator=(const Box& arr)
	{
		cout << "operator=构造调用" << endl;
		// 先判断原来堆区是否有数据,如果有,就要先释放
		if (this->p != NULL)
		{
			delete[] this->p;
			this->p = NULL;
			this->capacity = 0;
			this->size = 0;
		} 
		
		// 深拷贝
		this->capacity = arr.capacity;
		this->size = arr.size;
		this->p = new T[arr.capacity];
		for (int i = 0; i < this->size; ++i)
			this->p[i] = arr.p[i];
			
		return *this;
	} 
	
	// 尾插法
	int push_back(const T &val)
	{
		// 判断数组是否满
		if (this->capacity == this->size) 
			return 0;	// 不做操作
		this->p[this->size++] = val; 
		return 1;
	} 
	
	// 尾删法
	int pop_back()
	{
		// 判断数组是否空 
		if (this->size == 0)
			return 0;
		this->size--;	// 逻辑删除 
		return 1;
	} 
	
	// 让用户通过下标方式访问数组元素
	T& operator[](int index)
	{
		// 下标溢出 
		if (index >= this->size) {
			cout << "Box Warning : 提供的下标超出数组范围" << endl;
			return this->p[0]; 
		}
		// 下标为负数,反向访问
		if (index < 0 && 0-index <= this->size)
			return this->p[this->size + index]; 
		//  下标为正
		return this->p[index]; 
	} 
	
	// 返回数组容量
	int getCount() { return this->capacity; } 
	
	// 返回数组大小
	int getSize() { return this->size; } 
	
	// 析构函数 
	~Box()
	{
		cout << "析构调用" << endl;
		if (this->p) 
		{
			delete[] this->p;
			this->p = NULL;
		}
	}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

main.cpp 📄测试文件

#include <iostream>
#include <algorithm>
#include <string> 
#include "Box.hpp"

using namespace std;

int main(int argc, char** argv) {
	
	Box<User> arr(10);
	User u1("Tom1", 20);
	User u2("Tom2", 30);
	User u3("Tom3", 40);
	User u4("Tom4", 50);
	User u5("Tom5", 60);
	// 添加数据 
	arr.push_back(u1);
	arr.push_back(u2);
	arr.push_back(u3);
	arr.push_back(u4);
	arr.push_back(u5);
	// 复制一份
	Box<User> arr2(arr); 
	// 打印信息 
	for (int i = 0; i < arr.getSize(); ++i)
	{
		cout << "  姓名:" << arr[i].name 
		     << "  年龄:" << arr[i].age << endl;
	}
	cout << "容量:" << arr.getCount() << endl;
	cout << "大小:" << arr.getSize() << endl;
	
	return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 案例4:评委打分

🔑 涉及知识: vectordequesort()

📋 案例描述:

  • 有5名选手:选手ABCDE,10个评委分别对每一名选手打分,去除最高分,去除评委中最低分,取平均分。

💡 实现步骤:

  1. 创建五名选手,放到vector中
  2. 遍历vector容器,取出来每一个选手,执行for循环,可以把10个评分打分存到deque容器中
  3. sort算法对deque容器中分数排序,去除最高和最低分
  4. deque容器遍历一遍,累加总分
  5. 获取平均分

➰ 案例代码:





























































 

 

 

 



#include <iostream>
#include <algorithm>	// sort()
#include <string> 
#include <vector>
#include <deque>
#include <time.h>     // srand()

using namespace std;
// 选手类
class Player
{
public:
	string name;
	int score;
	
	Player(){};
	Player(string name, int score) {
		this->name = name;
		this->score = score;
	};
};
// 添加5名选手
void setPlayer(vector<Player> &v) {
	string s = "ABCDE";
	for (int i = 0; i < 5; ++i) {
		string name = "选手";
		name += s[i];
		Player p(name, 0);
		v.push_back(p);
	}
}
// 生成10个分数并将分数记入选手中
void setScore(vector<Player> &v) {
	for (vector<Player>::iterator it = v.begin(); it != v.end(); ++it) 
  {
		int score = 0;
		// 随机生成分数 
		deque<int> d;
		for (int i = 0; i < 10; ++i) d.push_back(rand() % 41 + 60);
		// 排序并剔除最高最低分
		sort(d.begin(), d.end());
		d.pop_front();
		d.pop_back();
		// 取平均分
		for (deque<int>::iterator dit = d.begin(); dit != d.end(); ++dit) score += *dit;
		score = score / d.size();
		// 平均分记入某选手
		it->score = score;
	}
}
// 输出选手最终分数
void print(const vector<Player> &v) {
	for (vector<Player>::const_iterator it = v.begin(); it != v.end(); ++it) {
		cout << it->name << "  分数:" << it->score << endl;
	}
}
// 案例主函数
int example() {
	// 随机数种子
	srand((unsigned int)time(NULL)); 
	// 1.创建容器v
	vector<Player> v;
	// 2.创建5个选手ABCDE,并放入容器v
	setPlayer(v);
	// 3.为每个选手打分
	setScore(v);
	// 4.选手结果
	print(v);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

# 案例5:关键字排序

🔑 涉及知识: listlist.sort()

📋 案例描述:User自定义数据类型进行排序,User中属性有姓名name、年龄age、身高height

  • 排序规则:按照年龄age进行升序,如果年龄相同按照身高height进行降序

➰ 案例代码:

#include <iostream>
#include <string> 
#include <list>

using namespace std;
// 用户类
class User
{
public:
	string name;
	int age;
	float height;
	
	User(){
	};
	User(string name, int age, float height) {
		this->name = name;
		this->age = age;
		this->height = height;
	};
};
// sort()排序回调函数 
bool compareUser(User &u1, User &u2)
{
	// 按照年龄排序,年龄相同就比较身高 
	if (u1.age == u2.age)
		return u1.height > u2.height;
	else
		return u1.age < u2.age; 
}
// 主函数
int main() {
	// 存放用户的容器 
	list<User> l;
	// 添加用户
	User u1("刘备", 35 , 175);
	User u2("曹操", 45 , 180);
	User u3("孙权", 40 , 170);
	User u4("赵云", 25 , 190);
	User u5("张飞", 35 , 160);
	User u6("关羽", 35 , 200);
	l.push_back(u1);
	l.push_back(u2);
	l.push_back(u3);
	l.push_back(u4);
	l.push_back(u5);
	l.push_back(u6);
	// 排序前 输出信息 
	cout << endl << "排序前:" << endl;
	for (list<User>::iterator it = l.begin(); it != l.end(); it++) {
		cout << "姓名:" << it->name << "  年龄:" << it->age << "  身高:" << it->height << endl;
	}
	// 排序
	l.sort(compareUser);
	// 排序后 输出信息 
	cout << endl << "排序后:" << endl;
	for (list<User>::iterator it = l.begin(); it != l.end(); it++) {
		cout << "姓名:" << it->name << "  年龄:" << it->age << "  身高:" << it->height << endl;
	}
	return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61

📌 总结:

  • 对于自定义数据类型,必须要指定排序规则,否则编译器不知道如何进行排序
  • 高级排序只是在排序规则上再进行一次逻辑规则制定,并不复杂

# 案例6:员工分组

🔑 涉及知识: vectormultimappair

📋 案例描述:

  • 公司今天招聘了10个员工(ABCDEFGHIJ),10名员工进入公司之后,需要指派员工在哪个部门工作
  • 员工信息有:姓名、工资组成;部门分为:策划、美术、研发
  • 随机给10名员工分配部门和工资
  • 通过 multimap 进行信息的插入 key (部门编号)、value (员工)
  • 分部门显示员工信息

💡 实现步骤:

  1. 准备好容器 vector vmap m
  2. 创建10名员工,随机分配工资,放到容器 v
  3. 遍历容器 v 容器,取出每个员工,随机分配部门(1-策划、2-美术、3-研发)
  4. 分组后,将员工部门编号作为 key,具体员工作为 value,放入到容器 m
  5. 分部门显示员工信息

➰ 案例代码:
























 


 







 


 


 

















#include <iostream> 	// 包含了<utility>中的pair 
#include <string> 
#include <vector>
#include <map>
#include <algorithm>	// rand()
#include <time.h>		// srand()

using namespace std;

// 员工类 
class Employee {
public:
	string name;	// 姓名
	int salary;		// 工资
	Employee(string n, int s) {
		this->name = n;
		this->salary = s;
	}
};
// 案例主函数 
void example() {
	// 随机种子
	srand((unsigned int)time(NULL)); 
	// 1.创建multimapr容器m、vector容器v 
	multimap<int, Employee> m;
	vector<Employee> v;
	// 2.创建10个员工,放入容器v 
	string s = "ABCDEFGHIJ", str; int r;	// 临时变量 
	for (int i = 0; i < 10; ++i) {
		str = "员工";
		str += s[i];				   // 员工A/B/C/D/E/F/G/H/I/J 
		r = rand() % 7000 + 4000;      // 随机产生区间[4000, 11000)里的工资 
		v.push_back(Employee(str, r)); // 分配给员工,并放入v中 
	}
	// 3.遍历员工,随机分配部门,并放入容器m中
	for (vector<Employee>::iterator it = v.begin(); it != v.end(); it++) {
		r = rand() % 3 + 1;	// 随机产生区间[1, 3]部门编号: 1-策划  2-美术  3-研发 
		// 4.将员工部门编号作为key,具体员工作为value,放入到容器m中
		m.insert(make_pair(r, *it));
	} 
	// 5.分部门打印信息 
	int k = 0;	// 部门编号,0作为开始 
	for (map<int, Employee>::iterator it = m.begin(); it != m.end(); it++) {
		// 如果当前员工部门与上一个员工部门不同,代表已经遍历到了新的部门员工信息 
		if (k != it->first) {
			k = it->first;
			// 打印部门信息 
			switch (k) {	
				case 1:	cout << "策划部:" << endl;	break;
				case 2:	cout << "美术部:" << endl;	break;
				case 3:	cout << "研发部:" << endl;	break;
			}
		}
		// 打印员工信息 
		cout << "    " << it->second.name << " 工资:" << it->second.salary << endl;
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

# 案例7:演讲比赛流程管理系统

🔑 涉及知识: STL<fstream>srand()/rand()string<ctime><functional><numeric><algorithm>

📋 系统需求:

  1. 比赛规则

    • 学校举行一场演讲比赛,共有12个人参加。比赛共两轮,第一轮为淘汰赛,第二轮为决赛。
    • 比赛方式:分组比赛,每组6个人;选手每次要随机分组,进行比赛
    • 每名选手都有对应的编号,如 10001 ~ 10012
    • 第一轮分为两个小组,每组6个人。 整体按照选手编号进行抽签后顺序演讲。
    • 当小组演讲完后,淘汰组内排名最后的三个选手,前三名晋级,进入下一轮的比赛。
    • 第二轮为决赛,前三名胜出
    • 每轮比赛过后需要显示晋级选手的信息
  2. 程序功能

    • 开始演讲比赛:完成整届比赛的流程,每个比赛阶段需要给用户一个提示,用户按任意键后继续下一个阶段
    • 查看往届记录:查看之前比赛前三名结果,每次比赛都会记录到文件中,文件用.csv后缀名保存
    • 清空比赛记录:将文件中数据清空
    • 退出比赛程序:可以退出当前程序
  3. 程序效果图

程序效果图

➰ 系统代码:

main.cpp 📄主函数

点击查看代码

 




 



#include <iostream>
#include "sManager.h"		// 比赛系统运行文件

using namespace std;

int main() {
	smanager();	// 比赛系统运行函数
	return 0;
}
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9

sManager.h 📄比赛系统运行文件

点击查看代码








 












































#ifndef SMANAGER_H
#define SMANAGER_H

#pragma once
#include <iostream>
#include <algorithm>
#include <string> 
#include <ctime>
#include "speechManager.h"	// 比赛管理系统类

using namespace std;

/*
	比赛流程管理系统运行文件 
*/
void smanager() 
{
	srand((unsigned int)time(NULL));
	SpeechManager sm;
	
	bool enter = true;	// 是否进入系统 
	int key;			// 选择码 
	// 选择操作
	while(enter)
	{
		sm.showMenu();
		cout << "选择操作:";
		scanf("%d", &key);
		getchar();
		
		switch(key)
		{
			case 0: // 退出比赛程序
				sm.exitSystem();
				enter = false;	// 退出系统 
				break;
			case 1: // 开始演讲比赛
				sm.startSpeech();
				break;
			case 2: // 查看往届记录 
				sm.showRecord();
				break;
			case 3: // 清空比赛记录
				sm.clearRecord();
				break;
			default:
				system("cls");
				break;
		}
	}
}
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

speechManager.h 📄比赛管理系统类(声明)

点击查看代码




 












































#pragma once
#include <iostream>
#include <vector>
#include <map>
#include "speaker.h"

using namespace std;

/* 设计演讲管理类 */
class SpeechManager {
public:
	vector<int> v1;		// 第一轮比赛选手编号
	vector<int> v2;		// 第二轮比赛选手编号
	vector<int> win;	// 决赛胜利选手编号
	map<int, Speaker> speakers;	// 编号与选手信息绑定
	int m_index;	// 记录比赛的次数 
	bool fileIsEmpty;	// 文件是否为空 
	map<int, vector<string> > m_Record;	//往届记录
public:
	// 构造函数
	SpeechManager();
	// 初始化
	void initSpeech(); 
	// 创建选手
	void createSpeaker(); 
	// 比赛菜单
	void showMenu(); 
	// 比赛开始
	void startSpeech(); 
	// 1.抽签
	void speechDraw(); 
	// 2.比赛
	void speechContest(); 
	// 3.显示晋级结果
	void showScore();
	// 4.保存分数到文件中 
	void saveRecord();
	// 查看往届记录
	void loadRecord();
	// 显示往届得分
	void showRecord();
	// 清空记录
	void clearRecord();
	// 退出比赛 
	void exitSystem();
	// 析构函数
	~SpeechManager(); 
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

speechManager.cpp 📄比赛管理系统类(实现)

点击查看代码





 





















































































































































































































































































































#include <algorithm>
#include <functional>
#include <numeric>
#include <deque>
#include <fstream>
#include "speechManager.h"	// 比赛管理系统类-声明

// 构造函数
SpeechManager::SpeechManager()
{
	this->initSpeech();		// 初始化
	this->createSpeaker();	// 创建选手
	this->loadRecord();	// 获取往届记录	 
}

// 初始化 
void SpeechManager::initSpeech()
{
	// 容器保证为空,并初始化比赛次数 
	this->v1.clear();
	this->v2.clear();
	this->win.clear();
	this->speakers.clear();
	this->m_index = 1;
	this->m_Record.clear();
}

// 创建选手
void SpeechManager::createSpeaker()
{
	string nameSeed = "ABCDEFGHIJKL";
	for (int i = 0; i < nameSeed.size(); i++) {
		// 选手
		string name = "选手";
		name += nameSeed[i];
		Speaker sp; 
		// 初始化 
		sp.m_Name = name;
		for (int j = 0; j < 2; j++) sp.m_Score[j] = 0;
		// 选手编号 
		v1.push_back(10001 + i); 
		this->speakers.insert(make_pair(10001 + i, sp));
	}
} 


// 比赛菜单
void SpeechManager::showMenu()
{
	cout << "********************************************" << endl;
	cout << "*************  欢迎参加演讲比赛 ************" << endl;
	cout << "*************  1.开始演讲比赛  *************" << endl;
	cout << "*************  2.查看往届记录  *************" << endl;
	cout << "*************  3.清空比赛记录  *************" << endl;
	cout << "*************  0.退出比赛程序  *************" << endl;
	cout << "********************************************" << endl;
	cout << endl;
}

// 比赛开始
void SpeechManager::startSpeech()
{
	//第一轮比赛
	//1、抽签
	this->speechDraw();
	//2、比赛
	this->speechContest();
	//3、显示晋级结果
	this->showScore();
	//第二轮比赛
	this->m_index++;
	//1、抽签
	this->speechDraw();
	//2、比赛
	this->speechContest();
	//3、显示最终结果
	this->showScore();
	//4、保存分数到文件中 
	this->saveRecord();
	
	// 比赛完成,重置选手和更新记录 
	this->initSpeech();		// 初始化
	this->createSpeaker();	// 创建选手
	this->loadRecord();	// 获取往届记录	  
	
	cout << "本届比赛完毕!" << endl;
	system("pause");
	system("cls");
} 

// 抽签
void SpeechManager::speechDraw()
{
	cout << "第 << " << this->m_index << " >> 轮比赛选手正在抽签"<<endl;
	cout << "---------------------" << endl;
	cout << "抽签后演讲顺序如下:" << endl;
	if (this->m_index == 1) {	// 第一轮 
		// 随机抽签 
		random_shuffle(this->v1.begin(), this->v1.end());
		for (vector<int>::iterator it = this->v1.begin(); it != this->v1.end(); it ++)
			cout << *it << "  ";
		cout << endl;
	} else {					// 第二轮 
		// 随机抽签 
		random_shuffle(this->v2.begin(), this->v2.end());
		for (vector<int>::iterator it = this->v2.begin(); it != this->v2.end(); it ++)
			cout << *it << "  ";
		cout << endl;
	}
	cout << "---------------------" << endl;
	system("pause");
	cout << endl;
}

// 比赛
void SpeechManager::speechContest()
{
	cout << "------------- 第"<< this->m_index << "轮正式比赛开始:------------- " << endl;

	multimap< double, int, greater<int> > groupScore; //临时容器,保存key分数 value 选手编号

	int num = 0; //记录人员数,6个为1组
	
	vector<int> v_Src;   //比赛的人员容器
	v_Src = (this->m_index == 1) ? v1 : v2;
	
	// 遍历所以选手 
	for (vector<int>::iterator it = v_Src.begin(); it != v_Src.end(); it++) 
	{
		num ++;
		// 打分
		deque<int> d;
		for (int i = 0; i < 10; i++) {
			double score = (rand() % 401 + 600) / 10.f;
			d.push_back(score);
		}
		sort(d.begin(), d.end(), greater<double>());	// 排序
		d.pop_back();	// 去掉最低分 
		d.pop_front();	// 去掉最高分 
		double sum = accumulate(d.begin(), d.end(), 0.0f);	// 获取总分
		double avg = sum / (double)d.size();				// 获取平均分 
		// 赋值给对手
		this->speakers[*it].m_Score[this->m_index - 1] = avg;
		
		// 6个人一组,用临时容器保存
		groupScore.insert(make_pair(avg, *it));
		if (num % 6 == 0) {	
			// 一组比赛完成,输出各选手成绩 
			cout << "第" << num / 6 << "小组比赛名次:" << endl;
			for (multimap<double, int, greater<int> >::iterator it = groupScore.begin(); it != groupScore.end(); it++)
			{
				cout << "编号: " << it->second 
					 << " 姓名: " << this->speakers[it->second].m_Name 
					 << " 成绩: " << this->speakers[it->second].m_Score[this->m_index - 1] 
					 << endl;
			}
			int count = 0;
			// 晋级 
			for (multimap<double, int, greater<int> >::iterator it = groupScore.begin(); it != groupScore.end() && count < 3; it++, count++)
			{
				if (this->m_index == 1) v2.push_back(it->second);	// 进入决赛 
				else win.push_back(it->second);	// 获得前三名 
			}
			groupScore.clear();
			cout << endl;
		}
	}
	cout << "------------- 第" << this->m_index << "轮比赛完毕  ------------- " << endl;
	system("pause");
} 

// 3.显示晋级结果
void SpeechManager::showScore()
{
	cout << "---------第" << this->m_index << "轮晋级选手信息如下:-----------" << endl;
	vector<int> v = (this->m_index == 1) ? v2 : win;
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
		cout << "选手编号:" << *it 
		     << " 姓名: " << speakers[*it].m_Name 
		     << " 得分: " << speakers[*it].m_Score[this->m_index - 1] 
		     << endl;
	}
	cout << endl;
	
	system("pause");
	system("cls");
	this->showMenu(); 
}

// 4.保存分数到文件中 
void SpeechManager::saveRecord()
{
	ofstream ofs;
	ofs.open("speech.csv", ios::out | ios::app);
	// 将赢者写入文件
	for (vector<int>::iterator it = win.begin(); it != win.end(); it++)
	{
		ofs << *it << ","
		    << speakers[*it].m_Score[1] << ",";
	} 
	ofs << endl;
	// 关闭文件
	ofs.close();
	cout << "记录已经保存" << endl; 
	// 有记录了,文件不为空 
	this->fileIsEmpty = false;
}

// 查看往届记录
void SpeechManager::loadRecord()
{
	ifstream ifs("speech.csv", ios::in);
	if (!ifs.is_open()) {
		this->fileIsEmpty = true;
		//cout << "文件不存在!" << endl;
		ifs.close();
		return;
	}
	char ch;
	ifs >> ch;
	if(ifs.eof()) {
		//cout << "文件为空!" << endl;
		this->fileIsEmpty = true;
		ifs.close();
		return;
	}
	// 文件不为空
	this->fileIsEmpty = false;
	
	ifs.putback(ch);	// 读取的单个字符放回去
	// 解析文件中的数据 
	string data;
	int index = 0;
	while (ifs >> data) // data = "10010,86.375,10009,81,10002,78,"
	{
		vector<string> v;
		
		int pos = -1;
		int start = 0;
		// 找分隔符','直到data数据的最后 
		while (true)
		{
			pos = data.find(",", start);	// 从0开始查找
			if (pos == -1) break;	// 找不到 返回
			string tmp = data.substr(start, pos - start);	// 找到了,进行分割
			v.push_back(tmp);
			start = pos + 1;  
		}
		this->m_Record.insert(make_pair(index, v));
		index++;
	}
	ifs.close();
}

//显示往届得分
void SpeechManager::showRecord()
{
	if (this->fileIsEmpty) {
		cout << "文件为空或者文件不存在!" << endl;
	}
	else {
		for (int i = 0; i < this->m_Record.size(); i++) {
			cout << "  第" << (i + 1) << "届" 
			     << "  冠军编号:" << this->m_Record[i][0] << "  分数:"  << this->m_Record[i][1] << " "
			     << "  亚军编号:" << this->m_Record[i][2] << "  分数:"  << this->m_Record[i][3] << " "
			     << "  季军编号:" << this->m_Record[i][4] << "  分数:"  << this->m_Record[i][5] << " "
				 << endl;
		}
	}
	system("pause");
	system("cls");
}

// 清空记录
void SpeechManager::clearRecord()
{
	cout << "确认清空?" << endl;
	cout << "1、确认" << endl;
	cout << "2、返回" << endl;

	int select = 0;
	cin >> select;

	if (select == 1)
	{
		//打开模式 ios::trunc 如果存在删除文件并重新创建
		ofstream ofs("speech.csv", ios::trunc);
		ofs.close();

		//初始化属性
		this->initSpeech();
		//创建选手
		this->createSpeaker();
		//获取往届记录
		this->loadRecord();

		cout << "清空成功!" << endl;
	}

	system("pause");
	system("cls");
}

// 退出比赛 
void SpeechManager::exitSystem()
{
	cout << "欢迎下次使用" << endl;
	system("pause");
	exit(0);
}
// 析构函数
SpeechManager::~SpeechManager()
{	
} 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314

speaker.h 📄参赛选手类

点击查看代码
#pragma once
#include <iostream>
using namespace std;

/*
	演讲选手类 
*/
class Speaker {
public:
	string m_Name;		// 姓名
	double m_Score[2];	// 两轮得分 
};
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12

# 案例8:机房预约系统

🔑 涉及知识: STL<fstream>srand()/rand()string<ctime><functional><numeric><algorithm>

📋 系统简介: 学校现有几个规格不同的机房,由于使用时经常出现"撞车"现象,现开发一套机房预约系统,解决这一问题。

  1. 身份简介:分别有三种身份使用该程序

    • 学生代表:申请使用机房
    • 教师:审核学生的预约申请
    • 管理员:给学生、教师创建账号
  2. 机房简介:机房总共有3间

    • 1号机房 --- 最大容量20人
    • 2号机房 --- 最多容量50人
    • 3号机房 --- 最多容量100人
  3. 申请简介

    • 申请的订单每周由管理员负责清空。
    • 学生可以预约未来一周内的机房使用,预约的日期为周一至周五,预约时需要选择预约时段(上午、下午)
    • 教师来审核预约,依据实际情况审核预约通过或者不通过
  4. 系统具体需求

    • 首先进入登录界面,可选登录身份有:
      • 学生代表
      • 老师
      • 管理员
      • 退出
    • 每个身份都需要进行验证后,进入子菜单
      • 学生需要输入 :学号、姓名、登录密码
      • 老师需要输入:职工号、姓名、登录密码
      • 管理员需要输入:管理员姓名、登录密码
    • 学生具体功能
      • 申请预约 --- 预约机房
      • 查看自身的预约 --- 查看自己的预约状态
      • 查看所有预约 --- 查看全部预约信息以及预约状态
      • 取消预约 --- 取消自身的预约,预约成功或审核中的预约均可取消
      • 注销登录 --- 退出登录
    • 教师具体功能
      • 查看所有预约 --- 查看全部预约信息以及预约状态
      • 审核预约 --- 对学生的预约进行审核
      • 注销登录 --- 退出登录
    • 管理员具体功能
      • 添加账号 --- 添加学生或教师的账号,需要检测学生编号或教师职工号是否重复
      • 查看账号 --- 可以选择查看学生或教师的全部信息
      • 查看机房 --- 查看所有机房的信息
      • 清空预约 --- 清空所有预约记录
      • 注销登录 --- 退出登录

💡 实现步骤:

➰ 系统代码:

main.cpp 📄主函数

#include "oManager.h"
using namespace std;

int main() {
	oManager();
	return 0;
}
1
2
3
4
5
6
7
1
2
3
4
5
6
7