简易计算器重制版,原版.
修复:区分不了运算符和数字的 bug。
待完善:支持负数运算。
#include <stdio.h>
#define MAX_LENG 100
double calc(char str[]);
void rpn(char str[], char rpn[]);
int isDigit(char c);
int isOperator(char c);
double atof(char s[]);
double peek();
void push(double n);
double pop();
int compare(char c1, char c2);
int type(char c);
int main() {
printf("%.6f", calc("3.3 * (3 + 9) - 12"));
}
double calc(char str[]) {
int i, j, c;
double temp, a, b;
char num[MAX_LENG];
char rpn_expre[MAX_LENG];
rpn(str, rpn_expre);
for (i = 0; rpn_expre[i] != '\0'; i++) {
num[0] = c = rpn_expre[i];
j = 0;
if (c == ' ' || c == '\t') {
continue;
}
if (isDigit(c)) {
while (isDigit(num[++j] = c = rpn_expre[++i])) {}
if (c == '.') {
while (isDigit(num[++j] = c = rpn_expre[++i])) {}
}
num[j] = '\0';
push(atof(num));
i--;
continue;
}
switch (c) {
case '+':
push(pop() + pop());
break;
case '-':
temp = pop();
push(pop() - temp);
break;
case '*':
push(pop() * pop());
break;
case '/':
temp = pop();
if (temp == 0.0) {
printf("error: zero divisor\n");
} else {
push(pop() / temp);
}
break;
case '%':
b = pop();
a = pop();
if (b == 0.0) {
printf("error: zero divisor\n");
} else {
push(a - (int)(a/b) * b);
}
break;
default:
printf("error: unknown operator %c\n", c);
break;
}
}
return pop();
}
void rpn(char str[], char rpn[]) {
int i, j, c;
for (i = j = 0; str[i] != '\0'; i++) {
rpn[j] = c = str[i];
// 跳过空格
if (c == ' ' || c == '\t') {
continue;
}
// 读取数字填充到 rpn
if (isDigit(c)) {
while (isDigit(rpn[++j] = c = str[++i])) {}
if (c == '.') {
while (isDigit(rpn[++j] = c = str[++i])) {}
}
rpn[j++] = ' ';
rpn[j] = '\0';
i--;
continue;
}
// 读取运算符填充到 rpn
if (c == ')') {
while ((rpn[j] = pop()) != '(') {j++;};
} else if (c == '(') {
push(c);
} else if (isOperator(c)) {
if (peek() == '(' || peek() == 0.0) {
push(c);
} else if (compare(c, peek()) > 0) {
push(c);
} else {
while (peek() != 0.0 && peek() != '(') {
rpn[j++] = pop();
}
push(c);
}
} else {
printf("error: unknown operator %c\n", c);
}
rpn[j] = '\0';
}
// 栈中元素全部出栈,填充到 rpn
while ((rpn[j] = pop()) != 0.0) {j++;};
rpn[j] = '\0';
}
int isDigit(char c) {
return c >= '0' && c <= '9';
}
int isOperator(char c) {
switch (c) {
case '+' :
case '-' :
case '*' :
case '/' :
case '%' :
return 1;
}
return 0;
}
double atof(char s[]) {
int sign = 1;
int i = 0;
switch (s[0]) {
case '-':
sign = -1;
i = 1;
break;
case '+':
i = 1;
break;
}
double n = 0.0;
while (s[i] >= '0' && s[i] <= '9') {
n = 10 * n + (s[i] - '0');
i++;
}
if (s[i] == '.') {
i++;
}
double power = 1.0;
while (s[i] >= '0' && s[i] <= '9') {
n = 10 * n + (s[i] - '0');
i++;
power *= 10;
}
return sign * n/power;
}
int size = 0;
double val[MAX_LENG];
double peek() {
if (size > 0) {
return val[size-1];
} else {
printf("error: stack empty\n");
return 0.0;
}
}
void push(double n) {
if (size < MAX_LENG) {
val[size++] = n;
} else {
printf("errof: stack full, can't push %g\n", n);
}
}
double pop() {
if (size > 0) {
return val[--size];
} else {
printf("error: stack empty\n");
return 0.0;
}
}
int compare(char c1, char c2) {
return type(c1) - type(c2);
}
int type(char c) {
switch (c) {
case '+':
case '-':
return 0;
case '*':
case '/':
case '%':
return 1;
default:
printf("error: unknown operator %c\n", c);
return -1;
}
}