c语言课程设计职工信息管理系统

99ANYc3cd6
预计阅读时长 47 分钟
位置: 首页 C语言 正文

C语言课程设计:职工信息管理系统

项目概述

本项目旨在使用C语言开发一个基于控制台的职工信息管理系统,该系统将实现对职工信息的增加、删除、修改、查询、显示以及数据保存到文件从文件加载等基本功能,通过本项目,可以综合运用C语言的结构体、指针、文件操作、排序算法等核心知识点,锻炼编程和解决问题的能力。

需求分析

系统需要具备以下核心功能:

  • 数据录入:能够从键盘输入新职工的信息,并将其添加到系统中。
  • 数据删除:能够根据职工编号或姓名删除指定职工的信息。
  • 数据修改:能够根据职工编号或姓名找到职工,并修改其部分或全部信息。
  • 数据查询:能够根据职工编号或姓名查询职工信息,并显示结果。
  • 数据浏览:能够以列表形式显示所有职工的信息。
  • 数据排序:能够按照职工编号或工资进行升序/降序排序。
  • 数据持久化:系统能够将所有职工信息保存到磁盘文件中,并在程序启动时自动加载,实现数据不丢失。

功能设计

为了满足上述需求,设计如下菜单驱动界面:

+-------------------------------------+
|      职工信息管理系统 v1.0          |
+-------------------------------------+
|  1. 添加职工信息                     |
|  2. 删除职工信息                     |
|  3. 修改职工信息                     |
|  4. 查询职工信息                     |
|  5. 显示所有职工                     |
|  6. 按工资排序                       |
|  0. 退出系统                         |
+-------------------------------------+

用户通过输入数字选择对应功能,系统执行相应操作后返回主菜单。

数据结构设计

为了存储职工信息,定义一个结构体 Employee

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h> // 用于 getch(),实现不回显的输入
// 定义职工结构体
typedef struct {
    int id;         // 职工编号
    char name[50];  // 职工姓名
    char gender[10];// 性别
    int age;        // 年龄
    float salary;   // 工资
} Employee;
// 定义一个动态数组来存储所有职工
Employee *employees = NULL;
int employee_count = 0; // 当前职工数量
int capacity = 0;      // 数组容量

使用动态数组 (malloc, realloc) 可以灵活地管理职工数量,避免静态数组大小固定的限制。

核心功能模块实现

以下是各个功能模块的C语言实现代码。

1 主菜单与主函数

// 函数声明
void add_employee();
void delete_employee();
void modify_employee();
void search_employee();
void display_all_employees();
void sort_by_salary();
void save_to_file();
void load_from_file();
void free_memory();
int main() {
    // 程序启动时,尝试从文件加载数据
    load_from_file();
    int choice;
    while (1) {
        system("cls"); // 清屏 (Windows系统)
        // system("clear"); // 清屏 (Linux/macOS系统)
        printf("+-------------------------------------+\n");
        printf("|      职工信息管理系统 v1.0          |\n");
        printf("+-------------------------------------+\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("请输入您的选择: ");
        scanf("%d", &choice);
        getchar(); // 消耗掉scanf留下的换行符
        switch (choice) {
            case 1: add_employee(); break;
            case 2: delete_employee(); break;
            case 3: modify_employee(); break;
            case 4: search_employee(); break;
            case 5: display_all_employees(); break;
            case 6: sort_by_salary(); break;
            case 0: 
                save_to_file(); // 退出前保存数据
                free_memory();  // 释放内存
                printf("感谢使用,再见!\n");
                system("pause");
                exit(0);
            default:
                printf("无效的输入,请重新选择!\n");
                system("pause");
        }
    }
    return 0;
}

2 添加职工信息

void add_employee() {
    system("cls");
    printf("--- 添加职工信息 ---\n");
    // 检查是否需要扩容
    if (employee_count >= capacity) {
        capacity = (capacity == 0) ? 2 : capacity * 2;
        employees = (Employee *)realloc(employees, capacity * sizeof(Employee));
        if (employees == NULL) {
            printf("内存分配失败!\n");
            system("pause");
            return;
        }
    }
    Employee e;
    printf("请输入职工编号: ");
    scanf("%d", &e.id);
    getchar(); // 消耗换行符
    // 检查编号是否已存在
    for (int i = 0; i < employee_count; i++) {
        if (employees[i].id == e.id) {
            printf("错误:该职工编号已存在!\n");
            system("pause");
            return;
        }
    }
    printf("请输入职工姓名: ");
    fgets(e.name, sizeof(e.name), stdin);
    e.name[strcspn(e.name, "\n")] = 0; // 去掉fgets读取的换行符
    printf("请输入性别: ");
    fgets(e.gender, sizeof(e.gender), stdin);
    e.gender[strcspn(e.gender, "\n")] = 0;
    printf("请输入年龄: ");
    scanf("%d", &e.age);
    getchar();
    printf("请输入工资: ");
    scanf("%f", &e.salary);
    getchar();
    employees[employee_count++] = e;
    printf("职工信息添加成功!\n");
    system("pause");
}

3 删除职工信息

void delete_employee() {
    system("cls");
    printf("--- 删除职工信息 ---\n");
    if (employee_count == 0) {
        printf("系统中没有职工信息!\n");
        system("pause");
        return;
    }
    int id;
    printf("请输入要删除的职工编号: ");
    scanf("%d", &id);
    getchar();
    int found = 0;
    for (int i = 0; i < employee_count; i++) {
        if (employees[i].id == id) {
            found = 1;
            // 将后面的元素前移
            for (int j = i; j < employee_count - 1; j++) {
                employees[j] = employees[j + 1];
            }
            employee_count--;
            printf("职工编号为 %d 的信息已删除!\n", id);
            break;
        }
    }
    if (!found) {
        printf("未找到职工编号为 %d 的职工!\n", id);
    }
    system("pause");
}

4 修改职工信息

void modify_employee() {
    system("cls");
    printf("--- 修改职工信息 ---\n");
    if (employee_count == 0) {
        printf("系统中没有职工信息!\n");
        system("pause");
        return;
    }
    int id;
    printf("请输入要修改的职工编号: ");
    scanf("%d", &id);
    getchar();
    int found = 0;
    for (int i = 0; i < employee_count; i++) {
        if (employees[i].id == id) {
            found = 1;
            printf("找到职工: %s\n", employees[i].name);
            printf("请输入新的姓名 (直接回车保持原值): ");
            char new_name[50];
            fgets(new_name, sizeof(new_name), stdin);
            if (strlen(new_name) > 1) { // 如果用户输入了内容
                new_name[strcspn(new_name, "\n")] = 0;
                strcpy(employees[i].name, new_name);
            }
            printf("请输入新的性别 (直接回车保持原值): ");
            char new_gender[10];
            fgets(new_gender, sizeof(new_gender), stdin);
            if (strlen(new_gender) > 1) {
                new_gender[strcspn(new_gender, "\n")] = 0;
                strcpy(employees[i].gender, new_gender);
            }
            printf("请输入新的年龄 (输入0保持原值): ");
            int new_age;
            scanf("%d", &new_age);
            getchar();
            if (new_age != 0) {
                employees[i].age = new_age;
            }
            printf("请输入新的工资 (输入-1保持原值): ");
            float new_salary;
            scanf("%f", &new_salary);
            getchar();
            if (new_salary != -1) {
                employees[i].salary = new_salary;
            }
            printf("职工信息修改成功!\n");
            break;
        }
    }
    if (!found) {
        printf("未找到职工编号为 %d 的职工!\n", id);
    }
    system("pause");
}

5 查询职工信息

void search_employee() {
    system("cls");
    printf("--- 查询职工信息 ---\n");
    if (employee_count == 0) {
        printf("系统中没有职工信息!\n");
        system("pause");
        return;
    }
    int id;
    printf("请输入要查询的职工编号: ");
    scanf("%d", &id);
    getchar();
    int found = 0;
    for (int i = 0; i < employee_count; i++) {
        if (employees[i].id == id) {
            found = 1;
            printf("\n--- 查询结果 ---\n");
            printf("职工编号: %d\n", employees[i].id);
            printf("职工姓名: %s\n", employees[i].name);
            printf("性别: %s\n", employees[i].gender);
            printf("年龄: %d\n", employees[i].age);
            printf("工资: %.2f\n", employees[i].salary);
            printf("----------------\n");
            break;
        }
    }
    if (!found) {
        printf("未找到职工编号为 %d 的职工!\n", id);
    }
    system("pause");
}

6 显示所有职工信息

void display_all_employees() {
    system("cls");
    printf("--- 所有职工信息 ---\n");
    if (employee_count == 0) {
        printf("系统中没有职工信息!\n");
        system("pause");
        return;
    }
    printf("%-10s %-20s %-10s %-10s %-10s\n", "编号", "姓名", "性别", "年龄", "工资");
    printf("------------------------------------------------\n");
    for (int i = 0; i < employee_count; i++) {
        printf("%-10d %-20s %-10s %-10d %-10.2f\n", 
               employees[i].id, 
               employees[i].name, 
               employees[i].gender, 
               employees[i].age, 
               employees[i].salary);
    }
    system("pause");
}

7 按工资排序

这里使用简单的冒泡排序算法,可以根据需要替换为更高效的排序算法(如快速排序)。

// 比较函数,用于qsort
int compare_salary_asc(const void *a, const void *b) {
    Employee *empA = (Employee *)a;
    Employee *empB = (Employee *)b;
    if (empA->salary > empB->salary) return 1;
    if (empA->salary < empB->salary) return -1;
    return 0;
}
int compare_salary_desc(const void *a, const void *b) {
    return -compare_salary_asc(a, b);
}
void sort_by_salary() {
    system("cls");
    printf("--- 按工资排序 ---\n");
    if (employee_count == 0) {
        printf("系统中没有职工信息!\n");
        system("pause");
        return;
    }
    int order;
    printf("请选择排序方式:\n");
    printf("1. 升序\n");
    printf("2. 降序\n");
    printf("请输入选择: ");
    scanf("%d", &order);
    getchar();
    if (order == 1) {
        qsort(employees, employee_count, sizeof(Employee), compare_salary_asc);
        printf("已按工资升序排序!\n");
    } else if (order == 2) {
        qsort(employees, employee_count, sizeof(Employee), compare_salary_desc);
        printf("已按工资降序排序!\n");
    } else {
        printf("无效的选择!\n");
        system("pause");
        return;
    }
    display_all_employees(); // 排序后直接显示
}

8 文件操作

void save_to_file() {
    FILE *fp = fopen("employees.dat", "wb"); // "wb" 表示二进制写入
    if (fp == NULL) {
        printf("无法打开文件进行保存!\n");
        return;
    }
    // 先写入职工数量
    fwrite(&employee_count, sizeof(int), 1, fp);
    // 再写入所有职工数据
    fwrite(employees, sizeof(Employee), employee_count, fp);
    fclose(fp);
    printf("数据已成功保存到文件 employees.dat\n");
}
void load_from_file() {
    FILE *fp = fopen("employees.dat", "rb"); // "rb" 表示二进制读取
    if (fp == NULL) {
        // 文件不存在是正常情况,说明是第一次运行
        return;
    }
    // 读取职工数量
    fread(&employee_count, sizeof(int), 1, fp);
    // 根据数量分配内存
    if (employee_count > 0) {
        employees = (Employee *)malloc(employee_count * sizeof(Employee));
        if (employees == NULL) {
            printf("内存分配失败!\n");
            fclose(fp);
            exit(1);
        }
        capacity = employee_count;
        // 读取所有职工数据
        fread(employees, sizeof(Employee), employee_count, fp);
    }
    fclose(fp);
    printf("数据已成功从文件加载,\n");
}

9 内存释放

void free_memory() {
    if (employees != NULL) {
        free(employees);
        employees = NULL;
    }
    employee_count = 0;
    capacity = 0;
}

如何编译和运行

  1. 保存代码:将以上所有代码块合并到一个文件中,employee_management.c
  2. 编译:打开命令行(如Windows的CMD或PowerShell,Linux的Terminal),使用GCC进行编译。
    gcc employee_management.c -o employee_management.exe
    • 在Linux/macOS上,编译命令为 gcc employee_management.c -o employee_management
  3. 运行
    • 在Windows上:employee_management.exe
    • 在Linux/macOS上:./employee_management

项目扩展与优化建议

如果这是一个课程设计,并且希望获得更高的评价,可以考虑以下扩展:

  1. 增加查询方式:除了按编号查询,还可以增加按姓名模糊查询。
  2. 增加排序方式:除了按工资排序,还可以增加按年龄、姓名等排序。
  3. 改进数据结构:使用链表代替动态数组,链表在频繁的插入和删除操作上效率更高,但随机访问稍慢。
  4. 用户界面美化:使用颜色代码(Windows的<windows.h>)或更复杂的控制台库(如ncurses)来美化界面。
  5. 密码保护:为系统增加登录功能,设置管理员密码。
  6. 数据验证:在输入时增加更多的数据验证逻辑,例如年龄、工资必须是正数,姓名不能为空等。
  7. 多文件组织:将代码拆分为多个文件(如 main.c, employee.c, file_io.c, utils.h),使项目结构更清晰,符合大型项目的开发规范。
-- 展开阅读全文 --
头像
dede验证码不显示 服务器
« 上一篇 01-10
织梦文章首行缩进怎么设置?
下一篇 » 01-10
取消
微信二维码
支付宝二维码

目录[+]