// 用电收费管理程序
// 主要用结构体数组实现,用结构体表示每项记录,数据为:编号、用户地址、户名、上次读数、抄表读数、电费余额。
// 设计各个函数,分别实现以下功能:
//(1)录入:完成用户信息的输入;
//(2)删除:完成用户信息的删除;
//(3)插入:添加新用户且按照编号从小到大的顺序;
// (4) 修改:允许对已经录入的数据重新进行编辑、修改;
//(5)显示:显示所有用户的信息;
// a. 按用户地址查找用户信息,并打印显示;
// b. 按户名查找所有用户信息,并打印显示;
//(6)交费:按用户地址查找唯一信息,输入金额,实现交费功能;
//(7)抄表:按用户地址查找唯一信息,输入读数,实现抄表功能;
//(8)退出程序。
// 设计菜单,通过选择菜单调用以上各函数。#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//#define NULL 0
struct people
{
long num;//客户编号
char space[20];//客户地址
char name[20];//户名
long lastreading;//上次读书
long thisreading;//抄表读数
long electricitybalance;//电费余额
struct people *next;//用户缴费
};
int n;//定义全局变量,存放链表的长度,数据元素的个数等于n
struct people *creat(void);//录入
struct people *del(struct people*head,long num);//删除
struct people *insert(struct people*head,struct people*stud);//插入
struct people *change(struct people*head);//修改
void print(struct people *head);//显示
void show(struct people *head);//特殊查询
struct people *payment(struct people *head);
struct people *meter(struct people *head);
int main()
{
struct people *head,*stu;//head就是第一个元素,这是不带头结点的单链表
long del_num;//需要删除的用户编号
int numb,m;//numb用于主菜单的进入,m用于各个菜单下case的循环,k用于修改用户数据分菜单
printf("尊敬的管理员,欢迎进入用电收费管理系统\n");
printf("录入用户:1\n删除用户:2\n插入用户:3\n修改信息:4\n查询特定信息:5\n用户缴费:6\n本次抄表: 7\n退出系统:8\n");
do
{
printf("请输入要进行操作的序号:");
scanf("%d",&numb);
switch(numb)
{
case 1:
printf("建立链表,输入用户编号,用户姓名,用户地址,账户余额,上次读数:\n");
head=creat();//由于是不带头结点的单链表则需要给头指针重新赋值,若带头结点则不需要重新赋值
print(head);
break;//录入
case 2://删除
m=1;
while(m==1)
{
printf("删除链表,输入待删除链表的用户编号:");
scanf("%ld",&del_num);
head=del(head,del_num);//删除del(head,del_num)进入分程序;由于是不带头结点的单链表则需要给头指针重新赋值,若带头结点则不需要重新赋值
printf("如输入数字1则继续进行删除操作若输入0则进行菜单选择:");
scanf("%d",&m);//当head=0时输入del_num=0则停止该while();若head不为0则用输入del_num控制删除用户
}
print(head);//显示;break;
break;
case 3://插入
m=1;
while(m==1)
{
printf("插入链表,输入待插入链表的用户信息:");
stu=(struct people * )malloc(sizeof(struct people));
scanf("%ld%s%s%ld%ld",&stu->num,stu->name,stu->space,&stu->electricitybalance,&stu->lastreading);//用指针stu来储存新用户信息
head=insert(head,stu);//插入insert(head,stu);进入分程序由于是不带头结点的单链表则需要给头指针重新赋值,若带头结点则不需要重新赋值
n++;
printf("如输入数字1则继续进行插入操作若输入0则进行菜单选择:");
scanf("%d",&m);
}
print(head);//显示
break;
case 4://修改
m=1;
while(m==1)
{
head=change(head);//由于是不带头结点的单链表则需要给头指针重新赋值,若带头结点则不需要重新赋值
printf("如输入数字1则继续进行修改操作若输入0则进行菜单选择:");
scanf("%d",&m);
}
print(head);//显示
break;
case 5://特殊查询
show(head);
break;
case 6://用户缴费
head=payment(head);//由于是不带头结点的单链表则需要给头指针重新赋值,若带头结点则不需要重新赋值
print(head);//显示
break;
case 7:
head=meter(head);//由于是不带头结点的单链表则需要给头指针重新赋值,若带头结点则不需要重新赋值
print(head);//显示
}
}
while(numb!=8);
if(numb==8)
printf("已退出系统");
}
struct people *creat(void)//录入且为保证可以持续输入数据出现两个scanf
{
struct people *head,*p,*tail;
head=NULL;//设一条单链表的头指针变量为head,且该单链表无头结点,则其判空条件为head=NULL,若带头结点则判空条件为head->next=NULL.
n=0;//n为全局变量,数据元素的个数等于n
tail=(struct people *)malloc(sizeof(struct people));
p=tail;
int m=1;
while (m==1)//输入数据为1时继续录入
{
scanf("%ld%s%s%ld%ld",&p->num,p->name,p->space,&p->electricitybalance,&p->lastreading);
n=n+1;
if(n==1) head=p;
else tail->next=p;
tail=p;//用指针tail来储存指针p的内容,用p指针来进行后续的新建数据
p=(struct people*)malloc(sizeof(struct people));
printf("若继续请按1,若停止录入则按0:");
scanf("%d",&m);
}
tail->next=NULL;
return (head);//如果刚建立的时候没有用户这head=0,如果有用户则指针head指向首地址
}
struct people *insert(struct people * head,struct people * stud)//插入
{
struct people * pGuard;
if(head==NULL)//链表未插入之前无元素时,则stud为第一个元素
{
head=stud;
stud->next=NULL;
return (head);
}
if (head->num>stud->num)//链表未插入之前仅有一个元素时,将新建立的用户插入其中的时候按照编号从小到大排序新用户编号小于第一个用户
{
stud->next=head;
head=stud;//head始终用于记录第一个元素
return(head);
}
pGuard=head;//保存头指针
while((pGuard->next!=NULL)&&(pGuard->next->num<stud->num))//链表未插入之前存在第二个用户的条件下且新用户编号大于第二个用户编号
pGuard=pGuard->next;//寻找待插入点的位置至结尾
stud->next=pGuard->next;//指针pGuard在指针stud之前,pGuard->next在stud之后,因为此时pGuard->next->num>stud->num
pGuard->next=stud;//此时处理链表未插入之前仅有一个元素时,将新建立的用户插入其中的时候按照编号从小到大排序新用户编号大于第一个用户的情况
return(head);
}
struct people *del(struct people*head,long num)//删除
{
struct people *p,*pGuard;//用指针pGuard记录指针p的位置
if(head==NULL)//链表无元素时
{
printf("链表为空!\n");
return(head);
}
p=head;//将首地址传给p
while((num!=p->num)&&(p->next!=NULL))//寻找待删除节点至链尾strcmp适用于两个字符串,不适用于此
{
pGuard=p;//用指针pGuard记录指针p的位置
p=p->next;//当p->next==NULL时,指针p为最后一个元素,pGuard为倒数第二个;当num==p->num是pGuard在p的前一个指针
}
if(num==p->num)
{
if(p==head) head=p->next;//由于指针p是首地址的,所以当第一个用户被删除的时候,指针head指向第二个用户
else pGuard->next=p->next;//pGuard是位于指针p的后一位,当进行pGuard->next=p->next,则指针p的位置被删除
printf("删除编号为%ld的用户.\n",num);
n=n-1;
}
else printf("链表中不存在编号为%ld的用户\n",num);//此时时满足p->next==NULL
return (head);//返回头指针
}
void print(struct people *head)
{
struct people *p;
printf("现有%d条用户记录如下:\n",n);
p=head;
if(head!=NULL)
do
{
printf("用户编号:%ld 用户姓名:%s 用户地址:%s 账户余额:%ld 上次读数:%ld\n",p->num,p->name,p->space,p->electricitybalance,p->lastreading);
p=p->next;
}
while (p!=NULL);
}
struct people *change(struct people *head)//修改
{
int k;
int peoplenumb;
struct people *p;
printf("请输入要修改的客户的编号:");
scanf("%d",&peoplenumb);
if(head==NULL)//链表无元素时
{
printf("链表为空!\n");
return(head);
}
p=head;//将首地址传给p
for(k=0; k<n; k++)
{
if(p->num!=peoplenumb)//寻找待删除节点至链尾
p=p->next;
else
{
break;
}
}
if(k==n)
printf("未找到该用户\n");
else
{
printf("插入链表,输入待插入链表的用户信息:");
scanf("%ld%s%s%ld%ld",&p->num,p->name,p->space,&p->electricitybalance,&p->lastreading);//用指针pGuard来储存该用户修改后的信息
}
return (head);//返回头指针
}
void show(struct people *head)//相同信息归类查找
{
int j,k,f;//f用于统计同地区或同姓名人数,k用于选择查询相同地区或相同户名,j用于进行for循环
int c=1;
char homespace[20];
char homename[20];
struct people *happy;
happy=head;//将首地址传给p
printf("查找相同用户地址则按3,查找相同户名则按4:");
scanf("%d",&k);
switch(k)//表达式仅能为整形表达式
{
case 3:
while(c==1)
{
f=0;
happy=head;//将首地址传给p,以便再次进行查询相同地址
printf("请输入要查找的客户的家庭地址:");
scanf("%s",homespace);
for(j=0; j<n; j++)
{
if(strcmp(happy->space,homespace)!=0)//寻找待删除节点至链尾
happy=happy->next;
else
{
printf("用户编号:%ld 用户姓名:%s 用户地址:%s 账户余额:%ld 上次读数:%ld\n",happy->num,happy->name,happy->space,happy->electricitybalance,happy->lastreading);
happy=happy->next;
f++;
}
}
printf("以上共有%d条用户在同一地区:\n",f);
if(j==n&&f==0)
printf("未找到该家庭住址的用户\n");
printf("输入1则进行相同地址查询若输入0则不进行:");
scanf("%d",&c);
}
break;
case 4:
while(c==1)
{
f=0;
happy=head;//将首地址传给p,以便再次进行查询相同地址
printf("请输入要查找的客户的户主姓名:");
scanf("%s",homename);
for(j=0; j<n; j++)
{
if(strcmp(happy->name,homename)!=0)//寻找待删除节点至链尾
happy=happy->next;
else
{
printf("用户编号:%ld 用户姓名:%s 用户地址:%s 账户余额:%ld 上次读数:%ld\n",happy->num,happy->name,happy->space,happy->electricitybalance,happy->lastreading);
happy=happy->next;
f++;
}
}
printf("以上共有%d条用户是同一户主:\n",f);
if(j==n&&f==0)
printf("未找到该姓名的用户\n");
printf("输入1则继续进行相同用户查询若输入0则不进行:");
scanf("%d",&c);
}
}
}
struct people *payment(struct people *head)
{
int j,c=1,f=0,g,h;//g为缴款数目
char homespace[20];
struct people *happy;
happy=head;//将首地址传给p
while(c==1)
{
happy=head;//将首地址传给p,以便再次进行查询相同地址
printf("请输入要缴费的客户地址:");
scanf("%s",homespace);
for(j=0; j<n; j++)
{
if(strcmp(happy->space,homespace)!=0)//寻找待删除节点至链尾
happy=happy->next;
else
{
printf("请输入该用户本次交款数目:");
scanf("%d",&g);
printf("用户编号:%ld 用户姓名:%s 用户地址:%s 账户余额:%ld 上次读数:%ld\n",happy->num,happy->name,happy->space,happy->electricitybalance,happy->lastreading);
h=(happy->electricitybalance+g);
printf("本次交款之后用户现金余额为%d\n",h);
happy->electricitybalance=h;
happy=happy->next;
f++;
}
}
if(j==n&&f==0)
printf("未找到该编号的用户\n");
printf("输入1则进行相同地址查询若输入0则不进行:");
scanf("%d",&c);
}
return (head);//返回头指针
}
struct people *meter(struct people *head)
{
int j,c=1,f=0,g,h,v;//g为读数数目
char homespace[20];
struct people *happy;
happy=head;//将首地址传给p
while(c==1)
{
happy=head;//将首地址传给p,以便再次进行查询相同地址
printf("请输入要抄表的客户地址:");
scanf("%s",homespace);
for(j=0; j<n; j++)
{
if(strcmp(happy->space,homespace)!=0)//寻找待删除节点至链尾
happy=happy->next;
else
{
printf("请输入该用户本次抄表读数:");
scanf("%d",&g);
printf("用户编号:%ld 用户姓名:%s 用户地址:%s 账户余额:%ld 上次读数:%ld\n",happy->num,happy->name,happy->space,happy->electricitybalance,happy->lastreading);
h=g;
v=happy->lastreading-h;
printf("从上次抄表到现在使用度数为%d\n",v);
happy->lastreading=h;
happy=happy->next;
f++;
}
}
if(j==n&&f==0)
printf("未找到该编号的用户\n");
printf("输入1则继续进行抄表若输入0则不进行:");
scanf("%d",&c);
}
return (head);//返回头指针
}
C语言:用电收费管理程序
最新推荐文章于 2023-03-31 10:25:39 发布