链表嵌套链表实现水表增加用户,删除用户,修改用户信息,查询当月用水量和当月日均用量

#include <stdio.h>

#include<math.h>

#include<string.h>

struct Msg

{

    int month;

    int day;

    float countwater;

    struct Msg *next;

};

typedef struct User{

    char name[20];

    struct Msg *data;

    struct User *next;

}User;

void printMessage(struct User *head) { //打印输出链表

    struct User *p = head;

    struct Msg *p2 = NULL;

    if (head ==NULL)

    {

        printf("系统无数据\n");

    }else{

        for (p; p != NULL; p = p->next) {

            p2 = p->data;

        for (p2; p2 != NULL; p2 = p2->next) {

            printf("%s,%d,%d,%f\n", p->name, p2->month, p2->day, p2->countwater);

        }

        }

    }

   

   

}

struct Msg *insertStuMessage(struct Msg *head,struct Msg *newData2)

{

    if(head == NULL){

        head=newData2;

    }else{

        newData2->next=head;

        head=newData2;

    }

    return head;

}

int FindUserData(struct Msg *head,struct Msg *newData){

    struct Msg *i = head;//接收头节点数据

    struct Msg *j = newData;//接收p接点数据

     

    while (i != NULL) {

        if ( (j->month == i->month) && (j->day == i->day) && (j->countwater == i ->countwater)) {

            return 0;

            break;

        }

        i = i->next;

        break;

    }

    if(i == NULL){

        return 1;

    }

   

}


 

struct Msg *UserMessage(struct Msg *head){

    struct Msg *newData = NULL;

    newData=(struct Msg *)malloc(sizeof(struct Msg));

    printf("月份 日份 用水量\n");

    scanf("%d %d %f",&newData->month,&newData->day,&newData->countwater);

    //查找同个用户下有无相同数据

    if(FindUserData(head,newData) == 0){

        printf("该链表已经有该数据\n");

    }else {

        newData ->next = NULL;

        head=insertStuMessage(head,newData);  

    }

   

    return head;

}


 

int FindUserName1(struct User *head,char str[]){ //查找链表中的用户名

   

    while(head != NULL)

    {

        if(strcmp(head->name,str)==0){

            return 0;

           

        }

        head = head->next;

    }

    if(head == NULL){

        return 1;

    }

}

struct User *FindUserName2(struct User *head,char str[]){ //查找链表中的用户名

   

    while(head != NULL)

    {

        if(strcmp(head->name,str)==0){

            return head;

           

        }

        head = head->next;

    }

    if(head == NULL){

        return head;

    }

}


 

struct User *CreteUser(struct User *head)

{  

    struct User *p=head;//建立p指针指向head

    struct User *newUser=NULL;//用来记录新建用户信息

    struct Msg *UserMsg = NULL;

    newUser=(struct User *)malloc(sizeof(struct User));

    printf("用户名");

    scanf("%s",newUser->name);

    if(FindUserName1(head,newUser->name) == 0)

    {

        struct User *p1 = FindUserName2(head,newUser->name);

        UserMsg = p1->data;

        //这里要找到UserMsg下的节点,而不是将UerMsg = NULL直接赋值给UserMsg不然会挂不上该节点

        UserMsg = UserMessage(UserMsg);

        p1 ->data = UserMsg;

    }else{

        UserMsg = UserMessage(UserMsg);

        newUser ->data = UserMsg;

        newUser ->next = NULL;

    if(p == NULL){ //头插法

        p = newUser;

        printf("链表始终为空");

    }else{

        newUser->next=p;

        p=newUser;

        printf("链表始终不为空");

        printf("%s,%d,%d,%d",p->name,p->data->month,p->data->day,p->data->countwater);

    }

    }

   

    return p;

   

}

void DelUserData(struct Msg *head,int month,int day ){ //将链表的头节点删除后还有地址残留

    struct Msg *p2 = head;

    struct Msg *p1 = NULL;

    int month1 = month;

    int day1 = day;

    while(p2 != NULL) {

    if((p1 == NULL) && (month1 == p2->month) && (day1 == p2->day)) {

        if(p2->next != NULL) {

            head = p2->next;

            free(p2);

        } else {

            head = NULL;

            free(p2);

        }

        break;

    } else if((month1 == p2->month) && (day1 == p2->day)) {

        p1->next = p2->next;

        free(p2);

        break;

    }

    p1 = p2;

    p2 = p2->next;

}

   


 

}

void DelUser(struct User **head,char str[]){

    struct User *p1 = NULL;

    struct User *p2 = *head;

    struct Msg *msg = NULL;

    char str1[10];

    strcpy(str1, str); //直接复制


 

    while (p2 !=NULL)

    {

        if((p1 == NULL) && (strcmp(str1, p2->name) == 0) ) {

        if(p2->next != NULL) {

            msg = p2->data;

            p2->data = NULL;

            free(msg);

            *head = p2->next;

            free(p2);

           

        } else {

            msg = p2->data;

            p2->data = NULL;

            free(msg);

            *head = NULL;

            free(p2);

        }

            break;

        } else if((strcmp(str1, p2->name) == 0) ) {

            p1->next = p2->next;

            msg = p2->data;

            p2->data = NULL;

            free(msg);

            free(p2);

            break;

        }

        p1 = p2;

        p2 = p2->next;

    }

   

}


 

int ModMenu()    //修改的菜单

{

    int choose = 0;

    printf ("*    1  姓名        2  月份       *\n");

    printf ("*    3  日期        4  用水量     *\n");

    printf ("*    0  取消修改                  *\n");

    scanf ("%d", &choose);

    return choose;

}


 

void ModifyUser(struct User *head){

    struct User *p = head;

    struct User *w = NULL;

    char str1[10];

    int x = 0;

    struct Msg *modData = (struct Msg *)malloc(sizeof(struct Msg)); //为什么在这里将modData =NuLL会溢出错误

    printf("输入用户名");

    scanf("%s",str1);

    if(0 == FindUserName1(head,str1)) //先判断链表中是否有该用户

    {  

        w = FindUserName2(head,str1); //用来存放找到该用户名字的节点

        printf("请输入要修改的(月份/日份/用水量)以空格隔开\n"); //查找该用户下是否有该条数据

        scanf("%d %d %d",&modData->month,&modData->day,&modData->countwater);

        if( 0 == FindUserData(w->data,modData)){

           while (w->data !=NULL)

           {

            if (0 == FindUserData(w->data,modData))

            {

                printf("请选择修改的内容\n");

                x = ModMenu();

                switch (x)

                {

                case 1:

                    printf("新用户名:");

                    scanf("%s",w->name);

                    break;

                case 2:

                    printf("新月份:");

                    scanf("%d",&w->data->month);

                    break;

                case 3:

                    printf("新日期:");

                    scanf("%d",&w->data->day);

                    break;

                case 4:

                    printf("新用水量:");

                    scanf("%d",&w->data->countwater);

                    break;

                default:

                    printf("请输入正确的选项");

                    break;

                }

                break;

            }

            w ->data = w->data->next;

           

           }

           

        }

       

       

       

    }else printf("系统无该用户数据\n");

}

void Usage(struct User *head){

    char str1[10];

    int month = 0;

    float count = 0;

    int daycount = 0;

    struct User *w = NULL;

    printf("输入用户名");

    scanf("%s",str1);

    if(0 == FindUserName1(head,str1)) //先判断链表中是否有该用户

    {  

        printf("输入月份");

        scanf("%d",&month);

        w = FindUserName2(head,str1);

        switch (month)

        {

            case 1:

            case 3:

            case 5:

            case 7:

            case 8:

            case 12:

                daycount = 31;

                break;

            case 2:

                daycount = 28;

                break;

            case 4:

            case 6:

            case 9:

            case 10:

            case 11:

                daycount = 30;

                break;

            default:

                printf("请输入正确的月份\n");

                break;

        }

        if(w->data != NULL){

        while (w->data != NULL)

        {

            if(w->data->month == month){

                count += w->data->countwater;

            }

            w->data = w->data->next;

        }

       

        }

        float day_avg = (float)(count)/daycount;

        printf("用户%s的%d月的用水量为%f,日平均用水量为%f\n",w->name,month,count,day_avg);

    }else printf("系统无该用户数据\n");

}


 

int main()

{

    struct User *head = NULL;

    int x ;

    int answer = 0;

    do{

        printf("输入序号选择你要进行的操作:\n");  

        printf("1.增加信息\n");

        printf("2.删除信息\n");

        printf("3.修改信息\n");

        printf("4.查询用户当月用水量和日均用水量\n");

        printf("5.输出所有信息\n");

        printf("6.退出\n");

        scanf("%d",&x);

        switch(x)

        {

            case 0 : break;

            case 1 :

                head = CreteUser(head);

                break;

            case 2 :{

                char str[10];

                int month,day;

                struct User *U = NULL;

                printf("请输入要删除的用户的姓名\n");

                scanf("%s",str);

                //查找用户是否存在

                if(FindUserName1(head,str) == 0)

                {

                    printf("是否要删除该用户的所有数据:1/2\n");

                    scanf("%d",&answer);

                    if(answer == 1){

                        DelUser(&head,str);

                    }else{

                        printf("输入月份");

                        scanf("%d",&month);

                        printf("输入日份");

                        scanf("%d",&day);

                    //先遍历函数是否有该日期数据

                        U = FindUserName2(head,str);

                        DelUserData(U->data,month,day);

                    }

                   

                }else printf("系统无该用户数据\n");

            }

            break;  

            case 3 :

                ModifyUser(head);

                break;

            case 4 :

                Usage(head);

                break;

            case 5 :

                printMessage(head);

                break;

            case 6 :

                exit(0);

                break;

            default :

                printf ("选择错误!!!\n");

                break;

        }

    }while(x);

   

    return 0;

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值