- 先将中缀转后缀
- 再用后缀求值
- 以下程序中用到全局变量 字符串mys,和长度L来实现记录中缀转为后缀的表达式。
- 中缀转后缀 和 后缀求值可以参考前两篇文章
这里的求值只能针对具体的数字,如果中缀表达式中有未知变量形如a,b,c则无法计算结果
//中缀表达式转后缀表达式
/* 算法步骤:
初始化一个栈,用于保存暂时还不能确定运算顺序的运算符
从左到右处理各个元素,直到末尾,可能遇到三种情况:
4. 遇到操作数,直接加入后缀表达式
5. 遇到界限符,遇到左括号则直接入栈,遇到右括号则依次弹出栈内运算符并加入
后缀表达式,直到弹出左括号为止。注意左括号不加入后缀表达式
3.遇到运算符,依次弹出栈中优先级高于或等于当前运算符的所有运算符,并加入
后缀表达式,若碰到了左括号或栈空则停止,之后再把当前运算符入栈
*/
//栈的顺序存储结构,用静态数组实现
#include<stdio.h>
#include<string.h>
#define MaxSize 40//定义栈中元素的最大个数
#define ElemType int
char mys[50];//后缀字符串
int L=0;//后缀字符串的长度
typedef struct{
ElemType data[MaxSize];//存放栈中的元素
int top;//栈顶指针
}SqStack;//顺序栈
void InitStack(SqStack &s){
s.top=-1;//初始化栈顶指针
}
bool StackEmpty(SqStack s){
return s.top==-1;
}
bool Push(SqStack &s,ElemType x){
if(s.top == MaxSize-1){
printf("overflow\n");
return false;
}
s.data[++s.top]=x;
return true;
}
bool Pop(SqStack &s,ElemType &x){
//先判断栈是否为空
if(!StackEmpty(s)){
x = s.data[s.top--];
return true;
}
}
bool GetTop(SqStack s,ElemType &x){
//先判断栈是否为空
if(!StackEmpty(s)){
x = s.data[s.top];
return true;
}
}
bool DestroyStack(SqStack &s){
s.top=-1;
}
bool PrintStack(SqStack s){
int p=s.top;
if(p==-1){
printf("\n栈空\n");
return false;
}
printf("Stack is :");
while(p!=-1){
printf("%d ",s.data[p--]);
}
printf("\n");
}
bool isDigit(char c){
return (c>='0'&&c<='9');
}
bool isAlpha(char c){
return ((c>='a'&& c<='z')||(c>='A'&&c<='Z'));
}
//输入字符串,和其长度
bool midToSuffix(char str[],int len){
L=0;
SqStack s;
InitStack(s);
char ch;
ElemType topElem='\0';
for(int i=0;i<len;i++){
ch=str[i];
if(isDigit(ch)){
//printf("%c",ch);
sprintf(mys+L,"%c",ch);
L=strlen(mys);
if(!isDigit(str[i+1])){//不是数字的话则输出空格
//printf(" ");
char temp=' ';
sprintf(mys+L,"%c",temp);
L=strlen(mys);
}
continue;
}
if(isAlpha(ch)){//如果是字母的话
//printf("%c ",ch);
sprintf(mys+L,"%c ",ch);
L=strlen(mys);
continue;
}
switch(ch){
//遇到左括号则直接入栈
case '(':
Push(s,ch);break;
case '[':
Push(s,ch);break;
case '{':
Push(s,ch);break;
//遇到右括号,则依次弹出栈内运算符并加入后缀表达式;
case ')':
Pop(s,topElem);
while(topElem!='('){
//printf("%c ",topElem);
sprintf(mys+L,"%c ",topElem);
L=strlen(mys);
Pop(s,topElem);
};
break;
case ']':
Pop(s,topElem);
while(topElem!='['){
Pop(s,topElem);
//printf("%c ",topElem);
sprintf(mys+L,"%c ",topElem);
L=strlen(mys);
};
break;
case '}':
Pop(s,topElem);
while(topElem!='{'){
// printf("%c ",topElem);
sprintf(mys+L,"%c ",topElem);
L=strlen(mys);
Pop(s,topElem);
};
break;
case '+':
GetTop(s,topElem);//获取栈顶元素,这里用GetTop比直接Pop省事甚多
while(!StackEmpty(s) && topElem != '('&& topElem != '['&& topElem != '{'){//栈空
//printf("%c ",topElem);
sprintf(mys+L,"%c ",topElem);
L=strlen(mys);
Pop(s,topElem);//先打印后弹出
GetTop(s,topElem);//@@@
}
Push(s,'+');
break;
case '-':
GetTop(s,topElem);//弹出栈顶元素
//栈中只能是左括号or运算符
//若栈非空,且栈顶元素不是左括号, 对于+-,则无条件pop
while(!StackEmpty(s) && topElem != '('&& topElem != '['&& topElem != '{'){
// printf("%c ",topElem);
sprintf(mys+L,"%c ",topElem);
L=strlen(mys);
Pop(s,topElem);
GetTop(s,topElem);//@@@
//flag++;
}
//当前运算符号入栈
Push(s,'-');
break;
case '*':
GetTop(s,topElem);//弹出栈顶元素
//若栈非空,且栈顶元素不是左括号, 对于*,则只有* / 优先级>= *
while(!StackEmpty(s) && topElem != '('&& topElem != '['&& topElem != '{'){//
if(topElem=='*'||topElem=='/'){//优先级>='*'的出栈
//printf("%c ",topElem);
sprintf(mys+L,"%c ",topElem);
L=strlen(mys);
Pop(s,topElem);
GetTop(s,topElem);//@@@查看下一个栈顶元素是否需要弹出
continue;//@@@
}
break;//若优先级< '*',则直接跳出while
}
Push(s,'*');
break;
case '/':
GetTop(s,topElem);//弹出栈顶元素
//若栈非空,且栈顶元素不是左括号, 对于*,则只有* / 优先级>= /
while(!StackEmpty(s) && topElem != '('&& topElem != '['&& topElem != '{'){
if(topElem=='*'||topElem=='/'){
//printf("%c ",topElem);
sprintf(mys+L,"%c ",topElem);
L=strlen(mys);
Pop(s,topElem);
GetTop(s,topElem);//@@@
continue;
}
break;//若优先级< '/',则直接跳出while
}
//将此运算符入栈
Push(s,'/');
break;
}
}
while(!StackEmpty(s)){
Pop(s,topElem);
//printf("%c ",topElem);
sprintf(mys+L,"%c ",topElem);
L=strlen(mys);
}
return true;
}
int CharToNum(char c){
return (c-'0');
}
//输入后缀表达式字符串,和其长度,求最终结果
int SuffixToSum(char str[],int len){
SqStack s;
InitStack(s);
char ch;
int sum=0;
for(int i=0;i<len;i++){
ch=str[i];
//如果此字符是0~9
if(isDigit(ch)){
sum = sum*10 + CharToNum(ch);
if(str[i+1]==' '){//如果下一个为空格,则说明此数字结束
Push(s,sum);//说明此操作数组合结束,则将操作数入栈
sum=0;//并将sum置零
}
}
else if(ch==' '){//为空格则继续下一个循环
continue;
}
else{//说明是操作数
int x,y,result;
switch(ch){
case '+':
Pop(s,x);Pop(s,y);
result=y+x;break;
case '-':
Pop(s,x);Pop(s,y);
result=y-x;break;
case '*':
Pop(s,x);Pop(s,y);
result=y*x;break;
case '/':
Pop(s,x);Pop(s,y);
result=y/x;break;
}
Push(s,result);//将计算结果重新入栈
}
}
int finalResult;
Pop(s,finalResult);
return finalResult;
}
int main(){
char str0[35]="((15/(7-(1+1)))*3)-(4+(4+8))";
char str1[35]="8+3*5";
printf("中缀表达式: ");
for(int i=0;i<strlen(str0);i++){
printf("%c",str0[i]);
}
printf("\n后缀表达式:");
midToSuffix(str0, strlen(str0));
printf("%s\n",mys);
printf("\n");
int x;
x=SuffixToSum(mys,strlen(mys));
printf("结果为:%d\n",x);
printf("\n*****************************\n\n");
printf("中缀表达式: ");
for(int i=0;i<strlen(str1);i++){
printf("%c",str1[i]);
}
printf("\n后缀表达式:");
midToSuffix(str1, strlen(str1));
printf("%s\n",mys);
printf("\n");
x=SuffixToSum(mys,strlen(mys));
printf("结果为:%d\n",x);
return 0;
}