C语言数据结构期末课程设计-职工工资管理系统(文末附带源码)

题目描述:

编写一个程序来管理职工工资,系统能实现以下功能:

  • 输入:职工信息的输入,并能自动计算职工的实发工资
  • 实发工资所有相加
  • 要求先用记事本等编辑软件将各职工的基本信息编辑、保存在文件zhigong.dat中,运行程序后从文件中读取职工的基本信息;
  • 修改:对职工信息进行修改;
  • 增加:添加新职工信息;
  • 删除:删除指定职工的信息;
  • 查询:根据工号姓名查询职工的信息;根据应发工资区间段查询某些职工的信息;根据籍贯查询职工的信息;
  • 排序:根据工号对职工信息进行升序/降序排序;根据应发工资进行降序排序,若应发工资相同,年龄大的在前;根据实发工资进行降序排序,若实发工资相同,工号小的在前;
  • 统计:根据职工年龄统计各年龄段(<=30,31~40,41~50,51~60)职工人数及占总人数的比例;根据职称统计各职称(高工,工程师,助理工程师)的人数等;
  • 输出:输出所有职工信息或查询职工信息的结果;
  • 保存:将编辑(增加、插入、删除、修改)后职工的所有信息保存到文件workers.dat中。

要求每个功能模块用一个函数实现。结构体数组或者单链表头指针在main函数中定义

2.设计提示

(1)先确定职工信息的数据结构。如每个职工信息:工号、姓名、性别、出生日期、籍贯、职称、参加工作时间、应发工资、公积金、养老金、补贴、实发工资等。实发工资应该在输入过程中计算所得;

(2)划分实现职工工资管理的功能模块:如主菜单、输入数据、修改、查询、输出等功能,并确定各功能模块的实现算法;

(3)画出主要算法的流程图;

(4)选择C语言的技术:普通数组、结构体数组、函数、指针、单链表或文件等;

(5)编写程序代码。

功能模块:

算法分析

核心模块:添加、修改、删除、查询、排序、统计

添加流程图如下:

 修改职工信息流程图如下:

排序流程图如下:

删除流程图如下:

 运行结果截图测试:

输入1,进行添加功能,输入添加的人数,然后根据提示依次添加工号,姓名,性别,出生日期,籍贯,职称,参加工作时间,应发工资,公积金,养老金,补贴,实发工资;

 输入7输出所有的员工信息:

输入2 进行修改操作,如下图所示 :

输入3,进行删除操作:

删除后,工号3的员工不存在:

文件中,验证工号为3的员工不存在:

输入4,进行查询功能,选择1,按工号查询,查询结果如下图:

选择2,按姓名查: 

输入3,按工资区间查: 

 

输入4,按籍贯去查:

 

排序:

选择1,根据工号进行降序排序,原先文件工号为1在前,排完之后工号为2的在前

按工号排序查:

对应的文件中即可看到排序:

按工资排序:

根据应发工资排序:

职称统计:

 保存职工信息到文件:

此时需要,退出程序后

即可看到新保存的数据,否则不结束程序,exe程序会占用workers.dat文件, 

 

若不退出,则会出现:

代码实现:

 源代码访问链接icon-default.png?t=N7T8https://docs.qq.com/doc/p/71239d69a76f56cf1521717ae6b22c27cf876f10

定义数组:

//定义一个职工
//工号、姓名、性别、出生日期、籍贯、职称、
//参加工作时间、应发工资、公积金、养老金、补贴、实发工资
typedef struct employee {
	
	
	char jobnum[20];//工号
	char name[20];//姓名
	char sex[2];//性别
	char birthdate[20];//出生日期
	char place[30];//籍贯
	char workname[20];//职称
	char jointime[20];//参加工作时间
	double shouldsal;//应发工资
	double actsal;//实发工资
	double publicsal;//公积金
	double oldsal;//养老金
	double allowance;//补贴
	
}employee;

//链表
//节点
typedef struct Node
{
	struct employee emp;			//职工信息
	
	struct Node* Next;	//指向下一个节点
}Node;

//创建头节点
Node* Head = NULL;		//指向头节点,置为空

添加员工信息:

void Add(int n)
{
	struct employee emp[100];
	FILE *fp;
	int i;
	fp=fopen("zhigong.dat","a+");
	if(fp==NULL)
	{
		printf("打开文件失败,请重试!\n");
		getch(); 
		fclose(fp);
		exit(0);
	}
	printf("请输入全部职工的工号,姓名,性别,出生日期,籍贯,职称,参加工作时间,应发工资,公积金,养老金,补贴,实发工资;\n"); 
	
	for(i=0;i<n;i++)
	{	
		printf("----第%d个职工----\n", i+1);
		printf("工号:");
		scanf("%s",emp[i].jobnum);

		printf("姓名:");
		scanf("%s",emp[i].name);
		
		printf("性别:");
		scanf("%s",emp[i].sex);

		printf("出生日期:");
		scanf("%s",emp[i].birthdate);

		printf("籍贯:");
		scanf("%s",emp[i].place);

		printf("职称:");
		scanf("%s",emp[i].workname);
		
		printf("参加工作时间:");
		scanf("%s",emp[i].jointime);
		
		printf("应发工资:");
		scanf("%lf",&emp[i].shouldsal);
		
		printf("实发工资:");
		scanf("%lf",&emp[i].actsal);
		
		printf("公积金:");
		scanf("%lf",&emp[i].publicsal);
		
		printf("养老金:");
		scanf("%lf",&emp[i].oldsal);
		
		printf("补贴:");
		scanf("%lf",&emp[i].allowance);
		

			//fprintf(fp,"%s %s % %s %s %s %s %.2lf %.2lf %.2lf %.2lf %.2lf\n",emp[i].jobnum,emp[i].name,emp[i].birthdate,emp[i].place,emp[i].workname,emp[i].jointime,emp[i].shouldsal,emp[i].actsal,emp[i].publicsal,emp[i].oldsal,emp[i].allowance);} 
			 
		//写入数据 
		fprintf(fp,"%s %s %.2s %s %s %s %s %.2lf %.2lf %.2lf %.2lf %.2lf\n",emp[i].jobnum,emp[i].name,emp[i].sex,emp[i].birthdate,emp[i].place,emp[i].workname,emp[i].jointime,emp[i].shouldsal,emp[i].actsal,emp[i].publicsal,emp[i].oldsal,emp[i].allowance);} 
	fclose(fp);
	printf("添加职工成功,请按任意键返回\n");
	getch();
}

删除员工:

void Delete() {
	
	//struct employee emp[100];
	int c=0,i;
	FILE *fp; 
	fp=fopen("zhigong.dat","r");
		if(fp==NULL)
		{
			printf("打开文件失败!\n");
			getch();
			exit(0); 
		}
		//把文件里的数据放到链表中
		while (!feof(fp))
		{
		    //读取文件中的一行数据到一个职工信息结构体中
		    struct employee emp;
		    fscanf(fp,"%s %s %s %s %s %s %s %lf %lf %lf %lf %lf\n",
		        emp.jobnum, emp.name, emp.sex, emp.birthdate, emp.place, emp.workname,
		        emp.jointime, &emp.shouldsal, &emp.actsal, &emp.publicsal, &emp.oldsal, &emp.allowance);
		        c++;
		
		    //创建链表节点并赋值
		    Node* p = (Node*)malloc(sizeof(Node));
		    p->emp = emp;
		    p->Next = NULL;
		
		    //将节点添加到链表尾部
		    if (Head == NULL)
		    {
		        Head = p;
		    }
		    else
		    {
		        Node* tail = Head;
		        while (tail->Next != NULL)
		        {
		            tail = tail->Next;
		        }
		        tail->Next = p;
		    }
		}
		fclose(fp);
		//到链表之后通过链表来删除,再把链表里的数据写入到文件里
		
		    char gh[20];
		    //printf("请输入删除职工的工号:");
		    scanf("%s", gh);
		
		    // 遍历链表查找
		    
		    Node* p = Head;
		    // 记录前一个节点pre,删除时方便操作
		    // 初始时pre即为Head
		    Node* pre = Head;
		    // 记录是否有找到该工号的职员信息
		    bool isFindemp = false;
		
		    while (p != NULL) {
		        if (strcmp(gh, p->emp.jobnum) == 0) {  // 找到目标节点
		            isFindemp = true;
		            // 删除节点为头节点
		            if (p == Head) {
		                Head = p->Next;  // 直接把Next指向Head
		            }
		            // 删除节点为尾节点
		            else if (p->Next == NULL) {
		                p = pre;
		                p->Next = NULL;
		            }
		            // 删除节点为中间节点
		            else {
		                pre->Next = p->Next;
		            }
		            printf("删除成功。\n\n");
		            free(p);  // 释放目标节点内存
		            break;
		        }
		        pre = p;
		        p = p->Next;
		    }
		    if (!isFindemp) {
		        printf("工号输入有误,系统中暂无该职工信息,无法进行删除操作。\n\n");
		    }
		    //把删除了的链表更新到zhigong.dat中
		    Node* q = Head; // 新增指针 q
		    fp=fopen("zhigong.dat","w");
			while (q != NULL) {
			    fprintf(fp, "%s %s %s %s %s %s %s %lf %lf %lf %lf %lf\n", q->emp.jobnum, q->emp.name, q->emp.sex, q->emp.birthdate, q->emp.place, q->emp.workname, q->emp.jointime, q->emp.shouldsal, q->emp.actsal, q->emp.publicsal, q->emp.oldsal, q->emp.allowance);
			    q = q->Next;
			}
			getch(); 
			fclose(fp);
		   
}
		    
		    //链表删除完毕,再遍历链表,存储到workers.dat中
		    //FILE* fp = NULL;
//按照应发工资区间段 查询 
void gzcx(int n)
{   
	struct employee emp[100];
	double qj[10];//用户指定工资区间 
	int i;
	int c = 0;
	FILE *fp; 
	printf("请输入你要查询的应发工资区间,用空格分隔两区间:");
	scanf("%lf%lf",&qj[0],&qj[1]);
	
	fp=fopen("zhigong.dat","r");
	if(fp==NULL)
	{
		printf("打开文件失败!\n");
		getch();
		exit(0); 
	}
	
	while(!feof(fp)){
		fscanf(fp,"%s %s %s %s %s %s %s %lf %lf %lf %lf %lf\n",emp[c].jobnum,emp[c].name,emp[c].sex,emp[c].birthdate,emp[c].place,emp[c].workname,emp[c].jointime,&emp[c].shouldsal
		,&emp[c].actsal,&emp[c].publicsal,&emp[c].oldsal,&emp[c].allowance);
		c++; 
	}
	fclose(fp);
	n=c;
	
	for(i=0;i<c;i++)
	{
		//应发工资shouldsal ,根据用户输入的区间段来查询 
		if(emp[i].shouldsal>=qj[0]&&emp[i].shouldsal<=qj[1]){
		printf("工号\t姓名\t性别\t出生日期 籍贯\t职称\t\t参加工作时间\t\t应发工资\t实发工资\t公积金\t养老金\t补贴\n");
							printf("%s\t%s\t%.2s\t%s %s\t%s\t\t%s\t%.2lf\t%.2lf\t\t%.2lf\t\t%.2lf\t%.2lf\n",emp[i].jobnum,emp[i].name,emp[i].sex,emp[i].birthdate,emp[i].place,emp[i].workname,emp[i].jointime,emp[i].shouldsal
						,emp[i].actsal,emp[i].publicsal,emp[i].oldsal,emp[i].allowance); 
			printf("按任意键返回\n");
			getch();
			fclose(fp);
			return;			
		}
		
	}
	printf("未找到要查询雇员,请重试!\n");
	getch();
	fclose(fp);
	return;
}
//按照工号排序
void ghSort(int n){
	struct employee emp[100];
	int i,j;

	//struct employee* temp;//temp设为结构体指针,交换
	
	
	FILE *fp;
	int c = 0;

	fp=fopen("zhigong.dat","r+");//要进行读写,为r+
	if(fp==NULL)
	{
		printf("打开文件失败!\n");
		getch();
		exit(0);
	}
	while(!feof(fp)){
		fscanf(fp,"%s %s %s %s %s %s %s %lf %lf %lf %lf %lf\n",emp[c].jobnum,emp[c].name,emp[c].sex,emp[c].birthdate,emp[c].place,emp[c].workname,emp[c].jointime,&emp[c].shouldsal
		,&emp[c].actsal,&emp[c].publicsal,&emp[c].oldsal,&emp[c].allowance);
		c++;//c的作用 
	}

	fclose(fp);
	n=c;
	//通过工号进行升序排序并存储 
	//工号为字符串,比较用strcmp 
	//排序这里n-count count要记录的是总人数
	for(i=0;i<c-1;i++)
	{

	for(j=0;j<c-1-i;j++){
		if(strcmp(emp[j].jobnum,emp[j+1].jobnum)>0){
//				temp=&emp[j];
//				emp[j]=emp[j+1];
//				emp[j+1]=*temp;//temp指针*解引用
struct employee temp = emp[j];
emp[j] = emp[j + 1];
emp[j + 1] = temp;

				
			
			
		}
	} 
	}
	//更新记录 ,打开zhigong.dat
	fp=fopen("zhigong.dat","w");
	for(i=0;i<n;i++)
	{
			
		fprintf(fp,"%s\t%s\t%s\t%s\t%s\t%s\t%s\t%.2lf\t%.2lf\t%.2lf\t%.2lf\t%.2lf\n"
				,emp[i].jobnum,emp[i].name,emp[i].sex,emp[i].birthdate,emp[i].place
				,emp[i].workname,emp[i].jointime,emp[i].shouldsal
				,emp[i].actsal,emp[i].publicsal,emp[i].oldsal,emp[i].allowance);
	}
	fclose(fp);
	printf("数据按照工号升序排序成功,请按任意键返回主菜单。\n");
	getch();
	return;       
	
	
}
//根据应发工资进行排序
void shouldsalSort(int n){
	struct employee emp[100];
	int i,j;

//	struct employee* temp;
	
	
	FILE *fp;
	int c = 0;

	fp=fopen("zhigong.dat","r");
	if(fp==NULL)
	{
		printf("打开文件失败!\n");
		getch();
		exit(0);
	}
	while(!feof(fp)){
		fscanf(fp,"%s %s %s %s %s %s %s %lf %lf %lf %lf %lf\n",emp[c].jobnum,emp[c].name,emp[c].sex,emp[c].birthdate,emp[c].place,emp[c].workname,emp[c].jointime,&emp[c].shouldsal
		,&emp[c].actsal,&emp[c].publicsal,&emp[c].oldsal,&emp[c].allowance);
		c++;
	}

	fclose(fp);
	//通过应发工资进行降序排序并存储 
	
	for(i=0;i<c-1;i++)
	{

	for(j=0;j<c-1-i;j++){
		if(emp[j].shouldsal==emp[j+1].shouldsal){
							//年龄大的在前(出生日期)
							if(strcmp(emp[j].birthdate,emp[j+1].birthdate)>0){
								//字符串大,年龄小,交换
								struct employee temp = emp[j];
								emp[j] = emp[j + 1];
								emp[j + 1] = temp;
								continue;
							}
						}
		if(emp[j].shouldsal<emp[j+1].shouldsal){
			struct employee temp = emp[j];
			emp[j] = emp[j + 1];
			emp[j + 1] = temp;
			
		}
		

main函数:

  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白不会debug

需要源码打个赏呗~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值