【问题标题】:Evaluating Arithmetic Expression Using Recursion in C在 C 中使用递归评估算术表达式
【发布时间】:2018-11-11 19:53:41
【问题描述】:

这是一个使用递归计算算术表达式的算法:

  • 查找操作数1
  • t1 = Eval(operand1)
  • 查找操作数2
  • t2 = Eval(operand2)
  • 在 t1 和 t2 上应用运算符

假设:

  • 每个操作数都在两个运算符之间
  • 只有二元运算

  • 每个操作都有括号(包括最外面的括号)

输入:

  • 表示算术表达式的标记数组

  • num_tokens 是令牌的数量

标记的示例数组:{"("、"9"、"+"、"("、"50"、"-"、"25"、")"、")"}

我尝试实现该算法,但我的程序没有运行(退出状态 -1 是我得到的唯一消息)。为什么会这样?

int apply(char op, int a, int b) {
       if (op == '+'){
        printf("%d %c %d\n", a,op,b);
        return a + b;
       }
       else if (op == '-'){
        printf("%d %c %d\n", a,op,b);
        return a - b;
       }
       else if(op == '/'){
        printf("%d %c %d\n", a,op,b);
        return a / b;
       }
       else if(op == '*'){
        printf("%d %c %d\n", a,op,b);
        return a * b;
       }
}   

int eval_tokens(char** expression, int num_tokens)
{
  // implement me
    int index;
    int opIndex = find_operator(expression, num_tokens); //find index of operator
    int count1=0,count2=0,term1,term2,i,j;

    if(*expression[0] == '(')
      i = 1;
    else
      i = 0;

    while(i <= opIndex){
        i++;
        count1++;
    }

    term1 = eval_tokens(expression+1,count1);

    j = opIndex+1;
    while(j < num_tokens){
      count2++;
      j++;
    }

  term2 = eval_tokens(expression+opIndex+1,count2); //expression+opIndex+1 points to index after opIndex
  return apply(*expression[opIndex], term1, term2);
}

int main(void) {
    char*expression[] = {"(", "(", "5", "+", "3", ")", "-", "(", "2", "+", "1", ")", ")"};
    printf("result = %d\n", eval_tokens(expression, 13));
    return 0;
}

【问题讨论】:

  • **expression 用作堆栈(实际上是队列)。如果它是仅在二元运算符上的中缀,则顺序为.. (1) 使用递归调用从表达式“堆栈”中获取 LHS 操作数,(2) 从堆栈中获取操作数,(3) 从堆栈中获取 RHS 操作数并计算然后.
  • 嗯,你的程序的主要问题是它缺少main 函数。
  • @melpomene 我在测试时确实有一个主要功能。我会把它添加到我的问题中。
  • @StephanLechner 我如何从表达式“stack”中“获取”?
  • @StephanLechner 我尝试使用term1 = infix_eval_tokens(expression+1,count1); 获取左侧操作数,使用term2 = infix_eval_tokens(expression+opIndex+1,count2); 获取右侧操作数,但似乎不起作用。

标签: c recursion calculator


【解决方案1】:

要将str(或expression)用作可以从中取出项目的堆栈,我会在递归函数中使这些参数“可修改”。因此,您可以引入第二个函数int eval_tokens_recursive(char*** expression, int *num_tokens),它具有多一层间接性,实际上可以通过更改参数的值来“从堆栈中取出项目”。

代码如下所示。希望对您有所帮助。

int eval_tokens_recursive(char*** expression, int *num_tokens) {

    char *token = **expression;
    if (*num_tokens == 0) {
        printf("expecting more tokens.\n");
        exit(1);
    }
    if (*token == '(') { // begin of expression?
        (*expression)++;  // skip opening brace
        (*num_tokens)--;

        // lhs
        int lhs = eval_tokens_recursive(expression, num_tokens);

        // operand
        char operand = ***expression;
        (*expression)++;
        (*num_tokens)--;

        // rhs
        int rhs = eval_tokens_recursive(expression, num_tokens);

        (*expression)++;  // skip closing brace
        (*num_tokens)--;

        switch (operand) {
            case '+':
                return lhs + rhs;
            case '-':
                return lhs - rhs;
            case '*':
                return lhs * rhs;
            case '/':
                return lhs / rhs;
            default:
                return 0;
        }

    } else { // not an expression; must be a numeric token
        int operand;
        if (sscanf(token, "%2d", &operand) != 1) {
            printf("expecting numeric value; cannot parse %s.\n", token);
            exit(1);
        }
        (*expression)++;
        (*num_tokens)--;
        return operand;
    }

}

int eval_tokens(char** expression, int num_tokens) {
    return eval_tokens_recursive(&expression, &num_tokens);
}

int main() {

    char *expressions[] = {"(", "9", "+", "(", "50", "-", "25", ")", ")"};

    int result = eval_tokens(expressions, 9);

    printf("result: %d\n", result);

}

【讨论】:

  • 只是出于好奇,是否可以在没有辅助函数的情况下完成同样的事情?如果是这样,代码长度或函数内语句的复杂性是否有任何显着差异?
  • 我不这么认为,因为我看不到如何传回已处理的项目数量。关于代码长度/复杂性,引入一个辅助函数不会有任何重要意义。
猜你喜欢
  • 1970-01-01
  • 2019-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-01
  • 2021-08-18
相关资源
最近更新 更多