|
楼主 |
发表于 2006-4-28 13:28:25
|
显示全部楼层
- /* infix calculator version 0.1.3 #20060428
- * by 419Labs
- * kikistar.com@gmail.com
- * http://my.opera.com/419/
- *
- * References:
- * 1.[K&R] The C Programming Language (second edition)
- * 影印版 ISBN 7-302-02412-X/TP.1214
- * 2.[Mark Allen Weiss] Data Structures and Algorithm Analysis in C
- (second edition) 中文版 ISBN 7-111-12748-X
- * 3.[严蔚敏 吴伟民] 数据结构(C语言版) ISBN 7-900643-22-2
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #define MAXOP 100
- #define NUMBER '0' // signal that a number was found
- #define EMPTY 0
- enum Optype { ND, TOR }; // ND for operand, TOR for operator
- union Era
- {
- double nd; // op.era.nd
- char tor; // op.era.tor
- };
- struct Op
- {
- int max;
- int top;
- enum Optype type;
- union Era *era;
- };
- struct Op *create_stack(int max, enum Optype);
- void push(union Era, struct Op *);
- union Era pop(struct Op *);
- void nullerr(void);
- int getop(char []);
- double operate(struct Op *opnd, struct Op *optor);
- void print_stack(struct Op *op);
- char top_tor(struct Op *);
- int
- main()
- {
- int c;
- char s[MAXOP];
- union Era era;
- struct Op *opnd;
- struct Op *optor;
- opnd = create_stack(MAXOP, ND);
- optor = create_stack(MAXOP, TOR);
- printf(" 本程序可进行“加减乘除(+ - * /)”四则混合运算。\n");
- printf(" 输入 q 或按 Ctrl+D 退出程序。\n");
- printf(" 输入算式后按回车即可算出答案:\n\n");
- while ((c = getop(s)) != EOF) {
- switch (c) {
- case NUMBER:
- if (opnd->top > optor->top + 1) { // 如果是逆波兰算式
- printf("\tparse error\n");
- while (getchar() != '\n')
- /*void*/;
- opnd->top = EMPTY;
- era.nd = 0.0;
- }
- else
- era.nd = atof(s);
- push(era, opnd);
- break;
- case '+': // + 和 - 优先级最低,把除了 '(' 以外的全部操作符弹出后入栈
- case '-':
- if (optor->top == EMPTY) {
- era.tor = c;
- push(era, optor);
- }
- else {
- while (optor->top > EMPTY)
- if (top_tor(optor) == '(')
- break;
- else {
- era.nd = operate(opnd, optor);
- push(era, opnd);
- }
- era.tor = c;
- push(era, optor);
- }
- break;
- case '*': // 乘除优先级最高,把相同优先级的乘和除弹出后入栈
- case '/':
- if (optor->top == EMPTY) {
- era.tor = c;
- push(era, optor);
- }
- else {
- while (optor->top > EMPTY)
- if (((era.tor = top_tor(optor)) == '+')
- || (era.tor == '-')
- || (era.tor == '('))
- break;
- else {
- era.nd = operate(opnd, optor);
- push(era, opnd);
- }
- era.tor = c;
- push(era, optor);
- }
- break;
- case '(': // '(' 不作运算,直接放入optor栈。
- era.tor = c;
- push(era, optor);
- break;
- case ')': // 把 '(' 之前的全部操作符弹出,计算后把 '(' 也弹出
- while (optor->top > EMPTY)
- if (top_tor(optor) == '(')
- break;
- else {
- era.nd = operate(opnd, optor);
- push(era, opnd);
- }
- pop(optor);
- break;
- case '\n': // 把余下的操作符全部弹出,计算后输出结果
- if (opnd->top == EMPTY)
- /*do nothing*/;
- else
- while (optor->top > EMPTY)
- if (top_tor(optor) == '(')
- pop(optor);
- else {
- era.nd = operate(opnd, optor);
- push(era, opnd);
- }
- era = pop(opnd);
- printf("\t%.8g\n", era.nd);
- break;
- case 'p':
- print_stack(opnd);
- getchar();
- break;
- case 'q':
- exit(0);
- break;
- default:
- printf("error: unknown command %s\n", s);
- break;
- }
- }
- return 0;
- }
- struct Op *create_stack(int max, enum Optype type)
- {
- struct Op *op;
- op = malloc(sizeof(*op));
- if (op == NULL)
- nullerr();
- op->era = calloc(sizeof(union Era), max);
- if (op->era == NULL)
- nullerr();
- op->max = max;
- op->top = EMPTY;
- op->type = type;
- return op;
- }
- void
- push(union Era era, struct Op *op)
- {
- if (op->top >= op->max) {
- if (op->type == ND)
- printf("error: stack full, can't push %g\n", era.nd);
- else
- printf("error: stack full, can't push %c\n", era.tor);
- }
- else
- op->era[op->top++] = era;
- }
- union Era
- pop(struct Op *op)
- {
- if (op->top > EMPTY)
- return op->era[--op->top];
- else {
- printf("error: stack empty\n");
- if (op->type == ND)
- op->era[EMPTY].nd = 0.0;
- else
- op->era[EMPTY].tor = 0;
- return op->era[EMPTY];
- }
- }
- void nullerr(void)
- {
- printf("not enough memory\n");
- exit(1);
- }
- int getop(char s[]) // [K&R] section 4.3
- {
- int i, c;
- while ((s[0] = c = getchar()) == ' ' || c == '\t')
- /*do nothing*/;
- s[1] = '\0';
- if (!isdigit(c) && c != '.')
- return c; // not a number
- i = 0;
- if (isdigit(c)) // collect integer part
- while (isdigit(s[++i] = c = getchar()))
- ;
- if (c == '.') // collect fraction part
- while (isdigit(s[++i] = c = getchar()))
- /*do nothing*/;
- s[i] = '\0';
- if (c != EOF)
- ungetc(c, stdin);
- return NUMBER;
- }
- double operate(struct Op *opnd, struct Op *optor)
- {
- union Era nd1, nd2, tor;
- nd2 = pop(opnd);
- nd1 = pop(opnd);
- tor = pop(optor);
- switch (tor.tor) {
- case '+':
- return nd1.nd + nd2.nd;
- break;
- case '-':
- return nd1.nd - nd2.nd;
- break;
- case '*':
- return nd1.nd * nd2.nd;
- break;
- case '/':
- return nd1.nd / nd2.nd;
- break;
- default:
- return 0.0;
- break;
- }
- }
- void print_stack(struct Op *op)
- {
- int i;
- for (i = op->top; i > 0; i--)
- printf("%g\n", op->era[i].nd);
- }
- char top_tor(struct Op *op)
- {
- return op->era[op->top-1].tor; // after push, top plus one
- }
复制代码 |
|