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,并初始化为链表头指针head
Student *current = head;
// 定义一个布尔变量idExists,用于标记学号是否已存在,初始值为false
bool 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; // 记录上一个学生的学号,默认为-1
while (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个字符是不是 .txt
if (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范围前,查重也是一个很常见也很必要的功能,里面的排序用到一些常见的算法:冒泡排序,头插法,尾插法......,是一个很好的锻炼。