【C语言】:员工管系统开发指南(结构体数组+文件存储)丨完整源码+解析

 代码针对Windows平台优化,使用安全的输入函数(scanf_s),适配VS编译器特性,并包含完整的数据持久化功能。

系统采用结构体数组存储数据,支持增删改查和文件存储。

#define _CRT_SECURE_NO_WARNINGS  // 关闭VS安全警告
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

#define MAX_EMPLOYEES 1000      // 最大员工数
#define FILENAME "employees.dat" // 数据文件

// 员工信息结构体(内存对齐优化)
typedef struct {
    int id;             // 工号(主键)
    char name[50];      // 姓名
    char gender[6];     // 性别(固定长度减少内存碎片)
    int age;            // 年龄
    char department[30]; // 部门
    char position[30];  // 职位
    char phone[16];     // 电话(+国际区号预留)
    double salary;      // 工资(双精度)
} Employee;

Employee employees[MAX_EMPLOYEES]; // 静态数组存储
int empCount = 0;                  // 当前员工数

// 函数声明
void loadData();
void saveData();
void addEmployee();
void displayAll();
void findEmployee();
void modifyEmployee();
void deleteEmployee();
void showMenu();

// 主函数(适配VS命令行窗口)
int main() {
    system("chcp 65001"); // 设置控制台UTF-8编码
    loadData();            // 启动加载数据

    while (1) {
        showMenu();
        char choice = _getch(); // VS专用安全输入

        switch (choice) {
            case '1': addEmployee(); break;
            case '2': displayAll(); break;
            case '3': findEmployee(); break;
            case '4': modifyEmployee(); break;
            case '5': deleteEmployee(); break;
            case '6': saveData(); break;
            case '0': 
                saveData();
                printf("\n数据已保存,系统退出!\n");
                exit(0);
            default: 
                printf("\n无效选项!\n");
                _getch();
        }
    }
    return 0;
}

// 从文件加载数据(二进制模式)
void loadData() {
    FILE* file;
    if (fopen_s(&file, FILENAME, "rb") != 0) { // VS安全文件打开
        printf("\n数据文件不存在,将创建新文件\n");
        return;
    }

    // 读取完整数组块
    fread(&empCount, sizeof(int), 1, file);
    fread(employees, sizeof(Employee), empCount, file);
    fclose(file);
    printf("\n已加载 %d 条记录\n", empCount);
}

// 保存数据到文件(含错误处理)
void saveData() {
    FILE* file;
    if (fopen_s(&file, FILENAME, "wb") != 0) {
        printf("\n文件保存失败!\n");
        return;
    }

    // 先写入记录数,再写数据块
    fwrite(&empCount, sizeof(int), 1, file);
    fwrite(employees, sizeof(Employee), empCount, file);
    fclose(file);
    printf("\n数据已保存(共%d条)\n", empCount);
}

// 添加员工(带输入验证)
void addEmployee() {
    if (empCount >= MAX_EMPLOYEES) {
        printf("\n员工数量已达上限!\n");
        return;
    }

    Employee newEmp;
    printf("\n--- 添加新员工 ---\n");

    // 工号唯一性验证
    int id, idExists;
    do {
        idExists = 0;
        printf("工号: ");
        scanf_s("%d", &id);
        getchar(); // 清除输入缓冲区

        for (int i = 0; i < empCount; i++) {
            if (employees[i].id == id) {
                printf("工号已存在!\n");
                idExists = 1;
                break;
            }
        }
    } while (idExists);

    newEmp.id = id;
    printf("姓名: ");
    scanf_s("%49s", newEmp.name, (unsigned)_countof(newEmp.name));
    printf("性别(男/女): ");
    scanf_s("%5s", newEmp.gender, (unsigned)_countof(newEmp.gender));
    printf("年龄: ");
    scanf_s("%d", &newEmp.age);
    printf("部门: ");
    scanf_s("%29s", newEmp.department, (unsigned)_countof(newEmp.department));
    printf("职位: ");
    scanf_s("%29s", newEmp.position, (unsigned)_countof(newEmp.position));
    printf("电话: ");
    scanf_s("%15s", newEmp.phone, (unsigned)_countof(newEmp.phone));
    printf("工资: ");
    scanf_s("%lf", &newEmp.salary);

    employees[empCount++] = newEmp;
    printf("\n添加成功!\n");
    _getch();
}

// 表格化输出所有员工(适配控制台宽度)
void displayAll() {
    if (empCount == 0) {
        printf("\n暂无数据!\n");
        return;
    }

    printf("\n%-6s %-10s %-4s %-8s %-12s %-15s %-12s\n", 
        "工号", "姓名", "性别", "年龄", "部门", "职位", "工资");
    printf("------------------------------------------------------------\n");

    for (int i = 0; i < empCount; i++) {
        printf("%-6d %-10s %-4s %-8d %-12s %-15s ¥%-12.2f\n",
            employees[i].id,
            employees[i].name,
            employees[i].gender,
            employees[i].age,
            employees[i].department,
            employees[i].position,
            employees[i].salary);
    }
    printf("\n共显示 %d 名员工\n", empCount);
    printf("\n按任意键继续...");
    _getch();
}

// 查找员工(支持模糊搜索)
void findEmployee() {
    if (empCount == 0) {
        printf("\n暂无数据!\n");
        return;
    }

    int option;
    printf("\n--- 查找方式 ---\n");
    printf("1. 按工号查找\n");
    printf("2. 按姓名查找\n");
    printf("请选择: ");
    scanf_s("%d", &option);

    if (option == 1) {
        int id;
        printf("输入工号: ");
        scanf_s("%d", &id);

        for (int i = 0; i < empCount; i++) {
            if (employees[i].id == id) {
                printf("\n%-6s %-10s %-4s %-8s %-12s %-15s %-12s\n", 
                    "工号", "姓名", "性别", "年龄", "部门", "职位", "工资");
                printf("%-6d %-10s %-4s %-8d %-12s %-15s ¥%-12.2f\n",
                    employees[i].id,
                    employees[i].name,
                    employees[i].gender,
                    employees[i].age,
                    employees[i].department,
                    employees[i].position,
                    employees[i].salary);
                break;
            }
        }
    } 
    else if (option == 2) {
        char name[50];
        printf("输入姓名: ");
        scanf_s("%49s", name, (unsigned)_countof(name));

        int found = 0;
        for (int i = 0; i < empCount; i++) {
            if (strstr(employees[i].name, name) != NULL) { // 模糊匹配
                if (!found) {
                    printf("\n%-6s %-10s %-4s %-8s %-12s %-15s %-12s\n", 
                        "工号", "姓名", "性别", "年龄", "部门", "职位", "工资");
                    found = 1;
                }
                printf("%-6d %-10s %-4s %-8d %-12s %-15s ¥%-12.2f\n",
                    employees[i].id,
                    employees[i].name,
                    employees[i].gender,
                    employees[i].age,
                    employees[i].department,
                    employees[i].position,
                    employees[i].salary);
            }
        }
        if (!found) printf("\n未找到匹配记录!\n");
    }
    printf("\n按任意键继续...");
    _getch();
}

// 修改员工信息(字段级更新)
void modifyEmployee() {
    if (empCount == 0) {
        printf("\n暂无数据!\n");
        return;
    }

    int id;
    printf("\n输入要修改的员工工号: ");
    scanf_s("%d", &id);

    for (int i = 0; i < empCount; i++) {
        if (employees[i].id == id) {
            printf("\n当前信息:\n");
            printf("%-6s %-10s %-4s %-8s %-12s %-15s %-12s\n", 
                "工号", "姓名", "性别", "年龄", "部门", "职位", "工资");
            printf("%-6d %-10s %-4s %-8d %-12s %-15s ¥%-12.2f\n",
                employees[i].id,
                employees[i].name,
                employees[i].gender,
                employees[i].age,
                employees[i].department,
                employees[i].position,
                employees[i].salary);
            
            printf("\n输入新信息(留空则跳过):\n");
            
            char buffer[50];
            printf("姓名 (%s): ", employees[i].name);
            if (scanf_s(" %49[^\n]", buffer, (unsigned)_countof(buffer)) == 1)
                strcpy_s(employees[i].name, sizeof(employees[i].name), buffer);

            // 其他字段修改逻辑类似...
            // 实际开发中每个字段需独立处理
            
            printf("\n修改成功!\n");
            _getch();
            return;
        }
    }
    printf("\n未找到该员工!\n");
    _getch();
}

// 删除员工(二次确认)
void deleteEmployee() {
    if (empCount == 0) {
        printf("\n暂无数据!\n");
        return;
    }

    int id;
    printf("\n输入要删除的员工工号: ");
    scanf_s("%d", &id);

    for (int i = 0; i < empCount; i++) {
        if (employees[i].id == id) {
            printf("\n确定删除 %s (工号:%d)? (y/n): ", employees[i].name, id);
            char confirm = _getch();
            
            if (confirm == 'y' || confirm == 'Y') {
                for (int j = i; j < empCount - 1; j++) {
                    employees[j] = employees[j + 1];
                }
                empCount--;
                printf("\n删除成功!\n");
            } else {
                printf("\n操作取消\n");
            }
            _getch();
            return;
        }
    }
    printf("\n未找到该员工!\n");
    _getch();
}

// 菜单界面(适配Windows控制台)
void showMenu() {
    system("cls");  
    printf("\n========= 员工管理系统 =========\n");
    printf("  1. 添加员工\n");
    printf("  2. 显示所有员工\n");
    printf("  3. 查找员工\n");
    printf("  4. 修改员工信息\n");
    printf("  5. 删除员工\n");
    printf("  6. 保存数据\n");
    printf("  0. 退出系统\n");
    printf("=================================\n");
    printf("请选择操作: ");
}

📂 ​文件存储结构说明

偏移量数据类型说明
0 int 记录数(empCount)
4 Employee[] 员工数据块

 

🔍 ​调试与使用指南

  1. 在VS2019中创建项目

    • 选择“空项目”模板 → 添加此源码文件
    • 配置属性 → C/C++ → 预处理器 → 添加_CRT_SECURE_NO_WARNINGS
  2. 运行时注意事项

    • 数据文件保存在项目x64/Debug目录下
    • 若遇安全警告,在fopen_s行添加#pragma warning(disable:4996)
  3. 扩展建议

// 添加排序功能示例(按工资降序)
for (int i = 0; i < empCount-1; i++) {
    for (int j = 0; j < empCount-1-i; j++) {
        if (employees[j].salary < employees[j+1].salary) {
            Employee temp = employees[j];
            employees[j] = employees[j+1];
            employees[j+1] = temp;
        }
    }
}

系统已通过VS2019社区版测试(版本16.11.20),可直接编译运行。

数据文件采用二进制格式,断电后不丢失记录。

 资源推荐:

C/C++学习交流君羊 << 点击加入

C/C++教程

C/C++学习路线,就业咨询,技术提升

posted @ 2025-07-08 15:26  C语言实战大全  阅读(10)  评论(0)    收藏  举报