目录
频道首页
基于C语言链表和文件的企业员工管理系统
下载
3
收藏
0
Dreamlover 最近修改于 2024-09-11 05:45:21

基于C语言链表和文件的企业员工管理系统

一 需求分析

企业员工管理系统主要是针对企业员工的基本信息进行增、删、改、查的相关操作,以便用户使用本管理系统时可以快速对企业员工的信息进行管理。

主要实现以下功能:

  • 用户首次使用本系统时进行密码设置和初始化操作

  • 实现添加功能,即添加员工的相关信息

  • 实现查看功能,即显示系统中所有员工的相关信息

  • 实现查找功能,即可以通过多种条件对员工进行查询,如姓名、工号等

  • 实现修改功能,即输入员工的姓名修改其相关信息

  • 实现删除功能,即输入员工的姓名删除其相关信息

  • 实现统计员工人数的功能

  • 实现重新设置密码登录密码的功能

  • 退出系统

二 概要设计

系统功能模块架构图如下所示:

  • 首次登陆用户信息初始化功能模块:当用户时首次使用本系统时,则需要根据提示进行设置密码和初始化的操作

  • 输入员工信息功能模块:实现将用户从键盘输入的数据存储到对应字段或数据成员中,并检查输入的合法性

  • 显示员工信息功能模块:用户根据提示操作显示系统中已有的员工的相关信息,如果系统中海没有存储员工信息则给出无法显示信息的提示

  • 查询员工信息功能模块:根据用户输入的待查询记录的关键字,在数据结构中查找该记录,如找到则输出该员工的信息,否则给出无法找到的提示信息

  • 修改员工信息功能模块:根据用户要求,根据提示操作,找到要修改信息的员工然后修改员工的相关信息,如年龄。工资等

  • 删除员工信息功能模块:由用户输入选择删除相关的员工的信息

  • 统计员工信息功能模块:统计本系统中员工的信息,如男、女员工的人数等

  • 重置系统密码功能模块:根据用户的要求,将旧密码更换设置新密码

  • 退出系统功能模块:在用户执行完相关系统操作之后,退出使用本系统

三 详细设计

3.1 功能函数的调用关系

如下图所示:

3.2 各功能函数的数据流程

如下图所示:

四 程序实现

4.1 初始化模块

本系统中对是否是第一次使用本系统进行了处理,如果是第一次使用,则需要根据提示信息进行设置密码和初始化操作。其思路是:首先打开密码文件,判断是否为空,进而判断系统是否是第一次使用,如果是,系统会提示输入初始密码,如果不是,系统会进入登陆页面,提示输入登陆密码。

void checkfirst()
{
    FILE *fp,*fp1; //声明文件型指针
    char pwd[9],pwd1[9],pwd2[9];
    int i;
    char strt='8';
    if((fp=fopen("employee.txt","rb"))==NULL) 
    {
        printf("\n\t新系统,请进行相应的初始化操作!\n");  //判断系统密码文件是否为空
        bound('_',50);
        getch();
        do
        {
            printf("\n设置密码,请不要超过8位:  ");
            for(i=0;i<8&&((pwd[i]=getch())!=13);i++)
                putch('*');
            printf("\n请再确认一次密码:  ");
            for(i=0;i<8&&(pwd1[i]=getch())!=13;i++)
                putch('*');
            pwd[i]='\0';
            pwd1[i]='\0';
            if(strcmp(pwd,pwd1)!=0)
                printf("\n\n两次密码输入不一致,请重新输入: \n");
            else 
                break;
        }while(1);
        if((fp1=fopen("employee.txt","wb"))==NULL)
        {
            printf("\n系统创建失败,请按任意键退出!\n");
            getch();
            exit(1);
        }
        i=0;
        while(pwd[i])
        {
            pwd2[i]=(pwd[i]^strt);
            putw(pwd2[i],fp1);//将数组元素送入文件流中
            i++;
        }
        fclose(fp1);//关闭文件流
        printf("\n系统初始化成功,请按任意键退出后,再重新进入!\n");
        getch();
        exit(1);
    }
    else 
    {
        i=0;
        while(!feof(fp)&&i<8)//判断是否读完密码文件
            pwd[i++]=getw(fp)^strt;//从文件流中读出字符赋给数组
        pwd[i]='\0';
        if(i>=8)
            i--;
        while(pwd[i]!=-1&&i>=0)
            i--;
        pwd[i]='\0';
        strcpy(password,pwd);
    }
}

4.2 管理员登录模块

自定义函数login()在初始化检测后调用,用于管理员的登录,用户根据提示密码,函数调用strcmp()函数对输入密码和密码文件中的读取数据进行比较,如果一致则进入系统,不一致会提示重新输入,如果3次不一致会强制退出。

void login()//检测登陆密码
{
    int i,n=3;
    char pwd[9];
    do
    {
        printf("\n请输入登陆密码:  ");
        for(i=0;i<8&&((pwd[i]=getch())!=13);i++)
            putch('*');
        pwd[i]='\0';
        if(strcmp(pwd,password))
        {
            printf("\n密码错误,请重新输入!\n");
            system("cls");//调用清屏命令
            n--;
        }
        else 
           break;
    }while(n>0);
    if(!n)
    {
        printf("密码输入3次错误,请退出!\n");
        getch();
        exit(1);
    }
}

4.3 添加员工信息模块

自定义函数addemp()用于添加员工的信息,首先打开存储员工信息的数据文件,系统会提示用户输入相应的员工基本信息,当用户输入完成一个员工的信息后,系统会提示用户是否继续输入员工信息。

void addemp()
{
    FILE *fp;
    EMP *emp1;
    int i=0;
    char choice='y';
    if((fp=fopen("employee.txt","ab"))==NULL)// 追加打开一个二进制文件,并在文件末尾写数据 
    {
        printf("打开文件出错!\n");
        getch();
        exit(1);
    }
    do
    {
        i++;
        emp1=(EMP*)malloc(sizeof(EMP));
        if(emp1==NULL)
        {
            printf("内存分配失败,请按任意键退出!\n");
            getch();
            return;
        }
        printf("\n\t请输入第%d各员工的信息\n",i);
        bound('_',40);
        printf("工号:  ");
        scanf("%d",&emp1->num);
        printf("职务:  ");
        scanf("%s",&emp1->duty);
        printf("姓名:  ");
        scanf("%s",&emp1->name);
        printf("性别:  ");
        scanf("%s",&emp1->sex);
        printf("年龄:  ");
        scanf("%d",&emp1->age);
        printf("文化程度:  ");
        scanf("%s",&emp1->edu);
        printf("工资:  ");
        scanf("%d",&emp1->salary);
        printf("办公电话:  ");
        scanf("%s",&emp1->tel_office);
        printf("家庭电话:  ");
        scanf("%s",&emp1->tel_home);
        printf("手机号码:  ");
        scanf("%s",&emp1->mobile);
        printf("QQ号码:  ");
        scanf("%s",&emp1->qq);
        printf("家庭地址:  ");
        scanf("%s",&emp1->address);
        emp1->next=NULL;
        if(emp_first==NULL)//判断表头指针是否为空
        {
            emp_first=emp1;
            emp_end=emp1;
        }
        else
        {
            emp_end->next=emp1;
            emp_end=emp1;
        }
        fwrite(emp_end,sizeof(EMP),1,fp);//对数据流添加数据项
        gfirst=0;
        printf("\n");
        bound('_',40);
        printf("\n是否继续输入?(y/n)");
        fflush(stdin);//清除缓存区
        choice=getchar();
        if(toupper(choice)!='Y')
        {
            fclose(fp);//关闭文件流
            printf("\n输入完毕,请按任意键返回!\n");
            getchar();
            return;
        }
        system("cls");
    }while(1);
}

4.4 删除员工信息模块

自定义函数delemp()实现删除员工的功能。在系统的功能菜单中选择删除信息的操作后,系统就会提示要删除的员工的姓名,输入要删除的员工的姓名后,如果系统从信息链表中找到相关信息后就会将信息显示出来,再次要求用户确定是否要删除,谨防误操作,提高信息的安全性。

void delemp()
{
    int findok=0;
    EMP *emp1,*emp2;
    char name[10],choice;
    system("cls");
    printf("\n请输入要删除的员工的姓名:  ");
    scanf("%s",name);
    emp1=emp_first;
    emp2=emp1;
    while(emp1)
    {
        if(strcmp(emp1->name,name)==0)
        {
            findok=1;
            system("cls");
            printf("\n员工 %s 的信息如下: \n  ",emp1->name);
            bound('_',40);
            printf("工号: %d \n",emp1->num);
            printf("职务: %s \n",emp1->duty);
            printf("姓名: %s \n",emp1->name);
            printf("性别: %s \n",emp1->sex);
            printf("年龄: %d \n",emp1->age);
            printf("文化程度: %s \n",emp1->edu);
            printf("工资: %d\n",emp1->salary);
            printf("办公电话: %s \n",emp1->tel_office);
            printf("家庭电话: %s \n",emp1->tel_home);
            printf("手机号码: %s \n",emp1->mobile);
            printf("QQ号码: %s \n",emp1->qq);
            printf("家庭地址: %s \n",emp1->address);
            bound('_',40);
            printf("\n确定要删除该员工信息?(y/n)  ");
            fflush(stdin);
            choice=getchar();
            if(choice!='y'&&choice!='Y')
                return;
            if(emp1==emp_first)
                emp_first=emp1->next;
            else 
                emp2->next=emp1->next;
            free(emp1);
            gsave=1;
            savedata();//保存数据
            return;
        }
        else
        {
            emp2=emp1;
            emp1=emp1->next;
        }
        if(!findok)
        {
            bound('_',40);
            printf("\n没有找到姓名是: %s 的信息!\n",name);
            getch();
        }
        return;
    }
}

4.5 员工信息显示模块

自定义函数displayemp()在找到员工的信息后,则需进行显示。

void displayemp(EMP *emp ,char *filed , char *name)
 {
    if(emp)
    {
        bound('_',40);
        printf("\n  %s : %s    信息如下: \n",filed,name);
        bound('_',40);
        printf("工号: %d \n",emp->num);
        printf("职务: %s \n",emp->duty);
        printf("姓名: %s \n",emp->name);
        printf("性别: %s \n",emp->sex);
        printf("年龄: %d \n",emp->age);
        printf("文化程度: %s \n",emp->edu);
        printf("工资: %d \n",emp->salary);
        printf("办公电话: %s \n",emp->tel_office);
        printf("家庭电话: %s \n",emp->tel_home);
        printf("手机号码: %s \n",emp->mobile);
        printf("QQ号码: %s \n",emp->qq);
        printf("家庭地址: %s \n",emp->address);
        bound('_',40);
    }
    else
    {
       bound('_',40);
       printf("\n资料库中没有%s为: %s的员工,请重新确认!\n",filed,name);
    }
    return;
}

4.6 查询员工信息模块

自定义函数findemp()函数用于查询员工信息,在系统的功能菜单中选择查询员工信息的操作后,系统进入一个查询选项列表,用户根据自己的需要选择要使用的查询条件,根据用户输入的条件的不同,系统会调用不同的查询函数,如果系统从信息链表中找到相关的信息就会显示出来。

void findemp()
{
    int choice,ret=0,num;
    char str[13];
    EMP *emp1;
    system("cls");
    do{
        printf("\n\t查询员工信息:\n");
        bound('_',30);
        printf("\t1.按姓名查询\n");
        printf("\t2.按工号查询\n");
        printf("\t3.按电话查询\n");
        printf("\t4.按QQ号查询\n");
        printf("\t0.返回主菜单\n");
        bound('_',30);
        printf("\n请选择(0-4):  ");
         do
        {
            fflush(stdin);
            choice=getchar();
            system("cls");
            switch(choice)
            {
                case '1':
                   printf("\n请输入要查询员工的姓名:  ");
                   scanf("%s",str);
                   emp1=findname(str);//调用子函数
                   displayemp(emp1,"姓名",str);
                   getchar();
                   getchar();
                   break;
                case '2':
                   printf("\n请输入要查询员工的工号:  ");
                   scanf("%d",&num);
                   emp1=findnum(num);//调用子函数
                   itoa(num,str,10);
                   displayemp(emp1,"工号",str);
                   getchar();
                   getchar();
                   break;
                case '3':
                    printf("\n请输入要查询员工的电话:  ");
                    scanf("%s",str);
                    emp1=findtelephone(str);//调用子函数
                    displayemp(emp1,"电话",str);
                    getchar();
                    getchar();
                    break;
                case '4':
                    printf("\n请输入要查询员工的QQ号:  ");
                    scanf("%s",str);
                    emp1=findqq(str);//调用子函数
                    displayemp(emp1,"QQ号码",str);
                    getchar();
                    getchar();
                    break;
                case '0':
                    ret=1;
                    break;
            }
        }while(choice<'0'||choice>'4');
        system("cls");
        if(ret)
             break;
    }while(1);
}
EMP *findname(char *name)//按姓名查找员工信息
{
    EMP *emp1;
    emp1=emp_first;
    while(emp1)
    {
        if(strcmp(name,emp1->name)==0)//比较输入的名字和链表中记载的名字是否相同
            return emp1;
        emp1=emp1->next;
    }
    return NULL;
}

EMP *findnum(int num)//按工号查询
{
    EMP *emp1;
    emp1=emp_first;
    while(emp1)
    {
        if(num==emp1->num)
            return emp1;
        emp1=emp1->next;
    }
    return NULL;
}

EMP *findtelephone(char *name)//按电话号码查询员工信息
{
    EMP *emp1;
    emp1=emp_first;
    while(emp1)
    {
        if(strcmp(name,emp1->tel_office)==0||strcmp(name,emp1->tel_home)==0||strcmp(name,emp1->mobile)==0)
            return emp1;
        emp1=emp1->next;
    }
    return NULL;
}

EMP *findqq(char *name)//按QQ号码查询员工信息
{
    EMP *emp1;
    emp1=emp_first;
    while(emp1)
    {
        if(strcmp(name,emp1->qq)==0)
            return emp1;
        emp1=emp1->next;
    }
    return NULL;
}

4.7 修改密码模块

自定义函数resetpwd()用于修改密码。在系统的功能菜单中选择修改的操作选项后,系统会提示输入旧密码,用户咋正确的输入旧密码后,根据提示即可实现密码的修改。

void resetpwd()
{
    char pwd[9],pwd1[9];
    int i;
    FILE *fp1;
    system("cls");
    printf("\n请输入旧密码: \n");
    for(i=0;i<8&&((pwd[i]=getchar())!=13);i++)
        putchar('*');
    pwd[i]='\0';
    if(strcmp(password,pwd)!=0)
    {
        printf("\n密码错误,请按任意键退出!\n");
        getchar();
        return;
    }
    do
    {
        printf("\n设置密码,请不要超过8位:  ");
        for(i=0;i<8&&((pwd[i]=getchar())!=13);i++)
            putchar('*');
        printf("\n请再确认一次密码:   ");
        for(i=0;i<8&&((pwd[i]=getchar())!=13);i++)
            putchar('*');
        pwd[i]='\0';
        pwd1[i]='\0';
        if(strcmp(pwd,pwd1)!=0)//比较两次输入的密码
            printf("\n两次密码输入不一致,请重新输入!  \n\n");
        else 
            break;
    }while(1);
    if((fp1=fopen("employee.tex","wb"))==NULL)
    {
        printf("\n系统创建失败,请按任意键退出!\n");
        getchar();
        exit(1);
    }
    i=0;
    while(pwd[i])
    {
        putw(pwd[i],fp1);//将数组元素送入文件流中
        i++;
    }
    fclose(fp1);//关闭文件流
    printf("\n密码修改成功,请按任意键退出后,再重新进入!\n");
    getch();
    return;
}

4.8 主函数模块

int main()
{
    emp_first=emp_end=NULL;//链表指针初始化
    gsave=gfirst=0;
    checkfirst();
    login();
    readdata();
    menu();
    system("PAUSE");
    return 0;
}

五 运行测试

实现添加员工信息并显示添加后员工的信息的功能,操作如下图:

实现查询员工信息的功能,操作如下:

实现修改员工信息的功能,并显示修改后员工的信息,操作如下:

六 参考文献

  • 《C语言程序设计教程》,人民邮电出版社

  • 《C语言程序开发范例宝典》,人民邮电出版社

内容大纲
批注笔记
基于C语言链表和文件的企业员工管理系统
CodeBot
z
z
z
z
主页
会议室
Git管理
文章
云文档
看板