C++学习(四十)(C语言部分)之 学生管理系统设计

涉及到的:
指针申请内存 结构体
数据结构部分
排序
文件操作

 

vs2013
数据结构 排序 结构体 指针

功能:
1、人工录入信息
2、删除
3、查找
4、修改
5、全部显示
6、文件的读取和保存
7、排序

设计:
学生信息 学号 名字 年龄 成绩(结构体)
1、数据 用数组存放学生信息 顺序表(数组+size+len实现) 链表(结构体指针实现)
2、增删查改
3、菜单 +提示 +界面

注册 -->注册的用户 密码 存到文件
登录 输入用户名和密码 到文件中找有没有匹配的记录

 

首先在项目编写过程中,将需要的功能,函数等思路罗列清楚。

大致分为以下四个板块

//******头文件  宏定义 类型定义 全局变量********

//******************函数声明*************************

//*****************主函数****************************

//******************函数定义************************

 

第一步,对学生信息的录入工作

先将学生属性用结构体存放

将所用到的函数首先在函数声明部分进行声明,之后再函数定义部分对所用到的函数进行定义,并在需要的时候进行调用。

最先做好的部分就是菜单和信息录入

测试结果如下所示:

发现输出有一点问题,之后再做修改。

具体测试代码笔记如下:

  1 //****************头文件  宏定义 类型定义 全局变量********************
  2 #include<stdio.h>
  3 #include<windows.h>
  4 #include<stdlib.h>
  5 #include<string.h>
  6 #include<WinBase.h>
  7 
  8 //学生基本信息
  9 typedef struct student
 10 {
 11     char stuNum[12];//学号
 12     char name[20];//名字
 13     int age;//年龄
 14     float grade;//成绩
 15     //后续可以继续加
 16 
 17     struct student*next;//如果用数组存 那么不需要指针域  链表存 需要指针域
 18 }STU,*PSTU;
 19 //****************函数声明********************
 20 void menu();//菜单
 21 void insertStu(PSTU head);//录入
 22 void findMenu(PSTU head);//查询用菜单
 23 void findByAge(PSTU head);//根据年龄查找信息
 24 //void changeStu();//修改
 25 void printAll(PSTU head);//全部打印
 26 //---------------------------------主函数
 27 void deleStuByNum(PSTU head);//通过学号删除学员信息
 28 
 29 void sortByGrade(PSTU head);//按照分数排序
 30 
 31 void swap(PSTU a, PSTU b); //交换两个节点
 32 
 33 void insertFile(PSTU head);//从文件中读取内容
 34 
 35 void setFile(PSTU head);//存档
 36 
 37 void freeNode(PSTU head);//释放所有节点
 38 
 39 void deleStuByGrade(PSTU head);//通过成绩删除
 40 
 41 //******************主函数********************
 42 int main()
 43 {
 44 
 45     menu();
 46     return 0;
 47 }
 48 
 49 //****************函数定义********************
 50 //菜单
 51 void menu()
 52 {
 53     //链表 
 54     PSTU head=(PSTU)malloc(sizeof(STU));//定义头指针
 55     head->next = NULL;//头结点的next赋值NULL
 56     //录入文件   打开文件并且读取文件内容  (没写完 待补充  )***************
 57     insertFile(head);//读取文件内容
 58     while (1)//循环一直进行
 59     {
 60         system("cls");//清屏函数 用于控制台的
 61         printf("**************************\n");
 62         printf("****欢迎进入学生管理系统****\n");
 63         printf("1.录入学生信息\n");
 64         printf("2.查询学生信息\n");
 65         printf("3.修改学生信息\n");
 66         printf("4.删除学生信息\n");
 67         printf("5.打印所有学生信息\n");
 68         printf("6.排序\n");
 69         printf("0.退出\n");
 70         printf("输入你的选择\n\n");
 71         int choice = -1;
 72         scanf("%d", &choice);//获取用户用户的操作
 73         switch (choice)
 74         {
 75         case 1://录入
 76             insertStu(head);//传递实参
 77             break;
 78         case 2://查询
 79             findMenu(head);//查询
 80             break;
 81         case 3://修改  先查询  找到位置之后 再修改
 82             //不写
 83             break;
 84         case 4://删除  //示例用学号删除学生信息
 85             deleStuByNum(head);
 86             break;
 87         case 5://全部打印
 88             printAll(head);
 89             break;
 90         case 6:
 91             //链表的排序
 92             //默认用学号排序   换成用分数排序
 93             sortByGrade(head);
 94             break;
 95         case 0://退出程序
 96             /*
 97             跳转语句   goto
 98             return //跳出这个循环
 99             break//跳出循环 跳出swicth
100             continue//跳过本轮循环 进入下一轮循环
101             exit(0);//函数  表示退出这个程序   stdlib.h
102             */
103             //--------------------=========//跳出循环
104             setFile(head);//退出前存档
105             //存挡  当前所有内容 写入文件(待补充,,,,,,,,,,,>
106             //释放所有节点内存(待补充-------------------->
107             freeNode(head);//释放这个链表所有结点
108             return;//跳出这个函数
109             break;
110         default:
111             //输入错误
112             //重新输入
113             printf("输入错误 请重新输入\n");
114             Sleep(2000);//休息两秒  Windows.h
115             //....
116             break;
117         }
118     }
119 }
120 
121 //录入
122 void insertStu(PSTU head)
123 {
124     PSTU p = (PSTU)malloc(sizeof(STU));
125     printf("输入学生信息");
126     printf("输入学号"); scanf("%s", p->stuNum);//录入
127     printf("输入姓名"); scanf("%s", p->name);
128     printf("输入年龄"); scanf("%d", &p->age);
129     printf("输入成绩"); scanf("%f", &p->grade);
130     //输入完成之后  连接
131     //p->next = head->next;
132     //head->next = p;//头插
133     
134     ///插入的时候同时进行排序
135     PSTU temp = head;
136     //插入到合适的位置
137     while (temp->next != NULL)
138     {
139         if (strcmp(temp->next->stuNum, p->stuNum)>0)//找到第一个比他大的元素
140         {
141             break;
142         }
143         temp = temp->next;
144     }
145     //如果temp->next==NULL  插入放在里面的话这个节点不会被插入到链表中  因此放在外面
146     p->next = temp->next;
147     temp->next = p;//插入
148     Sleep(1000);//看一下效果
149 }
150 
151 //全部打印
152 void printAll(PSTU head)
153 {
154     PSTU p = head->next;
155     while (p != NULL)
156     {
157         printf("学号%10s\t名字%10s\t年龄%5d\t分数%.2f\n", p->stuNum, p->name, p->age, p->grade);
158         p = p->next;
159     }
160     //printf("学号\t\t名字\t\t年龄\t\t分数\n");//这个需要另外对齐
161     //while (p != NULL)
162     //{
163     //    printf("%s\t%s\t%d\t%.2f\n", p->stuNum, p->name, p->age, p->grade);
164     //    p = p->next;
165     //}
166     Sleep(2000);//休息一会
167 }
168 
169 //查询用菜单
170 void findMenu(PSTU head)
171 {
172     system("cls");
173     printf("请输入你要查询的方式");
174     printf("1.按照年龄查询");
175 
176     int choice;
177     scanf("%d", &choice);
178     switch (choice)
179     {
180     case 1://根据年龄查询
181         //通过年龄区间 得到信息  可以写函数  也可以直接写 
182         break;
183     }
184 }
185 
186 //根据年龄查找信息
187 void findByAge(PSTU head)
188 {
189     //1.根据年龄查询
190     //2.根据区间查询
191     printf("请输入一个年龄区间");
192     int x, y;//年龄
193     scanf("%d %d", &x, &y);
194     if (x >= y)
195     {
196         for (PSTU temp = head->next; temp != NULL; temp = temp->next)
197         {
198             if (temp->age >= y&&temp->age <= x)
199             {
200                 printf("学号%10s\t名字%10s\t年龄%5d\t分数%.2f\n", temp->stuNum, temp->name, temp->age, temp->grade);
201             }
202         }
203     }
204     else//x<=y
205     {
206         //自己补齐
207     }
208     Sleep(2000);
209 }
210 
211 //通过学号删除学员信息
212 void deleStuByNum(PSTU head)
213 {
214     PSTU p = head;
215     char stuNum[20];
216     printf("输入你要删除的学员的学号");
217     scanf("%s", stuNum);
218     //删除一个节点  要删除位置前面的结点
219 
220     //for (; p->next != NULL; p = p->next)
221     //{
222     //    if (strmp(p->next->stuNum, stuNum) == 0)
223     //    {
224     //        break;
225     //    }
226     //}
227     //if (p->next!=NULL)
228     //{
229     //    PSTU q = p->next;
230     //    p->next = q->next;
231     //    free(q);//释放结点
232     //    //如果多个学号相同的同学
233     //    printf("删除成功");
234     //}
235     //else
236     //{
237     //    printf("找不到对应的记录 删除失败\n");
238     //}
239 
240     for (; p->next != NULL; )
241     {
242         if (strcmp(p->next->stuNum, stuNum) == 0)
243         {
244             PSTU q = p->next;
245             p->next = q->next;
246             free(q);//释放结点
247             //如果多个学号相同的同学
248         //printf("删除成功");
249         }
250         else
251         {
252             p = p->next;//这句不直接放在外面的原因  避免少比较一个元素
253             //比如说   A->B->C->D
254             //p 刚刚开始指向A  删除B之后 A->C->D
255             //p往后移动  C就没有参与比较  所以为了避免这种情况  p=p->next放在else中
256         }
257     }
258     Sleep(2000);
259 }
260 
261 //按照分数排序
262 void sortByGrade(PSTU head)
263 {
264     //冒泡 插入  选择 快速
265     // 冒泡  从头到尾  如果相邻元素位置有问题  交换
266     //插入 将后面的一个结点插入到前面的有序位置中
267     //选择 交换两个节点  每次找剩下那个最小的进行交换
268     //快速  一分为2  分开进行快速排序
269 
270     //快速    冒泡   选择 交换
271     //做法 :找到两个位置  进行交换
272     
273     //链表的循环条件稍微改一下 
274     //选择排序
275     PSTU p = head->next;//第一个节点
276     PSTU q, min;
277     while (p != NULL)
278     {
279         min = p;//刚刚开始指向p的位置
280         q = p->next;//从p的后面开始找
281         while (q != NULL)
282         {
283             //if (strcmp(q->stuNum, min->stuNum) < 0)
284             if (q->grade<min->grade)
285             {
286                 min = q;//标记最小
287             }
288             q = q->next;
289         }
290         if (min == NULL||min == p);//不需要交换
291         else swap(p, min);//交换两个节点的数据
292         p = p->next;
293     }
294 
295 
296 }
297 
298 //交换两个节点  写一个函数 
299 void swap(PSTU a, PSTU b)
300 {
301     char stuNum[12];//学号
302     char name[20];//名字
303     int age;//年龄
304     float grade;//成绩
305     strcpy(stuNum, a->stuNum);
306     strcpy(a->stuNum, b->stuNum);
307     strcpy(b->stuNum, stuNum);
308     strcpy(name, a->name);
309     strcpy(a->name, b->name);
310     strcpy(b->name, name);
311     age = a->age;
312     a->age = b->age;
313     b->age = age;
314     grade = a->grade;
315     a->grade = b->grade;
316     b->grade = grade;
317 }
318 
319 //文件操作   -->数据存放文件中(保留数据)
320 //读档
321 void insertFile(PSTU head)//从文件中读取内容
322 {
323     FILE *fp = fopen("student.txt", "r");//rwa  三选一
324     //r  文件不存在 打开失败
325     //w  文件不存在 创建文件  但是文件存在 清空文件内容
326     if (fp == NULL)
327     {
328         fp = fopen("student.txt", "w");//创建新文件
329         fclose(fp);
330         return;
331     }
332     //学号 名字 年龄 成绩
333     STU temp, *p;
334     while (1)//循环读取
335     {
336         fscanf(fp, "%s %s %d %f", temp.stuNum, temp.name, &temp.age, &temp.grade);//读取内容
337         if (feof(fp)) break;//如果文件读到末尾  返回1
338         //feof  文件中有三个数据  当读完第三个数据的时候不会返回1
339         //读到第四个的时候有问题
340 
341         p = (PSTU)malloc(sizeof(STU));
342         *p = temp;//赋值
343         //将这个节点 连到链表上
344         PSTU q = head;
345         //插入到合适的位置
346         while (q->next != NULL)
347         {
348             if (strcmp(q->next->stuNum, p->stuNum)>0)//找到第一个比他大的元素
349             {
350                 break;
351             }
352             q = q->next;
353         }
354         //如果temp->next==NULL  插入放在里面的话这个节点不会被插入到链表中  因此放在外面
355         p->next = q->next;
356         q->next = p;//插入
357 
358     }
359     fclose(fp);//关闭文件
360 
361 }
362 
363 //存档
364 void setFile(PSTU head)
365 {
366     //写入  w a
367     FILE *fp = fopen("student.txt", "w");//清空原内容
368     PSTU p = head->next;
369     while (p != NULL)
370     {
371         fprintf(fp,"%s %s %d %.2f\n", p->stuNum, p->name, p->age, p->grade);//写入文件
372         p = p->next;
373     }
374     fclose(fp);
375 }
376 
377 void freeNode(PSTU head)//释放所有节点
378 {
379     PSTU temp = head;
380     while (head != NULL)
381     {
382         temp = head;
383         head = head->next;
384         free(temp);//释放节点
385     }
386 }
387 
388 //通过成绩删除
389 void deleStuByGrade(PSTU head)
390 {
391     PSTU arr[10];
392     int len = 0;
393     int size = 10;
394     //准备数组
395     float Grade;
396     printf("输入的你要删除的学生的成绩");
397     scanf("%f", &Grade); //取地址
398     PSTU p = head->next;
399     while (p != NULL)
400     {
401         if (p->grade < Grade + 3 && p->grade>Grade - 3)// 浮点型 存的都是近似值  给一个区间
402         {
403             if (len < size) arr[len++] = p;//存放符合要求一个结点的位置
404         }
405     }
406     //找到所有符合要求的节点
407     for (int i = 0; i < len; ++i)
408     {
409         printf("编号%d--->学号%s,姓名%s,年龄%d,成绩%.2f",i, arr[i]->stuNum, arr[i]->name, arr[i]->age, arr[i]->grade);
410     }
411     printf("输入你要删除的元素的编号");
412     int choice;
413     scanf("%d", &choice);
414     if (choice >= 0 && choice < len)//说明有删除的元素
415     {
416         //找到结点并且删除就可以了
417         //arr[choice];//结点的地址
418         //找前面那个结点  然后删除
419         PSTU temp = head;
420         while (temp!=NULL)
421         {
422             //找要删除的前面那个结点的位置
423             if (temp->next == arr[choice])
424             {
425                 temp->next = arr[choice]->next;
426                 free(arr[choice]);
427                 break;
428             }
429             temp = temp->next;
430         }
431     }
432 }
433 /*
434 //指针申请内存  结构体
435 //数据结构部分
436 //排序
437 
438 time 函数
439 gettickcount
440 
441 
442 开始获取一次时间  结束的获取一次时间
443 时间差  --->运行时间
444 
445 //测试
446 DWORD time1 = GetTickCount();
447 Sleep(2000);
448 DWORD time2 = GetTickCount();
449 printf("%ld", time2 - time1);
450 getchar();
451 
452 
453 
454 1.算法优化 -->排序 
455 2.存储优化  --->数组  单链表   双链表
456     数组  省内存  中间插入 开头插入 比较麻烦  尾端插入效率高
457             查找  访问从前往后 也可以从后往前
458     单链表 插入很方便  内存不是很省  没有长度限制
459             访问 不是很方便
460     双链表  插入方便  内存不是很省  
461             访问可以从前往后 也可以从后往前
462 3.计算  右移代替除以2 

注:其中部分功能并没有实现,还有一些是需要补充的,等以后有时间再补充吧

部分成功展示:

2019-04-04  10:19:07

猜你喜欢

转载自www.cnblogs.com/Yuuki-/p/10653392.html