学生管理系统
1.明确功能
2.数据存储
3.准备知识
3.1 枚举
3.2 链表
(单链表,循环链表,双向链表,双向循环链表)
4. 项目(待续)
1.明确功能
A. 学生:
- 查询个人详细信息。
- 查询某个课程成绩。
- 选择课程。
B. 老师:
- 查询个人详细信息。
- 给某个学生的某个课程打分。
- 申请课程。
C. 管理员:
- 查询所有学生信息。
- 查询所有老师信息。
- 查询某一个用户的详细信息。
- 添加一个老师信息。
- 添加一个学生信息。
- 添加一个管理员信息。
2.数据存储
1. 常规存储数据手段->数据库(没有学)->文件。
2. 保存哪些数据:
- a.保存所有用户的基本信息,例如users.txt文件。
- b.保存具体的一个用户的详细信息,例如用户名.txt文件。
3.准备知识
3.1 枚举
3.1.1 定义枚举类型
1.枚举语法定义格式:
enum 枚举名 { 枚举元素1, 枚举元素2, ........., 枚举元素n };
2.枚举成员的值:
第一个枚举成员的默认值为整型的 0,后续枚举成员的值在前一个成员上加 1。
没有指定值的枚举元素,其值为前一元素加 1
3.定义枚举类型例子
//第一个枚举成员的值定义为 1,第二个就为 2,以此类推。 enum DAY{ MON = 1, TUE, WED, THU, FRI, SAT, SUN };
enum season { spring, //0 summer = 3, //3 autumn, //4 winter //5 };
3.1.2 定义枚举变量
1.先定义枚举类型,再定义枚举变量
enum DAY{ MON=1, TUE, WED, THU, FRI, SAT, SUN }; enum DAY day;
2.定义枚举类型的同时定义枚举类型
enum DAY{ MON=1, TUE, WED, THU, FRI, SAT, SUN } day;
3.省略枚举名称,直接定义枚举
enum{ MON=1, TUE, WED, THU, FRI, SAT, SUN } day;
4.使用
typedef
为变量重定义一个名字。//用户类型 typedef enum { UserTypeNone, //没有身份 UserTypeStudent, //学生 UserTypeTeacher, //老师 UserTypeAdmin //管理员 }UserType; UserType type;
3.1.3 枚举在switch中的使用
#include <stdio.h> #include <stdlib.h> int main(){ enum color { red=1, green, blue }; enum color favorite_color; /* ask user to choose color */ printf("请输入你喜欢的颜色: (1. red, 2. green, 3. blue): "); scanf("%d", &favorite_color); /* 输出结果 */ switch (favorite_color){ case red: printf("你喜欢的颜色是红色"); break; case green: printf("你喜欢的颜色是绿色"); break; case blue: printf("你喜欢的颜色是蓝色"); break; default: printf("你没有选择你喜欢的颜色"); } return 0; } //运行 请输入你喜欢的颜色: (1. red, 2. green, 3. blue): 1 你喜欢的颜色是红色
3.2 链表(单链表,循环链表,双向链表,双向循环链表)
1.区别:
2.单链表的操作代码:
#include<stdio.h> #include<malloc.h> #include<assert.h> //方便修改数据域里面的类型 #define ElemType int //定义结点 typedef struct ListNode { ElemType data; struct ListNode *next; }ListNode,*PNode; //定义链表 typedef struct LinkList { PNode first; PNode last; size_t size; }LinkList; //初始化函数 void InitList(LinkList *list); //尾插函数 void push_back(LinkList *list,ElemType x); //头插函数 void push_front(LinkList *list,ElemType x); //尾删函数 void pop_back(LinkList *list); //头删函数 void pop_front(LinkList *list); //显示函数 void show_list(LinkList *list); //按值插入 void insert_val(LinkList *list,ElemType x); //查找 ListNode* find(LinkList *list,ElemType x); //链表长度 int length(LinkList *list); //按值删除 void delete_val(LinkList *list,ElemType x); //顺序 void sort(LinkList *list); //逆值 void resver(LinkList *list); //清空 void clear(LinkList *list); //销毁 void destroy(LinkList *list); //主函数 int main() { LinkList mylist; InitList(&mylist); ElemType Item; ListNode *P = NULL;//初始化find所找的结点 int select; while (1) { printf("*************************************\n"); printf("*[1].push_back [2].push_front *\n"); printf("*[3].pop_back [4].pop_front *\n"); printf("*[5].show_list [6].insert_val *\n"); printf("*[7].find [8].length *\n"); printf("*[9].delete_val [10].sort *\n"); printf("*[11].resver [12].clear *\n"); printf("*[13].quit_system [*]destroy *\n"); printf("*************************************\n"); printf("请选择:>"); scanf("%d",&select); switch (select) { case 1://尾插 printf("请输入要插入的数据(-1结束):>"); while (scanf("%d",&Item),Item != -1) { push_back(&mylist,Item); } break; case 2://头插 printf("请输入要插入的数据(-1结束):>"); while (scanf("%d",&Item),Item != -1) { push_front(&mylist,Item); } break; case 3://尾删 pop_back(&mylist); printf("成功尾删\n"); break; case 4://头删 pop_front(&mylist); printf("成功头删\n"); break; case 5://显示 show_list(&mylist); break; case 6://按值插入 //插在所给值前面的位置 printf("请输入要插入的数据:>"); scanf("%d",&Item); insert_val(&mylist,Item); printf("插入成功\n"); break; case 7://查找 printf("请输入要查找的数据:>"); scanf("%d",&Item); P = find(&mylist,Item); break; case 8://链表长度 printf("链表的长度为%d.\n",length(&mylist)); break; case 9://按值删除 printf("请输入要删除的数据:>"); scanf("%d",&Item); delete_val(&mylist,Item); break; case 10://顺序 sort(&mylist); printf("排序完成.\n"); break; case 11://逆值 resver(&mylist); printf("逆值完成.\n"); break; case 12://清空 clear(&mylist); printf("清空完成.\n"); break; case 13://结束 break; default: printf("输入的数据不合法,请重新输入"); break; } } return 0; } //初始化函数 void InitList(LinkList *list) { //开辟first和last的空间,初始状态指向同一个结点 list->first = list->last = (ListNode*)malloc(sizeof(ListNode)); assert(list->first != NULL); //初始化first和last list->first->next = NULL; //初始化链表的长度为0 list->size = 0; } //尾插函数 void push_back(LinkList *list,ElemType x) { //创造一个结点 ListNode *s = (ListNode *)malloc(sizeof(ListNode)); assert(s != NULL); //结点赋值 s->data = x; s->next = NULL; //调整指向关系(包含了空链表的情况) list->last->next = s; list->last = s; //更改链表长度 list->size++; } //头插函数 void push_front(LinkList *list,ElemType x) { //创建一个结点 ListNode *s = (ListNode *)malloc(sizeof(ListNode)); assert(s != NULL); //结点赋值与指向关系 s->data = x; s->next = list->first->next; list->first->next = s; //空链表的情况 if (list->size == 0) { list->last = s; } //更改链表的长度 list->size++; } //尾删函数 void pop_back(LinkList *list) { //空链表的情况下,直接返回 if (list->size == 0) { return; } //非空链表下 //创建一个结点,循环找到尾结点之前的结点 ListNode *p = list->first; while (p->next != list->last) { p = p->next; } //当一个节点的下一个结点=尾结点时,结束循环 //释放尾结点 free(list->last); //调整指向关系 list->last = p; list->last->next = NULL; //更改链表长度 list->size--; } //头删函数 void pop_front(LinkList *list) { //空链表的情况下,直接返回 if(list->size == 0) { return; } //非空链表情况 //调整指向关系 ListNode *p = list->first->next; list->first->next = p->next; //释放 free(p); //链表长度为1时,调整尾结点指向关系 if(list->size == 1) { list->last = list->first; } //更改链表长度 list->size--; } //显示函数 void show_list(LinkList *list) { //创建结点用首元结点初始化 ListNode *p = list->first->next; //循环取值 while (p != NULL) { printf("%d-->",p->data); p = p->next; } //当结点指针域所指向的结点为NULL时结束循环 printf("NULL.\n"); } //按值插入 void insert_val(LinkList *list,ElemType x) { //创建一个结点 ListNode *s = (ListNode*)malloc(sizeof(ListNode)); assert(s != NULL); //结点赋值 s->data = x; s->next = NULL; //循环找位置 ListNode *p = list->first; while (p->next != NULL && p->next->data < x) { p = p->next; } //某个结点指针域所指向的下一个结点为NULL或者其数据域的值>=x结束循环 if (p->next == NULL) { //没有找到所给结点,直接尾插 list->last = s; } //调整指向关系 s->next = p->next; p->next = s; //更改链表长度 list->size++; } //查找 ListNode* find(LinkList *list,ElemType x) { //循环找出 ListNode *p = list->first->next; while (p != NULL && p->data != x) { p = p->next; } //结点为空或者其数据=x结束循环 if (p == NULL) { //链表中没有该数据的情况下 printf("链表中没有这个数据\n"); } return p; } //链表长度 int length(LinkList *list) { return list->size; } //按值删除 void delete_val(LinkList *list,ElemType x) { //链表为空的情况下 if (list->size == 0) { printf("链表为空.\n"); return; } //find函数找到位置 ListNode *p = find(list,x); //链表中没有该数据 if (p == NULL) { printf("要删除的数据不存在.\n"); return; } //删除的是链表中最后一个数字 if (p == list->last) { pop_back(list); } else { //创建结点用要被删除的结点下一个结点初始化 ListNode *q = p->next; //令要被删除的节点的数据等于下一个结点的数据 p->data = q->data; //调整指向关系 p->next = q->next; //删除要被删除的结点下一个结点 free(q); //更改链表长度 list->size--; } printf("删除成功.\n"); } //顺序 void sort(LinkList *list) { //链表为空或者长度为1 if (list->size == 0 || list->size == 1) { return; } //链表不为空或者长度不为1 //创建结点 ListNode *s = list->first->next; ListNode *q = s->next; //拆分链表 list->last = s; list->last->next = NULL; while (q != NULL) { s = q; q = q->next; //循环找位置 ListNode *p = list->first; while (p->next != NULL && p->next->data < s->data) { p = p->next; } //某个结点指针域所指向的下一个结点为NULL或者其数据域的值>=x结束循环 if(p->next == NULL) { //没有找到结点,直接尾插 list->last = s; } //调整指向关系 s->next = p->next; p->next = s; } } //逆值 void resver(LinkList *list) { //链表为空或者长度为1 if (list->size == 0 || list->size == 1) { return; } //链表不为空或者长度不为1 //创建结点 ListNode *p = list->first->next; ListNode *q = p->next; //拆分链表 list->last = p; list->last->next = NULL; while (q != NULL) { //取值头插 p = q; q = p->next; p->next = list->first->next; list->first->next = p; } } //清空 void clear(LinkList *list) { //链表为空 if (list->size == 0) { return; } //链表不为空 ListNode *p = list->first->next; //循环删除结点,先依次删除first->next后面的结点,最后删除first->next结点 while (p != NULL) { list->first ->next = p->next; free(p); p = list->first->next; } //当p为空时,结束循环 list->last = list->first; //更改链表长度 list->size = 0; } //销毁 void destroy(LinkList *list) { clear(list); free(list->first); list->first = list->last = NULL; }
3.单链表的操作结果:
4. 项目
东哥讲完后,会继续补充