- 论坛徽章:
- 5
|
本帖最后由 starwing83 于 2013-03-17 10:48 编辑
这个是从Lua源代码里面单独抽出来的(思路是Lua的,代码是自己写的),只有你的一半不到,你可以看看(我没有处理空格):- #include <stdio.h>
- #include <stdlib.h>
- #include <setjmp.h>
- #include <math.h>
- typedef enum BinOpr {
- OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW, OP_NON
- } BinOpr;
- static struct { int left, right; } binop_prio[] = {
- {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, {10,9},
- };
- #define UNARY_PRIO 8
- static BinOpr get_binop(const char **s) {
- switch (**s) {
- case '+': ++*s; return OP_ADD;
- case '-': ++*s; return OP_SUB;
- case '*': ++*s; return OP_MUL;
- case '/': ++*s; return OP_DIV;
- case '%': ++*s; return OP_MOD;
- case '^': ++*s; return OP_POW;
- default: return OP_NON;
- }
- }
- static double doexpr(int op, double a, double b) {
- switch (op) {
- case OP_ADD: return a+b;
- case OP_SUB: return a-b;
- case OP_MUL: return a*b;
- case OP_DIV: return a/b;
- case OP_MOD: return a-floor(a/b)*b;
- case OP_POW: return pow(a, b);
- default: return 0;
- }
- }
- typedef struct ExprContext {
- jmp_buf jbuf;
- const char *errmsg, *s;
- BinOpr op;
- } Expr;
- static double error(Expr *e, const char *msg) {
- e->errmsg = msg;
- longjmp(e->jbuf, 1);
- }
- static double expr(Expr *e, int limit) {
- double n;
- BinOpr op;
- if (*e->s == '-') {
- ++e->s;
- n = -expr(e, UNARY_PRIO);
- }
- else if (*e->s == '(') {
- ++e->s;
- n = expr(e, 0);
- if (*e->s++ != ')') error(e, "')' expected");
- }
- else {
- const char *s = e->s;
- n = strtod(s, (char**)&e->s);
- if (e->s == s) error(e, "'number' expected");
- }
- op = get_binop(&e->s);
- while (op != OP_NON && binop_prio[op].left > limit) {
- n = doexpr(op, n, expr(e, binop_prio[op].right));
- op = e->op;
- }
- e->op = op;
- return n;
- }
- double calc(const char *s, const char **perr) {
- Expr e;
- e.s = s;
- e.errmsg = NULL;
- if (setjmp(e.jbuf) == 0) {
- double n = expr(&e, 0);
- if (*e.s != '\n' && *e.s != '\0' && *e.s != '=')
- error(&e, "traling chars detected");
- return n;
- }
- if (perr) *perr = e.errmsg;
- return 0;
- }
- int main(void) {
- char buff[BUFSIZ];
- while (printf("> "), fgets(buff, BUFSIZ, stdin) != NULL) {
- const char *errmsg = NULL;
- double n = calc(buff, &errmsg);
- if (errmsg) printf("ERROR: %s\n", errmsg);
- else printf("%g\n", n);
- }
- return 0;
- }
复制代码 |
|