用链表写一个简单的职工工资管理系统

117 阅读19分钟

前言:

简单职工管理系统的一点详细学习记录

功能介绍

用户完成对职工编号和信息输入,通过功能选项进行对职工信息的输入,显示,修改,查找,删除,统计,保存至数据文件以及退出系统。

经分析,职工工资管理系统的功能需求如下:

1.     输入记录

2.     显示记录

3.     修改记录

4.     查找记录

5.     删除记录

6.     统计总体信息情况

7.     保存数据文件

具体实现

分块介绍

1)头文件和结点结构体

下面是头文件和结点的一个结构体,定义出职工特点,以及该结点下一个结点位置

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

 typedef struct worker
{
	char id[10];   //工号
	char name[20]; //姓名
	double basic;     //基本工资
	double wage;      //职务工资
	double extra;     //津贴
	double hospital;  //医疗保险
	double fund;      //公积金
	double sum;       //总和
	struct worker* next;

}Worker; //别称方便下面书写

2)函数声明

可以根据自己的需求进行添加

//函数声明
 void show(Worker* header);//显示
 void change1(Worker *header,char id[]);//按照id修改
 void Delete(Worker* header, char id[]);//删除
 void find(Worker* header, char id[]);//查找
 void menu();//菜单
 void tongj(Worker* header);//统计
 void save(Worker* header);//保存数据到文件
 void append(Worker *header,int n);//根据人数向链表末尾添加结点
 void read(Worker* header);//从文件读取数据
 void print(Worker* header);//打印信息

3) main主函数

调用system(“cls”)函数进行清屏,调用menu()功能菜单显示,提供选择界面,再利用switch()函数,选择需要进行的操作后(输入相应数字),调用相应函数,对职工工资信息进行管理,操作完毕后,再次显示菜单,再次输入相应选择,进行循环,输入0时while()中传入的参数是0,循环结束,退出职工工资管理系统。

 //主函数
 int main()
 {
	 //创建头结点
	 Worker* header = (Worker*)malloc(sizeof(Worker));
	 if (NULL == header)
	 {
		 printf("error!\n");
	 }
	 else {
		 header->next = NULL;
	 }
	 int nn;
	 do
	 {
		 system("cls");
		 char a = ' ';
		 char b = ' ';
		 char ID[10] = {0};
		 menu();
		 scanf_s("%d", &nn);
		 switch (nn)
		 {
		 case 1:
		     printf("请输入您要输入的人数:\n");
		     int n;
			 scanf_s("%d", &n);
			 read(header);
			 append(header, n);
			 a = getchar();
			 print(header);
			 printf("\n请按任意键返回主菜单\n");
			 b = getchar();
			 menu();
			 break;
		 case 2:
			 read(header);
			 show(header);
			 a = getchar();
			 printf("\n请按任意键返回主菜单\n");
			 b = getchar();
			 menu();
			 break;
		 case 3:
			 printf("请输入要查找的id:");
			 scanf_s("%s", ID, 10);
			 read(header);
			 find(header, ID);
			 a = getchar();
			 printf("\n请按任意键返回主菜单\n");
			 b = getchar();
			 menu();
			 break;
		 case 4:
			 printf("请输入要修改的员工id:\n");
			 scanf_s("%s", ID, 10);
			 read(header);
			 b = getchar();
			 change1(header,ID);
			 a = getchar();
			 printf("\n请按任意键返回主菜单\n");
			 b = getchar();
			 menu();
			 break;
		 case 5:
			 printf("请输入要删除的职工id:\n");
			 scanf_s("%s",ID,10);
			 read(header);
			 Delete(header, ID);
			 a = getchar();
			 printf("删除成功!\n");
			 printf("\n请按任意键返回主菜单\n");
			 b = getchar();
			 menu();
			 break;
		 case 6:
			 a = getchar();
			 read(header);
			 tongj(header);
			 printf("\n请按任意键返回主菜单\n");
			 b = getchar();
			 menu();
			 break;
		 case 7:
			 save(header);
			 a = getchar();
			 printf("成功保存!\n");
			 printf("\n请按任意键返回主菜单\n");
			 b = getchar();
			 menu();
			 break;
		 case 0:
			 printf("谢谢使用\n");
			 exit(0);

		 default:
			 printf("输入错误");

		 }
	 } while (nn);
	 return 0;
	
 }

4)保存数据到文件

定义了一个文件或者打开已经存在的文件用来存放职工信息数据记录,并判断是否打开成功。如果打开成功,用while函数将传入链表中的职工信息输入文件。

//保存数据到文件
 void save(Worker* header)
 {
	 Worker* phou = header->next;
	 FILE* fp;
	 if ((fp = fopen("WorkerSalary.txt", "w")) == NULL)
	 {
		 printf("打开失败!\n");
		 exit(0);
	 }
	 while (phou != NULL)
	 {
		 fprintf(fp, "%s %s %lf %lf %lf %lf %lf %lf\n", phou->id, phou->name, phou->basic, phou->wage, phou->extra, phou->hospital, phou->fund, phou->sum);
		 phou = phou->next;

	 }
	 fclose(fp);
 }

5)向链表末尾添加结点

往链表添加新的职工信息,定义一个辅助指针指向传入的header,通过while循环判断是否到链表末尾,(使添加到文件末尾)如果到链表末尾则开始按传入的n值批量通过malloc分配内存新建结点,进行指针判空,不为空则进行职工id输入,为不使输入id出现重复,通过while循环比较输入的id是否与从文件中读取到的职工id比较,若相同则提醒用户重新输入,一直到用户输入的id与存在的id不同,接着进行其他信息的输入,再调用save函数将信息保存到文件。

 //向链表末尾添加结点
 void append(Worker* header, int n) {
	 if (header == NULL)
	 {
		 return;
	 }
	 Worker* phou = header;
	 while (phou->next != NULL)
	 {
		 phou = phou->next;
	 }
	 for (int i = 1; i <= n; i++)
	 {
		 Worker* newworker = (Worker*)malloc(sizeof(Worker));
		 if (NULL == newworker || phou == NULL)
		 {
			 printf("error!\n");
			 free(newworker);

		 }
		 else {
			 int flag = 1;
			 char ID[10] = {'\0'};
			 while (flag)
			 {
				 printf("请输入%d员工的id:", i);
				 scanf_s("%s",ID,2);
				 Worker* p = header;
				 while (p != NULL)
				 {
					 if (strcmp(p->id, ID) == 0)
					 {
						 printf("该id已被占用,请重新输入:\n");
						 break;
					 }
					 p = p->next;
				 }
				 if (p == NULL)
				 {
					 flag = 0;
				 }

			 }
			 for (int i = 0; i<10; i++)
			 {
				 newworker->id[i] = ID[i];
			 }
			 printf("请输入%d员工的姓名:", i);
			 scanf_s("%s", &newworker->name, 20);
			 printf("请输入%d员工的基本工资:", i);
			 scanf_s("%lf", &newworker->basic);
			 printf("请输入%d员工的职务工资:", i);
			 scanf_s("%lf", &newworker->wage);
			 printf("请输入%d员工的岗位津贴:", i);
			 scanf_s("%lf", &newworker->extra);
			 printf("请输入%d员工的医疗保险:", i);
			 scanf_s("%lf", &newworker->hospital);
			 printf("请输入%d员工的公积金:", i);
			 scanf_s("%lf", &newworker->fund);
			 newworker->sum = newworker->basic + newworker->wage + newworker->extra - newworker->hospital - newworker->fund;
			 newworker->next = NULL;
			 phou->next = newworker;
			 phou = newworker;
		 }

	 }
	 save(header);
	 printf("输入成功!\n");
 }

6)从文件读取到链表

第四模块是从文件读取数据到链表,打开存有职工工资信息的文件,判断打开是否成功,通过while循环和feof函数判断是否读到文件末尾,读数据时,根据信息创建新结点,并为结点用malloc分配内存,将文件里的数据读入链表,接着辅助指针后移,继续存入信息,最后关闭文件。

//从文件读取数据到链表
 void read(Worker* header)
 {
	 if (header == NULL)
	 {
		 return;
	 }

	 Worker* phou = header;
	 FILE* fp;
	 if ((fp = fopen("WorkerSalary.txt", "r")) == NULL)
	 {
		 printf("打开文件失败!\n");
		 return;
	 }
	 while (feof(fp) == 0)
	 {
		 Worker* newworker = (Worker*)malloc(sizeof(Worker));
		newworker->next = NULL;
		if (NULL == newworker || phou == NULL)
		 {
			 printf("error!\n");
			 free(newworker);
		 }
		 int nread = fscanf(fp, "%s %s %lf %lf %lf %lf %lf %lf", newworker->id, newworker->name, &newworker->basic,
			 &newworker->wage, &newworker->extra, &newworker->hospital, &newworker->fund, &newworker->sum);
		 if (nread == EOF)
		 {
			 free(newworker);
			 break;
		 }
		 else
		 {
			 phou->next = newworker;
			 phou = newworker;
		 }

	 }
	 phou->next = NULL;
	 fclose(fp);
 }
 

7)菜单

该部分为功能菜单,结合前面主函数中的相应功能的序号对菜单功能进行显示

 //菜单
 void menu()
 {
	 printf("\t\t\t\t\t				   							\n");
	 printf("\t\t\t\t\t▔▔▔▔▔▔▔▔▔▔▔欢迎进入工资管理系统▔▔▔▔▔▔▔▔▔▔\n");
	 printf("\t\t\t\t\t  1.输入职工的信息         					\n");
	 printf("\t\t\t\t\t  2.按姓名显示某个或某几个职工的相关信息 \n");
	 printf("\t\t\t\t\t  3.按id查找某个员工的相关信息      			\n");
	 printf("\t\t\t\t\t  4.修改某个职工的相关信息				    	\n");
	 printf("\t\t\t\t\t  5.删除某个职工的相关信息				     	\n");
	 printf("\t\t\t\t\t  6.统计输出所有职工总工资情况  			    \n");
	 printf("\t\t\t\t\t  7.将所有职工的工资信息保存至文件			    \n");
	 printf("\t\t\t\t\t  0.退出								        \n");
	 printf("\t\t\t\t\t▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁谢谢使用▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\n");
	 printf("\t\t\t\t\t请输入相应数字,进行相应的操作:\n");
 }

8)删除职工工资信息记录

第六模块是删除职工工资信息记录,首先对header进行判空,不为空则创建两个辅助指针pqian,phou(随便取名,看起来好判断)。pqian指向header,phou指向pqian的下一个结点,通过while循环寻找与传入id相同的id,找到后通过break退出循环,让pqian的next指向phou的next,使phou这个结点自动从链表上脱落删除。 否则让pqian指向phou,phou指向phou的下一个结点,一直到链表结束,如果该不存在,则输出提醒。最后释放辅助指针,对删除后的职工信息保存至文件,进行信息更新。

//删除数据
 void Delete(Worker* header, char id[])
 {
	 if (header == NULL)
	 {
		 printf("数据为空,无法删除\n");
	 }
	 else
	 {
		 //创建两个辅助指针
		 Worker* pqian = header;
		 Worker* phou = pqian->next;
		 while (phou != NULL)
		 {
			 if (strcmp(phou->id, id) == 0)
			 {
				 break;
			 }
			 pqian = phou;
			 phou = phou->next;

		 }
		 if (phou == NULL)
		 {
			 printf("数据不存在,无法删除\n");
			 return;
		 }
		 pqian->next = phou->next;
		 free(phou);
		 phou = NULL;
		 save(header);

	 }
 }

9)根据id进行查找

第七模块是根据id对职工工资信息进行查找,首先定义一个辅助指针phou指向header的下一个结点,再定义一个flag为标记,如果查到存在该职工,更改flag的值,对该职工的信息进行显示。若flag的值没变,则提示没有该职工

//查找数据
 void find(Worker* header, char id[])
 {
	 Worker* phou = header->next;
	 int flag = 0;
	 while (phou != NULL)
	 {
		 if (strcmp(phou->id, id) == 0)
		 {
			 flag = 1;
			 printf("该职工的信息如下:\n");
			 printf("id:%s\n", phou->id);
			 printf("姓名:%s\n", phou->name);
			 printf("基本工资:%.1lf\n", phou->basic);
			 printf("职务工资:%.1lf\n", phou->wage);
			 printf("岗位津贴:%.1lf\n", phou->extra);
			 printf("医疗保险:%.1lf\n", phou->hospital);
			 printf("公积金:%.1lf\n", phou->fund);
			 printf("总工资:%.1lf\n", phou->sum);
			 break;
		 }
		 else
		 {
			 phou = phou->next;
		 }
	 }
	 if (flag == 0)
	 {
		 printf("没有该职工,查找失败!\n");
	 }

 }

10)根据职工姓名以及想要显示的职工人数对职工工资信息进行显示

第八模块是根据职工姓名以及想要显示的职工人数对职工工资信息进行显示,并对查看的几个人进行总工资的统计求平均值。

 //显示  根据姓名显示出一个或者几个人的各项工资贺平均工资
 void show(Worker* header)
 {
	 Worker* phou = header->next;

	 printf("请输入你想要查看的职工人数:");
	 int m;
	 int flag = 0;
	 double allmoney = 0.0;
	 scanf_s("%d", &m);
	 for (int i = 0; i < m; i++)
	 {
		 printf("请输入职工name:\n");
		 char Name[20] = { 0 };
		 scanf_s("%s", Name, 20);
		 phou = header->next;
		 while (phou != NULL)
		 {
			 if (strcmp(phou->name, Name) == 0)
			 {
				 flag = 1;
				 printf("%s的基本工资:%.1lf\n", phou->name, phou->basic);
				 printf("%s的职务工资:%.1lf\n", phou->name, phou->wage);
				 printf("%s的岗位津贴:%.1lf\n", phou->name, phou->extra);
				 printf("%s的医疗保险:%.1lf\n", phou->name, phou->hospital);
				 printf("%s的公积金:%.1lf\n", phou->name, phou->fund);
				 printf("%s的总工资:%.1lf\n", phou->name, phou->sum);
				 allmoney = allmoney + phou->sum;
			 }
			 phou = phou->next;
		 }

	 }
	 if (flag == 0)
	 {
		 printf("没有该职工!");
	 }
	 else {
		 printf("%d人的平均工资:%.1lf\n", m, allmoney / (1.0 * m));
	 }


 }
 //打印
 void print(Worker* header)
 {
	 Worker* phou = header->next;
	 printf("职工信息如下:\n");
	 printf("|%4s |%10s |%10s |%10s |%10s |%10s |%10s |%10s|\n", "id", "姓名", "基本工资", "职务工资", "津贴", "医疗保险", "公积金", "总工资");
	 while (phou != NULL)
	 {
		 printf("|%4s |%10s |%10.1lf |%10.1lf |%10.1lf |%10.1lf |%10.1lf |%10.1lf|\n", phou->id, phou->name, phou->basic, phou->wage, phou->extra, phou->hospital, phou->fund, phou->sum);
		 phou = phou->next;
	 }

 }

11)该部分是一个单纯的打印出链表中的所有数据

//打印
 void print(Worker* header)
 {
	 Worker* phou = header->next;
	 printf("职工信息如下:\n");
	 printf("|%4s |%10s |%10s |%10s |%10s |%10s |%10s |%10s|\n", "id", "姓名", "基本工资", "职务工资", "津贴", "医疗保险", "公积金", "总工资");
	 while (phou != NULL)
	 {
		 printf("|%4s |%10s |%10.1lf |%10.1lf |%10.1lf |%10.1lf |%10.1lf |%10.1lf|\n", phou->id, phou->name, phou->basic, phou->wage, phou->extra, phou->hospital, phou->fund, phou->sum);
		 phou = phou->next;
	 }

 }

12)根据职工ID修改相应信息

第十模块是根据职工id修改信息数据(也可以根据姓名来,不过姓名容易重名),先是写一个提醒选择更改菜单,再定义一个辅助指针phou指向header的下一个结点,利用while循环和id查找需要改变的职工,通过switch函数,选择需要进行的操作(输入相应数字),对相应数据进行更改。最后调用print函数,对修改后的信息进行显示。

 //根据id修改数据
 void change1(Worker* header, char id[])
 {
	 printf("如果需要修改姓名请输入:1\n");
	 printf("如果需要修改id请输入:2\n");
	 printf("如果需要修改基本工资请输入:3\n");
	 printf("如果需要修改职务工资请输入:4\n");
	 printf("如果需要修改岗位津贴请输入:5\n");
	 printf("如果需要修改医疗保险请输入:6\n");
	 printf("如果需要修改公积金请输入:7\n\n");
	 printf("请输入需要修改的项目编号:\n");
	 Worker* phou = header->next;
	 int n;
	 scanf_s("%d", &n);
	 char Name[20] = { '\0' };

	 while (phou != NULL)
	 {
		 if (strcmp(phou->id, id) == 0)
		 {
			 switch (n)
			 {
			 case 1:
				 printf("请输入更改后的姓名:\n");
				 scanf_s("%s", &Name, 20);
				 for (int i = 0; i<20; i++)
				 {
					 phou->name[i] = Name[i];
				 }
				 break;
			 case 2:
				 printf("请输入修改后的id:\n");
				 char ID[10];
				 ID[0] = '0';
				 scanf_s("%s", &ID, 10);
				 for (int i = 0; i<10; i++)
				 {
					 phou->id[i] = ID[i];
				 }
				 break;
			 case 3:
				 printf("请输入修改后的值:\n");
				 double n1;
				 scanf_s("%lf", &n1);
				 phou->basic = n1;
				 break;
			 case 4:
				 printf("请输入修改后的值:\n");
				 double n2;
				 scanf_s("%lf", &n2);
				 phou->wage = n2;
				 break;
			 case 5:
				 printf("请输入修改后的值:\n");
				 double n3;
				 scanf_s("%lf", &n3);
				 phou->extra = n3;
				 break;
			 case 6:
				 printf("请输入修改后的值:\n");
				 double n4;
				 scanf_s("%lf", &n4);
				 phou->hospital = n4;
				 break;
			 case 7:
				 printf("请输入修改后的值:\n");
				 double n5;
				 scanf_s("%lf", &n5);
				 phou->fund = n5;
				 break;
			 default:
				 printf("输入错误.\n");
				 break;


			 }
			 phou->sum = phou->basic + phou->wage + phou->extra - phou->hospital - phou->fund;
			 print(header);
			 save(header);
			 break;

		 }
		 phou = phou->next;
	 }
 }

13)统计

第十一模块是统计显示文件中的所有信息,首先使用system(“cls”)进行清屏,再定义一个辅助指针指向header的下一个结点,通过for循环对每一个结点进行显示,并统计出该职工的各项工资的总和,判断总工资的范围(1000到2000、2000到3000、>3000),进行累计,再让辅助指针指向phou的下一个结点。直到链表结束,计算各项工资的平均工资,并对平均工资进行显示,根据累计的各个范围数据计算不同工资范围工资情况人数占比。

 //统计显示文件内所有信息
 void tongj(Worker* header)
 {
	 system("cls");
	 Worker* phou = header->next;
	 int m = 0, n1 = 0, n2 = 0, n3 = 0;
	 double sum3 = 0.0;
	 double basic = 0.0, wage = 0.0, extra = 0.0, hosptial = 0.0, fund = 0.0, sum = 0.0;
	 printf("职工信息如下:\n");
	 printf("|%4s |%10s |%10s |%10s |%10s |%10s |%10s |%10s|\n", "id", "姓名", "基本工资", "职务工资", "津贴", "医疗保险", "公积金", "总工资");
	 for (int i = 0; i < 1000; i++)
	 {
		 if (phou == NULL)
		 {
			 printf("\n");
			 break;
		 }
		 printf("|%4s |%10s |%10.1lf |%10.1lf |%10.1lf |%10.1lf |%10.1lf |%10.1lf|\n", phou->id, phou->name, phou->basic, phou->wage, phou->extra, phou->hospital, phou->fund, phou->sum);
		 m++;
		 basic += phou->basic;
		 wage += phou->wage;
		 extra += phou->extra;
		 hosptial += phou->hospital;
		 fund += phou->fund;
		 sum += phou->sum;
		 sum3 = phou->basic + phou->wage + phou->extra;
		 if (sum3 > 3000)
		 {
			 n1++;
		 }
		 if (sum3 > 2000 && sum3 < 3000)
		 {
			 n2++;
		 }
		 if (sum3 > 1000 && sum3 < 2000)
		 {
			 n3++;
		 }
		 phou = phou->next;

	 }
	 printf("|%16s ", "各项平均工资");
	 printf("|%10.1lf |%10.1lf |%10.1lf |%10.1lf |%10.1lf |%10.1lf|\n", basic / (m * 1.0), wage / (m * 1.0), extra / (1.0 * m), hosptial / (1.0 * m), fund / (1.0 * m), sum / (1.0 * m));
	 printf("工资前三项之和在3000元以上的占:%.1lf\n", 100 * n1 / (1.0 * m));
	 printf("工资前三项之和在2000~3000元的占:%.1lf\n", 100 * n2 / (1.0 * m));
	 printf("工资前三项之和在1000~2000元的占:%.1lf\n", 100 * n3 / (1.0 * m));
 }

总体实现

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

 typedef struct worker
{
	char id[10];   //工号
	char name[20]; //姓名
	double basic;     //基本工资
	double wage;      //职务工资
	double extra;     //津贴
	double hospital;  //医疗保险
	double fund;      //公积金
	double sum;       //总和
	struct worker* next;

}Worker; 

 
 
 //函数声明
 void show(Worker* header);//显示
 void change1(Worker *header,char id[]);//按照id修改
 void Delete(Worker* header, char id[]);//删除
 void find(Worker* header, char id[]);//查找
 void menu();//菜单
 void tongj(Worker* header);//统计
 void save(Worker* header);//保存数据到文件
 void append(Worker *header,int n);//根据人数向链表末尾添加结点
 void read(Worker* header);//从文件读取数据
 void print(Worker* header);//打印信息

 //主函数
 int main()
 {
	 //创建头结点
	 Worker* header = (Worker*)malloc(sizeof(Worker));
	 if (NULL == header)
	 {
		 printf("error!\n");
	 }
	 else {
		 header->next = NULL;
	 }
	 int nn;
	 do
	 {
		 system("cls");
		 char a = ' ';
		 char b = ' ';
		 char ID[10] = {0};
		 menu();
		 scanf_s("%d", &nn);
		 switch (nn)
		 {
		 case 1:
		     printf("请输入您要输入的人数:\n");
		     int n;
			 scanf_s("%d", &n);
			 read(header);
			 append(header, n);
			 a = getchar();
			 print(header);
			 printf("\n请按任意键返回主菜单\n");
			 b = getchar();
			 menu();
			 break;
		 case 2:
			 read(header);
			 show(header);
			 a = getchar();
			 printf("\n请按任意键返回主菜单\n");
			 b = getchar();
			 menu();
			 break;
		 case 3:
			 printf("请输入要查找的id:");
			 scanf_s("%s", ID, 10);
			 read(header);
			 find(header, ID);
			 a = getchar();
			 printf("\n请按任意键返回主菜单\n");
			 b = getchar();
			 menu();
			 break;
		 case 4:
			 printf("请输入要修改的员工id:\n");
			 scanf_s("%s", ID, 10);
			 read(header);
			 b = getchar();
			 change1(header,ID);
			 a = getchar();
			 printf("\n请按任意键返回主菜单\n");
			 b = getchar();
			 menu();
			 break;
		 case 5:
			 printf("请输入要删除的职工id:\n");
			 scanf_s("%s",ID,10);
			 read(header);
			 Delete(header, ID);
			 a = getchar();
			 printf("删除成功!\n");
			 printf("\n请按任意键返回主菜单\n");
			 b = getchar();
			 menu();
			 break;
		 case 6:
			 a = getchar();
			 read(header);
			 tongj(header);
			 printf("\n请按任意键返回主菜单\n");
			 b = getchar();
			 menu();
			 break;
		 case 7:
			 save(header);
			 a = getchar();
			 printf("成功保存!\n");
			 printf("\n请按任意键返回主菜单\n");
			 b = getchar();
			 menu();
			 break;
		 case 0:
			 printf("谢谢使用\n");
			 exit(0);

		 default:
			 printf("输入错误");

		 }
	 } while (nn);
	 return 0;
	
 }
 //保存数据到文件
 void save(Worker* header)
 {
	 Worker* phou = header->next;
	 FILE* fp;
	 if ((fp = fopen("WorkerSalary.txt", "w")) == NULL)
	 {
		 printf("打开失败!\n");
		 exit(0);
	 }
	 while (phou != NULL)
	 {
		 fprintf(fp, "%s %s %lf %lf %lf %lf %lf %lf\n", phou->id, phou->name, phou->basic, phou->wage, phou->extra, phou->hospital, phou->fund, phou->sum);
		 phou = phou->next;

	 }
	 fclose(fp);
 }
 //向链表末尾添加结点
 void append(Worker* header, int n) {
	 if (header == NULL)
	 {
		 return;
	 }
	 Worker* phou = header;
	 while (phou->next != NULL)
	 {
		 phou = phou->next;
	 }
	 for (int i = 1; i <= n; i++)
	 {
		 Worker* newworker = (Worker*)malloc(sizeof(Worker));
		 if (NULL == newworker || phou == NULL)
		 {
			 printf("error!\n");
			 free(newworker);

		 }
		 else {
			 int flag = 1;
			 char ID[10] = {'\0'};
			 while (flag)
			 {
				 printf("请输入%d员工的id:", i);
				 scanf_s("%s",ID,2);
				 Worker* p = header;
				 while (p != NULL)
				 {
					 if (strcmp(p->id, ID) == 0)
					 {
						 printf("该id已被占用,请重新输入:\n");
						 break;
					 }
					 p = p->next;
				 }
				 if (p == NULL)
				 {
					 flag = 0;
				 }

			 }
			 for (int i = 0; i<10; i++)
			 {
				 newworker->id[i] = ID[i];
			 }
			 printf("请输入%d员工的姓名:", i);
			 scanf_s("%s", &newworker->name, 20);
			 printf("请输入%d员工的基本工资:", i);
			 scanf_s("%lf", &newworker->basic);
			 printf("请输入%d员工的职务工资:", i);
			 scanf_s("%lf", &newworker->wage);
			 printf("请输入%d员工的岗位津贴:", i);
			 scanf_s("%lf", &newworker->extra);
			 printf("请输入%d员工的医疗保险:", i);
			 scanf_s("%lf", &newworker->hospital);
			 printf("请输入%d员工的公积金:", i);
			 scanf_s("%lf", &newworker->fund);
			 newworker->sum = newworker->basic + newworker->wage + newworker->extra - newworker->hospital - newworker->fund;
			 newworker->next = NULL;
			 phou->next = newworker;
			 phou = newworker;
		 }

	 }
	 save(header);
	 printf("输入成功!\n");
 }

 //从文件读取数据到链表
 void read(Worker* header)
 {
	 if (header == NULL)
	 {
		 return;
	 }

	 Worker* phou = header;
	 FILE* fp;
	 if ((fp = fopen("WorkerSalary.txt", "r")) == NULL)
	 {
		 printf("打开文件失败!\n");
		 return;
	 }
	 while (feof(fp) == 0)
	 {
		 Worker* newworker = (Worker*)malloc(sizeof(Worker));
		newworker->next = NULL;
		if (NULL == newworker || phou == NULL)
		 {
			 printf("error!\n");
			 free(newworker);
		 }
		 int nread = fscanf(fp, "%s %s %lf %lf %lf %lf %lf %lf", newworker->id, newworker->name, &newworker->basic,
			 &newworker->wage, &newworker->extra, &newworker->hospital, &newworker->fund, &newworker->sum);
		 if (nread == EOF)
		 {
			 free(newworker);
			 break;
		 }
		 else
		 {
			 phou->next = newworker;
			 phou = newworker;
		 }

	 }
	 phou->next = NULL;
	 fclose(fp);
 }
 //菜单
 void menu()
 {
	 printf("\t\t\t\t\t				   							\n");
	 printf("\t\t\t\t\t▔▔▔▔▔▔▔▔▔▔▔欢迎进入工资管理系统▔▔▔▔▔▔▔▔▔▔\n");
	 printf("\t\t\t\t\t  1.输入职工的信息         					\n");
	 printf("\t\t\t\t\t  2.按姓名显示某个或某几个职工的相关信息 \n");
	 printf("\t\t\t\t\t  3.按id查找某个员工的相关信息      			\n");
	 printf("\t\t\t\t\t  4.修改某个职工的相关信息				    	\n");
	 printf("\t\t\t\t\t  5.删除某个职工的相关信息				     	\n");
	 printf("\t\t\t\t\t  6.统计输出所有职工总工资情况  			    \n");
	 printf("\t\t\t\t\t  7.将所有职工的工资信息保存至文件			    \n");
	 printf("\t\t\t\t\t  0.退出								        \n");
	 printf("\t\t\t\t\t▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁谢谢使用▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁\n");
	 printf("\t\t\t\t\t请输入相应数字,进行相应的操作:\n");
 }

 //删除数据
 void Delete(Worker* header, char id[])
 {
	 if (header == NULL)
	 {
		 printf("数据为空,无法删除\n");
	 }
	 else
	 {
		 //创建两个辅助指针
		 Worker* pqian = header;
		 Worker* phou = pqian->next;
		 while (phou != NULL)
		 {
			 if (strcmp(phou->id, id) == 0)
			 {
				 break;
			 }
			 pqian = phou;
			 phou = phou->next;

		 }
		 if (phou == NULL)
		 {
			 printf("数据不存在,无法删除\n");
			 return;
		 }
		 pqian->next = phou->next;
		 free(phou);
		 phou = NULL;
		 save(header);

	 }
 }

 //查找数据
 void find(Worker* header, char id[])
 {
	 Worker* phou = header->next;
	 int flag = 0;
	 while (phou != NULL)
	 {
		 if (strcmp(phou->id, id) == 0)
		 {
			 flag = 1;
			 printf("该职工的信息如下:\n");
			 printf("id:%s\n", phou->id);
			 printf("姓名:%s\n", phou->name);
			 printf("基本工资:%.1lf\n", phou->basic);
			 printf("职务工资:%.1lf\n", phou->wage);
			 printf("岗位津贴:%.1lf\n", phou->extra);
			 printf("医疗保险:%.1lf\n", phou->hospital);
			 printf("公积金:%.1lf\n", phou->fund);
			 printf("总工资:%.1lf\n", phou->sum);
			 break;
		 }
		 else
		 {
			 phou = phou->next;
		 }
	 }
	 if (flag == 0)
	 {
		 printf("没有该职工,查找失败!\n");
	 }

 }

 //显示  根据姓名显示出一个或者几个人的各项工资贺平均工资
 void show(Worker* header)
 {
	 Worker* phou = header->next;

	 printf("请输入你想要查看的职工人数:");
	 int m;
	 int flag = 0;
	 double allmoney = 0.0;
	 scanf_s("%d", &m);
	 for (int i = 0; i < m; i++)
	 {
		 printf("请输入职工name:\n");
		 char Name[20] = { 0 };
		 scanf_s("%s", Name, 20);
		 phou = header->next;
		 while (phou != NULL)
		 {
			 if (strcmp(phou->name, Name) == 0)
			 {
				 flag = 1;
				 printf("%s的基本工资:%.1lf\n", phou->name, phou->basic);
				 printf("%s的职务工资:%.1lf\n", phou->name, phou->wage);
				 printf("%s的岗位津贴:%.1lf\n", phou->name, phou->extra);
				 printf("%s的医疗保险:%.1lf\n", phou->name, phou->hospital);
				 printf("%s的公积金:%.1lf\n", phou->name, phou->fund);
				 printf("%s的总工资:%.1lf\n", phou->name, phou->sum);
				 allmoney = allmoney + phou->sum;
			 }
			 phou = phou->next;
		 }

	 }
	 if (flag == 0)
	 {
		 printf("没有该职工!");
	 }
	 else {
		 printf("%d人的平均工资:%.1lf\n", m, allmoney / (1.0 * m));
	 }


 }
 //打印
 void print(Worker* header)
 {
	 Worker* phou = header->next;
	 printf("职工信息如下:\n");
	 printf("|%4s |%10s |%10s |%10s |%10s |%10s |%10s |%10s|\n", "id", "姓名", "基本工资", "职务工资", "津贴", "医疗保险", "公积金", "总工资");
	 while (phou != NULL)
	 {
		 printf("|%4s |%10s |%10.1lf |%10.1lf |%10.1lf |%10.1lf |%10.1lf |%10.1lf|\n", phou->id, phou->name, phou->basic, phou->wage, phou->extra, phou->hospital, phou->fund, phou->sum);
		 phou = phou->next;
	 }

 }


 //根据id修改数据
 void change1(Worker* header, char id[])
 {
	 printf("如果需要修改姓名请输入:1\n");
	 printf("如果需要修改id请输入:2\n");
	 printf("如果需要修改基本工资请输入:3\n");
	 printf("如果需要修改职务工资请输入:4\n");
	 printf("如果需要修改岗位津贴请输入:5\n");
	 printf("如果需要修改医疗保险请输入:6\n");
	 printf("如果需要修改公积金请输入:7\n\n");
	 printf("请输入需要修改的项目编号:\n");
	 Worker* phou = header->next;
	 int n;
	 scanf_s("%d", &n);
	 char Name[20] = { '\0' };

	 while (phou != NULL)
	 {
		 if (strcmp(phou->id, id) == 0)
		 {
			 switch (n)
			 {
			 case 1:
				 printf("请输入更改后的姓名:\n");
				 scanf_s("%s", &Name, 20);
				 for (int i = 0; i<20; i++)
				 {
					 phou->name[i] = Name[i];
				 }
				 break;
			 case 2:
				 printf("请输入修改后的id:\n");
				 char ID[10];
				 ID[0] = '0';
				 scanf_s("%s", &ID, 10);
				 for (int i = 0; i<10; i++)
				 {
					 phou->id[i] = ID[i];
				 }
				 break;
			 case 3:
				 printf("请输入修改后的值:\n");
				 double n1;
				 scanf_s("%lf", &n1);
				 phou->basic = n1;
				 break;
			 case 4:
				 printf("请输入修改后的值:\n");
				 double n2;
				 scanf_s("%lf", &n2);
				 phou->wage = n2;
				 break;
			 case 5:
				 printf("请输入修改后的值:\n");
				 double n3;
				 scanf_s("%lf", &n3);
				 phou->extra = n3;
				 break;
			 case 6:
				 printf("请输入修改后的值:\n");
				 double n4;
				 scanf_s("%lf", &n4);
				 phou->hospital = n4;
				 break;
			 case 7:
				 printf("请输入修改后的值:\n");
				 double n5;
				 scanf_s("%lf", &n5);
				 phou->fund = n5;
				 break;
			 default:
				 printf("输入错误.\n");
				 break;


			 }
			 phou->sum = phou->basic + phou->wage + phou->extra - phou->hospital - phou->fund;
			 print(header);
			 save(header);
			 break;

		 }
		 phou = phou->next;
	 }
 }
 //统计显示文件内所有信息
 void tongj(Worker* header)
 {
	 system("cls");
	 Worker* phou = header->next;
	 int m = 0, n1 = 0, n2 = 0, n3 = 0;
	 double sum3 = 0.0;
	 double basic = 0.0, wage = 0.0, extra = 0.0, hosptial = 0.0, fund = 0.0, sum = 0.0;
	 printf("职工信息如下:\n");
	 printf("|%4s |%10s |%10s |%10s |%10s |%10s |%10s |%10s|\n", "id", "姓名", "基本工资", "职务工资", "津贴", "医疗保险", "公积金", "总工资");
	 for (int i = 0; i < 1000; i++)
	 {
		 if (phou == NULL)
		 {
			 printf("\n");
			 break;
		 }
		 printf("|%4s |%10s |%10.1lf |%10.1lf |%10.1lf |%10.1lf |%10.1lf |%10.1lf|\n", phou->id, phou->name, phou->basic, phou->wage, phou->extra, phou->hospital, phou->fund, phou->sum);
		 m++;
		 basic += phou->basic;
		 wage += phou->wage;
		 extra += phou->extra;
		 hosptial += phou->hospital;
		 fund += phou->fund;
		 sum += phou->sum;
		 sum3 = phou->basic + phou->wage + phou->extra;
		 if (sum3 > 3000)
		 {
			 n1++;
		 }
		 if (sum3 > 2000 && sum3 < 3000)
		 {
			 n2++;
		 }
		 if (sum3 > 1000 && sum3 < 2000)
		 {
			 n3++;
		 }
		 phou = phou->next;

	 }
	 printf("|%16s ", "各项平均工资");
	 printf("|%10.1lf |%10.1lf |%10.1lf |%10.1lf |%10.1lf |%10.1lf|\n", basic / (m * 1.0), wage / (m * 1.0), extra / (1.0 * m), hosptial / (1.0 * m), fund / (1.0 * m), sum / (1.0 * m));
	 printf("工资前三项之和在3000元以上的占:%.1lf\n", 100 * n1 / (1.0 * m));
	 printf("工资前三项之和在2000~3000元的占:%.1lf\n", 100 * n2 / (1.0 * m));
	 printf("工资前三项之和在1000~2000元的占:%.1lf\n", 100 * n3 / (1.0 * m));
 }