基于双向循环链表实现的学生管理系统,包括初始化,插入,删除,查抄,保存,自动按照姓名排序功能,退出并保存功能。
实现思想是将程序的各个部分划分为三个层次。主函数为界面层,即客户端层;其中后缀为Student的一般是某个功能的调度函数,属于逻辑层的内容;在调度函数之下有相应的被调度的函数,也就是相应功能的实现函数,一般后缀名为Node,意思就是这个函数直接操作链表中的结点,可以简单的划分为实现层;
这样分层实现呢有利于代码维护和个功能之间对包含或者重叠功能的直接调用,从而提高代码重用度,而降低代码冗余,并且最低成的实现函数也可以用于别的项目中对双向循环链表的操作。
本次学生管理系统的实现是先用一个初始化文件函数将一些学生信息先存入磁盘中,然后用初始化函数读出到链表中进行各种操作,保存功能和退出功能可以将链表中操作了的内容,也就是内存中的内容写入磁盘中,其中对文件的操作采用二进制读写文件,读写对象为学生结构体。
以下是代码实现:
#include<stdio.h> #include<stdlib.h> #include<string.h> #pragma warning (disable:4996) //定义学生信息结点 struct SNode{ char name[50]; char sex; int math; int chinese; int history; }; typedef struct SNode Student; //定义链表结点 struct Node{ Student student; struct Node *left; struct Node *right; }; typedef struct Node Node; void init(void);//初始化一个学生信息文件 Node * createList();//创建双向循环链表 void initializationList(Node *head);//初始化链表 int insertStudent(Node *head);//菜单中插入功能调度函数 int insertList(Node *head, Student newStudent);//插入功能实现函数,头插法插入结点 void searchStudent(Node *head);//查找功能的调度函数 Node *searchNode(Node *head, char *name);//查找功能的实现函数 int deleteStudent(Node *head);//菜单中删除功能的调度函数 int deleteNode(Node *head, char *name);//删除功能的实现函数 int lenList(Node *head);//求双向循环链表的长度 void sortList(Node *head, int len);//依据姓名字符串的排序函数 int saveToFile(Node *head);//将存放在内存中的学生数据写回磁盘文件中 void printList(Node * head);//打印链表内容 int main(void) { // init();//若没有学生信息文件,可打开此函数,初始化完成后可关闭此函数, //可在本函数内修改初始学生信息 printf("学生管理系统/n"); printf("目前所有学生:/n"); Node *head = createList();//创建双向循环链表管理学生 initializationList(head);//从文件中读取初始学生信息初始化链表 while (1) { int len = lenList(head); sortList(head, len);//输出之前按照名字排序 system("CLS");//调用系统清屏函数 printf("学生管理系统/n"); printf("目前所有学生:/n"); printList(head);//打印链表中的信息 printf("1->添加/t2->删除/t3->查找4->保存5->退出/n"); int select = 0; scanf("%d",&select); switch (select) { case 1: insertStudent(head); system("CLS"); printf("学生管理系统/n"); printf("目前所有学生:/n"); printList(head); break; case 2: deleteStudent(head); system("CLS"); printf("学生管理系统/n"); printf("目前所有学生:/n"); printList(head); break; case 3: searchStudent(head); printf("请按下任意键返回主菜单/n"); getchar(); break; case 4: saveToFile(head); printf("保存成功/n"); system("CLS"); printf("学生管理系统/n"); printf("目前所有学生:/n"); initializationList(head); printList(head); break; case 5: printf("程序即将退出/n"); saveToFile(head); printf("保存成功/n"); exit(1); break; } } return 0; } //创建初始化文件 void init(void) { FILE *fop = fopen("D:/Test/classTest/student.txt", "wb"); Student students[5] = { { "zhao", 'm', 90, 100, 100 }, { "qian", 'w', 60, 60, 60 }, { "sun", 'm', 85, 85, 90 }, { "li", 'm', 60, 100, 100 }, { "zhou", 'w', 100, 100, 100 } }; fwrite(students, sizeof(Student), 5, fop); fclose(fop); } //创建双向循环链表 Node * createList() { Node *head = (Node *)malloc(sizeof(Node)); if (head) { head->left = head; head->right = head; return head; } else return NULL; } //初始化链表 void initializationList(Node *head) { FILE *fip = fopen("D:/Test/classTest/student.txt", "rb"); Student newStudent; while (fread(&newStudent, sizeof(Student), 1, fip) != 0){ insertList(head, newStudent); } } //菜单中插入功能调度函数 int insertStudent(Node *head) { Student newStudent; printf("请输入学生信息:/n"); printf("姓名:"); scanf("%s",&newStudent.name); getchar(); printf("性别:"); newStudent.sex=getchar(); printf("数学:"); scanf("%d",&newStudent.math); printf("语文:"); scanf("%d",&newStudent.chinese); printf("历史:"); scanf("%d",&newStudent.history); insertList(head, newStudent); } //结点插入 //插入功能实现函数,头插法插入 int insertList(Node *head, Student data) { Node *newNode = (Node *)malloc(sizeof(Node)); if (newNode) { newNode->student = data; newNode->left = head; newNode->right = head->right; head->right = newNode; newNode->right->left = newNode; return 1; } else return -1; } //菜单中删除功能的调度函数 int deleteStudent(Node *head) { printf("请输入需要删除的学生的姓名:"); char name[50]; scanf("%s",name); getchar(); int flag=deleteNode(head, name); if (flag) printf("删除成功/n"); else printf("删除失败/n"); return flag; } //删除功能的实现函数 int deleteNode(Node *head, char *name) { Node *searchStudent = searchNode(head, name); if (searchStudent){ searchStudent->left->right = searchStudent->right; searchStudent->right->left = searchStudent->left; free(searchStudent); return 1; } return 0; } //查找功能的调度函数 void searchStudent(Node *head) { printf("请输入需要删除的学生的姓名:"); char name[50]; scanf("%s", name); getchar(); Node *result = searchNode(head, name); if (result) { printf("姓名/t性别/t数学/t语文/t历史/n"); printf("%s/t%c/t%d/t%d/t%d/n", result->student.name, result->student.sex, result ->student.math, result->student.chinese, result->student.history); } else printf("没有找到该学生/n"); } //查找功能的实现函数 Node *searchNode(Node *head, char *name) { Node *left = head; Node *right = head; do { left = left->left; right = right->right; if (strcmp(left->student.name, name)==0) return left; if (strcmp(right->student.name, name)==0) return right; } while (left != right && left->left != right); return NULL; } //依据姓名字符串的排序函数 void sortList(Node *head, int len) { Node *p, *q, *max, *temp; Student t; p = head->right; q = p->right; int i = 0, j = 0; for (i = 0; i < len - 1; i++) { if (p == head) break; max = p; q = p; for (j = i; j < len; j++) { if (q == head) break; if (strcmp(max->student.name, q->student.name)>0) max = q; q = q->right; } if (max != p) { t = max->student; max->student = p->student; p->student = t; } p = p->right; } } //求双向循环链表的长度 int lenList(Node *head) { Node *p = head; int len = 0; while (p->right != head){ len++; p = p->right; } return len; } //打印链表内容 void printList(Node * head) { Node *p = head->right; while (p != head) { printf("%s/t%c/t%d/t%d/t%d/n", p->student.name, p->student.sex, p->student.math, p->student.chinese, p->student.history); p = p->right; } } //将存放在内存中的学生数据写回磁盘文件中 int saveToFile(Node *head) { FILE *fop = fopen("D:/Test/classTest/student.txt", "wb"); Node *p = head->right; while (p != head) { fwrite(&p->student,sizeof(Student), 1, fop); p = p->right; } return 1; }