中缀试转后缀试及前缀试并计算其结果

/*
        参考大神nb的代码,感觉思路不错!终于搞明白了!一开始不明白在计算表达式的时候,利用栈到底做了什么!现在感觉我们利用栈就是模拟我们书面上计算表达式,
       将优先级高的运算先计算出来,然后放进栈中,等待下一次的计算
*/
#include<iostream>
#include<string>
#include<stack>
#include<cstdio>
using namespace std;

class node
{
public:
     double ret;
     string prefix, suffix;//前缀表达式和后缀表达式
     node()
     {
         ret=0;
         prefix=suffix="";
     }
};

stack<node>optd;//操作数栈
stack<char>optr;//操作符栈

char formula[1000];//表达式以"=" 结束 

int cmp(char ch)//定义符号的优先级
{
   switch(ch)
   {
      case '#': return -2;
      case '=': return -1;
      case '+':
      case '-': return 1;
      case '*':
      case '/': return 2;
      case '(': return 3;
      case ')': return 0;
   }
   return -2;
}

double deal(double x, char ch, double y)
{
   switch(ch)
   {
       case '+': return x+y;
       case '-': return x-y;
       case '*': return x*y;
       case '/': return x/y;
   }
   return 0.0;
}

void cal()
{
   int i=0, n;
   node num, aTmp, bTmp;
   while(optr.top()!='=')
   {
      if(formula[i]>='0' && formula[i]<='9')
      {
           sscanf(formula+i, "%lf%n", &num.ret, &n);
           num.prefix.assign(formula+i, n);
           num.suffix.assign(formula+i, n);
           i+=n;
           optd.push(num);
      }
      else
      {
           if(optr.top()=='(' && formula[i]==')')//消除一对括弧
           {
         optr.pop();
         ++i;
         }
           if(cmp(formula[i]) > cmp(optr.top()) || optr.top()=='(')//当前运算符大于栈顶运算符直接进栈
     {
         optr.push(formula[i]);
         ++i;
     }
     else
     {
        char ch=optr.top(), preTmp[]={ch, ' ', '\0'}, sufTmp[]={' ', ch, '\0'} ;
        optr.pop();//弹出一个栈顶操作符
        bTmp=optd.top(); optd.pop();//得到第二个操作数
        aTmp=optd.top(); optd.pop();//得到第一个操作数
        aTmp.ret=deal(aTmp.ret, ch, bTmp.ret);

        aTmp.suffix+=" " + bTmp.suffix + sufTmp;//得到运算后的后缀式子
        aTmp.prefix=preTmp + aTmp.prefix + " " + bTmp.prefix;//得到运算前的后缀式子
        optd.push(aTmp);//不要忘记将计算的结果放入栈中
     }
      }
   }
   optr.pop();//别忘记弹出栈顶上的'='
}

int main()
{
   optr.push('#');//初始化栈顶操作符是‘#’
   while(cin>>formula)
   {
       cal();
       node ans=optd.top(); optd.pop();
       cout<<"表达式结果:"<<ans.ret<<endl<<"前缀试:"<<ans.prefix+'='<<endl<<"后缀试:"<<ans.suffix+'='<<endl;
   }
   return 0;
}
时间: 2024-11-03 21:16:14

中缀试转后缀试及前缀试并计算其结果的相关文章

前缀、中缀和后缀表达式

关键字:概念, 前缀表达式, 前缀记法, 中缀表达式, 中缀记法, 波兰式, 后缀表达式, 后缀记法, 逆波兰式 它们都是对表达式的记法,因此也被称为前缀记法.中缀记法和后缀记法.它们之间的区别在于运算符相对与操作数的位置不同:前缀表达式的运算符位于与其相关的操作数之前:中缀和后缀同理. 举例:(3 + 4) × 5 - 6 就是中缀表达式- × + 3 4 5 6 前缀表达式3 4 + 5 × 6 - 后缀表达式 中缀表达式(中缀记法)中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀

用C语言写解释器(三)——中缀转后缀

声明 为提高教学质量,我所在的学院正在筹划编写C语言教材.<用C语言写解释器>系列文章经整理后将收入书中"综合实验"一章.因此该系列的文章主要阅读对象定为刚学完C语言的学生(不要求有数据结构等其他知识),所以行文比较罗嗦,请勿见怪.本人水平有限,如有描述不恰当或错误之处请不吝赐教!特此声明. 操作符排序 如果你忘记了后缀表达式的概念,赶紧翻回上一篇<用C语言写解释器(二)>回顾一下.简单地说,将中缀表达式转换成后缀表达式,就是将操作符的执行顺序由"优先

中缀转后缀表达式并求值

通过栈将中缀表达式转换为后缀表达式并根据后缀表达式求解,包含的Header.h为之前发过的栈操作相关函数实例程序,改成头文件就行.练习+记录,高手无视. OutPut: The init formula:3+4*5+(6*7+8)*9 The stack is empty. Convert result:345*+67*8+9*+ Calculate result:473 //Code by Pnig0s1992 //Date:2012,3,21 #include <stdio.h> #inc

你的“试错”是试错了还是试对了?

                 关于试错,有很多人有一些误解,只从字面理解"试错"两个字的意思,认为试错的意思就是有一个idea后就马上去做,然后看看到底是不是正确的--只要简单思考一下,我们就知道这种方法是不正确的--如果一个事情有十种可能性,难道我们要每一个可能都试一下吗?如果有一百.一千种可能呢?即使公司有足够的财力.人力去支持这种试错,但是每个机会点的窗口期可能只有1-2 年(甚至更短),往往在你把所有可能性都试一遍之前,就有别的公司成功发展起来了--这种"枚举&q

中粮集团进军互联网:先试B2B再试B2C

中介交易 SEO诊断 淘宝客 云主机 技术大厅 互联网的高速发展推动了传统企业营销渠道的多元化.近日,一名资深网购达人向记者爆料,其无意中进入了一个叫做"我买网"的网站,发现主页上赫然写着"中粮集团旗下食品购物网站"的字样,怀疑中粮集团也要开网店.记者就此问题致电中粮集团相关人士,对方告诉记者,"我买网"确系中粮集团所有. 记者了解到,该网站主要销售的是中粮旗下的食品,目前还在进行内测,并未正式对外运营. 八年前试水中华食物网 成立逾半个世纪的大

java数据结构与算法之中缀表达式转为后缀表达式的方法_java

本文实例讲述了java数据结构与算法之中缀表达式转为后缀表达式的方法.分享给大家供大家参考,具体如下: //stack public class StackX { private int top; private char[] stackArray; private int maxSize; //constructor public StackX(int maxSize){ this.maxSize = maxSize; this.top = -1; stackArray = new char[

详解C++编程中的主表达式与后缀表达式编写基础_C 语言

主表达式主表达式是更复杂的表达式的构造块.它们是文本.名称以及范围解析运算符 (::) 限定的名称.主表达式可以具有以下任一形式: literal this :: name name ( expression ) literal 是常量主表达式.其类型取决于其规范的形式. this 关键字是指向类对象的指针.它在非静态成员函数中可用,并指向为其调用函数的类的实例. this 关键字只能在类成员函数体的外部使用. this 指针的类型是未特别修改 this 指针的函数中的 type *const(

由扩展方法引“.NET研究”申出的编程思维

1. Helper大爆炸上海闵行企业网站设计与制作g> .NET Framework为我们提供了丰富的类库,但是这并不是万能地,在大部分的时间,我们都需要为我们的项目特殊定制我们的通用类库. 常常,我们都可以构造一个类,类里封装一些方法.但是对于很多时候,我们并没有办法提取出这样一个类,举一个小例子,我们在很多时候,需要把url给保存到数据库里,作为一个唯一标识,但是我们知道url所占空间很大,如果用url来建立索引的话是非常耗费空间,而且影响效率的,那么我们最常用的办法就是把url做一个Has

一起谈.NET技术,由扩展方法引申出的编程思维

1. Helper大爆炸 .NET Framework为我们提供了丰富的类库,但是这并不是万能地,在大部分的时间,我们都需要为我们的项目特殊定制我们的通用类库. 常常,我们都可以构造一个类,类里封装一些方法.但是对于很多时候,我们并没有办法提取出这样一个类,举一个小例子,我们在很多时候,需要把url给保存到数据库里,作为一个唯一标识,但是我们知道url所占空间很大,如果用url来建立索引的话是非常耗费空间,而且影响效率的,那么我们最常用的办法就是把url做一个Hash来作为索引的替代品. 这个时