运用栈把算术表达式+,-,*,/,%(中缀表达式)转换成后缀表达式并且计算出值
原理:
1.首先判断是数值还是符号,如果是数值放进字符数组以#表示结束,
2.如果是符号,放进栈,
3.每个符号之间要比较优先级,如果栈顶符号优先级低,符号进栈,如果相等(即“(” “)”)出栈,栈顶符号优先级高,栈顶元素出栈进入字符数组,得到后缀表达式
4.计算后缀表达式,判断是数字还是符号。直到遇到符号,将前面的数字计算后放进栈,一直重复,知道“\0”
代码(局限用整数,因为有模运算,若要任何类型的代码,我的blog有)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <iostream> 4 using namespace std; 5 #define MaxOp 100 6 #define MaxSize 100 7 struct //设定运算符优先级 8 { 9 char ch; //运算符 10 int pri; //优先级 11 } 12 lpri[]= {{'=',0},{'(',1},{'*',5},{'/',5},{'%',5},{'+',3},{'-',3},{')',6}}, 13 rpri[]= {{'=',0},{'(',6},{'*',4},{'/',4},{'%',4},{'+',2},{'-',2},{')',1}}; 14 int leftpri(char op) //求左运算符op的优先级 15 { 16 int i; 17 for (i=0; i<MaxOp; i++) 18 if (lpri[i].ch==op) 19 return lpri[i].pri; 20 } 21 int rightpri(char op) //求右运算符op的优先级 22 { 23 int i; 24 for (i=0; i<MaxOp; i++) 25 if (rpri[i].ch==op) 26 return rpri[i].pri; 27 } 28 bool InOp(char ch) //判断ch是否为运算符 29 { 30 if (ch=='(' || ch==')' || ch=='+' || ch=='-' 31 || ch=='*' || ch=='/'||ch=='%') 32 return true; 33 else 34 return false; 35 } 36 int Precede(char op1,char op2) //op1和op2运算符优先级的比较结果 37 { 38 if (leftpri(op1)==rightpri(op2)) 39 return 0; 40 else if (leftpri(op1)<rightpri(op2)) 41 return -1; 42 else 43 return 1; 44 } 45 void trans(char *exp,char postexp[]) 46 //将算术表达式exp转换成后缀表达式postexp 47 { 48 struct 49 { 50 char data[MaxSize]; //存放运算符 51 int top; //栈指针 52 } op; //定义运算符栈 53 int i=0; //i作为postexp的下标 54 op.top=-1; 55 op.top++; //将'='进栈 56 op.data[op.top]='='; 57 while (*exp!='\0') //exp表达式未扫描完时循环 58 { 59 if (!InOp(*exp)) //为数字字符的情况 60 { 61 while (*exp>='0' && *exp<='9') //判定为数字 62 { 63 postexp[i++]=*exp; 64 exp++; 65 } 66 postexp[i++]='#'; //用#标识一个数值串结束 67 } 68 else //为运算符的情况 69 switch(Precede(op.data[op.top],*exp)) 70 { 71 case -1: //栈顶运算符的优先级低:进栈 72 op.top++; 73 op.data[op.top]=*exp; 74 exp++; //继续扫描其他字符 75 break; 76 case 0: //只有括号满足这种情况 77 op.top--; //将(退栈 78 exp++; //继续扫描其他字符 79 break; 80 case 1: //退栈并输出到postexp中 81 postexp[i++]=op.data[op.top]; 82 op.top--; 83 break; 84 } 85 } //while (*exp!='\0') 86 while (op.data[op.top]!='=') 87 //此时exp扫描完毕,退栈到'='为止 88 { 89 postexp[i++]=op.data[op.top]; 90 op.top--; 91 } 92 postexp[i]='\0'; //给postexp表达式添加结束标识 93 } 94 95 float compvalue(char exp[]) //计算后缀表达式的值 96 { 97 struct 98 { 99 int data[MaxSize]; //存放数值 100 int top; //栈指针 101 } st; //定义数值栈 102 float d; 103 char ch; 104 int t=0; //t作为exp的下标 105 st.top=-1; 106 ch=exp[t]; 107 t++; 108 while (ch!='\0') //exp字符串未扫描完时循环 109 { 110 switch (ch) 111 { 112 case'+': 113 st.data[st.top-1]=st.data[st.top-1]+st.data[st.top]; 114 st.top--; 115 break; 116 case '-': 117 st.data[st.top-1]=st.data[st.top-1]-st.data[st.top]; 118 st.top--; 119 break; 120 case '*': 121 st.data[st.top-1]=st.data[st.top-1]*st.data[st.top]; 122 st.top--; 123 break; 124 case '%': 125 st.data[st.top-1]=st.data[st.top-1]%st.data[st.top]; 126 st.top--; 127 break; 128 case '/': 129 if (st.data[st.top]!=0) 130 st.data[st.top-1]=st.data[st.top-1]/st.data[st.top]; 131 else 132 { 133 printf("\n\t除零错误!\n"); 134 exit(0); //异常退出 135 } 136 st.top--; 137 break; 138 default: 139 d=0; //将数字字符转换成数值存放到d中 140 while (ch>='0' && ch<='9') //为数字字符 141 { 142 d=10*d+ch-'0'; 143 ch=exp[t]; 144 t++; 145 } 146 st.top++; 147 st.data[st.top]=d; 148 } 149 ch=exp[t]; 150 t++; 151 } 152 return st.data[st.top]; 153 } 154 155 int main() 156 { 157 int i=0; 158 char exp[10]; 159 printf("请输入数学表达式:"); 160 scanf("%s",exp); 161 char postexp[MaxSize]; 162 trans(exp,postexp); 163 printf("中缀表达式:%s\n",exp); 164 printf("后缀表达式:%s\n",postexp); 165 printf("表达式的值:%g\n",compvalue(postexp)); 166 return 0; 167 }
博客园的文章都是大学时写的,质量不太好。
我的新文章都会发布再新的 blog :https://blog.biyongyao.com
请大家关注哟!!