电信计费模拟实现C语言.docx
- 文档编号:11158571
- 上传时间:2023-02-25
- 格式:DOCX
- 页数:23
- 大小:434.85KB
电信计费模拟实现C语言.docx
《电信计费模拟实现C语言.docx》由会员分享,可在线阅读,更多相关《电信计费模拟实现C语言.docx(23页珍藏版)》请在冰豆网上搜索。
电信计费模拟实现C语言
程序设计报告
(2012/2013学年第二学期)
题目:
电信计费模拟实现
专业通信工程
学生姓名
班级学号
指导教师郭剑
指导单位计算机软件教学中心
日期2013年6月27日
电信计费模拟实现
一、课题内容和要求
电信计费系统主要负责对电信各类客户每月帐单统计、查询、备份等管理工作。
本课题以该系统要求编写一个程序,实现对电信计费的模拟。
通过此可以,熟练掌握文件读写、函数调用等知识,以及查找、典型算法的设计与应用。
二、需求分析
功能框架图:
(见图1)
图1
(1)提供可操作的主菜单:
输出个菜单,用于显示以从文件中加载的总客户信息和若干个可选的功能选项。
根据客户输入的选项来运行不同的功能,运行不同的函数。
(2)进行文本信息的载入:
从指定的文件中以链表形式加载所需的客户信息。
这里的文件是在编译时就已经指定好的、存在的文本,需设计者预先自己建立好。
(3)查找客户功能:
以客户输入的电话号码进行查找对应的客户信息并将它们输出。
(4)对现有信息的保存:
保存内存中的最新的记录输出到磁盘文件中。
这里默认的是保存到原读取文件中并覆盖原来的信息。
(5)将信息备份到另外的一个文本中:
通过文件格式读写函数,将源文件信息写到客户提供的目标文件中。
(6)分类合计功能:
客户话费小计、长话费小计、通话费合计、客户帐单数量。
三、概要设计
1主要结构体:
structconsumer//用户信息定义
{
charname1[10];//客户姓氏
charname2[10];//客户名
charphone[9];//电话号码
charYN[2];//来电显示是否
}yhzl[100];
structfeelist//话单信息定义
{
charnumber1[9];//主叫号码
charnumber2[13];//被叫号码
charqishi[15];//通话起始时间
charzhongzhi[15];//通话终止时间
}hd[300];
structhuafei
{
charhaoma[9];//本人号码
charxingming1[10];//姓
charxingming2[10];//名
inty;//月租费
intg;//功能费
doubleshinei;//市内话费
doublechangtu;//长途话费
doublezonghe;//总和
}hfd[100];
2主要函数流程图:
(1)装载函数:
用于实现用户与系统的交互,显示用户菜单、操作提示等,流程图如图2所示:
图2图3
(2)查找函数:
利用用户输入的号码进行顺序查找并将找到的客户的所有通话记录并输出。
见图3
(3)查看账单:
利用计算函数和输入的用户号码,,进行顺序查找出用户的通话账单并显示在屏幕上。
见图4
图4图5
(4)检查错误话单:
检查号码通话时长是否大于三天,并显示和保存异常话单,如图5
(5)保存文件函数:
将用户所有通话记录保存到本文件中。
四、源程序代码
#include
#include
#include
structconsumer//用户信息定义
{
charname1[10];//姓
charname2[10];//名
charphone[9];//电话号码
charYN[2];//来电显示是否
}yhzl[100];
structfeelist//话单信息定义
{
charnumber1[9];//主叫号码
charnumber2[13];//被叫号码
charqishi[15];//通话起始时间
charzhongzhi[15];//通话终止时间
}hd[300];
structhuafei
{
charhaoma[9];//本人号码
charxingming1[10];//姓
charxingming2[10];//名
inty;//月租费
intg;//功能费
doubleshinei;//市内话费
doublechangtu;//长途话费
doublezonghe;//总和
}hfd[100];
constinta=25,b=6;//a为月租费,b为来电显示费
constdoublec=0.1,d=0.7;//c为市内电话单价,d为长途电话单价
voidjisuan();//计算所有话费信息
voidmenu();//显示菜单
doubleshijian(char[],char[]);//计算单次通话时长
voidjilu(char[]);//显示个人所有通话记录
voidxiangxi(char[]);//显示个人话费账单
voidsavefile(char[]);//保存个人所有通话记录
voidcheck(char[]);//检查号码通话时长是否大于三天,并显示和保存异常话单
intmain()
{
inte;//e为所选操作项目序号
charf;//f为记录是否继续操作(Y或N)
charp1[9];//电话号码字符串
jisuan();
printf("欢迎进入电信计费模拟系统\n");
printf("*****************************************************************************\n");
printf("请输入您的号码:
\n");
gets(p1);
menu();
do{
printf("请选择您要进行的操作:
\n");
scanf("%d",&e);
switch(e)
{
case1:
jilu(p1);break;
case2:
xiangxi(p1);break;
case3:
savefile(p1);break;
case4:
check(p1);break;
case0:
exit(0);
default:
printf("\n%d不可用",e);
}
printf("\n是否继续(Y/N)?
\n");
getchar();
f=getchar();
}while(f=='Y'||f=='y');
return0;
}
voidjisuan()//打开文件,并生成“费用详单”文件
{
inti=0,j=0;
intnum1;//num1为来电显示费用
doublet,changtuhf=0.0,shineihf=0.0,sum=0.0;//changtuhf长途话费累加变量,shineihf市内话费累加变量,sum话费总和
FILE*fp1,*fp2,*fp3;
fp1=fopen("D:
\\话单记录.txt","r");
fp2=fopen("D:
\\用户资料.txt","r");
fp3=fopen("D:
\\费用详单.txt","w");
if(!
fp1)
{
printf("filecannotbeopened");
exit(0);
}
if(!
fp2)
{
printf("filecannotbeopened");
exit(0);
}
if(!
fp3)
{
printf("filecannotbeopened");
exit(0);
}
for(i=0;!
feof(fp2);i++)
{
fscanf(fp2,"%s%s%s%s",&yhzl[i].name1,&yhzl[i].name2,&yhzl[i].phone,&yhzl[i].YN);
for(j=0;!
feof(fp1);j++)
{
fscanf(fp1,"%s%s%s%s",&hd[j].number1,&hd[j].number2,&hd[j].qishi,&hd[j].zhongzhi);
if(strcmp(yhzl[i].phone,hd[j].number1)==0)//找出所选号码对应的通话记录
{
if(strcmp(yhzl[i].YN,"Y")==0)//判断是否开通来电显示功能
num1=b;
elsenum1=0;
t=shijian(hd[j].qishi,hd[j].zhongzhi);
if((t-(int)t)>0)t=(int)t+1;
elset=(int)t;
if(hd[j].number2[0]=='0')
changtuhf+=d*t;
else
shineihf+=c*t;
}
}
sum=a+num1+shineihf+changtuhf;
fprintf(fp3,"%-10s%-6s%-10s%-10d%-10d%-15lf%-15lf%-15lf\n",yhzl[i].phone,yhzl[i].name1,yhzl[i].name2,a,num1,shineihf,changtuhf,sum);
rewind(fp1);
changtuhf=0.0,shineihf=0.0,sum=0.0;
}
fclose(fp1);
fclose(fp2);
fclose(fp3);
}
voidmenu()
{
printf("*****************************************************************************\n");
printf("请选择需要的服务:
\n");
printf("*****************************************************************************\n");
printf("1-通话记录显示\n");
printf("2-详细话费\n");
printf("3-保存话费\n");
printf("4-检测通话时长异常\n");
printf("0-退出\n");
printf("*****************************************************************************\n");
}
voidjilu(charphone1[])//利用用户输入的号码进行顺序查找并将找到的客户信息输出
{
inti=0;
FILE*tt;
tt=fopen("D:
\\话单记录.txt","r");
if(!
tt)
{
printf("filecannotbeopened");
exit(0);
}
fscanf(tt,"%s%s%s%s",&hd[i].number1,&hd[i].number2,&hd[i].qishi,&hd[i].zhongzhi);
while(!
feof(tt))
{
if(strcmp(hd[i].number1,phone1)==0)
fprintf(stdout,"%-10s%-10s%-20s%-20s\n",hd[i].number1,hd[i].number2,hd[i].qishi,hd[i].zhongzhi);
i++;
fscanf(tt,"%s%s%s%s",&hd[i].number1,&hd[i].number2,&hd[i].qishi,&hd[i].zhongzhi);
}
fclose(tt);
}
voidxiangxi(charphone1[])//将用户月租费、功能费、市话费、长途费和合计显示在屏幕上
{
inti=0;
FILE*ss;
ss=fopen("D:
\\费用详单.txt","r");
if(!
ss)
{
printf("filecannotbeopened");
exit(0);
}
fscanf(ss,"%s%s%s%d%d%lf%lf%lf",&hfd[i].haoma,&hfd[i].xingming1,&hfd[i].xingming2,&hfd[i].y,&hfd[i].g,&hfd[i].shinei,&hfd[i].changtu,&hfd[i].zonghe);
while(!
feof(ss))
{
if(strcmp(hfd[i].haoma,phone1)==0)
{
printf("用户号码用户姓名月租费功能费市话费长途费合计\n");
printf("%-10s%-6s%-10s%-10d%-10d%-10.3lf%-10.3lf%-10.3lf\n",hfd[i].haoma,hfd[i].xingming1,hfd[i].xingming2,hfd[i].y,hfd[i].g,hfd[i].shinei,hfd[i].changtu,hfd[i].zonghe);
break;
}
else
fscanf(ss,"%s%s%s%d%d%lf%lf%lf",&hfd[i].haoma,&hfd[i].xingming1,&hfd[i].xingming2,&hfd[i].y,&hfd[i].g,&hfd[i].shinei,&hfd[i].changtu,&hfd[i].zonghe);
}
fclose(ss);
}
voidsavefile(charphone1[])//将用户的所有通话记录输出到指定文件中
{inti=0;
FILE*q,*p;
q=fopen("D:
\\话单记录.txt","r");
p=fopen("D:
\\话单保存.txt","w");
if(!
q)
{
printf("filecannotbeopened");
exit(0);
}
if(!
p)
{
printf("filecannotbeopened");
exit(0);
}
fscanf(q,"%s%s%s%s",&hd[i].number1,&hd[i].number2,&hd[i].qishi,&hd[i].zhongzhi);
while(!
feof(q))
{
if(strcmp(hd[i].number1,phone1)==0)
fprintf(p,"%-10s%-10s%-20s%-10s\n",hd[i].number1,hd[i].number2,hd[i].qishi,hd[i].zhongzhi);
i++;
fscanf(q,"%s%s%s%s",&hd[i].number1,&hd[i].number2,&hd[i].qishi,&hd[i].zhongzhi);
}
printf("您的话单已保存于D盘");
fclose(q);
fclose(p);
}
voidcheck(charphone1[])//检查号码通话时长是否大于三天,并显示和保存异常话单
{
inti=0;
doublet;
FILE*p1,*p2;
p1=fopen("D:
\\话单记录.txt","r");
p2=fopen("D:
\\话单异常.txt","w");
if(!
p1)
{
printf("filecannotbeopened");
exit(0);
}
if(!
p2){
printf("filecannotbeopened");
exit(0);
}
fscanf(p1,"%s%s%s%s",&hd[i].number1,&hd[i].number2,&hd[i].qishi,&hd[i].zhongzhi);
while(!
feof(p1))
{
t=shijian(hd[i].qishi,hd[i].zhongzhi);
if(t>4320)
{
fprintf(p2,"%-10s%-10s%-20s%-10s\n",hd[i].number1,hd[i].number2,hd[i].qishi,hd[i].zhongzhi);
if(strcmp(phone1,hd[i].number1)==0)
printf("您的异常通话时长话单为:
\n%-10s%-10s%-20s%-10s\n",hd[i].number1,hd[i].number2,hd[i].qishi,hd[i].zhongzhi);
}
else
{
fscanf(p1,"%s%s%s%s",&hd[i].number1,&hd[i].number2,&hd[i].qishi,&hd[i].zhongzhi);
}
i++;
}
fclose(p1);fclose(p2);
}
doubleshijian(charkt[],charjt[])
{
inttyear,tmonth,tday,thour,tminute,ts;
intkyear,kmonth,year,month;
doublet,t1;
tyear=(jt[0]-kt[0])*1000+(jt[1]-kt[1])*100+(jt[2]-kt[2])*10+(jt[3]-kt[3]);
tmonth=(jt[4]-kt[4])*10+(jt[5]-kt[5]);
tday=(jt[6]-kt[6])*10+(jt[7]-kt[7]);
thour=(jt[8]-kt[8])*10+(jt[9]-kt[9]);
tminute=(jt[10]-kt[10])*10+(jt[11]-kt[11]);
ts=(jt[12]-kt[12])*10+(jt[13]-kt[13]);
kyear=kt[0]*1000+kt[1]*100+kt[2]*10+kt[3];
if(kyear%4==0&&kyear%100!
=0||kyear%400==0)
year=tyear*527040;
else
year=tyear*525600;
kmonth=(kt[6]-48)*10+(kt[7]-48);
switch(tmonth)
{
case-11:
if(kyear%4==0&&kyear%100!
=0||kyear%400==0)month=-335;elsemonth=-334;break;
case0:
month=0;break;
case1:
month=kmonth;break;
default:
break;
}
t1=year+month*1440+tday*1440+thour*60+tminute+ts/60.0;
t=t1;
returnt;//返回值:
单次通话时间
}
五、测试数据及其结果分析
(1)主菜单:
图6
(2)主要操作
图7
(3)主要功能
图8
(4)输出的所有话单记录文件
图9
(5)输出账单文件
图10
(6)退出系统
输入0或当出现“是否继续
图11
结果分析:
1)在输入菜单选项时如果输入的内容不是0-4之间的数字,而是其他数字,系统将显示“不可用,是否继续
2)当结束某项操作时,系统会自动询问用户是否继续查询。
3)当输入文件时,如文件事先未建立,系统将提示filecannotbeopened
4)当输出文件时,如文件事先未建立,系统将自行建立。
5)当选择“检查通话时长异常”选项时,系统会提示如果异常将会产生的结果,如果有异常,系统将自动输出异常通话记录。
六、调试过程中的问题
1)输出格式的控制问题:
选择选项二中显示详细话单是只能显示用户名,而不能显示姓,输出的号码也不对应。
原因是%s无法读入带有空格的字符串,解决方法是将用户姓和名分别存在两个字符串中分别读取和输出。
2)在话单记录末尾添加一条记录时,原有记录减少一条,删除添加的记录,原有记录无法恢复。
原因是在读取最后一条前系统已跳出循环体,解决方法是在while循环外增加一条fprintf语句。
3)保存后在下次运行时出错问题:
在保存信息时,应在每个信息之间加空格来保存,否则在文件下次使用时读取就会没有分界点。
4)在判断循环结束时因中间有i++的操作而使再循环时指针溢出问题:
因为在循环体中有i++的操作,所以可能出现指针已经指尾而在再次循环时有后移而出错的问题,这里可以通过将while改成do-while来使程序通过。
七、课程设计总结
这次的程序设计实习是一次真正的动手实践过程。
从最初的分析课题到设计程序,自己发现问题、讨论并解决问题。
让我对未来可能的工作环境有了些许初步的认知,并对所学知识进行了检验,其中不仅对C语言的操作有了进一步的掌握还了解到了程序设计的书写风格及其注释的格式。
并且锻炼了团队合作能力、增强了责任意识。
对于这个课题来说,重点在对函数的调用,当然还有不少文件的读写问题。
但难点还是函数内部的算法与复杂字符串结构体的结合,其中不乏有需要变通之处。
例如,显示详细话单是只能显示用户名,而不能显示姓,输出的号码也不对应。
原因是%s无法读入带有空格的字符串,解决方法是将用户姓和名分别存在两个字符串中分别读取和输出。
另外在话单记录末尾添加一条记录时,原有记录减少一条,删除添加的记录,原有记录无法恢复。
原因是在读取最后一条前系统已跳出循环体,解决方法是在while循环外增加一条fprintf语句。
在这次设计中对于文件的调用十分频繁,此时就需要注意对文件的操作权限,如果操作权限不足,将导致程序运行出错。
另外一点要说的就是这个程序用了很多的循环,因此对于循环的控制要十分小心,有时while和do-while的区别也是十分重要的。
这个程序的功能虽然不算复杂,程序本身也不够完备,但想用基础的c语言编好它也并非易事,总的来说一周的努力还是换来了一些成果的!
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 电信 计费 模拟 实现 语言