数据结构课程设计-班级考勤管理系统

写这个博客,主要是为了总结一下,之前写过的东西,方便以后回来看看,写得不好,勿喷!!!

题目描述:
设计一个对本班所有人员进行考勤的管理系统,要求系统管理员(班长、学委或纪律委员)可以查询、添加、删除、修改和统计考勤信息,每条考勤信息至少包括:编号,学号、姓名,日期,地点,当天第几节课,性质(只记录迟到,缺席和请假三种非出席情况)等,非管理员(本班所有人员)可以查询和统计本班考勤信息。查询和统计可以按姓名、日期、性质等分类查询,查询结果按一定顺序排序后显示(利用第7章相关排序算法)。

基本功能:
程序中的相关人员列表、考勤情况等都必须采用所学过的一种数据结构(链表、栈、队列、树等)存储,不能全部只使用数组。所有功能的操作是对数据结构(数组或链表等)中的数据进行操作。
每一个功能模块需要划分多个子模块,使用各自不同的结构体来储存不同的信息,实现信息的添加、删除、查询、修改和统计等操作。其他信息根据功能需求可以自行设计。
(1) 有良好的输出界面。
(2) 系统管理员的登录功能,非管理员(班级所有成员)的注册登录功能。
(3) 管理员和非管理员必须为本班人员(与自己班级人员名单为准)。
(4) 管理员对信息的添加、修改、删除、查询和统计(按不同情况查询或统计,结果按顺序排序显示,如统计某人所有的缺席或迟到情况、按日期统计某天所有缺席或迟到的人员(结果按学号显示)、显示所有缺席或迟到人员(结果按次数从多到少显示等等)。
(5) 非管理人员只有查询和统计功能。
(6) 系统可以查看全班所有人员名单,且答辩时系统至少已经录入10条以上迟到、缺席和请假信息。

扩展功能要求(不限以下3条):
(1) 在考勤信息中增加确认功能,班级成员可以对考勤情况进行确认。
(2) 运行文件对各种信息进行合理的保存和读取。
(3) 对考勤系统进行功能扩展,使其查询、统计等功能更合理、更方便、更具使用性。

我还是按照我之前的套路,一步一步地分析题目的需求,方便之后的代码编写。

开发平台:Dev-C++ 5.11

考勤数据表MySQL 考勤数据表设计_vscode

步骤一:分析功能需求

班级考勤管理系统,可以记录本班同学的考勤信息,实现了管理员登录功能和非管理员登录和注册功能,非本班人员不能登录和注册。

管理员登录成功,能够实现的功能有:1、查看个人信息2、修改密码3、确认考勤信息4、浏览所有学生的信息5、浏览所有考勤信息6、添加考勤记录7、删除考勤记录8、修改考勤记录9、查询考勤记录10、统计考勤信息11、重置其它学生密码。

非管理员登录成功,能够实现的功能有:1、查个人信息2、修改密码3、确认考勤信息4、浏览所有考勤信息5、查询考勤信息6、统计考勤信息。

注册功能只限非管理员和本班同学注册,管理员不用注册。

步骤二:分析业务逻辑

设计整个系统的功能逻辑,大概画出整体的功能流程图,方便代码编写。

考勤数据表MySQL 考勤数据表设计_vscode_02


分析完业务逻辑之后,我们还需要考虑三个问题:1、数据的保存2、数据的展示3、用户的交互。

数据保存:

从题目来看数据应保存在文件中,我选择的是保存在txt文件中。

数据展示:

数据的可视化我是直接在控制台中进行输出。

用户交互:

用户的输入输出都是通过控制台,进行交互的。

步骤三:编写代码

定义数据结构:

//结构体   学生的账号
struct ID
{
	int role;         //身份标志,0为非管理员,1为管理员 
	char id [15];     //账号 
	char name [10];   //姓名 
	char pwd [15];    //密码 
	int late;         //迟到次数 
	int absent;       //缺席次数 
	int vacation;     //请假次数 
	int amount;       //缺勤次数 
} All_ID[55];         //定义55个账号管理
//结构体    考勤信息 
typedef struct node * pointer; //结点指针类型 
struct node                    //结点结构 
{
	int number;                //编号 
	char student_ID [15];      //学号 
	char name [10];            //名字 
	char date [10];            //日期 
	char address [10];         //地址 
	char course [10];          //课程 
	char reason [10];          //性质 
	char check [10];           //确认情况 
	
	pointer next;              //指针域 
};
typedef pointer lklist;        //单链表类型,即头指针类型

准备数据,(在工程目录下新建两个txt文件,用于存放数据。一个是ID.txt,用于存放所有同学的基本信息。另一个是考勤.txt,用于存放所有的考勤信息。)
注意:
每行数据用英文格式的空格隔开。

考勤数据表MySQL 考勤数据表设计_考勤数据表MySQL_03


考勤数据表MySQL 考勤数据表设计_vscode_04


接下来,编写各功能函数~~~

1、void readFile_ID(struct ID All_ID[]):该函数用于读取所有帐号的信息,在程序开始时,将所有的帐号信息导入到程序中,用于后续的操作。

//读账号文件函数 
void readFile_ID(struct ID All_ID[])
{
	int i=0;
	FILE *fp;
	fp=fopen("ID.txt","r");    
	while(!feof(fp)) 
	{
		fscanf(fp,"%d %s %s %s %d %d %d %d\n",&All_ID[i].role,All_ID[i].id,All_ID[i].name,All_ID[i].pwd,&All_ID[i].late,&All_ID[i].absent,&All_ID[i].vacation,&All_ID[i].amount);
		i++;           
		flag++;      //用于记录有多少个账号 
	}
	fclose(fp);     //关闭文件 
	
}

2、void writeFile_ID(struct ID All_ID[],int i):该函数用于存储所有帐号的信息,在程序运行过程中,若修改了帐号信息或考勤信息被修改后,将重新保存好信息。

//写账号文件函数 
void writeFile_ID(struct ID All_ID[],int i)
{
	FILE *fp;
	int j;
	fp=fopen("ID.txt","w");
	for(j=0;j<i;j++) 
	{
		fprintf(fp,"%d %s %s %s %d %d %d %d\n", All_ID[j].role,All_ID[j].id,All_ID[j].name,All_ID[j].pwd,All_ID[j].late,All_ID[j].absent,All_ID[j].vacation,All_ID[j].amount );   
	}
	fclose(fp);  //关闭文件
	
}

3、void browse(struct ID All_ID[],int i):该函数用于浏览所有帐号信息,主要用于管理员查看所有人的信息,方便管理和统计。

//浏览所有账号函数 
void browse(struct ID All_ID[],int i)
{
	int j=0;
	printf("_________________________________________________________________________________________\n");
	printf("      账号           姓名        密码      迟到/次    缺席/次   请假/次    缺勤/次\n");
	for( j=0 ; j<i ; j++ )
	{
		printf("  %-16s  %-11s %-13s %-10d %-9d %-10d %-11d\n", All_ID[j].id,All_ID[j].name,All_ID[j].pwd,All_ID[j].late,All_ID[j].absent,All_ID[j].vacation,All_ID[j].amount );
	}
	printf("_________________________________________________________________________________________\n");
	
}

4、void init( struct ID All_ID[] , lklist head ):该函数用于初始化统计考勤信息,在程序开始时,将考勤信息按每个人分类别统计好,迟到有多少次,缺席有多少次,请假有多少次,每个人一共缺勤了多少次。用于后续的统计排序查看。

//初始化统计考勤信息 
void init( struct ID All_ID[] , lklist head )
{
	int i=0;	
	int a=0,b=0,c=0;    // a用于记录迟到的人数,b用于记录缺席的人数,c用于记录请假的人数 
	pointer p;
 		
	for(i=0;i<flag;i++)
	{
		a=0;b=0;c=0;
		p=head->next;
		while(p!=NULL)
		{
			if( strcmp(All_ID[i].id,p->student_ID)==0 && strcmp(p->reason,"迟到")==0 )
			{
				a++;   //如果存在迟到的学生,a就自增 1 
			}
			else if( strcmp(All_ID[i].id,p->student_ID)==0 && strcmp(p->reason,"缺席")==0 )
			{
				b++;   //如果存在缺席的学生,b就自增 1 
			}
			else if( strcmp(All_ID[i].id,p->student_ID)==0 && strcmp(p->reason,"请假")==0 )
			{
				c++;   //如果存在请假的学生,c就自增 1 
			}
			p=p->next;		
		}
		All_ID[i].late = a;         //统计迟到人数 
		All_ID[i].absent = b;       //统计缺席人数 
		All_ID[i].vacation = c;     //统计请假人数 
		All_ID[i].amount = All_ID[i].late + All_ID[i].absent + All_ID[i].vacation;   //统计缺勤人数 
	
	}
		
}

5、lklist creat():该函数用于读取所有的考勤信息,在程序开始时,将所有的考勤信息导入到程序中,以尾插法的方式生成一条不带头结点的链表,并返回头指针。

//创建单链表,导入学生考勤信息   尾插法 
lklist creat()
{
	pointer head,rear,s;
	head = new node;
	rear = head;
   
	FILE *fp;
	fp=fopen("考勤.txt","r");    
	while(!feof(fp)) 
	{
		s = new node;
		fscanf(fp,"%d %s %s %s %s %s %s %s\n",&s->number,s->student_ID,s->name,s->date,s->address,s->course,s->reason,s->check);
		rear->next = s;
		rear = s;      
		count++;      //用于记录有多少条考勤信息 
	}	
 	rear->next = NULL;
 	fclose(fp);       //关闭文件 
 	
 	return head;
}

6、void writeFile(lklist head):该函数用于存储所有的考勤信息,在程序运行过程中,若对考勤信息进行了改动,修改后,将所有考勤信息重新保存到文件中。

//将考勤信息写入文件 
void writeFile(lklist head)
{	
	FILE *fp;
	fp=fopen("考勤.txt","w"); 
	
	int number=1;	
	pointer p;
	p=head->next;
	
	while(p!=NULL)
	{
		fprintf(fp,"%d %s %s %s %s %s %s %s\n", number,p->student_ID,p->name,p->date,p->address,p->course,p->reason,p->check );   
		p=p->next;
		number++;
	}
	fclose(fp);  //关闭文件
	
}

7、void cout(lklist head):该函数用于浏览所有的考勤信息,主要输出已经输入的考勤信息以及后期修改后的考勤信息。

//输出所有考勤信息 
void cout(lklist head)
{
	pointer p;
 	p=head->next;
 	
 	printf("______________________________________________________________________________________________________________________\n");
	printf("   编号          学号           姓名         日期        地点         课程节数       缺勤性质     确认情况\n");
 	while(p!=NULL)
	{
  		printf("    %-5d    %-15s   %-10s   %-9s   %-12s   %-13s   %-9s   %-10s\n",p->number,p->student_ID,p->name,p->date,p->address,p->course,p->reason,p->check);
  		p=p->next;
 	}
 	printf("______________________________________________________________________________________________________________________\n\n");
}

8、pointer get(lklist head,int i):该函数用于按序号查找想要查找的考勤信息,并返回该结点,主要用于其它功能对考勤信息的操作。

//按序号查找 
pointer get(lklist head,int i)
{
	int j;
	pointer p;
	if(i==0)  return head;
	if(i<0)  return NULL;
	j=0;
	p=head->next;
	while(p!=NULL)
	{
		j++;
		if(j==i)  break;
		p=p->next;
	}
	return p;
}

9、int Delete(lklist head , int i):该函数用于删除特定的考勤信息,主要根据输入的序号数,查找到该考勤信息并将其删除,删除成功返回1,否则返回0。

//删除运算 
int Delete(lklist head , int i)
{
	pointer p,q;
	q=get(head,i-1);
	
	if(q==NULL||q->next==NULL)
	{
		printf("非法删除位置\n");
		return 0;
	}
	
	p=q->next;
	q->next=p->next;
	delete p;
	
	return 1;
}

10、int no_Manager_Langing(struct ID All_ID[],int i):该函数用于非管理员登录,根据输入的帐号和密码,如果密码输入正确,则返回1,否则返回0。登录成功后,调用非管理员主菜单的函数,否则输出密码错误,登录失败。

//非管理员登陆函数  登陆成功返回 1 ,登陆失败返回 0 
int no_Manager_Langing(struct ID All_ID[],int i)
{
	char id [15];       //用于存放输入的账号 
	char pwd [15];      //用于存放输入的密码 
	int j = 0;
	int sign = 0;       //用于记录密码是否正确 
	
	printf("\n\n非管理员登陆\n");
	printf("请输入账号:");
	scanf("%s",id);
	printf("请输入密码:"); 
	scanf("%s",pwd);
	
	for(j=0;j<i;j++)
	{
		if( All_ID[j].role==0 && strcmp(id,All_ID[j].id)==0 && strcmp(pwd,All_ID[j].pwd)==0 )
		{
			strcpy(ID,id);
			sign = 1;   //密码正确,令sign为 1
			break;
		}
		else
		{
			sign = 0;   //密码错误,令sign为 0 
		}
	}
		
	return sign;	
}

11、int no_Manager_Login(struct ID All_ID[],int i):该函数用于非管理员和本班同学的注册,根据输入的帐号判断是否是非管理员和本班同学,若是,则注册成功,返回1,否则返回0。

//非管理员注册函数   注册成功返回 1 ,注册失败返回 0 
int no_Manager_Login(struct ID All_ID[],int i)
{
	char id [15];        //用于存放输入的账号 
	char pwd [15];       //用于存放输入的密码 
	char repwd [15];     //用于存放再次输入的密码 
	int j = 0;
	int sign = 0;        //用于记录注册是否成功 
	
	printf("\n非管理员注册\n");
	printf("请输入学号:");
	scanf("%s",id);
	printf("请输入密码:");
	scanf("%s",pwd);
	printf("请再次确认密码:");
	scanf("%s",repwd);
	
	for(j=0;j<i;j++)
	{
		if( All_ID[j].role==0 && strcmp(id,All_ID[j].id)==0 && strcmp(pwd,repwd)==0 )
		{
			strcpy(All_ID[j].pwd,pwd);
			sign = 1;   //注册成功,令sign为 1 
			break;
		}
		else 
		{
			sign = 0;   //注册失败,令sing为 0 
		}
	}
	
	return sign;
}

12、void mangerMenu( struct ID All_ID[] , lklist head ):该函数为管理员主菜单输出函数,可以根据不同的选择,实现不同的功能。主要有,查看个人信息功能、修改密码功能、确认考勤信息功能、浏览所有学生的信息功能、浏览所有考勤信息功能、添加考勤信息功能、删除考勤信息功能、修改考勤信息功能、查询考勤信息功能、统计考勤信息功能。

//管理员菜单
void mangerMenu( struct ID All_ID[] , lklist head )
{
	if(warning( head )!=0)
	{
		printf("\n你存在待确认的考勤信息!\n请前往确认!\n");
	}
	
	int chose=10;
	while(chose!=0)
	{
		printf("\n           管理员菜单            \n");
		printf("***********************************\n");
		printf("*          1.查看个人信息         *\n");
		printf("*          2.修改密码             *\n");
		printf("*          3.确认考勤信息         *\n");
		printf("*          4.浏览所有学生的信息   *\n"); 
		printf("*          5.浏览所有考勤信息     *\n");
		printf("*          6.添加考勤记录         *\n");				
		printf("*          7.删除考勤记录         *\n");
		printf("*          8.修改考勤记录         *\n");
		printf("*          9.查询考勤信息         *\n");
		printf("*          10.统计考勤信息        *\n");
		printf("*          11.重置其它学生密码    *\n");
		printf("*          0.退出                 *\n");
		printf("***********************************\n");
		printf("请输入功能的选项:");
		scanf("%d",&chose);	
		
		switch(chose)
		{
			case 1: search( All_ID , head ) ;break;   //查看个人信息 
			
			case 2: if( changePwd(All_ID)==1 ) //判断修改密码是否成功 
					{
						printf("\n\n修改成功!\n\n");
					}
					else
					{
						printf("\n输入有误!请重新输入!\n\n");
					}
					writeFile_ID(All_ID,flag); //修改密码后,重新写入文件 
					break;
					
			case 3: checkMessage( head );      //确认考勤信息 
					 writeFile( head );        //确认考勤信息后,重新写入文件 
					 break;
					  
			case 4: browse( All_ID , flag ) ;break;   //浏览所有学生的信息 
			
			case 5: cout( head ) ;break;              // 浏览所有考勤信息
				
			case 6: insert(head,count) ;       //添加考勤信息 
					init( All_ID , head );     //添加考勤信息后,重新统计考勤信息 
					count++;                   //添加考勤信息后,考勤记录加 1 
					break;
			
			case 7: deletes( head );           //删除考勤记录  
					count--; 
					init( All_ID , head );     //删除考勤记录后,重新统计考勤信息 
					writeFile( head );         //删除考勤记录后,重新写入文件 
					break;
			
			case 8: modify( head );            //修改考勤记录
					init( All_ID , head );     //修改考勤记录后,重新统计考勤信息 
					writeFile( head );         //修改考勤记录后,重新写入文件 
					break;
					
			case 9: inquiryMenu( head ) ;break;         //查询考勤信息 
			
			case 10: statisticsMenu( All_ID ) ;break;   //统计考勤信息 
		
			case 11: resetPwd(All_ID);                  //重置其它学生密码
					 writeFile_ID(All_ID,flag);         //修改密码后,重新写入文件 
					 break;
		
			case 0: printf("\n欢迎下次使用!\n\n");
					exit(0) ;
					break;
			
			default:printf("您输入的数据有误!\n请重新输入!\n");
		}
			
	}
	
}

13、void no_managerMenu( struct ID All_ID[] , lklist head ):该函数为非管理员主菜单输出函数,可以根据不同的选择,实现不同的功能。主要有,查看个人信息功能、修改密码功能、确认考勤信息功能、浏览所有考勤信息功能、查询考勤信息功能、统计考勤信息功能。

//非管理员菜单
void no_managerMenu( struct ID All_ID[] , lklist head )
{
	if(warning( head )!=0)
	{
		printf("\n你存在待确认的考勤信息!\n请前往确认!\n");
	}
	
	int chose=0;
	while(chose!=7)
	{
		printf("\n       非管理员菜单          \n");
		printf("*******************************\n");
		printf("*       1.查看个人信息        *\n");
		printf("*       2.修改密码            *\n");
		printf("*       3.确认考勤信息        *\n");
		printf("*       4.浏览所有考勤信息    *\n");
		printf("*       5.查询考勤信息        *\n");	
		printf("*       6.统计考勤信息        *\n");
		printf("*       7.退出                *\n");
		printf("*******************************\n");	 	
		printf("请输入功能的选项:");
		scanf("%d",&chose);
	
		switch(chose)
		{
			case 1: search( All_ID , head ) ;break;     //查看个人信息
			
			case 2: if( changePwd(All_ID)==1 )   //修改密码
					{
						printf("\n\n修改成功!\n\n");
					}
					else
					{
						printf("\n输入有误!请重新输入!\n\n");
					}
					writeFile_ID(All_ID,flag);
					break;
			
			case 3: checkMessage( head );      //确认考勤信息 
					writeFile( head );         //确认完考勤信息,写入文件 
					break;
			
			case 4: cout( head ) ;break;       // 浏览所有考勤信息
			
			case 5: inquiryMenu( head ) ;break;        //查询考勤信息
			
			case 6: statisticsMenu( All_ID ) ;break;   //统计考勤信息 
			
			case 7: printf("\n欢迎下次使用!\n\n");
					exit(0); 
					break;
			
			default:printf("您输入的数据有误!\n请重新输入!\n");
		}
	
	}
	
}

文章篇幅有限完整的代码我放到了文章的最后~~~有兴趣的同学可以看看

14、void checkMessage( lklist head ):该函数用于确认个人的考勤信息,根据实际情况,输出所有的待确认的考勤信息,如果考勤信息无误,则选择确认,若没有待确认的考勤信息,则不会输出。

//确认考勤信息 
void checkMessage( lklist head )
{
	int sign=0;   //记录是否存在未确认的考勤信息 
	char chose;
	pointer p;
 	p=head->next;
 	
 	printf("\n______________________________________________________________________________________________________________________\n");  
	printf("   编号          学号           姓名         日期        地点         课程节数       缺勤性质     确认情况\n");
 	while(p!=NULL)
	{
		if( strcmp(ID,p->student_ID)==0 && strcmp(p->check,"待确认")==0 )   //判断是否存在待确认的考勤信息 
		{
			sign++;
			printf("    %-5d    %-15s   %-10s   %-9s   %-12s   %-13s   %-9s   %-10s\n",p->number,p->student_ID,p->name,p->date,p->address,p->course,p->reason,p->check);
		}
  		p=p->next;
 	}
 	printf("______________________________________________________________________________________________________________________\n");
 	
	if(sign!=0)   //判断是否存在考勤信息,如果存在,则执行是否确认该考勤信息 
	{
		printf("是否确认该考勤信息(Y/N):"); 
		getchar();           //用于清除回车
		scanf("%c",&chose);  //需要输入Y或者N
		
		while(chose!='Y'&&chose!='N')      //容错处理,用于判断是否是Y或者N,不是则需要重新输入
		{
			printf("输入错误,请重新输入(Y/N):");
			getchar();           //用于清除回车
			scanf("%c",&chose);  //需要重新输入Y或者N
		}
		
		if(chose=='Y')   
		{
			p=head->next;   //将指针重新指向头部 
			while(p!=NULL)
			{
				if( strcmp(ID,p->student_ID)==0 && strcmp(p->check,"待确认")==0 )
				{
					strcpy(p->check,"已确认");   //确认考勤信息 
				}
  				p=p->next;
 			}
 			printf("已确认!\n"); 
		}
		else
		{
			printf("已退出!\n");
		}	
	}
	else
	{
		printf("没有待确认的考勤信息!\n\n");
	}

}

15、void modify( lklist head ):该函数用于修改考勤信息,根据实际情况,输入想要修改的考勤信息编号,该函数会提供一个菜单功能,选择某一项信息进行修改,包括日期、地点、课程节数和性质。修改成功会输出修改后的信息。

//修改考勤信息
void modify( lklist head )
{
	pointer p;	
	int a=0;         //用于记录,是否找到想要修改的考勤信息
	int b=0;         //用于是否退出修改菜单 
	int sign=0;      //用于记录,是否修改完考勤信息 
	int chose=0;     //用于菜单的选择功能 
	int numbers=0;   //用于存储输入的编号 
	
	cout( head );	
	while(a==0)
	{
		printf("请输入想要修改的考勤信息的编号:");
		scanf("%d",&numbers);
		
		p=head->next;
		while(p!=NULL)
		{
			if(numbers==p->number)
			{
				a++;
				printf("______________________________________________________________________________________________________________________\n");
				printf("   编号          学号           姓名         日期        地点         课程节数       缺勤性质     确认情况\n");
				printf("    %-5d    %-15s   %-10s   %-9s   %-12s   %-13s   %-9s   %-10s\n",p->number,p->student_ID,p->name,p->date,p->address,p->course,p->reason,p->check);
				printf("______________________________________________________________________________________________________________________\n\n");	
				break;
			}
  			p=p->next;
 		}
		if(a==0)       //对没有查询到信息进行输出
		printf("\n您想要修改的信息不存在!  请重新输入!\n\n");		
	}
	
	printf("\n          选择修改的类型             \n");
	printf("***************************************\n"); 
	printf("*           1   修改日期              *\n");
	printf("*           2   修改地点              *\n");
	printf("*           3   修改课程节数          *\n");
	printf("*           4   修改性质              *\n");
	printf("*           5   退出                  *\n");
	printf("***************************************\n"); 
	while(b==0)
	{
		printf("请输入修改的类型:");
		scanf("%d",&chose);
		switch(chose)
		{
			case 1: printf("请输入修改后的日期(**月**号):");
					scanf("%s",p->date);
					b++;
					sign++;
					break;
			
			case 2: printf("请输入修改后的地点:");
					scanf("%s",p->address);
					b++;
					sign++;
					break;
			
			case 3: printf("请输入修改后的课程节数:");
					scanf("%s",p->course);
					b++;
					sign++;
					break;
			
			case 4: printf("请输入修改后的性质(迟到/缺席/请假):");
					scanf("%s",p->reason);
					b++;
					sign++;
					break;
			
			case 5: printf("已退出修改!\n");
					b++;
					break;
			
			default:printf("您输入的数据有误! 请重新输入!\n\n");	
		}	
	} 
	if(sign!=0)
	{
		printf("______________________________________________________________________________________________________________________\n");
		printf("   编号          学号           姓名         日期        地点         课程节数       缺勤性质     确认情况\n");
		printf("    %-5d    %-15s   %-10s   %-9s   %-12s   %-13s   %-9s   %-10s\n",p->number,p->student_ID,p->name,p->date,p->address,p->course,p->reason,p->check);
		printf("______________________________________________________________________________________________________________________\n");	
		printf("修改成功!\n\n");
	}
	
}

步骤四:功能测试

就随便测了几个功能,边测边改bug

考勤数据表MySQL 考勤数据表设计_考勤数据表MySQL_05


考勤数据表MySQL 考勤数据表设计_数据_06

考勤数据表MySQL 考勤数据表设计_c语言_07

总结

程序优点:基本实现要求的所有功能,程序能较好地运行,而且用户输入错误时有保障机制,能让用户重新输入数据。在运行过程中,有良好的输出界面,能清晰地显示。每次的输入都有提醒,输入有误时,也有保障机制,能让程序稳定执行下去。每个子功能,都存在子菜单,为实现不同的功能,操作方便。在内部代码的实现上,功能分明,思路清晰。实现了所需的功能操作和更加有序的程序代码。将不同的功能封装在不同的函数中,调用调试方便,也方便后期的修改。在使用时,简单方便,通俗易懂,效率高。

程序不足:一、在时间复杂度上,时间复杂度有点高,优化程度不足,多处使用循环嵌套语句。二、在空间维度上,定义了不少的全局变量,用于统计数据和记录,占用了不少的内存空间。不是全部的数据都采用链表储存,部分数据采用了数组的形式储存,为了方便经常查找统计。三、在功能实现方面上,实现了全部的功能。但在某些功能的实现上,设置得不够合理,使用不够方便。如在修改和删除功能上不能批量操作,只能逐条操作。在某些输入操作时,必须按照提示输入,否则不能达到理想的效果。四、在代码量上,实现整个系统功能的代码量过长,并且某些功能的代码冗长,重复的代码很多,没有做到很好地减化代码量,若后期想修改某些功能时,修改量比较大,比较复杂。