C语言编程—中缀表达式转换为后缀表达式
思路:
中缀转后缀保存结果栈:stack,保存数据和+-*/
操作符栈:op_stack,保存+-*/()
场景一:遇到数据,直接入栈stack
场景二:遇到"("直接入栈op_stack,遇到")"将栈中左括号之后入栈的运算符全部出栈,输出到保存操作数的栈中stack,同时左括号出栈但丢弃。
场景三:遇到乘号和除号直接入栈op_stack,直到遇到优先级比他更低的运算符,依次出栈op_stack->入栈stack。
场景四:遇到加号和减号,如果此时op_stack栈空,则直接入栈,否则,将栈中优先级高的运算符依次弹栈(注意:加号和减号属于同一个优先级,所以也依次弹栈)直到栈空或则遇到左括号为止,停止弹栈。(因为左括号要匹配右括号时才弹出)。
场景五:扫描完字符串字符后,如果op_stack栈不为空,将op_stack栈中的操作符依次弹出->入栈stack。
例1:34*(23-(1+23)*4-324)中缀转后缀表达式
34*(23-(1+23)*4-324)对应的后缀表达式:suffix=34 23 1 23 + 4 * - 324 - *,计算结果:-13498
例2:34*(23-(1+23)*4-324)*(23-32*(23-324)/(34+34)) 中缀转后缀表达式
在例1的基础上加上*(23-32*(23-324)/(34+34))
34*(23-(1+23)*4-324)*(23-32*(23-324)/(34+34))对应的后缀表达式:
suffix=34 23 1 23 + 4 * - 324 - 23 32 23 324 - 34 34 + / * - * *
例3:34*(23-(1+23)*4-324)*(23-32*(23-324)/(34+34))/(43-45*343)中缀转后缀表达式
34*(23-(1+23)*4-324)*(23-32*(23-324)/(34+34))/(43-45*343)中缀转后缀:
suffix=34 23 1 23 + 4 * - 324 - 23 32 23 324 - 34 34 + / * - 43 45 343 * - / * *
C语言实现代码:待实现
/*
* calculator.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define false 0
#define true 1
typedef int bool;
bool isOperator(char c)
{
return (c == '+' || c == '-' || c == '*' || c == '/');
}
bool isOperand(char c)
{
return (c >= '0' && c <= '9');
}
bool isValidExpression(char* exp, int len)
{
int parenthesesCount = 0;
for (int i = 0; i < len; i++)
{
if (isOperand(exp[i]))
{
while (i < len && isOperand(exp[i]))
{
i++;
}
i--;
}
else if(exp[i] == '.')
{
if(!isOperand(exp[i - 1]) || !isOperand(exp[i + 1])) return false;
}
else if (isOperator(exp[i]))
{
if (i == 0 || (i == len - 1)) return false;
if ((!isOperand(exp[i - 1]) && exp[i - 1] != ')')
|| (!isOperand(exp[i + 1]) && exp[i + 1] != '(')) return false;
}
else if (exp[i] == '(')
{
parenthesesCount++;
if (i == len - 1) return false;
}
else if (exp[i] == ')')
{
parenthesesCount--;
if (parenthesesCount < 0) return false;
}
else
{
return false;
}
}
return parenthesesCount == 0;
}
double calculate(double num1, double num2, char op)
{
switch(op)
{
case '+':
return num1 + num2;
case '-':
return num1 - num2;
case '*':
return num1 * num2;
case '/':
return (num2 != 0) ? num1 / num2 : 0;
}
return 0;
}
int AdjustExpression(char *expIn, int len, char *expOut)
{
int num = 0;
for(int i = 0; i < len; i++)
{
if(strchr("+-*/()0123456789.", expIn[i])) expOut[num++] = expIn[i];
}
return num;
}
double CalcExpression(char *expression)
{
int len = strlen(expression);
char *exp = (char *)malloc(len * sizeof(char));
memset(exp, 0x00, len * sizeof(char));
len = AdjustExpression(expression, len, exp);
if(!isValidExpression(exp, len)) return 0;
char *operatorStack = (char *)malloc(len * sizeof(char));
int operatorTop = -1;
double *operand = (double *)malloc(len * sizeof(double));
int operandTop = -1;
for(int i = 0; i < len; i++)
{
if(isOperand(exp[i]))
{
double div = 1.0, num = 0;
bool dot = false;
while(i < len && strchr("0123456789.", exp[i]))
{
if(exp[i] == '.')
{
dot = true;
i++;
}
div = dot ? div * 10 : div;
num = num * 10 + exp[i] - '0';
i++;
}
operand[++operandTop] = num / div;
i--;
}
else if(exp[i] == '(')
{
operatorStack[++operatorTop] = exp[i];
}
else if(exp[i] == ')')
{
while(operatorTop >= 0 && operatorStack[operatorTop] != '(')
{
double num2 = operand[operandTop--];
double num1 = operand[operandTop--];
char operator = operatorStack[operatorTop--];
operand[++operandTop] = calculate(num1, num2, operator);
}
if(operatorTop >= 0 && operatorStack[operatorTop] == '(') operatorTop--;
}
else if(strchr("+-", exp[i]))
{
while(operatorTop >= 0 && strchr("+-", operatorStack[operatorTop]))
{
double num2 = operand[operandTop--];
double num1 = operand[operandTop--];
char operator = operatorStack[operatorTop--];
operand[++operandTop] = calculate(num1, num2, operator);
}
operatorStack[++operatorTop] = exp[i];
}
else if(strchr("*/", exp[i]))
{
while(operatorTop >= 0 && strchr("*/", operatorStack[operatorTop]))
{
double num2 = operand[operandTop--];
double num1 = operand[operandTop--];
char operator = operatorStack[operatorTop--];
operand[++operandTop] = calculate(num1, num2, operator);
}
operatorStack[++operatorTop] = exp[i];
}
}
while(operatorTop >= 0)
{
double num2 = operand[operandTop--];
double num1 = operand[operandTop--];
char operator = operatorStack[operatorTop--];
operand[++operandTop] = calculate(num1, num2, operator);
}
double result = operand[operandTop];
free(operatorStack);
free(operand);
free(exp);
return result;
}
typedef struct TestCaseSetCalc{
char str[100];
double expValue;
}TestCaseSetCalc;
TestCaseSetCalc testcaseCalc[] = {
{"1.0+1.0",2},
{"1.0*1.0",1},
{"1.1+1.2",2.3},
{"((1.0+2.0)*3.0)",9},
{"((1+2)*3)",9},
{"((1+2)*(1-2))",-3},
{"((1+2)*(1+2)/3)",3},
{"1",1},
{"(1)",1},
{"1+1",2},
{"(1+1)",2},
{"(3+2)-5",0},
{"(3+2)-(5+5)",-5},
{"(3+2)*5",25},
{"1*1",1},
{"(1)*(1)",1},
{"(1)*(1+1)",2},
{"(1+(4+5+2)-3)+(6+8)",23},
};
void CalcExpression_test()
{
int caseNum = sizeof(testcaseCalc) / sizeof(testcaseCalc[0]);
int flag[100] = {0};
for(int i =0; i < caseNum; i++)
{
double ret = CalcExpression(testcaseCalc[i].str);
printf("CalcExpression ret %lf, exp %lf\n", ret, testcaseCalc[i].expValue);
if(ret != testcaseCalc[i].expValue)
{
flag[i]++;
printf("CalcExpression erro idx %d\n", i);
}
}
printf("CalcExpression OK\n");
}
int main()
{
CalcExpression_test();
return 0;
}