利用栈求表达式的值.docx
- 文档编号:24679474
- 上传时间:2023-05-31
- 格式:DOCX
- 页数:41
- 大小:485.13KB
利用栈求表达式的值.docx
《利用栈求表达式的值.docx》由会员分享,可在线阅读,更多相关《利用栈求表达式的值.docx(41页珍藏版)》请在冰豆网上搜索。
利用栈求表达式的值
软件综合课程设计
利用栈求表达式的值
二〇一四年六月
《课程设计》
一、利用栈求表达式的值
1.问题陈述
利用栈求表达式的值,可供小学生作业,并能给出分数。
(限1人完成)
要求:
建立试题库文件,随机产生n个题目;题目涉及加减乘除,带括弧的混合运算;随时可以退出;保留历史分数,能回顾历史,给出与历史分数比较后的评价
2.程序代码
#include
#include
#include
#include
#include
#include
#defineMAX_LEN1024
#defineEXP_LEN4
constchar*OPERATOR="+-*/";
/*S1保存数字或运算结果,S2保存操作符,Exp为输入的表达式*T1为栈S1的顶指针,T2为栈S2的顶指
针,p为扫描Exp的位置*/
charS2[MAX_LEN],Exp[MAX_LEN*2];
intS1[MAX_LEN],T1,T2,p;
/*检查生成的表达式是否合理*/
intisCorrect;
/*number为随机生成的表达式的操作数,oper为运算符,bracket为括号数组(0表示没有括号,-1表示左
括号,1表示右括号)*/
intnumber[EXP_LEN],bracket[EXP_LEN];
charoper[EXP_LEN-1];
/*用户答案*/
charreply[MAX_LEN*2];/*题目数量,默认为5道题*/
intN=5;/*获得运算符的优先级*/
intGetPriority(charc){
if(c=='+'||c=='-')
return1;
else
return2;
}
/*将字符转换成int*/
intGetNum(){
intr=0;
while(isdigit(Exp[p]))
{
r=r*10+Exp[p]-'0';
p=p+1;
}
returnr;
}
/*从栈顶取出两个数字,进行op对应的操作*/
voidCalc(charop){
inta=S1[T1-2],b=S1[T1-1];
if(op=='+')
a+=b;
elseif(op=='-')
{a-=b;
/*如果中间结果出现负数,认为不合法*/
if(a<0)
isCorrect=0;
}
elseif(op=='*')
a*=b;
else{
/*如果中间结果出现无法整除或除数为0,认为不合法*/
if(b==0||a%b!
=0)
isCorrect=0;
if(b!
=0)
a/=b;
}/*将计算结果压入S1操作数栈中,并更新栈顶指针*/
S1[T1-2]=a;
T1=T1-1;
}
/*操作符入栈*/
voidPush(charop){
/*优先计算括号内的表达式*/
if(op==')'){
while(S2[T2-1]!
='(')
{
T2=T2-1;
Calc(S2[T2]);
}
T2=T2-1;
}
elseif(op=='(')
/*左括号直接入栈*/
{
S2[T2]=op;
T2=T2+1;
}
else
{
/*先计算优先级高的表达式*/
while(T2>0&&S2[T2-1]!
='('&&GetPriority(S2[T2-1])>=GetPriority(op))
{T2=T2-1;
Calc(S2[T2]);
}
/*将op压入S2操作符栈中,并更新栈顶指针*/
S2[T2]=op;
T2=T2+1;
}
}/*计算表达式的值*/
intProcessExp()
{/*清空栈,将扫描指针复位*/
T1=T2=p=0;
while(Exp[p]!
='\0')
{/*如果是数值,入S1栈*/
if(isdigit(Exp[p]))
{
S1[T1]=GetNum();
T1=T1+1;
--p;
}
else/*反之是运算符,入S2栈*/
{
Push(Exp[p]);
}p=p+1;
}/*取出S2中剩余操作符,进行运算*/
while(T2>0)
{
T2=T2-1;
Calc(S2[T2]);
}
returnS1[0];
}/*打印欢迎*/
voidWelcome(){
printf("
***************************************************\n");
printf("*欢迎进入四则运算表达式测试中心*\n");
printf("*系统为您随机生成了%d道题,请您开始答题*\n",N);printf("*(总分%d分,每题10分)*\n",N*10);
printf("*输入任意字母退出系统*\n");
printf("***************************************************\n");
printf("\n");
printf("\n");
}
/*生成合法的表达式(中间结果没有负数,分数和小数等)*/
intGenerateExp(){
inti,j,k,w,ret,digit[16];
/*一直循环直到随机到一个合法的表达式*/
while(true){
isCorrect=1;/*随机操作数*/
for(i=0;i number[i]=rand()%100+1;/*随机操作符*/ for(i=0;i oper[i]=OPERATOR[rand()%4]; j=-1;/*随机括号的位置*/ memset(bracket,0,sizeof(bracket)); while(true){ i=j+1; if(EXP_LEN-1-i<=0) break; j=rand()%(EXP_LEN-1-i)+i; bracket[j]=-1; i=j+1; j=rand()%(EXP_LEN-i)+i; bracket[j]=1; }/*构造生成的表达式*/ memset(Exp,0,sizeof(Exp)); j=0; for(i=0;i { if(bracket[i]==-1) { Exp[j]='('; j=j+1; } k=0; while(number[i]>0) { digit[k]=number[i]%10; number[i]/=10; k++; } for(w=k-1;w>=0;w--) { Exp[j]=digit[w]+'0'; j=j+1; } if(bracket[i]==1) { Exp[j]=')'; j=j+1; } Exp[j]=oper[i]; j++;}/*计算表达式的结果*/ ret=ProcessExp();/*如果合法,退出*/ if(isCorrect) break; }returnret; } /*结合学生的历史成绩进行评估*/ voidEvaluate(inttotalNum,intcorrectNum){ /*打开历史数据文件*/ FILE*file=fopen("history.txt","at+"); doublecurAccurate=correctNum*100.0/totalNum,lastAccurate,avgAccurate=0; intlinebreak=1,improve=0,hTotalNum,hCorrectNum; /*打印本次测试结果(总题数,答对数,答错数,总分以及正确率)*/ printf("您共回答了%d道题,答对%d道题,答错%d道题! \n",totalNum,correctNum,totalNum-correctNum); printf("您的总得分为%d分,正确率为%.2lf%%\n",correctNum*10,curAccurate); /*文件打开失败*/ if(file==NULL) { printf("历史文件读入有误! \n"); }else { /*读取历史数据,并计算历史平均正确率,和最近的一次正确率*/ printf("\n历史数据评估: \n"); while(fscanf(file,"%d%d",&hTotalNum,&hCorrectNum)! =EOF) { printf("%d道题答对%d道",hTotalNum,hCorrectNum); if(linebreak%5==0) printf("\n"); linebreak++; lastAccurate=hCorrectNum*100.0/hTotalNum; avgAccurate+=lastAccurate; } printf("\n\n"); /*若有过1次及以上的历史测试*/ if(linebreak>1) { /*打印对比本次正确率和历史平均正确率,上一次正确率之间的关系*/ avgAccurate/=linebreak-1; printf("您的平均正确率为%.2lf%%,上一次的正确率为%.2lf%%\n",avgAccurate,lastAccurate); printf("本次测试您的正确率为%.2lf%%,不%s于平均正确率! \n\n",curAccurate,curAccurate>lastAccurate? "低": "高"); /*计算此次正确率相比上一次正确率的增幅*/ if(fabs(lastAccurate)>1e-7) improve=(curAccurate-lastAccurate)*100/lastAccurate; else improve=curAccurate; /*若没有增幅*/ if(improve==0) printf("相比上一次测试,您的正确率没有变化! \n"); else { /*若是负增幅,则为退步,否则为进步(根据增幅的大小,打印不同的程度"略微","较大"等)*/ printf("相比上一次测试,你有了"); if(abs(improve)<20) printf("略微的"); elseif(abs(improve)<40) printf("较大的"); elseif(abs(improve)<60) printf("很大的"); else printf("极大的"); if(improve<0) printf("退步! "); else printf("进步! "); printf("\n"); } } else { printf("对不起,尚无历史数据! \n"); } /*将此次测试数据写入历史文件*/ fprintf(file,"%d%d\n",totalNum,correctNum); } fclose(file);} /*总的处理流程*/ voidmain(){ inti,j,ans=0,rep=0,correctNum=0,totalNum; charc;srand(time(NULL)); /*随机总题数*/ totalNum=N=rand()%10+1; /*打印欢迎信息*/ Welcome(); /*随机N道题目给学生回答*/ for(i=1;i<=N;i++) { printf("第%d题: ",i); ans=GenerateExp(); printf("%s=\n",Exp); printf("答案: "); /*忽略用户无意输入的空格和回车*/ while((c=getchar())=='\n'||c==''); /*将最后的合法字符放回输入缓冲区*/ ungetc(c,stdin); /*读取用户答案*/ gets(reply); rep=0; /*将用户的答案转化为数字*/ for(j=0;reply[j];j++) {if(! isdigit(reply[j])) break;rep=rep*10+reply[j]-'0'; } /*若发现用户输入中有字母,退出*/ if(reply[j]) break; /*与标准答案不一致*/ if(reply[j]||rep! =ans) printf("很抱歉,回答错误! \n"); elseif(rep==ans)/*回答正确*/ { printf("恭喜您,回答正确! \n"); /*将回答正确的题数加上1*/ correctNum++; }printf("\n"); } /*若没有回答完所有题目则退出,更新回答的总题数*/ if(i<=N) totalNum=i; /*结合历史数据进行评估*/ Evaluate(totalNum,correctNum); getchar();}intmain(intargs,char*argv[]) { main(); return0; } 3.运行结果 登路界面如图3-1所示,直接系统给出测试题目,但是题目数不一定,有时候10题,有时候5题等等,时间关系,没有仔细考虑实际问题,小学生做超过5位数的乘法实在太难了,连本人都是用计算机算的,汗颜,下次一定要充分考虑实际问题,作出正确的判断。 图3-1登录界面 测试题目如图3-2所示,有加减乘除和带括号运算都是系统随机抽取的。 图3-2测试界面 评价界面如图3-3所示,学生测试完以后,系统及时进行评价 图3-3 回顾历史,给出评价如图3-4所示,根据前几次的题目,给出这次测试的评价。 图3-4回顾历史 退出如图3-5所示,按下任意不是数字的字符便可以退出 图3-5退出界面 4.设计体会与总结 我的课程设计的题目是利用栈求表达式的值,刚开始做这个程序的时候,感到完全无从下手,甚至让我觉得完成这次程序设计根本是不可能的,于是开始查阅各种资料及参考文献,之后便开始手写程序,写完程序有很多问题,经常出现错误,但通过同学间的帮助最终基本解决问题。 在本课程设计中,我明白了理论与实际相结合的重要性,并提高了自己组织数据及编写程序的能力。 这次课程设计同样提高了我的综合运用所学知识的能力。 并对VC有了更深入的了解。 上机实习时对学生全面综合素质进行训练的一种最基本的方法,是与课堂听讲、自学和练习相辅相成、必不可少的一个教学环节。 上机实习一方面能使书本上的知识变“活”,起到深化理解和灵活掌握教学内容的目的: 另一方面,上机实习是对学生软件设计的综合能力的训练。 通过这段时间的课程设计,我认识到数据结构是一梦比较难的课程。 需要多花时间上机练习。 这次的课程训练培养了我实际分析问题、编程和动手能力,使我掌握了程序设计的基本能力。 二、活期储蓄帐目管理 1.问题陈述 活期储蓄处理中,储户开户、销户、存入、支出活动频繁,系统设计要求: 1)能比较迅速地找到储户的帐户,以实现存款、取款记账; 2)能比较简单,迅速地实现插入和删除,以实现开户和销户的需要。 2.需求分析 随着社会经济的发展,信息化程度的不断深入,传统的银行工作模式已经不能方便快捷的服务于大众。 现如今代理业务不断发展,业务品种越来越多,各项业务做法互有差异,这就对银行的电子化水平和相应的管理水平提出了更高的要求。 如何利用电子化的手段构建一个高效统一的、通用灵活的系统来管理各种各样的业务,是每个商业银行所要研究的课题。 支持决策系统的,需要在数据库的基础上,进行联机分析处理,每次处理的数据量大,响应时间长。 特别是银行每天要处理大量的存取款事件,做好存取款是银行工作重要的环节,然而要有效处理必须要有良好的程序和数据管理系统来建立一个良好的软件系统来实现快速、有效、准确、安全的处理银行事物。 主要用于银行的储蓄卡管理系统,它可以帮助我们有效、准确、并且高效实现的完成存取事件。 此系统操作方便效率、安全性高,只要客户开户并设定好密码就可以轻松的实现存取款。 3.概要设计 系统模块结构图 功能说明: 系统实现的主要有储蓄卡开户管理、存取款管理、用户查询历史数据显示、注销等功能。 储蓄卡开户管理模块: 卡号、姓名、开户金额、身份证号、地址、电话、密码、确认密码和保存组成。 (开户金额必须是数字,密码和确认密码必须一样是六位数字) 注销模块: 注销多余 通过该银行账户管理系统地运行,使办公人员可以轻松快捷的完成对账户管理的任务,提高账目管理效率,使银行的账目管理工作系统化、规范化、自动化。 该银行帐目管理信息系统,优点是设计过程思路清晰、模块划分简洁,设计各阶段分工明确。 经过实践证明,该划分是合理的,极大得提高了本系统的实现。 4.详细设计 登录页面 输入卡号和密码,根据用户输入的卡号和密码,到后台文件查询,若正确则登录成功,并保存卡好信息已备后用。 若卡号存在和密码不匹配或无该卡号已经注销,提示该卡号已存在或已注销,保持界面三次不变等待用户的重新输入。 主界面页面 主要导航栏有: 欢迎使用储蓄卡管理(存款、取款、修改密码、转账功能、注销退出) 储蓄卡开户页面 提供开户界面,由用户输入新储蓄卡的所有信息,将该信息保存到文件中,并将开户金额作为该卡的第一次存款记录存人文件。 存钱页面 从登录界面得到卡号,并提供数据输入界面,等待用户的输入存款金额。 从后台数据库中找到该用户余额记录,修改余额,并将该存款事件的相应信息写人数据库,同时将存钱的金额显示在页面上。 取款页面 从登录界面得到卡号,并提供数据输入界面,等待用户输入取款金额,如果取款金额大于该用户卡上的余额则不能取款,或者将新的余额写人文件,并将本次取款事件写入文件同时将取钱的金额显示在页面上,。 注销页面 5.程序代码 #include #include #include usingnamespacestd; classconsumer; classYH//银行类 { public: voidset_account();//银行开户功能 voiddel_account();//注销账户功能 voidtransfer(int);//转账功能 voidenter_account();//进入用户个人信息功能 voidaddmoney(int,float);//存款功能 voidexitYH();//退出系统 voidfunctionshow(); voidsave(); voidload();//功能界面 protected: consumer*account[20]; staticintacnum;//账户数 }; classconsumer: publicYH//用户类,继承银行类的属性 { public: friendclassYH; consumer(intid,stringName,intNumber,doubleIN,stringCompany,stringAddress,stringPassWord,floatm) { ID=id;name=Name;number=Number;in=IN;company=Company;address=Address;money=m;passwd=PassWord; } consumer(){ID=0;name='0';number=0;in=0;company='0';address='0';money=0;passwd='0';} intget_id(){returnID;} voidsavemoney();//取钱 stringget_passwd(){returnpasswd;}//取得密码 voiddisplay(); voidfetchmoney();//取钱 voidchange_passwd(); voidadd_money(float);//计算余额 voiddec_money(float);//计算余额 floatget_money();//卡卡转帐 private: intID;//开户帐号 stringpasswd;//用户密码 stringname;//用户姓名 floatmoney;//开户金额 intnumber;stringcompany;st
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 利用 表达式