首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c++中的前缀递归表示法

c++中的前缀递归表示法
EN

Stack Overflow用户
提问于 2012-08-19 18:36:07
回答 3查看 3.5K关注 0票数 0

我在寻找用波兰前缀表示法计算表达式的递归解决方案,但没有找到,但我找到了伪代码,我想将其转换为C++,但这很难。我写了很大的信,我不知道该怎么写。请纠正我,我是java人,对我来说,C++是个大烂摊子,但我无法控制。

代码语言:javascript
复制
int preEval(stack<string> stos){
  string el = "";
  if(stos.empty()){
    return 0;
  }else if(stos.top() IS VALUE){
    string el = stos.top();
    stos.pop();
    return atoi(el.c_str());
  }else if(stos.top() IS OPERATOR){
    int x = preEval(stos);
    int y = preEval(stos);
    return x OPERATOR y;
  }
  return 0;
}

编辑

当我有像/105这样的表达式时,应该堆叠元素(从顶部)/105,还是5 10 /?只是问一下,因为如果我想要在/105中,我必须以某种方式向后读字符串。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-08-19 19:44:51

如果你有这样的功能:

代码语言:javascript
复制
#include <assert.h>
#include <errno.h>
#include <stdlib.h>
#include <iostream>
#include <stack>
#include <string>

using std::stack;
using std::string;
using std::cerr;

enum Operator {
  operator_none,
  operator_plus,
  operator_minus
};

Operator tokenOperator(const string &token)
{
  if (token=="+") return operator_plus;
  if (token=="-") return operator_minus;
  return operator_none;
}

int applyOperator(Operator op,int x,int y)
{
  switch (op) {
    case operator_plus:  return x+y;
    case operator_minus: return x-y;
    case operator_none:
      break;
  }
  assert(false);
  return 0;
}

bool isValue(const string &token,int &output_value)
{
  char *end = 0;
  errno=0;
  output_value = strtol(token.c_str(),&end,10);
  if (errno!=0) return false;
  return *end=='\0';
}

bool isOperator(const string &token,Operator &output_operator)
{
  output_operator = tokenOperator(token);
  return output_operator!=operator_none;
}

然后可以这样实现preEval:

代码语言:javascript
复制
int preEval(stack<string> &stos)
{
  if (stos.empty()) return 0;

  string el = stos.top();
  stos.pop();

  int value = 0;
  Operator op = operator_none;

  if (isValue(el,value)) return value;

  if (isOperator(el,op)) {
    int x = preEval(stos);
    int y = preEval(stos);
    return applyOperator(op,x,y);
  }

  return 0;
}
票数 2
EN

Stack Overflow用户

发布于 2012-08-19 18:41:31

我认为,更好的解决方案是将工作分为两个阶段:词法和解析。

在词法阶段,您可以对每个令牌进行分类,以查看它是否是运算符(+-等)。或者一个常数,或者一个变量。然后将解析的实体打包到包含类型和其他信息的结构中。

在由代码提供的解析阶段,您使用的不是字符串,而是结构。从结构上看,您可以很容易地找到它的类型。(如果您选择构建从公共基派生的结构层次结构,则可以是结构内部的字段,也可以是结构的类型。)

实际上,在Java和C++中,逻辑应该是相同的。

票数 5
EN

Stack Overflow用户

发布于 2012-08-19 19:05:00

代码语言:javascript
复制
#include <string>
#include <map>

using namespace std;

bool is_value(string s) {
    return s.find_first_not_of("0123456789") == string::npos;
}

int do_add(int x, int y) {
    return x + y;
}

int do_subtract(int x, int y) {
    return x - y;
}

// etc.

typedef int (*binary_op)(int, int);   // Give this function pointer type a nice name
map<string, binary_op> ops;

// Somewhere before the preEval() is ever called
ops["+"] = do_add;
ops["-"] = do_subtract;    // etc.

binary_op lookup_op(string s) {
    map<string, binary_op>::const_iterator it = ops.find(s);
    if (it != ops.end()) {
        return *it;
    } else {
        return NULL;
    }
}

现在,不要单独测试令牌是否是运算符,然后执行该运算符,而是使用单个函数调用来获取一个指向需要调用的运算符函数的指针(如果令牌是运算符)或NULL。即:

代码语言:javascript
复制
}else if(stos.top() IS OPERATOR){
    int x = preEval(stos);
    int y = preEval(stos);
    return x OPERATOR y;
}

变成了

代码语言:javascript
复制
} else {
    binary_op op = lookup_op(stos.top());
    if (binary_op != NULL) {
        stos.pop();   // This fixes the bug I mentioned in my top comment
        int x = preEval(stos);
        int y = preEval(stos);
        return op(x, y);
    } else {
        syntax_error();
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12028960

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档