- 论坛徽章:
- 2
|
- /* EXPRESSION CACULATOR */
- #include <ctype.h>
- #include <float.h>
- #include <math.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- int nstr_trim(const char *s, int off, int lmt)
- {
- int i;
- for (i = off; i < lmt; ++i) {
- if (!isspace(s[i])) {
- break;
- }
- }
- return i;
- }
- int nstr_cmp(const char *s, int off, int lmt, const char *tar)
- {
- return strncmp(s + off, tar, strlen(tar));
- }
- int get_oprand(const char *s, int *io_off, int lmt, int *o_offset, int *o_limit, double *o_value)
- {
- int off, limit;
- char *endptr;
- double value;
- off = *io_off;
- off = nstr_trim(s, off, lmt);
- value = strtod(s + off, &endptr);
- if (value < -DBL_EPSILON || value > DBL_EPSILON) {
- if (value > -HUGE_VAL && value < HUGE_VAL) {
- limit = endptr - s;
- if (o_offset != NULL) {
- *o_offset = off;
- }
- if (o_limit != NULL) {
- *o_limit = limit;
- }
- if (o_value != NULL) {
- *o_value = value;
- }
- off = limit;
- *io_off = off;
- return 0;
- }
- }
- return -1;
- }
- int get_operator(const char *s, int *io_off, int lmt, int *o_type)
- {
- int off;
- off = *io_off;
- off = nstr_trim(s, off, lmt);
- if (nstr_cmp(s, off, lmt, "+") == 0) {
- *o_type = 0;
- ++off;
- *io_off = off;
- return 0;
- }else if (nstr_cmp(s, off, lmt, "-") == 0) {
- *o_type = 1;
- ++off;
- *io_off = off;
- return 0;
- }else if (nstr_cmp(s, off, lmt, "*") == 0) {
- *o_type = 2;
- ++off;
- *io_off = off;
- return 0;
- }else if (nstr_cmp(s, off, lmt, "/") == 0) {
- *o_type = 3;
- ++off;
- *io_off = off;
- return 0;
- }
- return -1;
- }
- int get_operator_prefix(const char *s, int *io_off, int lmt, int *o_type)
- {
- int off;
- off = *io_off;
- off = nstr_trim(s, off, lmt);
- if (nstr_cmp(s, off, lmt, "+") == 0) {
- *o_type = 0;
- ++off;
- *io_off = off;
- return 0;
- }else if (nstr_cmp(s, off, lmt, "-") == 0) {
- *o_type = 1;
- ++off;
- *io_off = off;
- return 0;
- }else if (nstr_cmp(s, off, lmt, "(") == 0) {
- *o_type = 4;
- ++off;
- *io_off = off;
- return 0;
- }
- return -1;
- }
- int get_operator_postfix(const char *s, int *io_off, int lmt, int *o_type)
- {
- int off;
-
- off = *io_off;
- off = nstr_trim(s, off, lmt);
- if (nstr_cmp(s, off, lmt, ")") == 0) {
- *o_type = 5;
- ++off;
- *io_off = off;
- return 0;
- }
- return -1;
- }
- int cac_exp(int op, double opd1, double opd2, double *o_value)
- {
- switch (op) {
- case 0:
- *o_value = opd1 + opd2;
- return 0;
- case 1:
- *o_value = opd1 - opd2;
- return 0;
- case 2:
- *o_value = opd1 * opd2;
- return 0;
- case 3:
- *o_value = opd1 / opd2;
- return 0;
- default:
- return -1;
- }
- }
- int try_operator(const char *s, int off, int lmt, int *o_type)
- {
- return get_operator(s, &off, lmt, o_type);
- }
- int compare_op(int op1, int op2)
- {
- op1 >>= 1;
- op2 >>= 1;
- if (op1 < op2) {
- return -1;
- }else if (op1 > op2) {
- return 1;
- }
- return 0;
- }
- /*
- * load_expression returns:
- *
- * 0 ok, o_value store expression's value
- * 1 oh no, lower priviledge
- * -1 error, gramer error
- */
- int load_expression(const char *s, int *io_off, int lmt, int op, double *io_opd)
- {
- int off;
- int type, op2;
- double value;
- int load_operand(const char *s, int *io_off, int lmt, double *o_value);
-
- off = *io_off;
- if (get_operator(s, &off, lmt, &type) == 0) {
- if (load_operand(s, &off, lmt, &value) == 0) {
- if (try_operator(s, off, lmt, &op2) == 0) {
- if (compare_op(op2, type) == 1) {
- if (load_expression(s, &off, lmt, type, &value) == 0) {
- cac_exp(type, *io_opd, value, io_opd);
- if (load_expression(s, &off, lmt, op, io_opd) == 0) {
- *io_off = off;
- return 0;
- }
- }
- }else {
- cac_exp(type, *io_opd, value, io_opd);
- if (load_expression(s, &off, lmt, op, io_opd) == 0) {
- *io_off = off;
- return 0;
- }
- }
- }else {
- cac_exp(type, *io_opd, value, io_opd);
- *io_off = off;
- return 0;
- }
- }
- }else {
- *io_off = off;
- return 0;
- }
- return -1;
- }
- int load_operand(const char *s, int *io_off, int lmt, double *o_value)
- {
- int off;
- int offset, limit;
- int type;
- double value;
- off = *io_off;
- if (get_operator_prefix(s, &off, lmt, &type) == 0) {
- switch (type) {
- case 0:
- if (load_operand(s, &off, lmt, &value) == 0) {
- *o_value = value;
- *io_off = off;
- return 0;
- }
- break;
- case 1:
- if (load_operand(s, &off, lmt, &value) == 0) {
- *o_value = -value;
- *io_off = off;
- return 0;
- }
- break;
- case 4:
- if (load_operand(s, &off, lmt, &value) == 0) {
- if (load_expression(s, &off, lmt, -1, &value) == 0) {
- if (get_operator_postfix(s, &off, lmt, &type) == 0) {
- if (type == 5) {
- *o_value = value;
- *io_off = off;
- return 0;
- }
- }
- }
- }
- break;
- default: /* ERROR: invalid operator */
- break;
- }
- }else if (get_oprand(s, &off, lmt, &offset, &limit, &value) == 0) {
- *o_value = value;
- *io_off = off;
- return 0;
- }
- return -1;
- }
- int caculator(const char *s, double *o_value)
- {
- int off, lmt;
- int type;
- double value;
- off = 0;
- lmt = strlen(s);
- type = -1;
- if (load_operand(s, &off, lmt, &value) == 0) {
- if (load_expression(s, &off, lmt, type, &value) == 0) {
- *o_value = value;
- return 0;
- }
- }
- return -1;
- }
- int main(void)
- {
- char exp_buf[256];
- double value;
- puts("I am an expression caculator.");
- while (puts("Please input an expression: Ctrl-Z to exit")
- , fgets(exp_buf, sizeof(exp_buf), stdin) != NULL) {
- if (caculator(exp_buf, &value) == 0) {
- printf("= %g\n", value);
- }else {
- puts("Oh, It's not a valid expression, Input again.");
- }
- }
- return 0;
- }
复制代码 |
|