写在前面

这一次是大一最后的程序实验课啦,基本上是对大一的一个检测自我水平的大作业吧。用C++实现一个学生信息管理系统。虽然我在大一上的时候用Java代码跟着黑马视频已经写过一个学生信息管理系统了,基本上也是增删改查操作,现在来看增删改查操作真的已经好简单了对于我来说哈哈哈。但是这一次不一样的地方在于要把学生信息写回.txt文本文件,相当于把存在内存的数据写入硬盘里面,实际上就是一个io流的操作嘛,之前我用的不太熟现在刚好可以拿来练手。正所谓语言不互通但是逻辑还是一样的。大概写了几天吧,我就提前给老师答辩了,还不错85分。主要是我按照了之前的理解先把学生对象存到容器中再进行文本文件的读写操作,但是老师的要求的是直接对文本文件进行操作,这个就是C++的特性了,要用指针对字节一个一个操作,真的很痛苦啊而且我也不太熟悉C++的底层,那就算了吧哈哈哈。以后可能就不写C++代码咯,也可能后面Java变成不主流了那只能用C++混口饭吃了,那么就记录一下这一次的C++期末大作业吧!大二就是我的领域啦!Java课程我来咯o( ̄▽ ̄)ブ

源代码实现

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
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
#include "app.h"
#include <list>//list容器类
#include <vector>
#include <string>
#include <locale>
#include<fstream>//包含了读写文件两种,支持数据的输入和输出操作
#include <iostream>
#include <sstream>
using namespace std;
//初始菜单函数接口
void menu() {
cout << "\n 学生信息管理系统\n\n"
<< "*******************************************************************************\n\n"
<< "\t\t\t\t0.退出系统\n\n"
<< "\t\t\t\t1.录入学生信息\n\n"
<< "\t\t\t\t2.导出学生信息\n\n"
<< "\t\t\t\t3.修改学生信息\n\n"
<< "\t\t\t\t4.删除学生信息\n\n"
<< "\t\t\t\t5.查询学生信息\n\n"
<< "*******************************************************************************\n";
}
//定义学生类
class Student {
private:
string id;//学号
string name;//学生姓名
string sex;//性别
int age;//年龄
string adder;//地址
string profession;//专业名称
int num_delete;//逻辑删除 1表示删除

public:

//无参构造方法
Student() {
num_delete = 0;//定义逻辑删除的默认值为0
}

// 有参构造方法
Student(string studentId, string studentName, string studentSex,
int studentAge, string studentAdder, string studentProfession) {
id = studentId;
name = studentName;
sex = studentSex;
age = studentAge;
adder = studentAdder;
profession = studentProfession;
num_delete = 0;//定义逻辑删除的默认值为0
}

// 匹配函数,判断当前学生对象是否匹配关键字
bool matchesKeyword(const string& keyword) const {
// 在此处实现匹配逻辑,假设关键字与姓名、性别和学号都进行匹配
bool idMatch = id.find(keyword) != string::npos;
bool nameMatch = name.find(keyword) != string::npos;
bool sexMatch = sex.find(keyword) != string::npos;
bool adderMatch = adder.find(keyword) != string::npos;
bool professionMatch = profession.find(keyword) != string::npos;

// 可以根据实际需求确定匹配条件,这里假设只要有一个字段匹配即可
return nameMatch || sexMatch || idMatch || adderMatch || professionMatch;
}

// Getter 方法
std::string getId() const {
return id;
}

std::string getName() const {
return name;
}

std::string getSex() const {
return sex;
}

int getAge() const {
return age;
}

std::string getAdder() const {
return adder;
}

std::string getProfession() const {
return profession;
}

int getNumDelete() const {
return num_delete;
}

// Setter 方法
void setId(const string& studentId) {
id = studentId;
}

void setName(const string& studentName) {
name = studentName;
}

void setSex(const string& studentSex) {
sex = studentSex;
}

void setAge(int studentAge) {
age = studentAge;
}

void setAdder(const string& studentAdder) {
adder = studentAdder;
}

void setProfession(const string& studentProfession) {
profession = studentProfession;
}

void setNumDelete(int deleteStatus) {
num_delete = deleteStatus;
}
};
//创建list容器存储学生类数据
list<Student> stulist;//list容器
list<Student>::iterator stu;//定义迭代器stu用来遍历list容器

//读取文本文件信息
void init() {
ifstream inputFile("students.txt");

// 读取文件数据

std::string line;
while (getline(inputFile, line)) {
Student student;
std::istringstream iss(line);
std::string field;

getline(iss, field, ','); // 读取学号字段
student.setId(field);

getline(iss, field, ','); // 读取姓名字段
student.setName(field);

getline(iss, field, ','); // 读取性别字段
student.setSex(field);

getline(iss, field, ','); // 读取年龄字段
student.setAge(stoi(field));

getline(iss, field, ','); // 读取地址字段
student.setAdder(field);

getline(iss, field); // 读取专业名称字段
student.setProfession(field);

stulist.push_back(student);
}
// 关闭文件
inputFile.close();
}

//检查学生输入是否合理的函数,抽取
Student checkStudent(string name,string sex,int age,string adder,string profession) {
string ids;
string a, b, c, d,e;
bool validInput = false;
bool validSex = false;

cout << "是否想添加姓名?(是/否)";
cin >> a;
if (a == "是") {
cout << "请输入姓名:" << endl;
cin >> name;
}
cout << "是否想添加性别?(是/否)";
cin >> b;
if (b == "是") {
while (!validSex) {
cout << "请输入性别(男/女):" << endl;
cin >> sex;
if (sex == "男" || sex == "女") {
validSex = true;
}
else {
cout << "性别输入不合理,重新输入";
}
}
}
cout << "是否想添加年龄?(是/否)";
cin >> c;
if (c == "是") {
while (!validInput) {
cout << "请输入年龄:" << endl;
if (cin >> age) {
if (age > 0 && age < 100) {
validInput = true;
}
else {
cout << "请输入一个合法的年龄" << endl;
}
}
else {
cout << "输入无效,请输入一个有效的数字年龄。" << endl;
cin.clear(); // 清除错误标志
cin.ignore(numeric_limits<streamsize>::max(), '\n'); // 忽略当前输入行
}
}
}
cout << "是否想添加地址?(是/否)";
cin >> d;
if (d == "是") {
cout << "请输入地址:" << endl;
cin >> adder;
}
cout << "是否想添加专业名称?(是/否)";
cin >> e;
if (e == "是") {
cout << "请输入专业名称:" << endl;
cin >> profession;
}
Student data(ids, name, sex, age, adder, profession);

return data;
}


//录入学生信息函数
void inputStudent() {
//录入信息的做法就是不断的创造新的节点,然后接到容器的尾部
cout << "请输入学生信息\n";
string ids, name, sex, adder, profession;
int age = 0;
bool validInput = false;
bool validId = false;
int i = 0;
while (!validId) {
cout << "请输入必选学号:(只可尝试三次)" << endl;
cin >> ids;
//对录入的数据进行判断
string yearString = ids.substr(0, 4);
//字符串转Int类型
int year = stoi(yearString);
if (year >= 1935 && year <= 2024 && ids.length() == 12) {
validId = true;
}
else {
cout << "输入无效,请输入符合规定的学号(12位数字并且数字含义正确)。" << endl;
i++;
if (i == 3) {
cout << "输入学号多次失败,自动返回系统界面" << endl;
return;
}
}
//遍历list容器查看学号是否已经存在
for (stu = stulist.begin(); stu != stulist.end(); stu++) {
if (ids == (*stu).getId()) {
cout << "学号已存在,请重新回初始界面选择" << endl;
return;
}
}
}
//调用抽取出来的函数直接添加
Student student = checkStudent(name, sex, age, adder, profession);


Student data(ids, student.getName(), student.getSex(), student.getAge(), student.getAdder(), student.getProfession());
//存入list容器中(在容器尾部插入元素)
stulist.push_back(data);
cout << "添加信息成功" << endl;
return;
}
//导出学生信息函数
void outputStudent() {
// 打开文件
ofstream outputFile1("students.txt");
ofstream outputFile2("DeleteStudents.txt");
//遍历list容器,获取学生对象
for (stu = stulist.begin(); stu != stulist.end(); stu++) {
if (outputFile1.is_open() && outputFile2.is_open()) {
if ((*stu).getNumDelete() != 1) {
// 写入学生对象的数据到文件
outputFile1 << (*stu).getId() << ", " << (*stu).getName() << ", " << (*stu).getSex()
<< ", " << (*stu).getAge() << ", " << (*stu).getAdder() << ", "
<< (*stu).getProfession() << endl;

cout << "学生信息导出成功!" << endl;
}
else {
// 写入学生对象的数据到文件
outputFile2 << (*stu).getId() << ", " << (*stu).getName() << ", " << (*stu).getSex()
<< ", " << (*stu).getAge() << ", " << (*stu).getAdder() << ", "
<< (*stu).getProfession() << endl;

cout << "学生信息导出成功!" << endl;
}
}
else {
cerr << "无法打开文件" << endl;
}
}

// 关闭文件
outputFile1.close();
outputFile2.close();
}

// 谓词函数,用于判断学号是否匹配
bool matchStudentId(const Student& student, const std::string& id) {
return student.getId() == id;
}

//修改学生数据
void updateStudent() {
string strId, name, sex, adder, profession;
int age = 0;
bool found = false;

cout << "请输入需要修改信息的学生的学号:";
cin >> strId;

// 遍历容器,查找匹配的学生对象
for (auto& student : stulist) {
if (student.getId() == strId && student.getNumDelete() != 1) {
found = true;
cout << "请输入你希望修改的学生信息:" << endl;
Student data = checkStudent(name, sex, age, adder, profession);

// 更新学生对象的数据
student.setName(data.getName());
student.setSex(data.getSex());
student.setAge(data.getAge());
student.setAdder(data.getAdder());
student.setProfession(data.getProfession());
break;
}
}

if (found) {
// 打开文件并清空内容
ofstream outputFile("students.txt", ios::out | ios::trunc);

if (outputFile.is_open()) {
// 将学生对象的数据写入文件
for (const auto& student : stulist) {
if (student.getNumDelete() != 1) {
outputFile << student.getId() << ", " << student.getName() << ", "
<< student.getSex() << ", " << student.getAge() << ", "
<< student.getAdder() << ", " << student.getProfession() << endl;
}
}

cout << "修改成功" << endl;
}
else {
cerr << "无法打开文件" << endl;
}

// 关闭文件
outputFile.close();
}
else {
cout << "该学号不存在或输入错误,请选择添加学生信息或再次输入:" << endl;
cout << "1.添加学生信息" << endl;
cout << "2.再次输入修改学号" << endl;
cout << "3.返回主菜单" << endl;
int choice;
cin >> choice;
switch (choice) {
case 1:
inputStudent();
break;
case 2:
updateStudent();
break;
default:
cout << "自动回到初始界面\n";
return;
break;
}
}
}

void deleteStudentPhysically(string id) {
ifstream inputFile("students.txt");
vector<Student> students;

// 读取文件数据

std::string line;
while (getline(inputFile, line)) {
Student student;
std::istringstream iss(line);
std::string field;

getline(iss, field, ','); // 读取学号字段
student.setId(field);

getline(iss, field, ','); // 读取姓名字段
student.setName(field);

getline(iss, field, ','); // 读取性别字段
student.setSex(field);

getline(iss, field, ','); // 读取年龄字段
student.setAge(stoi(field));

getline(iss, field, ','); // 读取地址字段
student.setAdder(field);

getline(iss, field); // 读取专业名称字段
student.setProfession(field);

students.push_back(student);
}

// 查找并删除已逻辑删除的学生数据
// 使用 lambda 表达式作为谓词函数来匹配学生对象
students.erase(remove_if(students.begin(), students.end(),
[id](const Student& s) { return s.getId() == id; }),
students.end());

// 关闭文件
inputFile.close();

// 将更新后的数据写回文件
ofstream outputFile("students.txt");
for (const auto& s : students) {
outputFile << s.getId() << ", " << s.getName() << ", " << s.getSex()
<< ", " << s.getAge() << ", " << s.getAdder() << ", "
<< s.getProfession() << endl;
}

// 关闭文件
outputFile.close();

cout << "已从文本文件中删除已逻辑删除的学生数据。" << endl;
}

//删除学生信息
void deldeteStudent() {
//通过学号查找学生信息
string strId;
bool f = true;
while (true) {
cout << "请输入需要删除信息的学生的学号";
cin >> strId;
if (strId.length() != 12) {
cout << "输入的学号有误,请重新输入" << endl;
}
else {
for (stu = stulist.begin(); stu != stulist.end(); stu++) {
if (strId == (*stu).getId()) {
//逻辑删除,将num_delete赋值为1
(*stu).setNumDelete(1);
deleteStudentPhysically(strId);
cout << "删除成功" << endl;
f = !f;
}
}
if (f) {
cout << "该同学的学号不存在无法删除" << endl;
}
break;
}
}
}

// 模糊查询函数
list<Student> fuzzySearch(const list<Student>& students, const string& keyword) {
list<Student> results;

for (const Student& student : students) {
if (student.matchesKeyword(keyword)) {
results.push_back(student);
}
}
return results;
}

//模糊查询并输出学生数据
void fuzzySearchResult() {
string keyword;
int i = 0;
cout << "请输入你想要查询的关键字";
cin >> keyword;
list<Student> searchResults = fuzzySearch(stulist, keyword);
if (searchResults.empty()) {
cout << "你输入的关键字无对应的匹配结果" << endl;
}
else {
cout << "含有关键字的学生对象输出如下:" << endl;
for (const Student& result : searchResults) {
if (result.getNumDelete() != 1) {
cout << result.getId() << ", " << result.getName() << ", " << result.getSex()
<< ", " << result.getAge() << ", " << result.getAdder() << ", "
<< result.getProfession() << endl;
i++;
}
}
cout << "满足条件的人数为:" << i << "人" << endl;
}
}

// 自定义比较函数,按照入学年份进行排序
bool compare(const Student& student1, const Student& student2) {
//先对学号进行处理,把入学年份拿到
string stringYear1 = student1.getId().substr(0, 4);
string stringYear2 = student2.getId().substr(0, 4);
//再转int类型比较大小
int year1 = stoi(stringYear1);
int year2 = stoi(stringYear2);
return year1 < year2;
}

//按照入学年份由小到大查询所有
void decList() {
stulist.sort(compare);
int i = 0;
// 输出排序后的学生对象
for (const Student& student : stulist) {
if (student.getNumDelete() != 1) {
cout << student.getId() << ", " << student.getName() << ", " << student.getSex()
<< ", " << student.getAge() << ", " << student.getAdder() << ", "
<< student.getProfession() << endl;
i++;
}
}
cout << "满足条件的人数为:" << i << "人" << endl;
}
//查询学生信息
void getStudent() {
int choice{ 0 };
cout << "请输入您要操作的序号" << endl;
cout << "1.模糊查询" << endl;
cout << "2.按照入学年份由小到大查询所有" << endl;
cin >> choice;
switch (choice) {
case 1:
fuzzySearchResult();
break;
case 2:
decList();
break;
default:
cout << "选择的序号不存在,请重新选择\n";
getStudent();
break;
}
}

//操作选择,采用switch选择
void keydown() {
int choice{ 0 };
cout << "请输入您要操作的序号";
cin >> choice;
switch (choice) {
case 0:
cout << "期待再次与你相遇...";
exit(0);
break;
case 1:
system("cls");
cout << "\n*****************************【录入学生信息】*********************************\n";
inputStudent();
break;
case 2:
system("cls");
cout << "\n*****************************【导出学生信息】*********************************\n";
outputStudent();
break;
case 3:
system("cls");
cout << "\n*****************************【修改学生信息】*********************************\n";
updateStudent();
break;
case 4:
system("cls");
cout << "\n*****************************【删除学生信息】*********************************\n";
deldeteStudent();
break;
case 5:
system("cls");
cout << "\n*****************************【查询学生信息】*********************************\n";
getStudent();
break;
default:
cout << "选择的序号不存在,请重新输入\n";
keydown();
break;
}
}


int main() {
init();
while (true) {
menu();
keydown();
}
return 0;
}