工资信息管理系统 I 的设计与实现
设计内容:编写一个小型的工资信息管理系统,通过键盘式选择菜单实现功 能选择(比如,输入数字 1 表示创建数据)。功能包括:数据输入、数据输出、数据添加、数据修改、数据删除、数据查找、数据排序和数据统计等。各功能模块要求独立的函数来表示,通过主函数直接或间接调用。
设计要求:
(1) 输出显示包含工号、姓名、员工类别、周工作时长、周工资
(2) 周工资按照以下方式计算:一周内工作时间不超过 40 小时,按正常工作时间计酬;超出 40 小时的工作时间部分,按正常工作时间报酬的 1.5 倍计酬。员工按 进公司时间分为新职工和老职工,进公司不少于 5 年的员工为老职工,5 年以 下的为新职工。新职工的正常工资为 30 元/小时,老职工的正常工资为 50 元/ 小时。
(3) 按职工号由小到大排序
(4) 要求输入一个职工号,用折半查找找出该职工的姓名。
(5) 统计显示每小时平均工资以及最高工资员工姓名
程序设计的思路
首先创建一个包含职工信息的结构体,包含工号、姓名、工龄、类别、周工作时长、周工资。然后直接在末尾定义变量staff[N],其中N是定义好的全局变量,值为100,即可以储存的最大员工数量为100。还有一个结构体变量temp,用于排序时充当中间变量。然后再根据题目要求实现的功能(8个),还有菜单、保存文件、读取文件函数,总共有10个大类函数。测试文件Test.c中包含了主函数和保存、读取文件函数。最为重要的一步是将Test.c中涉及的头文件、结构体、功能函数声明等信息包装在一个自己定义的test.h头文件中,方便功能函数调用。各个函数之间的调用主要是用switch case实现的。所有功能函数由主函数直接或间接调用。此外有system(“cls”)(清屏)、system(“color E0”)(设置背景颜色)函数实现了友好的用户体验。
目录
1.主函数
2.输入输出函数
3.增删改查函数
4.统计工资函数
5.排序函数
6.菜单函数
7.自定义头文件(用于各功能函数调用)
#include
#include
#include
#define N 100 //最大员工数量
//职工信息结构体
struct employee {
int num; //工号
char name[10]; //姓名
int year; //工龄
char category[10];//员工类别
int duration; //周工作时长
float wage; //周工资
}staff[N],temp; //temp用于排序时充当中间变量
//功能函数声明
void Menu(); //菜单函数
void Input(); //输入职工信息
void save(int m); //储存信息
int read(); //读取信息
void Output(); //输出信息
void Addition(); //添加函数
void Modify(); //修改操作
void Delete(); //删除操作
void Search(); //查找函数
void search_num(); //按工号折半查找
void search_name(); //按姓名查找
void search_year(); //按工龄查找
void Sort(); //按工号插入排序
void order(); //冒泡排序
void Analyse(); //职工数据统计
//主函数
int main()
{
int button, flag;
while (1)
{
do {
Menu(); //调用菜单函数
printf("请输入你需要操作的序号(1-9): ");
scanf("%d", &button);
if (button >= 1 && button <= 9) {
flag = 1; break;
}
else {
flag = 0;
system("cls"); //清屏
printf("\n\t\t\t您输入有误,请重新选择!");
}
} while (flag == 0);
switch (button) {
case 1: system("cls");
printf("\n");
printf("\t\t录入职工信息\n");
Input();
break;
case 2: system("cls");
printf("\n");
printf("\t\t输出职工信息\n");
Output();
printf("\n按Enter键返回菜单\n");
getchar(); //读取换行符
getchar(); //让程序暂停,等待输入
system("cls");
break;
case 3: system("cls");
printf("\n");
printf("\t\t添加职工信息\n");
Addition();
break;
case 4: system("cls");
printf("\n");
printf("\t\t修改职工信息\n");
Output(); //调用输出函数
Modify();
break;
case 5: system("cls");
printf("\n");
printf("\t\t删除职工信息\n");
Delete();
break;
case 6: system("cls");
printf("\n");
printf("\t\t查找职工信息\n");
Search();
break;
case 7: system("cls");
printf("\n");
printf("\t\t职工信息排序\n");
Sort();
break;
case 8: system("cls");
printf("\n");
printf("\t\t职工工资数据统计\n");
Analyse();
break;
case 9: system("cls");
printf("\n\n\n\t\t\tThank you for using !\n\n\n");
getchar();
system("pause");
exit(0);
break;
}
}
}
void save(int m) /*保存文件函数*/
{
int i;
FILE* fp;
if ((fp = fopen("clerk_list.txt", "wb")) == NULL)//创建文件并判断是否能打开
{
printf("open file error!\n");
exit(0);
}
/*将内存中职工信息输出到磁盘文件中去*/
for (i = 0; i < m; i++)
{
/* 二进制模式,可保证数值精度在储存前后保持一致 */
if (fwrite(&staff[i], sizeof(struct employee), 1, fp) != 1)
/* &staff[i]:要输出数据的地址,sizeof(struct empioyee):获取一个单体的
长度,1:数据项的个数,fp:目标文件指针*/
printf("file write error!\n");
}
fclose(fp);
}
int read() /*导入函数*/
{
FILE* fp;
int i = 0;
if ((fp = fopen("clerk_list.txt", "rb")) == NULL)
{
printf("open flie error!\n");
exit(0);
}
else {
do {
fread(&staff[i], sizeof(struct employee), 1, fp);//读取
i++;
} while (feof(fp) == 0); //检测流上的文件结束符,没有检测到结尾时,返回0
}
fclose(fp);
return(i - 1); //返回人数
}
#include "test.h"
/* 录入函数 */
void Input()
{
int i, m, number = 0;
printf("请输入需要创建信息的职工人数(1—100)\n");
scanf("%d", &m);
system("cls");
if (m > 100) {
printf("\t\t\t超出范围,请重新输入!\n");
Input();
}
else {
for (i = 0; i < m; i++)
{
printf("第%d个职工信息输入(按回车确认):\n", i + 1);
printf("请输入工号:");
scanf("%d", &number);
for (int j = 0; j < i; j++) {
if (staff[j].num == number)
{
printf("工号为%d的人已存在,请重新输入:",number);
scanf("%d", &number);
j = 0;
}
}
staff[i].num = number;
printf("请输入姓名:");
scanf("%s", &staff[i].name);
printf("请输入工龄(单位:年):");
scanf("%d", &staff[i].year);
printf("请输入周工作时长(单位:小时):");
scanf("%d", &staff[i].duration);
if (staff[i].year >= 5) {
strcpy(staff[i].category, "老职工");
if (staff[i].duration <= 40)
{
staff[i].wage = 50.0 * staff[i].duration;
}
else {
staff[i].wage = 2000.0 + 75.0 * (staff[i].duration - 40);
}
}
else {
strcpy(staff[i].category, "新职工");
if (staff[i].duration <= 40)
{
staff[i].wage = 30.0 * staff[i].duration;
}
else {
staff[i].wage = 1200.0 + 45.0 * (staff[i].duration - 40);
}
}
system("cls");
}
save(m);
printf("\n一个新的职工档案创建完毕!\n");
printf("\n按Enter键返回菜单\n");
getchar();
getchar();
system("cls");
}
}
/* 输出信息函数 */
void Output()
{
int i;
int m = read();
printf("\n\t--------------------------------公司职工信息--------------------------------\n");
printf("\n\t| 工号\t\t姓名\t工龄(年)\t类别\t周工作时长(时)\t周工资(元) | \n");
order();
for (i = 0; i < m; i++)
printf("\n%15d\t\t%s\t %d\t\t%s\t\t%d\t%8.2f\n", staff[i].num, staff[i].name,
staff[i].year, staff[i].category, staff[i].duration, staff[i].wage);
printf("\n");
}
#include "test.h"
/* 添加函数 */
void Addition()
{
int m = read();
int i, n, j, number;
printf("请输入需要添加信息的职工人数:");
scanf("%d", &n);
if (m + n > 100) {
printf("\n 对不起,您添加的职工人数超过范围!请重新输入(1到%d之间):", 100 - m);
Addition();
}
else {
for (i = m; i < m + n; i++) //从原始职工的末尾加1处录入
{
printf("第%d个职工的信息录入(按回车确认):\n", i + 1);
printf("请输入工号:");
scanf("%d", &number);
for (j = 0; j < i; j++) {
if (staff[j].num == number)
{
printf("\n工号为%d的人已存在,请重新输入:", number);
scanf("%d", &number);
j = 0;
}
}
staff[i].num = number;
printf("请输入姓名:");
scanf("%s", &staff[i].name);
printf("请输入工龄(单位:年):");
scanf("%d", &staff[i].year);
printf("请输入周工作时长(单位:小时):");
scanf("%d", &staff[i].duration);
if (staff[i].year >= 5) {
strcpy(staff[i].category, "老职工");
if (staff[i].duration <= 40)
{
staff[i].wage = 50.0 * staff[i].duration;
}
else {
staff[i].wage = 2000.0 + 75.0 * (staff[i].duration - 40);
}
}
else {
strcpy(staff[i].category, "新职工");
if (staff[i].duration <= 40)
{
staff[i].wage = 30.0 * staff[i].duration;
}
else {
staff[i].wage = 1200.0 + 45.0 * (staff[i].duration - 40);
}
}
system("cls");
}
save(m+n);
system("cls");
printf("\n添加职工档案成功!\n");
Output();
printf("\n按Enter键返回菜单\n");
getchar();
getchar();
system("cls");
}
}
/* 删除函数 */
void Delete()
{
int m = read();
/* i,j用于循环,t,n充当按钮,flag是标志 */
int i, j, t, n, flag, number;
Output(); //调用输出函数
printf("请输入要删除的职工的工号:");
scanf("%d", &number);
system("cls");
for (flag = 1, i = 0; flag==1 && i < m ; i++)
{
if (staff[i].num == number)
{
printf("已找到此人,原始信息为:\n");
printf("\n 工号\t\t姓名\t工龄(年)\t类别\t周工作时长(时)\t周工资(元) \n");
printf("\n %d\t\t%s\t %d\t\t%s\t\t%d\t%8.2f\n", staff[i].num, staff[i].name,
staff[i].year, staff[i].category, staff[i].duration, staff[i].wage);
printf("确认删除请按1,取消删除请按0:");
scanf("%d", &t);
if (t == 1)
{
/* 如果删除,后面其他职工信息都向前移一位 */
for (j = i; j < m - 1; j++)
staff[j] = staff[j + 1];
flag = 0;
}
else flag = 2;
}
}
system("cls");
switch (flag)
{
case 0:m = m - 1;
printf("\n\t\t\t删除成功!\n");
save(m); //调用保存函数
Output(); //调用输出函数
break;
case 1:printf("\n\t\t\t对不起,公司没有该员工!\n");
Output();
break;
case 2:printf("\n\t\t\t取消删除!\n");
break;
}
printf("\n继续删除请按1,返回菜单请按0:");
scanf("%d", &n);
system("cls");
switch (n)
{
case 1:Delete();
break;
case 0:main();
break;
default: break;
}
system("cls");
}
/* 修改函数 */
void Modify()
{
int num; //工号
char name[10] = { 0 }; //姓名
int year; //工龄
char category[10] = { 0 }; //员工类别
int duration; //周工作时长
float wage; //周工资
int m = read();
/* a,b,c,d都充当按钮,i用于循环,flag是标志 */
int a, b, c, d, i, flag = 0;
printf("\n");
printf("请输入要修改的职工的工号:");
scanf("%d", &num);
system("cls");
for (i = 0; i < m; i++)
{
if (staff[i].num == num)
{
flag = 1;
printf("\n已找到该职工,其信息为:\n");
printf("\n 工号\t\t姓名\t工龄(年)\t类别\t周工作时长(时)\t周工资(元) \n");
printf("\n %d\t\t%s\t %d\t\t%s\t\t%d\t%8.2f\n", staff[i].num, staff[i].name,
staff[i].year, staff[i].category, staff[i].duration, staff[i].wage);
printf("\n确认修改请按1,取消修改请按0:");
scanf("%d", &a);
if (a == 1)
{
printf("\n需要进行修改的选项:\n 1.工号 2.姓名 3.工龄 4.周工作时长\n");
printf("请输入要修改的选项的序号:");
scanf("%d", &b);
do {
switch (b)
{
case 1:printf("请输入修改后工号:");
scanf("%d", &num);
staff[i].num = num;
break;
case 2:printf("请输入修改后姓名:");
scanf("%s", &name);
strcpy(staff[i].name, name);
break;
case 3:printf("请输入修改后工龄:");
scanf("%d", &year);
staff[i].year = year;
if (year >= 5) {
strcpy(staff[i].category, "老职工");
if (staff[i].duration <= 40)
{
staff[i].wage = 50.0 * staff[i].duration;
}
else {
staff[i].wage = 2000.0 + 75.0 * (staff[i].duration - 40);
}
}
else {
strcpy(staff[i].category, "新职工");
if (staff[i].duration <= 40)
{
staff[i].wage = 30.0 * staff[i].duration;
}
else {
staff[i].wage = 1200.0 + 45.0 * (staff[i].duration - 40);
}
}
break;
case 4:printf("请输入修改后周工作时长:");
scanf("%d", &duration);
staff[i].duration = duration;
if (staff[i].year >= 5) {
if (staff[i].duration <= 40)
{
staff[i].wage = 50.0 * staff[i].duration;
}
else {
staff[i].wage = 2000.0 + 75.0 * (staff[i].duration - 40);
}
}
else {
if (staff[i].duration <= 40)
{
staff[i].wage = 30.0 * staff[i].duration;
}
else {
staff[i].wage = 1200.0 + 45.0 * (staff[i].duration - 40);
}
}
break;
}
printf("\n 确认修改请按1,重新输入请按2:");
scanf("%d", &c);
if (c == 1)
{
system("cls");
save(m);
printf("\n");
Output();
}
} while (c == 2);
}
}
//将职工遍历完后,自动退出循环
}
if (flag == 0)
{
printf("\n\t\t该职工不存在!\n");
printf("\n继续修改请按1,返回菜单请按0:");
scanf("%d", &d);
}
else {
printf("\n继续修改请按1,返回菜单请按0:");
scanf("%d", &d);
}
system("cls");
switch (d)
{
case 1:Output();
Modify();
break;
case 0:main();
break;
default:break;
}
system("cls");
}
/* 查找函数 */
void Search()
{
int button, flag ;
do {
printf("\n 按工号查询请按1,按姓名查询请按2,按工龄查询请按3,返回菜单请按0:");
scanf("%d", &button);
if (button >= 0 && button <= 3)
{
flag = 1;
break;
}
else {
flag = 0;
printf("\n您输入有误!请重新选择:");
}
} while (flag == 0);
system("cls");
while (flag == 1)
{
switch (button)
{
case 0:main();
break;
case 1:search_num();
break;
case 2:search_name();
break;
case 3:search_year();
break;
default:break;
}
system("cls");
}
}
void search_num() /* 按工号查找函数*/
{
int m = read();
int start, end, mid = 0, number = 0, i, button;
start = staff[0].num; //标记起始的工号
end = staff[m - 1].num; //标记末尾的工号
printf("\n请输入要查询的职工的工号:");
scanf("%d", &number);
while (start <= end)
{
mid = (start + end) / 2;
if (number < mid)
{
end = mid - 1;
}
else if (number > mid) {
start = mid + 1;
}
else {
break;
}
}
system("cls");
if (start <= end)
{
printf("\n已找到该员工,其信息为:");
printf("\n 工号\t\t姓名\t工龄(年)\t类别\t周工作时长(时)\t周工资(元) \n");
for (i = 0; i < m; i++) //通过循环匹配,将此人信息输出
{
if(staff[i].num==mid)
printf("\n %d\t\t%s\t %d\t\t%s\t\t%d\t%8.2f\n", staff[i].num, staff[i].name,
staff[i].year, staff[i].category, staff[i].duration, staff[i].wage);
}
printf("\n删除员工请按1,修改信息请按2,继续查询请按3,返回上一级请按4,返回菜单请按0:");
scanf("%d", &button);
switch (button)
{
case 0:system("cls");
main();
break;
case 1:Delete();
break;
case 2:Modify();
break;
case 3:break;
case 4:system("cls");
Search();
break;
default:break;
}
}
else { //遍历完,start>end,说明没有找到
printf("\n\t\t对不起,公司没有该员工!\n");
printf("\n\t\t按Enter键返回上一级\n");
getchar();
getchar();
system("cls");
Search();
}
}
void search_name() /* 按姓名查找函数 */
{
int m = read();
char name[10] = { 0 };
int i, button, flag = 0; //flag相当于符合要求的人数
printf("\n请输入要查找的姓名:");
scanf("%s", &name);
for (i = 0; i < m; i++)
{
if (strcmp(staff[i].name, name) == 0) //名字相同返回0
{
if (flag == 0)
{
printf("\n找到以下信息:\n");
printf("\n 工号\t\t姓名\t工龄(年)\t类别\t周工作时长(时)\t周工资(元) \n");
}
flag++;
printf("\n %d\t\t%s\t %d\t\t%s\t\t%d\t%8.2f\n", staff[i].num, staff[i].name,
staff[i].year, staff[i].category, staff[i].duration, staff[i].wage);
}
}
if (flag == 0)
{
printf("\n\t对不起,公司没有该员工!\n");
printf("\t按Enter键返回上一级\n");
getchar();
getchar();
system("cls");
Search();
}
else {
printf("\n查询到有%d个员工符合要求。\n", flag);
printf("\n删除员工请按1,修改信息请按2,继续查询请按3,返回上一级请按4,返回菜单请按0:");
scanf("%d", &button);
switch (button)
{
case 0:system("cls");
main();
break;
case 1:Delete();
break;
case 2:Modify();
break;
case 3:break;
case 4:system("cls");
Search();
break;
default:break;
}
}
}
void search_year() /* 按工龄查找函数 */
{
int m = read();
int year;
int i, button, flag = 0; //flag相当于符合要求的人数
printf("\n请输入要查找的工龄:");
scanf("%d", &year);
for (i = 0; i < m; i++)
{
if (staff[i].year == year)
{
if (flag == 0)
{
printf("\n找到以下信息:\n");
printf("\n 工号\t\t姓名\t工龄(年)\t类别\t周工作时长(时)\t周工资(元) \n");
}
flag++;
printf("\n %d\t\t%s\t %d\t\t%s\t\t%d\t%8.2f\n", staff[i].num, staff[i].name,
staff[i].year, staff[i].category, staff[i].duration, staff[i].wage);
}
}
if (flag == 0)
{
printf("\n\t对不起,公司没有该员工!\n");
printf("\t按Enter键返回上一级\n");
getchar();
getchar();
system("cls");
Search();
}
else {
printf("\n查询到有%d个员工符合要求。\n", flag);
printf("\n删除员工请按1,修改信息请按2,继续查询请按3,返回上一级请按4,返回菜单请按0:");
scanf("%d", &button);
switch (button)
{
case 0:system("cls");
main();
break;
case 1:Delete();
break;
case 2:Modify();
break;
case 3:break;
case 4:system("cls");
Search();
break;
default:break;
}
}
}
#include "test.h"
/* 统计显示每小时平均工资以及最高工资员工姓名 */
void Analyse()
{
int m = read();
/* i,j用于循环,key用于记录最高工资员工的人数,H[N]记录员工在文件中的位置 */
int i, j = 0, key = 0, H[N] = { 0 };
float most = staff[0].wage; //most记录最高工资
double sum = 0, avg = 0; //sum是工资总和,avg是每小时平均工资
for (i = 0; i < m; i++)
{
sum += staff[i].wage;
if (most < staff[i + 1].wage && i < m - 1)
{
most = staff[i + 1].wage; //找出最高工资
}
}
for (i = 0; i < m ; i++)
{
/* 记录工资与most相同的员工 */
while (j < N && staff[i].wage == most)
{
H[j] = i;
key = j;
j++;
break;
}
}
avg = sum / (m - 1);
printf("\n\t公司全体员工每小时平均工资为:%8.2f\n",avg);
printf("\n\t其中最高工资员工信息为:\n");
printf("\n 工号\t\t姓名\t工龄(年)\t类别\t周工作时长(时)\t周工资(元) \n");
for (j = 0; j <= key; j++)
{
printf("\n %d\t\t%s\t %d\t\t%s\t\t%d\t%8.2f\n", staff[H[j]].num, staff[H[j]].name,
staff[H[j]].year, staff[H[j]].category, staff[H[j]].duration, staff[H[j]].wage);
}
printf("\n\t按Enter键返回菜单\n");
getchar();
getchar();
system("cls");
}
#include "test.h"
void Sort() /* 用于主菜单调用 */
{
//选择排序法
int i, j, min;
int m = read();
for (i = 0; i < m-1; i++)
{
min = i;
for (j = i + 1; j < m; j++) //走访未排序的元素
if (staff[j].num < staff[min].num) //找到目前最小值
min = j; //记录最小值
if (min != i) {
temp = staff[min];
staff[min] = staff[i];
staff[i] = temp;
}
}
save(m); /* 按工号由小到大顺序储存 */
printf("\n\t排序后职工信息:\n");
printf("\n 工号\t\t姓名\t工龄(年)\t类别\t周工作时长(时)\t周工资(元) \n");
for (i = 0; i < m; i++)
printf("\n %d\t\t%s\t %d\t\t%s\t\t%d\t%8.2f\n", staff[i].num, staff[i].name,
staff[i].year, staff[i].category, staff[i].duration, staff[i].wage);
printf("\n");
printf("\n按Enter键返回菜单\n");
getchar();
getchar();
system("cls");
}
void order() /* 输出信息时,按工号由小到大顺序排序 */
{
int i, j;
int m = read();
//冒泡法排序
for (i = 0; i < m - 1; i++) {
for (j = 0; j < m - 1 - i; j++) {
if (staff[j].num > staff[j + 1].num)
{
temp = staff[j];
staff[j] = staff[j + 1];
staff[j + 1] = temp;
}
}
}
save(m); /* 按工号由小到大顺序储存 */
}
#include "test.h"
/* 菜单函数 */
void Menu() {
system("cls");
system("color E0");//背景色为淡黄色,前景色为黑色
printf("\n\n");
printf(" Welcome to \n");
printf(" Staff Information Management System (SIMS) \n\n");
printf("*****************************************************************\n");
printf("* 1.录入职工信息"); printf(" § 2.输出职工信息 *\n");
printf("* 3.添加职工信息"); printf(" § 4.修改职工信息 *\n");
printf("* 5.删除职工信息"); printf(" § 6.查找职工信息 *\n");
printf("* 7.职工信息排序"); printf(" § 8.职工工资统计 *\n");
printf("* 9.退出职工系统 § *\n");
printf("*****************************************************************\n");
printf("说明:*如首次使用 尚未输入数据 请先输入数据 \n *输入的数据将自动保存 \n\
*录入职工信息时请使用连续的工号 \n *再次选择输入功能时原数据将被覆盖\n\n");
}
#pragma once
#ifndef _HEAD_H_ //判断该文件内有没有定义过这个宏
#define _HEAD_H_ //若没有则定义
/* 该头文件包括了测试的文件信息 */
#include
#include
#include
#define N 100
//职工信息结构体
struct employee {
int num; //工号
char name[10]; //姓名
int year; //工龄
char category[10];//员工类别
int duration; //周工作时长
float wage; //周工资
}staff[N], temp; //temp用于排序时充当中间变量
//主函数
int main();
//功能函数声明
void Menu(); //菜单函数
void Input(); //输入职工信息
void save(int m); //储存信息
int read(); //读取信息
void Output(); //输出信息
void Addition(); //添加操作
void Modify(); //修改操作
void Delete(); //删除操作
void Search(); //查找函数
void search_num(); //按工号折半查找
void search_name(); //按姓名查找
void search_year(); //按工龄查找
void Sort(); //按工号插入排序
void order(); //供输出信息函数调用
void Analyse(); //职工数据统计
#endif // !_HEAD_H_ 结束
展示: