第一周实验
(1)来源:在博客园翻到的一篇名为C与C++实现学生管理系统的文章https://www.cnblogs.com/p-hacking/p/17359614.html
(2)运行环境+运行结果的截图(附伸缩源代码)
运行环境:Dev-C++
运行结果:


点击查看代码
#include <bits/stdc++.h>
using namespace std;
struct node {
char stuNum[10]; //学号
char stuName[10];//姓名
char sex[10];//性别
char domNum[10];//宿舍号码
char tel[10];//电话号码
int score;//成绩
/*
node(string stuNum[], string stuName, string sex, string domNum, string tel, int score) {
this->domNum = domNum;
this->score = score;
this->sex = sex;
this->stuName = stuName;
this->tel = tel;
this->stuNum = stuNum;
}
*/
};
//上面一些数据使用String类型而非int 或者 long long是考虑到溢出问题
vector<node> info;
int countNum;//全局变量初始化为0,记录输入人数。
int cmp1(node n1, node n2) {//构造升序比较器
return n1.score < n2.score;
}
int cmp2(node n1, node n2) {//构造降序比较器
return n1.score > n2.score;
}
void showMenu() {
cout << "********Welcome To Students' Information System********" << endl;
cout << "*****************请输入数字以进行使用******************" << endl;
cout << "*******************1:学生信息手动录入********************" << endl;
cout << "*******************2:学生信息自动导入********************" << endl;
cout << "*******************3:学生信息排序**********************" << endl;
cout << "*******************4:学生信息总览**********************" << endl;
cout << "*******************5:学生信息查询**********************" << endl;
cout << "*******************6: 退出程序 **********************" << endl;
}
void infoInput() {//学生信息录入
char stuNum[10]; //学号
char stuName[10];//姓名
string sex;//性别
char domNum[10];//宿舍号码
char tel[10];//电话号码
int score;//成绩
cout << "请输入学生学号:";
cin >> stuNum;
cout << "请输入学生姓名:";
cin >> stuName;
cout << "请输入学生性别:";
cin >> sex;
cout << "请输入学生宿舍号:";
cin >> domNum;
cout << "请输入学生电话:";
cin >> tel;
cout << "请输入学生分数(0-100):";
cin >> score;
if (score >= 0 && score <= 100 && (sex == "男" || sex == "女")) {
node n;
strcpy(n.stuName, stuName);
strcpy(n.sex,sex.c_str());
strcpy(n.stuNum, stuNum);
strcpy(n.domNum, domNum);
strcpy(n.tel, tel);
n.score = score;
info.push_back(n);
countNum++;
printf("信息插入成功\n");
} else {
cout << "插入非法数据" << endl;
}
}
void infoSort() {//学生信息排序
int s;
cout << "请选择排序类型:" << endl;
cout << " 1.按分数降序" << endl;
cout << " 2.按分数升序" << endl;
cin >> s;
if (s == 1) sort(info.begin(), info.end(), cmp2);
else if(s == 2) sort(info.begin(), info.end(), cmp1);
return;
}
void infoQuery() { //学生信息查询
cout << "请选择查询类型:" << endl;
cout << " 1.按学号查询" << endl;
cout << " 2.按姓名查询" << endl;
int s;
scanf("%d", &s);
if (s == 1) {
string sno;
cout << "请输入学号:" << endl;
cin >> sno;
int i;
for (i = 0; i < info.size(); i++) {
if (info[i].stuNum == sno) {
cout << "学号 姓名 性别 宿舍号码 电话号码 成绩" << endl;
cout << info[i].stuNum << " " << info[i].stuName << " " << info[i].sex << " " << info[i].domNum << " "
<< info[i].tel << " " << info[i].score << endl;
cout << "查询成功";
break;
}
}
if (i == info.size())
cout << "未查询到此学生" << endl;
} else if(s == 2) {
string sName;
cout << "请输入学号:" << endl;
cin >> sName;
int i;
for (i = 0; i < info.size(); i++) {
if (info[i].stuName == sName) {
cout << "学号 姓名 性别 宿舍号码 电话号码 成绩" << endl;
cout << info[i].stuNum << " " << info[i].stuName << " " << info[i].sex << " " << info[i].domNum << " "
<< info[i].tel << " " << info[i].score << endl;
cout << "查询成功";
break;
}
}
if (i == info.size())
cout << "未查询到此学生" << endl;
}
return;
}
void fileInput(){
char stuNum[10]; //学号
char stuName[10];//姓名
char sex[10];//性别
char domNum[10];//宿舍号码
char tel[10];//电话号码
int score;//成绩
node n;
FILE * fp;
char file[100] ;
cout<<"请输入数据路径:"<<endl;
scanf("%s",file);
if((fp = fopen(file,"r"))==NULL)
cout<<"输入路径有误或数据非法"<<endl;
else
{while (!feof(fp)){
fscanf(fp,"%s %s %s %s %s %d",stuNum, stuName,sex,domNum ,tel,&score);
strcpy(n.stuName, stuName);
strcpy(n.sex, sex);
strcpy(n.stuNum, stuNum);
strcpy(n.domNum, domNum);
strcpy(n.tel, tel);
n.score = score;
info.push_back(n);
countNum++;
}
cout<<"导入成功"<<endl;
}
}
void infoOutput() {//学生信息总览
cout << "序号 学号 姓名 性别 宿舍号码 电话号码 成绩" << endl;
for (int i = 0; i < info.size(); i++) {
cout << i + 1 << " " << info[i].stuNum << " " << info[i].stuName << " " << info[i].sex << " " << info[i].domNum
<< " " << info[i].tel << " " << info[i].score << endl;
}
cout << "共计" << countNum << "人" << endl;
}
int main() {
showMenu();
int a;
while (scanf("%d", &a)) {
switch (a) {
case 1:
infoInput();
break;
case 2:
fileInput();
break;
case 3:
infoSort();
break;
case 4:
infoOutput();
break;
case 5:
infoQuery();
break;
case 6:
return 0;
default:
break;
}
showMenu();
}
return 0;
}
- 当我进行某项动作,比如输入学号,但我不想进行该动作了,想中途退出了怎么办
2.输错了学生信息,想要修改怎么办
3.学生信息查询,按姓名查询,提示词却是请输入学号
4.根据代码健壮性的要求,对输入进行了一些限制,比如成绩范围和性别
(4)新代码附上
点击查看代码
#include <bits/stdc++.h>
using namespace std;
struct node {
char stuNum[10]; // 学号
char stuName[10]; // 姓名
char sex[10]; // 性别
char domNum[10]; // 宿舍号码
char tel[10]; // 电话号码
int score; // 成绩
};
vector<node> info;
int countNum = 0;
int cmp1(node n1, node n2) {
return n1.score < n2.score;
}
int cmp2(node n1, node n2) {
return n1.score > n2.score;
}
void showMenu() {
cout << "********Welcome To Students' Information System********" << endl;
cout << "*****************请输入数字以进行使用******************" << endl;
cout << "*******************1:学生信息手动录入********************" << endl;
cout << "*******************2:学生信息自动导入********************" << endl;
cout << "*******************3:学生信息排序**********************" << endl;
cout << "*******************4:学生信息总览**********************" << endl;
cout << "*******************5:学生信息查询**********************" << endl;
cout << "*******************6:学生信息修改**********************" << endl;
cout << "*******************7: 退出程序 **********************" << endl;
cout << "*********** 输入过程中输入 # 可退出当前操作 ************" << endl;
}
// 判断是否输入 # 退出
bool checkExit(string s) {
return s == "#";
}
void infoInput() {
string stuNum, stuName, sex, domNum, tel, scoreStr;
cout << "请输入学生学号(输入#退出):";
cin >> stuNum;
if (checkExit(stuNum)) { cout << "已退出录入\n"; return; }
cout << "请输入学生姓名(输入#退出):";
cin >> stuName;
if (checkExit(stuName)) { cout << "已退出录入\n"; return; }
cout << "请输入学生性别(输入#退出):";
cin >> sex;
if (checkExit(sex)) { cout << "已退出录入\n"; return; }
if (sex != "男" && sex != "女") {
cout << "性别只能是男/女,录入失败\n";
return;
}
cout << "请输入学生宿舍号(输入#退出):";
cin >> domNum;
if (checkExit(domNum)) { cout << "已退出录入\n"; return; }
cout << "请输入学生电话(输入#退出):";
cin >> tel;
if (checkExit(tel)) { cout << "已退出录入\n"; return; }
cout << "请输入学生分数(0-100,输入#退出):";
cin >> scoreStr;
if (checkExit(scoreStr)) { cout << "已退出录入\n"; return; }
for (int i = 0; i < scoreStr.size(); i++) {
char c = scoreStr[i];
if (!isdigit(c)) {
cout << "成绩必须是数字,录入失败\n";
return;
}
}
int score = atoi(scoreStr.c_str());
if (score < 0 || score > 100) {
cout << "成绩必须在 0~100 之间,录入失败\n";
return;
}
node n;
strcpy(n.stuNum, stuNum.c_str());
strcpy(n.stuName, stuName.c_str());
strcpy(n.sex, sex.c_str());
strcpy(n.domNum, domNum.c_str());
strcpy(n.tel, tel.c_str());
n.score = score;
info.push_back(n);
countNum++;
cout << "信息插入成功\n";
}
void infoModify() {
// 先判断是否有学生信息
if (info.empty()) {
cout << "暂无学生信息,无法修改!\n";
return;
}
string sno;
cout << "请输入要修改的学生学号(输入#退出):";
cin >> sno;
if (checkExit(sno)) {
cout << "已退出修改\n";
return;
}
// 查找对应学号的学生
int targetIndex = -1;
for (int i = 0; i < info.size(); i++) {
if (strcmp(info[i].stuNum, sno.c_str()) == 0) {
targetIndex = i;
break;
}
}
// 未找到学生
if (targetIndex == -1) {
cout << "未查询到该学号的学生,修改失败!\n";
return;
}
// 显示当前学生信息
cout << "\n当前该学生信息:\n";
cout << "学号:" << info[targetIndex].stuNum << endl;
cout << "姓名:" << info[targetIndex].stuName << endl;
cout << "性别:" << info[targetIndex].sex << endl;
cout << "宿舍号:" << info[targetIndex].domNum << endl;
cout << "电话:" << info[targetIndex].tel << endl;
cout << "成绩:" << info[targetIndex].score << endl;
// 选择要修改的字段
while (true) {
cout << "\n请选择要修改的字段(输入#退出修改):\n";
cout << "1. 姓名\n2. 性别\n3. 宿舍号\n4. 电话\n5. 成绩\n6. 完成修改\n";
cout << "输入选项:";
string op;
cin >> op;
if (checkExit(op)) {
cout << "已退出修改\n";
return;
}
int choice = atoi(op.c_str());
string newValue;
int newScore;
bool isDigit;
switch (choice) {
case 1: // 修改姓名
cout << "请输入新姓名:";
cin >> newValue;
strcpy(info[targetIndex].stuName, newValue.c_str());
cout << "姓名修改成功!\n";
break;
case 2: // 修改性别
cout << "请输入新性别(男/女):";
cin >> newValue;
if (newValue != "男" && newValue != "女") {
cout << "性别只能是男/女,修改失败!\n";
break;
}
strcpy(info[targetIndex].sex, newValue.c_str());
cout << "性别修改成功!\n";
break;
case 3: // 修改宿舍号
cout << "请输入新宿舍号:";
cin >> newValue;
strcpy(info[targetIndex].domNum, newValue.c_str());
cout << "宿舍号修改成功!\n";
break;
case 4: // 修改电话
cout << "请输入新电话:";
cin >> newValue;
strcpy(info[targetIndex].tel, newValue.c_str());
cout << "电话修改成功!\n";
break;
case 5: // 修改成绩
cout << "请输入新成绩(0-100):";
cin >> newValue;
// 校验成绩合法性
isDigit = true;
for (int i = 0; i < newValue.size(); i++) {
if (!isdigit(newValue[i])) {
isDigit = false;
break;
}
}
newScore = atoi(newValue.c_str());
if (!isDigit || newScore < 0 || newScore > 100) {
cout << "成绩必须是0-100的数字,修改失败!\n";
break;
}
info[targetIndex].score = newScore;
cout << "成绩修改成功!\n";
break;
case 6:
cout << "修改完成,返回主菜单!\n";
return;
default:
cout << "无效选项,请重新输入!\n";
break;
}
}
}
void infoSort() {
int s;
cout << "请选择排序类型(1降序 2升序,输入#退出):\n";
cout << "1.按分数降序\n2.按分数升序\n";
string op;
cin >> op;
if (op == "#") { cout << "已退出排序\n"; return; }
s = atoi(op.c_str());
if (s == 1) sort(info.begin(), info.end(), cmp2);
else if (s == 2) sort(info.begin(), info.end(), cmp1);
}
void infoQuery() {
cout << "请选择查询类型(1学号 2姓名,输入#退出):\n";
cout << "1.按学号查询\n2.按姓名查询\n";
string op;
cin >> op;
if (op == "#") { cout << "已退出查询\n"; return; }
int s = atoi(op.c_str());
if (s == 1) {
string sno;
cout << "请输入学号(输入#退出):";
cin >> sno;
if (checkExit(sno)) { cout << "已退出查询\n"; return; }
bool ok = 0;
for (int i = 0; i < info.size(); i++) {
if (strcmp(info[i].stuNum, sno.c_str()) == 0) {
cout << "学号 姓名 性别 宿舍号 电话 成绩\n";
cout << info[i].stuNum << " " << info[i].stuName << " "
<< info[i].sex << " " << info[i].domNum << " "
<< info[i].tel << " " << info[i].score << endl;
cout << "查询成功\n";
ok = 1;
break;
}
}
if (!ok) cout << "未查询到此学生\n";
} else if (s == 2) {
string sName;
cout << "请输入姓名(输入#退出):";
cin >> sName;
if (checkExit(sName)) { cout << "已退出查询\n"; return; }
bool ok = 0;
for (int i = 0; i < info.size(); i++) {
if (strcmp(info[i].stuName, sName.c_str()) == 0) {
cout << "学号 姓名 性别 宿舍号 电话 成绩\n";
cout << info[i].stuNum << " " << info[i].stuName << " "
<< info[i].sex << " " << info[i].domNum << " "
<< info[i].tel << " " << info[i].score << endl;
cout << "查询成功\n";
ok = 1;
break;
}
}
if (!ok) cout << "未查询到此学生\n";
}
}
void fileInput() {
char file[100];
cout << "请输入数据路径(输入#退出):\n";
cin >> file;
if (strcmp(file, "#") == 0) { cout << "已退出文件导入\n"; return; }
FILE *fp = fopen(file, "r");
if (!fp) {
cout << "路径错误或文件不存在\n";
return;
}
char stuNum[10], stuName[10], sex[10], domNum[10], tel[10];
int score;
int cnt = 0;
while (fscanf(fp, "%s %s %s %s %s %d",
stuNum, stuName, sex, domNum, tel, &score) != EOF) {
if (score < 0 || score > 100) continue;
if (strcmp(sex, "男") != 0 && strcmp(sex, "女") != 0) continue;
node n;
strcpy(n.stuNum, stuNum);
strcpy(n.stuName, stuName);
strcpy(n.sex, sex);
strcpy(n.domNum, domNum);
strcpy(n.tel, tel);
n.score = score;
info.push_back(n);
cnt++;
}
countNum += cnt;
fclose(fp);
cout << "导入成功,共 " << cnt << " 条\n";
}
void infoOutput() {
cout << "序号 学号 姓名 性别 宿舍号 电话 成绩\n";
for (int i = 0; i < info.size(); i++) {
cout << i + 1 << " " << info[i].stuNum << " " << info[i].stuName
<< " " << info[i].sex << " " << info[i].domNum
<< " " << info[i].tel << " " << info[i].score << endl;
}
cout << "共计 " << countNum << " 人\n";
}
int main() {
showMenu();
int a;
while (cin >> a) {
switch (a) {
case 1: infoInput(); break;
case 2: fileInput(); break;
case 3: infoSort(); break;
case 4: infoOutput(); break;
case 5: infoQuery(); break;
case 6: infoModify(); break;
case 7: return 0;
default: break;
}
showMenu();
}
return 0;
}


(6)总结:难点、花时间比较久的、逆向软件工程的一些思考
在这个实验过程中,更侧重于代码健壮性,修改了一些低级错误,以及自身使用时切身体会到的不方便的地方,感觉就是卡手。
在投递给AI后发现,可以改进的地方还有很多,比如
改用std::string替代字符数组,消除内存安全风险。
问题:cmp1/cmp2返回int不符合 C++ 排序规则(应返回bool),且未使用 lambda 表达式简化代码。优化方案:修正返回值类型,排序时直接使用 lambda 表达式,省去全局比较函数。
问题:无信息删除功能;
查询姓名时仅匹配完全一致,未支持模糊查询;
无数据持久化(修改 / 新增后未保存到文件)
既然考虑到了健壮性,考虑到了对分数,性别进行限制,那是不是应该再对像学号等属性进行格式限制
还譬如表现形式能不能再美化一点点等。
就是实验过程中考虑到的很浅,没有想到怎么还有那么多需要改进的地方,受限于自身学识浅薄,确实没能优化太多

浙公网安备 33010602011771号