c_cpp [JudgeGirl] 65.表达树 - 我在C中首次尝试OOP

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp [JudgeGirl] 65.表达树 - 我在C中首次尝试OOP相关的知识,希望对你有一定的参考价值。

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<ctype.h>
#define VARNAME_LEN 36
#define VARTABLE_LEN 128
#define STACK_LEN 400

typedef struct _varPair {
  int value;
  char name[VARNAME_LEN];
} varPair;

typedef enum { NODE_OP, NODE_VAR, NODE_NUM } nodeType;

typedef struct { nodeType type; } nodeBase;

typedef struct _opNode {
  nodeBase _super;
  char op;
  nodeBase *left, *right;
} nodeOp;

typedef struct _varNode {
  nodeBase _super;
  varPair *var;
} nodeVar;

typedef struct _numNode {
  nodeBase _super;
  int num;
} nodeNum;

// added a bit of error handling inclusive of "assert()"
// some of which can be removed

void printTree(nodeBase* t) {
  static int dep = 0;
  for (int i = 0; i < dep * 2; i++) putchar(' ');
  if (!t) return;

  nodeOp* t_op = (nodeOp*) t;
  varPair* t_varp = ((nodeVar*)t)->var;
  switch (t->type) {
    case NODE_OP:
      printf("[OP] %c", t_op->op);
      if (!t_op->left && !t_op->right) {
        // this should not happen
        printf("*\n");
        return;
      }
      puts("");
      dep++;
      assert(t_op->left  != NULL);
      assert(t_op->right != NULL);
      printTree(t_op->left);
      printTree(t_op->right);
      dep--;
      break;
    case NODE_NUM:
      printf("[NUM] %d\n", ((nodeNum*)t)->num);
      break;
    case NODE_VAR:
      printf("[VAR] %s ", t_varp->name);
      if (t_varp->value < 0)
        printf("[UNASSIGNED]\n");
      else
        printf("%d\n", t_varp->value);
      break;
  }
}

static varPair varTable[VARTABLE_LEN];
static int varcnt;

static varPair* getVar(char* name) {
  for (int i = 0; i < VARTABLE_LEN; i++) {
    if (strcmp(varTable[i].name, name) == 0)
      return &varTable[i];
  }
  return NULL;
}

static nodeBase* lex(char* token) {
  char* fc = token;
  // is always a "positive" integer!!
  if (isdigit(*fc)) {
    nodeNum* node = (nodeNum*) malloc(sizeof(nodeNum*));
    ((nodeBase*)node)->type = NODE_NUM;
    node->num = atoi(token);
    return (nodeBase*) node;
  } else if (isalpha(*fc) || *fc == '_' || *fc == '$') {
    nodeVar* node = (nodeVar*) malloc(sizeof(nodeVar*));
    ((nodeBase*)node)->type = NODE_VAR;
    node->var = getVar(token);
    if (node->var == NULL) {
      assert(varcnt < VARTABLE_LEN);
      node->var = &varTable[varcnt++];
      strcpy(node->var->name, token);
      node->var->value = -1;
    }
    return (nodeBase*) node;
  } else {
    nodeOp* node = (nodeOp*) malloc(sizeof(nodeOp*));
    ((nodeBase*)node)->type = NODE_OP;
    node->op = *fc;
    return (nodeBase*) node;
  }
}

static int yield(nodeBase* t) {
  nodeOp* t_op = (nodeOp*) t;
  switch(t->type) {
    case NODE_NUM:
      return ((nodeNum*)t)->num;
    case NODE_VAR:
      return ((nodeVar*)t)->var->value;
    case NODE_OP:
      switch (t_op->op) {
        case '+': return yield(t_op->left) + yield(t_op->right);
        case '-': return yield(t_op->left) - yield(t_op->right);
        case '*': return yield(t_op->left) * yield(t_op->right);
        case '/': return yield(t_op->left) / yield(t_op->right);
        default: assert(0); return -1;
      }
  }
}

int main() {
  char token[VARNAME_LEN];
  nodeBase* stack[STACK_LEN];
  int top = 0;

  // lexer
  while (scanf("%s", token) != EOF) {
    if (token[0] == '(') {
      // printf("( LBRACE\n");
      // do nothing; take action in the next step (always be an op)
    } else if (token[0] == ')') {
      // link to operator and pop
      // printf(") RBRACE\n");
      assert(top >= 3);
      nodeOp* opNode = (nodeOp*) stack[top - 3];
      assert(((nodeBase*)opNode)->type == NODE_OP);
      opNode->left = stack[top - 2];
      opNode->right = stack[top - 1];
      top -= 2;
      if (top == 1) break;
    } else {
      // will be a node
      // printf("NODE %s\n", token);
      assert(top < STACK_LEN);
      stack[top++] = lex(token);
    }
  };

  printTree(stack[0]);

  // read variables and assign values
  while (scanf("%s", token) != EOF) {
    varPair* varp = getVar(token);
    assert(varp != NULL);

    getchar();  // ' '
    getchar();  // '='
    scanf("%d", &varp->value);
  }

  // check the result
  printTree(stack[0]);

  // compute the result!
  printf("%d\n", yield(stack[0]));
}

以上是关于c_cpp [JudgeGirl] 65.表达树 - 我在C中首次尝试OOP的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp 表达式树 - 中缀到后缀

c_cpp SN65DSI86测试程序

正则表达式 65 CPL 和无分词

c_cpp 子集树与排列树的.cpp

c_cpp C ++中的AVL树实现。自平衡树

c_cpp 线段树