数式计算(递归解法)_四则运算

数式计算(递归解法)_四则运算

  1 /**
  2 *注:1.有一个bug(以及未知什么bug) 我已知的是: (a@b)(ps:@为运算符),这种带括号的表达式不能单独的出现,否则异常退出,,但是只要(a@b)@n
  3 
  4 带括号的表达式出现任意+,-,*,/的运算都能进行正常运算(前面 n@(a@b)也不可以)。。。不知道为什么()表达式后面没有操作时会异常退出。
  5 *不知道如何解决。希望感兴趣的人帮帮忙!
  6 
  7 //--------------------------------------------
  8 *一般的数式计算(允许括号的)需要通过栈来实现,但是其实对一些新手(我还没学数据结构)来说,用递归其实也是能很好的实现的。而且也很易于理解。
  9 *主要思路是-判断是有括号,无括号情况,有乘除和无乘除。有乘除时将乘除先算,算出来的值取代乘除的算式。
 10 *将括号中的数先算,将算出来的式子的值(括号中也会进行判断是否有无括号,有无乘除)将算出来的数取代原来的算式,然后递归.
 11 *最后的结束条件(判断其中运算符的数量): 只要算一个单一运算符的式子,因为在递归中所有的复杂的式子都被替换成了值。
 12 */
 13 
 14 #include<iostream>
 15 #include<cctype>
 16 #include<vector>
 17 #include<cstdlib>
 18 #include<cstring>
 19 #include<string>
 20 
 21 #define Jia 100001
 22 #define Jian 100002
 23 #define Chen 100003
 24 #define Chu 100004
 25 #define Qian 100005
 26 #define Hou 100006
 27 
 28 using namespace std;
 29 
 30 void Exchange(vector<double>& v, string s);   //将字符串转换成double型数
 31 double Calculate_Single(vector<double> v);    //进行数式计算
 32 double Count(double a, double b, double c);   //计算一组算式
 33 double integer(char c,double &rin);           // 将连续数字字符串转换为整数
 34 
 35 double integer(char c,double &rin)       // 将连续数字字符串转换为整数
 36 {
 37     rin = rin*10 + (c-'0');
 38     return rin;
 39 }
 40 
 41 void Exchange(vector<double>& v, string s)
 42 {
 43     char *p = &s[0];
 44     double re;
 45     while (*p) {
 46         re = 0;
 47         for ( ; *p; ++p) {
 48             if (isdigit(*p))           //如果是数字字符
 49                 integer(*p, re);       //转换成整数
 50             else{
 51                 if (*p == '(') { v.push_back(Qian); p++;}
 52                 break;
 53             }
 54         }
 55         if (re)
 56             v.push_back(re);
 57         if (*p == '\0')
 58             break;
 59         p--;
 60         while (*p++) {
 61             if (*p == '+') { v.push_back(Jia); continue;    }
 62             if (*p == '-') { v.push_back(Jian); continue;   }
 63             if (*p == '*') { v.push_back(Chen); continue;   }
 64             if (*p == '/') { v.push_back(Chu); continue;    }
 65             if (*p == '(') { v.push_back(Qian); continue;    }
 66             if (*p == ')') { v.push_back(Hou); continue;    }
 67             if (isdigit(*p))
 68                 break;
 69         }
 70     }
 71     //    cout << re << endl;        //debug
 72 }
 73 
 74 double Count(double a, double b, double c) {
 75     if (c == Jia)  return a + b;
 76     if (c == Jian) return a - b;
 77     if (c == Chen) return a * b;
 78     if (c == Chu)  return a / b;
 79     cerr << "运算出错,运算符不为+、-、*、/ !\n";
 80     exit(1);
 81 }
 82 
 83 //思路:递归--将乘除,括号这些地方的算式算成值,替换到只有加减的式子中去,最后这个只要算一个只有加减的式子即可
 84 double Calculate_Single(vector<double> v)  //进行数式计算带括号--用递归实现
 85 {
 86     unsigned jia = 0, jian = 0, cheng = 0, chu = 0, qian = 0, hou = 0;
 87     for (auto it = v.begin(); it != v.end(); ++it) {    //遍历v中每个元素,数一共有多少个操作符
 88         if (*it == Jia)    jia++;
 89         else if (*it == Jian) jian++;
 90         else if (*it == Chen) cheng++;
 91         else if (*it == Chu) chu++;
 92         else if (*it == Qian) qian++;
 93         else if (*it == Hou) hou++;
 94     }
 95     //    for (auto t : v)   //debug
 96     //        cout  << t << "\t" << endl;
 97 
 98     if (jia + jian + cheng + chu == 1) {       //最后一步--只算一个算式
 99         if (jia == 1) return v[0] + v[2];
100         if (jian == 1) return v[0] - v[2];
101         if (cheng == 1) return v[0] * v[2];
102         if (chu == 1) return v[0] / v[2];
103     }
104    if (qian + hou == 0) {                                                //无括号的情形
105         if (cheng + chu == 0 ) {                                         //无乘除情形
106             vector<double> vv;                                            //对一组数进行操作
107             double re = Count(v[0], v[2], v[1]); //只对一对算式进行操作
108             vv.push_back(re);                                              //将一对算式的结果推入底部,相当于用答案取代了那个算式
109             for (auto i = v.begin() + 3; i != v.end(); ++i) {   //将上一个算式后的所有字符添加vv到底部
110                 vv.push_back(*i);
111             }
112             return Calculate_Single(vv);   //用递归实现--相当于将一处的算式替换成了数字
113         }
114         else {       //有乘除--目标:将指针一直前进到乘/除字符的位置t,计算该算式,保存乘/除前面所有的字符,再保存乘除算成的值,再保存乘除后的算式
115             int t;    //标志位置-乘或除的位置
116             vector<double> vv;  //用来保存计算过乘除的式子
117             for (t = 0; v[t] != Chen && v[t] != Chu; ++t);  //推进到乘除的地方
118             double re = Count(v[t-1], v[t+1], v[t]);           //计算乘除式子
119             for (int i = 0; i < t-1; i++) {                           //将乘除前面的式子push_back
120                 vv.push_back(v[i]);            
121             }
122             vv.push_back(re);                                                     //再替换乘除的式子为数值
123             for (auto it = v.begin() + t + 2; it != v.end(); ++it) {  //将乘除后面式子保存到vv中
124                 vv.push_back(*it);
125             }
126             return Calculate_Single(vv);                                       //递归--一直递归到式子中只有一个式子的情况
127         }
128     }
129     else {        //有括号的情况
130         vector<double> vv, vvv;             //vv--是保存将括号中计算结束后的式子,vvv--保存括号中的式子并计算出
131         int q, h;                                     //q -- 前括号的位置,h--后括号的位置
132         double re;                    
133         for (h = 0; v[h] != Hou; ++h);    //推进到后括号的位置
134         for (q = h; v[q] != Qian; --q);     //后退到前括号的位置
135         for (int i = q + 1; i < h; ++i)       //将括号中的式子push到vvv底部
136             vvv.push_back(v[i]);
137         re = Calculate_Single(vvv);       //将括号中的式子递归求出
138         for (int i = 0; i < q; i++) {        //将前括号中的式子push_back
139             vv.push_back(v[i]);        
140         }
141         vv.push_back(re);                                                   //将括号中的式子计算出push到vv底部
142         for (auto it = v.begin() + h + 1; it != v.end(); ++it)  //将括号后的式子push_back
143             vv.push_back(*it);
144         return Calculate_Single(vv);                                    //再次递归进行计算--一直到只有一个式子的时候终止
145     }
146     cerr << "Bug:Calculate_Single 失效!" << endl;
147     return 0;
148 }
149 
150 int main()
151 {
152     vector<double> data;
153     string line;
154     cin >> line;
155     Exchange(data, line);
156     double result = Calculate_Single(data);
157     cout << result << endl;
158     return 0;
159 }

 

posted @ 2016-05-09 23:15 douzujun 阅读( ...) 评论( ...) 编辑 收藏
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值