《带括号的表达式求值》课程设计报告.docx
- 文档编号:6954631
- 上传时间:2023-01-13
- 格式:DOCX
- 页数:23
- 大小:103.05KB
《带括号的表达式求值》课程设计报告.docx
《《带括号的表达式求值》课程设计报告.docx》由会员分享,可在线阅读,更多相关《《带括号的表达式求值》课程设计报告.docx(23页珍藏版)》请在冰豆网上搜索。
《带括号的表达式求值》课程设计报告
《数据结构与算法分析》课程设计报告
课题名称:
带括号的算术表达式求值
课题负责人名(学号):
0743111298
同组成员名单(角色):
戴维
指导教师:
评阅成绩:
评阅意见:
提交报告时间:
200年月日
带括号的算术表达式求值
软件工程专业
学生戴维指导老师朱宏
一、实验一:
带括号的算术表达式求值
二、实验的目的和要求:
1.采用算符优先数算法,能正确求值表达式;
2.熟练掌握栈的应用;
3.熟练掌握计算机系统的基本操作方法,了解如何编辑、编译、链接和运行一个C++程序;
4.上机调试程序,掌握查错、排错使程序能正确运行。
三、实验的环境:
1.硬件环境:
Intel(R)Celeron(R)MCPU
520@1.60GHz
1.60GHz,0.99Gb内存
2.软件环环境:
操作系统:
MicrosoftWindowsXP
Professinal版本2002
编译系统版本:
MicroSoftVisualC++6.0
包括操作系统,编译系统的版本的特点,编辑软件特点等。
四、算法描述:
对于带有括号的算术表达式有以下的运算法则:
1.先乘方,再乘除,最后加减。
2.同级运算从左到右。
3.先括号内,再括号外。
而运算符号的优先级别如下表所示:
运算符
=
()
+-
*/%
^
优先级
1
2
3
4
5
具体实现如下:
1.先建立两个堆栈,一个是操作符堆栈,一个为操作数堆栈。
并且将这两个堆栈先清空,然后在操作符号堆栈当中放入一个“=”,以便在后面方便判断表达式是否结束。
2.从输入流当中读取一个字符,循环执行下面的操作:
去出操作符号堆栈的栈顶元素,如果栈顶元素是不是“=”并且如果当前的字符也是“=”的时候,那么表示表达式已经结束了,当前操作数堆栈的栈顶元素就是表达式的值。
如果当前字符不是操作符,就将当前字符放回到输入流当中,读取操作数,并且将操作数加入到操作数堆栈当中,继续读入下一个字符。
如果当前字符是操作符就进行下面的操作:
.如果当前字符不是“+”或者“-”,则在当前字符前面加一个“0”放入到操作数栈当中。
如果当前字符和操作符的栈顶元素不匹配,例如当前字符是“(”,而栈顶字符“)”,显示错误信息。
如果操作符栈的栈顶元素是“(”并且当前字符是“)”,则从操作符栈当中取出,去掉括号,然后继续读入下面的字符。
如果当前字符是“(”,或者操作符栈顶元素的优先级别比当前字符低,则将当前字符放入到操作符栈当中。
继续读入下一个字符。
如果操作符栈顶元素的优先级别等于或者大于当前字符的优先级别,那么就取出操作数栈的RIGHT和LEFT元素,从操作符栈当中取出OP,然后进行操作(LEFT)OP(RIGHT),结果进入到操作数栈当中.
五、源程序清单:
Calculator.h:
template
classCalculator
{
private:
Stack
Stack
boolGetTwoOperands(double&left,double&right);
//从操作数栈当中取出最上面的两个数字
boolDoOperator(charop);
//runthefunction"leftopright"
boolIsOperator(charch);
//判断传入的字符是不是一个操作符
voidGetChar(char&ch);
//从输入流当中读入一个字符
intisp(charop);//堆栈外优先数
inticp(charop);//堆栈内优先数
public:
voidRun();//运行函数
};
template
voidCalculator
:
Run()
{
optr.clear();//将操作符栈的所有元素清空
opnd.clear();//将操作数栈的所有元素清空
optr.push('=');//先在操作符栈中传入一个‘=’号,为了能够更好的判断运算是否已经
结束
//当从外面的读入的字符是‘=’并且栈顶符号也是‘=’时,运算结束
charch;//临时的一个字符
charpriorChar;//前一个字符
charoptrTop;//操作符栈的栈顶元素
Data_elementoperand;//需要被操作的操作数
charop='0';//定义一个操作数为‘0’,便于操作小数的运算
GetChar(ch);//得到一个字符
optr.top(optrTop);//得到操作符栈的栈顶元素
if(optr.top(optrTop)==underflow)
//如果操作符号栈为空,抛出错误信息
{
cout<<"表达式有错!
"< return; } while(optrTop! ='='||ch! ='=') //通过判断当前的字符和栈顶的字符其中一个不为“=”的时候, //表示现在运算还没有结束,所以进行下面的操作 { if(isdigit(ch)||ch=='.') //如果当先的字符是一个数字或者当前字符是小数点,那么把该字符放回到 输入流当中, //再把该操作数读入,并且放到操作数栈当中去,把前一个字符赋为0,然后 再继续读入字符 { cin.putback(ch); cin>>operand; opnd.push(operand); priorChar='0'; GetChar(ch); } elseif(! IsOperator(ch)) //除了数字以外应该只有操作符,现在进行判断,如果不是数字,不是小数 点, //也不是操作符号,说明输入有错误,打印错误消息,再不断的读入字符, 直到读到表达式结束 { cout<<"表达式中出现非法字符! "< while(cin>>ch,ch! ='='); return; } else { if((priorChar=='='||priorChar=='(')&&(ch=='+'||ch=='-'))opnd.push (0); if(isp(optrTop) //如果操作符栈顶元素的优先级别小于当前操作符号的优先级别就 把当前的 //字符放到操作符栈当中,将当前字符赋值给前一个字符,再读入下一 个字符 { optr.push(ch); priorChar=ch; GetChar(ch); } elseif(isp(optrTop)>icp(ch)) //如果操作符栈顶元素的优先级别大于当前操作符号, //删除操作符栈顶元素,在判断OP是不是操作符号,如果不是就返回 { optr.top(op);optr.pop(); if(! DoOperator(op))return; } elseif(isp(optrTop)==icp(ch)&&ch==')') //如果栈内操作符和栈外操作符的优先级别一样的,并且当前的字 符为等号的时候 { optr.pop(); priorChar=')'; GetChar(ch); }; } if(optr.top(optrTop)==underflow) //如果操作符栈为空的话,输出错误消息 { cout<<"表达式有错! "< return; }; } if(opnd.top(operand)==underflow||optr.pop()==underflow) //如果操作数字栈为空或者是操作符号在删除了栈顶元素厚为空,输出错误信息 { cout<<"表达式有错! "< return; } else //删除操作数栈的栈顶元素,如果再删除操作符栈栈顶元素成功删除或者能够成功删除 //操作数栈的栈顶元素,输出错误信息 { opnd.pop(); if(opnd.pop()==success||optr.pop()==success) { cout<<"表达式有错! "< return; } cout< return; } }; template intCalculator : isp(charop) //栈外操作符的优先级判断 { intresult; switch(op) { case'=': result=0; break; case'(': result=1; break; case'^': result=7; break; case'*': case'/': case'%': result=5; break; case'+': case'-': result=3; break; case')': result=8; } returnresult; }; template //操作符栈内优先级的判断 intCalculator : icp(charop) { intresult; switch(op) { case'=': result=0; break; case'(': result=8; break; case'^': result=6; break; case'*': case'/': case'%': result=4; break; case'+': case'-': result=2; break; case')': result=1; } returnresult; }; template boolCalculator : GetTwoOperands(double&x,double&y) //从操作数栈当中得到两个数字,如果操作数字栈或者操作符栈的元素少于两个的时候输出错误信息 { if(opnd.empty()) { cout<<"表达式有错! "< returnfalse; } opnd.top(y);opnd.pop(); if(opnd.empty()) { cout<<"表达式有错! "< returnfalse; } opnd.top(x);opnd.pop(); returntrue; }; template boolCalculator : DoOperator(charop) //判断符号,进行相应的操作 { Data_elementx,y; boolresult=GetTwoOperands(x,y); if(result==true) { switch(op) { case'+': opnd.push(x+y); break; case'-': opnd.push(x-y); break; case'*': opnd.push(x*y); break; case'/': if(y==0) { cout<<"除数为零! "< returnfalse; } opnd.push(x/y); break; case'%': if((long)y==0) { cout<<"除数为零! "< returnfalse; } opnd.push((long)x%(long)y); break; case'^': opnd.push(pow(x,y)); } returntrue; } elsereturnfalse; }; template voidCalculator : GetChar(char&ch) //从输入流当中读入字符 { cin>>ch; while(ch==''||ch=='\n') cin>>ch; }; template boolCalculator : IsOperator(charch) //判断输入的字符是不是操作符 { if(ch=='='||ch=='('||ch=='^'||ch=='*'|| ch=='/'||ch=='%'||ch=='+'||ch=='-'||ch==')') returntrue; else returnfalse; }; LK_STACK.h: template structNode{ Node_entryentry;//定义一个结点元素 Node Node();//无参数构造函数 Node(Node_entryitem,Node }; template classStack{ public: Stack();//无参构造函数 boolempty()const;//判断堆栈是不是为空 Error_codepush(constStack_entry&item);//往堆栈当中传入元素 Error_codepop();//删除堆栈的栈顶元素 Error_codetop(Stack_entry&item)const;//得到堆栈的栈顶元素 voidclear();//清空堆栈的所有元素 ~Stack();//析构函数 Stack(constStack voidoperator=(constStack protected: Node }; template Node : Node()//构造函数 { next=NULL; } template Node : Node(Node_entryitem,Node //含参数构造函数 { entry=item; next=add_on; } template Stack : Stack() //堆栈的构造函数 { top_node=NULL; } template boolStack : empty()const //判断堆栈是不是为空 { if(top_node==NULL) returntrue; else returnfalse; } template Error_codeStack : push(constStack_entry&item) //往堆栈中添加元素 { Node if(new_top==NULL)returnoverflow; top_node=new_top; returnsuccess; } template Error_codeStack : pop() //删除堆栈的栈顶元素 { Node if(top_node==NULL)returnunderflow; top_node=old_top->next; deleteold_top; returnsuccess; } template Error_codeStack : top(Stack_entry&item)const //得到堆栈的栈顶元素 { Error_coderesult; if(empty()) returnunderflow; else{ item=top_node->entry; returnsuccess; } } template voidStack : clear() //清空整个堆栈 { while(! empty()) pop(); } template Stack : ~Stack() //析构函数 { clear(); } Utility.h: #include #include #include #include #include #include #include #include enumError_code{success,fail,underflow,overflow}; //enumbool{false,true}; Calculator.cpp: #include"Utility.h" #include"LK_STACK.H" #include"Calculator.h" voidmain() { Calculator chariscontinue='Y'; while(iscontinue=='Y') { cout<<"输入表达式(以等号“=”结束): "< s.Run(); cout<<"是否继续(Y/N)? "; cin>>iscontinue; iscontinue=toupper(iscontinue); } } 六、运行结果: 1.一般的整数操作: 3+4*5/2=13 2.小数的计算: 4.25*1+3.25/5=4.9 3.乘方操作: 4^4=256 4.取模运算: 7%3=1 5.负数运算: (-5)*6/2=15 6.分母为零的检验: 7.一次程序结束后继续下一次: 8.一次程序结束后退出程序: 七、实验运行情况分析(包括算法、运行结果、运行环境等问题的讨论)。 (一)算法分析: 对于带有括号的算术表达式有以下的运算法则: 1.先乘方,再乘除,最后加减。 2.同级运算从左到右。 3.先括号内,再括号外。 而运算符号的优先级别如下表所示: 运算符 = () +- */% ^ 优先级 1 2 3 4 5 具体实现如下: 1.先建立两个堆栈,一个是操作符堆栈,一个为操作数堆栈。 并且将这两个堆栈先清空,然后在操作符号堆栈当中放入一个“=”,以便在后面方便判断表达式是否结束。 2.从输入流当中读取一个字符,循环执行下面的操作: 去出操作符号堆栈的栈顶元素,如果栈顶元素是不是“=”并且如果当前的字符也是“=”的时候,那么表示表达式已经结束了,当前操作数堆栈的栈顶元素就是表达式的值。 如果当前字符不是操作符,就将当前字符放回到输入流当中,读取操作数,并且将操作数加入到操作数堆栈当中,继续读入下一个字符。 如果当前字符是操作符就进行下面的操作: .如果当前字符不是“+”或者“-”,则在当前字符前面加一个“0”放入到操作数栈当中。 如果当前字符和操作符的栈顶元素不匹配,例如当前字符是“(”,而栈顶字符“)”,显示错误信息。 如果操作符栈的栈顶元素是“(”并且当前字符是“)”,则从操作符栈当中取出,去掉括号,然后继续读入下面的字符。 如果当前字符是“(”,或者操作符栈顶元素的优先级别比当前字符低,则将当前字符放入到操作符栈当中。 继续读入下一个字符。 如果操作符栈顶元素的优先级别等于或者大于当前字符的优先级别,那么就取出操作数栈的RIGHT和LEFT元素,从操作符栈当中取出OP,然后进行操作(LEF
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 带括号的表达式求值 括号 表达式 求值 课程设计 报告