工资管理系统/c语言期末大作业学习经历-创新互联

大致流程

这次大作业开始构思到写完程序并测试完毕,经历了两周多的努力。在初步分化好模块之后,在网上找各种资料学习链表(比较推荐翁恺老师的课),后边又学习了一些相对应的知识,像是链表的排序算法(因为精力有限只学了插入排序)。准备工作做完之后,刚开始编写程序就遇到了Segment fault报错,因为是第一次用链表,对于这种报错完全是一头雾水,问了好几个同学,改了好几天。最后实在没办法,又从头写了一遍。虽然现在回过头来看,这玩意也没那么难,但是实际学习过程中真是不简单。

成都创新互联公司坚持“要么做到,要么别承诺”的工作理念,服务领域包括:成都网站设计、做网站、成都外贸网站建设公司、企业官网、英文网站、手机端网站、网站推广等服务,满足客户于互联网时代的盂县网站设计、移动媒体设计的需求,帮助企业找到有效的互联网解决方案。努力成为您成熟可靠的网络建设合作伙伴!

因为想做一个模块化的程序,每一个都可以配合mian函数独立使用,所以像是遍历,输入文件这样的功能重复出现了好几次。

函数功能实现及参数分析

1,结构体声明

Worker结构体包含了员工的工号,姓名,基本工资。奖金,扣款,应发工资,实发工资和税款信息;

List结构体包含了链表的头指针(head)和尾指针(tail),当对包含头指针和尾指针的结构体修改的函数结束后,虽然结构体不会保存,但指针所指向的地址已经被修改了,为函数省去了需要return的部分

2,Main函数

Main函数实现了读取文件,链表创建和模块选择的功能;

变量Option用于控制switch结构,对执行模块进行选择;变量n用于创建链节时判断当前链节是否为头节点。结构体指针emp1和p两个临时变量,指针temp1负责指向malloc函数开辟出的内存区域,并承接文件传进来的数据。指针p每次循环负责将前一个链节的指针指向后一个链节,并将指向后一个链节,以此延长链表。Boolean变量负责判断while循环内的switch函数是否执行,switch函数负责调用各大模块的函数。

3,输出,查找,修改,删除函数主体都有链表的遍历

输出操作,就是f临时指针,for循环遍历链表,遍历的同时,使用printf函数打印出来

查找操作,就是f临时指针,赋给头指针的值,for循环遍历链表,找到与工号相匹配的链节,printf将其输出出来。

修改操作,f临时指针,for循环遍历链表,找到匹配链节后,scanf对该链节数据重新输入,并计算其他数据。

删除操作,f和p为临时指针,f指向待删除结点,p指向前一个结点,连接待删除结点的前后两个链节,释放该链节的空间,并使指针指向为空

4,排序函数

指针lastSorted指向已经参与排序的部分的末尾链节,

指针curr指向下一步待插入到已排列部分的链节;

指针prev指向待插入链节在已排列部分该插入位置的前一个链节;

指针dummyhead便于在头结点插入链节;

在链表前端人为创造一个已排序的有序部分,初始时只有一个头节点,curr指针指向lastSorted后方第一个链节。此时从已排序部分遍历,找到刚好小于等于它的结点,将curr结点插入到该结点后方,再完成指针的链节。直到链表中的所有元素都加入到有序的部分,这个链表也就完成了排序;

首先做好函数声明与结构体声明

#include#include#include#include#define LEN sizeof(Worker)

typedef struct _Worker
{
    int num;                //工号
    char name[20];            //姓名
    float base_salay;        //基本工资 
    float bonus;            //奖金 
    float fine;                //扣款 
    float salay;            //应发工资 
    float real_salay;        //实发工资 
    float tax;                //税款 
    struct _Worker *next;    //指向下一链节的指针 
} Worker;

typedef struct _list //便于传递头指针和尾指针,程序执行完毕可以不使用return
{
    Worker *head;//头指针
    Worker *tail;//尾指针
}List;

    void Menu();                        //菜单函数
    void Print(List list);               //输出函数
    void Add(List list);                //增添函数
    void Delate(List list);             //删除函数
    void Amend(List list);              //修改函数
    void Seek(List list);                //查找函数
    void Sort(List list);               //排序函数
    void Statis(List list);             //统计函数

Worker结构体

是链表的基础,可分为两个部分,一部分是储存数据的

这个List结构是我在翁恺老师的c语言链表视频里学习到的,虽然是结构体,但他就只包含了两个指针。这两个指针分别指向头指针和尾指针。因为在一些函数里会对头指针,尾指针进行修改,而指针本身只是一个地址,所以在函数内修改后还需要返回值给main函数,为了方便一些,创建一个指针的指针

以下为全部代码,需配合对应txt文件使用

#include#include#include#include#define LEN sizeof(Worker)

typedef struct _Worker
{
    int num;                //工号
    char name[20];            //姓名
    float base_salay;        //基本工资 
    float bonus;            //奖金 
    float fine;                //扣款 
    float salay;            //应发工资 
    float real_salay;        //实发工资 
    float tax;                //税款 
    struct _Worker *next;    //指向下一链节的指针 
} Worker;

typedef struct _list //便于传递头指针和尾指针,程序执行完毕可以不使用return
{
    Worker *head;//头指针
    Worker *tail;//尾指针
}List;

    void Menu();                        //菜单函数
    void Print(List list);               //输出函数
    void Add(List list);                //增添函数
    void Delate(List list);             //删除函数
    void Amend(List list);              //修改函数
    void Seek(List list);                //查找函数
    void Sort(List list);               //排序函数
    void Statis(List list);             //统计函数

int main()
{
    List list;            //包含链表头指针和尾指针 
    int option;            //用于switch函数,对程序功能进行选择 
    int n=0;            //用于判断链表节点的位置 
    Worker *temp1,*p;    //两个临时指针,交替向后移动,以创建链表
    

    
    FILE *fp;
    if((fp=fopen("worker.txt","r+"))==NULL){
        printf("文件打开失败\n]");
        system("pause");//打开失败后按下按键即可退出程序
    }
    else{
        printf("文件打开成功\n");
            
    }//打开文件并对打开结果是否成功进行判断并提示


    while (feof(fp)==0)//while对文档中的数据进行读取
    {
        n++;
        temp1 = (Worker*)malloc(LEN);
        fscanf(fp,"%d %s %f %f %f %f %f %f",
           &temp1->num,&temp1->name,&temp1->base_salay,
           &temp1->bonus,&temp1->fine,&temp1->salay,&temp1->real_salay,&temp1->tax);
           
    
        temp1->next=NULL;
        if (n==1){
            list.head=temp1;//头指针 
        }
        else 
            p->next=temp1;
        p=temp1;
    }
    list.tail=p;//尾指针
    printf("文件数据读入完成\n");
    fclose(fp);//文件关闭
    fp=NULL;
    
    
    int boolean=1;//布尔值,用于判断while是否进行 
    
    do{
        Menu();                //程序打开后先输出菜单栏目     
        printf("\n请输入与模块相对应的数字进行使用\n"); 
        scanf("%d",&option);
        //do while 循环,实现一次打开,多次使用 

    switch(option)
    {
        case 1:
            Print(list);//输出函数 
            break;    
        case 2:
            Add(list);//增添函数 
            break;
        case 3:
            Delate(list);//删除函数 
            break;
            
        case 4:
            Amend(list);//修改函数 
            break;
            
        case 5:    
            Seek(list);//查找函数 
            break;
            
        case 6:
            Sort(list);//排序函数 
            break;    
        case 7:
            Statis(list);//统计函数 
            break;
                 
        default:
            printf("选择输入错误,请重新选择\n");
            break;
            
    }
        printf("\n如果继续使用程序请输入1,结束使用则输入0\n");
        scanf("%d",&boolean);
        system("cls");    
}while(boolean==1);
   
    return 0;

}
void Menu()
{
    printf("\n\n\t欢迎使用工资信息管理系统\n");
    printf("\t本程序含有以下功能模块\n");
    printf("\t请输入与模块相对应的数字进行使用\n");
    printf("\n\t--------工资信息管理系统---------\n"
            "\t|1.输出模块\t\t\t|\n"                    
            "\t|2.添加模块\t\t\t|\n" 
            "\t|3.删除模块\t\t\t|\n"
            "\t|4.修改模块\t\t\t|\n"
            "\t|5.查找模块\t\t\t|\n"
            "\t|6.排序模块\t\t\t|\n"
            "\t|7.统计模块\t\t\t|\n"
            "\t---------------------------------\n");
}



void Print(List list)
{
    Worker *f=list.head;
    printf("\n工号   姓名            基本工资  奖金      扣款      应发工资  实发工资  税款\n");
    for(;f;f=f->next)
    {
        printf("%-6d %-15s %-9.2f %-9.2f %-9.2f %-9.2f %-9.2f %-9.2f\n"
        ,f->num,f->name,f->base_salay,f->bonus,f->fine,f->salay,f->real_salay,f->tax);
    }
        
}

void Seek(List list)
{
    int number;
    Worker *f; //临时指针 
    printf("\n请输入你要查找的员工号\n");
    scanf("%d",&number);
    f=list.head;//将头指针赋给临时指针 
    for (;f;f=f->next)
    {
        if(f->num==number){
            printf("查询成功\n");
            printf("\n工号   姓名       基本工资  奖金      扣款      应发工资  实发工资  税款\n");
            printf("%-6d %-10s %-9.2f %-9.2f %-9.2f %-9.2f %-9.2f %-9.2f\n"
            ,f->num,f->name,f->base_salay,f->bonus,f->fine,f->salay,f->real_salay,f->tax);
            break;
        }
    } //遍历链表,将员工号与输入的数字相匹配 
}

void Add(List list)
{
    FILE *fp;//打开文件 
    if((fp=fopen("worker.txt","a+"))==NULL){
        printf("文件打开失败\n");
        exit(0);
    }

    Worker *f;//临时指针 
    int boolean;
    do{
        f=(Worker*)malloc(LEN);//由malloc函数 
        printf("\n请输入你要添加的员工信息\n"
        "依次为\n员工号 姓名 基本工资 奖金 扣款\n");
        scanf("%d %s %f %f %f",&f->num,f->name,&f->base_salay,&f->bonus,&f->fine);
        
        printf("\n如果继续添加员工信息请输入1,结束输入则输入0\n");
        scanf("%d",&boolean);
        
        f->salay=f->base_salay-f->fine+f->bonus;//应发工资的计算 
        
        if(f->salay<=5000)
            f->tax=0;
        else if(f->salay<=6500)
            f->tax=(f->salay-5000)*0.03;
        else if(f->salay<=9500)
            f->tax=(f->salay-5000)*0.1-105;
        else if(f->salay<=14000)
            f->tax=(f->salay-5000)*0.2-555;
        else if(f->salay<=40000)
            f->tax=(f->salay-5000)*0.25-1005;
        else if(f->salay<=60000)
            f->tax=(f->salay-5000)*0.3-2755;
        else if(f->salay<=85000)
            f->tax=(f->salay-5000)*0.35-5505;
        else
            f->tax=(f->salay-5000)*0.45-13505;
            //税款计算      
        f->real_salay=f->salay-f->tax;//实发工资
        
        fprintf(fp,"\n%d %s %f %f %f %f %f %f"
        ,f->num,f->name,f->base_salay,f->bonus,f->fine,f->salay,f->real_salay,f->tax);
        //将新开辟的空间所储存的数据 
        list.tail->next=f; //将新链节与链表相连 
        list.tail=list.tail->next;//更新尾指针
        list.tail->next=NULL;//保持尾指针的next指针指向为空 
        printf("输入成功\n");         
    }while (boolean!=0);
    fclose(fp);//关闭文件 
    fp=NULL;
}

void Delate(List list)
{
    FILE *fp;
    if((fp=fopen("worker.txt","w+"))==NULL){
        printf("文件打开失败\n]");
        exit(0);
    }
    //打开文件 
    int number;//员工号码 
    printf("\n请输入要删除的员工信息的员工号\n");
    scanf("%d",&number);
    Worker *f=list.head;//临时指针,将头指针赋给它 
    Worker *p=NULL; //临时指针 
    for(;f;p=f,f=f->next)//f为所求链节,p为前一链节 
    {
        if(f->num==number)
        {
            printf("你正在删除的员工姓名为%s\n",f->name);
            if(f==list.head){//特殊情况,删除头节点 
                list.head=f->next;
            }
            else{
                if(f==list.tail){//特殊情况,删除尾结点 
                    list.tail=p;
                    list.tail->next=NULL;
                }
                else{
                    p->next=f->next;//将前一链节的next指针,指向f的后一链节,以此跳过f,重新连接链表 
                }
            }
            free(f);//释放空间 
            break;
            f=NULL;//指针赋空 
        }        
    }
    printf("删除成功,正在同步至文本文件\n");
    for(f=list.head;f;f=f->next)
        {
        fprintf(fp,"\n%d %s %f %f %f %f %f %f"
        ,f->num,f->name,f->base_salay,f->bonus,f->fine,f->salay,f->real_salay,f->tax);
        }//将整个链表重新输入到文件中 
        printf("同步成功\n");
        fclose(fp);//文件关闭 
        fp=NULL; //指针赋空 
}

void Amend(List list)
{
    FILE *fp;//文件打开 
    if((fp=fopen("worker.txt","w+"))==NULL){
        printf("文件打开失败\n]");
        exit(0);
    }
    
    int number;
    printf("\n请输入要修改的员工信息的员工号\n");
    scanf("%d",&number);
    Worker *f;
    Worker *p=NULL; 
    //f和p都是临时指针 
    for(f=list.head;f;f=f->next)//链表遍历并寻找该链节 
    {
        if(f->num==number)
        {
            printf("将要修改信息的员工姓名为%s\n",f->name);

            printf("请重新输入该员工的信息\n"
                    "依次为 员工号 姓名 基本工资 奖金 扣款\n");
            scanf("%d %s %f %f %f",&f->num,f->name,&f->base_salay,&f->bonus,&f->fine);

            f->salay=f->base_salay-f->fine+f->bonus;//应发工资的计算 
        
            if(f->salay<=5000)
                f->tax=0;
            else if(f->salay<=6500)
                f->tax=(f->salay-5000)*0.03;
            else if(f->salay<=9500)
                f->tax=(f->salay-5000)*0.1-105;
            else if(f->salay<=14000)
                f->tax=(f->salay-5000)*0.2-555;
            else if(f->salay<=40000)
                f->tax=(f->salay-5000)*0.25-1005;
            else if(f->salay<=60000)
                f->tax=(f->salay-5000)*0.3-2755;
            else if(f->salay<=85000)
                f->tax=(f->salay-5000)*0.35-5505;
            else
                f->tax=(f->salay-5000)*0.45-13505;//税款计算 
                
                f->real_salay=f->salay-f->tax;//实发工资 
            break;   
        }        
    }

    printf("修改成功,正在同步至文本文件\n");
    for(f=list.head;f;f=f->next)
        {
        fprintf(fp,"\n%d %s %f %f %f %f %f %f"
        ,f->num,f->name,f->base_salay,f->bonus,f->fine,f->salay,f->real_salay,f->tax);
        }//链表同步至文件 
        printf("同步成功\n");
        fclose(fp);//文件关闭 
        fp=NULL; //指针赋空 
}


void Statis(List list)
{//求薪资最高的人的名字,和平均薪资
    Worker *f;//临时指针,薪资最高
    Worker *max;
    max=NULL;//指向为空
    float sum,average;//总和,平均工资
    int n=1;//记录人数
    sum=0;
    for(max=f=list.head;f->next;n++,f=f->next)
    {
        sum=f->real_salay+sum;//求和
        if(f->real_salay>=max->real_salay)
            {
                max=f;//f和f所指的进行比较
            }
            
    }
    average=sum/n;//用和求平均
    printf("员工平均薪资为%f\n薪资最高的员工是%s\n",average,max->name);
}

void Sort(List list)
{
    FILE *fp;//文件打开 
    if((fp=fopen("worker.txt","w+"))==NULL){
        printf("文件打开失败\n]");
        exit(0);
    }

    Worker* dummyHead=(Worker*)malloc(LEN);//哑节点,便于在头节点之前插入节点
    dummyHead->next=list.head;
    Worker *lastSorted;//已排序的最后一个链节
    Worker *curr;//待插入元素
    lastSorted=list.head;//初始时赋为头指针 
    curr=list.head->next;//待插入元素为第二个链节 
    
    while(curr)
    {
        if(lastSorted->num<=curr->num)//进行比较 
        {
            lastSorted=lastSorted->next;
        }
        else
        {
            Worker *prev=dummyHead;//待插入节点的前一个结点
            while(prev->next->num<=curr->num)
            {
                prev=prev->next;
            }
            //遍历链表,找到刚好小于待插入节点的那一个结点prev 
            lastSorted->next=curr->next;//将已排序的最后一个链节指向要交换的链节的下一个链节 
            curr->next=prev->next;//将待插入节点与prev的后方的链节相连 
            prev->next=curr;//将prev与待插入结点相连 
        }
        curr=lastSorted->next;//待插入结点重新定位到有序部分的后一个链节 
        list.head=dummyHead->next;//如果出现插入到头节点前方的现象,可以更新头节点 
    }

    Worker *f;
    printf("排序完成正在同步至文本文件\n");
    //链表同步至文件 
    for(f=list.head;f;f=f->next)
        {
        fprintf(fp,"\n%d %s %f %f %f %f %f %f"
        ,f->num,f->name,f->base_salay,f->bonus,f->fine,f->salay,f->real_salay,f->tax);
        }
    printf("同步成功\n");
}

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧

文章标题:工资管理系统/c语言期末大作业学习经历-创新互联
转载注明:https://www.cdcxhl.com/article8/cshcop.html

成都网站建设公司_创新互联,为您提供服务器托管建站公司虚拟主机网站营销商城网站小程序开发

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

商城网站建设