电话费管理系统:清华大学课程设计

转自jxyd.net的charly

9-0:编制电话费统计管理系统,包括本地电话费(0.18元/3分钟)、国内长途电话全价(1.0元/分钟+附加费0.1元/分),注意分时段折扣(附加费不半价打折),如7:00(含)-21:00(不含)时段,周一至周五全价,周六及周日半价,21:00(含)-24:00(不含)时段全部半价,0:00(含)-7:00(不含)全部打3折、IP电话(0.3元/分钟+本地电话费)不分时段,要求功能:
编写主菜单。
统计各个时段的业务量(即通话总时数)和话费收入。
对各个时段的通话业务进行排序。
打印简单的用户话费清单。
对不同的时间段拨打电话能够进行自动计费,同时考虑跨时间段的情况。其中,用户信息有用户姓名、电话号码、国内长途通话时间、市内电话通话时间、通话时段、月租费、当月费用。
考虑非周末的节假日的话费半价,应对程序进行如何处理,编写此功能的代码。

A:(感兴趣的同学可以此题替代前题)在Turbo C图形环境下编写一个中国象棋或围棋的游戏程序,要求能够正确显示棋盘、棋子,用户输入棋子移动坐标(中国象棋)或新下棋子坐标(围棋),接受用户输入,在屏幕上显示布局,死子能够自动清除。另外,请考虑如何让计算机判断棋局结束(此功能属额外内容,另加分)。
我应别人要求做了这一题,还有好几题。
的确不简单!
// telephoneManager.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include"help.h"
#include"release.h"

int main(int argc, char* argv[])
{
char ch;
timeRecord *list=NULL;

while(true)
{
help();
printf("请输入选项:");
scanf("%c",&ch);
getchar();
if(ch<'1'||ch>'9')break;
switch(ch)
{
case '1':
appendClient();
getchar();
break;
case '2':
findClient();
getchar();
break;
case '3':
stimulate();
getchar();
break;
case '4':
tongji(list);
getchar();
break;
case '5':
sortManager(list);
getchar();
break;
case '6':
printAllClients();
break;
case '7':
liuyanban();
break;
case '8':
printSuggest();
break;
}
}
return 0;
}
//help.h
void help()
{
printf("*****功能选项*****/n");
printf("增加客户请按1/n");
printf("查询客户请按2/n");
printf("模拟计费请按3/n");
printf("统计收入请按4/n");
printf("排序业务请按5/n");
printf("打印客户列表请按6/n");
printf("进入留言版请按7/n");
printf("查看所有留言请按8/n");
printf("退出系统请按其它/n");
}
//struct.h
#ifndef STRUCT_H
#define STRUCT_H
#include <time.h>
struct Time
{
int year;
int month;
int day;
int hour;
int minute;
int second;
};
struct Suggest
{
Time time;
char suggest[256];
};
struct shortClientInfo
{
char name[20];
char telephone[12];
};

struct timeRecord//时间段
{
int type;
int second;
float Money;
Time start;
Time end;
shortClientInfo client;
timeRecord *next;
};
struct ClientInfo//用户信息
{
char name[20];
char telephone[12];
long farCall;//seconds
long nearCall;//seconds
long ipCall;// seconds
float monthFixFee;//rent fees per month
float sum;//fees per month
};
#endif
//getmoney.h
#include"struct.h"
#include"getweekday.h"
float getMoney(Time start,Time* end,int second,int type);
float getMoney(Time start,Time* end,int second,int type)
{
float sum;
int half_sec=0,three_sec=0,whole_sec=0,weekday=0;
int half_min=0,three_min=0,whole_min=0;
Time run=start;
weekday=getweekday(start);

while(1)
{
if(second==0)
break;

second--;
run.second++;

if(weekday<6 && weekday>0)
{
if(run.hour<=7)//0~7点3折
three_sec++;
else if(run.hour<21)
{
//考虑节假日元月1日,5月1日,10月1日
if((run.month==1&&run.day==1)
||(run.month==5&&run.day==1)
||(run.month==10&&run.month==1))
{
half_sec++;
}
else
whole_sec++; //whole_min++;//7点~21点全价
}
else
half_sec++;//21点~24点半价
}
else//星期六和星期天
{
if(run.hour<=7)//0~7点3折
three_sec++;
else
half_sec++;//其余半价
}

if(run.second==61)
{
run.second=1;
run.minute++;
}
if(run.minute==61)
{
run.minute=1;
run.hour++;
}
if(run.hour==24)
{
run.hour=1;
run.day++;
weekday++;

if(weekday==7)//对星期循环计数
weekday=0;
}
if( run.month==1//大月
||run.month==3
||run.month==5
||run.month==7
||run.month==8
||run.month==10
||run.month==12)
{
if(run.day==32)
{
run.day=1;
run.month++;
}
}
else if(run.month==2)//二月
{
if((run.year%4==0
&&run.year%100!=0)
||run.year%400==0)
{
if(run.day==30)//闰年
{
run.day=1;
run.month++;
}
}
else//平年
{
if(run.day==29)
{
run.day=1;
run.month++;
}
}
}
else
{
if(run.month==4||//小月
run.month==6||
run.month==9||
run.month==11)
{
if(run.day==31)
{
run.day=1;
run.month++;
}
}
}
if(run.month==13)
{
run.month=1;
run.year++;
}
}
*end=run;
whole_min=(whole_sec+29)/60;
half_min=(half_sec+29)/60;
three_min=(three_sec+29)/60;
switch(type)
{
case 1:////国内长途电话
sum=whole_min*1.1+half_min*(1.0*0.5+0.1)+three_min*(1.0*0.3+0.1);
break;
case 2:///本地电话
sum=whole_min*0.06+half_min*0.06*0.5+three_min*0.06*0.3;
break;
case 3://///IP电话
sum=0.36*(whole_sec+half_sec+three_sec+59)/60;
break;
}
return sum;
}

//getweekday
//#include<stdio.h>
int getweekday(Time time);
int getweekday(Time time)
{
int s;
int c=0;
int x=time.year;
for(int i=1;i<=time.month;i++)
{
switch(i)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
if(i==time.month)
c+=time.day;
else
c+=31;
break;
case 4:
case 6:
case 9:
case 11:
if(i==time.month)
c+=time.day;
else
c+=30;
break;
case 2:
if(i==time.month)
c+=time.day;
else
{
if((time.year%4==0)&&(time.year%100!=0)||time.year%400==0)
c+=29;
else
c+=28;
}
break;
}
}
s=x-1+(int)(x-1)/4-(int)(x-1)/100+(int)(x-1)/400+c;
//printf("星期 %d/n",s%7);
return s%7;
}
//release.h
#include"business.h"
#include"file.h"
#include"getmoney.h"
void findClient();//查询客户
void stimulate();
void buildList(timeRecord*&list);
void sortManager(timeRecord*&list);
void tongji(timeRecord*&list);
void printAllClients();
void liuyanban();
void findClient()//查询客户
{
char s[13];
int month;
bool b;
printf("请输入客户号码:/n");
scanf("%s",s);
b=printClient(s);
if(b)
{
printf("/n请输入月份:/n");
scanf("%d",&month);
printPerMonth(s,month);
}
}
void stimulate()//模拟计费
{
char ch,s[20];
int y,month,d,h,minute,sec,second,type;
long length,num,which;
float sum;
ClientInfo client;
timeRecord tr;
FILE *fp;
fp=fopen("ClientInfo.txt","r");
if(!fp)
{
printf("**********error:无法打开客户文件***********/n");
return;
}
fseek(fp,0L,SEEK_END);
length=ftell(fp);
num=length/sizeof(ClientInfo);
printf("共有 %ld 位客户/n",num);
if(num==0)
return ;
printf("请输入数字选择一个客户打电话:");
scanf("%ld",&which);
while(which<1&&which>num)
{
printf("请输入正确的数字:");
scanf("%ld",&which);
}
fseek(fp,(which-1)*sizeof(ClientInfo),SEEK_SET);
fread(&client,sizeof(ClientInfo),1,fp);
fclose(fp);

strcpy(s,client.telephone);
strcat(s,".txt");
fp=fopen(s,"r");
if(!fp)
{
printf("**********error:无法打开该客户通话记录文件***********/n");
return;
}
scanf("%c",&ch);
printf("请输入开始时间:/n");
printf("年:");
scanf("%d",&y);
printf("月:");
scanf("%d",&month);
printf("日:");
scanf("%d",&d);
printf("时:");
scanf("%d",&h);
printf("分:");
scanf("%d",&minute);
printf("秒:");
scanf("%d",&sec);
tr.start.year=y;
tr.start.month=month;
tr.start.day=d;
tr.start.hour=h;
tr.start.minute=minute;
tr.start.second=sec;
tr.next=NULL;

printf("请输入通话类型(1,2,3):");
scanf("%d",&type);
tr.type=type;
printf("请输入通话时间(秒):");
scanf("%d",&second);
tr.second=second;
sum=getMoney(tr.start,&tr.end,second,type);
tr.Money=sum;
strcpy(tr.client.name,client.name);
strcpy(tr.client.telephone,client.telephone);
appendRecord(client.telephone,tr);
modifyClientInfo(client.telephone,type,second,sum);
fclose(fp);
}
void buildList(timeRecord*&list)
{
int hs,he;
printf("请输入时间段起始时刻(小时):");
scanf("%d",&hs);
while(hs<0||hs>=24)
{
printf("请输入正确时刻(小时):");
scanf("%d",&hs);
}
printf("请输入时间段结束时刻(小时):");
scanf("%d",&he);
while(he<0||he>24||hs>he)
{
printf("请输入正确时刻(小时):");
scanf("%d",&he);
}
getAllRecords(list,hs,he);
}
void sortManager(timeRecord*&list)
{
if(!list)
buildList(list);
getchar();
printf("输入 1按时间排序/n");
printf("输入 2 按费用排序/n");
printf("输入 其他不排序退出本模块/n");
char kind;
timeRecord *p=NULL;
scanf("%c",&kind);
switch(kind)
{
case '1':
sortByTime(p,list);
break;
case '2':
sortByMoney(p,list);
break;
default:
print(list);
break;
}
print(p);
delete list;
list=NULL;
delete p;
}
void tongji(timeRecord*&list)
{
long totaltime=0,far1=0,near1=0,ip=0;
float totalincome=0,farincome=0,nearincome=0,ipincome=0;
if(!list)
buildList(list);

getSeconds(list,far1,near1,ip);//得到三种时间(秒)
totaltime=far1+near1+ip;//获得某段通话总时间
getIncome(list,farincome,nearincome,ipincome);//得到三种收入(元)
totalincome=farincome+nearincome+ipincome;//获得总收入(元)
printf("*******这个时段内的通话时间统计*******/n");
printf("长途=%ld分 市内=%ld分 ip=%ld分 和=%ld分/n",far1/60,near1/60,ip/60,totaltime/60);

printf("*******这个时段内的通话收入统计*******/n");
printf("长途=%.2f元 市内=%.2f元 ip=%.2f元 和=%.2f元/n",farincome,nearincome,ipincome,totalincome);
delete list;
list=NULL;
}
void liuyanban()
{
char ch;
int i=0;
tm now;
Suggest suggest;
_getsystime(&now);
suggest.time.year=now.tm_year+1900;
suggest.time.month=now.tm_mon+1;
suggest.time.day=now.tm_mday;
suggest.time.hour=now.tm_hour;
suggest.time.minute=now.tm_min;
suggest.time.second=now.tm_sec;
printf("请输入建议内容:/n");
ch=getchar();
while(ch!='/n')
{
suggest.suggest[i++]=ch;
ch=getchar();
}
suggest.suggest[i++]='/0';
suggest.suggest[i]='/0';
appendSuggest(suggest);
}
void printAllClients()
{
FILE *fp;
ClientInfo client;
fp=fopen("ClientInfo.txt","r");
if(!fp)
{
printf("*********要测试的客户文件不存在***********/n");
return;
}
printf("姓名/t/t电话/t/t长途(秒)/t市内/tip/t月租/t当月小计/n");
printf("客户列表/n");
while(!feof(fp))
{
if(fread((ClientInfo*)&client,sizeof(ClientInfo),1,fp))
printf("%s/t%s/t/t%ld/t%ld/t%ld/t%.2f/t%.2f/n",client.name,client.telephone,
client.farCall,client.nearCall,client.ipCall,client.monthFixFee,client.sum);
}
fclose(fp);
}

sort.h
void sortByTime(timeRecord*&pnew,timeRecord*phead);
void sortByMoney(timeRecord*&pnew,timeRecord*phead);
void print(timeRecord *phead);
//这三个函数的测试放在了testBuildList();
void sortByTime(timeRecord*&pnew,timeRecord*phead)//这两段代码基本一样
{
timeRecord *p,*q,*t,*r,*temp;
if(!phead)
{
pnew=NULL;
return;
}
if(!phead->next)
{
pnew=new timeRecord;
*pnew=*phead;//不必排序
return;
}

q=NULL;
p=phead;
while(p)
{
if(pnew==NULL)
{
pnew=new timeRecord;
*pnew=*phead;
pnew->next=NULL;
}
else
{
t=pnew;
r=NULL;
while(t)
{
temp=new timeRecord;
*temp=*p;
temp->next=NULL;
if(p->second>t->second)
{
if(r==NULL)
{
temp->next=t;
pnew=temp;
}
else
{
temp->next=t;
r->next=temp;
}
break;
}
else
{
if(t->next==NULL)
{
t->next=temp;
break;
}
else
{
r=t;
t=t->next;
}
}
}
}
q=p;
p=p->next;
}
}
void sortByMoney(timeRecord*&pnew,timeRecord*phead)//都采用头插法排序
{
timeRecord *p,*q,*t,*r,*temp;
if(!phead)
{
pnew=NULL;
return;
}
if(!phead->next)
{
pnew=new timeRecord;
*pnew=*phead;//不必排序
return;
}

q=NULL;
p=phead;
while(p)
{
if(pnew==NULL)
{
pnew=new timeRecord;
*pnew=*phead;
pnew->next=NULL;
}
else
{
t=pnew;
r=NULL;
while(t)
{
temp=new timeRecord;
*temp=*p;
temp->next=NULL;
if(p->Money>t->Money)
{
if(r==NULL)
{
temp->next=t;
pnew=temp;
}
else
{
temp->next=t;
r->next=temp;
}
break;
}
else
{
if(t->next==NULL)
{
t->next=temp;
break;
}
else
{
r=t;
t=t->next;
}
}
}
}
q=p;
p=p->next;
}
}
void print(timeRecord *phead)
{
if(!phead)
{
printf("通话记录为空或没有建立链表/n");
return;
}
timeRecord*p;
p=phead;
while(p)
{
printf("%d-%d-%d %d:%d:%d /t%d-%d-%d %d:%d:%d ",
p->start.year,p->start.month,p->start.day,
p->start.hour,p->start.minute,p->start.second,
p->end.year,p->end.month,p->end.day,
p->end.hour,p->end.minute,p->end.second);
printf("%d %d %.2f %s %s/n",
p->type,p->second,p->Money,p->client.name,p->client.telephone);
p=p->next;
}
}

先要建立一份ClientInfo.txt空文件
本程序是对电话管理计费系统的模拟,使用c语言编写。
本程序实现了文档中的绝大部分要求。

所谓模拟,意思是不是真实的,但是却是合理的。
所以,用户可以不必考虑许多人同时通电话的情况,以免陷入泥潭,不能自拔。
模拟的部分全部手动输入。我没有提供年月日的合法性检查,可以不必在这些细节上花时间,
因为这只是练习而已,是不能实际使用的。用户输入时间时应该考虑后面一次输入的起始结束时间
一定要比前面一次的结束时间大,这里我没有提供检查。

模块说明:
主要模块包括:
增加客户,查询客户,模拟计费,统计业务,排序业务,留言版
这些主要模块均放在release.h中
涉及到文件的函数都放在file.h中
该文件中的函数大都被release.h中的函数调用

所有测试的函数都放在test.h中

主要函数列表说明
//file.h
void appendClient();//增加客户
void appendRecord(char*filename,timeRecord tr);//增加通话记录
bool printClient(char*telephone);//给出电话号码打印客户信息
void printPerMonth(char*telephone,int month);//给定电话号码,月打印该月通话费用
//给定电话号码作为文件名,起讫时间,获得链表,用于分段统计业务
void getRecordList(char*telephone,timeRecord*&phead,int s0,int e0);//单个客户的通话记录
void getAllRecords(timeRecord*&phead,int s0,int e0);
//获得通话记录链表,调用上面一个函数,获得所有记录

void modifyClientInfo(char*telephone,int type,int second,float sum);//修改客户通话时间及费用
void appendSuggest(Suggest suggest);//向文件追加一条建议
void printSuggest();//打印所有留言

//business.h
void getSeconds(timeRecord* phead,long &farcall,long&nearcall,long&ipcall);//得到三种时间(秒)
void getIncome(timeRecord* phead,float &farcall,float&nearcall,float&ipcall);//得到三种收入(元)
void getSeconds(timeRecord* phead,long &farcall,long&nearcall,long&ipcall)//得到三种时间(秒)

//getmoney.h
float getMoney(Time start,Time* end,int second,int type);//计费函数
//getweekday.h
int getweekday(Time time);//给定日期获得相应的星期,这段代码很简洁

//sort.h
void sortByTime(timeRecord*&pnew,timeRecord*phead);//给定链表,对其排序,结果放在新链表中
void sortByMoney(timeRecord*&pnew,timeRecord*phead);
void print(timeRecord *phead);//打印链表

//release.h//主控模块
void findClient();//查找客户
void stimulate();//模拟
void buildList(timeRecord*&list);//建立业务链表
void sortManager(timeRecord*&list);//排序业务
void tongji(timeRecord*&list);//统计业务
void printAllClients();//打印所有客户信息
void liuyanban();//留言版

//test.h 下的所有函数在这儿就不说明了

数据结构
为了省地盘,我就不写了,参考第一篇
算法说明:
用户每增加一个客户就会建立一个通话记录文件,该文件以电话号码命名。
这个程序的关键是文件操作,链表操作。
功能的核心是计费。
链表排序的部分,我采用的是头插法排序

写这个程序,我吸取了以前写程序的教训,每一个模块都经过了严格的测试。
应该说这个程序的模块划分较为合理,达到了文档的要求。
由于时间仓卒
错误之处在所难免
希望读者批评指正

读者在使用中若到错误,
请与我联系 email:zhangxianlieyou@eyou.com

感言
写程序不可操之过急
首先,应该充分分析程序的结构,对程序的框架了然于心。
第二,找出各个模块的关键算法。要把复杂的问题简单化,尽量考虑一个简单数学
的模型,不可顾虑太多。
第三,写程序时,考虑模块化,一个模块一个模块的做,并且一定要做完就测试,不可拖延。
第四,要精益求精,使程序更加简练,精简。这大概算得上审美要求了。
呵呵,做程序员就是苦啊。

阅读更多
个人分类: C代码(转载)
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭