第一周实验

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

image

屏幕截图 2026-03-10 142055

点击查看代码
#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;
}
(3)主要问题列表,针对问题的改善或者重构思路
  1. 当我进行某项动作,比如输入学号,但我不想进行该动作了,想中途退出了怎么办

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;
}
(5)重构的软件的测试截图

屏幕截图 2026-03-10 172528

屏幕截图 2026-03-10 172943

(6)总结:难点、花时间比较久的、逆向软件工程的一些思考

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

posted @ 2026-03-10 17:40  2452923崔骐  阅读(14)  评论(0)    收藏  举报