项目简介
使用VS2010,利用数据结构的单链表的框架,使用C语言,将每个学生信息(包括姓名、学号、专业、性别等)以单个单链表节点进行存储。用户可以通过后端来对学生信息进行增加、删除、修改、查询,在输入完成后可对学生的成绩进行排序。
项目功能
功能一:设置学生个人信息,包括:姓名、学号、专业、性别、年龄、联系方式、成绩。
功能二:学生信息添加。其中满足:
-
学号唯一,不允许重复
-
姓名只能是汉字,不允许输入数字或英文
-
性别只能是男或女
-
年龄范围:0-100岁
-
输入非法字段或不满足上述条件,提示错误
功能三:学生信息修改;修改时,先查询出某学生信息并显示,然后在对信息进行修改。允许修改某一个字段信息,也允许对整条数据修改。
功能四:学生信息删除,只能是整条数据删除,不允许删除某个字段。
功能五:查找学生的信息,两种方式查找(姓名或学号),如果出现相同姓名,必修全部显示出。
功能六:成绩排序,升序方式。
功能七:查询完整学生名单
功能八:退出系统
项目代码
定义单链表结构 Link_List.h
#ifndef Link_List_h
#define Link_List_h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
/* 单链表类型定义 */
typedef struct
{
char Num[20]; //学号
char Name[50]; //姓名
char Major[60]; //专业
char Sex[5]; //性别
int Age; //年龄
char Tel[20]; //电话
unsigned int Grade; //成绩
}LElemType;
typedef int Status;
/* 顺序表类型定义 */
#define TRUE 1 //真
#define FALSE 0 //假
#define YES 1 //是
#define NO 0 //否
#define OK 1 //通过
#define ERROR 0 //错误
#define SUCCESS 1 //成功
#define UNSUCCESS 0 //失败
#define INFEASIBLE -1 //不可行
#define OVERFLOW -2 //堆栈上溢
#define UNDERFLOW -3 //堆栈下溢
/* 单链表结构体 */
typedef struct LNode
{
LElemType data;
struct LNode* next;
}LNode;
typedef LNode* LinkList; //指向单链表结点的指针
/* 单链表(带头结点)函数列表 */
void PrintElem(LElemType e);
void Print_LinkList(LinkList L);
//(01)初始化单链表
Status InitList(LinkList *L);
//(02)置空单链表L,头结点保留
Status ClearList(LinkList L);
//(03)销毁单链表L,连同通结点一起销毁
void DestroyList(LinkList *L);
//(04)判断单链表L是否为空
Status ListEmpty(LinkList L);
//(05)返回单链表L元素个数
int ListLength(LinkList L);
//(06)算法2.8:用e接收单链表L中第i个元素
Status GetElem(LinkList L, int i, LElemType *e);
//(07)返回单链表L中第一个与e满足Compare关系的元素位序
int LocateElem(LinkList L, LElemType e);
//(10)算法2.9:在单链表L第i个位置之前插入e
Status ListInsert(LinkList L, int i, LElemType e);
//(11)算法2.10:删除单链表L第i个位置的值,并用e接收
Status ListDelete(LinkList L, int i, LElemType *e);
//(12)用Visit函数访问单链表L。
Status ListTraverse(LinkList L, void(*Visit)(LElemType*));
//(10)返回L中指向第i个结点的指针
extern LinkList GetElemPtr(LinkList L, int i);
//输入信息
extern void Input_DataElement(LElemType * elem);
//输出信息
extern void Output_DataElement(LElemType * elem);
//修改个人信息
extern void Rewrite_info(LinkList L,int i,LElemType *e);
定义单链表方法 Link_List.c
#include "Link_List.h"
#define this LElemType
/******************************************************************
*函数名称:Status InitList(LinkList *L)
*功 能:单链表的初始化,生成头结点
*入口参数:LinkList *L
*出口参数:Status
*描 述:
******************************************************************/
Status InitList(LinkList *L)
{
(*L) = (LinkList)malloc(sizeof(LNode));
if( !(*L) )
{
exit(OVERFLOW);
}
(*L)->next = NULL;
return OK;
}
/******************************************************************
*函数名称:DestroyList(LinkList *L)
*功 能:销毁链表
*入口参数:ElemType e
*出口参数:void
*描 述:
******************************************************************/
void DestroyList(LinkList *L) //销毁所有结点
{
LinkList p ;
p = *L;
while(p)
{
p = (*L)->next;
free(*L);
(*L) = p;
}
}
/******************************************************************
*函数名称:ClearList(LinkList L)
*功 能:清空链表,保留头结点
*入口参数:LinkList L
*出口参数:Status
*描 述:
******************************************************************/
Status ClearList(LinkList L) //保留头结点
{
LinkList pre, p;
if(!L)
{
return ERROR;
}
pre = L->next;
while(pre)
{
p = pre->next;
free(pre);
pre = p;
}
L->next = NULL;
return OK;
}
/******************************************************************
*函数名称:ListEmpty(LinkList L)
*功 能:判断链表是否为空
*入口参数:LinkList L
*出口参数:Status
*描 述:
******************************************************************/
Status ListEmpty(LinkList L)
{
if(L!=NULL && L->next==NULL) //链表存在且只有头结点
{
return TRUE;
}
else
{
return FALSE;
}
}
/******************************************************************
*函数名称:ListLength(LinkList L)
*功 能:获得链表的长度
*入口参数:LinkList L
*出口参数:Status
*描 述:
******************************************************************/
int ListLength(LinkList L)
{
LinkList p;
int i;
if(L)
{
i = 0;
p = L->next;
while(p)
{
i++;
p = p->next;
}
}
return i;
}
/******************************************************************
*函数名称:GetElem(LinkList L, int i, ElemType *e)
*功 能:取第i个数据元素的值
*入口参数:LinkList L
*出口参数:Status
*描 述:
******************************************************************/
Status GetElem(LinkList L, int i, LElemType *e)
{
int j;
LinkList p;// = L->next;
j = 1;
p = L->next;
while(p && j<i) //p不为空且还未到达i处
{
j++;
p = p->next;
}
if(!p || j>i) //第i个元素不存在
{
return ERROR;
}
*e = p->data;
return OK;
}
/******************************************************************
*函数名称:LocateElem(LinkList L, ElemType e, Status(Compare)(ElemType, ElemType))
*功 能:查找链表中大于指定数的位置
*入口参数:LinkList L
*出口参数:Status
*描 述:
******************************************************************/
int LocateElem(LinkList L, LElemType e)
{
int i;
LinkList p;
i = -1; //L不存在时返回-1
if(L)
{
i = 0;
p = L->next; //表示第一个结点
while(p)
{
i++;
if(strcmp(p->data.Num,e.Num) == 0)
{
return (i);
}
p = p->next;
}
if(p==NULL) //失配时已经是最后一个结点
{
i=0;
}
}
return i;
}
/******************************************************************
*函数名称:Status ListInsert(LinkList L, int i, ElemType e)
*功 能:单链表插入数据
*入口参数:LinkList *L
*出口参数:Status
*描 述:
******************************************************************/
Status ListInsert(LinkList L, int i, LElemType e)
{
LinkList p, s;
int j;
p = L;
j = 0;
while(p && j<i-1) //寻找第i-1个结点
{
p = p->next;
++j;
}
if(!p || j>i-1)
return ERROR;
s = (LinkList)malloc(sizeof(LNode));
if(!s)
{
exit(OVERFLOW);
}
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
/******************************************************************
*函数名称:Status ListDelete(LinkList L, int i, ElemType *e)
*功 能:单链表删除数据
*入口参数:LinkList *L
*出口参数:Status
*描 述:
******************************************************************/
Status ListDelete(LinkList L, int i, LElemType *e)
{
LinkList pre, p;
int j;
pre = L;
j = 1;
while(pre->next && j<i) //寻找第i个结点,并令pre指向其前驱
{
pre = pre->next;
++j;
}
if(!pre->next || j>i) //删除位置不合理
{
return ERROR;
}
p = pre->next;
pre->next = p->next;
*e = p->data;
free(p);
return OK;
}
/******************************************************************
*函数名称:ListTraverse(LinkList L, void(Visit)(ElemType))
*功 能:
*入口参数:LinkList L
*出口参数:Status
*描 述:
******************************************************************/
Status ListTraverse(LinkList L, void(*Visit)(LElemType*))
{
LinkList p;
if(!L)
{
return ERROR;
}
else
{
p = L->next;
}
while(p)
{
(*Visit)(&(p->data));
p = p->next;
}
return OK;
}
/******************************************************************
*函数名称:GetElemPtr
*功 能:返回L中指向第i个结点的指针
*入口参数:DuLinkList L, int i
*出口参数:int
*描 述:
******************************************************************/
LinkList GetElemPtr(LinkList L, int i)
{
int count;
LinkList p;
if(L && i>0)
{
count = 1;
p = L->next;
while(p && count<i)
{
count++;
p = p->next;
}
if(!p)
{
return p;
}
}
return NULL;
}
/**************************************************************
函数名称:Input_Data_Element
函数功能:输入数据元素
输入参数:数据e
输出参数:
返 回 值:状态
其它说明:
***************************************************************/
void Input_DataElement(LElemType * this)
{
int i = 0;
int j = 0;
printf("输入学号:");
while(1)
{
scanf("%s", this->Num);
j = 0;
i = 0;
while(this->Num[i] !='\0' &&j == 0)
{
if((int)this->Num[i]<48 || (int)this->Num[i]>57)
{
printf("输入学号有误,请重新输入:");
j = 1;
}
i++;
}
if(j==0)
{
break;
}
}
printf("输入姓名:");
while(1)
{
scanf("%s", this->Name);
j = 0;
i = 0;
while(this->Name[i] !='\0' &&j == 0)
{
if(this->Name[i]>=0)
{
printf("输入姓名有误,请重新输入:");
j = 1;
}
i++;
}
if(j==0)
{
break;
}
}
printf("输入专业:");
while(1)
{
scanf("%s", this->Major);
j = 0;
i = 0;
while(this->Major[i] !='\0' &&j == 0)
{
if(this->Major[i]>=0)
{
printf("输入专业有误,请重新输入:");
j = 1;
}
i++;
}
if(j==0)
{
break;
}
}
printf("输入性别:");
while(1)
{
scanf("%s", this->Sex);
if(strcmp(this->Sex,"男")==0||strcmp(this->Sex,"女")==0)
{
break;
}
else
{
printf("输入性别有误,请重新输入:");
}
}
printf("输入年龄:");
while(1)
{
this->Age = ShuRu2();
if(this->Age>100||this->Age<0)
{
printf("输入年龄有误,请重新输入:");
}
else
{
break;
}
}
printf("输入电话:");
while(1)
{
scanf("%s", this->Tel);
j = 0;
i = 0;
while(this->Tel[i] !='\0' &&j == 0)
{
if((int)this->Tel[i]<48 || (int)this->Tel[i]>57)
{
printf("输入电话有误,请重新输入:");
j = 1;
}
i++;
}
if(j==0)
{
break;
}
}
printf("输入成绩:");
while(1)
{
this->Grade = ShuRu2();
if(this->Grade>150||this->Grade<0)
{
printf("输入成绩有误,请重新输入:");
}
else
{
break;
}
}
}
/**************************************************************
函数名称:Output_Data_Element
函数功能:输入数据元素
输入参数:数据e
输出参数:
返 回 值:状态
其它说明:
***************************************************************/
void Output_DataElement(LElemType * this)
{
printf("学号\t%s\t", this->Num);
printf("姓名\t%s\t", this->Name);
printf("专业\t%s\t", this->Major);
printf("性别\t%s\t", this->Sex);
printf("年龄\t%d\t", this->Age);
printf("电话\t%s\t", this->Tel);
printf("成绩\t%d\t", this->Grade);
printf("\n");
}
/***************************************************************
修改学生个人信息 Rewrite_info
***************************************************************/
void Rewrite_info(LinkList L,int i,LElemType *e)
{
int j,k;
int m = 0;
int n= 0;
char num[20];
LinkList p;
p = L->next;
GetElem(L,i,e);
while(p)
{
if(strcmp(p->data.Num,e->Num)==0)
{
break;
}
p = p->next;
}
printf("\n1.修改所有信息项\n2.修改个别信息项\n请选择:");
while(1)
{
k = ShuRu2();
if(k!=1&&k!=2)
{
printf("输入错误,无法更改!\n");
printf("请重新输入:");
}
else
{
break;
}
}
if(k == 1)
{
while(1)
{
printf("请输入修改后的信息:\n");
Input_DataElement(e);
if(CheckReuse1(L,e,p))
{
break;
}
}
}
else
{
printf("请选择修改的个人信息项(1.学号 2.姓名 3.专业 4.性别 5.年龄 6.电话 7.成绩):");
while(1)
{
j = ShuRu2();
if(j <1 || j > 7)
{
printf("输入错误,无法更改!\n");
printf("请重新输入:");
}
else
{
break;
}
}
printf("请输入修改后的信息:");
switch(j)
{
case 1:
while(1)
{
scanf("%s", e->Num);
n = 0;
m = 0;
if(CheckReuse1(L,e,p))
{
while(p->data.Num[m] !='\0' && n==0)
{
if((int)p->data.Num[m]<48 || (int)p->data.Num[m]>57)
{
printf("输入学号有误,请重新输入:");
n = 1;
}
m++;
}
}
else
{
continue;
}
if(n==0)
{
break;
}
}
break;
case 2:
while(1)
{
scanf("%s", p->data.Name);
n = 0;
m = 0;
while(p->data.Name[m] !='\0' &&n == 0)
{
if(p->data.Name[m]>=0)
{
printf("输入姓名有误,请重新输入:");
n = 1;
}
m++;
}
if(n==0)
{
break;
}
}
break;
case 3:
while(1)
{
scanf("%s", p->data.Major);
n = 0;
m = 0;
while(p->data.Major[m] !='\0' &&n == 0)
{
if(p->data.Major[m]>=0)
{
printf("输入专业有误,请重新输入:");
n = 1;
}
m++;
}
if(n==0)
{
break;
}
}
break;
case 4:
while(1)
{
scanf("%s", p->data.Sex);
if(strcmp(p->data.Sex,"男")!=0&&strcmp(p->data.Sex,"女")!=0)
{
printf("输入性别有误,请重新输入:");
}
else
{
break;
}
}
break;
case 5:
while(1)
{
p->data.Age = ShuRu2();
if(p->data.Age>100||p->data.Age<0)
{
printf("输入年龄有误,请重新输入:");
}
else
{
break;
}
}
break;
case 6:
while(1)
{
scanf("%s", p->data.Tel);
n = 0;
m = 0;
while(p->data.Tel[m] !='\0' &&n == 0)
{
if((int)p->data.Tel[m]<48 || (int)p->data.Tel[m]>57)
{
printf("输入电话有误,请重新输入:");
n = 1;
}
m++;
}
if(n==0)
{
break;
}
}
break;
case 7:
while(1)
{
p->data.Grade = ShuRu2();
if(p->data.Grade>150||p->data.Grade<0)
{
printf("输入成绩有误,请重新输入:");
}
else
{
break;
}
}
break;
}
}
printf("修改成功!\n");
printf("修改后的名单为:\n");
ListTraverse(L,Output_DataElement);
}
/*************************************************************
修改学号查重
*************************************************************/
Status CheckReuse1(LinkList L,LElemType *e,LinkList p1)
{
LinkList p;
int i = 0;
i = LocateElem(L,p1->data);
ListDelete(L,i,&p1->data);
if(!L)
{
return (ERROR);
}
else
{
p = L->next; //p指向头结点,正向访问链表
}
while(p)
{
if(strcmp(p->data.Num,e->Num) == 0)
{
printf("该学号已被使用,请重新输入!\n");
return ERROR;
}
p = p->next;
}
ListInsert(L,i,*e);
return (OK);
}
/*************************************************************
学号查重
*************************************************************/
Status CheckReuse(LinkList L,LElemType *e)
{
LinkList p;
if(!L)
{
return (ERROR);
}
else
{
p = L->next; //p指向头结点,正向访问链表
}
while(p)
{
if(strcmp(p->data.Num,e->Num) == 0)
{
printf("该学号已被使用,请重新输入!\n");
return ERROR;
}
p = p->next;
}
return (OK);
}
/*************************************************************
输入学生学号获得位置i
*************************************************************/
int ShuRu1(LinkList L)
{
LElemType e;
int i;
printf("请输入该学生的学号:");
scanf("%s",&e.Num);
i = LocateElem(L, e);
while(i == 0)
{
printf("输入错误,未查询到该学生!\n");
printf("请重新输入:");
scanf("%s",&e.Num);
i = LocateElem(L, e);
}
GetElem(L,i, &e);
printf("该学生信息为:\n");
Output_DataElement(&e);
return i;
}
/*****************************************************************
交换次序
******************************************************************/
void Swap(LinkList L,LElemType *tmp1,LElemType *tmp2,LElemType *e)
{
int i,j;
i = LocateElem(L,*tmp1);
j = LocateElem(L,*tmp2);
ListDelete(L, i,e);
ListInsert(L, j,*e);
ListDelete(L, j-1,e);
ListInsert(L, i,*e);
}
/*****************************************************************
冒泡排序
******************************************************************/
void Bubble_sort(LinkList L ,LElemType *e,LElemType *tmp1,LElemType *tmp2)
{
int i,j,k;
for(i = 1;i<ListLength(L);i++)
{
for(j = 1;j <ListLength(L)-i+1;j++)
{
GetElem(L,j,tmp1);
GetElem(L,j+1,tmp2);
if (tmp1->Grade > tmp2->Grade)
{
Swap(L,tmp1,tmp2,e);
}
}
}
}
/*****************************************************************
比较学号
******************************************************************/
Status Cmp_2(LinkList tmp1,LinkList tmp2)
{
return strcmp(tmp1->data.Num,tmp2->data.Num);
}
/*****************************************************************
判断是否有学生
******************************************************************/
Status ListEmpty1(LinkList L)
{
if(ListEmpty(L))
{
printf("提示:现在名单里没有学生,仅可使用功能1、8\n");
return ERROR;
}
else
{
return YES;
}
}
/*****************************************************************
输入整型i
******************************************************************/
Status ShuRu2()
{
char a [8];
int i,k;
int j = 0;
while(1)
{
scanf(" %s",&a);
i = 0;
j = 0;
while(a[i]!='\0'&&j==0)
{
if((int)a[i]<48 || (int)a[i]>57)
{
printf("输入错误,请重新输入:");
j = 1;
}
i++;
}
if(j==0)
{
break;
}
}
k = i;
while(i>0)
{
j += ((int)a[i-1]-48)*pow(10,k-i);
i--;
}
return j;
}
/*****************************************************************
在无学生的情况下,输入正确的功能号
******************************************************************/
Status ShuRu3(LinkList L,int i)
{
while(1)
{
if(ListEmpty(L)&& i!=1 && i!=8)
{
printf("现在名单里没有学生,仅可使用功能1、8\n");
printf("请重新输入:");
i = ShuRu2();
}
else
{
break;
}
}
return i;
}
/*************************************************************
输入学生姓名获得位置i
*************************************************************/
void ShuRu4(LinkList L)
{
LElemType e;
int *i;
int j;
int k,m;
printf("请输入该学生的姓名:");
scanf("%s",&e.Name);
while(!LocateElemName1(L, e))
{
printf("输入错误,未查询到该学生!\n");
printf("请重新输入:");
scanf("%s",&e.Name);
}
printf("该学生信息为:\n");
LocateElemName2(L, e);
}
/******************************************************************
*函数名称:LocateElem(LinkList L, ElemType e, Status(Compare)(ElemType, ElemType))
*功 能:查找链表中等于指定数的位置
*入口参数:LinkList L
*出口参数:Status
*描 述:
******************************************************************/
int LocateElemName1(LinkList L, LElemType e)
{
int i = 0;
LinkList p;
if(L)
{
p = L->next; //表示第一个结点
while(p)
{
i++;
if(strcmp(p->data.Name,e.Name) == 0)
{
return OK;
}
p = p->next;
}
return ERROR;
}
}
/******************************************************************
*函数名称:LocateElem(LinkList L, ElemType e, Status(Compare)(ElemType, ElemType))
*功 能:查找链表中等于指定数的位置
*入口参数:LinkList L
*出口参数:Status
*描 述:
******************************************************************/
int LocateElemName2(LinkList L, LElemType e)
{
int i = 0;
int count = 0;
LinkList p;
if(L)
{
p = L->next; //表示第一个结点
while(p)
{
i++;
if(strcmp(p->data.Name,e.Name) == 0)
{
Output_DataElement(&p->data);
count++;
}
p = p->next;
}
if(!count)
{
return NULL;
}
}
}
主函数 main.c
#include"Link_List.h"
void main()
{
LinkList L;
LElemType e,tmp1,tmp2;
int i = 1 ;
int number = 0;
int count = 1;
float avg = 0;
char a[2];
int j = 0;
InitList(&L); //初始化
printf(" **********************************学生管理系统**********************************\n");
while(1)
{
printf("\n ------------------------------菜单------------------------------\n");
printf("\n 1.添加学生\t2.修改学生信息\t3.删除学生\t\n\n 4.查询学生个人信息(学号查询)\t5.查询学生个人信息(姓名查询)\t\n\n 6.查询成绩排名\t7.查询完整名单\t8.退出系统\t\n\n");
printf(" *******************************************************************************\n\n");
ListEmpty1(L);
printf("请输入想要进行的操作:");
i = ShuRu2();
i = ShuRu3(L,i);
switch(i)
{
case 1:
//增加学生
printf("输入要增加学生的人数:");
while(1)
{
number = ShuRu2(); //获得增加学生人数
if(number>=1)
{
break;
}
printf("增加人数有误,请重新输入:");
}
for(i = 1;i<=number;)
{
printf("请输入第%d个学生的信息:\n",count);
Input_DataElement(&e);
if(CheckReuse(L,&e))
{
ListInsert((L),count,e);
printf("添加成功!添加学生信息:\n");
Output_DataElement(&e);
count++;
i++;
}
}
break;
case 2:
if(!ListEmpty1(L))
{
break;
}
//修改学生信息
i = ShuRu1(L);
Rewrite_info(L,i,&e);
break;
case 3:
if(!ListEmpty1(L))
{
break;
}
//删除学生
ListEmpty1(L);
i = ShuRu1(L);
printf("是否要删除该学生(y/n)?");
j = 0;
while(j==0)
{
scanf("%s",a);
if(strcmp(a,"y")==0)
{
ListDelete((L),i,(&e)); //删除第i个学生
printf("删除成功!");
count--;
j = 1;
}
else if(strcmp(a,"n")==0)
{
j = 1;
break;
}
else
{
printf("输入错误,请重新输入:");
}
}
if(ListLength(L) == 0)
{
printf("该名单无任何学生信息!\n");
break;
}
break;
case 4:
if(!ListEmpty1(L))
{
break;
}
//查询学生个人信息(学号)
ShuRu1(L);
break;
case 5:
if(!ListEmpty1(L))
{
break;
}
//查询学生个人信息(姓名)
ShuRu4(L);
break;
case 6:
if(!ListEmpty1(L))
{
break;
}
//成绩排名
Bubble_sort(L ,&e,&tmp1,&tmp2);
ListTraverse(L,Output_DataElement);
break;
case 7:
//查询完整名单
if(ListEmpty(L))
{
printf("该名单无任何学生信息!\n");
break;
}
if(!(&L))
{
printf("该名单不存在!\n");
break;
}
ListTraverse(L,Output_DataElement);
break;
case 8:
//退出系统
system("pause");
exit(0);break;
default:
printf("输入错误,请重新输入!\n");
}
printf("\n");
printf("**********************************************************************************************************************\n\n");
}
system("pause");
}
界面实现效果
主界面
功能一:添加学生
功能二:修改学生信息
(1)修改所有信息项
(2)修改个别信息项
功能三:删除学生(P.S.删除前先再添加点学生)
功能四:查询学生个人信息(根据学号查询)
功能五:查询学生个人信息(根据学生姓名查询)
当出现学生姓名相同的情况,显示所有学生信息。
功能六:查询成绩排名
功能七:查询学生名单
功能八:退出系统
试错:
(1)当刚开始进入系统,还未进行学生信息录入时,仅能使用功能一和功能八。
(2)功能一添加学生里,当添加信息不符合要求(要求在项目功能里)时,系统返回提示语句,并让用户重新输入信息。
(3)功能三里,当输入想要删除的学生学号时,系统返回该学生具体信息,并再次询问是否删除,系统根据输入结果进行删除或保留学生信息。
(4)功能四、五里,当要查询的学生学号或姓名不存在时,系统返回提示语句,并让用户重新输入要查询的学生学号或姓名。
项目改进点
1.项目未接入数据库。可以在后期接入数据库保存数据。
2.项目有些步骤过于死板,例如当添加学生时,输入学号如果一直不满足要求,就会一直要求输入,直至输入正确形式的学号。可以在改进为:当错误输入累计三次时,系统提示是否继续进行此操作,如果选择是,则返回上一级,如果选择不是,则系统提醒输入要求并继续进行输入。
3.项目仅在终端显示,过于简略。可以在后期以页面的形式展现。