中缀表达式简单算术表达式的C++求解.docx
《中缀表达式简单算术表达式的C++求解.docx》由会员分享,可在线阅读,更多相关《中缀表达式简单算术表达式的C++求解.docx(21页珍藏版)》请在冰豆网上搜索。
中缀表达式简单算术表达式的C++求解
计算机软件技术基础作业一说明
中缀表达式简单算术表达式的求解
1、源程序见包内,经检测可以在MSVC++6.0中正确运行,可以输入800个符号内任意长度的中缀表达式,并拥有了判错功能;
2、本题通过构造堆栈实现中缀表达式的运算;
3、算法思路:
用模板实现的链式结构堆栈类并且实现类模板成员函数,专门定义算法函数charPrecede(charch1,charch2)进行运算,判别函数intOperator(charch)判别运算符号是否正确,。
运算时根据优先级的大小进行:
相等则消去括号;下一个大则压入下一个符号;前面大则先将前面数字算好,再将答案压入数字栈中。
最后将判错功能的算法加入程序中。
4、数据结构设计说明
本程序使用了堆栈的方法,同时采用了数组形式作为数据结构。
5、程序流程说明
6、程序运行的验证过程
(1)正常运行
(2)错误一
(3)错误二
(4)错误三
(5)错误四
(6)错误五
(7)错误六
(8)错误八
7、效果分析:
将数据压入一个堆栈中,分别读取数字符和运算符,中缀表达式由键盘输入,以回车键结束。
如:
3*((4+6)-(5-2)^3)。
由于C++不能读取’\n’,所以该题目只能在读取到’\0’时算到最终结果。
程序给出算术表达式的精确结果,同时给出错误之处!
比如中缀表达式中不能包含多余的空格;中缀表达式中的运算数由{0,1,…,8,9}中的单个数字组成;中缀表达式中只包含5种2目运算符:
+,-,*,/,^及两种优先级运算符“(”和“)”等等。
8、原创内容及体会
刚刚编写程序时,我按照老师课件进行。
但是遇到了不可解决的麻烦,其源程序见下:
(请老师指点,邮箱:
****************)
#include
#include
#include
#include
usingnamespacestd;
template
voidinitStack(T*s,intm,int*top)
{
s=newT(m);//动态申请容量为m的存储空间
*top=0;//栈顶指针
return;//当前分配的栈空间
}
template
voidpush(T*s,intm,int*top,Tx)
{
if(*top==m)
{cout<<"Stackoverflow!
"<*top=*top+1;//序号指针递增
s[*top-1]=x;//入栈
return;
}
template
Tpop(T*s,intm,int*top)
{
Ty;
if(*top==0)
{cout<<"Stackunderflow!
"<y=s[*top-1];//退栈
*top=*top-1;//序号指针递减
return(y);//返回栈顶元素
}
intOperate(inta,chare,intb)//运算操作
{
intc;
switch(e)
{
case'+':
{c=a+b;break;}
case'-':
{c=a-b;break;}
case'*':
{c=a*b;break;}
case'/':
{c=a/b;break;}
case'^':
{c=pow(a,b);break;}
default:
printf("error\n");
}
returnc;
}
charPrecede(charch1,charch2)
{
charch;
switch(ch1)
{
case'+':
case'-':
{
switch(ch2)
{
case'+':
case'-':
case')':
case'\n':
ch='>';
break;
case'*':
case'/':
case'^':
case'(':
ch='<';break;
}
break;
}
case'*':
case'/':
{
if(ch2=='('||ch2=='^')
ch='<';
else
ch='>';
break;
}
case'^':
{
if(ch2=='(')
ch='<';
else
ch='>';
break;
}
case'(':
{
if(ch2==')')
ch='=';
else
ch='<';
break;
}
case')':
{
ch='>';
break;
}
case'\n':
{
if(ch2=='\n')
ch='=';
else
ch='<';
break;
}
}
return(ch);
}
template
intEvaluateExpression()
{
charc,theta;inta,b,answer;T:
OPTR,OPND;
initStack(OPTR);push(OPTR,'\n');
initStack(OPND);c=getchar();
while(c!
='\n'||GetTop(OPTR)!
='\n'){//边输入边处理
if(!
In(c,OP)){push(OPND,c);c=getchar();}
//不是运算符则进栈,In(c,OP)判断c是否是运算符
else
switch(Precede(GetTop(OPTR),c))
{
case<:
//新输入的算符c优先级高,c进栈
push(OPTR,c);c=getchar();break;
case=:
//脱括号并接收下一字符
pop(OPTR,x);c=getchar();break;
case>:
//新输入的算符c优先级低(栈顶算符优先级高)
//出栈并将运算结果入栈OPND
pop(OPTR,theta);
pop(OPND,b);Pop(OPND,a);
push(OPND,Operate(a,theta,b));
break;
}//switch
}//while
answer=GetTop(OPND);
cout<return0;
}
template
intmain()
{
EvaluateExpression();
return0;
}
此程序运行过程中,编译没错,可一到连接就出现这个问题:
1unresolvedexternals!
再三思考,我放弃了这个方案,通过XX搜索,我找到一个以#结束,不能乘方运算,没有详细错误提示的程序,其思路与老师的方案大致相同,只不过采用了数组的形式,不过都对中缀表达式的长度没有确定的要求。
经过一整天的编辑,我终于完成并调试成功了这个程序,心里充满了成功的喜悦感!
以下是我的最终程序(与软件1.cpp内容相同):
#include"iostream.h"
#include"stdlib.h"
#include"math.h"
#include"time.h"
#defineTRUE1
#defineFALSE0
#defineERROR-1
typedefintStatus;
//用模板实现的链式结构堆栈类
template
classstack{
private:
structlink{
Tdata;//结点数据域
link*next;//下一结点指针
link(TData,link*Next){//结构体构造函数
data=Data;
next=Next;
}
}*head;//堆栈顶指针
public:
stack();//构造函数(初始化栈)
~stack();//析构函数(销毁栈)
voidpush(TData);//压栈操作
Tgettop()const;//取栈顶元素
Tpop();//出栈操作
Tgetvalue(intindex);//返回栈底开始第INDEX个栈中值
voidtraverse(intn);//遍历栈N个数换行
intempty();//判断栈是否为空,1是,0非
intsizeofstack();//返回栈的大小
voidclear();//清空栈
};
//类模板成员函数的实现
templatestack:
:
stack()//构造函数
{
head=0;
}
templatestack:
:
~stack()//析构函数
{
link*cursor=head;
while(head)
{
cursor=cursor->next;
deletehead;
head=cursor;
}
}
templatevoidstack:
:
push(TData)//压栈操作
{
head=newlink(Data,head);
}
templateTstack:
:
gettop()const//取栈顶元素
{
returnhead->data;
}
templateTstack:
:
pop()//出栈操作
{
if(head==0)return0;
Tresult=head->data;
link*oldhead=head;
head=head->next;
deleteoldhead;
returnresult;
}
templateTstack:
:
getvalue(intindex)//返回栈底开始第INDEX个栈中值
{
link*cursor=head;
inti=1;
intstacklen=sizeofstack();
if(index<=0||index>stacklen)return0;
while(i<=(stacklen-index))
{
cursor=cursor->next;
i++;
}
returncursor->data;
}
templatevoidstack:
:
traverse(intn)//遍历栈
{
link*cursor=head;
intiEnterSign=1;//换行标识
while(cursor)
{
cout<data<<"";
if(iEnterSign%n==0)cout<cursor=cursor->next;
iEnterSign++;
}
if((iEnterSign-1)%n!
=0)cout<}
templateintstack:
:
empty()//判断栈是否为空,1是,0非
{
returnhead==0?
1:
0;
}
templateintstack:
:
sizeofstack()//返回栈的大小
{
intsize=0;
link*cursor=head;
while(cursor)
{
cursor=cursor->next;
size++;
}
returnsize;
}
templatevoidstack:
:
clear()//清空栈
{
link*cursor=head;
while(cursor&&cursor->next)
{
cursor=cursor->next;
deletehead;
head=cursor;
}
}
intOperator(charch)
{
if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='^'||ch=='('||ch==')'||ch=='\r')
return(TRUE);
else
return(FALSE);
}
charPrecede(charch1,charch2)
{
charch;
switch(ch1)
{
case'+':
case'-':
{
switch(ch2)
{
case'+':
case'-':
case')':
case'\r':
case'#':
ch='>';
break;
case'*':
case'/':
case'^':
case'(':
ch='<';break;
}
break;
}
case'*':
case'/':
{
if(ch2=='(')
ch='<';
elseif(ch2=='^')
ch='<';
else
ch='>';
break;
}
case'^':
{
if(ch2=='(')
ch='<';
else
ch='>';
break;
}
case'(':
{
if(ch2==')')
ch='=';
else
ch='<';
break;
}
case')':
{
ch='>';
break;
}
case'\r':
case'#':
{
if(ch2=='\r'||ch2=='#')
ch='=';
else
ch='<';
break;
}
}
return(ch);
}
doublecalc(doublex,charch,doubley)
{
doublez;
switch(ch)
{
case'+':
z=x+y;break;
case'-':
z=x-y;break;
case'*':
z=x*y;break;
case'/':
z=x/y;break;
case'^':
z=pow(x,y);break;
}
return(z);
}
doublemiddexpression(char*exp)//求解中缀表达式
{
stack*opnd=new(stack);
stack*optr=new(stack);
charch=*exp;
doublex=0,y,z;
doubleresult;
optr->push('#');
while(ch!
='\0')
{
//cout<if(ch>='0'&&ch<='9')
{
x=ch-48;
opnd->push(x);
ch=*++exp;
if(ch>='0'&&ch<='9')
{
cout<<"不符合要求,运算数必须是0~9之间的数"<exit(0);
}
}
elseif(Operator(ch))
{
switch(Precede(optr->gettop(),ch))
{
case'<':
//栈顶元素优先权低
optr->push(ch);
ch=*++exp;
if(ch=='\0')
{
cout<<"表达式错误,操作符不能用作结尾!
"<exit(0);
}
break;
case'=':
//脱括号并接收下一字符
optr->pop();
ch=*++exp;
if(ch>='0'&&ch<='9')
{
cout<<"不符合要求,右括号后没有运算符!
"<exit(0);
}
break;
case'>':
//退栈并将运算结果入栈
if(opnd->sizeofstack()<2)
{
cout<<"数字不够,表达式不合法!
"<exit(0);
}
x=opnd->pop();
y=opnd->pop();
z=calc(y,optr->pop(),x);
opnd->push(z);
//cout<x=0;
break;
}
}
elseif(ch!
='\0'&&!
Operator(ch)&&ch!
='')
{
cout<<"不符合要求,只能进行:
+,-,*,/,^,(,)运算!
"<exit(0);
}
elseif(ch!
='\0'&&!
Operator(ch)&&ch=='')
{
cout<<"不符合要求,中缀表达式中不允许包含多余的空格!
"<exit(0);
}
else
{
cout<<"输入不合法!
"<exit(0);
}
if(ch=='\0')
{
while(opnd->sizeofstack()>=2)
{
if(optr->gettop()=='(')
{
cout<<"表达式中的'('没有')'与之相对应!
"<exit(0);
}
switch(Precede(optr->gettop(),'#'))
{
case'<':
//栈顶元素优先权低
optr->push(ch);
ch=*++exp;
break;
case'=':
//脱括号并接收下一字符
optr->pop();
ch=*++exp;
break;
case'>':
//退栈并将运算结果入栈
x=opnd->pop();
y=opnd->pop();
z=calc(y,optr->pop(),x);
opnd->push(z);
//cout<x=0;
break;
}
}
}
}
result=(opnd->pop());
return(result);
}
voidmain(void)//程序入口函数
{
charexp[800];
cout<<"请输入中缀表达式(以回车键结束):
"<cin.getline(exp,800);
cout<}整个程序化费了我将近两整天的功夫,而且到现在我编的第一个程序还不知道错在了哪里,恳求老师的邮件指导,在此不甚感激。
本次试验让我回顾了C++的编程内容,初步掌握了堆栈的使用,让我受益匪浅~~~~