1. 目的:写一个程序,从键盘输入一个合法的四则运算表达式,输出计算结果;

2. 实现原理:将表达式先由中缀式转为后缀式,然后利用栈计算表达式结果;

3. 实现代码:

版本1:

#include <iostream>
#include <stack>
#include <string>
using namespace std;
const int SIZE = 100;bool isOperator( char op )
{switch(op){case '+':case '-':case '*':case '/':return true;default:return false;}
}int priority( char op ) // 比较运算符优先级
{int value = -1;switch(op){case '#':value = -1;break;case '(':value = 0;break;case '+':case '-':value = 1;break;case '*':case '/':value = 2;break;}return value;
}// 中缀式转换为后缀式
// 把中缀表达式转换为后缀表达式,返回后缀表达式的长度(包括空格)  
int preToPostExp( string exp, char postExp[SIZE], int &len )
{stack<char> opSt; opSt.push('#');int i = 0;int j = 0;while( exp[i] != '#' ){if( exp[i] >= '0' && exp[i] <= '9' || exp[i] == '.' ){postExp[j++] = exp[i];len++;} else if( exp[i] == '(' )// 遇到“(”不用比较直接入栈{opSt.push(exp[i]);}else if( exp[i] == ')' )//遇到右括号将其对应左括号后的操作符(操作符栈中的)全部写入后缀表达式  {while( opSt.top() != '(' ){postExp[j++] = opSt.top();opSt.pop();len++;}opSt.pop(); //将'('出栈  将“(”出栈,后缀表达式中不含小括号 }else if( i == 0 && (exp[i] == '+' || exp[i] == '-')  ) //表明第一个数为正负号{postExp[j++] = exp[i];len++;}   else if( isOperator(exp[i]) ){postExp[j++] = ' ';  //用空格隔开操作数len++;//当前的操作符小于等于栈顶操作符的优先级时,将栈顶操作符写入到后缀表达式,重复此过程   while( priority(exp[i]) <= priority( opSt.top() ) ){postExp[j++] = opSt.top();opSt.pop();len++;}opSt.push(exp[i]); // 当前操作符优先级大于栈顶操作符的优先级,将该操作符入栈 }i++;} while( opSt.top() != '#' ) // 将所有的操作符加入后缀表达式{postExp[j++] = opSt.top();opSt.pop();len++;}return 0;
}double read_number(char str[],int *i)
{  double x=0.0;  int k = 0;  while(str[*i] >='0' && str[*i]<='9')  // 处理整数部分  {  x = x*10+(str[*i]-'0');  (*i)++;  }  if(str[*i]=='.') // 处理小数部分  {  (*i)++;  while(str[*i] >= '0'&&str[*i] <='9')  {  x = x * 10 + (str[*i]-'0');  (*i)++;  k++;  }  }  while(k!=0)  {  x /= 10.0;  k--;  }  return x;
}  // 计算后缀表达式结果
double computePostExp( char post[SIZE] )
{stack<double> stack;   // 操作数栈 double x1 = 0;double x2 = 0;bool flag = false;int i = 0;double d = 0;while( post[i] != '\0' ){if( post[i] >= '0' && post[i] <= '9' ){d =  read_number(post,&i);if(flag) // 第一个数为负数{d = -d;flag = false;}stack.push(d);} else if(post[i] == ' ' )i++;  else if (post[i] =='+')  {  x2 = stack.top();  stack.pop();x1 = stack.top(); stack.pop();stack.push(x1+x2);  i++;  }  else if( post[i] == '-' && i == 0 ) //表明第一个数为负数,方便计算-1+2*3{flag = true;i++;}else if (post[i] =='-')  {  x2 = stack.top();  stack.pop();x1 = stack.top();stack.pop(); stack.push(x1-x2);  i++;  }  else if (post[i] =='*')  {  x2 = stack.top();  stack.pop();x1 = stack.top();  stack.pop();stack.push(x1*x2);  i++;  }  else if (post[i] =='/')  {  x2 = stack.top();  stack.pop();x1 = stack.top();  stack.pop();stack.push(x1/x2);  i++;  }  }  return stack.top();
}int main()
{string exp = "";char postExp[SIZE];  // 保存后缀式结果 cout << "输入表达式(中缀,以#结束):"; cin >> exp; // 以#号结束int len = 0;preToPostExp( exp, postExp, len );postExp[len] = '\0';cout << "后缀表达式为:";cout << postExp << endl;cout << "\n由后缀表达式计算出的数值结果:  "; cout << computePostExp(postExp) << endl;system("pause");return 0;
}

/*
中缀式变后缀式算法:
反复读取输入内容直到结束为止
如果是数字直接入栈
否则如果是'('就等待处理括号里面的
否则如果是')'就倒回来处理直到左括号为止的全部运算
否则就是普通运算符(+,-,*,/)
  反复看那些暂存的未处理的运算符,只要优先级不比本运算符低就处理(入栈)
  暂存本运算符
反复取出栈中的剩余运算符并保存,直到栈无运算符
*/

4. 结果:

转载地址:

http://blog.csdn.net/geekcoder/article/details/6829386

注:相对于转载的地址中的代码,改进之一就是能够计算第一个操作数为负数的情况,即计算类似:-1+2*3的表达式

版本2:

#include <iostream>
#include <stack>
#include <string>
using namespace std;/*
表达式计算思路一:
1)准备两个栈:数据栈和运算符栈;
反复读取表达式:(2,3,4步)
2)如果是数,入数据栈;
3)如果是左括号,入运算符栈,如果是右括号,反复从运算符栈顶取运算符和从数据栈里取两个数据进行计算,并把结果入数据栈,直到遇到栈顶是左括号为止。
4)如果是运算符op,先跟栈顶的运算符比,只要不高于栈顶优先级,就取出栈顶的运算符和数据栈的两个数据进行计算,并把结果入数据栈,直到高于栈顶运算符优先级或者遇到左括号或者运算符栈空为止,此时把op入栈;
5)处理栈中的运算符:取出栈顶的运算符和数据栈的两个数据进行计算,并把结果入数据栈,直到运算符栈空为止;
6)这时数据栈中的数据就是计算结果。
*/
class Exp
{private:stack<char> ops;stack<double> ds;double v,  lh, rh; // 计算结果和临时操作数变量 char op; //运算符 public:double calinput()//读取并计算表达式直到结束为止{do{readdata();skipspace(); //跳过空白 }while( readop() );calremain(); //处理栈中剩余的运算符return v; } void readdata() //在该出现数据的时候可能出现'(' {// 如1+((2*3)) 左括号可能是多个 while( !(cin>>v) )  //读取数据失败,此时读取应该是'(',而v为double类型 {cin.clear();cin >> op; //读取'('if( op != '(' ){throw string("在该出现数值的地方出现了") + op; } ops.push(op); //左括号入栈 }ds.push(v);return;}void skipspace(){while( cin.peek() == ' ' || cin.peek() == '\t' ) //cin.peek只看不取走{cin.ignore(); //丢掉一个空白字符 } }bool readop() //读取运算符,可能出现右括号或者换行符(表达式结束) {//如(2*(3+4/(4-5))),右括号可能是多个 while( (op = cin.get() ) == ')' ){while( ops.top() != '(' ){rh = ds.top(); //取左操作数 ds.pop(); lh = ds.top();//取右操作数 ds.pop();ds.push( cal( lh, ops.top(), rh ) ); //计算并入栈ops.pop(); //取走运算符 }    ops.pop(); //丢弃'(' }if( op == '\n' ){return false;}if( strchr("+-*/", op ) == NULL ) //无效运算符 {throw string("无效运算符") + op; }while( !ops.empty() && ops.top() != '(' && !prior( op, ops.top() ) ){rh = ds.top(); ds.pop();lh = ds.top(); ds.pop();ds.push( cal( lh, ops.top(), rh ) ); //计算并入栈ops.pop(); //取走运算符   }ops.push(op);return true;} void calremain(){while( !ops.empty() ){rh = ds.top(); ds.pop();lh = ds.top(); ds.pop();ds.push( cal( lh, ops.top(), rh ) ); //计算并入栈ops.pop(); //取走运算符 }if( ds.size() != 1 ){throw string("无效的表达式"); }v = ds.top();ds.pop();return;}double cal( double lh, char op, double rh ){return op == '+'?lh+rh:op=='-'?lh-rh:op=='*'?lh*rh:lh/rh;}bool prior( char o1, char o2 )//若o1比o2优先级高返回true,否则返回false {return o1 != '+' && o1 != '-' && o2 != '*' && o2 != '/';}};int main()
{Exp e;try{cout << e.calinput() << endl;}catch( const string &e ){cout << e << endl;}system("pause");return 0;
}

输出结果:

计算四则表达式(中缀式转后缀式,然后计算结果)相关推荐

  1. c 语言表达式求值中缀变后缀,表达式求值关于中缀式转后缀式的问题!

    已结贴√ 问题点数:10 回复次数:6 表达式求值关于中缀式转后缀式的问题! 本人看资料的时候遇到一段代码,这段代码中转为后缀式的优先级那句不明白,请大神赐教,代码如下(c语言) #include # ...

  2. nyoj-257-郁闷的C小加(一 )中缀式变后缀式

    题目链接:here~~~~~~~ 今天看了此题,感觉栈和队列很好用,进一步深入了解 一个算术表达式,含有数字(为简化处理,数字只有一位),运算符:+.-.*,以及括号,求表达式的值. 给出的表达式是一 ...

  3. NYOJ 467 中缀式变后缀式

    中缀式变后缀式 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 人们的日常习惯是把算术表达式写成中缀式,但对于机器来说更"习惯于"后缀式,关于算术表达 ...

  4. java自动递增前缀式和后缀式区别

    java自动递增前缀式和后缀式区别 java自动递增(自动递减)前缀式表达式 '++' 操作符位于变量或表达式的前面,而后缀式表达式'++'位于变量或表达式的后面,Example: 前缀式: ++i: ...

  5. nyoj 1272 表达式求值(中缀式转后缀式)

    表达式求值 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 假设表达式定义为: 1. 一个十进制的正整数 X 是一个表达式. 2. 如果 X 和 Y 是 表达式,则 X+ ...

  6. 算术表达式的前缀式、中缀式、后缀式相互转换

    中缀表达式(中缀记法) 中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间.中缀表达式是人们常用的算术表示方法. 虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀 ...

  7. 语法树,前缀式,中缀式,后缀式

    前序遍历:根左右 中序遍历:左根右 后序遍历:左右根 前缀式:+AB 中缀式:A+B 后缀式:AB+ 例题一: 前序遍历(前缀式):- + 4 * 1 - 5 2 / 6 3 根在前,从最后开始:-5 ...

  8. 逆波兰式(后缀式)详解

    原表达式:a*(b*(c+d/e)-f)#    /* # 为表达式结束符号*/ 后缀式:abcde/+*f-*# 为运算符定义优先级:#   (   +   -   *   /   ** -1   ...

  9. 前缀式与后缀式的差别

    文章出处: http://blog.sina.com.cn/s/blog_5ca785c30100bb89.html websense的一道笔试题,问++i为什么比i++效率高. 有有心人详细而全面的 ...

  10. java 中缀式转后缀式

    import java.util.Stack; import java.util.regex.*; public class StringToArithmetic { private StringTo ...

最新文章

  1. DLM:微信大规模分布式n-gram语言模型系统
  2. 电脑前面的插孔没声音怎么设置_手机没声音是怎么回事
  3. 4+5的值是python_Python基础:数据类型-数字(5)
  4. 在Windows XP系统登录Active Directory域
  5. Jupyter Notebook 入门指南
  6. 中connect怎么用_烘焙中的各种酒,到底该怎么用?
  7. 蓝色起源起诉NASA,不服其将月球着陆器合同授予SpaceX
  8. php orm 内存泄漏,Lavarel Eloquent ORM常驻进程下的内存溢出问题
  9. 软核、固核、硬核的区别
  10. python创建子窗口_python GUI编程(Tkinter) 创建子窗口及在窗口上用图片绘图实例
  11. 无人驾驶入门1:无人驾驶概览
  12. (APP测试三板斧)第一板:Xposed+JustTrustMe绕过SSL Pining
  13. 在企业中采用知识管理工具的好处
  14. Rate 函数在PromQL 查询中的使用
  15. 拜登签署芯片法案后,英特尔股票的前景如何?
  16. 单纯技术背景已不吃香 MBA管理能力更被招聘者看好
  17. Django推导Django内部模块:wsgiref与jinja2
  18. 微信分享按钮隐藏、显示问题和注意事项
  19. yii mysql 查询 类型转换_yii2.0数据库查询修改等方法
  20. 萌宠历险记html5游戏在线玩,7724萌宠历险记

热门文章

  1. 【智衡跨境电商shopee运营】Shopee平台流量入口有哪些?
  2. win7指定网络名不再可用
  3. FIsh论坛《零基础入门学习Python》| 第012讲 课后测试题及答案
  4. LaTeX插入参考文献教程 | 非BibTeX格式
  5. 南京大学计算机专业复试面试,南京大学计算机CS专业复试超全PPT及真题、面试内部资料(离散编译上机面试)...
  6. SpringBoot整合MyBatis(七)
  7. JavaScript函数传参原理详解——值传递还是引用传递
  8. 角度与弧度的转换 C语言
  9. python——平方根
  10. 详细介绍MATLAB导入文本文件、excel等数据文件