学生信息管理系统
基于动态链表的增、删、改、查和文件的存储,实现对学生信息(姓名、性别、年龄、学号、电话、语文、数学、英语)的管理
存储学生信息的文件:#define FILEPATH "information.txt"
学生基本信息结构体
//学生基本信息信息
struct Student {
int data;
char name[10]; //姓名
char sex[10]; //性别
int age; //年龄
int id; //学号
int tel; //电话
float Chinese; //语文
float Math; //数学
float English; //英语
};
存放学生信息的链表结点
//存入、查找、删除、修改、输出学生信息,学生信息包括姓名,性别,年龄,学号,电话,成绩;
typedef struct LNode {
struct Student stu; //结点存储学生信息
struct LNode *next; //保存下一节点的地址
}LNode, *LinkList;
对学生信息的基本操作函数
LinkList CreatNode(struct Student *pData); //创建一个链表结点
void AppendNode(LinkList *root, struct Student *pData); //添加一个结点到链表末尾
void Foreach(LinkList root); //遍历链表并输出
LinkList FindNodeByPos(LinkList root, int pos); //找到链表中第pos个结点
void DeleteNode(LinkList *root, int pos); //删除链表中第pos个结点
void DeleteList(LinkList *root); //删除整个链表
LinkList FindNodeById(LinkList root, int id); //找到链表中与id相同的结点
LinkList FindNodeByName(LinkList root, char *name); //找到链表中与naem相同的结点
void Print(LinkList root); //打印单个学生信息
void choose(); //功能选择函数
void menu(); //菜单函数
void AppendStudent(); //增
void DeleteStudent(); //删
void ChangeStudent(); //改
void SearchStudentById(); //查 --- 按ID
void SearchStudentByName(); //查 --- 按Name
void ShowAllStudent(); //输出函数
LinkList ReadFile(LinkList root, FILE *fp, struct Student temp); //读取文件内容
void WriteFile(LinkList root, FILE *fp); //更新文件内容
系统入口菜单函数实现
void menu() {
cout << endl << endl;
printf("\t 欢迎使用学生信息管理系统\n");
printf("\t\t1.查看所有学生信息\n");
printf("\t\t2.增加学生信息\n");
printf("\t\t3.删除学生信息\n");
printf("\t\t4.修改学生信息\n");
printf("\t\t5.按学号查询学生信息\n");
printf("\t\t6.按姓名查询学生信息\n");
printf("\t\t7.退出\n");
}
系统功能选择函数实现
用户根据菜单界面选择相应的功能并输入对应的序号调用对应的函数
void choose() {
int number; //功能编号
while (1) {
system("cls"); //清屏
menu();
cout << "请选择功能:";
cin >> number;
switch (number)
{
case 1:ShowAllStudent(); cout << "请按任意键继续"; getchar(); getchar(); break;
case 2:AppendStudent(); cout << "请按任意键继续"; getchar(); getchar(); break;
case 3:DeleteStudent(); cout << "请按任意键继续"; getchar(); getchar(); break;
case 4:ChangeStudent(); cout << "请按任意键继续"; getchar(); getchar(); break;
case 5:SearchStudentById(); cout << "请按任意键继续"; getchar(); getchar(); break;
case 6:SearchStudentByName(); cout << "请按任意键继续"; getchar(); getchar(); break;
default:cout << "Bye bye!" << endl; Sleep(3000); exit(1); break;
}
}
}
学生信息的插入操作
- 建立空链表
- 读取文件内容保存在链表中
- 新建链表结点,将新的学生信息保存在该结点,并将该结点插入到链表的末尾
- 将整个链表写回到文件中,更新文件的信息
- 最后销毁链表回收资源
void AppendStudent() {
LinkList pList = NULL; //链表
struct Student temp; //临时存储一个学生的信息
memset(&temp, 0x00, sizeof(struct Student));
FILE *fp = NULL; //文件指针
//读取文件内容
pList = ReadFile(pList, fp, temp);
cout << "请输入要插入学生的信息:" << endl;
cout << "学号:"; cin >> temp.id;
cout << "姓名:"; cin >> temp.name;
cout << "年龄:"; cin >> temp.age;
cout << "性别:"; cin >> temp.sex;
cout << "电话:"; cin >> temp.tel;
cout << "成绩:语文 数学 英语";
cin >> temp.Chinese >> temp.Math >> temp.English;
AppendNode(&pList, &temp); //把结点添加到链表末尾
//更新文件内容
WriteFile(pList, fp);
//删除整个链表
DeleteList(&pList);
}
学生信息的删除操作
- 建立空链表
- 读取文件内容保存在链表中
- 输入要删除学生的学号,并在链表中查找该结点是否存在,如果存在则在链表中删除该结点,
- 将整个链表写回到文件中,更新文件的信息
- 最后销毁链表回收资源
void DeleteStudent() {
LinkList pList = NULL; //链表
struct Student temp; //临时存储一个学生的信息
memset(&temp, 0x00, sizeof(struct Student));
FILE *fp = NULL; //文件指针
//读取文件内容
pList = ReadFile(pList, fp, temp);
cout << "请输入要删除学生的的学号:";
int id;
cin >> id;
LinkList node = FindNodeById(pList, id);
if (node && node->next) {
LinkList FNode = node->next;
node->next = FNode->next;
delete FNode;
//更新文件信息
WriteFile(pList, fp);
}
else {
cout << "输入的ID有误!" << endl;
}
//删除整个链表
DeleteList(&pList);
}
学生信息的修改操作
- 建立空链表
- 读取文件内容保存在链表中
- 输入要修改学生的学号,并在链表中查找该结点是否存在,如果存在则在链表中修改该结点的信息,
- 将整个链表写回到文件中,更新文件的信息
- 最后销毁链表回收资源
void ChangeStudent() {
LinkList pList = NULL; //链表
struct Student temp; //临时存储一个学生的信息
memset(&temp, 0x00, sizeof(struct Student));
FILE *fp = NULL; //文件指针
//读取文件内容
pList = ReadFile(pList, fp, temp);
cout << "请输入要修改学生的的学号:";
int id;
cin >> id;
LinkList node = FindNodeById(pList, id);
if (node && node->next) {
cout << "请输入要修改的学生信息:" << endl;
cout << "学号:"; cin >> node->next->stu.id;
cout << "姓名:"; cin >> node->next->stu.name;
cout << "年龄:"; cin >> node->next->stu.age;
cout << "性别:"; cin >> node->next->stu.sex;
cout << "电话:"; cin >> node->next->stu.tel;
cout << "成绩:语文 数学 英语";
cin >> node->stu.Chinese >> node->stu.Math >> node->stu.English;
//更新文件信息
WriteFile(pList, fp);
}
else {
cout << "输入的ID有误!" << endl;
}
//删除整个链表
DeleteList(&pList);
}
学生信息的查找操作
- 建立空链表
- 读取文件内容保存在链表中
- 输入要查找学生的姓名,并在链表中查找该结点是否存在,如果存在则输出该结点的信息,
- 最后销毁链表回收资源
//查找 ---- 按名字
void SearchStudentByName() {
LinkList pList = NULL; //链表
struct Student temp; //临时存储一个学生的信息
memset(&temp, 0x00, sizeof(struct Student));
FILE *fp = NULL; //文件指针
//读取文件内容
pList = ReadFile(pList, fp, temp);
cout << "请输入要查找学生的Name:";
char name[10] = { 0 };
cin >> name;
LinkList node = FindNodeByName(pList, name);
if (node && node->next) {
Print(node->next);
}
else {
cout << "查无此人! 请查看输入的Name是否正确!" << endl;
}
}
创建新的链表结点函数封装
//创建一个链表结点
LinkList CreatNode(struct Student *pData) {
//LinkList pNew = (LinkList)malloc(sizeof(LNode));
LinkList pNew = new LNode; //新结点
if (NULL == pNew) {
return NULL;
}
else {
pNew->next = NULL;
strcpy(pNew->stu.name, pData->name);
strcpy(pNew->stu.sex, pData->sex);
pNew->stu.age = pData->age;
pNew->stu.id = pData->id;
pNew->stu.data = pData->data;
pNew->stu.tel = pData->tel;
pNew->stu.Chinese = pData->Chinese;
pNew->stu.Math = pData->Math;
pNew->stu.English = pData->English;
}
return pNew;
}
添加一个新结点到链表末尾函数封装
//添加一个结点到链表末尾
void AppendNode(LinkList *root, struct Student *pData) {
if (NULL == root) return;
else {
LinkList pTemp = *root;
//让pTemp指向链表的最后一个结点
while (pTemp->next) pTemp = pTemp->next;
pTemp->next = CreatNode(pData); //链表末尾连接新结点
}
}
遍历并输出链表结点信息
//遍历链表并输出
void Foreach(LinkList root) {
if (NULL == root) return;
while (root) {
printf("%3d\t", root->stu.id);
printf("%3s\t", root->stu.name);
printf("%3d\t", root->stu.age);
printf("%3s\t", root->stu.sex);
printf("%3d\t", root->stu.tel);
printf("%3.1f\t", root->stu.Chinese);
printf("%3.1f\t", root->stu.Math);
printf("%3.1f\t", root->stu.English);
root = root->next;
cout << endl << "-----------------------------------------------------------------" << endl;
}
}
按位置查找链表中的结点
//找到链表中第pos个结点
LinkList FindNodeByPos(LinkList root, int pos) {
if (NULL == root || pos < 0) return NULL;
if (pos == 0) return root;
for (size_t i = 0; i < pos; i++){
if (NULL == root) return NULL;
root = root->next;
}
return root;
}
删除链表中的指定结点
//删除链表中第pos个结点
void DeleteNode(LinkList *root, int pos) {
if (NULL == root || NULL == *root || pos < 0) return;
LinkList pDel = *root;
LinkList pDelPre = NULL;
if (pos == 0) {
*root = pDel->next;
delete pDel;
return;
}
//pDel = FindNodeByPos(*root, pos);
pDelPre = FindNodeByPos(*root, pos-1);
pDel = pDelPre->next;
if (NULL == pDel) return;
pDelPre->next = pDel->next;
delete pDel;
}
按ID查找链表中的结点
//找到链表中与id相同的结点
LinkList FindNodeById(LinkList root, int id) {
if (NULL == root) return NULL;
LinkList FNode = root->next;
while (root->next) {
if (FNode->stu.id == id) {
return root;
}
root = FNode;
FNode = FNode->next;
}
return root;
}
按Name查找链表中的结点
//找到链表中与naem相同的结点
LinkList FindNodeByName(LinkList root, char *name) {
if (NULL == root) return NULL;
LinkList FNode = root->next;
while (root->next) {
if (!strcmp(FNode->stu.name, name)) {
return root;
}
root = FNode;
FNode = FNode->next;
}
return root;
}
销毁整个链表
//删除整个链表
void DeleteList(LinkList *root) {
while (1) {
if (NULL == *root) return;
DeleteNode(root, 0);
}
}
输出所有学生信息的函数封装
//输出函数
void ShowAllStudent() {
LinkList pList = NULL; //链表
struct Student temp; //临时存储一个学生的信息
memset(&temp, 0x00, sizeof(struct Student));
FILE *fp = NULL; //文件指针
//读取文件内容
pList = ReadFile(pList, fp, temp);
//遍历容器并输出
printf("学号 姓名 年龄 性别 电话 语文 数学 英语\n");
Foreach(pList->next);
//删除整个链表
DeleteList(&pList);
}
输出单个学习信息的函数封装
//打印单个学生信息
void Print(LinkList root) {
if (root != NULL)
{
printf("学号 姓名 年龄 性别 电话 语文 数学 英语\n");
printf("%3d\t", root->stu.id);
printf("%3s\t", root->stu.name);
printf("%3d\t", root->stu.age);
printf("%3s\t", root->stu.sex);
printf("%3d\t", root->stu.tel);
printf("%3.1f\t", root->stu.Chinese);
printf("%3.1f\t", root->stu.Math);
printf("%3.1f\t", root->stu.English);
cout << endl << "-----------------------------------------------------------------" << endl;
}
}
读取文件内容函数封装
- 打开文件
- 按学生信息结构体大小读取文件内容
- 读取一个学生信息就建立一个新的链表结点,并将结点插入到链表的末尾
- 关闭文件
//读取文件内容
LinkList ReadFile(LinkList root, FILE *fp, struct Student temp) {
LinkList Head = new LNode; //头结点
Head->next = NULL;
root = Head; //链表
//打开文件
fp = fopen(FILEPATH, "ab+");
if (fp != NULL) {
//读取文件内容并存放在容器中
int r;
while (1) {
r = fread(&temp, 1, sizeof(struct Student), fp);
if (r <= 0) { //没读到
break;
}
else { //读到了一个学生的信息
//创建一个新链表结点结点并添加到链表末尾
AppendNode(&root, &temp);
}
}
}
//关闭文件
fclose(fp);
return root;
}
更新文件内容
- 打开文件
- 将整个链表写入到文件
- 关闭文件
//更新文件内容
void WriteFile(LinkList root, FILE *fp) {
//打开文件
fp = fopen(FILEPATH, "wb");
LinkList pTemp = root->next;
while (pTemp) {
fwrite(&(pTemp->stu), 1, sizeof(struct Student), fp);
pTemp = pTemp->next;
}
//关闭文件
fclose(fp);
}