基于双向循环链表实现的学生管理系统,包括初始化,插入,删除,查抄,保存,自动按照姓名排序功能,退出并保存功能。
实现思想是将程序的各个部分划分为三个层次。主函数为界面层,即客户端层;其中后缀为Student的一般是某个功能的调度函数,属于逻辑层的内容;在调度函数之下有相应的被调度的函数,也就是相应功能的实现函数,一般后缀名为Node,意思就是这个函数直接操作链表中的结点,可以简单的划分为实现层;
这样分层实现呢有利于代码维护和个功能之间对包含或者重叠功能的直接调用,从而提高代码重用度,而降低代码冗余,并且最低成的实现函数也可以用于别的项目中对双向循环链表的操作。
本次学生管理系统的实现是先用一个初始化文件函数将一些学生信息先存入磁盘中,然后用初始化函数读出到链表中进行各种操作,保存功能和退出功能可以将链表中操作了的内容,也就是内存中的内容写入磁盘中,其中对文件的操作采用二进制读写文件,读写对象为学生结构体。
以下是代码实现:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #pragma warning (disable:4996) 5 6 //定义学生信息结点 7 struct SNode{ 8 char name[50]; 9 char sex; 10 int math; 11 int chinese; 12 int history; 13 }; 14 15 typedef struct SNode Student; 16 17 //定义链表结点 18 struct Node{ 19 Student student; 20 struct Node *left; 21 struct Node *right; 22 }; 23 24 typedef struct Node Node; 25 26 void init(void);//初始化一个学生信息文件 27 Node * createList();//创建双向循环链表 28 void initializationList(Node *head);//初始化链表 29 int insertStudent(Node *head);//菜单中插入功能调度函数 30 int insertList(Node *head, Student newStudent);//插入功能实现函数,头插法插入结点 31 void searchStudent(Node *head);//查找功能的调度函数 32 Node *searchNode(Node *head, char *name);//查找功能的实现函数 33 int deleteStudent(Node *head);//菜单中删除功能的调度函数 34 int deleteNode(Node *head, char *name);//删除功能的实现函数 35 int lenList(Node *head);//求双向循环链表的长度 36 void sortList(Node *head, int len);//依据姓名字符串的排序函数 37 int saveToFile(Node *head);//将存放在内存中的学生数据写回磁盘文件中 38 void printList(Node * head);//打印链表内容 39 40 int main(void) 41 { 42 // init();//若没有学生信息文件,可打开此函数,初始化完成后可关闭此函数, 43 44 //可在本函数内修改初始学生信息 45 printf("学生管理系统\n"); 46 printf("目前所有学生:\n"); 47 48 Node *head = createList();//创建双向循环链表管理学生 49 initializationList(head);//从文件中读取初始学生信息初始化链表 50 51 while (1) 52 { 53 int len = lenList(head); 54 sortList(head, len);//输出之前按照名字排序 55 system("CLS");//调用系统清屏函数 56 printf("学生管理系统\n"); 57 printf("目前所有学生:\n"); 58 printList(head);//打印链表中的信息 59 printf("1->添加\t2->删除\t3->查找4->保存5->退出\n"); 60 int select = 0; 61 scanf("%d",&select); 62 switch (select) 63 { 64 case 1: 65 insertStudent(head); 66 system("CLS"); 67 printf("学生管理系统\n"); 68 printf("目前所有学生:\n"); 69 printList(head); 70 break; 71 case 2: 72 deleteStudent(head); 73 system("CLS"); 74 printf("学生管理系统\n"); 75 printf("目前所有学生:\n"); 76 printList(head); 77 break; 78 case 3: 79 searchStudent(head); 80 printf("请按下任意键返回主菜单\n"); 81 getchar(); 82 break; 83 case 4: 84 saveToFile(head); 85 printf("保存成功\n"); 86 system("CLS"); 87 printf("学生管理系统\n"); 88 printf("目前所有学生:\n"); 89 initializationList(head); 90 printList(head); 91 break; 92 case 5: 93 printf("程序即将退出\n"); 94 saveToFile(head); 95 printf("保存成功\n"); 96 exit(1); 97 break; 98 } 99 } 100 return 0; 101 } 102 103 //创建初始化文件 104 void init(void) 105 { 106 FILE *fop = fopen("D:/Test/classTest/student.txt", "wb"); 107 Student students[5] = { { "zhao", ‘m‘, 90, 100, 100 }, 108 { "qian", ‘w‘, 60, 60, 60 }, 109 { "sun", ‘m‘, 85, 85, 90 }, 110 { "li", ‘m‘, 60, 100, 100 }, 111 { "zhou", ‘w‘, 100, 100, 100 } }; 112 fwrite(students, sizeof(Student), 5, fop); 113 fclose(fop); 114 } 115 116 //创建双向循环链表 117 Node * createList() 118 { 119 Node *head = (Node *)malloc(sizeof(Node)); 120 if (head) 121 { 122 head->left = head; 123 head->right = head; 124 return head; 125 } 126 else 127 return NULL; 128 } 129 130 //初始化链表 131 void initializationList(Node *head) 132 { 133 FILE *fip = fopen("D:/Test/classTest/student.txt", "rb"); 134 Student newStudent; 135 while (fread(&newStudent, sizeof(Student), 1, fip) != 0){ 136 insertList(head, newStudent); 137 } 138 } 139 140 //菜单中插入功能调度函数 141 int insertStudent(Node *head) 142 143 { 144 Student newStudent; 145 printf("请输入学生信息:\n"); 146 printf("姓名:"); 147 scanf("%s",&newStudent.name); 148 getchar(); 149 printf("性别:"); 150 newStudent.sex=getchar(); 151 printf("数学:"); 152 scanf("%d",&newStudent.math); 153 printf("语文:"); 154 scanf("%d",&newStudent.chinese); 155 printf("历史:"); 156 scanf("%d",&newStudent.history); 157 insertList(head, newStudent); 158 } 159 160 //结点插入 161 //插入功能实现函数,头插法插入 162 int insertList(Node *head, Student data) 163 { 164 Node *newNode = (Node *)malloc(sizeof(Node)); 165 if (newNode) 166 { 167 newNode->student = data; 168 newNode->left = head; 169 newNode->right = head->right; 170 head->right = newNode; 171 newNode->right->left = newNode; 172 return 1; 173 } 174 else 175 return -1; 176 } 177 178 //菜单中删除功能的调度函数 179 int deleteStudent(Node *head) 180 { 181 printf("请输入需要删除的学生的姓名:"); 182 char name[50]; 183 scanf("%s",name); 184 getchar(); 185 int flag=deleteNode(head, name); 186 if (flag) 187 printf("删除成功\n"); 188 else 189 printf("删除失败\n"); 190 return flag; 191 } 192 193 //删除功能的实现函数 194 int deleteNode(Node *head, char *name) 195 { 196 Node *searchStudent = searchNode(head, name); 197 if (searchStudent){ 198 searchStudent->left->right = searchStudent->right; 199 searchStudent->right->left = searchStudent->left; 200 free(searchStudent); 201 return 1; 202 } 203 return 0; 204 } 205 206 //查找功能的调度函数 207 void searchStudent(Node *head) 208 { 209 printf("请输入需要删除的学生的姓名:"); 210 char name[50]; 211 scanf("%s", name); 212 getchar(); 213 Node *result = searchNode(head, name); 214 215 if (result) 216 { 217 printf("姓名\t性别\t数学\t语文\t历史\n"); 218 printf("%s\t%c\t%d\t%d\t%d\n", result->student.name, result->student.sex, 219 result ->student.math, result->student.chinese, result->student.history); 220 } 221 else 222 printf("没有找到该学生\n"); 223 } 224 225 //查找功能的实现函数 226 Node *searchNode(Node *head, char *name) 227 { 228 Node *left = head; 229 Node *right = head; 230 do 231 { 232 left = left->left; 233 right = right->right; 234 if (strcmp(left->student.name, name)==0) 235 return left; 236 if (strcmp(right->student.name, name)==0) 237 return right; 238 239 } while (left != right && left->left != right); 240 return NULL; 241 } 242 243 //依据姓名字符串的排序函数 244 void sortList(Node *head, int len) 245 { 246 Node *p, *q, *max, *temp; 247 Student t; 248 p = head->right; 249 q = p->right; 250 int i = 0, j = 0; 251 for (i = 0; i < len - 1; i++) 252 { 253 if (p == head) 254 break; 255 max = p; 256 q = p; 257 for (j = i; j < len; j++) 258 { 259 if (q == head) 260 break; 261 if (strcmp(max->student.name, q->student.name)>0) 262 max = q; 263 q = q->right; 264 } 265 if (max != p) 266 { 267 t = max->student; 268 max->student = p->student; 269 p->student = t; 270 } 271 p = p->right; 272 } 273 } 274 275 //求双向循环链表的长度 276 int lenList(Node *head) 277 { 278 Node *p = head; 279 int len = 0; 280 while (p->right != head){ 281 len++; 282 p = p->right; 283 } 284 return len; 285 } 286 287 //打印链表内容 288 void printList(Node * head) 289 { 290 Node *p = head->right; 291 while (p != head) 292 { 293 printf("%s\t%c\t%d\t%d\t%d\n", p->student.name, p->student.sex, 294 p->student.math, p->student.chinese, p->student.history); 295 p = p->right; 296 } 297 } 298 299 //将存放在内存中的学生数据写回磁盘文件中 300 int saveToFile(Node *head) 301 { 302 FILE *fop = fopen("D:/Test/classTest/student.txt", "wb"); 303 304 Node *p = head->right; 305 while (p != head) 306 { 307 fwrite(&p->student,sizeof(Student), 1, fop); 308 p = p->right; 309 } 310 return 1; 311 } 312
时间: 2024-10-19 15:15:25