Postfix Expression Evaluator

本文介绍了一个用于评估后缀表达式的Java类实现。该类使用栈来存储操作数,并定义了运算符及其优先级。文章详细展示了如何解析后缀表达式并进行计算,同时处理可能出现的语法错误。
 
  1. /**
  2.  * filename: PostfixEvaluator.java
  3.  * package:  
  4.  * author:   Li Ma
  5.  * email:    nick.ma85@yahoo.com
  6.  * date:     Oct 3, 2008 (created)
  7.  *                       Nov 2, 2008 (modified)
  8.  * description: this class evaluates postfix expression.
  9.  */
  10. import  java.util.*;
  11. public   class  PostfixEvaluator {
  12.         
  13.          /** the stack stores operands */
  14.          private  Stack<Integer> operandStack;
  15.         
  16.          /** each operator(char) has a integer value of priority */
  17.          private   static   final  Map<Character, Integer> OPERATORS;
  18.         
  19.          /** postfix expression */
  20.          private  String postfix;
  21.         
  22.          static  {
  23.                  // initialize the static field
  24.                 OPERATORS =  new  HashMap<Character, Integer>();
  25.                 OPERATORS.put( '+'1 );
  26.                 OPERATORS.put( '-'1 );
  27.                 OPERATORS.put( '*'2 );
  28.                 OPERATORS.put( '/'2 );
  29.         }
  30.         
  31.          /**
  32.          * description: the constructor with fields
  33.          */
  34.          public  PostfixEvaluator(String postfix) {
  35.                  // TODO Auto-generated constructor stub
  36.                 operandStack =  new  Stack<Integer>();
  37.                  this .postfix = postfix;
  38.         }
  39.          /**
  40.          * description: determine whether the character is an operator
  41.          * @param ch - the character to be tested
  42.          * @return      true if ch is an operator
  43.          */
  44.          private   boolean  isOperator( char  ch) {
  45.                  return  OPERATORS.containsKey(ch);
  46.         }
  47.         
  48.          /**
  49.          * description: evaluate the current operation, poping the two operands off 
  50.          * the operand stack and applying the operator.
  51.          * @param op - a character representing the operator
  52.          * @return the result of applying the operator
  53.          */
  54.          private   int  evalOp( char  op) {
  55.                  // pop the two operands off the stack
  56.                  int  rhs = operandStack.pop();
  57.                  int  lhs = operandStack.pop();
  58.                  int  result =  0 ;
  59.                 
  60.                  // evaluate the operator
  61.                  switch (op) {
  62.                  case   '+' :
  63.                         result = lhs + rhs;
  64.                          break ;
  65.                  case   '-' :
  66.                         result = lhs - rhs;
  67.                          break ;
  68.                  case   '*' :
  69.                         result = lhs * rhs;
  70.                          break ;
  71.                  case   '/' :
  72.                         result = lhs / rhs;
  73.                          break ;
  74.                 }
  75.                  return  result;
  76.         }
  77.         
  78.          /**
  79.          * description: evaluate the whole infix expression
  80.          * @return      the value of the infix expression
  81.          * @throws SyntaxErrorException
  82.          */
  83.          public   int  eval()  throws  SyntaxErrorException {
  84.                 
  85.                  // process each token
  86.                 StringTokenizer tokens =  new  StringTokenizer( this .postfix);
  87.                  try  {
  88.                          while (tokens.hasMoreTokens()) {
  89.                                 String next = tokens.nextToken();
  90.                                 
  91.                                  if (Character.isDigit(next.charAt( 0 ))) {
  92.                                          int  value = Integer.parseInt(next);
  93.                                         
  94.                                          // push value onto operand stack
  95.                                         operandStack.push(value);
  96.                                 }  else   if (isOperator(next.charAt( 0 ))) {
  97.                                          // it is an operator
  98.                                          // evaluate the operator
  99.                                          int  result = evalOp(next.charAt( 0 ));
  100.                                         operandStack.push(result);
  101.                                 }  else  {
  102.                                          throw   new  SyntaxErrorException( "Invalid character encountered" );
  103.                                 }
  104.                         }
  105.                         
  106.                          // no more tokens, pop result from operand stack
  107.                          int  answer = operandStack.pop();
  108.                          if (operandStack.empty()) {
  109.                                  return  answer;
  110.                         }  else  {
  111.                                  // indicate syntax error
  112.                                  throw   new  SyntaxErrorException( "Stack should be empty" );
  113.                         }
  114.                 }  catch (EmptyStackException e) {
  115.                          throw   new  SyntaxErrorException( "the stack is empty" );
  116.                 }
  117.         }
  118. }
  119. /**
  120.  * filename: SyntaxErrorException.java
  121.  * package:  
  122.  * author:   Li Ma
  123.  * email:    nick.ma85@yahoo.com
  124.  * date:     Oct 3, 2008
  125.  * description: this exception shows a syntax error.
  126.  */
  127. public   class  SyntaxErrorException  extends  Exception {
  128.          private   static   final   long  serialVersionUID = 1L;
  129.          public  SyntaxErrorException( final  String message) {
  130.                  super (message);
  131.         }
  132. }
#include <iostream> #include <string> #include <stack> #include <queue> #include <cmath> #include <map> #include <sstream> #include <cctype> #include <regex> using namespace std; // 定义支持的运算符及其优先级 map<string, int> operators = { {"+", 2}, {"-", 2}, {"*", 3}, {"/", 3}, {"^", 4} }; // 定义ExpressionCalculator类 class ExpressionCalculator { private: // 成员函数用于判断是否是运算符 bool is_operator(const string& token) const { return operators.find(token) != operators.end(); } // 成员函数用于判断是否是函数 bool is_function(const string& token) const { return token == "sin" || token == "cos" || token == "tan" || token == "sqrt" || token == "log" || token == "exp"; } // 成员函数用于获取运算符的优先级 int precedence(const string& op) const { return operators.at(op); } // 成员函数用于将中缀表达式转换为后缀表达式 queue<string> infix_to_postfix(const vector<string>& tokens) const { stack<string> op_stack; queue<string> output; for (const auto& token : tokens) { if (isdigit(token[0]) || (token[0] == '-' && token.length() > 1)) { // 处理负数 output.push(token); } else if (is_function(token)) { op_stack.push(token); } else if (is_operator(token)) { while (!op_stack.empty() && is_operator(op_stack.top()) && precedence(op_stack.top()) >= precedence(token)) { output.push(op_stack.top()); op_stack.pop(); } op_stack.push(token); } else if (token == "(") { op_stack.push(token); } else if (token == ")") { while (!op_stack.empty() && op_stack.top() != "(") { output.push(op_stack.top()); op_stack.pop(); } if (!op_stack.empty() && op_stack.top() == "(") { op_stack.pop(); } if (!op_stack.empty() && is_function(op_stack.top())) { output.push(op_stack.top()); op_stack.pop(); } } } while (!op_stack.empty()) { output.push(op_stack.top()); op_stack.pop(); } return output; } // 成员函数用于计算后缀表达式 double evaluate_postfix(const queue<string>& postfix) const { stack<double> eval_stack; queue<string> temp = postfix; while (!temp.empty()) { string token = temp.front(); temp.pop(); if (isdigit(token[0]) || (token[0] == '-' && token.length() > 1)) { eval_stack.push(stod(token)); } else if (is_operator(token)) { double rhs = eval_stack.top(); eval_stack.pop(); double lhs = eval_stack.top(); eval_stack.pop(); if (token == "+") { eval_stack.push(lhs + rhs); } else if (token == "-") { eval_stack.push(lhs - rhs); } else if (token == "*") { eval_stack.push(lhs * rhs); } else if (token == "/") { eval_stack.push(lhs / rhs); } else if (token == "^") { eval_stack.push(pow(lhs, rhs)); } } else if (is_function(token)) { double operand = eval_stack.top(); eval_stack.pop(); if (token == "sin") { eval_stack.push(sin(operand)); } else if (token == "cos") { eval_stack.push(cos(operand)); } else if (token == "tan") { eval_stack.push(tan(operand)); } else if (token == "sqrt") { eval_stack.push(sqrt(operand)); } else if (token == "log") { eval_stack.push(log(operand)); } else if (token == "exp") { eval_stack.push(exp(operand)); } } } return eval_stack.top(); } public: // 成员函数用于计算表达式 double calculate(const string& expression) { // 词法分析 vector<string> tokens = tokenize(expression); tokens = handle_negatives(tokens); // 转换为后缀表达式 queue<string> postfix = infix_to_postfix(tokens); // 计算结果 return evaluate_postfix(postfix); } // 词法分析函数 vector<string> tokenize(const string& expression) const { vector<string> tokens; string token = ""; for (size_t i = 0; i < expression.length(); ++i) { if (isspace(expression[i])) continue; if (isdigit(expression[i]) || expression[i] == '.') { token += expression[i]; } else if (expression[i] == '-' && (i == 0 || expression[i - 1] == '(' || is_operator(string(1, expression[i - 1])))) { token += expression[i]; } else { if (token != "") { tokens.push_back(token); token = ""; } token += expression[i]; tokens.push_back(token); token = ""; } } if (token != "") { tokens.push_back(token); } return tokens; } // 处理负数的函数 vector<string> handle_negatives(const vector<string>& tokens) const { vector<string> result; for (size_t i = 0; i < tokens.size(); ++i) { if (tokens[i] == "-" && (i == 0 || tokens[i - 1] == "(" || is_operator(tokens[i - 1]))) { // 负数 string num = "-"; i++; while (i < tokens.size() && (isdigit(tokens[i][0]) || tokens[i][0] == '.')) { num += tokens[i]; i++; } result.push_back(num); i--; } else { result.push_back(tokens[i]); } } return result; } }; int main() { ExpressionCalculator calculator; string input; cout << "请输入表达式(输入指令Q退出):"; while (true) { getline(cin, input); if (("Q" == input) || ("q" == input)) { break; } else { try { double result = calculator.calculate(input); cout << "结果: " << result << endl; } catch (...) { cout << "计算过程中出现错误。" << endl; } cout << "请输入表达式继续运算或输入指令(Q)退出: "; } } cout << "退出成功!" << endl; return 0; }改
06-13
import pygame,sys,copy from pygame.locals import * from E3_1 import * DarkOrange = 255,140,0 blue = 0,0,255 red = 255,0,0 black = 0,0,0 white = 255,255,255 pygame.init() screen = pygame.display.set_mode((600,600),SRCALPHA,32) font = pygame.font.Font(None, 36) priority = {"(":1, "+":3, "-":3, "*":5, "/":5} infix_operators = "+-*/()" expression = "1 + ( 5 - 3 ) * 4 + 10 / 5" exp = [] #用来存放转换后的后缀表达式 def initScreen(): screen.fill(white) pygame.display.set_caption("Stack") image = pygame.image.load('Image\\stack.jpg') screen.blit(image,(100,300)) textImage = font.render(expression, True, blue) screen.blit(textImage,(100,100)) draw(exp) pygame.display.update() def drawStack(st): st1 = copy.deepcopy(st) initScreen() while not st1.is_empty(): c = st1.pop() textImage = font.render(c, True, blue) screen.blit(textImage,(360,580 - (st1.length()+1) * 35)) pygame.display.update() pygame.time.delay(500) def draw(exp): for i in range(len(exp)): textImage = font.render(exp[i], True, red) screen.blit(textImage,(100+i*30,200)) pygame.display.update() def trans_infix_suffix(expression): st = SStack() line = expression.split() for x in list(line): if x not in infix_operators: exp.append(x) # x无需入栈,直接添加到exp中 elif st.is_empty() or x == '(': st.push(x) # x入栈 drawStack(st) elif x == ')': while not st.is_empty() and st.top() != "(": exp.append(st.pop()) # 弹出栈顶元素,并添加至exp中 drawStack(st) if st.is_empty(): raise SyntaxError("Missing \'(\'.") # 弹出栈顶元素,正常情况下为'(' st.pop() drawStack(st) else: # consider all ops left-associative while (not st.is_empty() and priority[st.top()] >= priority[x]): # 弹出栈顶元素,并添加至exp中 exp.append(st.pop()) drawStack(st) st.push(x)# x入栈 drawStack(st) while not st.is_empty(): exp.append(st.pop())# 依次弹出全部元素,并添加至exp中 drawStack(st) return exp def suf_exp_evaluator(exp): st=SStack() operators="+-*/" for x in exp: if not x in operators: st.push(float(x)) drawStack(st) continue a=st.pop() drawStack(st) b=st.pop() drawStack(st) if x=='+': c=b+a elif x=='-': c=b-a elif x=='*': c=b*a elif x=='/': if a==0 :raise ZeroDivisionError c=b/a st.push(c) drawStack(st) if st.length()==1: return st.top() raise SyntaxError("Extra operand(s).") initScreen() trans_infix_suffix(expression) suf_exp_evaluator(exp) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit()上面代码跑不起来
05-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值