#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;
}