当前位置: 首页 > news >正文

班级管理系统

         1.前言

        这个是我与一位朋友一块协作写的一个简答的系统,以下是对这个系统进行详细的介绍:

设计一个班级管理系统,能够实现以下功能:数据导入及显示,新记录输入,删除记录,成绩查询,成绩修改( 要求先输入密码),成绩排序 (可按单科排序或按平均分排序),成绩保存,成绩统计,退出系统。

         注意:这个只是做的一个小小的系统,有些功能不是很完整,请谅解!

        2.导入的2个文件

        导入的第一个文件:stu.txt,里面的内容为:

        101 Zhang 85.50 92.00 78.50
        102 LiSi 90.00 85.00 93.00
        103 WangWu 76.50 82.00 88.50
        104 liut 100.00 100.00 100.00
        105 tom 100.00 45.00 90.00
        106 Jack 100.00 45.00 90.00
        107 milan 100.00 45.00 90.00
        108 smith 100.00 45.00 90.00
        109 lan 100.00 89.00 90.00
        110 ert 100.00 46.00 90.00
        111 nigetr 100.00 47.00 90.00
        112 tyyy 100.00 48.00 90.00

      导入的第二个文件:stu1.txt,里面的内容为:

        101 Zhang 85.50 92.00 78.50
        102 LiSi 100.00 100.00 100.00
        103 WangWu 76.50 82.00 88.50
        104 liut 100.00 100.00 100.00
        105 tom 100.00 45.00 90.00
        106 Jack 100.00 45.00 90.00
        107 milan 100.00 45.00 90.00
        108 smith 100.00 45.00 90.00
        109 lan 100.00 89.00 90.00
        110 ert 100.00 46.00 90.00
        111 nigetr 100.00 47.00 90.00
        112 tyyy 100.00 48.00 90.00
        113 Zhang1 85.50 92.00 78.50

3.代码内容

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <cstring>
#include <stdbool.h>
#include <ctype.h>
#include <string>
#include <limits> #define START 0
#define END 100
#define PASSWORD "123456"// 定义学生结构体
typedef struct Student {int id;char name[50];float grades[3];float singleSubjectGrade; // 单科成绩成员变量float average; struct Student *next;
} Student;// 全局变量,指向链表头节点
Student *head = NULL;// 函数声明
void importData();              // a.数据导入 
void displayRecords();           // i.成绩展示 
void addRecord();               // b.新纪录输入 
void deleteRecord();            // c.删除记录
void searchGrades();            // d.成绩查询 
void modifyGrades();            // e.成绩修改(需密码验证)
void sortGrades();              // f.按单科或平均分排序
void statistics();              // g.统计成绩数据(如平均分、最高分等)
void saveData();                // h.将链表数据保存到文件
void freeList();                // j.释放链表内存,防止内存泄漏//主函数 
int main() {char choice;do {printf("\n系统功能选项:\n");printf("a、 数据导入\n");printf("b、 新记录输入\n");printf("c、 删除记录\n");printf("d、 成绩查询\n");printf("e、 成绩修改(要求先输入密码)\n");printf("f、 成绩排序(可按单科排序或按平均分排序)\n");printf("g、 成绩统计\n");printf("h、 成绩保存\n");printf("i、 成绩展示\n");printf("j、 退出系统\n");printf("提示:\n   (如果输入多个字符,默认只会读取输入的第一个字符)\n");printf("请输入选项: ");std::cin >> choice;std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');switch (choice) {case 'a':importData();break;case 'b':addRecord();break;case 'c':deleteRecord();break;case 'd':searchGrades();break;case 'e':modifyGrades();break;case 'f':sortGrades();break;case 'g':statistics();break;case 'h':saveData();break;case 'i':displayRecords();break;case 'j':freeList();printf("谢谢使用!");return 0;default:printf("无效的选项,请重新输入");}} while (true);return 0;
}// a.数据导入 
void importData() {FILE *file;  char filename[50]; // 用户输入的文件名 char line[100]; // 缓冲区int id; // 用户输入的id char name[50]; float grade1, grade2, grade3; // 成绩 // 循环提示用户输入文件名,直到输入正确while (true) {printf("请输入要导入的文件名: ");scanf("%s", filename);// 尝试打开文件file = fopen(filename, "r"); // 只读方式打开文件并返回一个指向该文件的指针if (file == NULL) {printf("无法打开文件 %s,请重新输入\n", filename);} else {break; }}//查重 // 读取文件内容并逐行解析while (fgets(line, sizeof(line), file)) { // 从file指向的文件读入长度为sizeof(line)的字符串,并将其存储在line缓冲区中// 使用 scanf 函数从字符串 line 中按照指定的格式 %d %s %f %f %f 解析数据,并将解析结果存储到对应的变量 id、name、grade1、grade2 和 grade3 中。if (sscanf(line, "%d %s %f %f %f", &id, name, &grade1, &grade2, &grade3) == 5) {// 检查学号是否已存在// 定义一个指向学生结构体的指针current,并初始化为链表头指针headStudent *current = head;// 定义一个布尔变量idExists,用于标记学号是否已存在,初始值为falsebool idExists = false;// 遍历链表,直到current指针为NULL(即到达链表末尾)while (current != NULL) {// 如果当前节点的学生学号与解析出的学号相等if (current->id == id) {// 将idExists设置为true,表示学号已存在idExists = true;// 跳出循环,因为已经找到了重复的学号break;}// 将current指针移动到链表的下一个节点current = current->next;}// 如果学号已存在if (idExists) {printf("警告:学号 %d 已存在,跳过该记录。\n", id);continue; // 跳过重复学号的记录}
//添加新的学生信息 // 创建新的学生节点Student *newStudent = (Student*)malloc(sizeof(Student));if (newStudent == NULL) {printf("内存分配失败\n");return;}// 填充学生信息newStudent->id = id;strcpy(newStudent->name, name);newStudent->grades[0] = grade1;newStudent->grades[1] = grade2;newStudent->grades[2] = grade3;newStudent->next = NULL;// 将学生节点插入链表if (head == NULL) {// 链表为空,新节点即为头节点head = newStudent;} else {// 找到链表尾部并插入新节点Student *current = head;while (current->next != NULL) {current = current->next;}current->next = newStudent;}} else {printf("文件格式错误,跳过该行: %s", line);}}printf("数据导入成功\n");// 关闭文件fclose(file);
}// i.成绩展示 
void displayRecords() {// 检查链表是否为空if (head == NULL) {printf("没有记录可供显示。\n");return;}printf("学生记录列表:\n");printf("学号\t姓名\t成绩1\t成绩2\t成绩3\n");// 遍历链表,输出每个学生的信息Student *current = head;// 定义一个变量previous_id用于存储上一个学生的学号,初始化可设为一个默认值int previous_id = -1;  // 记录上一个学生的学号,默认为-1while (current != NULL) {// 如果当前学生的学号和之前的学生学号不同,则输出该学生信息if (current->id != previous_id) {printf("%d\t%s\t%.2f\t%.2f\t%.2f\n", current->id, current->name, current->grades[0], current->grades[1], current->grades[2]);}// 更新previous_id为当前学生的学号,以便下次比较previous_id = current->id; // 将current指针移动到链表的下一个节点current = current->next;}
}// 新记录输入
void addRecord() {if (head == NULL) {printf("请先进行数据的导入(a)");return;}int id;char name[50];float grade1, grade2, grade3;char temp[100]; // 用于接收学号的字符串输入// 输入新学生的学号printf("请输入学生的学号: ");scanf("%s", temp);// 检查学号是否为纯数字且在int类型范围内for (int i = 0; temp[i] != '\0'; i++) {if (temp[i] < '0' || temp[i] > '9') {printf("学号必须为纯数字,请重新输入学生的学号: ");scanf("%s", temp);continue;}}id = atoi(temp); // 将字符串转换为整数// 检查学号是否已经存在于链表中Student *current = head;while (current != NULL) {if (current->id == id) {printf("学号已经存在,插入失败。\n");return;}current = current->next;}printf("请输入学生的姓名: ");scanf("%s", name);printf("请输入学生的三门成绩(用空格分隔),成绩请在%d~%d范围内: ", START, END);while (scanf("%f %f %f", &grade1, &grade2, &grade3) != 3) {printf("成绩输入格式错误,请重新输入学生的三门成绩(用空格分隔): ");while (getchar() != '\n');  // 清除输入缓冲区}// 进行判断输入的成绩是否符合标准while (true) {if (grade1 > 100 || grade1 < 0) {printf("你输入第一门成绩超过指定范围,请检查\n");}if (grade2 > 100 || grade2 < 0) {printf("你输入第二门成绩超过指定范围,请检查\n");}if (grade3 > 100 || grade3 < 0) {printf("你输入第三门成绩超过指定范围,请检查\n");}if ((grade1 <= 100 && grade1 >= 0) && (grade2 <= 100 && grade2 >= 0) && (grade3 <= 100 && grade3 >= 0)) {break;}printf("请重新输入学生的三门成绩(用空格分隔)");while (scanf("%f %f %f", &grade1, &grade2, &grade3) != 3) {printf("成绩输入格式错误,请重新输入学生的三门成绩(用空格分隔): ");while (getchar() != '\n');  // 清除输入缓冲区}}// 创建新的学生节点Student *newStudent = (Student*)malloc(sizeof(Student));if (newStudent == NULL) {printf("内存分配失败\n");return;}// 填充学生信息newStudent->id = id;strcpy(newStudent->name, name);newStudent->grades[0] = grade1;newStudent->grades[1] = grade2;newStudent->grades[2] = grade3;newStudent->next = NULL;// 将学生节点插入链表if (head == NULL) {// 链表为空,新节点即为头节点head = newStudent;} else {// 找到链表尾部并插入新节点current = head;while (current->next != NULL) {current = current->next;}current->next = newStudent;}printf("学生记录添加成功。\n");
}// 删除记录
void deleteRecord() {int targetId; //要删除的学生的学号 Student *prev = NULL;  //辅助指针 Student *current = head; //流动指针 char temp[100]; // 用于接收学号的字符串输入// 检查链表是否为空if(head == NULL) {printf("请先进行数据的导入(a)");  return; }// 输入要删除的学生学号printf("请输入要删除的学生学号: ");scanf("%s", temp);// 检查学号是否为纯数字且在int类型范围内for (int i = 0; temp[i] != '\0'; i++) {if (temp[i] < '0' || temp[i] > '9') {printf("学号必须为纯数字,请重新输入要删除的学生的学号: ");scanf("%s", temp);continue;}}targetId = atoi(temp); // 将字符串转换为整数// 在链表中查找要删除的学生节点while (current != NULL && current->id != targetId) {prev = current;current = current->next;}// 如果找到了目标节点,则删除它if (current != NULL) {// 如果目标节点是头节点if (prev == NULL) {head = current->next;} else {prev->next = current->next;}// 释放目标节点的内存空间free(current);printf("学生记录删除成功。\n");} else {printf("未找到要删除的学生记录。\n");}
}// 成绩查询
void searchGrades() {int targetId; //要查询的学生的学号 char temp[100]; // 用于接收学号的字符串输入// 检查链表是否为空if(head == NULL) {printf("请先进行数据的导入(a)"); return;}// 输入要删除的学生学号printf("请输入要查询成绩的学生学号: ");scanf("%s", temp);// 检查学号是否为纯数字且在int类型范围内for (int i = 0; temp[i] != '\0'; i++) {if (temp[i] < '0' || temp[i] > '9') {printf("学号格式错误,必须是大于0的纯数字,请重新输入要查询的学生的学号: ");scanf("%s", temp);continue;}}targetId = atoi(temp); // 将字符串转换为整数// 在链表中查找要查询成绩的学生节点Student *current = head;while (current != NULL && current->id != targetId) {current = current->next;}// 如果找到了目标节点,则输出其成绩if (current != NULL) {printf("学生 %s 的成绩为: %.2f %.2f %.2f\n", current->name, current->grades[0], current->grades[1], current->grades[2]);} else {printf("未找到学号为 %d 的学生记录。\n", targetId);}
}// 成绩修改
void modifyGrades() {int targetId; //要进行修改的学生的学号 char password[20]; //密码 char temp[100]; // 用于接收学号的字符串输入// 检查链表是否为空if(head == NULL) {printf("请先进行数据的导入(a)"); return;}// 输入要修改的学生学号printf("请输入要修改成绩的学生学号: ");scanf("%s", temp);// 检查学号是否为纯数字且在int类型范围内for (int i = 0; temp[i] != '\0'; i++) {if (temp[i] < '0' || temp[i] > '9') {printf("学号必须为纯数字,请重新输入要修改的学生的学号: ");scanf("%s", temp);continue;}}targetId = atoi(temp); // 将字符串转换为整数// 在链表中查找要修改成绩的学生节点Student *current = head;while (current != NULL && current->id != targetId) {current = current->next;}// 如果找到了目标节点,则进行成绩修改if (current != NULL) {// 输入密码进行验证,只有密码为123456时才能访问int attempts = 3; // 设置尝试次数上限while (attempts > 0) {printf("请输入密码进行验证: ");scanf("%s", password);if (strcmp(password, PASSWORD) == 0) {printf("密码验证通过。\n");break; // 密码正确,跳出循环} else {attempts--;if (attempts > 0) {printf("密码错误,请重新输入。您还有%d次尝试机会。\n", attempts);} else {printf("密码错误次数过多,操作被锁定。\n");return; // 密码错误次数过多,退出函数}}}// 输入新的成绩float newGrades[3];char buffer[100]; // 用于接收用户输入的字符串while (true) {printf("请输入新的三门成绩(用空格分隔): ");//getchar(); //清除缓存 fflush(stdin); // 清除输入缓冲区中的回车符fgets(buffer, sizeof(buffer), stdin);int valid = 1;int result = sscanf(buffer, "%f %f %f", &newGrades[0], &newGrades[1], &newGrades[2]);if (result == 3) {for (int i = 0; i < 3; i++) {if (newGrades[i] < 0 || newGrades[i] > 100) {valid = 0;printf("第%d门成绩必须在1到100之间,请重新输入\n", i + 1);break;}}if (valid) {break;}} else {printf("输入格式错误,请按照 '成绩1 成绩2 成绩3' 的格式输入\n");}}// 更新学生节点的成绩信息current->grades[0] = newGrades[0];current->grades[1] = newGrades[1];current->grades[2] = newGrades[2];printf("学生 %s 的成绩已成功修改。\n", current->name);} else {printf("输入的学号不存在,请检查");return;}}// 成绩排序
void sortGrades() {//判断是否为空 if(head == NULL) {printf("请先进行数据的导入(a)"); return;}char choice[10];//用户选择 while (1) {printf("请选择排序方式:\n");printf("a、 按照单科成绩排序\n");printf("b、 按照平均分排序\n");printf("请选择选项: ");fgets(choice, sizeof(choice), stdin);choice[strcspn(choice, "\n")] = '\0';  // 移除末尾的换行符if (strlen(choice) == 1 && (choice[0] == 'a' || choice[0] == 'b')) {break;  // 用户输入了正确的选项,退出循环} else {printf("无效的选项,请重新输入。\n");}}//方法声明 Student* sortBySubject();Student* sortByAverage();void printList(Student *head);switch (choice[0]) {case 'a':// 调用排序方法,获取排序后的新链表Student *sortedBySubject;sortedBySubject = sortBySubject();// 遍历输出排序后的链表printf("按照单科成绩排序后的结果:\n");printList(sortedBySubject);break;case 'b':// 调用排序方法,获取排序后的新链表Student *sortedByAverage;sortedByAverage = sortByAverage();// 遍历输出排序后的链表printf("按照平均分排序后的结果:\n");printList(sortedByAverage);break;default:printf("无效的选项,请重新输入。\n");}
}// 按照单科成绩排序,并将排序结果存储在新链表中
Student* sortBySubject() {int subject; //要排序地学科 printf("请选择排序的科目(1代表第一科,2代表第二科,3代表第三科): ");scanf("%d", &subject);if (subject < 1 || subject > 3) {printf("无效的科目编号\n");return NULL;}// 创建新链表的头节点Student *newHead = NULL; //新链表头节点 Student *current, *next; //遍历指针 // 复制链表节点到新链表,并按照单科成绩排序for (current = head; current != NULL; current = current->next) {Student *newStudent = (Student *)malloc(sizeof(Student)); //新创建学生节点 if (newStudent == NULL) {printf("内存分配失败\n");return NULL;}//链表复制 newStudent->id = current->id;strcpy(newStudent->name, current->name);for (int i = 0; i < 3; i++) {newStudent->grades[i] = current->grades[i];}// 计算平均分并存储newStudent->average = (newStudent->grades[0] + newStudent->grades[1] + newStudent->grades[2]) / 3;// 插入排序[头插法]Student *prev = NULL; //指向前一个节点 if (newHead == NULL || newHead->grades[subject - 1] > newStudent->grades[subject - 1]) {newStudent->next = newHead;newHead = newStudent;} else {Student *temp = newHead; //临时指针 while (temp != NULL && temp->grades[subject - 1] <= newStudent->grades[subject - 1]) {prev = temp;temp = temp->next;}newStudent->next = temp;prev->next = newStudent;}}printf("按照单科成绩排序完成\n");return newHead; // 返回新链表的头节点
}// 按照平均分排序,并将排序结果存储在新链表中
Student* sortByAverage() {// 1. 计算每个学生的平均分Student *current = head;int count = 0;// 先统计学生数量while (current != NULL) {count++;current = current->next;}// 创建结构体数组存储学生指针和平均分struct StudentInfo {Student *student;float average;} *students = (struct StudentInfo*)malloc(count * sizeof(struct StudentInfo));if (students == NULL) {printf("内存分配失败\n");return NULL;}// 计算平均分并填充数组current = head;for (int i = 0; i < count; i++) {float sum = current->grades[0] + current->grades[1] + current->grades[2];//将当前学生指针和计算出的平均分存入students数组 students[i].student = current;students[i].average = sum / 3;current = current->next;}// 2. 使用冒泡排序按平均分降序排列//外层循环控制排序轮数,内层循环比较相邻元素:for (int i = 0; i < count - 1; i++) {for (int j = 0; j < count - i - 1; j++) {if (students[j].average < students[j+1].average) {// 交换两个元素struct StudentInfo temp = students[j];students[j] = students[j+1];students[j+1] = temp;}}}// 3. 构建新链表(已按平均分降序)Student *newHead = NULL;for (int i = 0; i < count; i++) {Student *newNode = (Student*)malloc(sizeof(Student));if (newNode == NULL) {printf("内存分配失败\n");free(students);return NULL;}// 复制学生数据*newNode = *(students[i].student); // 直接复制整个结构体newNode->average = students[i].average;  // 确保平均分也被复制newNode->next = newHead;newHead = newNode;}free(students); // 释放临时数组printf("按照平均分排序完成\n");return newHead;
}// 遍历输出链表
void printList(Student *head) {printf("学生信息:\n");Student *current = head;while (current != NULL) {printf("学号:%d, 姓名:%s, 科目1成绩:%0.2f, 科目2成绩:%0.2f, 科目3成绩:%0.2f\n, 平均分:%.2f\n",current->id, current->name, current->grades[0], current->grades[1], current->grades[2],current->average);current = current->next;}
}// 统计每门课程成绩最高的学生、每门课程的平均成绩、超过某门课程平均成绩的学生人数
void statistics() {//判断是否为空 if(head == NULL) {printf("请先进行数据的导入(a)"); return;}int numCourses = 3; // 假设有3门课程float totalGrades[numCourses]; // 每门课程的总成绩float highestGrade[numCourses]; // 每门课程的最高成绩int numStudentsAboveAvg[numCourses]; // 超过某门课程平均成绩的学生人数int numStudents = 0; // 学生数量// 初始化统计数据for (int i = 0; i < numCourses; i++) {totalGrades[i] = 0.0;highestGrade[i] = 0.0;numStudentsAboveAvg[i] = 0;}// 遍历链表,计算每门课程的总成绩和最高成绩,同时统计学生数量Student *current = head;while (current != NULL) {numStudents++; // 统计学生数量for (int i = 0; i < numCourses; i++) {totalGrades[i] += current->grades[i];if (current->grades[i] > highestGrade[i]) {highestGrade[i] = current->grades[i];}}current = current->next;}// 计算每门课程的平均成绩float avgGrades[numCourses];for (int i = 0; i < numCourses; i++) {avgGrades[i] = totalGrades[i] / numStudents; // 使用学生数量计算平均成绩}// 再次遍历链表,统计超过某门课程平均成绩的学生人数current = head;while (current != NULL) {for (int i = 0; i < numCourses; i++) {if (current->grades[i] > avgGrades[i]) {numStudentsAboveAvg[i]++;}}current = current->next;}// 输出统计结果printf("每门课程成绩最高的学生:\n");for (int i = 0; i < numCourses; i++) {printf("课程 %d 的最高成绩为: %.2f\n", i + 1, highestGrade[i]);}printf("\n每门课程的平均成绩:\n");for (int i = 0; i < numCourses; i++) {printf("课程 %d 的平均成绩为: %.2f\n", i + 1, avgGrades[i]);}printf("\n超过某门课程平均成绩的学生人数:\n");for (int i = 0; i < numCourses; i++) {printf("超过课程 %d 平均成绩的学生人数为: %d\n", i + 1, numStudentsAboveAvg[i]);}
}//数据保存 
void saveData() {if(head == NULL) {printf("请先进行数据的导入(a)"); return;}FILE *file;char filename[50];// 询问用户输入文件名,直到输入的文件名以“.txt”结尾为止do {printf("请输入要保存的文件名: ");scanf("%s", filename);// 检查文件名是否以“.txt”结尾,如果不是则提示用户重新输入
//        检查文件名长度是否小于4个字符||检查文件名最后4个字符是不是 .txtif (strlen(filename) < 4 || strcmp(filename + strlen(filename) - 4, ".txt") != 0) {printf("文件名必须以“.txt”结尾,请重新输入\n");}} while (strlen(filename) < 4 || strcmp(filename + strlen(filename) - 4, ".txt") != 0);// 尝试打开文件,以读写模式打开文件,会清空原有数据并覆盖文件
//    清空文件:如果文件已存在,所有原有内容会被删除
//新建文件:如果文件不存在,会自动创建新文件file = fopen(filename, "w+");if (file == NULL) {printf("无法打开文件 %s\n", filename);return;}// 遍历链表,将每个节点的信息写入文件Student *current = head;while (current != NULL) {// 将学生信息写入文件fprintf(file, "%d %s %.2f %.2f %.2f\n", current->id, current->name, current->grades[0], current->grades[1], current->grades[2]);// 移动到下一个节点current = current->next;}printf("数据保存成功\n");// 关闭文件fclose(file);
}// 释放链表内存
void freeList() {// 遍历链表,释放每个节点的内存空间while (head != NULL) {// 保存当前节点的指针
//        直接free(head),就无法访问head->next来继续遍历Student *temp = head;// 将头指针指向下一个节点head = head->next;// 释放当前节点的内存空间free(temp);}printf("链表内存释放完成\n");
}

4.可拓展的功能:

正常的增删改查之后,进行文件保存是可以保存的,但是排序之后的保存并不能成功在磁盘保存,需要再进行改进。

5.演示的过程

        6.感受

              对于做这个的感受,是对我这个编程小白是个很大的挑战,里面用的最多的是链表的东西,然后需要做出各种判断,比如说在导入这个文件之前,其他操作是不可以进行的,因为链表还是空的,又比如说输入的学号需要做判断,是否为纯数字或在int范围前,查重也是一个很常见也很必要的功能,里面的排序用到一些常见的算法:冒泡排序,头插法,尾插法......,是一个很好的锻炼。

http://www.xdnf.cn/news/693307.html

相关文章:

  • Python+Flask+Html做一个简单的测试联调工具
  • 链路追踪神器zipkin安装详细教程教程
  • C语言中:递归问题的深入研究
  • mp中的密码处理
  • 数据分析的方法总结
  • 工业控制核心引擎高性能MCU——MM32F5370
  • 【教程】服务器如何防止GET/SYN洪泛攻击
  • C++ 模板元编程语法大全
  • 如何在使用kickstart安装物理机操作系统的过程中核对服务器的SN
  • Docker容器启动失败的常见原因分析
  • 每日C++ 5.28dddd
  • FreeCAD如何对器件表面逐面着色
  • 单点登陆(SSO)简介-笔记
  • style scoped作用域
  • RabbitMQ性能调优:关键技术、技巧与最佳实践
  • Vert.x学习笔记-什么是Context
  • Linux `less` 命令深度解析与高阶应用指南
  • python网络编程之socket
  • 面试高频图论题『墙与门』:Swift BFS 解法全流程拆解
  • node_modules\node-sass: Command failed.报错了
  • DeepSeek 赋能教育新生态,智能教育机器人开启智慧教学新篇章
  • RuoYi前后端分离框架将前端dist资源集成到Jar包中独立部署
  • 考研系列-操作系统:第二章、进程与线程
  • Java垃圾回收器全面解析:原理、参数、对比与实战调优
  • 用QT写一个车速表
  • 台式电脑CPU天梯图_2025年台式电脑CPU天梯图
  • PortSwigger-03-点击劫持
  • ASP.NET Core OData 实践——Lesson6使用Action(C#)
  • 扩展摩尔投票法:找出出现次数超过 n/3 的元素
  • 《汇编语言》第11章 标志寄存器