基於雙向循環鏈表實現的學生管理系統,包括初始化,插入,刪除,查抄,保存,自動按照姓名排序功能,退出並保存功能。函數
實現思想是將程序的各個部分劃分爲三個層次。主函數爲界面層,即客戶端層;其中後綴爲Student的通常是某個功能的調度函數,屬於邏輯層的內容;在調度函數之下有相應的被調度的函數,也就是相應功能的實現函數,通常後綴名爲Node,意思就是這個函數直接操做鏈表中的結點,能夠簡單的劃分爲實現層;code
這樣分層實現呢有利於代碼維護和個功能之間對包含或者重疊功能的直接調用,從而提升代碼重用度,而下降代碼冗餘,而且最低成的實現函數也能夠用於別的項目中對雙向循環鏈表的操做。對象
本次學生管理系統的實現是先用一個初始化文件函數將一些學生信息先存入磁盤中,而後用初始化函數讀出到鏈表中進行各類操做,保存功能和退出功能能夠將鏈表中操做了的內容,也就是內存中的內容寫入磁盤中,其中對文件的操做採用二進制讀寫文件,讀寫對象爲學生結構體。排序
如下是代碼實現:ip
#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; }