加/减/乘/除四则混合运算(C 语言)

   逆波兰表达式(也称为后缀表达式) C 语言简单实现

  本示例旨在展示逆波兰表达式原理,作简单的混合运算,不作容错处理也不保证结果。若混合运算字符串中有{ [ %] } 等,自行调试解决 

  列如计算: -20.5 + ( 100 - ( 3 + 2 ) * 8 ) / ( 8 - 5 ) - 10

  后缀表达式为:-20.5 100 3 2 + 8 * - 8 5 - / + 10 - 

  C  语言代码如下:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 #define CNT 1000
  6 
  7 struct node{
  8    float num;   //数字
  9    char op;     //操作符
 10 };
 11 
 12 struct node datas[CNT];  //后缀表达式
 13 int data_top = -1;       //栈顶索引
 14 
 15 char ops[CNT];          //操作符
 16 int op_top = -1;        //栈顶索引
 17  
 18 char nums[100];        //数字字符串
 19 int num_top = -1;      //栈顶索引
 20 int minus_tag = 1;     //负数标记
 21 //数字入栈
 22 void push_num(){
 23   if(num_top > -1){
 24      datas[++data_top].num = atof(nums) * minus_tag;
 25      datas[data_top].op = 0;
 26      num_top = -1;
 27      minus_tag = 1;
 28      memset(nums, 0, sizeof(nums));  
 29   }
 30 }
 31 //中缀转后缀
 32 void mtoe(const char* str){
 33   char *tmp;
 34   tmp = (char*)str;
 35   int last_tag = 1; //上一个字符是否是运算符,默认是,用于处理负数
 36   while(*tmp != '\0'){
 37     char ch = *tmp;
 38     ++tmp;
 39     if(ch == ' ') continue;
 40    
 41     if(ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '('){
 42       push_num();
 43       if( (ch == '-') && last_tag ){
 44          minus_tag = -1;//负数标记
 45          last_tag = 0;
 46          continue;
 47       }
 48       last_tag = 1;
 49       while(op_top > -1){
 50         if(ch == '(') break;
 51         char op = ops[op_top];
 52         if(op == '(') break;
 53         if(ch == '+' || ch == '-'){
 54           datas[++data_top].op = op;
 55           --op_top;    
 56         }else{
 57           if(op == '+' || op == '-') break;
 58           else{
 59             datas[++data_top].op = op;
 60             --op_top;  
 61           }
 62         }  
 63       }
 64       ops[++op_top] = ch;
 65     }else if(ch == ')'){
 66       push_num();
 67       last_tag = 0;
 68       while(ops[op_top] != '('){
 69         datas[++data_top].op = ops[op_top];
 70         --op_top;
 71       }
 72       --op_top; 
 73     }else{  
 74       last_tag = 0;
 75       nums[++num_top] = ch;
 76     }
 77   }// end of while *tmp 
 78   push_num();//最后的数据入栈
 79   while(op_top > -1){//最后的操作符入栈
 80      datas[++data_top].op = ops[op_top];
 81      --op_top;   
 82   } 
 83     
 84 }
 85 //计算值
 86 float calculating(){
 87   if(data_top < 0) return 0; 
 88   float stack[CNT] = {0};
 89   int top = -1;
 90   int i = 0;
 91   while(i <= data_top){
 92     char op = datas[i].op;
 93     if(op == 0){
 94        stack[++top] = datas[i].num;
 95     }else{
 96       float a = stack[top -1];
 97       float b = stack[top];
 98       --top;
 99       float c = 0;
100       if(op == '+') c = a + b;
101       else if(op == '-') c = a -b;
102       else if(op == '*') c = a * b;
103       else if(op == '/') c = a / b;
104       stack[top] = c;
105     }
106    ++i;
107   }
108   if(top < 0) return 0;
109   else return stack[top]; 
110 }
111 
112 int main(int argc, char *argv[]){
113   char *parms = "-20.5+(100-(3+2)*8)/(8-5) - 10";
114   //char *parms = "10+100/2*5";
115   data_top = -1;
116   op_top = -1;
117   num_top = -1;
118   mtoe(parms);
119   printf("\n");
120   printf("%s = ",parms);
121   printf("%f\n",calculating());
122   int i = 0;
123   for(i = 0; i <= data_top; i++){
124      if(datas[i].op) printf("%c ", datas[i].op); 
125      else printf("%f ",datas[i].num); 
126   }
127   printf("\n\n");
128   return 0;
129 }
显示代码

  执行结果:

  -20.5+(100-(3+2)*8)/(8-5) - 10 = -10.500000
  -20.500000 100.000000 3.000000 2.000000 + 8.000000 * - 8.000000 5.000000 - / + 10.000000 -

 

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 
 5 #define CNT 1000
 6 
 7 float datas[CNT];        //数字栈
 8 int data_top = -1;       //栈顶索引
 9 
10 char nums[100];        //数字字符串
11 int num_top = -1;      //栈顶索引
12 int minus_tag = 1;     //负数标记
13 //数字入栈
14 void push_num(){
15   if(num_top > -1){
16      datas[++data_top] = atof(nums) * minus_tag;
17      num_top = -1;
18      minus_tag = 1;
19      memset(nums, 0, sizeof(nums));  
20   }
21 }
22 //操作符入栈,则计算值
23 void push_op(char op)
24 {
25    float a = datas[data_top -1];
26    float b = datas[data_top];
27    float c = 0;
28    if(op == '+') c = a + b;
29    else if(op == '-') c = a -b;
30    else if(op == '*') c = a * b;
31    else if(op == '/') c = a / b;
32    datas[--data_top] = c;
33 }
34 //中缀转后缀并计算值
35 void calc(const char* str){
36   char *tmp;
37   tmp = (char*)str;
38   char ops[CNT];          
39   int op_top = -1;        
40   int last_tag = 1; //上一个字符是否是运算符,默认是,用于处理负数
41   while(*tmp != '\0'){
42     char ch = *tmp;
43     ++tmp;
44     if(ch == ' ') continue;
45    
46     if(ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '('){
47       push_num();
48       if( (ch == '-') && last_tag ){
49          minus_tag = -1;//负数标记
50          last_tag = 0;
51          continue;
52       }
53       last_tag = 1;
54       while(op_top > -1){
55         if(ch == '(') break;
56         char op = ops[op_top];
57         if(op == '(') break;
58         if(ch == '+' || ch == '-'){
59           push_op(op);
60           --op_top;    
61         }else{
62           if(op == '+' || op == '-') break;
63           else{
64             push_op(op);
65             --op_top;  
66           }
67         }  
68       }
69       ops[++op_top] = ch;
70     }else if(ch == ')'){
71       push_num();
72       last_tag = 0;
73       while(ops[op_top] != '('){
74         push_op(ops[op_top]);
75         --op_top;
76       }
77       --op_top; 
78     }else{  
79       last_tag = 0;
80       nums[++num_top] = ch;
81     }
82   }// end of while *tmp 
83   push_num();//最后的数据入栈
84   while(op_top > -1){//最后的操作符入栈
85      push_op(ops[op_top]);
86      --op_top;   
87   }     
88 }
89 
90 int main(int argc, char *argv[]){
91   char *parms = "-20.5+(100-(3+2)*8)/(8-5) - 10";
92   data_top = -1;
93   num_top = -1;
94   calc(parms);
95   printf("\n%s = ",parms);
96   printf("%f\n",datas[0]);
97   return 0;
98 }
优化版

  

附中缀表达式转前缀或后缀表达式原理

转化步骤:

  1. 按照运算符的优先级对所有的运算单位加括号
  2. 将运算符移动到对应括号的前面(前缀表达式)或后面(后缀表达式)
  3. 去掉括号,得到前缀或后缀表达式

示例:

    中缀表达式:5 + ( 6 + 7 ) × 8 - 9

1)加括号
    变成 ( ( 5 + ( ( 6 + 7 ) × 8 ) ) - 9 )

2)移动运算符

   前缀变成了 - ( + ( 5 × ( + ( 6 7 ) 8 ) ) 9 )

   后缀变成了 ( ( 5 ( ( 6 7 ) + 8 ) × ) + 9 ) -

3)去掉括号
   前缀表达式: - + 5 × + 6 7 8 9
   后缀表达式:5 6 7 + 8 × + 9 -

posted @ 2019-12-26 20:26  伯通心智  阅读(1549)  评论(0编辑  收藏  举报