C语言结构体实现职工工资管理系统源码与解析
本文详细介绍如何使用C语言的结构体和数组构建一个小型职工工资管理系统。代码实现了员工基本信息的录入、按工号修改、排序查询、数据删除以及男女职工数量统计等核心功能,适合用于程序设计的实践练习。
系统设计目标与核心逻辑
该工资管理系统旨在通过C语言的基础语法,展示如何处理结构化数据。系统采用结构体(struct)定义职工档案,包含工号、姓名、性别、部门、基本工资、绩效工资及奖金。其中,应发工资由系统在录入时自动计算,公式为:应发工资 = 基本工资 + 绩效工资 + 奖金。
功能模块说明
系统主菜单提供以下交互选项,用户可通过输入对应数字选择功能:
- 数据输入:支持批量录入职工信息。建议至少录入10条数据以测试系统稳定性。
- 数据修改:根据工号定位特定职工,更新其各项基本信息,并重新计算应发工资后展示全量更新结果。
- 数据处理:二级子菜单,提供“按工号排序”和“按工号查询”两种操作。排序采用冒泡算法思想进行字符串比较;查询则遍历数组匹配工号。
- 数据输出:格式化打印所有已录入职工的详细工资单。
- 数据删除:输入工号确认后,从数组中移除该记录并前移后续元素,保持数据结构紧凑。
- 统计男女职工数量:遍历数组比对性别字段,输出男、女职工的具体人数。
- 退出:终止程序运行。
完整代码实现
以下是经过整理的完整源代码。代码中使用了全局结构体数组 sta[10] 存储数据,并在各函数间通过引用传递或直接访问全局变量进行状态同步。请注意,原代码中的下标从1开始,实际使用时需确保录入数量不超过数组上限。
#include <stdio.h>
#include <string.h>
// 定义职工结构体
struct staff {
char number[20]; // 工号
char name[20]; // 姓名
char gender[10]; // 性别
char bumen[20]; // 部门
double jbgz; // 基本工资
double jxgz; // 绩效工资
double bonus; // 奖金
double yfgz; // 应发工资
};
// 全局变量声明
struct staff sta[10]; // 最多存储10名职工
// 函数原型声明
void inputdata();
void modifydata();
void processdata();
void sortdata();
void searchdata();
void outputdata();
void deldata();
void countgender();
int main() {
int i, choice;
while(1) {
// 绘制菜单边框
for(i=1; i<90; i++) printf("*");
printf("\n");
printf("1.数据输入 2.数据修改 3.数据处理 4.数据输出 5.数据删除 6.统计男女职工数量 7.退出\n");
for(i=1; i<90; i++) printf("*");
printf("\n");
// 获取有效菜单选项
do {
printf("请根据菜单输入数字:");
scanf("%d", &choice);
} while(choice != 1 && choice != 2 && choice != 3 && choice != 4 && choice != 5 && choice != 6 && choice != 7);
if(choice == 7) break;
else {
if(choice == 1) inputdata();
else if(choice == 2) modifydata();
else if(choice == 3) processdata();
else if(choice == 4) outputdata();
else if(choice == 5) deldata();
else if(choice == 6) countgender();
else printf("该数不合法;\n");
}
}
return 0;
}
// 1. 数据输入函数
void inputdata() {
int i;
for(i=1; i<=10; i++) {
printf("请输入第%d位职工的工号,姓名,性别,部门,基本工资,绩效工资,奖金:", i);
// 注意:scanf读取字符串时不需要&,但此处对char数组地址使用&也是合法的常见写法
scanf("%s %s %s %s %lf %lf %lf", &sta[i].number, &sta[i].name, &sta[i].gender, &sta[i].bumen, &sta[i].jbgz, &sta[i].jxgz, &sta[i].bonus);
sta[i].yfgz = sta[i].jbgz + sta[i].jxgz + sta[i].bonus;
printf("输入成功\n");
}
}
// 2. 数据修改函数
void modifydata() {
int i;
char num[20];
printf("请输入您想要修改职工的数据的工号:");
scanf("%s", &num);
for(i=1; i<10; i++) {
if(strcmp(num, sta[i].number) == 0) {
printf("请输入新工号,姓名,性别,部门,基本工资,绩效工资,奖金\n");
scanf("%s %s %s %s %lf %lf %lf", &sta[i].number, &sta[i].name, &sta[i].gender, &sta[i].bumen, &sta[i].jbgz, &sta[i].jxgz, &sta[i].bonus);
sta[i].yfgz = sta[i].jbgz + sta[i].jxgz + sta[i].bonus;
break;
}
}
printf("修改成功!\n");
printf("修改后的数据为:\n");
printf(" 工号 姓名 性别 部门 基本工资 绩效工资 奖金 应发工资\n");
// 输出全部修改后的数据(注:原逻辑仅输出了修改的那一位,此处保留原意或视需求调整为遍历输出)
for(i=1; i<=10; i++) {
if(sta[i].number[0] != '\0') // 简单判断非空
printf("%-10s %-8s %-6s %-8s %.2f %.2f %.2f %.2f\n", sta[i].number, sta[i].name, sta[i].gender, sta[i].bumen, sta[i].jbgz, sta[i].jxgz, sta[i].bonus, sta[i].yfgz);
}
}
// 3. 数据处理(排序/查询)
void processdata() {
int choice, i;
for(i=1; i<30; i++) printf("*");
printf("\n");
printf("二级菜单:\n");
printf("1.排序 2.查询\n");
for(i=1; i<30; i++) printf("*");
printf("\n");
printf("请根据菜单输入数字:");
scanf("%d", &choice);
if(choice == 1) sortdata();
else if(choice == 2) searchdata();
else printf("无效选择\n");
}
// 3.1 按工号排序
void sortdata() {
int i, j;
struct staff temp;
// 简单的冒泡排序,针对结构体整体交换更稳妥
for(i=1; i<=10; i++) {
for(j=i+1; j<=10; j++) {
if(strcmp(sta[i].number, sta[j].number) > 0) {
temp = sta[i];
sta[i] = sta[j];
sta[j] = temp;
}
}
}
outputdata(); // 排序完成后直接输出所有数据
}
// 3.2 按工号查询
void searchdata() {
int i;
char snum[20];
printf("请输入您想要查询的职工工号:");
scanf("%s", &snum);
for(i=1; i<=10; i++) {
if(strcmp(snum, sta[i].number) == 0) {
printf("该职工的数据为:\n");
printf(" 工号 姓名 性别 部门 基本工资 绩效工资 奖金 应发工资\n\n");
printf("%-10s %-10s %-10s %-10s %.2f %.2f %.2f %.2f\n", sta[i].number, sta[i].name, sta[i].gender, sta[i].bumen, sta[i].jbgz, sta[i].jxgz, sta[i].bonus, sta[i].yfgz);
break;
}
}
// 若循环结束未找到,可在此处添加“未找到”提示
}
// 4. 数据输出
void outputdata() {
int i;
printf(" 工号 姓名 性别 部门 基本工资 绩效工资 奖金 应发工资\n");
for(i=1; i<=10; i++) {
if(sta[i].number[0] != '\0') {
printf("%-10s %-10s %-10s %-10s %.2f %.2f %.2f %.2f\n", sta[i].number, sta[i].name, sta[i].gender, sta[i].bumen, sta[i].jbgz, sta[i].jxgz, sta[i].bonus, sta[i].yfgz);
}
}
}
// 5. 数据删除
void deldata() {
int i, j, choi;
char delnum[20];
printf("请输入您想要删除职工数据的工号:");
scanf("%s", &delnum);
for(i=1; i<=10; i++) {
if(strcmp(delnum, sta[i].number) == 0) {
printf("该职工的数据为:\n");
printf(" 工号 姓名 性别 部门 基本工资 绩效工资 奖金 应发工资\n");
printf("%-10s %-10s %-10s %-10s %.2f %.2f %.2f %.2f\n", sta[i].number, sta[i].name, sta[i].gender, sta[i].bumen, sta[i].jbgz, sta[i].jxgz, sta[i].bonus, sta[i].yfgz);
printf("确认删除该名职工的数据吗?(1.确认 2.取消)\n");
scanf("%d", &choi);
if(choi == 1) {
// 将后续元素前移覆盖当前元素
for(j=i; j<10; j++) {
strcpy(sta[j].number, sta[j+1].number);
strcpy(sta[j].name, sta[j+1].name);
strcpy(sta[j].gender, sta[j+1].gender);
strcpy(sta[j].bumen, sta[j+1].bumen);
sta[j].jbgz = sta[j+1].jbgz;
sta[j].jxgz = sta[j+1].jxgz;
sta[j].bonus = sta[j+1].bonus;
sta[j].yfgz = sta[j+1].yfgz;
// 清空最后一个位置,防止脏数据
sta[10].number[0] = 0;
sta[10].name[0] = 0;
sta[10].gender[0] = 0;
sta[10].bumen[0] = 0;
}
printf("删除成功!!\n");
}
break;
}
}
}
// 6. 统计男女职工数量
void countgender() {
int i, count=0, fecount=0;
char gen[10]="男";
for(i=1; i<=10; i++) {
if(sta[i].number[0] == '\0') continue; // 跳过空位
if(strcmp(gen, sta[i].gender) == 0)
count++;
else
fecount++;
}
printf("该公司有%d名男职工,有%d名女职工\n", count, fecount);
}
注意事项与优化建议
在实际应用或课程作业提交中,建议关注以下几点以完善系统健壮性:
- 动态扩容:当前数组固定为10人。若需管理更多员工,建议改用动态内存分配(
malloc)或扩大数组容量。 - 下标一致性:原代码部分循环从1开始至10,而数组索引通常为0-9。在维护代码时,建议统一标准,避免越界访问或逻辑遗漏。
- 输入验证:增加对工号唯一性的检查,防止重复录入导致的数据混乱。
以上就是C语言实现小型工资管理系统的详细内容,更多关于C语言结构体编程技巧的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









