本文内容:C语言实现并附有相关讲解

    1. 计算中缀表达式
    2. 计算后缀表达式
    3. 计算前缀表达式
    4. 中缀转后缀表达式
    5. 中缀转前缀表达式

    相关链接:

    1. 表达式求值汇总
    2. 多位数表达求值

    【例子】

    表达式 例子
    表达式(中缀) 表达式相关问题 - 图1*2#card=math&code=2%2A3%2B%287-6%2F5%29%2A2&id=lWyFD)
    前缀 表达式相关问题 - 图2
    后缀 表达式相关问题 - 图3

    【计算结果】
    表达式相关问题 - 图4

    【代码】

    1. #include<stdio.h>
    2. #include<string.h>
    3. // 计算
    4. float Cal(float a, char op, float b) {
    5. switch (op) {
    6. case '+' : return (a+b);
    7. case '-' : return (a-b);
    8. case '*' : return (a*b);
    9. case '/' : return (a/b);
    10. }
    11. return 0;
    12. }
    13. /*-----------------------
    14. |计算中缀表达式 |
    15. -----------------------*/
    16. /*
    17. 数据结构:两个栈,一个存放操作数(stack1),一个存放运算符(stack2)
    18. 操作步骤:
    19. 1. 从左到右扫描中缀表达式
    20. 若是数字,直接入stack1
    21. 若是字符:
    22. 若运算符栈为空,直接入栈stack2
    23. 若栈不为空,则要与stack2的栈顶的优先级进行比较
    24. 若当前字符为左括号,则压入stack2栈中
    25. 若当前字符为右括号,则从stack2中取出运算符,再从stack1栈中取出两个数字进行运算,运算结果压入stack1中;直到栈顶元素为左括号,将左括号弹出即可(即右括号与左括号做抵消)
    26. 若当前字符的优先级小于栈顶,则将栈顶元素抛出,从操作数栈中取两个数字进行运算,运算结果压入操作数栈。继续判断此字符与栈顶元素优先级大小,直到栈顶元素优先级小于此字符
    27. 若当前字符的优先级大于栈顶,则将此字符直接压入运算符栈中
    28. 2. 最后,若栈中还有元素,取出继续计算
    29. 函数:
    30. 1. CalInfix(str[]):传入中缀表达式,返回计算结果
    31. 2. Cal_from_stack12:上述步骤中,重复的操作即是从stack1中取操作数,stack2中取运算符进行运算,最后将结果压入stack1中。因此将这些操作封装成函数简化代码,增加可读性
    32. */
    33. float Cal_from_stack12(float stack1[], int &top1, char stack2[], int &top2) {
    34. // stack1为数字的栈、stack2为运算符的栈
    35. // 从两个栈中计算
    36. char op = stack2[top2--];
    37. float b = stack1[top1--];
    38. float a = stack1[top1--];
    39. float ret = Cal(a, op, b);
    40. stack1[++top1] = ret;
    41. return ret;
    42. }
    43. float CalInfix(char str[]) { //计算中缀表达式
    44. float stack1[100]; int top1=-1; //存放数字的栈
    45. char stack2[100]; int top2=-1; //存放运算符的栈
    46. int i;
    47. // 遍历中缀表达式
    48. for (i=0; str[i]!='\0'; ++i) {
    49. // str[i]是数字,直接入栈,后退出此次循环
    50. if (str[i]<='9' && str[i]>='0') { // str[i]数字
    51. stack1[++top1]=(float)(str[i]-'0');
    52. continue;
    53. }
    54. //str[i]是字符(运算符)
    55. // 运算符的栈为空,直接入栈
    56. if (top2==-1) {
    57. stack2[++top2] = str[i];
    58. continue;
    59. }
    60. // 运算符的栈不为空,要比较和栈顶的优先级
    61. if (str[i]=='+' || str[i]=='-') { // 当前运算符为+、-,那么比+、-、*、/优先级都小,所以要让它们都先计算完才能入栈
    62. while (stack2[top2]=='+' || stack2[top2]=='-' || stack2[top2]=='*' || stack2[top2]=='/') {
    63. Cal_from_stack12(stack1, top1, stack2, top2); //计算
    64. }
    65. stack2[++top2]=str[i]; //运算完后,str[i]入栈
    66. } else if (str[i]=='*' || str[i]=='/') { // 只有*、/计算完后,才能入栈
    67. while (stack2[top2]=='*' || stack2[top2]=='/') {
    68. Cal_from_stack12(stack1, top1, stack2, top2); //计算
    69. }
    70. stack2[++top2]=str[i]; //运算完后,str[i]入栈
    71. } else if (str[i]=='(') { //左括号,直接入栈
    72. stack2[++top2]=str[i];
    73. } else if (str[i]==')') { //右括号,处理到把'('抵消
    74. while (stack2[top2]!='(') {
    75. Cal_from_stack12(stack1, top1, stack2, top2); //计算
    76. }
    77. top2--; //弹出左括号
    78. }
    79. }
    80. // 遍历完成后,检查栈是否计算完
    81. while (top2!=-1) {
    82. Cal_from_stack12(stack1, top1, stack2, top2); //计算
    83. }
    84. return stack1[top1]; //返回计算结果
    85. }
    86. /*-------------------------
    87. |中缀表达式 转 前缀表达式|
    88. -------------------------*/
    89. /*
    90. 数据结构:
    91. 1. 一个栈stack:用于存运算符
    92. 2. 一个数组tmp:用于暂时存储输出结果,这个结果实际是前缀表达式的逆序。即结束后,将此数组逆置就获得了前缀表达式
    93. 算法步骤:从右至左扫描中缀表达式
    94. 若是操作数,直接输出到tmp数组中
    95. 若是运算符,查看栈顶
    96. 若是右括号,直接压入栈中
    97. 若是左括号,将栈元素弹出输出到tmp数组中,直到抵消到栈中的右括号
    98. 若此运算符优先级小于栈顶元素,则栈内元素出栈并输出到tmp数组中,直到该运算符优先级大于等于栈顶元素,再将其压入栈中
    99. 否则,则该运算符直接入栈
    100. 最后将栈中剩余元素输出到tmp中,结束后,将tmp数组翻转
    101. */
    102. int infix_to_prefix(char in[], char pre[]) {
    103. char stack[100]; int top=-1; //用于存放运算符
    104. char tmp[100]; int j=0; //存放暂时的结果,即前缀表达式的逆序
    105. int i;
    106. for (i=strlen(in)-1; i>=0; --i) { //从右到左扫描中缀表达式
    107. if ('0' <= in[i] && in[i] <= '9') { //操作数,直接输出
    108. tmp[j++] = in[i];
    109. } else if (in[i]==')') {
    110. stack[++top] = in[i];
    111. } else if (in[i]=='(') {
    112. while (stack[top]!=')') {
    113. tmp[j++] = stack[top--];
    114. }
    115. --top; //左括号出栈
    116. } else if (in[i]=='+' || in[i]=='-') {
    117. while (stack[top]=='*' || stack[top]=='/') {
    118. tmp[j++] = stack[top--];
    119. }
    120. stack[++top] = in[i];
    121. } else if (in[i]=='*' || in[i]=='/') {
    122. stack[++top] = in[i];
    123. } else {
    124. return 0;
    125. }
    126. }
    127. // 输出剩余东西
    128. while (top!=-1) {
    129. tmp[j++] = stack[top--];
    130. }
    131. // 逆置
    132. i=0;
    133. for (i=0, j=j-1; j>=0; ++i,--j) {
    134. pre[i] = tmp[j];
    135. }
    136. pre[i]='\0';
    137. return 0;
    138. }
    139. /*-----------------------
    140. |计算前缀表达式:波兰式|
    141. -----------------------*/
    142. /*从左到右遍历前缀表达式
    143. 若遇到操作符,入栈
    144. 若遇到操作数,查看栈顶
    145. 若栈顶是操作符,入栈;
    146. 若栈顶是操作数,则将操作数出栈,再出栈一个操作符,进行运算,运算后继续判断栈顶情况,直到栈顶不是操作数或栈空再将结果入栈
    147. */
    148. typedef struct{
    149. union{
    150. char op;
    151. float num;
    152. }data;
    153. int flag; //0为操作数,1为num
    154. }StackNode; //栈的结点
    155. float CalPrefix(char str[]) {
    156. // 默认:前缀表达式合法
    157. StackNode stack[100]; int top=-1; //用于存放操作数和操作符的栈
    158. char op;
    159. float a,result;
    160. int i;
    161. for (i=0; str[i]!='\0'; ++i) {
    162. if ('0' <= str[i] && str[i] <='9') { //数字
    163. if ( top==-1 || stack[top].flag!=1 ) { // 栈顶为空 或 栈顶不是数字,直接入栈
    164. ++top; stack[top].flag=1; stack[top].data.num = (float)(str[i]-'0'); //数字入栈
    165. continue; //此次循环处理结束!
    166. }
    167. result = (float)(str[i]-'0'); //获得当前的数字
    168. while (top!=-1 && stack[top].flag==1) { // 栈顶如果是数字,一直判断到不是数字
    169. a = stack[top--].data.num; //在栈中取一个操作数
    170. op = stack[top--].data.op; //在栈中取一个运算符
    171. result = Cal(a, op, result); //计算
    172. }
    173. ++top; stack[top].flag=1; stack[top].data.num = result; //将此轮计算结果入栈
    174. } else { //操作符
    175. ++top; stack[top].flag=0; stack[top].data.op = str[i];
    176. }
    177. }
    178. return stack[top].data.num;
    179. }
    180. /*-------------------------
    181. |中缀表达式 转 后缀表达式|
    182. -------------------------*/
    183. int infix_to_suffix(char in[], char suf[]) {
    184. char stack[100]; int top=-1; //运算符的栈
    185. int i, j;
    186. j=0; //suf[]的指针
    187. for (i=0; in[i]!='\0'; ++i) { //遍历in
    188. // 是数字
    189. if ('0' <= in[i] && in[i] <= '9') {
    190. suf[j++] = in[i];
    191. continue;
    192. }
    193. // 是符号
    194. if (top==-1) { //栈为空
    195. stack[++top] = in[i];
    196. continue;
    197. }
    198. // 栈不为空
    199. if (in[i]=='+' || in[i]=='-') {
    200. while (stack[top]=='+' || stack[top]=='-' || stack[top]=='*' || stack[top]=='/') {
    201. suf[j++] = stack[top--];
    202. }
    203. stack[++top] = in[i];
    204. } else if (in[i]=='*' || in[i]=='/') {
    205. while (stack[top]=='*' || stack[top]=='/') {
    206. suf[j++] = stack[top--];
    207. }
    208. stack[++top] = in[i];
    209. } else if (in[i]=='(') {
    210. stack[++top] = in[i];
    211. } else if (in[i]==')') {
    212. while (stack[top]!='(') {
    213. suf[j++] = stack[top--];
    214. }
    215. top--; //将栈中'('输出
    216. } else {
    217. suf[0]='\0';
    218. return -1;
    219. }
    220. }
    221. // 输出剩下的符号
    222. while (top!=-1) {
    223. suf[j++] = stack[top--];
    224. }
    225. suf[j]='\0';
    226. return 1; //转换成功
    227. }
    228. /*-------------------------
    229. |计算后缀表达式:逆波兰式|
    230. -------------------------*/
    231. float CalSuffix(char str[]) {
    232. float stack[100]; int top=-1; //存放数字
    233. int i;
    234. float a,b;
    235. for (i=0; str[i]!='\0'; ++i) {
    236. if ('0' <= str[i] && str[i] <= '9') { //数字
    237. stack[++top]=(float)(str[i]-'0');
    238. } else { //不是数字
    239. b=stack[top--];
    240. a=stack[top--];
    241. stack[++top]=Cal(a, str[i], b);
    242. }
    243. }
    244. return stack[top];
    245. }
    246. /* 例子
    247. 表达式(中缀):2*3+(7-6/5)*2
    248. 前缀: +*23*-7/652
    249. 后缀: 23*765/-2*+
    250. 测试数据:
    251. 2*3+(7-6/5)*2
    252. (1+2*3)/(4/3+2)+4/2-2
    253. */
    254. int main() {
    255. char in[100], suf[100], pre[100];
    256. for ( ; ; ) {
    257. // 输入中缀表达式
    258. printf("请输入中缀表达式:\n>>> ");
    259. scanf("%s", in);
    260. // CalInfix()函数测试
    261. printf("[中缀表达式] %s\n", in);
    262. printf("\t计算结果:%lf\n", CalInfix(in) );
    263. // 前缀表达式
    264. infix_to_prefix(in, pre);
    265. printf("[前缀表达式] %s\n", pre);
    266. printf("\t计算结果:%lf\n", CalPrefix(pre) );
    267. // 后缀表达式
    268. infix_to_suffix(in, suf);
    269. printf("[后缀表达式] %s\n", suf);
    270. printf("\t计算结果:%lf\n", CalSuffix(suf) );
    271. printf("\n");
    272. }
    273. return 0;
    274. }