#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#define inf 0x3f3f3f
typedef struct {
char id[50];
char name[50];
char gender[50];
char birth[50];
double sal;
double bu;
double ko;
double x;
} Employee;
typedef struct date {
int y;
int m;
int d;
}Date;
Employee e[5000];
#define W "test.txt"
int isValidID(char* id);
int isValidName(char* name);
int isValidGender(char* gender);
int isValidDate(char* date);
int isValidSalary(double salary);
void menu();
int ReadFile();
int WriteFile(const Employee tmp);
int count = 0;
void I();
void O();
void T();
void S();
void F();
void D();
void Q();
int main() {
if (ReadFile() == -1) {
printf("读取文件失败或文件为空!\n");
}
char c;
while (1) {
menu();
scanf("%c", &c);
switch (c) {
case 'I': I(); break;
case 'O': O(); break;
case 'T': T(); break;
case 'S': S(); break;
case 'F': F(); break;
case 'D': D(); break;
case 'Q': exit(0);
default: printf("无效输入,请重新选择。\n"); break;
}
}
}
void menu() {
printf("****************************************\n");
printf("* I:输入员工工资信息 *\n");
printf("* O:输出员工工资信息 *\n");
printf("* T:输出员工工资统计信息 *\n");
printf("* S:按要求排序后输出员工工资信息 *\n");
printf("* F:按员工号查找并输出其工资信息 *\n");
printf("* D:按员工号查找并删除其工资信息 *\n");
printf("* Q:退出系统 *\n");
printf("****************************************\n");
printf("请选择(I,O,T,S,F,D,Q): ");
}
int ReadFile() {
FILE* fp = fopen(W, "r");
if (fp == NULL) {
return -1;
}
char line[256];
while (fgets(line, sizeof(line), fp)) {
Employee tmp;
if (sscanf(line, "%s %s %s %s %lf %lf %lf", tmp.id, tmp.name, tmp.gender, tmp.birth, &tmp.sal, &tmp.bu, &tmp.ko) == 7) {
tmp.x = tmp.sal + tmp.bu - tmp.ko;
e[count++] = tmp;
}
}
fclose(fp);
return 0;
}
int WriteFile(const Employee tmp) {
FILE* fp = fopen(W, "a");
if (fp == NULL) {
return -1;
}
fprintf(fp, "%s %s %s %s %.2f %.2f %.2f\n", tmp.id, tmp.name, tmp.gender, tmp.birth, tmp.sal, tmp.bu, tmp.ko);
fclose(fp);
return 0;
}
int isValidID(char* id) {
if (strlen(id) != 4 || !isdigit(id[0]) || id[0] == '0')
{
if (strlen(id) != 4)printf("员工号\"%s\"长度必须为:4!\n",id);
if (id[0] == '0')printf("员工号第1位必须为1--9之间的数字!\n");
return 0;
}
for (int i = 1; i < strlen(id); i++)
{
if (!isdigit(id[i]))return 0;
}
for (int i = 1; i <= count; i++)
{
if (strcmp(id, e[i].id) == 0)
{
printf("员工号是员工信息的唯一标识,不允许重复!员工号\"%s\"已经存在。\n", id);
return 0;//重复
}
}
return 1;
}
int isValidName(char* name) {
if (strlen(name) >= 4 && strlen(name) <= 8)return 1;
else return 0;
}
int isValidGender(char* s) {
if (strcmp(s, "M") == 0 || strcmp(s, "m") == 0 || strcmp(s, "男") == 0)return 1;
if (strcmp(s, "F") == 0 || strcmp(s, "f") == 0 || strcmp(s, "女") == 0)return 1;
return 0;
}
int is_leap_year(int year) {
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
return 1;
}
else {
return 0;
}
}
int days_in_month(int y,int m)
{
int days[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (is_leap_year(y) && m == 2) return 29;
else return days[m];
}
int isValidD(const Date d)
{
if (d.y < 1 || d.y>2024 || d.m < 1 || d.m>12 || d.d > days_in_month(d.y, d.m))return 0;
return 1;
}
int isValidDate(char* date) {
Date d;
int age = 0;
/*出生日期格式:4位年 - 月 - 日 或 4位年.月.日(长度 <= 10)。
年龄必须在18~60之间(不考虑男女退休年龄的区别)。*/
if (!(sscanf(date, "%d-%d-%d", &d.y, &d.m, &d.d) == 3 || sscanf(date, "%d.%d.%d") == 3))return 0;
if (!isValidD(d))return 0;
age = 2024 - d.y;
if (age < 18 || age>60)return 0;
return 1;
}
int isValidSalary(double salary) {
return (salary >= 0 && salary <= 99999);
}
int compareByIdAsc(const void* a, const void* b) {
return strcmp(((Employee*)a)->id, ((Employee*)b)->id);
}
int compareByIdDesc(const void* a, const void* b) {
return strcmp(((Employee*)b)->id, ((Employee*)a)->id);
}
int compareByName(const void* a, const void* b) {
return strcmp(((Employee*)a)->name, ((Employee*)b)->name);
}
int compareByGender(const void* a, const void* b) {
return strcmp(((Employee*)a)->gender, ((Employee*)b)->gender);
}
int compareByAgeAsc(const void* a, const void* b) {
int ageA = 2024 - atoi(((Employee*)a)->birth);
int ageB = 2024 - atoi(((Employee*)b)->birth);
return ageA - ageB;
}
int compareByAgeDesc(const void* a, const void* b) {
int ageA = 2024 - atoi(((Employee*)a)->birth);
int ageB = 2024 - atoi(((Employee*)b)->birth);
return ageB - ageA;
}
int compareBySalaryAsc(const void* a, const void* b) {
double salaryA = ((Employee*)a)->sal + ((Employee*)a)->bu - ((Employee*)a)->ko;
double salaryB = ((Employee*)b)->sal + ((Employee*)b)->bu - ((Employee*)b)->ko;
return (salaryA > salaryB) - (salaryA < salaryB);
}
int compareBySalaryDesc(const void* a, const void* b) {
double salaryA = ((Employee*)a)->sal + ((Employee*)a)->bu - ((Employee*)a)->ko;
double salaryB = ((Employee*)b)->sal + ((Employee*)b)->bu - ((Employee*)b)->ko;
return (salaryB > salaryA) - (salaryB < salaryA);
}
void I() {
printf("请输入不超过4973名员工的员工信息:\n");
printf("员工号、姓名、性别、出生日期、岗位工资、补贴总额、代扣总额。\n");
printf("输入项目之间必须用<空格>分开!\n");
printf("例如:1010 伍惺委 男 1990-10-20 3220 1500 300 <回车>\n\n");
printf("要求:\n");
printf("1、员工号是员工信息的唯一标识,不允许重复,长度 <= 4,格式:第1位为1--9之间的数字,后面的字符可以是任意数字。\n");
printf("2、姓名必须是2个以上的汉字,最多4个汉字。\n");
printf("3、性别只能是男(M)或女(F)。\n");
printf("4、出生日期格式:4位年-月-日 或 4位年.月.日(长度 <= 10)。\n");
printf(" 年龄必须在18~60岁之间。\n");
printf("5、岗位工资、补贴总额、代扣总额必须在0到99999之间。\n\n");
printf("如果不想继续输入数据,请按 A <回车> 结束输入。\n");
while (1) {
Employee tmp;
scanf("%s", tmp.id); if (strcmp(tmp.id, "A") == 0) {
printf("\n");
break;
}
scanf("%s %s %s", tmp.name, tmp.gender, tmp.birth);
scanf("%lf %lf %lf", &tmp.sal, &tmp.bu, &tmp.ko);
tmp.x = tmp.sal + tmp.bu - tmp.ko;
printf("\n");
if (!isValidID(tmp.id))
{
printf("刚输入的员工数据有错,数据没有被保存!\n");
continue;
}
if (!isValidName(tmp.name))
{
printf("刚输入的员工数据有错,数据没有被保存!\n");
continue;
}
if (!isValidGender(tmp.gender))
{
printf("性别只能是\"男(M)\"或\"女(F)\"!\n");
printf("刚输入的员工数据有错,数据没有被保存!\n");
printf("\n");
continue;
}
if (!isValidDate(tmp.birth))
{
printf("出生日期\"%s\"长度必须<=10!格式:4位年-月-日 或 4位年.月.日\n", tmp.birth);
printf("刚输入的员工数据有错,数据没有被保存!\n");
printf("\n");
continue;
}
if (!isValidSalary(tmp.x))
{
printf("刚输入的员工数据有错,数据没有被保存!\n");
continue;
}
printf("\n");
WriteFile(tmp);
e[++count] = tmp;
}
printf("员工信息已保存。\n\n");
getchar();
}
void O() {
if (count == 0) {
printf("没有员工信息。\n");
return;
}
printf("\n");
printf("现有员工总数为:%d\n\n", count);
printf("员工号 姓名 性别 出生日期 岗位工资 补贴总额 代扣总额 应发工资\n");
printf("========================================================================\n");
for (int i = 0; i < count; i++) {
printf("%4s %6s %4s %-12s %6.2f %6.2f %6.2f %6.2f\n",
e[i].id, e[i].name, e[i].gender, e[i].birth, e[i].sal, e[i].bu, e[i].ko,e[i].x);
}
printf("========================================================================\n");
printf("\n");
getchar();
}
int Man(const char *s) {
printf("%s", s);
//if (s == "M" || s == "m" || s == "男")return 1;
if (strcmp(s, "M") == 0 || strcmp(s, "m") == 0 || strcmp(s, "男") == 0)return 1;
else return 0;
}
void T() {
if (count == 0) {
printf("没有员工信息。\n");
return;
}
double totalSalary = 0;
double totalBonus = 0;
double totalDeduction = 0;
double totalNetSalary = 0;
int ManCount = 0;
int WomanCount = 0;
double totalMan = 0;
double totalWoman = 0;
double maxSalary = -inf;
double minSalary = inf;
for (int i = 0; i < count; i++) {
totalSalary += e[i].sal;
totalBonus += e[i].bu;
totalDeduction += e[i].ko;
double tmp =e[i].x;
totalNetSalary += tmp;
if (maxSalary < tmp)maxSalary = tmp;
if (minSalary > tmp)minSalary = tmp;
if (Man(e[i].gender)==1)
{
ManCount++;
totalMan += tmp;
}
else
{
WomanCount++;
totalWoman += tmp;
}
}
printf("\n员工工资统计信息:\n");
printf("====================================\n");
printf("应发工资最高为:%.2f, 最低为:%.2f, 所有员工应发工资总额为:%.2f\n\n", maxSalary,minSalary, totalNetSalary);
printf("男性员工人数为:%d,女性员工人数为:%d\n\n", ManCount, WomanCount);
//printf("总岗位工资: %.2f\n", totalSalary);
// printf("总补贴总额: %.2f\n", totalBonus);
// printf("总代扣总额: %.2f\n", totalDeduction);
// printf("总应发工资: %.2f\n", totalNetSalary);
//printf("平均岗位工资: %.2f\n", totalSalary / count);
//printf("平均补贴总额: %.2f\n", totalBonus / count);
// printf("平均代扣总额: %.2f\n", totalDeduction / count);
printf("平均应发工资: %.2f(其中:男性平均值为:%.2f,女性平均值为:%.2f)\n", totalNetSalary / count,totalMan/ManCount,totalWoman/WomanCount);
printf("====================================\n");
getchar();
}
void S() {
if (count == 0) {
printf("没有员工信息。\n");
return;
}
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("q:不排序退出\n");
printf("================================\n");
printf("请选择(1--8和q):");
char choice;
scanf(" %c", &choice); // 用空格跳过缓冲区中的换行符
switch (choice) {
case '1':
qsort(e, count, sizeof(Employee), compareByIdAsc);
break;
case '2':
qsort(e, count, sizeof(Employee), compareByIdDesc);
break;
case '3':
qsort(e, count, sizeof(Employee), compareByName);
break;
case '4':
qsort(e, count, sizeof(Employee), compareByGender);
break;
case '5':
qsort(e, count, sizeof(Employee), compareByAgeAsc);
break;
case '6':
qsort(e, count, sizeof(Employee), compareByAgeDesc);
break;
case '7':
qsort(e, count, sizeof(Employee), compareBySalaryAsc);
break;
case '8':
qsort(e, count, sizeof(Employee), compareBySalaryDesc);
break;
case 'q':
return;
default:
printf("无效选择,请重新选择。\n");
return;
}
printf("\n排序后的员工信息:\n");
printf("员工号 姓名 性别 出生日期 岗位工资 补贴总额 代扣总额 应发工资\n");
printf("========================================================================\n");
for (int i = 0; i < count; i++) {
printf("%4s %6s %4s %-12s %6.2f %6.2f %6.2f %6.2f\n",
e[i].id, e[i].name, e[i].gender, e[i].birth, e[i].sal, e[i].bu, e[i].ko, e[i].x);
}
printf("========================================================================\n");
getchar();
}
void F() {
if (count == 0) {
printf("没有员工信息。\n");
return;
}
char id[50];
printf("请输入待查询的员工号:");
scanf("%s", id);
for (int i = 0; i < count; i++) {
if (strcmp(e[i].id, id) == 0) {
printf("\n");
printf("员工号 姓名 性别 出生日期 岗位工资 补贴总额 代扣总额 应发工资\n");
printf("%4s %6s %4s %-12s %6.2f %6.2f %6.2f %6.2f\n",
e[i].id, e[i].name, e[i].gender, e[i].birth, e[i].sal, e[i].bu, e[i].ko, e[i].sal + e[i].bu - e[i].ko);
printf("\n");
getchar();
return;
}
}
printf("\n");
printf("没有找到该员工。\n");
printf("\n");
getchar();
}
void D() {
if (count == 0) {
printf("没有员工信息。\n");
return;
}
char id[50];
printf("请输入待删除的员工号:");
scanf("%s", id);
for (int i = 0; i < count; i++) {
if (strcmp(e[i].id, id) == 0) {
for (int j = i; j < count - 1; j++) {
e[j] = e[j + 1];
}
count--;
printf("员工 [%s] 的信息已删除!\n", id);
getchar();
return;
}
}
printf("\n");
printf("没有找到该员工。\n");
printf("\n");
getchar();
}