Это не ответ.Просто чтобы показать, что это не так сложно:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
typedef struct expr_s {
char op;
struct expr_s *exprA, *exprB;
float value;
} expr;
int readExpr(expr *node, int argc, char *argv[]) {
int argn = 1;
assert(argc > 0);
switch(argv[0][0]) {
case '0' ... '9':
case '-': case '.':
node->op = '#'; // direct value
node->value = atof(argv[0]);
return 1;
case 'x':
if (argv[0][1] == '\0') { // variable
node->op = 'x';
return 1;
}
break;
default: ;
}
// binary expr
if (strcmp(argv[0], "mul") == 0) node->op = '*';
else if (strcmp(argv[0], "add") == 0) node->op = '+';
else if (strcmp(argv[0], "div") == 0) node->op = '/';
else if (strcmp(argv[0], "sub") == 0) node->op = '-';
else abort();
node->exprA = (expr*)malloc(sizeof(expr));
node->exprB = (expr*)malloc(sizeof(expr));
argn += readExpr(node->exprA, argc-argn, argv+argn);
argn += readExpr(node->exprB, argc-argn, argv+argn);
return argn;
}
float evalExpr(expr *node, float x) {
switch(node->op) {
case '#': return node->value;
case 'x': return x;
case '*': return (evalExpr(node->exprA, x) * evalExpr(node->exprB, x));
case '+': return (evalExpr(node->exprA, x) + evalExpr(node->exprB, x));
case '/': return (evalExpr(node->exprA, x) / evalExpr(node->exprB, x));
case '-': return (evalExpr(node->exprA, x) - evalExpr(node->exprB, x));
default: abort();
}
}
int main(int argc, char *argv[]) {
expr rootExpr;
float x;
readExpr(&rootExpr, argc-1, argv+1);
for(x=0; x < 5; x+=0.5) {
printf("f(%f) = %f\n", x, evalExpr(&rootExpr, x));
}
return 0;
}
Rusult:
./playground div 2 add 2 mul 2 x
f(0.000000) = 1.000000
f(0.500000) = 0.666667
f(1.000000) = 0.500000
f(1.500000) = 0.400000
f(2.000000) = 0.333333
f(2.500000) = 0.285714
f(3.000000) = 0.250000
f(3.500000) = 0.222222
f(4.000000) = 0.200000
f(4.500000) = 0.181818
Обратите внимание, что если вы будете использовать обратную польскую запись, вы увидите почти то же самое,но со стеком expr
вместо, если последующий вызов readExpr
.