zoukankan      html  css  js  c++  java
  • 数式计算(递归解法)_四则运算

      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 == '')
     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 << "运算出错,运算符不为+、-、*、/ !
    ";
     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 << "	" << 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 }

     

  • 相关阅读:
    奔溃瞬间1
    面试知识点blog汇总
    贪心
    树 和 图
    DFS 和 BFS
    STL
    哈希表
    手写堆
    并查集
    二项式反演学习笔记
  • 原文地址:https://www.cnblogs.com/douzujun/p/5475947.html
Copyright © 2011-2022 走看看