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的主要内容,如果未能解决你的问题,请参考以下文章