栈的应用——求解简单算术表达式值

来源:互联网 发布:深圳资深淘宝客服 编辑:程序博客网 时间:2024/06/05 10:19

问题描述:

这里限定的简单算术表达式求值问题是:用户输入一个包含“+”、“-”、“*”、“/”、正整数和圆括号的合法数学表达式,计算该表达式的运算结果。如:“2+4*(5-1)”=18。

代码示例:

#include <iostream>#include "SqStack.cpp"//包含顺序栈类模板using namespace std;class ExpressClass//求表达式值类{char *exp;//存放中缀表达式char postexp[MaxSize];//存放后缀表达式int pnum;//postexp中字符个数public:void Setexp(char *str);//获取一个中缀表达式void Disppostexp();//输出后缀表达式void Trans();//将算术表达式exp转换成后缀表达式postexpbool GetValue(double &v);//计算后缀表达式postexp的值void Trans1();//输出将算术表达式exp转换成后缀表达式postexp的过程bool GetValue1(double &v);//输出计算后缀表达式postexp的值的过程};void ExpressClass::Setexp(char *str)//获取一个中缀表达式{exp = str;}void ExpressClass::Trans()//将算术表达式exp转换成后缀表达式postexp{SqStackClass<char> op;//运算符栈int i = 0, j = 0;//i、j作为exp和postexp的下标char ch, e;while (exp[i])//exp表达式未扫描完时循环{ch = exp[i];if (ch == '(')//判定为左括号op.Push(ch);//将左括号进栈else if (ch == ')')//判定为右括号{while (!op.StackEmpty() && op.GetTop(e) && e != '(')//将op栈中'('之前的运算符退栈并存放到postexp中{op.Pop(e);postexp[j++] = e;}op.Pop(e);//将(退栈}else if (ch == '+' || ch == '-')//判定为加或减号{while (!op.StackEmpty() && op.GetTop(e) && e != '(')//将op栈中'('之前的所有运算符退栈并存放到postexp中{op.Pop(e);postexp[j++] = e;}op.Push(ch);//再将'+'或'-'进栈}else if (ch == '*' || ch == '/')//判定为'*'或'/'号{while (!op.StackEmpty() && op.GetTop(e) && e != '(' && (e == '*' || e == '/'))//将op栈中'('之前的'*'或'/'运算符依次出栈并存放到postexp中{op.Pop(e);postexp[j++] = e;}op.Push(ch);//再将'*'或'/'进栈}else//处理数字字符{while (ch >= '0' && ch <= '9')//判定为数字{postexp[j++] = ch;i++;//将连续的数字放入postexpif (exp[i]) ch = exp[i];else break;}i--;postexp[j++] = '#';//用#标识一个数值串结束}i++;//继续处理其他字符}while (!op.StackEmpty())//此时exp扫描完毕,栈不空时循环{op.Pop(e);//将栈中所有运算符退栈并放入postexppostexp[j++] = e;}pnum = j;//保存postexp中字符个数}bool ExpressClass::GetValue(double &v)//计算后缀表达式postexp的值{SqStackClass<double> st;//运算数栈stdouble a, b, c, d;int i = 0; char ch;while (i<pnum)//postexp字符串未扫描完时循环{ch = postexp[i];switch (ch){case '+'://判定为'+'号st.Pop(a);//退栈取数值ast.Pop(b);//退栈取数值bc = b + a;//计算cst.Push(c);//将计算结果进栈break;case '-'://判定为'-'号st.Pop(a);//退栈取数值ast.Pop(b);//退栈取数值bc = b - a;//计算cst.Push(c);//将计算结果进栈break;case '*'://判定为'*'号st.Pop(a);//退栈取数值ast.Pop(b);//退栈取数值bc = b*a;//计算cst.Push(c);//将计算结果进栈break;case '/'://判定为'/'号st.Pop(a);//退栈取数值ast.Pop(b);//退栈取数值bif (a != 0){c = b / a;//计算cst.Push(c);//将计算结果进栈}else return false;//除零错误返回falsebreak;default://处理数字字符d = 0;//将连续的数字符转换成数值存放到d中while (ch >= '0' && ch <= '9')//判定为数字字符{d = 10 * d + (ch - '0');i++;ch = postexp[i];}st.Push(d);//将数值d进栈break;}i++;//继续处理其他字符}st.GetTop(v);//栈顶元素即为求值结果return true;}void ExpressClass::Disppostexp()//输出后缀表达式{int i;for (i = 0; i < pnum; i++)cout << postexp[i];cout << endl;}//=================显示求解过程========================void ExpressClass::Trans1()//输出将算术表达式exp转换成后缀表达式postexp的过程{SqStackClass<char> op;//运算符栈opint i = 0, j = 0;//i、j作为exp和postexp的下标char ch, e;while (exp[i])//exp表达式未扫描完时循环{ch = exp[i];if (ch == '(')//判定为左括号{op.Push(ch);cout << "  运算符'" << ch << "'进栈\n";}else if (ch == ')')//判定为右括号{while (!op.StackEmpty() && op.GetTop(e) && e != '(')//将op栈中'('之前的运算符退栈并存放到postexp中{op.Pop(e);postexp[j++] = e;cout << "  运算符'" << e << "'退栈→postexp\n";}op.Pop(e);//将(退栈cout << "  运算符'('退栈\n";}else if (ch == '+' || ch == '-')//判定为加或减号{while (!op.StackEmpty() && op.GetTop(e) && e != '(')//将op栈中'('之前的运算符退栈并存放到postexp中{op.Pop(e);postexp[j++] = e;cout << "  运算符'" << e << "'退栈→postexp\n";}op.Push(ch);//将'+'或'-'进栈cout << "  运算符'" << ch << "'进栈\n";}else if (ch == '*' || ch == '/')//判定为'*'或'/'号{while (!op.StackEmpty() && op.GetTop(e) && e != '(' && (e == '*' || e == '/'))//将op栈中'('之前的'*'或'/'运算符依次出栈并存放到postexp中{op.Pop(e);postexp[j++] = e;cout << "  运算符'" << e << "'退栈→postexp\n";}op.Push(ch);//将'*'或'/'进栈cout << "  运算符'" << ch << "'进栈\n";}else//处理数字字符{while (ch >= '0' && ch <= '9')//判定为数字{postexp[j++] = ch;cout << "  " << ch << "→postexp\t";i++;if (exp[i]) ch = exp[i];//exp表达式未扫描完时取下一个字符else  break;}i--;postexp[j++] = '#';//用#标识一个数值串结束cout << "  postexp中加#\n";}i++;//继续处理其他字符}while (!op.StackEmpty())//此时exp扫描完毕,栈不空时循环{op.Pop(e);postexp[j++] = e;cout << "  运算符'" << e << "'退栈→postexp\n";}pnum = j;}bool ExpressClass::GetValue1(double &v)//输出计算后缀表达式postexp的值的过程{SqStackClass<double> st;//运算数栈double a, b, c, d; int i = 0; char ch;while (i < pnum)//postexp字符串未扫描完时循环{ch = postexp[i];switch (ch){case '+'://判定为'+'号st.Pop(a);//退栈取数值acout << "  运算数" << a << "退栈\t";st.Pop(b);//退栈取数值bcout << "  运算数" << b << "退栈\n";c = b + a;//计算ccout << "  计算" << b << "+" << a << "=" << c << endl;st.Push(c);//将计算结果进栈cout << "  运算数" << c << "进栈\n";break;case '-'://判定为'-'号st.Pop(a);//退栈取数值acout << "  运算数" << a << "退栈\t";st.Pop(b);//退栈取数值bcout << "  运算数" << b << "退栈\n";c = b - a;//计算ccout << "  计算" << b << "-" << a << "=" << c << endl;st.Push(c);//将计算结果进栈cout << "  运算数" << c << "进栈\n";break;case '*'://判定为'*'号st.Pop(a);//退栈取数值acout << "  运算数" << a << "退栈\t";st.Pop(b);//退栈取数值bcout << "  运算数" << b << "退栈\n";c = b*a;//计算ccout << "  计算" << b << "*" << a << "=" << c << endl;st.Push(c);//将计算结果进栈cout << "  运算数" << c << "进栈\n";break;case '/'://判定为'/'号st.Pop(a);//退栈取数值acout << "  运算数" << a << "退栈\t";st.Pop(b);//退栈取数值bcout << "  运算数" << b << "退栈\n";if (a != 0){c = b / a;//计算ccout << "  计算" << b << "/" << a << "=" << c << endl;st.Push(c);//将计算结果进栈cout << "  运算数" << c << "进栈\n";}else  return false;//除零错误返回falsebreak;default://处理数字字符d = 0;//将连续的数字符转换成数值存放到d中while (ch >= '0' && ch <= '9')//判定为数字字符{d = 10 * d + (ch - '0');i++;ch = postexp[i];}st.Push(d);//数值d进栈cout << "  运算数" << d << "进栈\n";break;}i++;//继续处理其他字符}st.GetTop(v);//栈顶元素即为求值结果cout << "  取栈顶数值" << v << endl;return true;}void main(){double v;ExpressClass obj;char *str = "(56-20)/(4+2)";obj.Setexp(str);cout << "中缀表达式" << str << "转换为后缀表达式的过程:\n";obj.Trans1();cout << "求得的后缀表达式:"; obj.Disppostexp();cout << "求后缀表达式的过程:\n";obj.GetValue1(v);cout << "求得的表达式值:" << v << endl;}


原创粉丝点击