#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <conio.h>
#define N 10
struct stack {
void *data;
int top;
};
struct Calculator {
struct stack *number;
struct stack *op;
};
struct stack *newStack(int n, int size) {
struct stack *s;
s = (struct stack*)malloc(sizeof(struct stack));
s->top = -1;
s->data = malloc(size * n);
return s;
}
void deleteStack(struct stack *s)
{
free(s->data);
free(s);
}
struct Calculator *newCalculator()
{
struct Calculator *cal;
cal = (struct Calculator *)malloc(sizeof(Calculator));
cal->number = newStack(N, sizeof(int));
cal->op = newStack(N, sizeof(char));
return cal;
}
void freeCalculator(struct Calculator *cal)
{
deleteStack(cal->number);
free(cal->op);
free(cal);
}
// 操作数的栈操作
int pushint(struct stack *s, int number)
{
if(s->top >= N-1)
return -1;
((int *)(s->data))[++s->top] = number;
return number;
}
int popint(struct stack *s)
{
if(s->top == -1)
return -1;
return(((int *)(s->data))[s->top--]);
}
// 操作符的栈操作
int pushchar(struct stack *s, char c)
{
if(s->top >= N-1)
return -1;
((char *)(s->data))[++s->top] = c;
return c;
}
char popchar(struct stack *s)
{
if(s->top == -1)
return -1;
return(((char *)(s->data))[s->top--]);
}
char topchar(struct stack *s)
{
if(s->top == -1)
return '\0';
return ((char *)(s->data))[s->top];
}
// 计算加减乘除运算
int calc(int n1, int n2, char op, int *result)
{
switch(op) {
case '+': *result = n1 + n2; break;
case '-': *result = n1 - n2; break;
case '*': *result = n1 * n2; break;
case '/': *result = n1 / n2; break;
default: return 0;
}
return 1;
}
int getnumber(char *expression, int *n)
{
int i=0, flag=0;
*n = 0;
if(expression[i] == '-') // 负数
{
flag = 2;
i ++;
}
while(expression[i] >= '0' && expression[i]<='9') {
*n = *n * 10 + expression[i] - '0';
i ++;
flag |= 1;
}
if(flag & 2)
*n *= -1;
if(flag & 1 == 0)
return 0;
return i;
}
// 获得字符串中的操作符
int getop(char *expression, char *op)
{
int i = 0;
if(expression[i] == '+' || expression[i] == '-' || expression[i] == '*' || expression[i] == '/' || expression[i] == '\0')
*op = expression[i++];
else
return 0;
return i;
}
// 找是否有左括号
int getLeftParentheses(char *expression)
{
int i = 0;
if(expression[i] == '(')
i++;
else
return 0;
return i;
}
// 找是否有右括号
int getRightParentheses(char *expression)
{
int i = 0;
if(expression[i] == ')')
i++;
else
return 0;
return i;
}
// 获得操作符的优先级
int get_priority(char op)
{
switch(op) {
case ')': return 0;
case '(': return 0;
case '+': return 1;
case '-': return 1;
case '*': return 2;
case '/': return 2;
default: return -1;
}
}
int isOperator(char op)
{
if(op == '+' || op == '-' || op == '*' || op == '/' || op == '\0')
return 1;
return 0;
}
// 比较操作符的优先级
int compare_priority(struct stack *op, char op2)
{
if(op->top == -1)
return 0;
if(get_priority(topchar(op)) >= get_priority(op2))
return 1;
return 0;
}
// 解析表达式,并且计算结果(flag = 0)或者生成二叉树表达式(flag = 1)
int exec(struct Calculator *cal, char *expression, int *result)
{
struct stack *number, *op;
int len, n;
char c;
number = cal->number;
op = cal->op;
while(expression[0] == '(') {
// 第一个字符是左括号,将左括号压入运算符栈中,处理表达式的下一个字符
expression ++;
pushchar(op, '(');
}
len = getnumber(expression, &n);
if(len == 0) {
return 0;
}
expression += len;
pushint(number, n);
do {
while(expression[0] == ')') {
expression ++;
do { // 将运算符栈中最顶端左括号之上的运算符进行计算
if(topchar(op) == 0) {
return 0;
}
if(topchar(op) == '(') {
popchar(op);
break;
}
else {
if(calc(popint(number), popint(number), popchar(op), result) == 0)
return 0;
pushint(number, *result);
}
} while(1);
}
// 取得下一个运算符
len = getop(expression, &c);
if(c == 0) // 读到表达式结尾
break;
if(len == 0) {
return 0;
}
expression += len;
while(compare_priority(op, c) > 0) { // 如果预算符栈中的运算符优先级高于当前运算符,则对栈中的运算符进行计算,并将计算结果压入操作数栈中
if(calc(popint(number), popint(number), popchar(op), result) == 0)
return 0;
pushint(number, *result);
}
pushchar(op, c);
// 如果取下一个操作数时遇到左括号
while(expression[0] == '(') {
expression ++;
pushchar(op, '(');
}
// 取得下一个操作数,并压入栈中
len = getnumber(expression, &n);
if(len == 0) {
return 0;
}
expression += len;
pushint(number, n);
} while(expression[0] != '\0');
// 表达式遍历结束,如果栈中还有未处理的运算符,则依次对其进行运算
while(topchar(op) != 0) {
if(calc(popint(number), popint(number), popchar(op), result) == 0) {
return 0;
}
if(topchar(op) != 0)
pushint(number, *result);
}
return 1;
}
// 将表达式中的空白字符去掉,并校验表达式是否正确
int format(char *expression)
{
int i, j, n=0;
// 去除空格或制表符,并检查左右括号的个数是否相同
for(i = 0, j = 0; expression[i] != 0; i++) {
while(expression[i] == ' ' || expression[i] == '\t')
i++;
if(expression[i] == '(') n++;
else if(expression[i] == ')') {
if(--n < 0) //右括号多了
return i;
}
expression[j++] = expression[i];
}
expression[j] = 0;
if(n > 0) // 左括号多了
return i;
for(i = 0; expression[i] != 0; i ++) {
if(expression[i] >= '0' && expression[i] <= '9') { // 操作数后面只能是运算符或右括号
if(!isOperator(expression[i+1]) && expression[i+1] != ')')
return i+1;
}
else if(expression[i] == '(') { // 左括号后面只能是左括号或操作数
if(expression[i+1] != '(' && (expression[i+1] < '0' || expression[i+1] > '9'))
return i+1;
}
else if(expression[i] == ')') { // 右括号后面只能是右括号或运算符
if(expression[i+1] != ')' && !isOperator(expression[i+1]))
return i+1;
}
else if(isOperator(expression[i])) { // 运算符后面只能是操作数或左括号
if((expression[i+1] < '0' || expression[i+1] > '9') && expression[i+1] != '(')
return i+1;
}
}
return 0;
}
main()
{
char expression[100];
int result;
struct Calculator *cal;
cal = newCalculator();
do {
printf("Input a expression: \n");
gets(expression);
result = format(expression);
if(result != 0)
printf("表达式错误,第%d个字符'%c'存在问题\n", result, expression[result]);
else {
if(exec(cal, expression, &result) == 1)
printf("%s = %d\n", expression, result);
else
printf("表达式错误\n");
}
printf("\nContinue? (y/n)\n");
} while(getch() == 'y');
freeCalculator(cal);
}
温馨提示:答案为网友推荐,仅供参考