逆向软件开发--学生管理系统

news/2025/2/27 13:10:03/文章来源:https://www.cnblogs.com/hailiZhou/p/18740061

本次实验目的:训练逆向软件设计与开发能力。

实验内容:找一个已有的项目,阅读分析,找出软件尚存的缺陷,改进其软件做二次开发,并将过程整理成博客。

来源:CSDN上的学生管理系统
链接:
https://blog.csdn.net/weixin_74362817/article/details/142308755fromshare=blogdetail&sharetype=blogdetail&sharerId=142308755&sharerefer=PC&sharesource=&sharefrom=from_link

代码:

点击查看代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 定义常量
#define MAX_STUDENTS 100   // 最大学生数量
#define NAME_LENGTH 50     // 姓名最大长度
#define MAJOR_LENGTH 30    // 专业名称最大长度// 定义学生结构体
typedef struct {int id;                   // 学号char name[NAME_LENGTH];   // 姓名char gender;              // 性别int age;                  // 年龄char major[MAJOR_LENGTH]; // 专业
} Student;// 全局变量
Student students[MAX_STUDENTS]; // 学生数组
int student_count = 0;          // 当前学生计数// 函数声明
void add_student();     // 添加学生
void delete_student();  // 删除学生
void modify_student();  // 修改学生信息
void query_student();   // 查询学生信息
void load_data();       // 加载学生数据
void save_data();       // 保存学生数据
void display_students();// 显示所有学生信息int main() {load_data();   // 加载已有的学生数据int choice;// 主菜单循环do {printf("\n学生管理系统\n");printf("1. 添加学生\n");printf("2. 删除学生\n");printf("3. 修改学生\n");printf("4. 查询学生\n");printf("5. 保存数据\n");printf("6. 退出\n");printf("请输入您的选择: ");scanf("%d", &choice);// 根据用户选择执行相应操作switch (choice) {case 1: add_student(); break;case 2: delete_student(); break;case 3: modify_student(); break;case 4: query_student(); break;case 5: save_data(); break;case 6: printf("退出系统。\n"); break;default: printf("无效选择,请重试。\n");}} while (choice != 6); // 当选择6时退出return 0;
}// 添加学生
void add_student() {// 检查是否达到最大学生数量if (student_count >= MAX_STUDENTS) {printf("学生数量已满,无法添加更多学生。\n");return;}// 创建新的学生结构体并输入信息Student new_student;printf("请输入学号: ");scanf("%d", &new_student.id);printf("请输入姓名: ");scanf("%s", new_student.name);printf("请输入性别 (M/F): ");scanf(" %c", &new_student.gender);printf("请输入年龄: ");scanf("%d", &new_student.age);printf("请输入专业: ");scanf("%s", new_student.major);// 将新学生添加到数组并增加计数students[student_count++] = new_student;printf("学生信息已添加。\n");
}// 删除学生
void delete_student() {int id;printf("请输入要删除的学号: ");scanf("%d", &id);// 查找并删除匹配学号的学生for (int i = 0; i < student_count; i++) {if (students[i].id == id) {// 移动后续学生位置for (int j = i; j < student_count - 1; j++) {students[j] = students[j + 1];}student_count--; // 减少学生计数printf("学生信息已删除。\n");return;}}printf("未找到学号为 %d 的学生。\n", id);
}// 修改学生
void modify_student() {int id;printf("请输入要修改的学号: ");scanf("%d", &id);// 查找并修改匹配学号的学生信息for (int i = 0; i < student_count; i++) {if (students[i].id == id) {printf("当前信息: 姓名: %s, 性别: %c, 年龄: %d, 专业: %s\n",students[i].name, students[i].gender, students[i].age, students[i].major);printf("请输入新姓名: ");scanf("%s", students[i].name);printf("请输入新性别 (M/F): ");scanf(" %c", &students[i].gender);printf("请输入新年龄: ");scanf("%d", &students[i].age);printf("请输入新专业: ");scanf("%s", students[i].major);printf("学生信息已修改。\n");return;}}printf("未找到学号为 %d 的学生。\n", id);
}// 查询学生
void query_student() {int id;printf("请输入要查询的学号 (0 列出所有学生): ");scanf("%d", &id);// 如果输入0则显示所有学生if (id == 0) {display_students();} else {// 查找并显示匹配学号的学生信息for (int i = 0; i < student_count; i++) {if (students[i].id == id) {printf("学号: %d, 姓名: %s, 性别: %c, 年龄: %d, 专业: %s\n",students[i].id, students[i].name, students[i].gender, students[i].age, students[i].major);return;}}printf("未找到学号为 %d 的学生。\n", id);}
}// 显示所有学生
void display_students() {// 检查是否有学生信息if (student_count == 0) {printf("无学生信息。\n");return;}// 逐个打印学生信息printf("学生信息列表:\n");for (int i = 0; i < student_count; i++) {printf("学号: %d, 姓名: %s, 性别: %c, 年龄: %d, 专业: %s\n",students[i].id, students[i].name, students[i].gender, students[i].age, students[i].major);}
}// 加载数据
void load_data() {// 打开文件读取学生信息FILE *file = fopen("students.txt", "r");if (file == NULL) {printf("未找到学生数据文件,使用空数据。\n");return;}// 读取文件内容并存储到学生数组while (fscanf(file, "%d %s %c %d %s", &students[student_count].id,students[student_count].name, &students[student_count].gender,&students[student_count].age, students[student_count].major) != EOF) {student_count++;}fclose(file); // 关闭文件
}// 保存数据
void save_data() {// 打开文件保存学生信息FILE *file = fopen("students.txt", "w");if (file == NULL) {printf("无法打开文件保存数据。\n");return;}// 将学生信息写入文件for (int i = 0; i < student_count; i++) {fprintf(file, "%d %s %c %d %s\n", students[i].id, students[i].name,students[i].gender, students[i].age, students[i].major);}fclose(file); // 关闭文件printf("学生信息已保存。\n");
}

一、在原有系统上进行分析
数据结构:代码中定义了一个Student结构体,用于存储学生的基本信息(学号、姓名、性别、年龄、专业)。
全局变量:students数组用于存储所有学生信息,student_count用于记录当前学生数量。
功能模块:add_student:添加学生信息。
delete_student:删除学生信息。
modify_student:修改学生信息。
query_student:查询学生信息。
load_data:从文件加载学生数据。
save_data:将学生数据保存到文件。
display_students:显示所有学生信息。

二、系统的优缺点
优点:

  1. 功能完整,满足基本需求
    系统实现了学生信息管理的核心功能,包括添加、删除、修改、查询和显示学生信息,能够满足基本的使用场景。
    提供了数据的持久化功能(通过文件存储),确保数据在程序退出后不会丢失。
  2. 代码结构清晰
    系统采用模块化设计,将不同功能封装为独立的函数,便于理解和维护。
    代码逻辑简单直接,适合初学者学习和理解。

缺点问题:
1、缺乏数据验证
输入时没有对用户输入进行验证(如学号是否重复、性别是否合法等)。
2、代码存在的问题
代码中有此display_students(显示所有学生信息)函数,功能中却没有展示出来。

三、进行二次开发
1、在输入学生信息时增加验证逻辑,确保数据的合法性。
新代码:

点击查看代码
void add_student() {// 检查是否达到最大学生数量if (student_count >= MAX_STUDENTS) {printf("学生数量已满,无法添加更多学生。\n");return;}// 创建新的学生结构体并输入信息Student new_student;printf("请输入学号: ");while (scanf("%d", &new_student.id) != 1) {printf("无效输入,请输入一个整数: ");while (getchar() != '\n'); // 清除缓冲区}printf("请输入姓名: ");scanf("%s", new_student.name);printf("请输入性别 (M/F): ");while (scanf(" %c", &new_student.gender) != 1 || (new_student.gender != 'M' && new_student.gender != 'F')) {printf("无效输入,请输入 M 或 F: ");while (getchar() != '\n'); // 清除缓冲区}printf("请输入年龄: ");while (scanf("%d", &new_student.age) != 1 || new_student.age < 0) {printf("无效输入,请输入一个正整数: ");while (getchar() != '\n'); // 清除缓冲区}printf("请输入专业: ");scanf("%s", new_student.major);// 将新学生添加到数组并增加计数students[student_count++] = new_student;printf("学生信息已添加。\n");
}

2、在功能中补上显示所有学生信息功能。
新代码:

点击查看代码
do {printf("\n学生管理系统\n");printf("1. 添加学生\n");printf("2. 删除学生\n");printf("3. 修改学生\n");printf("4. 查询学生\n");printf("5. 保存数据\n");printf("6. 显示所有学生信息");printf("7. 退出\n");printf("请输入您的选择: ");scanf("%d", &choice);

重构软件测试截图:

四、总结
难点:
代码逻辑理解:原代码中包含多个功能函数,每个函数又有其特定的逻辑,如删除学生信息时需要将后续学生前移,这涉及到数组元素的移动操作,理解起来有一定难度。特别是对于没有相关编程经验的人来说,要理清每个函数的具体实现和调用关系需要花费较多时间。主函数中的菜单循环和 switch 语句的结合,通过用户输入的选择来调用不同的功能函数,逻辑较为复杂,需要仔细分析才能掌握整个程序的流程。
输入验证的实现:为了增强系统的健壮性,添加输入验证功能是必要的。但实现输入验证需要考虑各种可能的输入情况,如输入非整数、输入不符合要求的性别等。在处理输入验证时,需要使用循环和条件判断来确保用户输入的是合法数据,这增加了代码的复杂度。

花费时间较久的部分:输入验证功能的实现,实现输入验证时,需要考虑不同类型的输入错误,并进行相应的处理。例如,在输入学号、年龄等整数时,要确保用户输入的是有效的整数;在输入性别时,要确保用户输入的是 M 或 F。为了处理这些错误输入,需要使用循环和条件判断来不断提示用户重新输入,直到输入合法数据为止。这个过程需要进行多次测试和调试,以确保输入验证的准确性和可靠性。

思考:我知道了在逆向软件工程中代码分析的重要性,逆向软件工程的第一步是对已有代码进行理解和分析。只有深入理解代码的逻辑和结构,才能准确地把握系统的功能和实现细节,为后续的改进和扩展打下基础。在这个学生管理系统的逆向开发过程中,通过仔细阅读代码,我们能够理解每个功能函数的作用和相互之间的调用关系,从而更好地进行改进。在面对缺乏文档的旧系统时,逆向分析可揭示其架构、功能逻辑,为维护和升级提供依据。像对学生管理系统的逆向,能让开发者把握数据处理和功能实现细节,进行针对性优化。同时,逆向工程有助于代码复用,避免重复开发,节省时间和资源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/890596.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

对自己独立开发游戏的能力考察~来自入行4年的小菜鸟自查

一直想设计开发一款自己喜欢玩的游戏,加入各种自己想要的元素,但是总感觉自己技术积累不够,这次刚好有空,尝试写一下,看看自己在哪方面比较欠缺,这次主要是为了检测自己独立开发的能力,着重战斗方面的设计,ui是随便弄的,原谅原谅 首先是主场景大地图,实现了地图创建加…

掌握领域驱动微服务中的聚合与实体

—— 从遗留单体系统转型为现代分布式系统的实战经验照片由 Shamin Haky 提供,来自 Unsplash你好啊,我是一名经验丰富的软件工程师,专注于大规模应用的设计。多年来,我见过各种架构——从庞大的单体架构,到精细调整过的微服务基础设施。 有一个核心概念,一直帮助我保持系…

PyCharm安装插件时出现Error loading package list:Unexpected end of file from server

将Manage Repositories中无法用的源删掉即可 截图为只保留了一个可用的源

day02 ip地址和服务器

day02 服务器与机房 上节回顾运维是什么: 简单来说保证服务器的安全稳定的运行今日内容 服务器的基础的知识 ip地址的查看 windows查看IP的命令是 ipconfig关于局域网,NAT的概念公网,局域网的概念,以及路由器帮你做了网络地址的转换运维不象写代码,纯靠动脑,不断的写吗,…

至顶AI实验室DeepSeek完全实用手册V1.0 ——从技术原理到使用技巧

最近有很多小伙伴在问我们关于DeepSeek的原理、怎么部署、怎么用好各种五花八门的问题,于是至顶AI实验室整理了一份实用手册来一一解答。手册从发展脉络,到个人和企业使用部署方案,再到“DeepSeek+”使用技巧,对DeepSeek进行全方位解读,适合想用和用好DeepSeek的企业和个人…

第四章:简单逻辑门

简单逻辑门 复习第一章:需要一台计算机,在研究其组成的方向上进行努力 第二章:知道了计算机由输入设备、存储器、运算器和输出设备组成,这个体系目前还在沿用 第三章:了解了计算机使用二进制(0 和 1)表示所有数据TL;DR逻辑门是计算机处理二进制信号的基本单元 三个基础逻…

day02_ip地址和服务器

day02 服务器与机房 上节回顾运维是什么: 简单来说保证服务器的安全稳定的运行今日内容 服务器的基础的知识 ip地址的查看 windows查看IP的命令是 ipconfig关于局域网,NAT的概念公网,局域网的概念,以及路由器帮你做了网络地址的转换运维不象写代码,纯靠动脑,不断的写吗,…

中国国旗Python

import turtle 设置画布大小 turtle.setup(600, 400) 设置画笔速度 turtle.speed(10) 绘制红色背景 turtle.penup() turtle.goto(-300, 200) turtle.pendown() turtle.color("red") turtle.begin_fill() for _ in range(2): turtle.forward(600) turtle.right(90) tu…

Hyacinth:一款覆盖主流框架的反序列化漏洞利用神器

免责声明 本文旨在提供有关特定漏洞或安全风险的详细信息,以帮助安全研究人员、系统管理员和开发人员更好地理解和修复潜在的安全威胁,协助提高网络安全意识并推动技术进步,而非出于任何恶意目的。利用本文提到的漏洞信息或进行相关测试可能会违反法律法规或服务协议。作者不…

QtCreator IDE中向项目添加ui文件并绑定类

在 Qt Creator 中使用 Qt Designer 创建 UI 文件步骤一、添加ui文件到pro中鼠标移动到项目->右键->添加现有文件;找到要添加的xxxx.ui文件;点击打开按钮,完成xxxx.ui的添加。二、在项目pro文件中指定UI_DIR路径指定UI_DIR路径有两个目的:1.编译输出的xxxx_ui.h文件会…

Thinkphp6---workman开发聊天

最近DeepSeek很火,就结合workman开发一个聊天对话功能: 一、安装 think-worker和 think-viewcomposer require topthink/think-worker composer require topthink/think-view版本更新比较快,通过这个安装的 think-worker 是4.0的,但是需要 thinkphp是8.0的 可以安装3.0的:…