1 /** 2 *注:1.有一个bug(以及未知什么bug) 我已知的是: ([email protected])(ps:@为运算符),这种带括号的表达式不能单独的出现,否则异常退出,,但是只要([email protected])@n 3 4 带括号的表达式出现任意+,-,*,/的运算都能进行正常运算(前面 [email protected]([email protected])也不可以)。。。不知道为什么()表达式后面没有操作时会异常退出。 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 }
时间: 2024-10-21 23:59:01